O HotXLS grava pastas de trabalho Open XML no formato ISO/IEC 29500 Strict a partir do Delphi e do C++Builder ao definir uma única propriedade, StrictOOXML, antes de salvar. Cada parte do pacote, de xl/workbook.xml até os arquivos de relacionamento e os tipos de conteúdo, é gravada com os vocabulários strict purl.oclc.org, em vez dos vocabulários transitórios schemas.openxmlformats.org, e os recursos que o Strict não permite são rejeitados com uma exceção explícita, em vez de serem gravados mesmo assim
A maioria dos desenvolvedores encontra essa exigência por meio de um documento de licitação. Editais do setor público em várias jurisdições pedem a forma padronizada pela ISO do Open XML, não a forma transitória que o Office grava por padrão, e um arquivo de repositório que exige ISO 29500 Strict rejeita um .xlsx comum mesmo que o Excel o abra perfeitamente. Os namespaces transitórios existem para acomodar o comportamento binário legado; os namespaces strict são o padrão propriamente dito
O que realmente muda entre Strict e Transitional?
A diferença visível é o vocabulário. Uma parte de pasta de trabalho strict declara http://purl.oclc.org/ooxml/spreadsheetml/main como seu namespace raiz e http://purl.oclc.org/ooxml/officeDocument/relationships para referências de relacionamento, e nenhum namespace transitório pode sobreviver em nenhum lugar do pacote. Os tipos de relacionamento mudam junto, então a parte de relacionamentos raiz nomeia .../ooxml/officeDocument/relationships/officeDocument em vez do equivalente familiar em openxmlformats, e o tipo de propriedades estendidas usa camelCase como extendedProperties
A diferença invisível é o escopo. O Strict omite deliberadamente partes do schema transitório que só existiam para permitir ida e volta com arquivos binários legados, junto com as extensões de fornecedor que o Office adicionou depois. É por isso que a conversão não é uma simples busca e substituição de strings: alguns recursos simplesmente não têm grafia strict e não podem ser gravados de forma alguma
Ativando o recurso
O código de criação comum não muda. Construa a pasta de trabalho da forma como você sempre faz, defina a flag e salve:
var
Wb: TXLSXWorkbook;
Sh: TXLSXWorksheet;
begin
Wb := TXLSXWorkbook.Create;
try
Sh := Wb.Sheets.Add('Data');
Sh.Cells[1, 1].Value := 'Product';
Sh.Cells[1, 2].Value := 'Amount';
Sh.Cells[2, 1].Value := 'Widget';
Sh.Cells[2, 2].Value := 17;
Sh.Cells[3, 2].Formula := '=SUM(B2:B2)';
Wb.StrictOOXML := True; // saída ISO/IEC 29500 Strict
if Wb.SaveAs('archive-copy.xlsx') <> 1 then
raise Exception.Create('strict save failed');
finally
Wb.Free;
end;
end;
A flag é redefinida no início de cada operação de salvamento e reatribuída a partir da propriedade da pasta de trabalho, então uma exceção durante um salvamento não consegue vazar o modo strict para o próximo. Esse detalhe importa em processos de servidor em que um único objeto de pasta de trabalho atende a várias solicitações de exportação
Por que um salvamento strict pode se recusar a executar?
Quatro famílias de recursos são extensões da Microsoft sem equivalente no ISO 29500 Strict, e o HotXLS lança uma exceção no momento de salvar, em vez de emitir um pacote que afirma estar em conformidade strict sem realmente estar:
// A saída Strict não pode incorporar um projeto VBA
// -> salve pastas de trabalho habilitadas para macro como .xlsm transitório
// A saída Strict não pode carregar controles de formulário
// -> botões, caixas de seleção, caixas de combinação e seus ctrlProps
// A saída Strict não pode carregar comentários encadeados
// -> o modelo moderno de persons/threads, não as notas clássicas
// A saída Strict não pode carregar metadados de array dinâmico
// -> intervalos de derramamento (spill ranges) registrados na parte de metadados
Falhar ruidosamente é a escolha certa aqui. Um projeto VBA descartado silenciosamente transforma uma pasta de trabalho funcional em uma quebrada que ainda assim abre, e o relato dessa falha chega de um usuário semanas depois. Uma exceção nomeia o recurso e a propriedade a mudar enquanto o código chamador ainda sabe o que estava exportando. A preservação de macros e de links externos no caminho transitório é abordada em preservação de projetos VBA e links externos
Duas famílias de extensões são tratadas de forma diferente, e vale a pena entender por quê. Barras de dados, sparklines e recursos semelhantes vivem nos vocabulários x14 e xm, e as variantes SVG de imagens vivem em c15. Esse conteúdo de lista de extensão tem namespaces autodescritivos, analisadores de planilhas genéricos os toleram, e não há equivalente ISO para traduzi-los. O HotXLS os mantém em vez de descartar conteúdo do usuário. Se um validador no seu pipeline for rigoroso quanto a extensões além dos namespaces, remova esses recursos da pasta de trabalho de origem antes de exportar
A tradução precisa alcançar partes que ninguém normalmente reescreve
O problema de engenharia interessante na saída strict não é o XML da planilha. É as partes que um gravador rápido preferiria copiar literalmente. O HotXLS preserva temas, conexões, links externos, gráficos e blobs de tabela dinâmica copiando diretamente seus bytes comprimidos originais, o que é exatamente a coisa certa a fazer pela fidelidade e exatamente a coisa errada para a saída strict, porque os bytes copiados carregam namespaces transitórios
Sob StrictOOXML, esses cinco caminhos preservados passam a ser reconstruídos ou a uma reexecução tradutora, contornando o caminho rápido de cópia de bytes. Todo o XML passa por uma única rotina de tradução, que se ancora em valores de atributo entre aspas duplas, de modo que uma string com aparência de URI dentro de uma célula nunca pode ser reescrita por acidente. Texto de célula contendo a mesma URI é escapado como entidade no XML, então a substituição ancorada não consegue enxergá-lo. O gravador em streaming traduz seu esqueleto primeiro e depois divide em sheetData, já que os blocos de linha não contêm nenhuma URI de vocabulário. A mecânica relacionada do caminho de preservação é abordada em ida e volta sem perdas de temas, listas de extensão e calcChain
Lendo arquivos que o Excel salvou como strict
A saída é só metade da história. O Excel oferece "Planilha Open XML Estrita" como opção de salvamento, e os arquivos produzidos dessa forma precisam abrir corretamente. O HotXLS normaliza os tipos de relacionamento em cada ponto de análise de relacionamento no pacote, a raiz, os links externos, as planilhas, os desenhos e as tabelas dinâmicas, de modo que um tipo de relacionamento strict corresponde à mesma constante interna que sua contraparte transitória
A contraparte do lado da leitura é a normalização de prefixos de namespace, que permite que prefixos arbitrários e ambos os vocabulários se resolvam para uma única tabela de nomes canônica. Esse trabalho beneficia arquivos comuns tanto quanto os strict, já que geradores de terceiros vinculam prefixos livremente, e é a mesma mecânica descrita em resolução de relacionamentos OPC em pacotes XLSX
Uma checklist rápida antes de entregar a saída strict
Verifique com o pacote, não com o Excel. O Excel abre as duas formas sem reclamar, então uma abertura bem-sucedida não prova nada sobre conformidade. Descompacte o resultado e confirme que xl/workbook.xml declara o namespace purl, que nenhuma parte contém schemas.openxmlformats.org/spreadsheetml, e que os tipos de relacionamento em _rels/.rels e xl/_rels/workbook.xml.rels usam as formas strict
Depois reabra o arquivo pelo HotXLS e compare valores, fórmulas, formatos e hiperlinks com a origem. Um teste de releitura é a única forma barata de comprovar que a tradução não danificou o conteúdo, e ele exercita ao mesmo tempo a normalização do lado da leitura. Se suas pastas de trabalho carregam gráficos, verifique-os também, já que a parte de gráfico é uma das partes preservadas que passa a um caminho reconstruído sob o modo strict
Saída strict, leitura tolerante e preservação sem perdas fazem parte do mesmo mecanismo OOXML para Delphi e C++Builder; a lista completa de recursos está na página do componente de planilhas para Delphi HotXLS