O foaie de calcul poartă două straturi de identitate. Există grila de celule, și există metadatele documentului care călătoresc alături de ea: titlu, autor, companie, cuvinte cheie, marcajele de timp. Excel nu arată niciodată acel al doilea strat în grilă, și totuși este stratul pe care Windows Search îl indexează, cel pe care SharePoint îl citește pentru a titla un document, și cel după care se clasează un sistem de management al înregistrărilor. Când un registru de lucru generat își moștenește Author și Title de la șablonul din care a fost construit, fiecare sistem din aval înregistrează designerul șablonului drept autorul a patru mii de extrase de cont ale clienților. Metadatele nu sunt corecte nicăieri și sunt consultate peste tot
HotXLS expune acest strat ca proprietăți obișnuite la nivel de registru de lucru pe ambele sale motoare: fațada BIFF pentru .xls și fațada OOXML pentru .xlsx. Citiți un câmp după ce deschideți un fișier și scrieți un câmp înainte de a-l salva. Biblioteca decide în ce container fizic ajunge valoarea. Ce merită înțeles înainte de a scrie un generator este ce câmpuri suportă fiecare format cu adevărat, unde trăiesc fizic acele câmpuri, și regula unică de blocare care guvernează dacă un .xlsx înregistrează vreun metadate deloc
Două formate, două modele de stocare
Motivul pentru care o bibliotecă de foi de calcul are nevoie de două implementări de metadate, și motivul pentru care instrumentele pe jumătate terminate marchează corect un format și îl uită pe celălalt, este că .xls și .xlsx își țin proprietățile în locuri fără legătură. Un registru de lucru BIFF le scrie în fluxuri de fișier compus OLE, în principal setul de proprietăți SummaryInformation care precedă chiar Excel-ul, alături de înregistrarea în flux WRITEACCESS care numește pe oricine a salvat ultima dată fișierul. Un registru de lucru OOXML le păstrează ca părți XML în interiorul pachetului zip, împărțite după scop: docProps/core.xml conține câmpurile Dublin Core (titlu, creator, subiect, cuvinte cheie, date), iar docProps/app.xml conține câmpurile la nivel de aplicație precum compania și aplicația generatoare, conform ECMA-376 Partea 1
HotXLS aplatizează ambele modele de stocare în proprietăți directe ale obiectului registru de lucru. Nu deschideți niciodată manual un flux de set de proprietăți și nici nu editați o parte XML. Atribuiți șiruri și date registrului de lucru, iar containerul corect se materializează pentru orice format salvați
Marcarea registrelor de lucru generate din înregistrarea de business
Pe partea XLSX, TXLSXWorkbook expune Title, Subject, Author, Keywords, Description, Category, LastModifiedBy, Company, Application și AppVersion ca șiruri, plus Created și Modified ca valori TDateTime, unde zero înseamnă nesetat. Regula care închide gaura de moștenire încape într-o frază: atribuiți fiecare câmp la fiecare rulare, luând valorile din înregistrarea de business, în loc să aveți încredere în orice a purtat șablonul din întâmplare
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open('statement-template.xlsx') <> 1 then
raise Exception.Create('Template not available');
// Suprascrieți fiecare câmp: orice rămâne neatins este
// moștenit de la oricine a proiectat șablonul.
Book.Title := 'Account Statement 2026-06 / ACME Corp';
Book.Subject := 'Monthly account statement';
Book.Author := 'Billing Service 4.2';
Book.LastModifiedBy := 'Billing Service 4.2';
Book.Company := 'Northwind Financial';
Book.Category := 'Customer Delivery';
Book.Keywords := 'statement;billing;2026-06;acct-10024';
Book.Description := 'Generated document - manual edits are not retained';
Book.Created := Now;
Book.Modified := Now;
Book.SaveAs('statement-10024.xlsx');
finally
Book.Free;
end;
end;
Câmpul Keywords merită mai multă gândire decât primește de obicei. Infrastructura de căutare îl indexează cuvânt cu cuvânt, Windows Search, SharePoint și majoritatea produselor DMS la fel, așa că o convenție separată prin punct și virgulă care poartă numărul de cont și perioada transformă fiecare registru de lucru livrat într-o înregistrare căutabilă, fără niciun drum dus-întors la baza de date. Aceeași rază de acțiune este și capcana. Proprietățile călătoresc cu fiecare copie a fișierului, mult dincolo de controalele de acces ale sistemului care le-a scris, așa că datele personale nu au ce căuta acolo
Perechea de marcaje de timp poartă o semantică care merită fixată prin politică, nu lăsată la voia obiceiului. Created ar trebui să marcheze momentul în care pipeline-ul dvs. a generat documentul și apoi să rămână înghețat. Modified este câmpul pe care Excel îl actualizează de fiecare dată când un destinatar salvează fișierul, așa că o divergență între cele două după livrare este o dovadă pozitivă că cineva a editat registrul de lucru în aval, ceea ce tranșează mai mult de o dispută despre ale cui numere le poartă cu adevărat o foaie de calcul retransmisă. O capcană se ascunde în starea nesetată: este valoarea literală zero, nu o excepție și nu un null, așa că codul de audit trebuie să testeze explicit pentru zero. Formatați un TDateTime nesetat fără acea gardă, și jurnalele dvs. se umplu cu o dată din decembrie 1899, greșită cu încredere
DocPropsTouched: registrul de lucru care se livrează fără docProps
Un flag doar-citire, DocPropsTouched, blochează scriitorul de proprietăți XLSX. Un registru de lucru la care nu a fost atribuită niciodată nicio proprietate nu produce nicio parte docProps; HotXLS refuză să scrie un schelet de metadate gol. Comportamentul este ordonat, și are două consecințe în jurul cărora merită proiectat
Codul de recepție de pe partea de consum nu trebuie să presupună că core.xml există în fiecare pachet. Un instrument care îl cere strict va respinge fișiere minime perfect valide. Iar dacă postura dvs. de conformitate cere ca fiecare document ieșit să poarte cel puțin o identitate de generator, acea cerere devine cod, nu o proprietate a formatului: atribuiți necondiționat Application și Author în calea de salvare, pentru că un registru de lucru neatins este pe deplin legal conform specificației, în timp ce vă încalcă tacit politica
Suprafața XLS moștenită și capcana Comments
Fațada BIFF poartă setul de câmpuri mai vechi și mai mic: Title, Subject, Author, Keywords, Comments, Company și Manager, plus LastSavedBy, un alias al lui UserName, care scrie înregistrarea WRITEACCESS pe care Excel o afișează atunci când un alt utilizator ține fișierul blocat
var
Legacy: IXLSWorkbook; // interfață numărată prin referințe: fără Free manual
begin
Legacy := TXLSWorkbook.Create;
if Legacy.Open('archive-1999.xls') <= 0 then
raise Exception.Create('Cannot open archive file');
Legacy.Title := 'FY1999 ledger (migrated copy)';
Legacy.Author := 'Archive Migration Batch';
Legacy.Company := 'Northwind Financial';
Legacy.Comments := 'Migrated 2026-06-11; source retained in cold storage';
Legacy.LastSavedBy := 'migration-svc'; // înregistrare BIFF WRITEACCESS
Legacy.SaveAs('archive-1999-stamped.xls');
end;
O coliziune de denumire provoacă o confuzie recurentă. Proprietatea Comments la nivel de document de aici este remarca în text liber afișată în dialogul de proprietăți al fișierului. Nu are nicio legătură cu comentariile de celulă, care sunt obiecte de strat de desen atașate intervalelor printr-un API complet separat. O revizuire de cod care acceptă „deja scriem Comments” fără să verifice la care se referă a acceptat o afirmație despre funcționalitatea greșită, iar asta se întâmplă mai des decât ar sugera numele comun. Cele două împart patru litere și niciun octet de stocare
Citirea metadatelor la recepție, și lipsa unei sonde
Citirea este simetrică. După Open, aceleași proprietăți revin populate din fișier, ceea ce transformă un audit de metadate al registrelor de lucru primite într-o buclă scurtă
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open(FileName) = 1 then
begin
Writeln(Format('%s | title="%s" author="%s" created=%s',
[ExtractFileName(FileName), Book.Title, Book.Author,
FormatDateTime('yyyy-mm-dd', Book.Created)]));
if Book.Created = 0 then
Writeln(' no creation date recorded');
end;
finally
Book.Free;
end;
end;
Planificați în jurul unei limitări în timp ce faceți asta. Nu există o sondă doar pentru proprietăți. GetSheetNames poate lista foile fără să încarce un registru de lucru, dar citirea lui Title sau Author înseamnă un Open complet, așa că triajul de metadate pe o arhivă mare plătește costul complet de analiză pentru fiecare fișier. Pe partea BIFF puteți reduce acel cost pentru audituri doar-citire setând _DisableGraphics pe true înainte de deschidere, ceea ce omite complet stratul de desen. Se potrivește unei bucle care doar citește proprietăți și statistici de celule, și este exact greșit în momentul în care aceeași instanță ar putea salva, pentru că desenul omis ar fi aruncat. Când doar structura foilor poate pre-filtra setul, exporturile cu o singură foaie fiind lucrul evident de omis, tehnicile ieftine din articolul nostru despre listarea foilor și inspecția ușoară reduc câte fișiere ajung la trecerea costisitoare. Iar pe job-urile de marcare în masă, unde se scriu mii de ieșiri, nu se inspectează, tiparele de throughput pe partea de scriere din articolul nostru despre scrierile în flux pentru job-uri de lot se transferă neschimbate, pentru că atribuirea de proprietăți nu adaugă nimic măsurabil la timpul de salvare
Traversarea formatelor și conținerea scurgerii
Proprietățile fac dus-întors curat în interiorul unei singure fațade: deschideți un .xlsx, editați-l, salvați-l, iar setul revine intact. Traversarea formatelor este locul unde se rupe presupunerea de paritate, pentru că seturile de câmpuri BIFF și OOXML nu se aliniază unu la unu. BIFF are Manager și niciun marcaj de timp; OOXML are Category, Description și perechea Created/Modified. Un convertor care copiază orbește pierde tot ce formatul destinație nu poate reține, așa că mapați câmpurile explicit și puneți maparea în lista dvs. de verificare a conversiei, alături de tot restul ce nu supraviețuiește călătoriei
Scurgerea pe care o deschide moștenirea de șablon merge în sens invers: informații pe care nu ați vrut niciodată să le livrați. Nume de autori, etichete interne de proiect parcate în cuvinte cheie, un titlu de ciornă pe care nimeni nu l-a validat. Disciplina de suprascriere-a-tot din generatorul de mai sus este întreaga apărare, și merită verificată așa cum ar face-o un outsider, deschizând dialogul de Proprietăți la care orice client poate ajunge, sau dezarhivând .xlsx-ul și citind docProps/core.xml direct din pachet. Ce vedeți acolo este exact ce vede fiecare indexator din aval
Acea vizibilitate din aval este și motivul pentru care câteva câmpuri merită mai multă atenție decât restul. Title, Author, Keywords (care apar ca Tags) și Comments sau Description poartă cea mai mare parte a greutății de indexare în SharePoint și Windows Search. Un Title cu adevărat distinct pentru fiecare document, purtând perioada și contul, face mai mult pentru capacitatea de a fi găsit decât orice schemă de denumire a folderelor suprapusă peste el, și costă o singură atribuire per salvare
Proprietățile documentului sunt cea mai ieftină lustruire profesională pe care o poate purta un registru de lucru generat, și defectul cel mai frecvent livrat atunci când nimeni nu le deține. Ambele suprafețe de proprietăți descrise aici aparțin de HotXLS Delphi Component, care le scrie nativ pentru XLS și XLSX fără automatizare Excel