Quando o HotXLS exporta uma planilha para PDF com a tagação automática habilitada, imagens de planilha que carregam texto alternativo agora emitem como elementos de estrutura /Figure independentes com uma entrada /Alt Unicode, marked-content identifiers densos e locais de página e entradas exatas de parent tree. Imagens sem texto alternativo permanecem artifacts decorativos, e gráficos também permanecem artifacts. Esse escopo preciso importa: torna imagens informativas alcançáveis a um leitor de tela, e não é a mesma coisa que conformidade total PDF/UA
A mecânica por trás disso é mais interessante que a descrição do recurso, porque dois dos detalhes são do tipo que silenciosamente produz um PDF estruturalmente válido cuja estrutura aponta para o conteúdo errado
O que conta como uma imagem informativa?
Apenas um AltText não vazio. A propriedade TXLSXImage.AltText faz o round-trip do atributo OOXML descr das propriedades não visuais da imagem, que é onde o Excel guarda o texto que um usuário digita no painel de texto alternativo. Esse é o único sinal no arquivo de que o autor considerou que a imagem carrega informação em vez de decoração, então é o único sinal em que o exportador confia
Dois quase-acertos são deliberadamente não aceitos. O campo título, guardado separado da descrição, não é um substituto: um título é um nome para o objeto, não um equivalente textual dele, e promovê-lo a /Alt produziria um documento que passa em uma checagem automatizada enquanto anuncia "Imagem 3" a um leitor de tela. Uma descrição vazia também não é uma lacuna a ser preenchida com um placeholder; significa que a imagem permanece um artifact, que é o desfecho correto para um logo ou uma régua divisória. Gráficos também permanecem artifacts por ora, porque o equivalente textual de um gráfico são seus dados e sintetizar um a partir das séries seria invenção em vez de extração
uses
lxHandleX, lxPDF;
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Exporter: TXLSPDFExport;
I: Integer;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('regional-review.xlsx');
Sheet := Book.Sheets.ByPos[0];
// Audite antes de exportar: uma imagem sem descrição
// será exportada como artifact decorativo
for I := 0 to Sheet.Images.Count - 1 do
if Sheet.Images[I].AltText = '' then
Sheet.Images[I].AltText := DescribeImage(Sheet.Images[I].Name);
Exporter := TXLSPDFExport.Create;
try
Exporter.TagMode := xlsPdfTagsAutomatic;
Exporter.DocumentLanguage := 'en-US';
Exporter.SaveAsPDF(Sheet, 'regional-review.pdf');
finally
Exporter.Free;
end;
finally
Book.Free;
end;
end;
Por que a página precisa de um único alocador de MCID?
Porque a parent tree é um array indexado por marked-content identifier, e dois alocadores produzem duas entradas reivindicando o mesmo slot. O PDF tagged conecta conteúdo a estrutura nos dois sentidos. No lado do conteúdo, um trecho do content stream da página é embrulhado em operadores BDC e EMC carregando um número /MCID que é único dentro dessa página. No lado da estrutura, o dicionário de página carrega uma chave /StructParents nomeando uma linha do /ParentTree do documento, e essa linha é um array cujo elemento no índice n é o elemento de estrutura que possui o MCID n
Uma página de planilha contém células de tabela e, agora, figuras. Se o tagger de células conta seus identificadores a partir de zero e o tagger de figuras também conta a partir de zero, a primeira figura reivindica o slot que a primeira célula já possui. Nada no arquivo resultante é malformado o suficiente para um parser rejeitar: a árvore de estrutura está intacta, o marked content está balanceado, e um validador vê um documento com uma parent tree. O que um leitor de tela recebe é uma célula de tabela anunciada como imagem, ou uma imagem anunciada com o texto de uma célula. O exportador portanto aloca de um contador de nível de página compartilhado pelos dois taggers, e congela o record da página só quando o número de objeto da página é conhecido, já que a linha da parent tree não pode ser escrita antes de a página a que se refere ter uma identidade
A Figure deve embrulhar toda a instância visível
A colocação ingênua é embrulhar o operador Do que invoca o XObject da imagem, já que é o operador que desenha a imagem. Não basta. Uma imagem de planilha frequentemente é desenhada com uma sombra atrás e um caminho de recorte ao redor, e essas marcas são parte do objeto visível. Deixadas fora do escopo /Figure viram conteúdo não marcado, que é exatamente o estado que uma auditoria de estrutura sinaliza
Então o escopo de marked-content abre antes da sombra e fecha depois do desenho da imagem, cobrindo também o recorte. O compartilhamento é preservado onde o compartilhamento é correto: duas células mostrando o mesmo payload de imagem ainda referenciam um XObject de imagem, porque isso é uma otimização de nível de recurso e não tem nada a ver com semântica. O que cada instância visível recebe é seu próprio MCID e seu próprio elemento de estrutura, porque duas ocorrências do mesmo logo em lugares diferentes são duas coisas que um leitor encontra. A colocação de imagens e a geometria EMU que posiciona esses objetos é coberta em o artigo de geometria de imagens
Ordem de leitura em uma página de planilha
A ordem de leitura é uma decisão que o exportador precisa tomar, porque uma planilha não tem fluxo autoral do jeito que um documento tem. A regra adotada é estável e fácil de explicar: para cada página, a tabela vem primeiro, depois figuras em ordem de desenho. Um leitor portanto ouve o conteúdo tabular da página e depois suas imagens, em vez de ter imagens intercaladas na posição que os objetos de desenho por acaso ocupavam no arquivo
Essa ordem é por página em vez de por documento, o que importa em uma pasta de trabalho que pagina em dezenas de páginas: o ramo de estrutura de cada página é autossuficiente, então um leitor se movendo entre páginas não salta de volta a uma tabela anterior. Se você precisa controlar como a aba pagina em primeiro lugar, a interação de configuração de página e área de impressão é descrita em o artigo de proteção e configuração de página
O que isto certifica, e o que não
Certifica que imagens informativas chegam à tecnologia assistiva com sua descrição fornecida pelo autor, e que o mapeamento de conteúdo para estrutura está correto em vez de meramente presente. Não torna a saída PDF/UA conforme, e descrevê-la assim seria uma alegação que a implementação não pode sustentar: gráficos ainda são artifacts, e uma declaração de conformidade completa exige uma auditoria de todo tipo de estrutura, toda fonte e os metadados do documento como um todo
Se seu requisito é um perfil de arquivamento ou conformidade em vez de melhoria de acessibilidade, essa é uma configuração de exportação diferente e um conjunto diferente de checagens, descrito em o artigo de exportação de arquivamento PDF/A. Os dois se combinam, mas respondem a auditores diferentes
Uma sugestão prática para um pipeline de relatórios: audite o texto alternativo no ponto em que a pasta de trabalho é gerada, não no momento da exportação. O gerador sabe o que cada imagem de gráfico ou diagrama embutido representa, e pode escrever uma descrição real no AltText; uma passada em tempo de exportação só pode dizer que uma descrição está ausente. O HotXLS lê e escreve XLS, XLSX, ODS e CSV nativamente de Delphi e C++Builder sem dependência de Excel, e suas opções de configuração de exportação estão listadas na página de produto do HotXLS Delphi spreadsheet component