Техническа статия

Tagged PDF фигури от Excel изображения с HotXLS

Когато HotXLS експортира работен лист към PDF с автоматично етикетиране включено, картини на работен лист, които носят алтернативен текст, вече излъчват като независими /Figure структурни елементи с Unicode /Alt запис, плътни странично-локални marked-content идентификатори и точни parent-tree записи; Картини без алтернативен текст остават декоративни артефакти и графиките остават артефакти също; Този прецизен обхват има значение: той прави информативните изображения достигаеми за screen reader и не е същото като пълна PDF/UA съответност

Механизмите зад него са по-интересни от описанието на функцията, защото две от тях са от рода детайли, които мълшиво произвеждат структурно валиден PDF, чиято структура сочи към грешното съдържание

Какво се брои като информативно изображение?

Само непразен AltText; Свойството TXLSXImage.AltText round-trip-ва OOXML атрибута descr на не-визуалните свойства на картината, което е мястото, където Excel съхранява текста, който потребител въвежда в alt-text прозореца; Това е единственият сигнал във файла, че авторът е смятал картината за носеща информация, а не декорация, така че това е единственият сигнал, на който exporter-ът вярва

Две близки до целта варианти са нарочно неприети; Полето заглавие, съхранявано отделно от описанието, не е заместител: заглавие е име за обекта, не текстов еквивалент на него и издигането му в /Alt би произвело документ, който минава автоматична проверка, докато обявява „Картина 3“ на screen reader; Празно описание също не е дупка за запълване с placeholder; то означава изображението остава артефакт, което е правилният изход за лого или разделителна линия; Графиките също остават артефакти засега, защото текстовият еквивалент на графика са нейните данни и синтезирането на такъв от сериите би било измислица, а не извличане

Картини с непразен AltText експортират като PDF Figure структурни елементи със собствен MCID; празни описания и графики остават артефакти
Само авторското описание в AltText сигнализира информативно изображение; заглавие само по себе си никога не става 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];

    // Одит преди експорт: изображение без описание ще бъде
    // експортирано като декоративен артефакт
    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 идентификатор и два разпределителя произвеждат два записа, претендиращи един и същ слот; Tagged PDF свързва съдържанието със структурата в двете посоки; От страната на съдържанието отсечка от content потока на страницата е обвита в операторите BDC и EMC, носещи /MCID число, уникално в тази страница; От страната на структурата речникът на страницата носи ключ /StructParents, назоваващ ред на документа /ParentTree и този ред е масив, чийто елемент на индекс n е структурният елемент, притежаващ MCID n

Страница от работен лист съдържа клетки на таблица и, сега, фигури; Ако cell tagger-ът брои своите идентификатори от нула и figure tagger-ът също брои от нула, първата фигура претендира слота, който първата клетка вече притежава; Нищо в получения файл не е недобре оформено достатъчно за парсер да го отхвърли: дървото на структурата е непокътнато, marked content-ът е балансиран и валидатор вижда документ с parent tree; Това, което screen reader получава, е клетка от таблица, обявена като изображение, или изображение, обявено с текста на клетка; Exporter-ът следователно разпределя от един странично-ниво брояч, споделен от двата tagger-а и замразява страницата запис само веднъж, когато номерът на обекта на страницата е известен, тъй като parent-tree редът не може да бъде записан, преди страницата, към която се отнася, да има идентичност

Независими cell и figure tagger-и се сблъскват върху parent tree слот нула; един странично-ниво MCID брояч държи всяка марка съпоставена на един собственик
Сблъскващият се файл все още минава структурен валидатор; само обявяването на screen reader е грешно

Figure-ът трябва да обгръща цялата видима инстанция

Наивното разположение е да се обгради операторът Do, който извиква image XObject-а, тъй като това е операторът, който рисува картината; Това не е достатъчно; Картина на работен лист често се рисува със сянка зад нея и клипиращ път около нея и тези марки са част от видимия обект; Оставени извън обхвата /Figure те стават немаркирано съдържание, което е точно състоянието, което структурен аудит маркира

Така marked-content обхватът се отваря преди сянката и се затваря след рисуването на изображението, покривайки и клипа; Споделянето се запазва там, където споделянето е правилно: две клетки, показващи един и същ picture payload, все още реферират един image XObject, защото това е ресурсно-ниво оптимизация и няма нищо общо със семантиката; Това, което всяка видима инстанция получава, е собствен MCID и собствен структурен елемент, защото две срещания на едно и също лого на различни места са две неща, които четец среща; Поставянето на изображения и EMU геометрията, която позиционира тези обекти, е разгледано в статията за image геометрия

Марката BDC отваря Figure обхвата преди сянка и клип, а EMC затваря след рисуването на изображението Do, покривайки цялата видима инстанция
Обгръщането само на image оператора би оставило сянка и клип като немаркирано съдържание; ресурсното споделяне между клетки се запазва

Ред на четене на страница от работен лист

Редът на четене е решение, което exporter-ът трябва да вземе, защото електронна таблица няма авторски поток по начина, по който документ има; Приетото правило е стабилно и лесно за обяснение: за всяка страница таблицата идва първа, после фигурите в ред на рисуване; Четец следователно чува табличното съдържание на страницата и после неговите изображения, вместо изображенията да са преплетени на каквато и да е позиция, на която drawing обектите случайно са заемали във файла

Този ред е за страница, а не за документ, което има значение върху работна книга, която пагинира в десетки страници: структурният клон на всяка страница е самостоятелен, така че четец, движещ се между страници, не прескача обратно в по-ранна таблица; Ако се нуждаете от контрол върху това как листът пагинира изобщо, взаимодействието page-setup и print-area е описано в статията за защита и page setup

Какво това сертифицира и какво не

То сертифицира, че информативни картини достигат assistive технология с тяхното предоставено от автора описание и че съпоставянето съдържание-към-структура е правилно, а не просто налично; То не прави изхода PDF/UA съответстващ и описването му по този начин би било твърдение, което имплементацията не може да подкрепи: графиките все още са артефакти и пълно съответстващо твърдение изисква одит на всеки структурен тип, всеки шрифт и метаданните на документа като цяло

Ако вашето изискване е архивен или съответстващ профил, а не подобрение на достъпността, това е различна export конфигурация и различен набор от проверки, описани в статията за PDF/A архивен export; Двете се съчетават, но отговарят на различни одитори

Едно практично предложение за конвейер за отчети: одитирайте алтернативния текст в момента, в който работната книга се генерира, а не по време на export; Генераторът знае какво представлява всяко изображение на графика или вградена диаграма и може да напише истинско описание в AltText; проход по време на export може само да ви каже, че описание липсва; HotXLS чете и записва XLS, XLSX, ODS и CSV нативно от Delphi и C++Builder без Excel зависимост и неговите опции за export конфигурация са изброени на продуктовата страница HotXLS Delphi spreadsheet component