Articolo tecnico

Figure PDF taggate da immagini Excel con HotXLS

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

Le immagini con AltText non vuoto vengono esportate come elementi di struttura PDF Figure con il proprio MCID; descrizioni vuote e grafici restano artifact
Solo la descrizione dell'autore in AltText segnala un'immagine informativa; un titolo da solo non diventa mai il testo alternativo
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à

Tagger indipendenti di celle e figure collidono sulla casella zero dell'albero dei padri; un contatore MCID a livello di pagina tiene ogni mark mappato a un solo proprietario
Il file in collisione passa comunque un validatore strutturale; solo l'annuncio dello screen reader è sbagliato

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

Il mark BDC apre l'ambito della Figure prima di ombra e ritaglio e l'EMC chiude dopo il disegno dell'immagine Do, coprendo l'intera istanza visibile
Avvolgere solo l'operatore immagine lascerebbe ombra e ritaglio come contenuto non marcato; la condivisione di risorse tra celle è preservata

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