معالجة الأخطاء

ملاحظة

لا يتوفر السلوك الذي تصفه هذه المقالة إلا عند تشغيل ميزة معاينة إدارة الأخطاء على مستوى الصيغة من خلال تشغيل الإعدادات>الميزات القادمة>معاينة. مزيد من المعلومات: التحكم في الميزات التي يتم تمكينها

الأخطاء تحدث. الشبكات تتعطل، مساحات التخزين تنفد، قيم غير متوقعة تأتي. من المهم أن يستمر منطقك في العمل بشكل صحيح في مواجهة المشكلات المحتملة.

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

كمنشئ تطبيق، يمكنك التحكم في الأخطاء في تطبيقك:

  • اكتشاف خطأ ومعالجته. في حالة احتمالية حدوث خطأ، يمكن كتابة صيغ التطبيق للكشف عن شرط الخطأ ثم إعادة محاولة تنفيذ العملية. لا يلزم أن يكون المستخدم النهائي قلقا بشأن حدوث خطأ لأن منشئ التطبيق وضع هذا الاحتمال في الاعتبار. يتم ذلك مع الدوال IfError وIsError وIsErrorBlank داخل صيغة.
  • الإبلاغ عن خطأ. إذا لم يتم التعامل مع الخطأ في الصيغة التي تم العثور عليه فيها، عندئذ يتم نقل الخطأ إلى معالج App.OnError. وهنا، لا يمكن استبدال الخطأ بعد ذلك حيث إنه قد حدث بالفعل وهو جزء من حسابات الصيغة. ولكن يمكنك استخدام App.OnError للتحكم في كيفية الإبلاغ عن الخطأ للمستخدم النهائي، بما في ذلك الإبلاغ عن الأخطاء كلها. يوفر App.OnError أيضا نقطة اختناق شائعة للإبلاغ عن الأخطاء عبر التطبيق بأكمله.
  • إنشاء خطأ ثم إعادة طرحه. وأخيرًا، يمكنك الكشف عن شرط خطأ بمنطقك الخاص، وهو شرط خاص لتطبيقك. استخدام دالة Error لإنشاء أخطاء مخصصة. يتم استخدام الدالة Error أيضًا لإعادة طرح خطأ بعد تحليله في IfError أو App.OnError.

الشروع في العمل

لنبدأ بمثال بسيط.

  1. قم بإنشاء شاشة جديدة في تطبيق اللوحة من Power Apps.
  2. قم بإدراج عنصر تحكم TextInput. سيتم تعيينه إلى الاسم TextInput1 بشكل افتراضي.
  3. قم بإدراج عنصر تحكم Label.
  4. قم بتعيين خاصية Text الخاصة بعنصر التحكم Label إلى الصيغة.
1/Value( TextInput1.Text )

شعار خطأ معروض مع

يوجد لدينا خطأ لأن النص الافتراضي لعنصر التحكم TextInput هو "Text input"، والذي لا يمكن تحويله إلى رقم. وهذا أمر جيد بشكل افتراضي، حيث يتلقى المستخدم النهائي إعلامًا يفيد بأن شيئا ما لا يعمل كما هو متوقع في التطبيق.

من الواضح أننا لا نرغب في ظهور خطأ للمستخدم في كل مرة يقوم فيها ببدء تشغيل هذا التطبيق. من المرجح أن "Text input" ليس الإعداد الافتراضي الصحيح لمربع إدخال النص على أية حال. لعلاج هذا الأمر، سنقوم بتغيير خاصية الإعداد الافتراضي لعنصر التحكم TextInput إلى:

Blank()

شعار خطأ معروض مع

لدينا الآن خطأ مختلف. أما العمليات الرياضية ذات القيمة الفارغة، مثل القسمة، فهي ستعرض القيمة الفارغة بالرقم صفر. وهذا يؤدي الآن إلى حدوث خطأ ناجم عن القسمة على صفر. لتصحيح هذا الأمر، نحتاج إلى تحديد السلوك المناسب لهذا الموقف في هذا التطبيق. قد تكون تظهر الإجابة بقيمة فارغة عندما يكون إدخال النص بقيمة فارغة. يمكننا تحقيق هذا من خلال إنهاء الصيغة بالدالة IfError:

