Τεχνικό Άρθρο

Tagged PDF Figure από εικόνες Excel με HotXLS

Όταν το HotXLS εξάγει ένα φύλλο εργασίας σε PDF με ενεργοποιημένη αυτόματη ετικετοποίηση, οι εικόνες φύλλου που κουβαλούν εναλλακτικό κείμενο εκπέμπονται πλέον ως ανεξάρτητα στοιχεία δομής /Figure με εγγραφή /Alt Unicode, πυκνά σελίδα-τοπικά marked-content identifiers και ακριβείς εγγραφές parent-tree. Οι εικόνες χωρίς εναλλακτικό κείμενο παραμένουν διακοσμητικά artifacts, και τα διαγράμματα παραμένουν επίσης artifacts. Εκείνο το ακριβές εύρος έχει σημασία: κάνει τις πληροφοριακές εικόνες προσιτές σε screen reader, και δεν είναι το ίδιο πράγμα με την πλήρη συμμόρφωση PDF/UA

Η μηχανική πίσω από αυτό είναι πιο ενδιαφέρουσα από την περιγραφή της λειτουργίας, επειδή δύο από αυτά είναι ο τύπος λεπτομέρειας που παράγει σιωπηλά ένα δομικά έγκυρο PDF του οποίου η δομή δείχνει λάθος περιεχόμενο

Τι μετράει ως πληροφοριακή εικόνα;

Μόνο ένα μη κενό AltText. Η ιδιότητα TXLSXImage.AltText τυλίγει το OOXML attribute descr των μη οπτικών ιδιοτήτων της εικόνας, που είναι εκεί όπου το Excel αποθηκεύει το κείμενο που πληκτρολογεί ο χρήστης στο πάνελ alt-text. Είναι το μόνο σήμα στο αρχείο ότι ο συγγραφέας θεώρησε την εικόνα κουβάλα πληροφορία και όχι διακόσμηση, οπότε είναι το μόνο σήμα στο οποίο εμπιστεύεται ο εξαγωγέας

Δύο σχεδόν-υποψήφια απορρίπτονται σκόπιμα. Το πεδίο title, αποθηκευμένο χωριστά από την περιγραφή, δεν είναι υποκατάστατο: ένας title είναι όνομα για το object, όχι textual ισοδύναμό του, και η προώθησή του σε /Alt θα παρήγαγε έγγραφο που περνά αυτοματοποιημένο έλεγχο ενώ ανακοινώνει «Picture 3» σε screen reader. Μια κενή περιγραφή δεν είναι επίσης κενό προς γέμισμα με placeholder· σημαίνει ότι η εικόνα μένει artifact, που είναι το σωστό αποτέλεσμα για λογότυπο ή διαχωριστική γραμμή. Τα διαγράμματα παραμένουν επίσης artifacts προς το παρόν, επειδή το textual ισοδύναμο ενός διαγράμματος είναι τα δεδομένα του και η σύνθεση ενός από τις σειρές θα ήταν εφεύρεση και όχι εξαγωγή

Εικόνες με μη κενό AltText εξάγονται ως στοιχεία δομής PDF Figure με το δικό τους MCID· κενές περιγραφές και διαγράμματα μένουν artifacts
Μόνο η περιγραφή του συγγραφέα στο AltText σηματοδοτεί πληροφοριακή εικόνα· ένας title μόνος δεν γίνεται ποτέ το alt κείμενο
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];

    // Έλεγχος πριν την εξαγωγή: μια εικόνα χωρίς περιγραφή
    // θα εξαχθεί ως διακοσμητικό artifact
    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;

Γιατί η σελίδα χρειάζεται έναν και μοναδικό κατανομέα MCID;

