Quando HotXLS esporta un foglio in PDF con il tagging automatico attivo, le immagini del foglio che trasportano testo alternativo ora vengono emesse come elementi di struttura /Figure indipendenti con una voce /Alt Unicode, identificatori di marked-content densi e locali alla pagina e voci esatte dell'albero dei padri. Le immagini senza testo alternativo restano artifact decorativi, e i grafici restano artifact anch'essi. Quell'ambito preciso conta: rende le immagini informative raggiungibili da uno screen reader, e non è la stessa cosa della piena conformità PDF/UA
La meccanica dietro è più interessante della descrizione della funzione, perché due dei suoi elementi sono il tipo di dettaglio che produce silenziosamente un PDF strutturalmente valido la cui struttura punta al contenuto sbagliato
Cosa conta come immagine informativa?
Solo un AltText non vuoto. La proprietà TXLSXImage.AltText fa il round-trip dell'attributo OOXML descr delle proprietà non visive dell'immagine, che è dove Excel conserva il testo che un utente digita nel riquadro del testo alternativo. È l'unico segnale nel file che l'autore abbia considerato l'immagine portatrice di informazione anziché di decorazione, quindi è l'unico segnale di cui l'esportatore si fida
Due quasi-opzioni sono deliberatamente non accettate. Il campo titolo, conservato separatamente dalla descrizione, non è un sostituto: un titolo è un nome per l'oggetto, non un equivalente testuale di esso, e promuoverlo in /Alt produrrebbe un documento che supera un controllo automatizzato annunciando "Immagine 3" a uno screen reader. Una descrizione vuota non è nemmeno un vuoto da riempire con un segnaposto; significa che l'immagine resta un artifact, che è l'esito corretto per un logo o una riga di separazione. I grafici restano anch'essi artifact per ora, perché l'equivalente testuale di un grafico sono i suoi dati e sintetizzarne uno dalle serie sarebbe invenzione anziché estrazione
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];
// Audit prima di esportare: un'immagine senza descrizione
// verrà esportata come 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;
Perché la pagina ha bisogno di un unico allocatore MCID?
Perché l'albero dei padri è un array indicizzato per marked-content identifier, e due allocatori producono due voci che rivendicano la stessa casella. Il PDF taggato collega contenuto e struttura in entrambe le direzioni. Sul lato contenuto, un intervallo dello stream di contenuto della pagina è avvolto in operatori BDC e EMC che trasportano un numero /MCID unico entro quella pagina. Sul lato struttura, il dizionario di pagina trasporta una chiave /StructParents che nomina una riga del /ParentTree del documento, e quella riga è un array il cui elemento all'indice n è l'elemento di struttura proprietario dell'MCID n
Una pagina di foglio contiene celle di tabella e, ora, figure. Se il tagger delle celle conta i propri identificatori da zero e il tagger delle figure conta anch'esso da zero, la prima figura rivendica la casella che la prima cella possiede già. Nulla nel file risultante è abbastanza malformato perché un parser lo rifiuti: l'albero della struttura è intatto, il marked content è bilanciato, e un validatore vede un documento con un albero dei padri. Ciò che uno screen reader ottiene è una cella di tabella annunciata come immagine, o un'immagine annunciata con il testo di una cella. L'esportatore quindi alloca da un contatore a livello di pagina condiviso da entrambi i tagger, e congela il record di pagina solo una volta noto il numero di oggetto della pagina, poiché la riga dell'albero dei padri non può essere scritta prima che la pagina a cui si riferisce abbia un'identità
La Figure deve avvolgere l'intera istanza visibile
La collocazione ingenua è avvolgere l'operatore Do che invoca lo XObject dell'immagine, poiché è l'operatore che disegna l'immagine. Non basta. Un'immagine di foglio è spesso disegnata con un'ombra dietro e un tracciato di ritaglio attorno, e quei mark sono parte dell'oggetto visibile. Lasciati fuori dall'ambito /Figure diventano contenuto non marcato, che è esattamente lo stato che un audit della struttura segnala
Così l'ambito del marked-content si apre prima dell'ombra e si chiude dopo il disegno dell'immagine, coprendo anche il ritaglio. La condivisione è preservata dove la condivisione è corretta: due celle che mostrano lo stesso payload di immagine referenziano ancora uno XObject di immagine, perché è un'ottimizzazione a livello di risorsa e non c'entra nulla con la semantica. Ciò che ogni istanza visibile ottiene è il proprio MCID e il proprio elemento di struttura, perché due occorrenze dello stesso logo in posti diversi sono due cose che un lettore incontra. Il posizionamento delle immagini e la geometria EMU che colloca questi oggetti è trattata nell'articolo sulla geometria delle immagini
Ordine di lettura su una pagina di foglio
L'ordine di lettura è una decisione che l'esportatore deve prendere, perché un foglio di calcolo non ha un flusso redatto come lo ha un documento. La regola adottata è stabile e facile da spiegare: per ogni pagina, prima la tabella, poi le figure in ordine di disegno. Un lettore quindi sente il contenuto tabellare della pagina e poi le sue immagini, anziché avere immagini intercalate nella posizione qualsiasi in cui gli oggetti di disegno capitavano di trovarsi nel file
Quell'ordine è per pagina anziché per documento, il che conta su una cartella che si impagina in dozzine di pagine: il ramo di struttura di ogni pagina è autosufficiente, così un lettore che si muove tra le pagine non salta indietro in una tabella precedente. Se serve controllo su come il foglio si impagini in primo luogo, l'interazione tra impostazioni pagina e area di stampa è descritta nell'articolo su protezione e impostazioni pagina
Cosa certifica, e cosa no
Certifica che le immagini informative raggiungono le tecnologie assistive con la descrizione fornita dall'autore, e che la mappatura contenuto-struttura è corretta anziché semplicemente presente. Non rende l'output conforme a PDF/UA, e descriverlo così sarebbe un'affermazione che l'implementazione non può sostenere: i grafici restano artifact, e una dichiarazione di conformità completa richiede un audit di ogni tipo di struttura, di ogni font e dei metadati del documento nel loro insieme
Se il requisito di Lei è un profilo di archiviazione o di conformità anziché un miglioramento dell'accessibilità, quella è una diversa configurazione di esportazione e un diverso insieme di controlli, descritti nell'articolo sull'esportazione archivistica PDF/A. Le due si combinano, ma rispondono ad auditor diversi
Un suggerimento pratico per una pipeline di report: auditare il testo alternativo nel punto in cui la cartella viene generata, non al momento dell'esportazione. Il generatore sa cosa rappresenta ogni immagine di grafico o diagramma incorporato, e può scrivere una vera descrizione in AltText; una passata al momento dell'esportazione può solo dire che una descrizione manca. HotXLS legge e scrive XLS, XLSX, ODS e CSV nativamente da Delphi e C++Builder senza dipendenza da Excel, e le sue opzioni di configurazione dell'esportazione sono elencate nella pagina di prodotto di HotXLS Delphi spreadsheet component