Când HotXLS exportă o foaie de lucru în PDF cu marcare automată activată, imaginile foilor de lucru care poartă text alternativ emit acum ca elemente de structură /Figure independente, cu o intrare Unicode /Alt, identificatori de conținut marcat denși și locali paginii și intrări exacte în arborele părinte. Imaginile fără text alternativ rămân artifact decorative, iar graficele rămân de asemenea artifact. Acest domeniu precis contează: face imaginile informative accesibile unui cititor de ecran, și nu este același lucru cu conformitatea PDF/UA completă
Mecanismele din spate sunt mai interesante decât descrierea funcției, deoarece două dintre ele sunt genul de detaliu care produce în tăcere un PDF structural valid a cărui structură indică spre conținutul greșit
Ce se contează drept imagine informativă?
Doar un AltText nevid. Proprietatea TXLSXImage.AltText duce dus-întors atributul OOXML descr al proprietăților non-vizuale ale imaginii, acolo unde Excel stochează textul pe care un utilizator îl bate în panoul de text alternativ. Acesta este singurul semnal din fișier că autorul a considerat imaginea ca purtând informație, nu decorațiune, deci este singurul semnal în care exporterul are încredere
Două aproape-potriviri nu sunt acceptate în mod deliberat. Câmpul de titlu, stocat separat de descriere, nu este un substitut: un titlu este un nume pentru obiect, nu un echivalent textual al lui, iar promovarea lui în /Alt ar produce un document care trece o verificare automată anunțând totuși „Picture 3" unui cititor de ecran. O descriere goală nu este de asemenea o lacună de umplut cu un substituent; înseamnă că imaginea rămâne artifact, ceea ce este rezultatul corect pentru un logo sau o linie de delimitare. Graficele rămân de asemenea artifact pentru moment, deoarece echivalentul textual al unui grafic sunt datele lui, iar sintetizarea unuia din serii ar fi invenție, nu extracție
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];
// Auditați înainte de export: o imagine fără descriere
// va fi exportată ca artifact decorativ
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;
De ce are nevoie pagina de un singur alocator MCID?
Pentru că arborele părinte este un vector indexat după identificator de conținut marcat, iar doi alocatori produc două intrări care revendică același slot. PDF-ul marcat conectează conținutul la structură în ambele direcții. Pe partea de conținut, un segment al content stream-ului paginii este învelit în operatori BDC și EMC care poartă un număr /MCID unic în interiorul acelei pagini. Pe partea de structură, dicționarul paginii poartă o cheie /StructParents care numește un rând al /ParentTree documentului, iar acel rând este un vector al cărui element la indexul n este elementul de structură care deține MCID n
O pagină de foaie de lucru conține celule de tabelă și, acum, figuri. Dacă marcatorul de celule își numără identificatorii de la zero, iar marcatorul de figuri numără și el de la zero, prima figură revendică slotul pe care prima celulă îl deține deja. Nimic din fișierul rezultat nu este suficient de malformat pentru ca un parser să îl respingă: arborele de structură este intact, conținutul marcat este echilibrat, iar un validator vede un document cu un arbore părinte. Ce primește un cititor de ecran este o celulă de tabelă anunțată drept imagine, sau o imagine anunțată cu textul unei celule. Exporterul alocă prin urmare dintr-un contor la nivel de pagină partajat de ambii marcatori, și îngheață înregistrarea paginii doar odată ce numărul de obiect al paginii este cunoscut, deoarece rândul din arborele părinte nu poate fi scris înainte ca pagina la care se referă să aibă o identitate
Figura trebuie să învelească întreaga instanță vizibilă
Plasarea naivă este să învelească operatorul Do care invocă XObject-ul imaginii, deoarece acela este operatorul care desenează imaginea. Nu este de ajuns. O imagine de foaie de lucru este adesea desenată cu o umbră în spate și o cale de decupare în jur, iar acele mărci fac parte din obiectul vizibil. Lăsate în afara domeniului /Figure ele devin conținut nemarcat, ceea ce este exact starea pe care un audit de structură o semnalează
Deci domeniul de conținut marcat se deschide înaintea umbrei și se închide după desenarea imaginii, acoperind și decuparea. Partajarea este păstrată acolo unde partajarea este corectă: două celule care afișează aceeași sarcină utilă de imagine referențiază tot un singur XObject de imagine, deoarece aceasta este o optimizare la nivel de resursă și nu are nimic de-a face cu semantica. Ce primește fiecare instanță vizibilă este propriul ei MCID și propriul ei element de structură, deoarece două apariții ale aceluiași logo în locuri diferite sunt două lucruri pe care un cititor le întâlnește. Plasarea imaginilor și geometria EMU care poziționează aceste obiecte este tratată în articolul despre geometria imaginilor
Ordinea de lectură pe o pagină de foaie de lucru
Ordinea de lectură este o decizie pe care exporterul trebuie să o ia, deoarece o tabelă nu are un flux autorat așa cum are un document. Regula adoptată este stabilă și ușor de explicat: pentru fiecare pagină, tabela vine mai întâi, apoi figurile în ordinea de desenare. Un cititor aude deci conținutul tabular al paginii și apoi imaginile ei, în loc să aibă imagini împletite la orice poziție s-au aflat obiectele de desenare în fișier
Ordinea aceea este per pagină, nu per document, ceea ce contează pe un registru de lucru care se paginează în zeci de pagini: ramura de structură a fiecărei pagini este autosuficientă, deci un cititor care se mișcă între pagini nu sare înapoi într-o tabelă anterioară. Dacă aveți nevoie de control asupra modului în care se paginează foaia de la bun început, interacțiunea între configurarea paginii și aria de tipărire este descrisă în articolul despre protecție și configurarea paginii
Ce certifică aceasta și ce nu certifică
Certifică că imaginile informative ajung la tehnologia asistivă cu descrierea furnizată de autor, și că cartografierea conținut-structură este corectă, nu doar prezentă. Nu face rezultatul conform PDF/UA, iar descrierea lui astfel ar fi o afirmație pe care implementarea nu o poate susține: graficele sunt încă artifact, iar o declarație completă de conformitate cere un audit al fiecărui tip de structură, al fiecărui font și al metadatelor documentului ca întreg
Dacă cerința dumneavoastră este un profil de arhivare sau de conformitate, nu o îmbunătățire de accesibilitate, aceasta este o altă configurație de export și un alt set de verificări, descrise în articolul despre exportul de arhivare PDF/A. Cele două se combină, dar răspund auditorilor diferiți
O sugestie practică pentru un pipeline de rapoarte: auditați textul alternativ în punctul în care este generat registrul de lucru, nu la momentul exportului. Generatorul știe ce reprezintă fiecare imagine de grafic sau diagramă înglobată, și poate scrie o descriere reală în AltText; o trecere la momentul exportului vă poate spune doar că o descriere lipsește. HotXLS citește și scrie XLS, XLSX, ODS și CSV nativ din Delphi și C++Builder fără nicio dependență de Excel, iar opțiunile lui de configurare a exportului sunt listate pe pagina de produs HotXLS Delphi spreadsheet component