IfError( 1/Value( TextInput1.Text ), Blank() )

لا يظهر شعار خطأ، خطأ سببه استبدال قيمة فارغة بفراغ

الآن يتم استبدال الخطأ بقيمة صالحة ويختفي شعار الخطأ. ولكن تشمل الدالة IfError التي استخدمناها كل الأخطاء، بما في ذلك إدخال قيمة غير صالحة مثل "hello". يمكننا معالجة هذا الأمر من خلال ضبط IfError للتعامل مع حالة القسمة على صفر فقط وإعادة طرح جميع الأخطاء الأخرى:

IfError( 1/Value( TextInput1.Text ), 
         If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )

لا يظهر شعار خطأ، خطأ سببه تحديدًا استبدال القسمة على صفر بفراغ، وإلا فقد يُعاد طرح الخطأ

لذلك، لنقم بتشغيل تطبيقنا ونجرب بعض القيم المختلفة.

بدون أية قيمة، كما هو الحال عندما يبدأ تشغيل التطبيق، لا توجد إجابة يتم عرضها لأن القيمة الافتراضية هي فارغة، لكن لا يتم عرض خطأ لأن الدالة IfError تحل محل خطأ القسمة على صفر.

لا تظهر إجابة ولا يظهر شعار خطأ

إذا قمنا بإدخال 4، سنحصل على النتيجة المتوقعة وهي 0.25:

يظهر 0.25 ولا يظهر شعار خطأ

وإذا قمنا بإدخال قيم غير صالحة، مثل hello، فسوف نتلقى شعار خطأ:

لا تظهر قيمة ولا يظهر شعار خطأ لعدم القدرة على تحويل

