مقال تقني

تشغيل AutoFilters في Excel دون Excel داخل Delphi: HotXLS

تحسب HotXLS معايير AutoFilter المخزنة سلفاً في ملف XLSX دون تشغيل Excel. ومنذ v2.384.136 تنفذ TXLSXWorksheet.PreviewAutoFilterRows و ApplyAutoFilter و AutoFilterRowVisible قوائم القيم ومجموعات التواريخ ومرشحات Top/Bottom-n والنسبة، ومرشحات التواريخ النسبية والمتوسط، ومرشحات ألوان التعبئة والخط، ومرشحات أيقونات التنسيق الشرطي، تحت تاريخ مرجعي مثبت وحدود موارد معلنة

المُحفز المعتاد مصنف مرشحه شخص في Excel وخادم عليه أن يتصرف بناء عليه. يضبط أحدهم «Top 10 by revenue» و«This month» على تاريخ الطلب وتعبئة حمراء على الصفوف المتأخرة، يحفظ، ويرفع الملف. تحتاج خدمة Delphi عندك الآن مجموعة الصفوف التي ستعرضها Excel: لعدّها أو تصديرها أو كتابة الملف مرة أخرى بالصفوف الصحيحة مخفية. الملف يحمل التعريف فقط. قبل هذا الإصدار كانت HotXLS تحسب المعايير المخصصة العادية، لكن الأنواع المتقدمة جلست في XML المخزن بلا شيء ينفذها، فكان الجواب الأمين «افتحها في Excel»

ما تنفذه HotXLS فعلاً من AutoFilter محفوظ؟

تنفذ HotXLS نوع مرشح واحداً لكل عمود، مأخوذاً من عنصر filterColumn الذي كتبته Excel، وتجمع الأعمدة بـ AND، تماماً كقوائم Excel المنسدلة. العناصر قادمة من مجموعة AutoFilter في ECMA-376 Part 1 §18.3.2، وكل منها يقابل مسار حساب مميزاً:

ينبّه تنفيذ AutoFilter في HotXLS داخل Delphi كل عنصر filterColumn محفوظ إلى أحد خمسة مسارات حساب - filters و customFilters و top10 و dynamicFilter و colorFilter أو iconFilter - ويرفع EXLSXAutoFilterUnsupported لأي شيء آخر
تحسب HotXLS نوع مرشح واحداً لكل عمود من مجموعة AutoFilter في ECMA-376 Part 1 وتجمع الأعمدة بـ AND، فتطابق مجموعة الصفوف المرئية ما ستعرضه قوائم Excel المنسدلة
  • filters مع أبناء filter و dateGroupItem: قائمة قيم مؤشرة، ومدخل فارغ اختياري، ومجموعات تواريخ تقويمية من السنة نزولاً إلى الثانية، مضمومة بـ OR
  • customFilters: معيار مقارنة أو معياران يضمهما AND أو OR، المسار القائم سلفاً
  • top10: أعلى أو أسفل n عنصراً، أو n بالمئة، مع val محدودة بـ 1-500 عنصر أو 1-100 بالمئة
  • dynamicFilter: اليوم، وأمس، وغداً، والأسبوع/الشهر/الربع/السنة الحالي والسابق والتالي، والسنة حتى تاريخه، و M1-M12، و Q1-Q4، وفوق المتوسط ودونه
  • colorFilter و iconFilter: لون تعبئة أو خط فعلي يحل عبر النمط التفاضلي (differential style)، وأيقونات التنسيق الشرطي بمجموعة الأيقونات ومعرف الأيقونة الصفري

أي شيء خارج تلك القائمة يفشل بـ EXLSXAutoFilterUnsupported بدل إنتاج مجموعة صفوف مخمَّنة. في ذلك أنواع الانحراف المعياري فوق ودون من ST_DynamicFilterType، وقيم calendarType غير الميلادية، وعناصر امتداد مجهولة، ومراجع dxfId غير المحلولة، وعمود يحمل كيفما اتصل نوعي مرشح دفعة واحدة. محرك مرشح يعيد بهدوء صفوف «قريبة بما يكفي» أسوأ من محرك يرفض، لأن أحداً لا ينتبه حتى تصدر تقارير بعملاء مخطئين فيها

عايِن أولاً ثم طبّق

