Technical Article

Extraindo Informações de Resumo de Documentos de Arquivos Excel no Delphi

Ao processar grandes lotes de planilhas Excel em um pipeline automatizado, raramente você deseja carregar o documento inteiro na memória apenas para descobrir o que é. Freqüentemente, os metadados incorporados no arquivo (autor, título, data de criação e propriedades personalizadas) são suficientes para rotear, indexar ou rejeitar o documento. No mundo do Microsoft Office, esses metadados são conhecidos como Informações de Resumo do Documento (Document Summary Information).

Extrair essas informações nativamente no Delphi sem depender de automação OLE (que requer que o Excel esteja instalado na máquina host) requer a análise direta da estrutura do arquivo subjacente. Neste artigo, veremos como os resumos de documentos funcionam em arquivos do Excel e como extraí-los de forma eficiente usando análise de fluxo bruta.

Compreendendo os Fluxos de Metadados do Excel

Historicamente, arquivos Excel mais antigos (.xls) são armazenados em formatos de Documento Composto OLE, atuando efetivamente como mini sistemas de arquivos contendo fluxos e armazenamentos. Os metadados estão alojados em dois fluxos específicos:

  • SummaryInformation: Contém propriedades padrão como Título, Assunto, Autor, Palavras-chave e Número de Revisão.
  • DocumentSummaryInformation: Contém propriedades estendidas, como Empresa, Gerente e propriedades personalizadas definidas pelo usuário.

Arquivos modernos do Excel (.xlsx) usam o formato Office Open XML (OOXML), que é uma estrutura XML compactada (zip). Os metadados aqui estão localizados em docProps/core.xml, docProps/app.xml e docProps/custom.xml. Um componente de análise Delphi robusto deve lidar perfeitamente com ambas as estruturas internas enquanto expõe uma API unificada ao desenvolvedor.

Analisando Documentos Compostos OLE no Delphi

Para ler o SummaryInformation de um arquivo legado `.xls` sem ferramentas de terceiros, você precisa analisar o Armazenamento Estruturado OLE. A Microsoft expõe isso através da interface COM IPropertySetStorage. Aqui está uma implementação Delphi bruta que evita a inicialização do 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;

Extração Programática com HotXLS

Embora a API COM do Windows funcione para arquivos `.xls`, ela não funciona para arquivos `.xlsx` modernos (que são arquivos ZIP). Além disso, usar a API COM em multiplataforma (por exemplo, no Linux ou macOS via FireMonkey) é impossível. Atualizações recentes do componente HotXLS introduziram unidades dedicadas (por exemplo, lxXlsSummary) para isolar e otimizar a leitura desses fluxos de resumo em ambos os formatos de forma completamente nativa em código Delphi.

Um Exemplo Multiplataforma

Usando as interfaces XlsReadDocumentSummaryInformation e XlsReadSummaryInformation, você pode capturar rapidamente as strings de metadados de ambos `.xls` e `.xlsx` sem se preocupar com a arquitetura do sistema de arquivos subjacente.

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;

Por que a Extração Dedicada de Resumo é Importante

O principal benefício dessa abordagem é o desempenho e a segurança da memória. Ao evitar a instanciação completa do DOM (Document Object Model) da pasta de trabalho e analisar apenas o docProps/core.xml ou os fluxos de propriedades OLE, o espaço ocupado pelo seu aplicativo permanece incrivelmente pequeno. Se você estiver indexando 10.000 arquivos Excel em um compartilhamento de rede, tentar analisar totalmente cada um deles destruirá sua memória e levará horas. A extração dedicada de resumo conclui a mesma tarefa em segundos.

Além disso, a leitura nativa dos fluxos garante que seu aplicativo possa ser executado como um serviço em segundo plano ou em um servidor Linux headless sem nunca invocar o Excel.exe — um requisito crítico para arquiteturas escaláveis modernas.

Nota: Ferramentas abrangentes de análise do Excel e extração de metadados estão disponíveis no HotXLS VCL Component.