هذا مثال تقديمي بسيط. يمكن التعامل مع الأخطاء بطرق مختلفة، اعتمادًا على احتياجات التطبيق:

  1. فبدلاً من شعار الخطأ، قد تظهر كلمة "#خطأ" في عنصر تحكم التسمية مع الصيغة. للحفاظ على أنواع الاستبدالات متوافقة مع الوسيطة الأولى إلى IfError، يلزمنا أن نقوم بشكل واضح بتحويل النتيجة الرقمية إلى سلسلة نصية باستخدام الدالة Text.
    IfError( Text( 1/Value( TextInput1.Text ) ), 
             If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
    
    لا يظهر شعار خطأ وبدلاً من ذلك يظهر #Error كنتيجة
  2. بدلاً من إنهاء هذا المثيل المحدد مع IfError، كان يمكننا كتابة معالج App.OnError مركزي. لا يمكننا استبدال السلسلة المعروضة بكلمة "#خطأ"حيث حدث الخطأ بالفعل، ولا يتم توفير App OnError إلا للتحكم في إعداد التقارير.
    If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
    

نشر الأخطاء

تتدفق الأخطاء خلال الصيغ كما هي في Excel. في Excel مثلاً، إذا كانت الخلية A1 بها الصيغة =1/0، فإن A1 ستعرض قيمة الخطأ #DIV0!:

جدول بيانات Excel مع ظهور A1=1/0 و#DIV/0! في الخلية

وإذا كانت الخلية A2 تشير إلى A1 بصيغة مثل =A1*2، فإن الخطأ يتم نشره من خلال هذه الصيغة أيضًا:

جدول بيانات Excel مع ظهور A2=A1*2 و#DIV/0! في الخلية

يحل الخطأ محل القيمة التي كان سيتم حسابها من قبل. لا توجد نتيجة لعملية الضرب في الخلية A2، فقط الخطأ من القسمة في A1.

Power Fx تعمل بنفس الطريقة. بشكل عام، إذا تم توفير خطأ كوسيطة للدالة أو العامل، فلن تتم العملية وسيتدفق خطأ الإدخال نتيجة للعملية. على سبيل المثال، Mid( Text( 1/0 ), 1, 1 ) عرض خطأ القسمة على صفر، مع مرور معظم الأخطاء الداخلية عبر دالة Text ودالة Mid:

شعار خطأ يظهر عملية غير صالحة: قسمة على صفر

بشكل عام، لا تتدفق الأخطاء خلال خصائص عنصر تحكم Power Apps. لنقم بتوسيع المثال السابق باستخدام عنصر تحكم إضافي يعرض إذا ما كانت خاصية Text للتسمية الأولى حالة خطأ:

لا يظهر أي خطأ على عنصر تحكم التسمية الثاني

لا يوجد مشكلة في عدم نشر الأخطاء من خلال عنصر التحكم لأن النظام سيلاحظ أخطاء في الإدخال إلى كافة خصائص عناصر التحكم. لن يتم فقد الخطأ.

تتبع معظم الدوال والمعاملات قاعدة "التوقف وعرض رسالة خطأ"، ولكن هناك بعض الاستثناءات. الدوال IsError وIsErrorBlank وIfError مصممة للعمل مع الأخطاء وبالتالي قد لا تعرض خطأ حتى إذا تم تمرير واحد فيها.

ملاحظة الأخطاء

لا تتم ملاحظة الأخطاء حتى يتم استخدام قيمتها.

ونتيجة لذلك، قد لا تعرض الدالتين If وSelect خطأ في حالة مرور واحد. فكر في الصيغة If( false, 1/0, 3 ). يوجد خطأ القسمة على صفر في هذه الصيغة، ولكن نظرًا لأن If لا تتولى هذا الفرع لأن false وPower Fx وPower Apps لن تقوم بالإبلاغ عن خطأ:

لا يظهر شعار خطأ مع الدالة If في خاصية نص التسمية

لن يترتب على استخدام الدالة Set مع حدوث خطأ الإبلاغ عن خطأ عند نقطة وضع الخطأ في المتغير. على سبيل المثال، في Power Apps، إليك صيغة في App.OnStart تضع خطأ القسمة على صفر في المتغير x:

لا يظهر شعار خطأ مع استدعاء الدالة Set في App.OnStart

لا يتم الإبلاغ عن خطأ، بسبب عدم الإشارة إلى x. ومع ذلك، في هذه اللحظات التي نقوم فيها بإضافة عنصر تحكم التسمية ونضبط خاصية Text الخاصة به على x، يتم عرض الخطأ:

يظهر شعار خطأ مع عنصر تحكم التسمية الذي يشير إلى المتغير x

يمكنك ملاحظة الأخطاء في صيغة تتضمن الدوال IfError وIsError وIsErrorOrBlank. باستخدام هذه الدوال، يمكنك عرض قيمة بديلة أو اتخاذ إجراء بديل أو تعديل الخطأ قبل ملاحظته والإبلاغ عنه.

‏‏الإبلاغ عن الأخطاء

بعد ملاحظة خطأ، الخطوة التالية هي الإبلاغ عن الخطأ إلى المستخدم النهائي.

وعلى العكس من Excel، لا يوجد دائمًا مكان مناسب لعرض نتيجة الخطأ، حيث قد تقود نتيجة للصيغة خاصية مثل إحداثيات س وص الخاصة بالتحكم، والتي لا يوجد مكان مناسب لعرض بعض النصوص لها. ويتحكم كل مضيف Power Fx في كيفية عرض الأخطاء في النهاية للمستخدم النهائي وكيفية تحكم المنشئ في هذه العملية. في Power Apps، يتم عرض شعار خطأ، ويتم استخدام App.OnError للتحكم في كيفية الإبلاغ عن الخطأ.

من المهم ملاحظة أن App.OnError لا يمكنه استبدال الخطأ بنفس طريقة IfError. عند تنفيذ App.OnError، يكون الخطأ قد حدث بالفعل، وقد تم نشر النتيجة من خلال صيغ أخرى. يتحكم App.OnError فقط في كيفية الإبلاغ عن الخطأ للمستخدم النهائي ويوفر خطافا للصانع لتسجيل الخطأ إذا رغبت في ذلك.

يوفر متغيرا النطاق FirstError وAllErrors معلومات سياق حول الخطأ أو الأخطاء. ويترتب على ذلك توفر معلومات عن نوع الخطأ ومنشأه والموقع الذي تمت ملاحظته فيه.

التوقف بعد حدوث خطأ

تدعم صيغ السلوك اتخاذ إجراء وتعديل قواعد البيانات وتغيير الحالة. تسمح هذه الصيغ بأكثر من إجراء واحد يتم القيام به في تسلسل باستخدام عامل التسلسل ; (أو ;; وفقًا للإعداد المحلي).

في هذه الحالة، على سبيل المثال، يعرض عنصر تحكم الشبكة محتوى الجدول T. يغير كل زر يتم تحديده الحالة في هذا الجدول بعمليتي استدعاء تصحيح:

صورة متحركة تُظهر السجلين في الجدول T قيد التحديث بأرقام عشوائية بعد كل نقرة فور الزر

في صيغة سلوك متسلسل، لا تتوقف الإجراءات بعد الخطأ الأول. لنقم بتعديل المثال لتمرير رقم فهرس غير صالح في عملية استدعاء التصحيح الأولى. تستمر عملية استدعاء التصحيح الثانية على الرغم من هذا الخطأ السابق. يتم إعلام المستخدم النهائي بالخطأ الأول، كما يظهر كخطأ في Studio في عنصر التحكم:

صورة متحركة تُظهر السجل الثاني فقط في الجدول T قيد التحديث بأرقام عشوائية بعد كل نقرة فور الزر‬، السجل الأول ينتج عنه خطأ

يمكن استخدام IfError لإيقاف التنفيذ بعد حدوث خطأ. وبشكل مشابه للدالة If، توفر الوسيطة الثالثة لهذه الدالة مكانًا لتنفيذ الإجراءات التي ينبغي تنفيذها فقط في حالة عدم وجود خطأ:

صورة متحركة تُظهر عدم وجود أي تغييرات في أي من السجلين في الجدول T، لأن IfError تمنع إكمال العملية الثانية بعد خطأ

في حالة حدوث خطأ أثناء أحد عمليات تكرار ForAll، لن يتم إيقاف بقية عمليات التكرار. تم تصميم ForAll لتنفيذ كل تكرار بشكل مستقل ، مما يسمح بالتنفيذ المتوازي. عندما يكتمل ForAll، يتم عرض خطأ، والذي يحتوي على كافة الأخطاء التي تواجهك (عن طريق فحص AllErrors في IfError أو App.OnError).

على سبيل المثال، ستنتج عن الصيغة التالية أن تعرض ForAll خطأين (للقسمة على صفر للقيمة Value بالنسبة لرقم 0، مرتين) وسينتج عن Collection ثلاثة سجلات (عندما لا تساوي قيمة Value 0): [1, 2, 3].

Clear( Collection ); 
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );

العمل مع العديد من الأخطاء

نظرا لأن صيغة السلوك يمكن أن تقوم بتنفيذ أكثر من إجراء واحد، فقد تواجه أيضا أكثر من خطأ واحد.

افتراضيا، يتم إعلام المستخدم النهائي بالخطأ الأول. في هذا المثال، ستفشل عمليتي استدعاء التصحيح، والثانية تتضمن خطأ القسمة على صفر. يتم عرض الخطأ الأول فقط (حول الفهرس) للمستخدم:

أول خطأ في الفهرس يتم عرضه في شعار خطأ، ولا يتم الإبلاغ عن الخطأ الثاني

يمكن للدالة IfError وApp.OnError الوصول إلى جميع الأخطاء التي تواجهها مع متغير نطاق AllErrors. في هذه الحالة، يمكننا تعيين هذا على متغير عام وننظر إلى كل الخطأين اللذين تمت مواجهتهما. فهي تظهر في الجدول بنفس الترتيب الذي واجهتها به:

التقاط الأخطاء في المتغير العمومي PatchErrors حيث يمكننا أن نرى وجود الخطأين

يمكن عرض أخطاء متعددة في صيغ غير سلوكية أيضًا. على سبيل المثال، قد يتسبب استخدام دالة Patch على دفعة من السجلات للتحديث في أخطاء متعددة، خطأ لكل سجل غير صالح.