تقسم HotXLS العمل إلى معاينة قراءة فقط وتطبيق معاملاتي، وتأخذ كلتاهما سجل TXLSXAutoFilterExecutionOptions نفسه. تعيد PreviewAutoFilterRows عدد صفوف البيانات المطابقة ولا تمس ظهور الصفوف قط. تحضّر ApplyAutoFilter(AResetVisible, Options) كل قرار صف أولاً وعندها فقط تنشر مجموعة الصفوف المخفية الجديدة في خطوة واحدة، فاستثناء أثناء التحضير يترك الورقة كما هي تماماً

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Options: TXLSXAutoFilterExecutionOptions;
  Matching: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('orders-filtered-by-sales.xlsx');
    Sheet := Book.Sheets[1];   // مفهرس Sheets يبدأ من 1

    // ابدأ دائماً من الافتراضيات ثم غير حقولاً منفردة
    Options := XLSDefaultAutoFilterExecutionOptions;
    Options.ReferenceDate := EncodeDate(2026, 10, 19);

    Matching := Sheet.PreviewAutoFilterRows(nil, Options);  // العد فقط
    WriteLn('Rows Excel would show: ', Matching);

    // صحيح: تصبح الصفوف المطابقة مرئية حتى لو خفيت سلفاً
    Sheet.ApplyAutoFilter(True, Options);
    Book.SaveAs('orders-applied.xlsx');
  finally
    Book.Free;
  end;
end;

هيّئ السجل بـ XLSDefaultAutoFilterExecutionOptions في كل مرة. تملأ الدالة السجل بالأصفار ثم تضبط كل حد، ويرفض سياق التنفيذ سجلاً ليست كل حدوده موجبة بـ EXLSXAutoFilterLimit. سجل معلن على المكدس ومملوء حقلاً حقلاً سيحمل عادة قمامة أو أصفاراً في الحقول التي نسيتها. تستخدم الصيغ بلا وسائط‏ (ApplyAutoFilter(True) و PreviewAutoFilterRows(Callback) و AutoFilterRowVisible(Row)) الافتراضيات نفسها، بالتاريخ الحالي مرجعاً

يقرر علم AResetVisible ماذا يحدث للصفوف التي تجتاز المرشح وكانت مخفية سلفاً.‏ True تجعل كل صف مطابق مرئياً، وهو ما تفعله Excel عند إعادة التطبيق. و False يحفظ الإخفاء اليدوي السابق على الصفوف المطابقة ولا يضيف إخفاء إلا للصفوف الراسبة. تحفظ الصفوف خارج مدى AutoFilter حالتها في الحالتين. وإن تغير المصنف بين التحضير والنشر ترفع ApplyAutoFilter استثناء بدل نشر قرارات محسوبة من بيانات قديمة

لماذا تتجاهل قوائم القيم النجمة وعلامة الاستفهام؟

مدخلات قائمة القيم في عنصر filters رموز عرض حرفية، فتقارن HotXLS ‏* و ? بوصفهما محرفين عاديين. مدخل مؤشر A* في القائمة المنسدلة يعني أن الخلية تعرض A* تماماً لا «يبدأ بـ A». أما محارف البدل فلـ customFilters، حيث إن «يبدأ بـ» و«يحتوي» أنماط فعلاً، وتحتفظ تلك بالقواعد المنفصلة المغطاة في كيفية مطابقة HotXLS لمعايير محارف البدل في Excel وتهريب المدّة. وخلط الدلالتين أسرع طريق لتصفية عمود أرقام قطع إلى هراء

المقارنة على القيمة المعروضة، ما يثير سؤال أي عرض. تنسق HotXLS الخلية بصيغة العدد الأساسية لها، بما في ذلك الطبقات النمطية المخزنة، وتتجاهل عمداً صيغة عدد يطبقها التنسيق الشرطي فوقها. وتظهر ضوابط Excel الأصلية في تجهيزة HotXLS لماذا يهم الرمز: العدد 1 والنص «1» كلاهما يطابق اختيار 1، والعدد 1 المنسق بـ 0.0 يطابق بدلاً من ذلك 1.0 مع النص «1.0»، ويبقى النص «01» مميزاً عن كليهما. ولا يُحل النص الشبيه بتاريخ أبداً إلى تاريخ، فخلية نص تحمل «2026-10-19» لن تقع في مجموعة تواريخ

