Коли HotXLS експортує аркуш у PDF з увімкненим автоматичним тегуванням, картинки аркуша, що несуть альтернативний текст, тепер виводяться як незалежні структурні елементи /Figure із записом Unicode /Alt, щільними локальними для сторінки ідентифікаторами позначеного вмісту та точними записами батьківського дерева. Картинки без альтернативного тексту лишаються декоративними артефактами, і діаграми також лишаються артефактами. Та точна сфера має значення: вона робить інформативні зображення досяжними для читача з екрана, і це не те саме, що повна відповідність PDF/UA
Механіка за цим цікавіша за опис можливості, бо дві з них — це той сорт деталей, що мовчки творить структурно чинний PDF, чия структура вказує на неправильний вміст
Що рахується інформативним зображенням?
Лише непорожній AltText. Властивість TXLSXImage.AltText проводить туди й назад атрибут descr OOXML з невізуальних властивостей картинки, — саме там Excel зберігає текст, який користувач набирає в панелі альтернативного тексту. Це єдиний сигнал у файлі, що автор вважав картину носієм інформації, а не прикраси, тож це єдиний сигнал, якому довіряє експортер
Дві майже-влучання свідомо не приймаються. Поле назви, що зберігається окремо від опису, — не заміна: назва — це ім'я об'єкта, а не текстовий еквівалент його, і просування її в /Alt дало б документ, що проходить автоматичну перевірку, оголошуючи «Picture 3» читачеві з екрана. Порожній опис — також не прогалина, яку заповнити заповнювачем; він означає, що зображення лишається артефактом, що і є правильний результат для логотипа чи розділювальної лінійки. Діаграми також лишаються артефактами поки що, бо текстовий еквівалент діаграми — її дані, і синтезувати один із серій — винахід, а не витяг
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?
Бо батьківське дерево — масив, індексований ідентифікатором позначеного вмісту, і два розподільники творять два записи, що заявляють одну саму комірку. Тегований PDF з'єднує вміст зі структурою в обидва боки. Зі сторони вмісту ділянка потоку вмісту сторінки огортається операторами BDC та EMC з номером /MCID, унікальним у межах тієї сторінки. Зі сторони структури словник сторінки несе ключ /StructParents, що називає рядок документа /ParentTree, і той рядок — масив, чий елемент за індексом n — структурний елемент, що володіє MCID n
Сторінка аркуша містить клітинки таблиці і, тепер, фігури. Якщо тегувальник клітинок рахує свої ідентифікатори від нуля і тегувальник фігур також рахує від нуля, перша фігура заявляє комірку, якою вже володіє перша клітинка. Ніщо в отриманому файлі не настільки спотворене, щоб парсер відкинув: дерево структури ціле, позначений вміст збалансований, і валідатор бачить документ з батьківським деревом. А читач з екрана отримує клітинку таблиці, оголошену як зображення, або зображення, оголошене текстом клітинки. Експортер тому розподіляє з одного лічильника рівня сторінки, спільного для обох тегувальників, і заморожує запис сторінки лише тоді, коли номер об'єкта сторінки відомий, бо рядок батьківського дерева не можна записати до того, як сторінка, на яку він вказує, має ідентичність
Фігура мусить огортати весь видимий примірник
Наївне розміщення — огорнути оператор Do, що викликає зображення XObject, бо саме той оператор малює картину. Цього недостатньо. Картинку аркуша часто малюють з тінню позаду та шляхом відсікання навколо, і ті позначки — частина видимого об'єкта. Залишені поза сферою /Figure, вони стають непозначеним вмістом — точно той стан, який прапорить аудит структури
Тож сфера позначеного вмісту відкривається до тіні і закривається після малювання зображення, покриваючи також відсікання. Поширення зберігається там, де поширення правильне: дві клітинки, що показують те саме навантаження картинки, досі посилаються на одне зображення XObject, бо це оптимізація рівня ресурсів і не має нічого спільного з семантикою. Кожен видимий примірник отримує власний MCID і власний структурний елемент, бо два входження того самого логотипа в різних місцях — дві речі, з якими стикається читач. Розміщення зображень і геометрія EMU, що позиціонує ці об'єкти, охоплені в статті про геометрію зображень
Порядок читання на сторінці аркуша
Порядок читання — рішення, яке має прийняти експортер, бо електронна таблиця не має авторського потоку, як документ. Прийняте правило стабільне і легке для пояснення: для кожної сторінки спершу таблиця, потім фігури в порядку малювання. Читач тому чує табличний вміст сторінки, а потім її зображення, замість того щоб мати зображення, переплетені на тих позиціях, які випадково зайняли об'єкти малювання в файлі
Той порядок на сторінку, а не на документ, що має значення на книзі, яка розбивається на десятки сторінок: структурна гілка кожної сторінки самодостатня, тож читач, що рухається між сторінками, не стрибає назад у попередню таблицю. Якщо вам потрібен контроль над тим, як аркуш розбивається на сторінки в першу чергу, взаємодія налаштування сторінки та області друку описана в статті про захист і налаштування сторінки
Що це сертифікує, а що ні
Воно сертифікує, що інформативні картинки досягають асистивної технології з авторським описом, і що відображення вмісту в структуру правильне, а не просто присутнє. Воно не робить результат відповідним PDF/UA, і описувати його так означало б заяву, якої реалізація не може підтримати: діаграми досі артефакти, а повна заява відповідності вимагає аудиту кожного типу структури, кожного шрифта та метаданих документа в цілому
Якщо ваша вимога — архівний чи відповідний профіль, а не покращення доступності, це інша конфігурація експорту та інший набір перевірок, описаний у статті про архівний експорт PDF/A. Обидва поєднуються, але відповідають різним аудиторам
Одна практична порада для звітного конвеєра: аудіруйте альтернативний текст у точці, де книга генерується, а не в момент експорту. Генератор знає, що зображує кожна картинка діаграми чи вбудована схема, і може записати справжній опис у AltText; прохід у момент експорту може лише сказати, що опис відсутній. HotXLS читає та пише XLS, XLSX, ODS і CSV власними засобами з Delphi та C++Builder без залежності від Excel, а його опції конфігурації експорту наведені на сторінці продукту HotXLS Delphi spreadsheet component