Technical Article

Extrahieren von Dokumentenzusammenfassungsinformationen aus Excel-Dateien in Delphi

Wenn große Stapel von Excel-Tabellen in einer automatisierten Pipeline verarbeitet werden, möchten Sie selten das gesamte Dokument in den Speicher laden, nur um herauszufinden, was es ist. Oft reichen die in der Datei eingebetteten Metadaten – Autor, Titel, Erstellungsdatum und benutzerdefinierte Eigenschaften – aus, um das Dokument weiterzuleiten, zu indizieren oder abzulehnen. In der Microsoft Office-Welt sind diese Metadaten als Dokumentenzusammenfassungsinformationen (Document Summary Information) bekannt.

Das Extrahieren dieser Informationen nativ in Delphi, ohne sich auf die OLE-Automatisierung zu verlassen (die erfordert, dass Excel auf dem Host-Rechner installiert ist), erfordert das direkte Parsen der zugrunde liegenden Dateistruktur. In diesem Artikel untersuchen wir, wie Dokumentenzusammenfassungen in Excel-Dateien funktionieren und wie man sie effizient durch direktes Parsen der Streams extrahiert.

Verständnis von Excel-Metadaten-Streams

Historisch gesehen werden ältere Excel-Dateien (.xls) in OLE-Compound-Dokumentformaten gespeichert, die effektiv als Mini-Dateisysteme fungieren, die Streams und Storages enthalten. Die Metadaten sind in zwei bestimmten Streams untergebracht:

  • SummaryInformation: Enthält Standardeigenschaften wie Titel, Thema, Autor, Schlüsselwörter und Revisionsnummer.
  • DocumentSummaryInformation: Enthält erweiterte Eigenschaften wie Unternehmen, Manager und benutzerdefinierte Eigenschaften.

Moderne Excel-Dateien (.xlsx) verwenden das Office Open XML (OOXML)-Format, das eine gezippte XML-Struktur ist. Die Metadaten befinden sich hier in docProps/core.xml, docProps/app.xml und docProps/custom.xml. Eine robuste Delphi-Parsing-Komponente muss beide internen Strukturen nahtlos verarbeiten und dem Entwickler gleichzeitig eine einheitliche API zur Verfügung stellen.

Parsen von OLE-Compound-Dokumenten in Delphi

Um die SummaryInformation aus einer älteren `.xls`-Datei ohne Tools von Drittanbietern zu lesen, müssen Sie den OLE Structured Storage parsen. Microsoft stellt dies über die COM-Schnittstelle IPropertySetStorage zur Verfügung. Hier ist eine native Delphi-Implementierung, die das Starten von Excel vermeidet:

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;

Programmgesteuerte Extraktion mit HotXLS

Während die Windows-COM-API für `.xls`-Dateien funktioniert, funktioniert sie nicht für moderne `.xlsx`-Dateien (die ZIP-Archive sind). Darüber hinaus ist die Verwendung der COM-API plattformübergreifend (z. B. unter Linux oder macOS über FireMonkey) unmöglich. Kürzliche Aktualisierungen der HotXLS-Komponente führten dedizierte Units ein (z. B. lxXlsSummary), um das Lesen dieser Zusammenfassungs-Streams für beide Formate vollständig nativ im Delphi-Code zu isolieren und zu optimieren.

Ein plattformübergreifendes Beispiel

Mithilfe der Schnittstellen XlsReadDocumentSummaryInformation und XlsReadSummaryInformation können Sie die Metadaten-Strings sowohl aus `.xls` als auch aus `.xlsx` schnell abrufen, ohne sich um die zugrunde liegende Dateisystemarchitektur kümmern zu müssen.

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;

Warum dedizierte Zusammenfassungsextraktion wichtig ist

Der Hauptvorteil dieses Ansatzes ist Leistung und Speichersicherheit. Indem die Instanziierung des vollständigen Workbook-DOMs (Document Object Model) vermieden und nur docProps/core.xml oder die OLE-Eigenschaften-Streams geparst werden, bleibt der Platzbedarf Ihrer Anwendung unglaublich gering. Wenn Sie 10.000 Excel-Dateien auf einer Netzwerkfreigabe indizieren, wird der Versuch, jede einzelne vollständig zu parsen, Ihren Speicher überlasten und Stunden dauern. Die dedizierte Zusammenfassungsextraktion erledigt dieselbe Aufgabe in Sekunden.

Darüber hinaus stellt das native Lesen der Streams sicher, dass Ihre Anwendung als Hintergrunddienst oder auf einem Headless-Linux-Server ausgeführt werden kann, ohne jemals Excel.exe aufzurufen – eine entscheidende Anforderung für moderne, skalierbare Architekturen.

Hinweis: Umfassende Excel-Parsing- und Metadatenextraktionstools sind in der HotXLS VCL-Komponente verfügbar.