كيف تقرر مرشحات Top 10 والمتوسط والتواريخ الديناميكية؟

تحسب HotXLS عتبات الترتيب والمتوسط مرة واحدة على عمود المصدر كله، لا على الصفوف التي تركها مرشح آخر مرئية. لا تدخل المجموعة إلا الأعداد المنتهية، أي أن النص الشبيه بعدد مثل «100» مستثنى، وتُجمع المجموعة قبل اتخاذ أي قرار صف. في مصنف الضوابط الأصلي يحفظ مرشح فوق المتوسط متوسط 27 عبر العمود الكامل حتى بعد أن يخفي عمود ثانٍ القيمة 50؛ لا يتحول إلى متوسط 21.25 للصفوف المتبقية

تُدرج التعادلات عند العتبة كما في Excel. مرشح Top 3 على قيم فيها مدخلان متعادلان عند 20 يختار أربعة صفوف. ويأخذ نمط النسبة الحصة المقطوعة من المجموعة العددية، بأرضية عنصر واحد، فـ Top 50 percent من خمس قيم يختار قيمتين بعتبة 30. وتعكس بدائل Bottom المقارنة. وهذه الأرقام من مجموعات صفوف Excel الخاصة المسجلة في تجهيزات اختبار HotXLS، لا من قراءة المواصفة التي تصمت عن معظمها

تحسب HotXLS عتبات Top 10 والنسبة وفوق المتوسط في AutoFilter لـ Excel داخل Delphi مرة واحدة على عمود المصدر كله، محبسةً القيم المخفية في المجموعة والتعادلات عند العتبة في النتيجة
يحفظ فوق المتوسط متوسط العمود الكامل 27 بدل متوسط الصفوف المتبقية 21.25، ومرشح Top 3 على قيم فيها مدخلان متعادلان عند 20 يختار أربعة صفوف

التواريخ الديناميكية تحتاج تاريخاً مرجعياً مثبتاً

يثبت TXLSXAutoFilterExecutionOptions.ReferenceDate معنى «اليوم» لعملية كاملة. المرشحات النسبية مثل هذا الأسبوع أو الربع السابق، وقواعد تواريخ التنسيق الشرطي التي تطعم مرشحات الألوان، كلها تحسب مقابل ذلك التاريخ الواحد، فيتوافق البصر عند 23:59:59 مع التطبيق بعد ثانية. القيمة الصفرية تنتقي التاريخ الحالي مرة عند بدء العملية؛ وتحترم القيم التسلسلية نظام تاريخ المصنف 1900 أو 1904، بما في ذلك التسلسل الستيني الوهمي في Excel بنظام 1900 لمرشحي M2 و Q1

النوافذ مجالات تقويمية مفتوحة من جهة: يجري هذا الأسبوع من الأحد إلى الأحد التالي، وهذا الربع من أول يوم في الربع إلى أول يوم في التالي، والسنة حتى تاريخها من 1 يناير حتى نهاية اليوم المرجعي. ثبّت ReferenceDate صراحة في أي شيء يجري في مهمة دفعية أو اختبار. مهمة ليلية تعبر منتصف الليل، أو اختبار وحدة كُتب في أكتوبر وعليه أن ينجح في يناير، سيكونان وإلا قد أنتجا مجموعات صفوف تختلف بلا سبب مرئي

تحسب HotXLS قواعد التواريخ النسبية في dynamicFilter لـ Excel داخل Delphi مقابل تاريخ مرجعي مثبت واحد TXLSXAutoFilterExecutionOptions.ReferenceDate، بنوافذ هذا الأسبوع والربع والسنة حتى تاريخها مفتوحة من جهة
تثبيت التاريخ المرجعي يجعل البصر عند 23:59:59 متفقاً مع التطبيق بعد ثانية، ويثبت عثرية التسلسل 60 بنظام 1900 التي تمس مرشحي M2 و Q1

تُرشَّح خلايا الصيغ على قيمها المخزنة. لا يعيد محرك المرشح حساب المصنف بصمت، فملف حفظه كاتب لم يترك نتائج مخزنة يحتاج ممر حساب صريحاً قبل أن يرى المرشح أعداداً أو تواريخ ذات معنى

