مقال تقني

كتابة ملفات XLSX بصيغة ISO 29500 الصارمة من Delphi

يكتب HotXLS مصنّفات Open XML بصيغة ISO/IEC 29500 الصارمة من Delphi وC++Builder بضبط خاصية واحدة، StrictOOXML، قبل الحفظ. ويُكتب كل جزء في الحزمة، من xl/workbook.xml وصولًا إلى ملفات العلاقات وأنواع المحتوى، بمفردات purl.oclc.org الصارمة بدلًا من مفردات schemas.openxmlformats.org الانتقالية، وتُرفَض الميزات التي لا تسمح بها الصيغة الصارمة برفع استثناء صريح بدلًا من كتابتها رغم ذلك

ويصادف معظم المطورين هذا المتطلب عبر وثيقة مشتريات. فالمناقصات الحكومية في عدة ولايات قضائية تطلب الصيغة المعيارية لـ Open XML وفق ISO، لا الصيغة الانتقالية التي تكتبها Office افتراضيًا، وأي أرشيف يُلزِم بصيغة ISO 29500 الصارمة سيرفض ملف .xlsx عاديًا حتى وإن كان Excel يفتحه بشكل مثالي. وتوجد مساحات الأسماء الانتقالية لاستيعاب سلوك الملفات الثنائية القديمة؛ أما الصارمة فهي المعيار نفسه

ما الذي يختلف فعليًا بين الصيغة الصارمة والانتقالية؟

الفرق المرئي هو المفردات. فجزء المصنّف الصارم يُعلن http://purl.oclc.org/ooxml/spreadsheetml/main كمساحة أسماء جذرية، وhttp://purl.oclc.org/ooxml/officeDocument/relationships لمراجع العلاقات، ولا يجوز أن تبقى أي مساحة أسماء انتقالية في أي مكان في الحزمة. وتتغيّر أنواع العلاقات معها، بحيث يُسمّى جزء العلاقات الجذري .../ooxml/officeDocument/relationships/officeDocument بدلًا من المكافئ المألوف بصيغة openxmlformats، ويُكتب نوع الخصائص الموسَّعة بصيغة camelCase كـ extendedProperties

أما الفرق غير المرئي فهو النطاق. إذ تُسقِط الصيغة الصارمة عمدًا أجزاء من المخطط الانتقالي كانت موجودة فقط لدعم التحويل ذهابًا وإيابًا للملفات الثنائية القديمة، إلى جانب امتدادات المزوّد التي أضافتها Office لاحقًا. وهذا هو سبب كون التحويل ليس بحثًا واستبدالًا للسلاسل النصية: فبعض الميزات ببساطة لا تملك صيغة صارمة مكافئة، ويجب ألا تُكتب على الإطلاق

تفعيلها

لا يتغيّر كود التأليف الاعتيادي. ابنِ المصنّف بالطريقة المعتادة، واضبط العلم، واحفظ:

var
  Wb: TXLSXWorkbook;
  Sh: TXLSXWorksheet;
begin
  Wb := TXLSXWorkbook.Create;
  try
    Sh := Wb.Sheets.Add('Data');
    Sh.Cells[1, 1].Value := 'Product';
    Sh.Cells[1, 2].Value := 'Amount';
    Sh.Cells[2, 1].Value := 'Widget';
    Sh.Cells[2, 2].Value := 17;
    Sh.Cells[3, 2].Formula := '=SUM(B2:B2)';

    Wb.StrictOOXML := True;          // مخرجات ISO/IEC 29500 الصارمة
    if Wb.SaveAs('archive-copy.xlsx') <> 1 then
      raise Exception.Create('strict save failed');
  finally
    Wb.Free;
  end;
end;

يُعاد ضبط العلم في بداية كل عملية حفظ ويُعاد تعيينه من خاصية المصنّف، بحيث لا يستطيع استثناء أثناء عملية حفظ واحدة تسريب الوضع الصارم إلى العملية التالية. وهذا التفصيل مهم في عمليات الخادم حيث يخدم كائن مصنّف واحد عدة طلبات تصدير

لماذا قد يرفض الحفظ الصارم التنفيذ؟

أربع عائلات من الميزات هي امتدادات من Microsoft لا مكافئ لها في ISO 29500 الصارمة، ويرفع HotXLS استثناءً عند الحفظ بدلًا من إصدار حزمة تدّعي مطابقة صارمة وهي ليست كذلك:

// لا يستطيع الإخراج الصارم تضمين مشروع VBA
//   -> احفظ المصنّفات المُمكَّن فيها الماكرو كـ .xlsm انتقالية
// لا يستطيع الإخراج الصارم حمل عناصر تحكم النماذج
//   -> الأزرار، ومربعات الاختيار، والقوائم المنسدلة وخصائص ctrlProps الخاصة بها
// لا يستطيع الإخراج الصارم حمل التعليقات المترابطة
//   -> نموذج persons/threads الحديث، لا الملاحظات الكلاسيكية
// لا يستطيع الإخراج الصارم حمل بيانات وصفية للمصفوفات الديناميكية
//   -> نطاقات الانسكاب المسجَّلة عبر جزء البيانات الوصفية

والفشل بصوت عالٍ هو المقايضة الصحيحة هنا. فمشروع VBA يُسقَط بصمت يحوّل مصنّفًا يعمل إلى مصنّف معطوب لا يزال يُفتَح، ويصل تقرير الفشل من مستخدم بعد أسابيع. أما الاستثناء فيسمّي الميزة والخاصية الواجب تغييرها بينما لا يزال الكود المستدعي يعرف ما كان يُصدّره. ويُغطّى الحفاظ على الماكرو والروابط الخارجية على المسار الانتقالي في الحفاظ على مشاريع VBA والروابط الخارجية