الأخطاء في الجداول

كما شاهدنا سابقا، يمكن تخزين الأخطاء في المتغيرات. يمكن أيضا تضمين الأخطاء في هياكل البيانات، مثل الجداول. وهذا أمر هام حتى لا يمكن لخطأ في أي سجل أن يبطل الجدول بالكامل.

على سبيل المثال، فكر في عنصر تحكم جدول البيانات هذا في Power Apps:

جدول بيانات يظهر خطأ في الحقل

لقد واجهت العملية الحسابية في AddColumns خطأ القسمة على صفر لأحد القيم. بالنسبة لهذا السجل الواحد، فإن العمود تبادلي يتضمن قيمة خطأ (القسمة على صفر) ولكن السجلات الأخرى ليست كذلك وهي سجلات صالحة. IsError( Index( output, 2 ) ) إرجاع false وإرجاع IsError( Index( output, 2 ).Value ) true.

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

اطلع على هذا المثال. هنا، لا توجد أخطاء في الجدول الأصلي، ولكن عمل التصفية ينشئ خطأ كلما كانت القيمة تساوي 0:

جدول بيانات يعرض أخطاء لسجلين تعذرت معالجتهما بواسطة معايير التصفية

القيم -5 و-3 يتم تصفيتها بشكل صحيح. تؤدي القيم 0 إلى حدوث خطأ في معالجة عامل التصفية، وبالتالي يتم تضمين السجل في حالة ضرورة تضمين السجل أو عدم تضمينه في النتيجة. لزيادة فرص الربح للمستخدمين النهائيين ومساعدة المنشئين على تصحيح الأخطاء، نقوم بتضمين سجل خطأ في مكان الأصل. في هذه الحالة، يقوم IsError( Index( output, 2 ) ) بعرض القيمة true.

أخطاء مصدر البيانات

الدوال التي تعمل على تعديل البيانات في مصادر البيانات، مثل Patch، وCollect، وRemove، وRemoveIf، وUpdate، وUpdateIf، وSubmitForm تبلغ عن الأخطاء بطريقتين:

  • تُرجع كل واحدة من هذه الدوال قيمة خطأ كنتيجة للعملية. يمكن اكتشاف الأخطاء باستخدام الدالة IsError ويتم استبدالها أو إيقافها باستخدام الدالة IfError وApp.OnError كالمعتاد.
  • بعد العملية، ستقوم الدالة Errors أيضًا بإرجاع الأخطاء الخاصة بالعمليات السابقة. ويمكن أن يفيد هذا الأمر في عرض رسالة الخطأ على شاشة نموذج بدون الحاجة إلى التقاط الخطأ في متغير حالة.

على سبيل المثال، ستتحقق هذه الصيغة من وجود خطأ من Collect وعرض رسالة خطأ مخصصة:

IfError( Collect( Names, { Name: "duplicate" } ),
         Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )

كما تعرض الدالة Errors على عرض معلومات حول الأخطاء السابقة أثناء عمليات وقت التشغيل. يمكن أن يكون من المفيد عرض خطأ على شاشة نموذج دون الحاجة إلى التقاط الخطأ في متغير حالة.

إعادة طرح الأخطاء

وفي بعض الأحيان، من المتوقع حدوث بعض الأخطاء المحتملة ويمكن تجاهلها بأمان. داخل IfError وApp.OnError، إذا تم اكتشاف خطأ ينبغي تمريره إلى معالج أعلى التالي، يمكن إعادة طرحه مع Error( AllErrors ).

إنشاء الأخطاء الخاصة بك

