Uneori singura întrebare la care o rutină de recepție trebuie să răspundă este una structurală: are acest registru de lucru o foaie numită „Mapping”, sau câte file conține. Să răspundeți la asta apelând Open este modul costisitor de a o face. O deschidere completă umflă tabelul de șiruri partajate, decodează fiecare înregistrare de stil și parcurge celulele fiecărei foi de lucru, pentru că nu are cum să știe că doreați doar cuprinsul. Pe un fișier mare, asta înseamnă sute de megaocteți de alocări și câteva secunde de CPU cheltuite pentru a citi o listă ce ocupă câțiva kiloocteți. HotXLS, biblioteca nativă Delphi pentru foi de calcul a losLab, vă oferă acea listă direct: GetSheetNames întoarce numele foilor de lucru, în ordinea din registrul de lucru, fără să materializeze o singură celulă
De ce este ieftin de citit catalogul
Ambele formate de foi de calcul își pun cuprinsul aproape de început, ceea ce face ca un apel de listare să fie rapid, nu doar isteț. Un pachet OOXML ține catalogul de foi în xl/workbook.xml, o parte care rămâne mică indiferent dacă registrul de lucru conține zece rânduri sau zece milioane. Un fișier .xls BIFF8 își stochează înregistrările BoundSheet la începutul fluxului de globale al registrului de lucru, înaintea oricăror date de celule. Așadar, munca pe care o evită un apel de listare nu este o eroare de rotunjire față de o deschidere completă. Este cea mai mare parte a fișierului. Citirea catalogului costă aceiași câțiva kiloocteți indiferent de numărul de rânduri, în timp ce o deschidere completă scalează odată cu datele, iar pe un registru de lucru de câțiva megaocteți acel decalaj ajunge la câteva ordine de mărime, atât în octeți atinși, cât și în memorie alocată
Acest cost constant este proprietatea în jurul căreia merită proiectat. O poartă de recepție construită pe GetSheetNames se comportă la fel pe un fișier de 200 de rânduri și pe unul de 200 MB, așa că cel mai lent fișier dintr-un lot nu mai dictează ritmul pentru a decide dacă un fișier merită măcar procesat
Un singur apel pentru .xls, .xlsx și formatele șablon
Pe fațada XLS, TXLSWorkbook.GetSheetNames citește mai mult decât .xls. Acceptă și formatele bazate pe zip .xlsx, .xlsm, .xltx și .xltm, extrăgând doar workbook.xml din arhivă. Pentru intrare .xls autentică, scanează înregistrările BoundSheet și se oprește la prima înregistrare EOF a subfluxului de globale, astfel încât un fișier binar mare costă tot doar kiloocteții săi de deschidere. Fațada XLSX poartă o garanție care contează mai mult pentru codul de serviciu de lungă durată decât pare la prima vedere: TXLSXWorkbook.GetSheetNames nu resetează, dar nici nu populează instanța registrului de lucru, astfel încât o instanță care deja ține un document deschis poate sonda alte fișiere fără să îl deranjeze pe cel din mână. GetODSSheetNames aplică aceeași abordare pachetelor OpenDocument, iar fiecare dintre aceste apeluri are o supraîncărcare pentru flux, ceea ce vă permite să inspectați un upload care nu ajunge niciodată pe disc
var
Book: TXLSXWorkbook;
Names: TStringList;
I: Integer;
begin
Names := TStringList.Create;
Book := TXLSXWorkbook.Create;
try
if Book.GetSheetNames('upload-7f3a.xlsx', Names) <= 0 then
raise Exception.Create('unreadable workbook package');
if Names.IndexOf('Mapping') < 0 then
raise Exception.Create('required Mapping sheet is missing');
for I := 0 to Names.Count - 1 do
Writeln(Format('sheet %d: %s', [I, Names[I]]));
finally
Book.Free;
Names.Free;
end;
end;
Același apel face un bun dialog de import pentru desktop. Listați foile, lăsați utilizatorul să aleagă una și plătiți costul deschiderii complete abia după ce alegerea este făcută. Cu un registru de lucru cu cincizeci de foi, diferența este vizibilă: un selector care apare instantaneu, față de unul care se blochează în timp ce tot fișierul se încarcă în spate
Fișierele .xlsm cu macrocomenzi activate și formatele șablon se listează exact ca un .xlsx simplu, deoarece catalogul se află în același workbook.xml, indiferent dacă un vbaProject.bin călătorește sau nu odată cu pachetul. Un pipeline de recepție poate, prin urmare, să enumere foile unui registru de lucru cu macrocomenzi pentru rutare, fără să atingă vreodată încărcătura de macrocomenzi și fără să facă nimic care ar rula-o, lăsând decizia privind politica pentru macrocomenzi pe seama etapei care chiar deschide fișierul
Citirea valorii de retur fără a vă amăgi
Convențiile de retur nu sunt uniforme în HotXLS. Unele apeluri returnează 1 la succes, altele returnează un număr, astfel încât pentru funcțiile de listare singura verificare care rezistă este tratarea oricărei valori de zero sau mai mici ca eșec, cu lista de șiruri golită. Rezistați tentației de a citi o listă goală ca „un registru de lucru fără foi”. Atât ECMA-376, cât și specificația BIFF8 impun cel puțin o foaie într-un registru de lucru valid, așa că zero nume înseamnă întotdeauna că citirea a eșuat, niciodată că fișierul este legitim gol
O listare eșuată este ea însăși un semnal care merită păstrat. Un fișier .xlsx care eșuează la apel este unul dintre câteva lucruri specifice: trunchiat, deloc un pachet OOXML autentic (exporturile CSV etichetate greșit din alte sisteme apar aici constant), sau un container criptat. Deosebirea între acestea este treaba verificării următoare. Înregistrarea primilor octeți ai fișierului respins alături de eșec transformă de obicei un fir de suport într-un singur mesaj
Detectarea containerelor criptate înainte de rutare
Un fișier .xlsx criptat nu este o arhivă zip. Este un fișier compus OLE care înfășoară fluxurile EncryptionInfo și EncryptedPackage, astfel încât GetSheetNames nu poate vedea în interior și returnează eșec ca orice alt fișier ilizibil. CanReadEncrypted testează exact acea formă de container, ceea ce permite recepției să ruteze intenționat un fișier criptat, în loc să înghită o eroare generică de citire venită de undeva din adâncul unui worker:
type
TIntakeRoute = (irNormal, irNeedsPassword, irUnreadable);
function ClassifyUpload(const FileName: string; Names: TStrings): TIntakeRoute;
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
// OOXML criptat este un container OLE, nu o arhivă zip: verificați
// mai întâi, pentru că apelurile de listare nu pot privi în interior.
if Book.CanReadEncrypted(FileName) then
Exit(irNeedsPassword);
if SameText(ExtractFileExt(FileName), '.ods') then
begin
if Book.GetODSSheetNames(FileName, Names) <= 0 then
Exit(irUnreadable);
end
else if Book.GetSheetNames(FileName, Names) <= 0 then
Exit(irUnreadable);
Result := irNormal;
finally
Book.Free;
end;
end;
Criptarea este locul unde HotXLS este în mod deliberat asimetric, așa că rutarea trebuie să respecte acest lucru. Criptarea .xls veche (RC4, RC4 CryptoAPI, XOR) este lizibilă: TXLSWorkbook.Open(FileName, Password) decriptează cu o parolă stocată, iar acele fișiere pot rămâne pe calea automatizată. Pachetele OOXML criptate merg în sens invers. HotXLS poate scrie unul cu SaveAsEncrypted, dar nu poate citi înapoi unul. OpenEncrypted ridică EXlsxEncryptionNotImplemented atunci când primește un pachet criptat, motiv pentru care o proiectare onestă a recepției trimite fișierele .xlsx criptate către o persoană cu Excel și păstrează în cod fișierele .xls purtătoare de parolă
Pentru lucrul pe loturi, acest clasificator își câștigă locul rulând peste un întreg director de intrare înainte ca vreun worker să înceapă procesarea reală, deoarece fiecare sondare costă cam cât o deschidere de fișier și câțiva kiloocteți de citiri. Mutarea ei în față schimbă modul de eșec de care operațiunile chiar le pasă. În loc ca un job de la 3 dimineața să moară la fișierul 412 din 600, obțineți 412 fișiere puse la coadă și 5 respinse la recepție, fiecare cu un motiv atașat. Aceleași apeluri de bibliotecă, o poveste operațională mult mai bună
Întrebările la care un apel de listare nu poate răspunde
Numele și ordinea reprezintă tot ce obțineți. Apelurile de listare nu spun nimic despre vizibilitate, așa că foile ascunse și foarte ascunse ajung în listă arătând ca oricare alta. Nu raportează dimensiuni ale intervalului utilizat, nici numere de celule, nici proprietăți de document. Partea docProps/core.xml este mică și ea, dar astăzi nu există o sondare doar pentru proprietăți, așa că metadatele de autor și titlu tot mai costă o Open completă. Modul curat de a trăi cu asta este să lăsați faptele ieftine să ruteze fiecare fișier și să rezervați pe cele costisitoare pentru fișierele care supraviețuiesc rutării. Pentru fișierele care chiar avansează spre o citire profundă, o scanare doar-citire a unui .xls mare rulează vizibil mai rapid cu _DisableGraphics := True, care omite analiza OfficeArt. Doar nu salvați niciodată din acea instanță: stratul de desen pe care l-a omis a dispărut din model, iar salvarea l-ar elimina din fișier
Fișierele care trec de triaj se îndreaptă de obicei către o analiză mai profundă. Banca de lucru pentru audit și conversie a registrelor de lucru acoperă contoarele per-foaie care merită colectate odată ce o deschidere completă este justificată, iar ghidul de performanță pentru registre de lucru mari acoperă păstrarea rapidă a acelei deschideri complete
HotXLS este o bibliotecă nativă Object Pascal pentru foi de calcul, pentru Delphi și C++Builder; suprafața API completă, inclusiv apelurile de inspecție prezentate aici, este documentată pe pagina de produs HotXLS Delphi Component