Technical Article

Estrarre le Informazioni di Riepilogo Documento dai File Excel in Delphi

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.