Technisch artikel

Getagde PDF-Figures uit Excel-afbeeldingen met HotXLS

Wanneer HotXLS een werkblad naar PDF exporteert met automatisch taggen aan, worden werkbladafbeeldingen die alternatieve tekst dragen nu uitgezonden als zelfstandige /Figure-structuurelementen met een Unicode-/Alt-ingang, dichte pagina-lokale marked-content identifiers en exacte parent-tree-ingangen. Afbeeldingen zonder alternatieve tekst blijven decoratieve artefacten, en grafieken blijven ook artefacten. Dat precieze bereik doet ertoe: het maakt informatieve afbeeldingen bereikbaar voor een schermlezer, en het is niet hetzelfde als volledige PDF/UA-conformiteit

De mechaniek erachter is interessanter dan de functieomschrijving, want twee ervan zijn het soort detail dat geruisloos een structureel geldige PDF oplevert waarvan de structuur naar de verkeerde inhoud wijst

Wat geldt als een informatieve afbeelding?

Alleen een niet-lege AltText. De eigenschap TXLSXImage.AltText voert het OOXML-attribuut descr van de niet-visuele eigenschappen van de afbeelding rond, en daar bewaart Excel de tekst die een gebruiker in het alt-tekstvenster typt. Dat is het enige signaal in het bestand dat de auteur de afbeelding als informatiedrager in plaats van decoratie beschouwde, dus het is het enige signaal dat de exporter vertrouwt

Twee bijna-goede kandidaten worden bewust niet geaccepteerd. Het titelveld, apart van de omschrijving opgeslagen, is geen vervanger: een titel is een naam voor het object, geen tekstuele tegenhanger ervan, en die tot /Alt promoveren zou een document opleveren dat een geautomatiseerde controle haalt terwijl het tegen een schermlezer "Afbeelding 3" verkondigt. Een lege omschrijving is ook geen gat dat met een placeholder moet worden gevuld; die betekent dat de afbeelding een artefact blijft, wat de juiste uitkomst is voor een logo of een scheidslijn. Grafieken blijven voorlopig ook artefacten, want de tekstuele tegenhanger van een grafiek zijn zijn gegevens, en er een synthetiseren uit de reeksen zou uitvinden zijn in plaats van extraheren

Afbeeldingen met niet-lege AltText worden geëxporteerd als PDF Figure-structuurelementen met hun eigen MCID; lege omschrijvingen en grafieken blijven artefacten
Alleen de auteursomschrijving in AltText signaleert een informatieve afbeelding; een titel alleen wordt nooit de alt-tekst
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 vóór het exporteren: een afbeelding zonder omschrijving
    // wordt geëxporteerd als decoratief artefact
    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;

Waarom heeft de pagina één MCID-toewijzer nodig?

Omdat de parent tree een array is die geïndexeerd wordt op marked-content identifier, en twee toewijzers twee ingangen opleveren die dezelfde plek claimen. Getagde PDF verbindt inhoud en structuur in beide richtingen. Aan de inhoudskant wordt een reikwijdte van de paginacontentstream gewikkeld in de operatoren BDC en EMC die een /MCID-nummer dragen dat uniek is binnen die pagina. Aan de structuurkant draagt de paginadictionary een sleutel /StructParents die een rij van de document-/ParentTree benoemt, en die rij is een array waarvan het element op index n het structuurelement is dat MCID n bezit

Een werkbladpagina bevat tabelcellen en, inmiddels, figures. Als de celtagger zijn identifiers telt vanaf nul en de figuretagger ook vanaf nul telt, claimt de eerste figure de plek die de eerste cel al bezit. Niets aan het resulterende bestand is misvormd genoeg om een parser te laten weigeren: de structuurboom is intact, de marked content is gebalanceerd, en een validator ziet een document met een parent tree. Wat een schermlezer krijgt, is een tabelcel die wordt aangekondigd als afbeelding, of een afbeelding die wordt aangekondigd met de tekst van een cel. De exporter wijst daarom toe vanuit één teller op paginaniveau die beide taggers delen, en bevriest het paginarecord pas zodra het paginaobjectnummer bekend is, want de parent-tree-rij kan niet worden geschreven voordat de pagina waar hij naar verwijst een identiteit heeft

