يُقيِّم HotXLS دالة LAMBDA في إكسل كقيمة دالة حقيقية من الدرجة الأولى. الاسم المعرَّف الذي يكون نص RefersTo الخاص به دالة LAMBDA يمكن استدعاؤه بالاسم كـ =MyFunc(5)، والإغلاق المربوط داخل LET يمكن استدعاؤه كـ =LET(f, LAMBDA(x, x*2), f(21))، والبيئة المعجمية الملتقَطة وقت التعريف تنتقل مع الإغلاق. يُحفَظ نص الصيغة حرفياً عند التنقل ذهاباً وإياباً داخل مصنف العمل
هذه هي الميزة التي تفصل بين محرك صيغ ومحلل صيغ. كل ما قبل LAMBDA كان يمكن تقييمه بالمشي عبر شجرة من القيم. تتطلب LAMBDA كومة نطاقات، وبمجرد أن تملك كومة نطاقات، تبدأ فئة كاملة من منطق جداول البيانات الذي يؤلفه المستخدمون بالعمل في تطبيق Delphi الخاص بك بدلاً من العمل في إكسل فقط
لماذا تتوقف معظم المحركات غير التابعة لإكسل عند الكلمة المفتاحية LAMBDA؟
لأن مقيِّم جداول البيانات الكلاسيكي يملك نوعاً واحداً بالضبط من القيم: رقم، أو سلسلة نصية، أو منطقي، أو خطأ، أو مرجع إلى خلايا تحمل تلك القيم. لا يوجد مكان لوضع دالة فيه. عندما قدَّم إكسل 365 دالة LAMBDA، أضاف نوع قيمة يحمل أسماء المعاملات، وتعبير المتن، والارتباطات المرئية حيث كُتب. المحرك الذي يفتقر إلى ذلك النوع يستطيع تحليل LAMBDA(x, x*2) وتخزين النص، لكن في اللحظة التي تحاول فيها خلية استدعاءها، لا يوجد ما يمكن استدعاؤه
ينفّذ HotXLS الجزء المفقود كقيمة إغلاق بالإضافة إلى كومة نطاقات وقت التشغيل. استدعاء إغلاق يدفع بيئته الملتقَطة، ثم يدفع قيم الوسائط تحت أسماء المعاملات، ويقيّم المتن، ويقتطع الكومة عائداً إلى العلامة. هذا الترتيب مهم، والقسم التالي يشرح السبب
الطرق الثلاث التي تُستدعى بها دالة LAMBDA
يحل HotXLS استدعاء اسم دالة غير معروف عبر ثلاثة مسارات، تُجرَّب بالترتيب، ومعرفة أيها ينطلق يفسر معظم المفاجآت. أولاً، اسم مربوط في نطاق LET أو LAMBDA الحالي: إذا كانت f ارتباطاً محلياً يحمل إغلاقاً، فإن f(21) يطبّقه. ثانياً، اسم معرَّف في مصنف العمل يبدأ نص صيغته بـ LAMBDA: MyFunc(5) يترجم متن ذلك الاسم ويطبّقه. ثالثاً، معالج الدوال المعرَّفة من المستخدم الكلاسيكي، دون تغيير، لكل ما لا يطالب به المساران الأولان
الارتباط المحلي الذي يحمل شيئاً غير إغلاق غير قابل للاستدعاء. اربط f بالرقم 3 ثم اكتب f(21) وستحصل على خطأ قيمة، لا على محاولة ضرب. هذا أكثر صرامة مما ستكون عليه لغة ديناميكية، وذلك عمداً: خطأ إملائي يحوّل استدعاء دالة إلى مرجع عرَضي هو إجابة خاطئة صامتة، وهي أسوأ نتيجة يمكن أن ينتجها محرك جداول بيانات
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Model');
// دالة مسمّاة قابلة لإعادة الاستخدام، بنطاق مصنف العمل
Book.DefinedNames.Add('NetOf', 'LAMBDA(amount, rate, amount*(1-rate))');
Sheet.Cells[2, 2].Formula := 'NetOf(1250, 0.19)';
// إغلاق مربوط ومطبَّق داخل صيغة واحدة
Sheet.Cells[3, 2].Formula := 'LET(double, LAMBDA(x, x*2), double(21))';
// LET متداخلة: كل ارتباط مرئي للارتباطات التي تليه
Sheet.Cells[4, 2].Formula :=
'LET(base, 100, bump, LAMBDA(v, v+base), LET(step, bump(5), step*2))';
Book.Recalculate;
Book.SaveAs('lambda-model.xlsx');
finally
Book.Free;
end;
end;
كيف يُحل التظليل عندما تتصادم الأسماء؟
المعاملات تفوز. عندما يطبّق HotXLS إغلاقاً، فإنه يدفع البيئة المعجمية الملتقَطة أولاً وارتباطات الوسائط ثانياً، بحيث يُظلِّل معامل مُسمَّى rate ارتباطاً خارجياً باسم rate ويُظلِّل أيضاً مرجع عمود بنفس الإملاء في الصيغة المحيطة. هذا الترتيب هو ما يجعل الدالة المسمّاة آمنة لإعادة الاستخدام: لا يستطيع المستدعي تغيير معنى المتن عن طريق الخطأ بوجود ارتباط بنفس الاسم في النطاق
يُفحص عدد الوسائط قبل تقييم أي شيء. الاستدعاء الذي لا يطابق فيه عدد الوسائط عدد معاملات الإغلاق يُعيد خطأ قيمة فوراً، بدلاً من تقييم بعض الوسائط ثم الفشل، مما يُبقي التقييم الخالي من التأثيرات الجانبية خالياً فعلاً من أي عمل جزئي. تُقتطع كومة النطاقات عائدة إلى علامة دخولها داخل كتلة finally، بحيث لا يستطيع خطأ داخل متن ترك ارتباطات قديمة مرئية للصيغة التالية
var
Book: TXLSXWorkbook;
Name: TXLSXDefinedName;
begin
Book := TXLSXWorkbook.Create;
try
if Book.Open('customer-model.xlsx') = 1 then
begin
// افحص ما ألّفه المستخدم قبل الوثوق بإعادة حساب
Name := Book.DefinedNames.FindByName('NetOf');
if (Name <> nil) and
(UpperCase(Copy(Name.Formula, 1, 6)) = 'LAMBDA') then
Log('Named lambda found: ' + Name.Formula);
Book.Recalculate;
Log(VarToStr(Book.Sheets[1].Cells[2, 2].Value));
end;
finally
Book.Free;
end;
end;
لم تعد LET جزئية
نفّذت إصدارات HotXLS السابقة LET إلى حد كافٍ فقط للتعامل مع حالة الارتباط الواحد الشائعة. التنفيذ الحالي كامل: كل ارتباط مرئي لجميع الارتباطات اللاحقة ولتعبير المتن، وتتألف LET المتداخلة بشكل طبيعي، بحيث تُقيَّم LET(a, 1, b, a+1, LET(c, b*2, c)) بالطريقة نفسها التي يقيّمها بها إكسل
هذا الاكتمال أهم مما يبدو عليه. LET هي وسيلة المستخدمين لتفادي إعادة حساب التعبير الفرعي نفسه خمس مرات في صيغة واحدة، لذا تستخدمها مصنفات العمل الحقيقية في نفس الأشكال المتداخلة بعمق التي يخطئ فيها التنفيذ الجزئي. إذا كنت تتحايل سابقاً على الثغرات بتوسيع ارتباطات LET قبل التقييم، فيمكن الاستغناء عن ذلك الحل البديل
الفاصلة أم الفاصلة المنقوطة: كلتاهما الآن
يقبل نص الصيغة في HotXLS الآن الفاصلة كفاصل وسائط إلى جانب الفاصلة المنقوطة الكلاسيكية. هذا ليس إعداد لغة محلية؛ إنه قاعدة قبول في المحلل. هذا مهم لأن الصيغ تصل من أماكن لا تتحكم فيها: مُلصَقة من تذكرة دعم، منسوخة من توثيق، مولَّدة بواسطة نص برمجي أصدر صيغة إكسل القياسية، مستوردة من ملف CSV لسلاسل صيغ
الأثر العملي هو أن SUM(A1,A2) وSUM(A1;A2) كلاهما يُترجم. يحافظ التنقل ذهاباً وإياباً على أياً كان المصدر قد استخدمه، بحيث يُكتب مصنف عمل حمّلته مرة أخرى بفواصله الأصلية بدلاً من تطبيعها من وراء ظهر المستخدم
ما الذي يُحفظ عند التنقل، وما الذي يجب فحصه
يُخزَّن نص الصيغة حرفياً، بحيث تنجو دالة LAMBDA في اسم معرَّف من دورة تحميل وحفظ سليمة وتُفتح في إكسل كالدالة نفسها. أما دالة LAMBDA مجردة مخزَّنة كنتيجة خلية، بمعنى صيغة تُقيَّم إلى إغلاق بدلاً من قيمة، فتحافظ على سلوك التخطي-دون-قيمة القائم: يُحفظ النص، ولا تُختلق أي نتيجة رقمية مخزَّنة مؤقتاً له. تلك هي النتيجة الصادقة، إذ لا توجد قيمة عددية لتخزينها مؤقتاً
عادتان تستحقان التبني. امنح دوال lambda المسمّاة نطاق مصنف العمل ما لم يكن هناك سبب لعدم ذلك، لأن دالة بنطاق ورقة تختفي عند نسخ الورقة تُنتج خطأ اسم في مكان بعيد عن السبب؛ وقواعد النطاق موضحة في الأسماء المعرَّفة والصيغ عبر الأوراق. وعندما يكون مصنف عمل مليء بدوال lambda مسمّاة موجَّهاً لتقرير يجب أن يكون مستقراً، فكّر في تجميد النتائج باستخدام ConvertFormulasToValues بحيث يرى المستهلكون اللاحقون أرقاماً بدلاً من دوال قد لا يدعمونها
بالنسبة لإعادة الحساب الثقيلة، متون LAMBDA هي تعبيرات عادية في رسم الاعتماد وتُجدوَل مثل أي صيغة أخرى، وهو ما يوضحه إعادة الحساب التزايدية ورسم الاعتماد. إذا كان نموذجك يستدعي دالة مسمّاة واحدة عبر آلاف الصفوف، فإن التكلفة هي المتن، لا آلية الاستدعاء، وتنطبق نصيحة التحسين نفسها كما تنطبق على أي صيغة متكررة
HotXLS مكون جداول بيانات أصلي لـ Delphi وC++Builder يقرأ ويكتب XLS وXLSX وODS دون إكسل أو أي أتمتة Office. محرك الصيغ والأسماء المعرَّفة وواجهة برمجة إعادة الحساب موثَّقة على صفحة مكون HotXLS لجداول البيانات في Delphi