يمكنك أيضًا إنشاء الأخطاء الخاصة بك باستخدام الدالة Error.

إذا كنت تقوم بإنشاء الأخطاء الخاصة بك، فمن المستحسن استخدام قيم أعلى من 1000 لتجنب التعارضات المحتملة مع قيم أخطاء النظام المستقبلية.

قيم تعداد ErrorKind

تعداد ErrorKind القيمة الوصف
AnalysisError 18 ‏‏خطأ النظام. حدثت مشكلة في تحليل المحول البرمجي.
BadLanguageCode 14 تم استخدام رمز لغة غير صالح أو غير معروف.
BadRegex 15 التعبير العادي غير صالح. تحقق من بناء الجملة المستخدم مع الدوال IsMatch أو Match أو MatchAll.
Conflict 6 لقد تم بالفعل تغيير السجل الذي تم تحديثه من المصدر وينبغي حل التعارض. والحل الشائع هو حفظ أي تغييرات محلية وتحديث السجل ثم إعادة تطبيق التغييرات.
ConstraintViolated 8 لم يمر السجل بعملية تحقق من القيود على الخادم.
CreatePermission 3 لا يوجد لدى المستخدم إذن بإنشاء سجل لسجل مصدر البيانات. على سبيل المثال، تم استدعاء الدالة Collect.
DeletePermissions 5 لا يوجد لدى المستخدم إذن بحذف سجل مصدر البيانات. على سبيل المثال، تم استدعاء الدالة Remove.
Div0 13 القسمة على صفر.
EditPermissions 4 لا يوجد لدى المستخدم إذن بإنشاء سجل لسجل مصدر البيانات. على سبيل المثال، تم استدعاء الدالة Patch.
GeneratedValue 9 تم تمرير قيمة إلى الخادم بشكل غير صحيح لأي حقل يتم احتسابه تلقائيًا بواسطة الخادم.
InvalidFunctionUsage 16 استخدام الدالة غير صالح. في الغالب تكون وسيطة واحدة أو أكثر من وسيطات الوظيفة غير صحيحة أو تستخدم بطريقة غير صالحة.
FileNotFound 17 تعذر العثور على موقع تخزين SaveData.
InsufficientMemory 21 لا توجد ذاكرة أو مساحة تخزين كافية على الجهاز للعملية.
InvalidArgument 25 تم تمرير وسيطة غير صالحة إلى دالة.
Internal 26 ‏‏خطأ النظام. هناك مشكلة داخلية في إحدى الدوال.
MissingRequired 2 فُقد حقل مطلوب من سجل.
Network 23 حدثت مشكلة في اتصالات الشبكة.
None 0 ‏‏خطأ النظام. لا يوجد خطأ.
NotApplicable 27 لا تتوفر قيمة. مفيد للتفريق بين قيمة فارغة يمكن التعامل معها على أنها صفر في الحسابات الرقمية عن القيم الفارغة التي يجب وضع علامة عليها كمشكلة محتملة إذا تم استخدام القيمة.
NotFound 7 تعذر العثور على السجل. على سبيل المثال، السجل الذي سيتم تعديله في دالة Patch.
NotSupported 20 العملية غير مدعومة من قبل هذا المشغل أو الجهاز.
رقمي 24 تم استخدام دالة رقمية بطريقة غير صحيحة. على سبيل المثال، تعرض Sqrt القيمة -1.
QuotaExceeded 22 تم تجاوز الحصة النسبية للتخزين.
ReadOnlyValue 10 العمود للقراءة فقط ولا يمكن تعديله.
ReadPermission 19 لا يوجد لدى المستخدم إذن قراءة سجل مصدر البيانات.
مزامنة 1 تم الإبلاغ عن خطأ من قِبل مصدر البيانات. تحقق من عمود الرسالة لمزيد من المعلومات.
غير معروفة 12 حدث خطأ، ولكن من نوع غير معروف.
التحقق من الصحة 11 لم يمر السجل بتحقق من الصحة.