Onafhankelijke cel- en figuretaggers botsen op parent tree-plek nul; één MCID-teller op paginaniveau houdt elke markering aan één eigenaar gekoppeld
Het botsende bestand haalt nog steeds een structurele validator; alleen de aankondiging van de schermlezer is verkeerd

De Figure moet de hele zichtbare instantie omsluiten

De naïeve plaatsing is de operator Do omsluiten die het afbeeldings-XObject aanroept, want dat is de operator die de afbeelding tekent. Het is niet genoeg. Een werkbladafbeelding wordt vaak getekend met een schaduw erachter en een clipping pad eromheen, en die markeringen zijn deel van het zichtbare object. Buiten de /Figure-scope gelaten worden ze ongemarkeerde inhoud, en dat is precies de toestand die een structuuraudit vlagt

Daarom opent de marked-content-scope vóór de schaduw en sluit na het tekenen van de afbeelding, en omvat ook de clip. Delen blijft behouden waar delen correct is: twee cellen die dezelfde afbeeldingspayload tonen refereren nog steeds naar één afbeeldings-XObject, want dat is een optimalisatie op resourceniveau en heeft niets met semantiek te maken. Wat elke zichtbare instantie krijgt is zijn eigen MCID en zijn eigen structuurelement, want twee voorkomens van hetzelfde logo op verschillende plaatsen zijn twee dingen die een lezer tegenkomt. Afbeeldingsplaatsing en de EMU-geometrie die deze objecten positioneert wordt behandeld in het artikel over afbeeldingsgeometrie

De BDC-markering opent de Figure-scope vóór schaduw en clip en EMC sluit na het tekenen van de Do-afbeelding, omvattend de hele zichtbare instantie
Alleen de afbeeldingsoperator omsluiten zou schaduw en clip als ongemarkeerde inhoud achterlaten; het delen van resources tussen cellen blijft behouden

Leesvolgorde op een werkbladpagina

Leesvolgorde is een beslissing die de exporter moet nemen, want een spreadsheet heeft geen geschreven stroom zoals een document die heeft. De aangehouden regel is stabiel en makkelijk uit te leggen: per pagina komt eerst de tabel, daarna de figures in tekenvolgorde. Een lezer hoort dus eerst de tabelinhoud van de pagina en daarna diens afbeeldingen, in plaats van afbeeldingen tussengevoegd op welke positie de tekenobjecten toevallig in het bestand innamen

Die volgorde is per pagina in plaats van per document, wat telt bij een werkboek dat pagineert naar tientallen pagina's: de structuurtak van elke pagina is zelfstandig, dus een lezer die tussen pagina's beweegt springt niet terug in een eerdere tabel. Heeft u zeggenschap nodig over hoe het blad in de eerste plaats pagineert, dan wordt de interactie tussen pagina-instelling en afdrukbereik beschreven in het artikel over beveiliging en pagina-instelling

Wat dit certificeert, en wat niet

Het certificeert dat informatieve afbeeldingen de hulptechnologie bereiken met hun door de auteur geleverde omschrijving, en dat de inhoud-naar-structuur-mapping correct is in plaats van slechts aanwezig. Het maakt de uitvoer niet PDF/UA-conform, en het zo noemen zou een claim zijn die de implementatie niet kan dragen: grafieken zijn nog steeds artefacten, en een volledige conformiteitsverklaring vereist een audit van elk structuurtype, elk font en de documentmetadata als geheel

Is uw vereiste een archiverings- of conformiteitsprofiel in plaats van toegankelijkheidsverbetering, dan is dat een andere exportconfiguratie en een andere set controles, beschreven in het artikel over PDF/A-archiveringsexport. De twee combineren, maar ze antwoorden aan verschillende auditors

Eén praktische suggestie voor een rapportagepijplijn: audit alternatieve tekst op het moment waarop het werkboek wordt gegenereerd, niet op exporttijd. De generator weet wat elke grafiekafbeelding of ingebedde figuur voorstelt en kan een echte omschrijving in AltText schrijven; een passe op exporttijd kan u alleen vertellen dat een omschrijving ontbreekt. HotXLS leest en schrijft XLS, XLSX, ODS en CSV natively vanuit Delphi en C++Builder zonder Excel-afhankelijkheid, en zijn exportconfiguratieopties staan op de productpagina van de HotXLS Delphi spreadsheet component