當 HotXLS 以啟用自動加標籤的方式把工作表匯出為 PDF,攜帶替代文字的工作表圖片現在會以獨立的 /Figure 結構元素發出,帶 Unicode /Alt 項、頁面局部的密集標記內容識別碼與精確的父樹項。沒有替代文字的圖片維持裝飾性 artifact,圖表也維持 artifact。這個精確範圍很重要:它讓有資訊的圖片可被螢幕閱讀器觸及,而它不等於完整的 PDF/UA 符合
它背後的機制比功能描述更有意思,因為其中兩個屬於那種會悄悄產出結構有效、結構卻指向錯誤內容的 PDF 的細節
什麼算有資訊的圖片?
只有非空的 AltText。TXLSXImage.AltText 屬性來回轉換圖片非視覺屬性中的 OOXML descr 屬性——正是 Excel 儲存使用者在替代文字窗格裡輸入之文字的地方。那是檔案中唯一的訊號,表明作者認為這張圖片承載資訊而非裝飾,所以它是匯出器唯一信任的訊號
兩個擦邊情況刻意不被接受。與描述分開儲存的標題欄位不是替代品:標題是物件的名稱,不是它的文字等價物,把它提升為 /Alt 會產出通過自動檢查、卻向螢幕閱讀器朗讀「Picture 3」的文件。空描述也不是要用佔位符填補的缺口;它意味著圖片維持 artifact,這對 logo 或分隔線是正確結果。圖表目前也維持 artifact,因為圖表的文字等價物是它的資料,從數列合成一段文字是發明而不是擷取
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 配置器?
因為父樹是以標記內容識別碼為索引的陣列,兩個配置器會產生兩個宣稱同一槽位的項目。加標籤 PDF 以雙向連接內容與結構。內容側,頁面內容串流的一段被攜帶頁內唯一 /MCID 號碼的 BDC 與 EMC 運算子包住。結構側,頁面字典攜帶 /StructParents 鍵,指名文件 /ParentTree 的一列,那一列是陣列,索引 n 處的元素是擁有 MCID n 的結構元素
一個工作表頁面包含表格儲存格,現在還有圖形。如果儲存格標籤器從零開始數識別碼,圖形標籤器也從零開始數,第一個圖形就會宣稱第一個儲存格已擁有的槽位。產出的檔案沒有任何地方畸形到會被剖析器拒絕:結構樹完好,標記內容平衡,驗證器看到的是一份有父樹的文件。螢幕閱讀器得到的,是被朗讀成圖片的表格儲存格,或帶著儲存格文字朗讀的圖片。因此匯出器從兩個標籤器共享的頁面層級計數器配置,並且只在頁面物件編號已知之後才凍結頁面記錄,因為父樹列在它指向的頁面取得身分之前無從寫起
Figure 必須包住整個可見實例
天真的做法是包住呼叫影像 XObject 的 Do 運算子,因為那正是畫出圖片的運算子。這不夠。工作表圖片往往帶著背後的陰影與周圍的剪裁路徑一起繪製,那些標記是可見物件的一部分。留在 /Figure 範圍之外,它們就成了未標記內容,正是結構稽核會標記的那種狀態
所以標記內容範圍在陰影之前開啟、在圖片繪製之後關閉,連剪裁一起涵蓋。在共享正確的地方保留共享:顯示同一圖片負載的兩個儲存格仍參照同一個影像 XObject,因為那是資源層級的最佳化,與語意無關。每個可見實例得到的是自己的 MCID 與自己的結構元素,因為同一 logo 出現在兩處,就是讀者遇到的兩個東西。圖片放置與定位這些物件的 EMU 幾何在圖片幾何文章中涵蓋
工作表頁面上的閱讀順序
閱讀順序是匯出器必須做的決定,因為試算表不像文件那樣有排好的流程。採用的規則穩定且容易解釋:每頁先表格,再按繪製順序排圖形。讀者因此先聽到頁面的表格內容、再聽到它的圖片,而不是圖片以繪圖物件碰巧在檔案中佔據的位置交錯出現
那個順序是按頁而不是按文件,這在會分頁成數十頁的活頁簿上很重要:每頁的結構分支自包含,在頁面之間移動的讀者不會跳回較早的表格。如果您需要控制工作表一開始怎麼分頁,頁面設定與列印範圍的互動在保護與頁面設定文章中描述
這認證什麼,不認證什麼
它認證的是:有資訊的圖片帶著作者提供的描述觸及輔助科技,而且內容到結構的對應是正確的,而不只是存在。它不讓輸出 PDF/UA 符合,那樣描述會是實作無法支撐的宣稱:圖表仍是 artifact,完整的符合性聲明需要稽核每一種結構型別、每一套字型,以及文件中繼資料整體
如果您的需求是歸檔或符合性設定檔而不是無障礙改善,那是另一種匯出設定與另一組檢查,見PDF/A 歸檔匯出文章。兩者可以結合,但它們回答的是不同的稽核者
給報表管線的一個實務建議:在活頁簿產生的地方稽核替代文字,而不是在匯出時。產生器知道每張圖表影像或內嵌圖示代表什麼,可以往 AltText 寫入真實描述;匯出時的檢查只能告訴您缺了描述。HotXLS 從 Delphi 與 C++Builder 原生讀寫 XLS、XLSX、ODS 與 CSV,不依賴 Excel,匯出設定選項列於 HotXLS Delphi spreadsheet component 產品頁