Technical Article

Podešavanje svojstava Excel dokumenata i metapodataka radnih svezaka u Delphi-ju pomoću HotXLS-a

Tabela nosi dva sloja identiteta. Postoji mreža ćelija i postoje metapodaci dokumenta koji idu uz nju: naslov, autor, kompanija, ključne reči i vremenske oznake. Excel nikada ne prikazuje taj drugi sloj u mreži, ali to je sloj koji Windows Search indeksira, koji SharePoint čita da bi naslovio dokument i prema kojem sistem za upravljanje zapisima arhivira datoteke. Kada generisana radna sveska nasledi svog autora i naslov iz šablona na osnovu kojeg je napravljena, svaki nizvodni sistem beleži dizajnera šablona kao autora četiri hiljade korisničkih izvoda. Metapodaci nisu tačni nigde, a konsultuju se svuda.

HotXLS prikazuje ovaj sloj kao obična svojstva na nivou radne sveske na oba svoja mehanizma: BIFF fasadi za .xls i OOXML fasadi za .xlsx. Čitate polje nakon otvaranja datoteke, a upisujete ga pre čuvanja. Biblioteka odlučuje u koji fizički kontejner vrednost smešta. Pre nego što napišete generator, korisno je razumeti koja polja svaki format zapravo podržava, gde ta polja fizički žive i jedno ključno pravilo koje određuje da li .xlsx uopšte beleži bilo kakve metapodatke.

Dva formata, dva modela skladištenja

Razlog zašto je biblioteci za rad sa tabelama potrebna dvostruka implementacija metapodataka, i razlog zašto polovični alati ispravno označavaju jedan format a zaboravljaju drugi, jeste taj što .xls i .xlsx čuvaju svoja svojstva na nepovezanim mestima. BIFF radna sveska ih upisuje u tokove OLE složenih datoteka (compound-file streams), uglavnom u skup svojstava SummaryInformation koji je stariji od samog Excel-a, zajedno sa zapisom WRITEACCESS unutar toka koji imenuje onoga ko je poslednji sačuvao datoteku. OOXML radna sveska ih čuva kao XML delove unutar zip paketa, podeljene po nameni: docProps/core.xml sadrži polja Dublin Core standarda (naslov, kreator, tema, ključne reči, datumi), dok docProps/app.xml sadrži polja na nivou aplikacije kao što su kompanija i aplikacija generator, prema specifikaciji ECMA-376 Deo 1.

HotXLS objedinjuje oba ova modela skladištenja u direktna svojstva objekta radne sveske. Nikada ne otvarate tokove skupa svojstava niti ručno menjate XML delove. Dodeljujete tekstualne nizove i datume radnoj svesci, a ispravan kontejner se kreira za onaj format u kojem čuvate podatke.

Popunjavanje generisanih radnih svezaka iz poslovnih zapisa

Na XLSX strani, TXLSXWorkbook izlaže svojstva Title, Subject, Author, Keywords, Description, Category, LastModifiedBy, Company, Application i AppVersion kao tekstualne nizove, i Created i Modified kao TDateTime vrednosti gde nula znači da nisu podešeni. Pravilo koje rešava problem nasleđivanja je jednostavno: dodelite vrednost svakom polju prilikom svakog pokretanja, uzimajući podatke iz poslovne evidencije umesto da verujete onome što je šablon slučajno sadržao.

var
  Book: TXLSXWorkbook;
begin
  Book := TXLSXWorkbook.Create;
  try
    if Book.Open('statement-template.xlsx') <> 1 then
      raise Exception.Create('Template not available');

    // Overwrite every field: anything left untouched is
    // inherited from whoever designed the template.
    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;

Polje Keywords zaslužuje više pažnje nego što mu se obično pridaje. Infrastruktura za pretragu ga indeksira doslovno, bilo da je reč o Windows Search-u, SharePoint-u ili većini DMS proizvoda, pa konvencija sa vrednostima razdvojenim tačka-zarezom koja sadrži broj naloga i period pretvara svaku isporučenu radnu svesku u lako pronalaziv zapis bez potrebe za upitom bazi podataka. Međutim, ta dostupnost je ujedno i zamka. Svojstva putuju sa svakom kopijom datoteke, daleko izvan kontrole pristupa sistema koji ih je kreirao, tako da ličnim podacima tu nije mesto.

Par vremenskih oznaka nosi semantiku koju je bolje definisati internim pravilima nego ostaviti navici. Svojstvo Created treba da označava trenutak kada je vaš sistem generisao dokument i nakon toga da ostane nepromenjeno. Svojstvo Modified je polje koje Excel ažurira svaki put kada primalac sačuva datoteku, pa je razlika između ove dve vrednosti nakon isporuke jasan dokaz da je neko menjao radnu svesku nizvodno, što rešava mnoge sporove o tome čije brojke prosleđena tabela zapravo sadrži. Jedna zamka leži u nepodešenom stanju: to je doslovna vrednost nula, a ne izuzetak niti null, tako da kod za reviziju mora eksplicitno da testira nulu. Ako formatirate nepodešeno svojstvo TDateTime bez ove zaštite, vaši dnevnici će se napuniti pogrešnim datumom iz decembra 1899. godine.

DocPropsTouched: radna sveska koja se isporučuje bez docProps

Zastavica samo za čitanje, DocPropsTouched, kontroliše upisivanje XLSX svojstava. Radna sveska u kojoj nijedno svojstvo nikada nije dodeljeno ne generiše nikakve docProps delove; HotXLS odbija da upiše prazan kostur metapodataka. Ovo ponašanje je uredno, ali ima dve posledice koje vredi uzeti u obzir pri projektovanju.

