O HotXLS escreve pastas de trabalho Open XML ISO/IEC 29500 Strict a partir do Delphi e do C++Builder através da definição de uma única propriedade, StrictOOXML, antes de gravar. Cada parte do pacote, desde xl/workbook.xml até aos ficheiros de relações e aos tipos de conteúdo, é escrita com os vocabulários strict de purl.oclc.org em vez dos vocabulários transitórios de schemas.openxmlformats.org, e as funcionalidades que o Strict não permite são rejeitadas com uma exceção explícita, em vez de serem escritas na mesma
A maioria dos programadores encontra este requisito através de um documento de contratação pública. Os concursos do setor público em várias jurisdições pedem a forma normalizada ISO do Open XML, e não a forma transitória que o Office escreve por predefinição, e um arquivo que exija ISO 29500 Strict vai rejeitar um .xlsx normal, mesmo que o Excel o abra na perfeição. Os espaços de nomes transitórios existem para acomodar comportamento binário legado; os espaços de nomes strict são a norma propriamente dita
O que realmente difere 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 o seu espaço de nomes raiz e http://purl.oclc.org/ooxml/officeDocument/relationships para referências de relação, e nenhum espaço de nomes transitório pode sobreviver em qualquer ponto do pacote. Os tipos de relação mudam com isso, pelo que a parte de relações raiz nomeia .../ooxml/officeDocument/relationships/officeDocument em vez do equivalente openxmlformats habitual, e o tipo de propriedades estendidas passa a camelCase como extendedProperties
A diferença invisível é o âmbito. O Strict omite deliberadamente partes do esquema transitório que só existiam para permitir a compatibilidade bidirecional com ficheiros binários legados, juntamente com as extensões de fornecedor que o Office acrescentou depois. É por isso que a conversão não é uma simples substituição de texto: algumas funcionalidades simplesmente não têm forma strict e não podem ser escritas de todo
Ativar a funcionalidade
O código de criação comum não muda. Construa a pasta de trabalho da forma habitual, defina a opção, e grave:
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 opção é reposta no início de cada operação de gravação e reatribuída a partir da propriedade da pasta de trabalho, pelo que uma exceção durante uma gravação não pode fazer o modo strict infiltrar-se na gravação seguinte. Este detalhe importa em processos de servidor onde um único objeto de pasta de trabalho serve vários pedidos de exportação
Por que razão uma gravação strict pode recusar-se a correr?
Quatro famílias de funcionalidades são extensões da Microsoft sem equivalente ISO 29500 Strict, e o HotXLS lança uma exceção no momento da gravação em vez de emitir um pacote que afirma conformidade strict sem o ser:
// A saída Strict não pode incorporar um projeto VBA
// -> grave pastas de trabalho com macros como .xlsm transitório
// A saída Strict não pode transportar controlos de formulário
// -> botões, caixas de verificação, caixas de combinação e as respetivas ctrlProps
// A saída Strict não pode transportar comentários em thread
// -> o modelo moderno de persons/threads, não as notas clássicas
// A saída Strict não pode transportar metadados de arrays dinâmicos
// -> intervalos de spill registados através da parte de metadados
Falhar ruidosamente é a opção correta aqui. Um projeto VBA silenciosamente descartado transforma uma pasta de trabalho funcional numa pasta de trabalho quebrada que ainda assim abre, e o relatório da falha chega de um utilizador semanas depois. Uma exceção nomeia a funcionalidade e a propriedade a alterar enquanto o código que chama ainda sabe o que estava a exportar. A preservação de macros e de ligações externas no percurso transitório está descrita em preservar projetos VBA e ligações externas
Duas famílias de extensões são tratadas de forma diferente, e vale a pena saber porquê. As barras de dados, os sparklines e funcionalidades semelhantes residem nos vocabulários x14 e xm, e as variantes SVG de imagens residem em c15. Este é conteúdo de lista de extensão cujos espaços de nomes são autodescritivos, os analisadores de folhas de cálculo genéricos toleram-nos, e não existe equivalente ISO para os traduzir. O HotXLS mantém-nos em vez de descartar conteúdo do utilizador. Se um validador no seu pipeline for rigoroso quanto a extensões, além de espaços de nomes, remova essas funcionalidades da pasta de trabalho de origem antes de exportar
A tradução tem de alcançar partes que normalmente ninguém reescreve
O problema de engenharia interessante na saída strict não é o XML da folha de cálculo. É as partes que um escritor rápido preferiria copiar textualmente. O HotXLS preserva temas, ligações, ligações externas, gráficos e blobs de tabelas dinâmicas copiando diretamente os seus bytes comprimidos originais, o que é exatamente a coisa certa a fazer para a fidelidade e exatamente a coisa errada para a saída strict, porque os bytes copiados transportam espaços de nomes transitórios
Sob StrictOOXML, esses cinco percursos preservados passam a reconstrução ou a uma reprodução com tradução, 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, para que uma string com aspeto de URI dentro de uma célula nunca possa ser reescrita por acidente. O texto de célula que contenha o mesmo URI é escapado como entidade no XML, pelo que a substituição ancorada não o consegue ver. O escritor em fluxo traduz primeiro o seu esqueleto e depois divide em sheetData, já que os blocos de linhas não contêm nenhum URI de vocabulário. A mecânica relacionada com o percurso de preservação está descrita em ciclos completos sem perdas de temas, listas de extensão e calcChain
Ler ficheiros que o Excel gravou como strict
A saída é apenas metade da história. O Excel oferece "Folha de Cálculo Open XML Strict" como opção de gravação, e os ficheiros produzidos dessa forma têm de abrir corretamente. O HotXLS normaliza os tipos de relação em cada ponto de análise de relações do pacote, a raiz, as ligações externas, as folhas de cálculo, os desenhos e as tabelas dinâmicas, pelo que um tipo de relação strict corresponde à mesma constante interna do seu equivalente transitório
A contrapartida do lado da leitura é a normalização de prefixos de espaço de nomes, que permite que prefixos arbitrários e ambos os vocabulários se resolvam para uma única tabela de nomes canónica. Esse trabalho beneficia tanto os ficheiros comuns como os strict, já que os geradores de terceiros associam prefixos livremente, e é a mesma maquinaria descrita em resolução de relações OPC em pacotes XLSX
Uma lista de verificação breve antes de disponibilizar a saída strict
Verifique com o pacote, não com o Excel. O Excel abre ambas as formas sem problemas, pelo que uma abertura bem-sucedida não prova nada sobre a conformidade. Descomprima o resultado e confirme que xl/workbook.xml declara o espaço de nomes purl, que nenhuma parte contém schemas.openxmlformats.org/spreadsheetml, e que os tipos de relação em _rels/.rels e xl/_rels/workbook.xml.rels usam as formas strict
Depois volte a abrir o ficheiro através do HotXLS e compare valores, fórmulas, formatos e hiperligações com a origem. Um teste de releitura é a única forma económica de provar que a tradução não danificou o conteúdo, e exercita ao mesmo tempo a normalização do lado da leitura. Se as suas pastas de trabalho tiverem gráficos, verifique-os também, já que a parte do gráfico é uma das partes preservadas que muda para um percurso reconstruído em modo strict
A saída strict, a leitura tolerante e a preservação sem perdas fazem todas parte do mesmo motor OOXML para Delphi e C++Builder; a lista completa de funcionalidades está na página do componente de folha de cálculo para Delphi HotXLS