أي ألوان يرى مرشح الألوان؟

يرى مرشح ألوان في HotXLS اللون الفعلي من تنسيق الخلية المباشر مضافاً إليه أي تجاوز من تنسيق شرطي مطابق، ولا شيء يأتي من نمط جدول فقط. وسلوك Excel هو نفسه: صف مخطط رسمته أزرق فاتح نمط جدول مدمج ليس «أزرق فاتح» للقائمة المنسدلة للمرشح. في الضوابط الأصلية تنتقي مرشح التعبئة الحمراء خلية رسمتها حمراء التنسيقات الشرطية، بينما خلية منسقة حمراء مباشرة طغت عليها قاعدة صفراء نشطة تُستبعد

وصلت ثلاث تنقيحات في إصدارات لاحقة. تعامل النسخة 2.384.138 تعبئات التدرج الخطي والمساري معاملة مميزة عن الألوان الصلبة وعن لا تعبئة، فالتدرج لا يطابق معيار لون صلب قط حتى لو كان لأحد محطاته ذلك اللون بعينه. وأضافت النسخة 2.384.140 ترشيح لون الخط للنص الغني، حيث تطابق الخلية إذا كان أي شوط غير فارغ يحمل RGB المطلوب أو اللون التلقائي أو الموروث. وأكملت النسخة 2.384.150 قرارات النص الغني الشرطي، وتبين أنها الغريبة

قد تعيد Excel الأصلية استخدام قرار لوني بين خلية نص غني وخلية عادية بالنص نفسه والنمط الأساسي نفسه ومسار القاعدة الشرطية المطابقة نفسه، فيمكن أن يعتمد مجموعة الصفوف المرئية على ترتيب تلك الخلايا. تستنسخ HotXLS ذلك بتحضير مدى البيانات الكامل بترتيب صفوف تصاعدي، حتى لو سألت AutoFilterRowVisible عن صف واحد. ففحص الصف 40 يكلف ممراً على المدى، لكن فحص الصف والمعاينة والتطبيق تعيد دائماً الجواب نفسه للصف نفسه

لكل مورد حد، وماذا تلتقط

يسقف HotXLS كل نوع عمل في عملية AutoFilter بحقله الخاص في TXLSXAutoFilterExecutionOptions، لأن مصنفاً مرشحاً من نموذج رفع مدخل غير موثوق. الافتراضات 1048576 لـ MaxXmlCharacters، و16384 لـ MaxXmlNodes، و4096 لـ MaxFilterItems، و4000000 لـ MaxExaminedCells، و1000000 لكل من MaxEffectiveFormatCells و MaxPopulationValues، و67108864 بايتاً لـ MaxContextBytes، و16000000 لـ MaxConditionalSteps. يقيس MaxContextBytes الحالة المنطقية المحتفظ بها والأظرفة المؤقتة المحجوزة، لا ذاكرة العملية

type
  TFilterJob = class
  public
    Deadline: TDateTime;
    VisibleRows: TList<Integer>;
    procedure HandleRow(Sender: TObject; SheetIndex, Row: Integer;
      Visible: Boolean; var Cancel: Boolean);
    procedure HandleWork(Sender: TObject; ACompleted: Int64;
      var ACancel: Boolean);
  end;

procedure TFilterJob.HandleRow(Sender: TObject; SheetIndex, Row: Integer;
  Visible: Boolean; var Cancel: Boolean);
begin
  // تستدعى لكل صف بيانات؛ و Visible هو قرار المرشح
  if Visible then
    VisibleRows.Add(Row);
end;

procedure TFilterJob.HandleWork(Sender: TObject; ACompleted: Int64;
  var ACancel: Boolean);
begin
  // تعد ACompleted الخلايا المفحوصة وقد تبقى ثابتة أثناء التنسيق
  ACancel := Now > Deadline;
end;

يستقبل الاستدعاء العكسي للصفوف في PreviewAutoFilterRows كل صف بيانات مع قراره، لا المطابقة وحدها، وتظل الدالة تعيد عدد المطابقات. ضبط معامل Cancel عنده يوقف الزيارة مبكراً دون استثناء. و OnWork هو خطاف الإلغاء: ضبط ACancel على True يرفع EXLSXAutoFilterCancelled. وأثناء تحضير العملية القرارات تمتلك إيجار قراءة على المصنف، فلا يجوز لأي استدعاء عكسي تعديل ذلك المصنف