Επειδή το parent tree είναι ένας πίνακας δεικτοδοτημένος με marked-content identifier, και δύο κατανομείς παράγουν δύο εγγραφές που διεκδικούν την ίδια θέση. Το tagged PDF συνδέει το περιεχόμενο με τη δομή και προς τις δύο κατευθύνσεις. Στην πλευρά περιεχομένου, ένα τμήμα του content stream της σελίδας τυλίγεται σε τελεστές BDC και EMC που κουβαλάν αριθμό /MCID μοναδικό μέσα σε εκείνη τη σελίδα. Στην πλευρά δομής, το λεξικό σελίδας κουβαλά κλειδί /StructParents που ονομάζει μια γραμμή του /ParentTree του εγγράφου, και εκείνη η γραμμή είναι πίνακας του οποίου το στοιχείο στον δείκτη n είναι το στοιχείο δομής που κατέχει το MCID n

Μια σελίδα φύλλου περιέχει κελιά πίνακα και, πλέον, figures. Αν ο ετικετοποιητής κελιών μετρά τα αναγνωριστικά του από το μηδέν και ο ετικετοποιητής figures μετρά επίσης από το μηδέν, το πρώτο figure διεκδικεί τη θέση που κατέχει ήδη το πρώτο κελί. Τίποτα στο προκύπτον αρχείο δεν είναι παραμορφωμένο αρκετά ώστε να το απορρίψει parser: το δέντρο δομής είναι άθικτο, το marked content είναι ισορροπημένο, και ένας validator βλέπει έγγραφο με parent tree. Αυτό που παίρνει ένας screen reader είναι κελί πίνακα που ανακοινώνεται ως εικόνα, ή εικόνα που ανακοινώνεται με το κείμενο ενός κελιού. Ο εξαγωγέας δεσμεύει επομένως από έναν μετρητή επιπέδου σελίδας κοινό και στους δύο ετικετοποιητές, και παγώνει την εγγραφή σελίδας μόνο όταν είναι γνωστός ο αριθμός object της σελίδας, αφού η γραμμή parent-tree δεν μπορεί να γραφτεί πριν η σελίδα στην οποία αναφέρεται αποκτήσει ταυτότητα

Ανεξάρτητοι ετικετοποιητές κελιών και figures συγκρούονται στη θέση μηδέν του parent tree· ένας μετρητής MCID επιπέδου σελίδας κρατά κάθε σημείο αντιστοιχισμένο σε έναν κάτοχο
Το συγκρουόμενο αρχείο εξακολουθεί να περνά δομικό validator· μόνο η ανακοίνωση του screen reader είναι λάθος

Το Figure πρέπει να τυλίγει όλη την ορατή εμφάνιση

Η αφελής τοποθέτηση είναι να τυλιχτεί ο τελεστής Do που καλεί το image XObject, αφού εκείνος είναι ο τελεστής που ζωγραφίζει την εικόνα. Δεν φτάνει. Μια εικόνα φύλλου συχνά ζωγραφίζεται με σκιά πίσω της και διαδρομή αποκοπής γύρω της, και εκείνα τα σημεία είναι μέρος του ορατού object. Αφεμένα έξω από το εύρος /Figure γίνονται μη σημασμένο περιεχόμενο, που είναι ακριβώς η κατάσταση που επισημαίνει ένας έλεγχος δομής

Έτσι το εύρος marked-content ανοίγει πριν τη σκιά και κλείνει μετά τη ζωγραφική της εικόνας, καλύπτοντας και την αποκοπή. Ο διαμοιρασμός διατηρείται εκεί όπου ο διαμοιρασμός είναι σωστός: δύο κελιά που δείχνουν το ίδιο payload εικόνας εξακολουθούν να αναφέρονται σε ένα image XObject, επειδή εκείνο είναι βελτιστοποίηση επιπέδου πόρων και δεν έχει καμία σχέση με σημασιολογία. Αυτό που παίρνει κάθε ορατή εμφάνιση είναι το δικό της MCID και το δικό της στοιχείο δομής, επειδή δύο εμφανίσεις του ίδιου λογοτύπου σε διαφορετικά σημεία είναι δύο πράγματα που συναντά ένας αναγνώστης. Η τοποθέτηση εικόνων και η γεωμετρία EMU που τοποθετεί αυτά τα objects καλύπτεται στο άρθρο για τη γεωμετρία εικόνων