وثمة عائلتا امتدادات تُعامَلان بشكل مختلف، ويستحق الأمر معرفة السبب. فأشرطة البيانات، والرسوم البيانية المصغّرة، والميزات المماثلة تقيم في مفردتَي x14 وxm، بينما تقيم صيغ SVG من الصور في c15. وهذه محتوى قائمة امتدادات مساحات أسمائها ذاتية الوصف، وتتسامح معها أدوات تحليل جداول البيانات العامة، ولا يوجد مكافئ ISO لترجمتها إليه. ويحتفظ HotXLS بها بدلًا من إسقاط محتوى المستخدم أرضًا. وإذا كانت أداة التحقق في خط أنابيبك صارمة بشأن الامتدادات وكذلك مساحات الأسماء، فأزل تلك الميزات من المصنّف المصدر قبل التصدير

الترجمة يجب أن تصل إلى أجزاء لا يعيد أحد كتابتها عادة

مشكلة الهندسة المثيرة للاهتمام في الإخراج الصارم ليست XML ورقة العمل. بل هي الأجزاء التي يفضّل الكاتب السريع نسخها حرفيًا. فيحافظ HotXLS على السمات، والاتصالات، والروابط الخارجية، والمخططات البيانية، وكتل PivotTable بنسخ بايتاتها المضغوطة الأصلية مباشرة، وهو الصواب تمامًا من حيث الدقة والخطأ تمامًا بالنسبة إلى الإخراج الصارم، لأن البايتات المنسوخة تحمل مساحات أسماء انتقالية

وتحت StrictOOXML، تتحول هذه المسارات الخمسة المحفوظة إلى إعادة بناء أو إلى إعادة تشغيل مُترجِمة، متجاوزة مسار النسخ السريع للبايتات. ويمر كل XML عبر إجراء ترجمة واحد، يرتكز على قيم السمات المحاطة بعلامات اقتباس مزدوجة بحيث لا يمكن أبدًا إعادة كتابة سلسلة نصية تبدو كعنوان URI داخل خلية عن طريق الخطأ. ويُهرَب نص الخلية الذي يحتوي على العنوان نفسه ككيان في XML، بحيث لا يستطيع الاستبدال المرتكز رؤيته. ويُترجم الكاتب المتدفق هيكله أولًا ثم يقسمه عند sheetData، لأن كتل الصفوف لا تحتوي على أي عناوين URI للمفردات إطلاقًا. وتُغطّى الآليات ذات الصلة بمسار الحفظ في التحويل ذهابًا وإيابًا بلا فقدان للسمات وقوائم الامتدادات وسلسلة الحساب calcChain

قراءة الملفات التي حفظها Excel بصيغة صارمة

الإخراج نصف القصة فقط. فيوفّر Excel خيار حفظ باسم "جدول بيانات Open XML الصارم"، ويجب أن تُفتَح الملفات المُنتَجة بهذه الطريقة بشكل صحيح. ويُوحِّد HotXLS أنواع العلاقات في كل موضع لتحليل العلاقات في الحزمة، أي الجذر، والروابط الخارجية، وأوراق العمل، والرسومات، وجداول PivotTable، بحيث يُطابِق نوع علاقة صارم الثابت الداخلي نفسه الذي يُطابقه نظيره الانتقالي

والمكافئ على جانب القراءة هو توحيد بادئات مساحات الأسماء، الذي يسمح لبادئات عشوائية ولكلتا المفردتين بالانحلال إلى جدول أسماء معياري واحد. ويفيد هذا العمل الملفات العادية والملفات الصارمة على حد سواء، إذ إن المولّدات الخارجية تربط البادئات بحرية، وهي الآلية نفسها الموصوفة في حل علاقات OPC في حزم XLSX

قائمة تحقق قصيرة قبل شحن الإخراج الصارم

تحقق باستخدام الحزمة، لا باستخدام Excel. فـ Excel يفتح كلا الصيغتين دون مشكلة، لذا لا يثبت الفتح الناجح شيئًا بشأن المطابقة. فُك ضغط النتيجة وتأكد من أن xl/workbook.xml يُعلن مساحة اسم purl، وأن ما من جزء يحتوي على schemas.openxmlformats.org/spreadsheetml، وأن أنواع العلاقات في _rels/.rels وxl/_rels/workbook.xml.rels تستخدم الصيغ الصارمة

ثم أعد فتح الملف عبر HotXLS وقارن القيم والصيغ والتنسيقات والروابط التشعبية بالمصدر. واختبار إعادة القراءة هو الطريقة الرخيصة الوحيدة لإثبات أن الترجمة لم تُتلف المحتوى، وهو يُشغِّل توحيد جانب القراءة في الوقت نفسه. وإذا كانت مصنّفاتك تحمل مخططات بيانية، فتحقق منها أيضًا، لأن جزء المخطط أحد الأجزاء المحفوظة التي تتحول إلى مسار مُعاد بناؤه في الوضع الصارم

والإخراج الصارم، والقراءة المتسامحة، والحفظ بلا فقدان كلها جزء من محرك OOXML نفسه لـ Delphi وC++Builder؛ وتوجد قائمة الميزات الكاملة على صفحة مكوّن HotXLS لجداول البيانات في Delphi