Kod za prijem datoteka na potrošačkoj strani ne sme pretpostaviti da core.xml postoji u svakom paketu. Alat koji ga striktno zahteva odbaciće potpuno ispravne minimalne datoteke. Takođe, ako vaša pravila o usaglašenosti zahtevaju da svaki odlazni dokument sadrži bar identitet generatora, taj zahtev postaje deo koda, a ne svojstvo formata: dodelite Application i Author bezuslovno prilikom čuvanja, jer je nedirnuta radna sveska potpuno ispravna prema specifikaciji, iako tiho krši vaša interna pravila.

Stari XLS interfejs i zamka sa svojstvom Comments

BIFF fasada sadrži stariji, manji skup polja: Title, Subject, Author, Keywords, Comments, Company i Manager, uz LastSavedBy, koji je alias za UserName, a koji upisuje zapis WRITEACCESS koji Excel prikazuje kada je datoteka zaključana od strane drugog korisnika.

var
  Legacy: IXLSWorkbook;     // reference-counted interface: no manual Free
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';   // BIFF WRITEACCESS record

  Legacy.SaveAs('archive-1999-stamped.xls');
end;

Jedna kolizija u nazivima izaziva čestu zabunu. Svojstvo Comments na nivou dokumenta ovde predstavlja slobodan tekstualni komentar koji se prikazuje u dijalogu svojstava datoteke. Ono nema nikakve veze sa komentarima ćelija, koji su objekti na sloju crtanja i vezuju se za opsege preko potpuno drugog API-ja. Revizija koda koja prihvati izjavu „već upisujemo Comments“ bez provere na šta se tačno misli, prihvatila je tvrdnju o pogrešnoj funkciji, što se dešava češće nego što bi zajedničko ime sugerisalo. Ta dva pojma dele nekoliko slova, ali ni jedan jedini bajt zajedničkog skladišta.

Čitanje metapodataka pri prijemu i problem sa sondiranjem

Čitanje je simetrično. Nakon poziva Open, ista svojstva se učitavaju iz datoteke, što pretvara reviziju metapodataka dolaznih radnih svezaka u kratku petlju.

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;

Planirajte rad u skladu sa jednim ograničenjem. Ne postoji sonda koja čita samo svojstva. GetSheetNames može izlistati listove bez učitavanja radne sveske, ali čitanje svojstava Title ili Author zahteva potpun poziv Open, tako da trijaža metapodataka kroz veliku arhivu plaća punu cenu analiziranja za svaku datoteku. Na BIFF strani možete smanjiti taj trošak za revizije koje samo čitaju podatke postavljanjem _DisableGraphics na true pre otvaranja, čime se potpuno preskače sloj crtanja. To je pogodno za petlju koja samo čita svojstva i statistiku ćelija, ali je potpuno pogrešno ako ista instanca treba da čuva podatke, jer bi preskočeni sadržaj crteža bio odbačen. Kada sama struktura listova može unapred filtrirati skup (pri čemu su izvozi sa jednim listom očigledan kandidat za preskakanje), jednostavne tehnike opisane u našem članku o izlistavanju listova i laganoj inspekciji smanjuju broj datoteka koje stižu do zahtevnog prolaza. Kod grupnih poslova upisivanja, gde se pišu hiljade izlaza umesto što se analiziraju, obrasci propusnosti na strani upisa iz našeg članka o strimovanju upisa za grupne poslove prenose se bez izmena, pošto dodeljivanje svojstava ne dodaje merljivo vreme procesu čuvanja.

Prelazak između formata i sprečavanje curenja podataka

Svojstva uspešno prolaze pun krug unutar jedne fasade: otvorite .xlsx, izmenite ga, sačuvate i ceo skup se vraća netaknut. Prelazak između formata je tačka gde pretpostavka o jednakosti pada, jer se polja BIFF i OOXML ne podudaraju jedan na jedan. BIFF ima Manager i nema vremenske oznake; OOXML ima svojstva Category, Description i par Created/Modified. Konvertor koji slepo kopira podatke izgubiće sve što odredišni format ne može da podrži, pa eksplicitno mapirajte polja i stavite to mapiranje na svoju kontrolnu listu za konverziju pored svega ostalog što ne preživljava prelazak.

Curenje podataka koje otvara nasleđivanje šablona ide u suprotnom smeru: informacije koje nikada niste nameravali da pošaljete javnosti. Imena autora, interne oznake projekta smeštene u ključne reči, radna verzija naslova koju niko nije odobrio. Pravilo da se sve prepiše iz gornjeg generatora je jedina odbrana, a ispravnost vredi verifikovati na način na koji bi to uradio spoljni korisnik: otvaranjem dijaloga Properties kojem svaki kupac može pristupiti, ili raspakivanjem .xlsx datoteke i čitanjem docProps/core.xml direktno iz paketa. Ono što tamo vidite je upravo ono što vidi i svaki nizvodni sistem za indeksiranje.

Ta nizvodna vidljivost je takođe razlog zašto nekoliko polja zahteva više pažnje od ostalih. Svojstva Title, Author, Keywords (koje se prikazuju kao oznake/tags) i Comments ili Description nose većinu težine indeksiranja u SharePoint-u i Windows Search-u. Naslov (Title) koji je zaista jedinstven po dokumentu, i sadrži period i broj naloga, čini mnogo više za lakše pronalaženje od bilo koje šeme imenovanja fascikli, a zahteva samo jedno dodeljivanje vrednosti po čuvanju.

Svojstva dokumenta predstavljaju najjednostavniji profesionalni sjaj koji generisana radna sveska može imati, a ujedno i najčešći propust kada niko ne vodi računa o njima. Oba interfejsa za svojstva opisanih ovde pripadaju komponenti HotXLS Component, koja ih nativno upisuje za XLS i XLSX bez Excel automatizacije.