Το σημείο BDC ανοίγει το εύρος Figure πριν σκιά και αποκοπή και το EMC κλείνει μετά τη ζωγραφική Do της εικόνας, καλύπτοντας όλη την ορατή εμφάνιση
Το τύλιγμα μόνο του τελεστή εικόνας θα άφηνε σκιά και αποκοπή ως μη σημασμένο περιεχόμενο· ο διαμοιρασμός πόρων ανάμεσα σε κελιά διατηρείται

Σειρά ανάγνωσης σε σελίδα φύλλου

Η σειρά ανάγνωσης είναι απόφαση που πρέπει να πάει ο εξαγωγέας, επειδή ένα λογιστικό φύλλο δεν έχει συγγραφμένη ροή όπως ένα έγγραφο. Ο κανόνας που υιοθετήθηκε είναι σταθερός και εύκολος να εξηγηθεί: για κάθε σελίδα, πρώτα ο πίνακας, μετά τα figures σε σειρά ζωγραφικής. Ένας αναγνώστης ακούει λοιπόν το περιεχόμενο πίνακα της σελίδας και μετά τις εικόνες της, αντί να έχει εικόνες πλεκτές σε όποια θέση τυχαία κατείχαν τα objects σχεδίου στο αρχείο

Εκείνη η σειρά είναι ανά σελίδα και όχι ανά έγγραφο, που έχει σημασία σε ένα βιβλίο εργασίας που σελιδοποιείται σε δεκάδες σελίδες: ο κλάδος δομής κάθε σελίδας είναι αυτοτελής, οπότε ένας αναγνώστης που μετακινείται ανάμεσα σε σελίδες δεν πηδά πίσω σε προηγούμενο πίνακα. Αν χρειάζεστε έλεγχο του πώς σελιδοποιείται το φύλλο εξαρχής, η αλληλεπίδραση διαμόρφωσης σελίδας και περιοχής εκτύπωσης περιγράφεται στο άρθρο για την προστασία και τη διαμόρφωση σελίδας

Τι πιστοποιεί αυτό, και τι δεν πιστοποιεί

Πιστοποιεί ότι οι πληροφοριακές εικόνες φτάνουν στην υποβοηθούμενη τεχνολογία με την περιγραφή που παρείχε ο συγγραφέας τους, και ότι η αντιστοίχιση περιεχομένου-δομής είναι σωστή και όχι απλώς παρούσα. Δεν κάνει την έξοδο συμμορφούμενη PDF/UA, και η περιγραφή της έτσι θα ήταν ισχυρισμός που η υλοποίηση δεν μπορεί να στηρίξει: τα διαγράμματα εξακολουθούν να είναι artifacts, και μια πλήρης δήλωση συμμόρφωσης απαιτεί έλεγχο κάθε τύπου δομής, κάθε γραμματοσειράς, και των metadata του εγγράφου ως συνόλου

Αν η απαίτησή σας είναι προφίλ αρχειοθέτησης ή συμμόρφωσης και όχι βελτίωση προσβασιμότητας, αυτή είναι διαφορετική διαμόρφωση εξαγωγής και διαφορετικό σύνολο ελέγχων, που περιγράφεται στο άρθρο για την αρχειακή εξαγωγή PDF/A. Τα δύο συνδυάζονται, αλλά απαντούν σε διαφορετικούς ελεγκτές

Μια πρακτική πρόταση για αγωγό αναφορών: ελέγξτε το εναλλακτικό κείμενο στο σημείο που παράγεται το βιβλίο εργασίας, όχι τη στιγμή της εξαγωγής. Η γεννήτρια ξέρει τι αντιπροσωπεύει κάθε εικόνα διαγράμματος ή ενσωματωμένο διάγραμμα, και μπορεί να γράψει πραγματική περιγραφή στο AltText· ένα πέρασμα στιγμής εξαγωγής μπορεί μόνο να σας πει ότι λείπει μια περιγραφή. Το HotXLS διαβάζει και γράφει XLS, XLSX, ODS και CSV εγγενώς από Delphi και C++Builder χωρίς εξάρτηση Excel, και οι επιλογές διαμόρφωσης εξαγωγής του καταγράφονται στη σελίδα προϊόντος HotXLS Delphi spreadsheet component