Uma folha de cálculo carrega duas camadas de identidade. Há a grelha de células e há os metadados do documento que a acompanham: título, autor, empresa, palavras-chave e carimbos de data/hora. O Excel nunca mostra essa segunda camada na grelha, mas é a camada que o Windows Search indexa, a que o SharePoint lê para dar título a um documento e a que um sistema de gestão de arquivos utiliza para arquivar. Quando um livro de trabalho gerado herda o seu Autor e Título do modelo a partir do qual foi construído, cada sistema a jusante regista o estruturador do modelo como autor de quatro mil extratos de clientes. Os metadados não estão corretos em lado nenhum e são consultados em toda a parte.
O HotXLS expõe esta camada como propriedades comuns ao nível do livro de trabalho em ambos os seus motores: a fachada BIFF para .xls e a fachada OOXML para .xlsx. Lê um campo após abrir um ficheiro e escreve um campo antes de o guardar. A biblioteca decide em qual contentor físico o valor vai parar. O que vale a pena compreender antes de escrever um gerador é quais os campos que cada formato realmente suporta, onde esses campos residem fisicamente e a única regra de controlo que governa se um .xlsx regista ou não quaisquer metadados.
Dois formatos, dois modelos de armazenamento
A razão pela qual uma biblioteca de folhas de cálculo necessita de duas implementações de metadados, e a razão pela qual ferramentas inacabadas carimbam um formato corretamente e esquecem o outro, é que o .xls e o .xlsx guardam as suas propriedades em locais não relacionados. Um livro de trabalho BIFF escreve-as em fluxos de ficheiros compostos OLE, principalmente no conjunto de propriedades SummaryInformation que precede o próprio Excel, a par do registo em fluxo WRITEACCESS que nomeia quem guardou o ficheiro pela última vez. Um livro de trabalho OOXML guarda-as como partes XML dentro do pacote zip, divididas por finalidade: docProps/core.xml contém os campos Dublin Core (título, criador, assunto, palavras-chave, datas) e docProps/app.xml contém os campos ao nível da aplicação, tais como empresa e aplicação geradora, em conformidade com a norma ECMA-376 Parte 1.
O HotXLS unifica ambos os modelos de armazenamento em propriedades diretas do objeto do livro de trabalho. Nunca precisa de abrir um fluxo de conjunto de propriedades ou editar manualmente uma parte XML. Atribui cadeias de caracteres e datas ao livro de trabalho, e o contentor correto materializa-se para qualquer formato que guardar.
Carimbar livros de trabalho gerados a partir do registo de negócio
No lado XLSX, a classe TXLSXWorkbook expõe Title, Subject, Author, Keywords, Description, Category, LastModifiedBy, Company, Application e AppVersion como strings, mais Created e Modified como valores TDateTime onde zero significa não definido. A regra que fecha a lacuna de herança resume-se a uma frase: atribua cada campo em cada execução, obtendo os valores a partir do registo de negócio em vez de confiar no que quer que o modelo contenha.
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open('statement-template.xlsx') <> 1 then
raise Exception.Create('Template not available');
// Overwrite every field: anything left untouched is
// inherited from whoever designed the template.
Book.Title := 'Account Statement 2026-06 / ACME Corp';
Book.Subject := 'Monthly account statement';
Book.Author := 'Billing Service 4.2';
Book.LastModifiedBy := 'Billing Service 4.2';
Book.Company := 'Northwind Financial';
Book.Category := 'Customer Delivery';
Book.Keywords := 'statement;billing;2026-06;acct-10024';
Book.Description := 'Generated document - manual edits are not retained';
Book.Created := Now;
Book.Modified := Now;
Book.SaveAs('statement-10024.xlsx');
finally
Book.Free;
end;
end;
O campo Keywords merece mais reflexão do que habitualmente recebe. As infraestruturas de pesquisa indexam-no literalmente, seja o Windows Search, o SharePoint ou a maioria dos produtos DMS. Assim, uma convenção separada por ponto e vírgula contendo o número de conta e o período transforma cada livro de trabalho entregue num registo localizável sem qualquer consulta de base de dados adicional. Esse alcance é também o reverso da medalha. As propriedades viajam com cada cópia do ficheiro, muito além dos controlos de acesso do sistema que as escreveu, pelo que dados pessoais não devem constar ali.
O par de carimbos de data/hora carrega uma semântica que vale a pena definir na política interna em vez de a deixar ao acaso. O campo Created deve marcar o momento em que o seu fluxo de trabalho gerou o documento e permanecer inalterado. Modified is the field Excel updates whenever a recipient saves the file, so a divergence between the two after delivery is positive evidence that someone edited the workbook downstream, which settles more than one dispute about whose numbers a forwarded spreadsheet really holds. One trap hides in the unset state: it is the literal value zero, not an exception and not a null, so audit code has to test for zero explicitly. Format an unset TDateTime without that guard and your logs fill with a confidently wrong December 1899 date.
DocPropsTouched: o livro de trabalho que é enviado sem docProps
Um sinalizador de apenas leitura, DocPropsTouched, controla o gravador de propriedades XLSX. Um livro de trabalho no qual nunca foi atribuída qualquer propriedade não produz quaisquer partes docProps; o HotXLS recusa-se a escrever um esqueleto de metadados vazio. O comportamento é limpo e traz duas consequências que vale a pena acautelar na fase de desenho.
O código de receção no lado de consumo não deve assumir que o ficheiro core.xml existe em todos os pacotes. Uma ferramenta que o exija obrigatoriamente rejeitará ficheiros mínimos perfeitamente válidos. E se a sua postura de conformidade exigir que cada documento de saída tenha pelo menos a identidade do gerador, essa exigência traduz-se em código e não numa propriedade do formato: atribua Application e Author incondicionalmente no caminho de gravação, dado que um livro de trabalho intocado é inteiramente legal perante a especificação, embora viole silenciosamente a sua política.
A interface XLS antiga e a armadilha de Comments
A fachada BIFF inclui o conjunto de campos mais antigo e reduzido: Title, Subject, Author, Keywords, Comments, Company e Manager, além de LastSavedBy, um pseudónimo de UserName, que escreve o registo WRITEACCESS que o Excel apresenta quando outro utilizador tem o ficheiro bloqueado.
var
Legacy: IXLSWorkbook; // reference-counted interface: no manual Free
begin
Legacy := TXLSWorkbook.Create;
if Legacy.Open('archive-1999.xls') <= 0 then
raise Exception.Create('Cannot open archive file');
Legacy.Title := 'FY1999 ledger (migrated copy)';
Legacy.Author := 'Archive Migration Batch';
Legacy.Company := 'Northwind Financial';
Legacy.Comments := 'Migrated 2026-06-11; source retained in cold storage';
Legacy.LastSavedBy := 'migration-svc'; // BIFF WRITEACCESS record
Legacy.SaveAs('archive-1999-stamped.xls');
end;
Uma colisão de nomes gera confusão recorrente. A propriedade Comments ao nível do documento é a observação em texto livre apresentada na janela de propriedades do ficheiro. Não tem qualquer relação com os comentários de células, que são objetos da camada de desenho associados a intervalos através de uma API completamente distinta. Uma revisão de código que aceite "já escrevemos Comments" sem verificar a qual se refere aceitou uma alegação sobre a funcionalidade errada, e isso ocorre com mais frequência do que o nome partilhado sugeriria. Ambos partilham quatro letras e nem um único byte de armazenamento.
Ler metadados na receção e a lacuna de sondagem
A leitura é simétrica. Após o método Open, as mesmas propriedades regressam preenchidas a partir do ficheiro, o que transforma uma auditoria de metadados de livros de trabalho recebidos num ciclo curto.
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open(FileName) = 1 then
begin
Writeln(Format('%s | title="%s" author="%s" created=%s',
[ExtractFileName(FileName), Book.Title, Book.Author,
FormatDateTime('yyyy-mm-dd', Book.Created)]));
if Book.Created = 0 then
Writeln(' no creation date recorded');
end;
finally
Book.Free;
end;
end;
Planeie com uma limitação em mente. Não existe uma sondagem exclusiva de propriedades. O método GetSheetNames pode listar folhas sem carregar um livro de trabalho, mas ler o Title ou Author exige um Open completo, pelo que a triagem de metadados num arquivo grande paga o custo total de análise em cada ficheiro. No lado BIFF, pode reduzir esse custo para auditorias de apenas leitura definindo _DisableGraphics como true antes da abertura, o que ignora a camada de desenho. Ajusta-se a um ciclo que apenas lê propriedades e estatísticas de células, mas está incorreto no momento em que a mesma instância possa efetuar uma gravação, porque o conteúdo de desenho ignorado seria descartado. Quando a estrutura das folhas por si só permite filtrar o conjunto, sendo as exportações de folha única o caso óbvio a descartar, as técnicas económicas do nosso artigo sobre listagem de folhas e inspeção leve reduzem a quantidade de ficheiros que alcançam a passagem dispendiosa. E em tarefas de carimbagem em massa, onde são gravados milhares de resultados em vez de inspecionados, os padrões de desempenho de escrita do nosso artigo sobre escritas em fluxo para tarefas em lote aplicam-se sem alterações, pois a atribuição de propriedades não acrescenta tempo de gravação mensurável.
Cruzar formatos e conter a fuga de informação
As propriedades realizam o ciclo completo de ida e volta de forma limpa dentro de uma única fachada: abra um .xlsx, edite-o, guarde-o e o conjunto regressa intacto. A transição entre formatos é onde a suposição de paridade falha, porque os conjuntos de campos BIFF e OOXML não coincidem um para um. O BIFF tem o campo Manager e nenhum carimbo de data/hora; o OOXML tem Category, Description e o par Created/Modified. Um conversor que copie cegamente perderá o que quer que o formato de destino não consiga conter, pelo que deve mapear os campos explicitamente e incluir o mapeamento na sua lista de verificação de conversão, a par de tudo o resto que não sobrevive à viagem.
A fuga que a herança de modelos abre funciona no sentido inverso: informação que nunca teve intenção de enviar para o exterior. Nomes de autores, etiquetas de projetos internos guardadas em palavras-chave ou um título provisório que ninguém apagou. A disciplina de sobrescrever tudo exemplificada no gerador acima é la defesa completa, e vale a pena verificar da mesma forma que um terceiro o faria: abrindo a janela de Propriedades a que qualquer cliente tem acesso ou descompactando o .xlsx e lendo o ficheiro docProps/core.xml diretamente do pacote. O que vir ali é exatamente o que qualquer indexador a jusante verá.
Essa visibilidade a jusante é também o motivo pelo qual alguns campos requerem mais cuidado do que os restantes. Title, Author, Keywords (que surgem como Etiquetas/Tags) e Comments ou Description concentram a maior parte do peso de indexação no SharePoint e no Windows Search. Um Título que seja genuinamente distinto por documento, contendo o período e a conta, contribui mais para a capacidade de localização do que qualquer esquema de nomenclatura de pastas sobreposto, custando apenas uma atribuição por gravação.
As propriedades de documentos são o acabamento profissional mais económico que um livro de trabalho gerado pode ter, e o defeito mais comummente distribuído quando ninguém se responsabiliza por elas. Ambas as superfícies de propriedades aqui descritas pertencem ao Componente HotXLS, que as escreve nativamente para XLS e XLSX sem automação do Excel.