כש-HotXLS מייצא גיליון אל PDF עם תיוג אוטומטי מופעל, תמונות גיליון שנושאות טקסט חלופי פולטות עכשיו כאלמנטי מבנה /Figure עצמאיים עם ערך /Alt של Unicode, מזהי marked-content צפופים מקומיים לעמוד ורשומות עץ-הורה מדויקות. תמונות בלי טקסט חלופי נשארות artifacts דקורטיביים, ותרשימים נשארים artifacts גם הם. היקף מדויק זה חשוב: הוא הופך תמונות אינפורמטיביות לנגישות לקורא מסך, והוא אינו אותו דבר כהתאמה מלאה ל-PDF/UA
המכניקה שמאחורי זה מעניינת יותר מתיאור התכונה, כי שתיים מהן הן מהסוג של פרט שמפיק בשקט PDF תקין מבחינה מבנית שהמבנה שלו מצביע על התוכן השגוי
מה נחשב תמונה אינפורמטיבית?
רק AltText לא ריק. התכונה TXLSXImage.AltText שומרת round-trip על התכונה descr של ה-OOXML של תכונות ה-non-visual של התמונה, שם Excel מאחסן את הטקסט שמשתמש מקליד בחלונית ה-alt-text. זהו האות היחיד בקובץ שהמחבר ראה בתמונה נושאת מידע ולא קישוט, ולכן הוא האות היחיד שהמייצא סומך עליו
שני כמעט-התאמות נדחות בכוונה. שדה הכותרת, המאוחסן בנפרד מהתיאור, אינו תחליף: כותרת היא שם עבור ה-object, לא שקול טקסטואלי שלו, וקידומו אל /Alt היה מפיק מסמך שעובר בדיקה אוטומטית בזמן שהוא מכריז "Picture 3" לקורא מסך. תיאור ריק אינו גם פער למלא עם placeholder; הוא אומר שהתמונה נשארת artifact, מה שהוא התוצאה הנכונה עבור לוגו או קו מפריד. תרשימים נשארים artifacts לבינתיים גם כן, כי השקול הטקסטואלי של תרשים הוא הנתונים שלו וסינתזה שלו מהסדרות הייתה המצאה ולא חילוץ
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 יחיד?
כי עץ ההורים הוא מערך שממופתח לפי מזהה marked-content, ושני מקצים מפיקים שתי רשומות שתובעות את אותו משבצת. PDF מתויג מחבר תוכן אל מבנה בשני הכיוונים. בצד התוכן, טווח מ-stream התוכן של העמוד נעטף באופרטורי BDC ו-EMC שנושאים מספר /MCID ייחודי בתוך אותו עמוד. בצד המבנה, מילון העמוד נושא מפתח /StructParents שקורא בשם שורה של /ParentTree של המסמך, ואותה שורה היא מערך שהאיבר שלו באינדקס n הוא אלמנט המבנה הבעלים של MCID n
עמוד גיליון מכיל תאי טבלה וכעת גם figures. אם מתייג התאים סופר את המזהים שלו מאפס ומתייג ה-figures סופר גם הוא מאפס, ה-figure הראשון תובע את המשבצת שהתא הראשון כבר בבעלותו. שום דבר בקובץ המתקבל אינו פגום מספיק כדי שמנתח ידחה אותו: עץ המבנה תקין, ה-marked content מאוזן, ומאמת רואה מסמך עם עץ הורים. מה שקורא מסך מקבל הוא תא טבלה שמוכרז כתמונה, או תמונה שמוכרזת עם הטקסט של תא. המייצא לכן מקצה ממונה אחד ברמת העמוד ששני המתייגים חולקים, ומקפיא את רשומת העמוד רק ברגע שמספר ה-object של העמוד ידוע, כי את שורת עץ-ההורים לא ניתן לכתוב לפני שלעמוד שהיא מפנה אליו יש זהות
ה-Figure חייב לעטוף את כל המופע הנראה
המיקום הנאיבי הוא לעטוף את האופרטור Do שמפעיל את XObject התמונה, שכן זה האופרטור שמצייר את התמונה. זה לא מספיק. תמונת גיליון לעיתים קרובות מצוירת עם צל מאחוריה ונתיב חיתוך סביבה, והסימנים האלה חלק מה-object הנראה. מושארים מחוץ לתחום ה-/Figure הם הופכים לתוכן לא מסומן, שהוא בדיוק המצב שביקורת מבנה מסמנת
לכן תחום ה-marked-content נפתח לפני הצל ונסגר אחרי ציור התמונה, ומכסה גם את החיתוך. שיתוף נשמר היכן ששיתוף נכון: שני תאים שמציגים את אותו payload של תמונה עדיין מפנים ל-XObject אחד של התמונה, כי זו אופטימיזציה ברמת משאבים ואין לה שום קשר לסמנטיקה. מה שכל מופע נראה מקבל הוא MCID משלו ואלמנט מבנה משלו, כי שני מופעים של אותו לוגו במקומות שונים הם שני דברים שקורא פוגש. מיקום תמונות והגאומטריה של ה-EMU שממקמת את ה-objects האלה מכוסים במאמר גאומטריית התמונות
סדר קריאה בעמוד גיליון
סדר קריאה היא החלטה שהמייצא חייב לקבל, כי לגיליון נתונים אין זרימה מחוברת כפי שיש למסמך. הכלל המאומץ יציב וקל להסבר: עבור כל עמוד, הטבלה באה קודם, ואז figures בסדר הציור. קורא לכן שומע את התוכן הטבלאי של העמוד ואז את התמונות שלו, במקום תמונות ששזורות באיזו עמדה שמות ה-objects לציור תפסו במקרה בקובץ
הסדר הזה הוא לכל עמוד ולא לכל מסמך, מה שחשוב בחוברת שמדופדפת לעשרות עמודים: הענף המבני של כל עמוד עצמאי, כך שקורא שעובר בין עמודים לא קופץ חזרה אל טבלה מוקדמת. אם אתם צריכים שליטה על אופן הדפדוף של הגיליון מלכתחילה, התקשרות בין הגדרות עמוד ואזור הדפסה מתוארת במאמר ההגנה והגדרות העמוד
מה זה מאשר, ומה לא
הוא מאשר שתמונות אינפורמטיביות מגיעות אל טכנולוגיה מסייעת עם התיאור שסיפק המחבר, ושהמיפוי מתוכן אל מבנה נכון ולא רק קיים. הוא אינו הופך את הפלט לתואם PDF/UA, ותיאורו כך היה טענה שהמימוש אינו יכול לתמוך בה: תרשימים עדיין artifacts, והצהרת התאמה מלאה דורשת ביקורת של כל סוג מבנה, כל גופן, ומטא-הנתונים של המסמך כולו
אם הדרישה שלכם היא פרופיל ארכיון או התאמה ולא שיפור נגישות, זו תצורת ייצוא אחרת וקבוצת בדיקות אחרת, המתוארות במאמר ייצוא ארכיוני PDF/A. השניים משולבים, אבל הם עונים למבקרים שונים
הצעה מעשית אחת לצינורית דוחות: בקרו טקסט חלופי בנקודה שבה החוברת נוצרת, ולא בזמן הייצוא. המחולל יודע מה כל תמונת תרשים או תרשים מוטמע מייצג, ויכול לכתוב תיאור אמיתי אל AltText; מעבר בזמן ייצוא יכול רק לומר לכם שתיאור חסר. HotXLS קורא וכותב XLS, XLSX, ODS ו-CSV באופן מקורי מ-Delphi ו-C++Builder בלי תלות ב-Excel, ואפשרויות תצורת הייצוא שלו מופיעות בדף המוצר של HotXLS Delphi spreadsheet component