Quando si elaborano grandi lotti di fogli di calcolo Excel in una pipeline automatizzata, raramente si desidera caricare l'intero documento in memoria solo per capire di cosa si tratta. Spesso, i metadati incorporati all'interno del file, autore, titolo, data di creazione e proprietà personalizzate, sono sufficienti per instradare, indicizzare o rifiutare il documento. Nel mondo di Microsoft Office, questi metadati sono noti come Informazioni di Riepilogo Documento.
L'estrazione nativa di queste informazioni in Delphi senza affidarsi all'automazione OLE (che richiede l'installazione di Excel sulla macchina host) richiede l'analisi diretta della struttura del file sottostante. In questo articolo, vedremo come funzionano i riepiloghi dei documenti nei file Excel e come estrarli in modo efficiente utilizzando l'analisi dei flussi grezzi.
Comprendere i Flussi di Metadati di Excel
Storicamente, i file Excel più vecchi (.xls) sono archiviati in formati di Documento Composito OLE (OLE Compound Document), agendo efficacemente come mini file system contenenti flussi e archivi. I metadati sono alloggiati in due flussi specifici:
\u0005SummaryInformation: contiene proprietà standard come Titolo, Oggetto, Autore, Parole Chiave e Numero di Revisione.\u0005DocumentSummaryInformation: contiene proprietà estese come Azienda, Manager e proprietà personalizzate definite dall'utente.
I file Excel moderni (.xlsx) utilizzano il formato Office Open XML (OOXML), che è una struttura XML compressa in formato ZIP. I metadati qui si trovano in docProps/core.xml, docProps/app.xml e docProps/custom.xml. Un componente di parsing Delphi robusto deve gestire senza problemi entrambe le strutture interne offrendo al contempo un'API unificata allo sviluppatore.
Analisi dei Documenti Compositi OLE in Delphi
Per leggere SummaryInformation da un file legacy `.xls` senza strumenti di terze parti, è necessario analizzare lo spazio di archiviazione strutturato OLE. Microsoft espone questo tramite l'interfaccia COM IPropertySetStorage. Ecco un'implementazione Delphi pura che evita di avviare Excel:
uses
System.SysUtils, System.Win.ComObj, Winapi.ActiveX, Winapi.Windows;
procedure ExtractXlsSummaryInfo(const FileName: string);
var
Stg: IStorage;
PropSetStg: IPropertySetStorage;
PropStg: IPropertyStorage;
PropSpec: TPropSpec;
PropVariant: TPropVariant;
Hr: HRESULT;
begin
// Open the OLE Compound Document
Hr := StgOpenStorage(PWideChar(WideString(FileName)), nil,
STGM_READ or STGM_SHARE_DENY_WRITE, nil, 0, Stg);
if Failed(Hr) then
raise Exception.Create('Failed to open OLE storage. File may not be a valid .xls document.');
// Query for the property set storage interface
if Stg.QueryInterface(IPropertySetStorage, PropSetStg) = S_OK then
begin
// Open the SummaryInformation stream (FMTID_SummaryInformation)
Hr := PropSetStg.Open(FMTID_SummaryInformation, STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg);
if Succeeded(Hr) then
begin
// Read the Author property (PIDSI_AUTHOR = 4)
PropSpec.ulKind := PRSPEC_PROPID;
PropSpec.propid := PIDSI_AUTHOR;
if PropStg.ReadMultiple(1, @PropSpec, @PropVariant) = S_OK then
begin
if PropVariant.vt = VT_LPSTR then
Writeln('Author: ', string(AnsiString(PropVariant.pszVal)));
PropVariantClear(PropVariant);
end;
end;
end;
end;
Estrazione Programmatica con HotXLS
Sebbene l'API COM di Windows funzioni per i file `.xls`, non funziona per i moderni file `.xlsx` (che sono archivi ZIP). Inoltre, l'utilizzo dell'API COM in ambito multipiattaforma (ad esempio su Linux o macOS tramite FireMonkey) è impossibile. I recenti aggiornamenti del componente HotXLS hanno introdotto unità dedicate (ad esempio, lxXlsSummary) per isolare e ottimizzare la lettura di questi flussi di riepilogo su entrambi i formati in modo completamente nativo nel codice Delphi.
Un Esempio Multipiattaforma
Utilizzando le interfacce XlsReadDocumentSummaryInformation e XlsReadSummaryInformation, è possibile acquisire rapidamente le stringhe dei metadati sia da `.xls` che da `.xlsx` senza preoccuparsi dell'architettura del file system sottostante.
uses
lxXlsSummary;
var
Summary: TXlsSummaryInfo;
ExtendedInfo: TXlsDocumentSummaryInfo;
begin
// Extract standard summary from an OOXML format seamlessly
Summary := XlsReadSummaryInformation('C:\Data\FinancialReport.xlsx');
try
Writeln('Title: ', Summary.Title);
Writeln('Author: ', Summary.Author);
Writeln('Creation Date: ', DateTimeToStr(Summary.CreateTime));
finally
Summary.Free;
end;
// Extract extended document summary
ExtendedInfo := XlsReadDocumentSummaryInformation('C:\Data\FinancialReport.xlsx');
try
Writeln('Company: ', ExtendedInfo.Company);
Writeln('Manager: ', ExtendedInfo.Manager);
finally
ExtendedInfo.Free;
end;
end;
Perché l'Estrazione Dedicata dei Riepiloghi è Importante
Il vantaggio principale di questo approccio è le prestazioni e la sicurezza della memoria. Evitando l'istanziazione dell'intero DOM (Document Object Model) della cartella di lavoro e analizzando solo docProps/core.xml o i flussi di proprietà OLE, l'impronta della tua applicazione rimane incredibilmente piccola. Se stai indicizzando 10.000 file Excel su una condivisione di rete, il tentativo di analizzarli completamente esaurirà la memoria e richiederà ore. L'estrazione dedicata dei riepiloghi completa la stessa attività in pochi secondi.
Inoltre, la lettura nativa dei flussi assicura che la tua applicazione possa funzionare come servizio in background o su un server Linux headless senza mai richiamare Excel.exe: un requisito critico per le moderne architetture scalabili.
Nota: gli strumenti completi per l'analisi di Excel e l'estrazione di metadati sono disponibili nel Componente VCL HotXLS.