تتيح معاودة الاتصال OnUserFunction لكود التطبيق تقييم دوال ورقة العمل المخصصة أو غير المدعومة أثناء Calculate. عيِّنها على TXLSWorkbook أو TXLSXWorkbook قبل استدعاء Calculate
استخدم OnUserFunctionEx عندما تحتاج معاودة الاتصال إلى سياق الصيغة الحالي. يُبلِّغ السياق عن فهرس الورقة القائم على 1 بالإضافة إلى صف وعمود خلية الصيغة القائمَين على 1؛ تُبلِّغ استدعاءات Calculate على مستوى المصنف التي لا تُقيِّم خلية بصف وعمود = 0
البنية
type
TXLSUserArgKind = (akuValue, akuRangeRef, akuArray);
TXLSUserFunctionContext = record
SheetIndex: Integer;
Row: Integer;
Col: Integer;
ArgCount: Integer;
ArgKinds: array of TXLSUserArgKind;
end;
TXLSUserFunctionEvent = procedure(
Sender: TObject;
const FunctionName: WideString;
const Args: Variant;
var Value: Variant;
var Handled: Boolean) of object;
TXLSUserFunctionExEvent = procedure(
Sender: TObject;
const FunctionName: WideString;
const Args: Variant;
const Context: TXLSUserFunctionContext;
var Value: Variant;
var Handled: Boolean) of object;
property OnUserFunction: TXLSUserFunctionEvent;
property OnUserFunctionEx: TXLSUserFunctionExEvent;
property AllowUnsafeFormulaCallbacks: Boolean;
المتغيرات
| FunctionName |
اسم الدالة كما ورد في نص الصيغة |
| Args |
مصفوفة Variant ذات فهرس صفري تحمل قيم الوسائط بعد تقييمها. في الدوال بلا وسائط تكون هذه القيمة
Null |
| Context |
في OnUserFunctionEx، يُبلّغ عن SheetIndex وRow وCol، إضافة إلى واصف الوسائط: ArgCount يطابق طول مصفوفة Args (0 في الاستدعاءات بلا وسائط)، بينما يصنّف ArgKinds كل وسيط على أنه akuValue (قيمة literal) أو akuRangeRef (إشارة إلى خلية أو نطاق) أو akuArray (ثابت مصفوفة). قيم الورقة والصف والعمود قائمة على 1 في صيغ الخلايا؛ ويكون الصف والعمود 0 عندما لا تجري عملية تقييم لأي خلية. تُلتقط هذه الأنواع قبل تقييم الوسائط، بحيث يستطيع المعالج ذو الأسلوب الشبيه بـ SUM أو MAP أن يميّز أن مستدعي الصيغة كتب إشارة مرجعية حتى لو حمل إدخال Args بعد التقييم القيمة فقط |
| Value |
أسند إليها نتيجة الدالة |
| Handled |
أسندها إلى True عندما توفّر معاودة الاتصال
نتيجة. واتركها False للاحتفاظ بالسلوك المعتاد تجاه الدوال
غير المدعومة |
سياسة أمان معاودة الاتصال
قيمة AllowUnsafeFormulaCallbacks الافتراضية هي False في مصنفات Classic XLS وXLSX، فالحفاظ على صيغة لا يخوّل أبدًا كود التطبيق المضيف معالجة اسم دالة خارجية خطرة أو من النمط الماكروي
تغطي البوابة الافتراضية DDE وCALL وREGISTER وREGISTER.ID وWEBSERVICE وRTD وSQL.REQUEST وEXEC وRUN وCREATE.OBJECT وAPP.ACTIVATE وSEND.KEYS وOPEN وSAVE وSAVE.AS وFOPEN وFWRITE وFWRITELN وFCLOSE وFILE.DELETE بعد توحيد أي بادئة future-function معروفة
يحدث الرفض قبل تقييم الوسائط وقبل تشغيل معاودات الاتصال المحلية على مستوى المصنف أو العملية أو الخاصة بالمحلِّل أو بالأحداث؛ أما أسماء الدوال المخصصة وغير المدعومة العادية فتبقي على سلوك معاودة الاتصال الحالي لديها
اضبط خاصية المصنف على True فقط عندما تكون كل الصيغ والمعالجات المسجلة موثوقة؛ وبدلًا من ذلك يمكن لتقييم سياقي معيّن أن يفعّل الخيار لاستدعاء واحد عبر TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks، في حين يتجاوز تمرير False صراحةً أي تفعيل على مستوى المصنف بأكمله
مثال
procedure TForm1.WorkbookUserFunction(Sender: TObject;
const FunctionName: WideString; const Args: Variant;
var Value: Variant; var Handled: Boolean);
begin
if SameText(FunctionName, 'DOUBLEPLUS') then
begin
Value := Double(Args[0]) * 2 + Double(Args[1]);
Handled := True;
end;
end;
Workbook.OnUserFunction := WorkbookUserFunction;
Value := Workbook.Calculate('=DOUBLEPLUS(A1;5)');
مثال مُدرك للسياق
procedure TForm1.WorkbookUserFunctionEx(Sender: TObject;
const FunctionName: WideString; const Args: Variant;
const Context: TXLSUserFunctionContext;
var Value: Variant; var Handled: Boolean);
begin
if SameText(FunctionName, 'ROWBONUS') then
begin
Value := Double(Args[0]) + Context.Row + Context.Col;
Handled := True;
end;
end;
Workbook.OnUserFunctionEx := WorkbookUserFunctionEx;
Value := Worksheet.Calculate('=C2');
استقبال وسائط النطاقات
عندما يُقيَّم وسيط إلى نطاق من ورقة العمل، يكون إدخال Args هو Variant من النوع varUnknown يحمل ICalcRangeList؛ ولا تُنسخ القيمة المقَّيمة لكل خلية تغطيها النطاقات إلى الـ Variant. اختبره واستخرجه باستخدام التحميل الزائد من VarIsRange الذي يعيد القائمة، ثم اقرأ المستطيلات المحلولة عبر TXLSCalcRange
type
TXLSCalcRange = class
property row1: Integer; { 0-based, inclusive }
property col1: Integer; { 0-based, inclusive }
property row2: Integer;
property col2: Integer;
property SheetIndex: Integer;
end;
ICalcRangeList = interface
property Count: Integer;
property Item[Index: Integer]: TXLSCalcRange;
end;
function VarIsRange(Value: Variant): Boolean; overload;
function VarIsRange(Value: Variant; var Int: ICalcRangeList): Boolean; overload;
function RangeToVariant(Value: TXLSCalcRangeList): Variant;
تتبع الإحداثيات اصطلاح TXLSGetValue نفسه: قائمة على الصفر وشاملة للطرفين. والمعالج الذي يريد أن يعيد نطاقًا بنفسه يبني TXLSCalcRangeList ويغلّفه بـ RangeToVariant قبل إسناد Value؛ يحتفظ عندها المحرك بالإشارة إلى النطاق للصيغ التابعة بدل لقطة عددية واحدة
انظر أيضاً