Options := XLSDefaultAutoFilterExecutionOptions;
Options.ReferenceDate := Date;
Options.MaxExaminedCells := 500000;   // سقف أكثر شدة للملفات المرفوعة
Options.OnWork := Job.HandleWork;
try
  Sheet.PreviewAutoFilterRows(Job.HandleRow, Options);
  Sheet.ApplyAutoFilter(True, Options);
except
  on E: EXLSXAutoFilterUnsupported do
    Log('Filter needs Excel: ' + E.Message);
  on E: EXLSXAutoFilterLimit do
    Log('Filter exceeded a budget: ' + E.Message);
  on E: EXLSXAutoFilterCancelled do
    Log('Filter cancelled at deadline');
  on E: EXLSXAutoFilterExecution do
    Log('Filter state invalid: ' + E.Message);
end;

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

أين الحدود

التغطية واسعة، لكن بعض الحواف تستحق المعرفة قبل أن توعد عميلاً بالتكافؤ:

  • ترفض مرشحات الانحراف المعياري الديناميكية حتى يوجد مقياس موثق، وإن كان التعداد يحوي قيماً لها
  • تبدأ نوافذ الأسبوع يوم الأحد؛ والمصنفات المعتمدة على بداية أسبوع مختلف غير مصمَّمة
  • نتائج الصيغ تأتي من المخزن المحفوظ فقط، دون إعادة حساب داخل استدعاء المرشح
  • ألوان نمط الجداول لا تطابق مرشح ألوان قط، بحسب التصميم واتساقاً مع Excel
  • بنية نص غني مجهولة أو بيانات ألوان مجهولة تفشل صراحة، بينما الخصائص المعروفة غير اللونية مثل عائلة الخط لا تحجب مطابقة لونية
  • واجهة XLS ومخزنها BIFF8 مسار منفصل، تغطيه كتابة HotXLS لمعايير DOPER لـ AutoFilter في BIFF8

إن كنت ما تزال تقرر كيف يترابط تعريف AutoFilter والتحقق من صحة البيانات والجداول في مصنف تولده بنفسك، فابدأ بـ التحقق من صحة البيانات و AutoFilter والجداول في HotXLS داخل Delphi، الذي يغطي SetAutoFilter ومعرفات الأعمدة ومتى يسري مرشح فعلاً

FAQ

هل تغيّر PreviewAutoFilterRows الصفوف المخفية؟

لا. تحسب PreviewAutoFilterRows المعايير المخزنة فقط وتبلّغ القرارات عبر قيمتها المعادة واستدعائها العكسي الاختياري. لا تنشر ApplyAutoFilter وحدها مجموعة صفوف مخفية جديدة، وتفعل ذلك بعد تحضير كل القرارات، فيترك الفشل الظهور الأصلي سليماً

لماذا يعطي مرشح تاريخ نسبي صفوفاً مختلفة في أيام مختلفة؟

المرشحات مثل اليوم وهذا الأسبوع أو الشهر السابق معرفة نسبةً إلى التاريخ الحالي، تماماً كما في Excel. اضبط ReferenceDate في TXLSXAutoFilterExecutionOptions على تاريخ ثابت عندما تحتاج نتائج قابلة للتكرار؛ والقيمة الصفرية تعني تاريخ بدء العملية

هل تستطيع HotXLS الترشيح على ألوان قادمة من نمط جدول؟

لا، ولا تستطيع Excel ذلك أيضاً. تطابق مرشحات ألوان HotXLS تنسيق الخلية المباشر والتجاوزات المدعومة من التنسيق الشرطي فقط. الألوان المرسومة بنمط جدول مدمج أو مخصص وحده لا تشارك، فنتيجة مرشح الألوان توافق ما ستنقيته القائمة المنسدلة في Excel

ينفَّذ التنفيذ المتقدم لـ AutoFilter مع API ورقة عمل XLSX في HotXLS، مكون جداول البيانات لـ Delphi لقراءة وكتابة ملفات Excel دون Excel، منذ v2.384.136، مع إضافة معالجة ألوان التدرج والنص الغني والنص الغني الشرطي حتى v2.384.150