1. نظرة عامة
في هذا الدرس العملي، ستستخدم برمجة تطبيقات Google لكتابة إضافة Google Workspace لـ Gmail تتيح للمستخدمين إضافة بيانات الإيصالات من رسالة إلكترونية إلى جدول بيانات مباشرةً من داخل Gmail. عندما يتلقّى المستخدم إيصالاً عبر البريد الإلكتروني، يفتح الإضافة التي تحصل تلقائيًا على معلومات النفقات ذات الصلة من الرسالة الإلكترونية. يمكن للمستخدم تعديل معلومات النفقات ثم إرسالها لتسجيل نفقاته في جدول بيانات Google.
أهداف الدورة التعليمية
- إنشاء إضافة Gmail لـ Google Workspace باستخدام "برمجة تطبيقات Google"
- تحليل رسالة إلكترونية باستخدام "برمجة تطبيقات Google"
- التفاعل مع "جداول بيانات Google" من خلال "برمجة تطبيقات Google"
- تخزين قيم المستخدمين باستخدام خدمة Properties في "برمجة تطبيقات Google"
المتطلبات
- إمكانية الوصول إلى الإنترنت ومتصفّح ويب
- حساب Google
- بعض الرسائل، ويُفضّل أن تكون إيصالات البريد الإلكتروني، في Gmail
2. الحصول على الرمز النموذجي
أثناء العمل على هذا الدرس التطبيقي حول الترميز، قد يكون من المفيد الرجوع إلى نسخة عاملة من الرمز الذي ستكتبه. يحتوي مستودع GitHub على رمز نموذجي يمكنك استخدامه كمرجع.
للحصول على رمز نموذجي، نفِّذ ما يلي من سطر الأوامر:
git clone https://github.com/googleworkspace/gmail-add-on-codelab.git
3- إنشاء إضافة أساسية
ابدأ بكتابة الرمز لإصدار بسيط من الإضافة يعرض نموذجًا للمصروفات بجانب رسالة إلكترونية.
أولاً، أنشئ مشروعًا جديدًا في برمجة تطبيقات وافتح ملف البيان الخاص به.
- انتقِل إلى script.google.com. يمكنك من هنا إنشاء مشاريع "برمجة تطبيقات Google" وإدارتها ومراقبتها.
- لإنشاء مشروع جديد، انقر على مشروع جديد في أعلى يمين الصفحة. يفتح المشروع الجديد بملف تلقائي اسمه
Code.gs. اتركCode.gsبدون تغيير في الوقت الحالي، ستستخدمه لاحقًا. - انقر على مشروع بلا عنوان، وأدخِل اسم مشروعك Expense It!، ثم انقر على إعادة تسمية.
- على يمين الصفحة، انقر على إعدادات المشروع
. - ضَع علامة في مربّع الاختيار عرض ملف البيان "appscript.json" في المحرر".
- انقر على أداة التعديل
. - لفتح ملف البيان، انقر على
appscript.jsonفي أعلى يمين الصفحة.
في appscript.json، حدِّد البيانات الوصفية المرتبطة بالإضافة، مثل اسمها والأذونات التي تتطلّبها. استبدِل محتوى appsscript.json بإعدادات الضبط التالية:
{
"timeZone": "GMT",
"oauthScopes": [
"https://www.googleapis.com/auth/gmail.addons.execute"
],
"gmail": {
"name": "Expense It!",
"logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/receipt_black_24dp.png",
"contextualTriggers": [{
"unconditional": {
},
"onTriggerFunction": "getContextualAddOn"
}],
"primaryColor": "#41f470",
"secondaryColor": "#94f441"
}
}
انتبه جيدًا إلى جزء البيان المعروف باسم contextualTriggers. يحدّد هذا الجزء من ملف البيان الدالة التي يحدّدها المستخدم والتي سيتم استدعاؤها عند تفعيل الإضافة لأول مرة. في هذه الحالة، يتم استدعاء getContextualAddOn، الذي يحصل على تفاصيل حول الرسالة الإلكترونية المفتوحة ويعرض مجموعة من البطاقات للمستخدم.
لإنشاء الدالة getContextualAddOn، اتّبِع الخطوات التالية:
- على يمين الشاشة، مرِّر المؤشر فوق
Code.gs، ثم انقر على "القائمة"
> إعادة التسمية. - اكتب
GetContextualAddOnواضغط على المفتاحEnter. يضيف برمجة تطبيقات تلقائيًا.gsإلى اسم الملف، لذا لا تحتاج إلى كتابة امتداد الملف. إذا كتبتGetContextualAddOn.gs، ستسمّي "برمجة تطبيقات Google" ملفكGetContextualAddOn.gs.gs. - في
GetContextualAddOn.gs، استبدِل الرمز التلقائي بالدالةgetContextualAddOn:
/**
* Returns the contextual add-on data that should be rendered for
* the current e-mail thread. This function satisfies the requirements of
* an 'onTriggerFunction' and is specified in the add-on's manifest.
*
* @param {Object} event Event containing the message ID and other context.
* @returns {Card[]}
*/
function getContextualAddOn(event) {
var card = CardService.newCardBuilder();
card.setHeader(CardService.newCardHeader().setTitle('Log Your Expense'));
var section = CardService.newCardSection();
section.addWidget(CardService.newTextInput()
.setFieldName('Date')
.setTitle('Date'));
section.addWidget(CardService.newTextInput()
.setFieldName('Amount')
.setTitle('Amount'));
section.addWidget(CardService.newTextInput()
.setFieldName('Description')
.setTitle('Description'));
section.addWidget(CardService.newTextInput()
.setFieldName('Spreadsheet URL')
.setTitle('Spreadsheet URL'));
card.addSection(section);
return [card.build()];
}
تتألف واجهة مستخدم كل إضافة من إضافات Google Workspace من بطاقات مقسّمة إلى قسم واحد أو أكثر، ويحتوي كل قسم على عناصر واجهة مستخدم يمكنها عرض المعلومات والحصول عليها من المستخدم. تنشئ الدالة getContextualAddOn بطاقة واحدة تتضمّن تفاصيل حول نفقات تم العثور عليها في رسالة إلكترونية. تحتوي البطاقة على قسم واحد يتضمّن حقول إدخال نصية للبيانات ذات الصلة. تعرض الدالة مصفوفة من بطاقات الإضافة. في هذه الحالة، تتضمّن المصفوفة المعروضة بطاقة واحدة فقط.
قبل نشر إضافة Expense It!، تحتاج إلى مشروع Google Cloud Platform (GCP)، والذي تستخدمه مشاريع "برمجة التطبيقات" لإدارة التفويضات والخدمات المتقدّمة وتفاصيل أخرى. لمزيد من المعلومات، يُرجى الانتقال إلى مشاريع Google Cloud Platform.
لنشر الإضافة وتشغيلها، اتّبِع الخطوات التالية:
- افتح مشروعك على Google Cloud Platform، وانسخ رقم المشروع.
- من مشروع برمجة تطبيقات، انقر على إعدادات المشروع
في يمين الصفحة. - ضمن "مشروع Google Cloud Platform (GCP)"، انقر على تغيير المشروع.
- أدخِل رقم مشروعك على Google Cloud Platform، ثم انقر على ضبط المشروع.
- انقر على نشر > اختبار عمليات النشر.
- تأكَّد من أنّ نوع النشر هو إضافة Google Workspace. إذا لزم الأمر، انقر على "تفعيل أنواع النشر"
في أعلى مربّع الحوار، ثم اختَر إضافة Google Workspace كنوع النشر. - بجانب التطبيقات: Gmail، انقر على تثبيت.
- انقر على تم.
يمكنك الآن الاطّلاع على الإضافة في بريدك الوارد في Gmail.
- على الكمبيوتر، افتح Gmail.
- في اللوحة الجانبية اليسرى، انقر على Expense It! تظهر الإضافة
. قد تحتاج إلى النقر على "المزيد من الإضافات"
للعثور عليها. - افتح رسالة إلكترونية، ويُفضّل أن تكون إيصالاً يتضمّن نفقات.
- لفتح الإضافة، انقر على Expense It! في اللوحة الجانبية اليسرى.
. - امنح تطبيق Expense It! إذن الوصول إلى حسابك على Google من خلال النقر على منح الإذن بالوصول واتّباع التعليمات.
تعرض الإضافة نموذجًا بسيطًا بجانب رسالة Gmail مفتوحة. لا يمكنها تنفيذ أي إجراء آخر حتى الآن، ولكنك ستضيف إليها وظائف أخرى في القسم التالي.
للاطّلاع على آخر التعديلات على الإضافة أثناء مواصلة هذا التدريب العملي، ما عليك سوى حفظ الرمز البرمجي وإعادة تحميل Gmail. لا يلزم إجراء عمليات نشر إضافية.
4. الوصول إلى الرسائل الإلكترونية
أضِف رمزًا برمجيًا يسترد محتوى البريد الإلكتروني وقسِّم الرمز البرمجي إلى وحدات لتنظيمه بشكل أفضل.
بجانب "الملفات"، انقر على "إضافة"
> نص برمجي وأنشئ ملفًا باسم Cards. أنشئ ملف نص برمجي ثانيًا باسم Helpers. تنشئ Cards.gs البطاقة وتستخدم دوال من Helpers.gs لملء الحقول في النموذج استنادًا إلى محتوى الرسالة الإلكترونية.
استبدِل الرمز التلقائي في Cards.gs بهذا الرمز:
var FIELDNAMES = ['Date', 'Amount', 'Description', 'Spreadsheet URL'];
/**
* Creates the main card users see with form inputs to log expenses.
* Form can be prefilled with values.
*
* @param {String[]} opt_prefills Default values for each input field.
* @param {String} opt_status Optional status displayed at top of card.
* @returns {Card}
*/
function createExpensesCard(opt_prefills, opt_status) {
var card = CardService.newCardBuilder();
card.setHeader(CardService.newCardHeader().setTitle('Log Your Expense'));
if (opt_status) {
if (opt_status.indexOf('Error: ') == 0) {
opt_status = '<font color=\'#FF0000\'>' + opt_status + '</font>';
} else {
opt_status = '<font color=\'#228B22\'>' + opt_status + '</font>';
}
var statusSection = CardService.newCardSection();
statusSection.addWidget(CardService.newTextParagraph()
.setText('<b>' + opt_status + '</b>'));
card.addSection(statusSection);
}
var formSection = createFormSection(CardService.newCardSection(),
FIELDNAMES, opt_prefills);
card.addSection(formSection);
return card;
}
/**
* Creates form section to be displayed on card.
*
* @param {CardSection} section The card section to which form items are added.
* @param {String[]} inputNames Names of titles for each input field.
* @param {String[]} opt_prefills Default values for each input field.
* @returns {CardSection}
*/
function createFormSection(section, inputNames, opt_prefills) {
for (var i = 0; i < inputNames.length; i++) {
var widget = CardService.newTextInput()
.setFieldName(inputNames[i])
.setTitle(inputNames[i]);
if (opt_prefills && opt_prefills[i]) {
widget.setValue(opt_prefills[i]);
}
section.addWidget(widget);
}
return section;
}
تأخذ الدالة createExpensesCard صفيفًا من القيم لملء النموذج مسبقًا كمعلَمة اختيارية. يمكن للدالة عرض رسالة حالة اختيارية، تكون باللون الأحمر إذا بدأت الحالة بـ "Error:"، وتكون باللون الأخضر في الحالات الأخرى. بدلاً من إضافة كل حقل إلى النموذج يدويًا، تتكرّر دالة مساعدة باسم createFormSection خلال عملية إنشاء أدوات إدخال النص، وتضبط كل قيمة تلقائية باستخدام setValue، ثم تضيف الأدوات إلى الأقسام الخاصة بها على البطاقة.
الآن، استبدِل الرمز التلقائي في Helpers.gs بهذا الرمز:
/**
* Finds largest dollar amount from email body.
* Returns null if no dollar amount is found.
*
* @param {Message} message An email message.
* @returns {String}
*/
function getLargestAmount(message) {
return 'TODO';
}
/**
* Determines date the email was received.
*
* @param {Message} message An email message.
* @returns {String}
*/
function getReceivedDate(message) {
return 'TODO';
}
/**
* Determines expense description by joining sender name and message subject.
*
* @param {Message} message An email message.
* @returns {String}
*/
function getExpenseDescription(message) {
return 'TODO';
}
/**
* Determines most recent spreadsheet URL.
* Returns null if no URL was previously submitted.
*
* @returns {String}
*/
function getSheetUrl() {
return 'TODO';
}
يتم استدعاء الدوال في Helpers.gs من خلال getContextualAddon لتحديد القيم التي يتم ملؤها مسبقًا في النموذج. في الوقت الحالي، ستعرض هذه الدوال السلسلة "TODO" فقط لأنّك ستنفّذ منطق التعبئة المسبقة في خطوة لاحقة.
بعد ذلك، عدِّل الرمز في GetContextualAddon.gs لكي يستفيد من الرمز في Cards.gs وHelpers.gs. استبدِل الرمز في GetContextualAddon.gs بالرمز التالي:
/**
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Returns the contextual add-on data that should be rendered for
* the current e-mail thread. This function satisfies the requirements of
* an 'onTriggerFunction' and is specified in the add-on's manifest.
*
* @param {Object} event Event containing the message ID and other context.
* @returns {Card[]}
*/
function getContextualAddOn(event) {
var message = getCurrentMessage(event);
var prefills = [getReceivedDate(message),
getLargestAmount(message),
getExpenseDescription(message),
getSheetUrl()];
var card = createExpensesCard(prefills);
return [card.build()];
}
/**
* Retrieves the current message given an action event object.
* @param {Event} event Action event object
* @return {Message}
*/
function getCurrentMessage(event) {
var accessToken = event.messageMetadata.accessToken;
var messageId = event.messageMetadata.messageId;
GmailApp.setCurrentMessageAccessToken(accessToken);
return GmailApp.getMessageById(messageId);
}
لاحظ الدالة الجديدة getCurrentMessage التي تستخدم الحدث المقدَّم من Gmail لقراءة الرسالة المفتوحة حاليًا للمستخدم. لكي تعمل هذه الوظيفة، أضِف نطاقًا إضافيًا إلى بيان البرنامج النصي يسمح بالوصول للقراءة فقط إلى رسائل Gmail.
في appscript.json، عدِّل oauthScopes لكي يطلب أيضًا نطاق https://www.googleapis.com/auth/gmail.addons.current.message.readonly.
"oauthScopes": [
"https://www.googleapis.com/auth/gmail.addons.execute",
"https://www.googleapis.com/auth/gmail.addons.current.message.readonly"
],
في Gmail، شغِّل الإضافة، وامنح تطبيق Expense It! إذن الوصول إلى الرسائل الإلكترونية. تم الآن ملء حقول النموذج مسبقًا بالقيمة "TODO".
5- التفاعل مع "جداول بيانات Google"
يتضمّن إضافة Expense It! نموذجًا يتيح للمستخدم إدخال تفاصيل حول أحد النفقات، ولكن لا يمكن إرسال هذه التفاصيل إلى أي مكان. لنضِف زرًا يرسل بيانات النموذج إلى جدول بيانات Google.
لإضافة زر، سنستخدم الفئة ButtonSet. للتفاعل مع "جداول بيانات Google"، سنستخدم خدمة "جداول بيانات Google".
عدِّل createFormSection لعرض زرّ يحمل التصنيف "إرسال" كجزء من قسم النموذج في البطاقة. يُرجى تنفيذ ما يلي:
- أنشئ زر نص باستخدام
CardService.newTextButton()، مع تسمية الزر "إرسال" باستخدامCardService.TextButton.setText(). - صمِّم الزرّ بحيث يتمّ استدعاء الإجراء
submitFormالتالي عند النقر عليه من خلالCardService.TextButton.setOnClickAction():
/**
* Logs form inputs into a spreadsheet given by URL from form.
* Then displays edit card.
*
* @param {Event} e An event object containing form inputs and parameters.
* @returns {Card}
*/
function submitForm(e) {
var res = e['formInput'];
try {
FIELDNAMES.forEach(function(fieldName) {
if (! res[fieldName]) {
throw 'incomplete form';
}
});
var sheet = SpreadsheetApp
.openByUrl((res['Spreadsheet URL']))
.getActiveSheet();
sheet.appendRow(objToArray(res, FIELDNAMES.slice(0, FIELDNAMES.length - 1)));
return createExpensesCard(null, 'Logged expense successfully!').build();
}
catch (err) {
if (err == 'Exception: Invalid argument: url') {
err = 'Invalid URL';
res['Spreadsheet URL'] = null;
}
return createExpensesCard(objToArray(res, FIELDNAMES), 'Error: ' + err).build();
}
}
/**
* Returns an array corresponding to the given object and desired ordering of keys.
*
* @param {Object} obj Object whose values will be returned as an array.
* @param {String[]} keys An array of key names in the desired order.
* @returns {Object[]}
*/
function objToArray(obj, keys) {
return keys.map(function(key) {
return obj[key];
});
}
- أنشئ تطبيقًا مصغّرًا لمجموعة أزرار باستخدام
CardService.newButtonSet()وأضِف زر النص إلى مجموعة الأزرار باستخدامCardService.ButtonSet.addButton(). - أضِف أداة مجموعة الأزرار إلى قسم النموذج في البطاقة باستخدام
CardService.CardSection.addWidget().
في بضعة أسطر من الرمز البرمجي فقط، يمكننا فتح جدول بيانات من خلال عنوان URL الخاص به ثم إضافة صف من البيانات إلى ورقة البيانات هذه. يُرجى العِلم أنّه يتم تمرير إدخالات النموذج إلى الدالة كجزء من الحدث e، ونتأكّد من أنّ المستخدم قد قدّم جميع الحقول. بافتراض عدم حدوث أي أخطاء، ننشئ بطاقة نفقات فارغة بحالة إيجابية. في حال رصدنا خطأً، سنعيد البطاقة الأصلية التي تم ملؤها مع رسالة الخطأ. تسهّل الدالة المساعدة objToArray تحويل ردود النموذج إلى مصفوفة، والتي يمكن بعد ذلك إلحاقها بجدول البيانات.
أخيرًا، عدِّل القسم oauthScopes في appsscript.json مرة أخرى لطلب النطاق https://www.googleapis.com/auth/spreadsheets. عند منح هذا النطاق الإذن، يمكن للإضافة قراءة جداول بيانات Google الخاصة بالمستخدم وتعديلها.
"oauthScopes": [
"https://www.googleapis.com/auth/gmail.addons.execute",
"https://www.googleapis.com/auth/gmail.addons.current.message.readonly",
"https://www.googleapis.com/auth/spreadsheets"
],
إذا لم يسبق لك إنشاء جدول بيانات جديد، يمكنك إنشاء جدول بيانات على https://docs.google.com/spreadsheets/.
أعِد تشغيل الإضافة وحاوِل إرسال النموذج. تأكَّد من إدخال عنوان URL الكامل لعنوان URL المقصود في حقل نموذج عنوان URL لجدول البيانات.
6. تخزين القيم باستخدام خدمة "الخصائص"
في كثير من الأحيان، يسجّل المستخدمون العديد من النفقات في جدول البيانات نفسه، لذا سيكون من الملائم تقديم عنوان URL لجدول البيانات الأخير كقيمة تلقائية في البطاقة. لمعرفة عنوان URL الأحدث لجدول البيانات، علينا تخزين هذه المعلومات في كل مرة يتم فيها استخدام الإضافة.
تتيح لنا خدمة الخصائص تخزين أزواج المفتاح/القيمة. في حالتنا، سيكون المفتاح المناسب هو "SPREADSHEET_URL"، بينما ستكون القيمة هي عنوان URL نفسه. لتخزين هذه القيمة، عليك تعديل submitForm في Cards.gs بحيث يتم تخزين عنوان URL لجدول البيانات كخاصية عند إضافة صف جديد إلى ورقة البيانات.
يُرجى العِلم أنّه يمكن أن تتضمّن المواقع أحد النطاقات الثلاثة التالية: النص البرمجي أو المستخدم أو المستند. لا ينطبق نطاق المستند على إضافة ميزات Gmail، على الرغم من أنّه ذو صلة بنوع منفصل من الإضافات عند تخزين معلومات خاصة بمستند Google أو جدول بيانات معيّن. بالنسبة إلى الإضافة، السلوك المطلوب هو أن يرى المستخدم جدول البيانات الأخير الخاص به (بدلاً من جدول بيانات مستخدم آخر) كخيار تلقائي في النموذج. نتيجةً لذلك، نختار نطاق المستخدم بدلاً من نطاق النص البرمجي.
استخدِم PropertiesService.getUserProperties().setProperty() لتخزين عنوان URL لجدول البيانات. أضِف ما يلي إلى submitForm في Cards.gs:
PropertiesService.getUserProperties().setProperty('SPREADSHEET_URL',
res['Spreadsheet URL']);
بعد ذلك، عدِّل الدالة getSheetUrl في Helpers.gs لعرض الموقع المخزَّن كي يرى المستخدم أحدث عنوان URL في كل مرة يستخدم فيها الإضافة. استخدِم PropertiesService.getUserProperties().getProperty() للحصول على قيمة السمة.
/**
* Determines most recent spreadsheet URL.
* Returns null if no URL was previously submitted.
*
* @returns {String}
*/
function getSheetUrl() {
return PropertiesService.getUserProperties().getProperty('SPREADSHEET_URL');
}
أخيرًا، للوصول إلى خدمة "السمة"، يجب أيضًا منح الإذن للبرنامج النصي. أضِف النطاق https://www.googleapis.com/auth/script.storage إلى ملف البيان كما كان من قبل للسماح للإضافة بقراءة معلومات الموقع وكتابتها.
7. تحليل رسالة Gmail
لتوفير وقت المستخدمين، لنملأ النموذج مسبقًا بالمعلومات ذات الصلة حول النفقات من الرسالة الإلكترونية. لقد أنشأنا بالفعل دوال في Helpers.gs تؤدي هذا الدور، ولكن حتى الآن لم نعرض سوى "TODO" للتاريخ والمبلغ ووصف النفقات.
على سبيل المثال، يمكننا الحصول على تاريخ استلام الرسالة الإلكترونية واستخدامه كقيمة تلقائية لتاريخ النفقات.
/**
* Determines date the email was received.
*
* @param {Message} message - The message currently open.
* @returns {String}
*/
function getReceivedDate(message) {
return message.getDate().toLocaleDateString();
}
نفِّذ الدالتَين المتبقّيتَين:
- قد يتضمّن
getExpenseDescriptionدمج اسم المُرسِل وموضوع الرسالة، على الرغم من وجود طرق أكثر تطورًا لتحليل نص الرسالة وتقديم وصف أكثر دقة. - بالنسبة إلى
getLargestAmount، ننصحك بالبحث عن رموز معيّنة مرتبطة بالمال. تحتوي الإيصالات غالبًا على قيم متعددة، مثل الضرائب والرسوم الأخرى. فكِّر في الطريقة التي يمكنك من خلالها تحديد المبلغ الصحيح. قد تكون التعبيرات العادية مفيدة أيضًا.
إذا كنت بحاجة إلى بعض الأفكار الإضافية، يمكنك استكشاف المستندات المرجعية الخاصة بـ GmailMessage أو الاطّلاع على رمز الحل الذي نزّلته في بداية الدرس التطبيقي حول الترميز. بعد أن تضع تصاميمك الخاصة لجميع الدوال في Helpers.gs، يمكنك تجربة الإضافة. افتح الإيصالات وابدأ في تسجيلها في جدول بيانات.
8. محو النموذج باستخدام إجراءات البطاقة
ماذا يحدث إذا أخطأ تطبيق Expense It! في تحديد النفقات في رسالة إلكترونية مفتوحة وملأ النموذج مسبقًا بمعلومات غير صحيحة؟ يمحو المستخدم النموذج. يتيح لنا صف CardAction تحديد دالة يتم استدعاؤها عند النقر على الإجراء. لنستخدِمها لمنح المستخدم طريقة سريعة لمحو النموذج.
عدِّل createExpensesCard بحيث تحتوي البطاقة التي تعرضها على إجراء بطاقة بعنوان "محو النموذج"، وعند النقر عليه يتم استدعاء الدالة clearForm التالية التي يمكنك لصقها في Cards.gs. عليك تمرير opt_status كمَعلمة باسم "الحالة" إلى الإجراء للتأكّد من بقاء رسالة الحالة عند محو النموذج. يُرجى العِلم أنّ المَعلمات الاختيارية للإجراءات يجب أن تكون من النوع Object.<string, string>، لذا إذا لم يكن opt_status متاحًا، عليك تمرير {'Status' : ''}.
/**
* Recreates the main card without prefilled data.
*
* @param {Event} e An event object containing form inputs and parameters.
* @returns {Card}
*/
function clearForm(e) {
return createExpensesCard(null, e['parameters']['Status']).build();
}
9- إنشاء جدول بيانات
بالإضافة إلى استخدام برمجة تطبيقات Google لتعديل جدول بيانات حالي، يمكنك إنشاء جدول بيانات جديد تمامًا آليًا. بالنسبة إلى الإضافة، لنسمح للمستخدم بإنشاء جدول بيانات خاص بالمصروفات. للبدء، أضِف قسم البطاقة التالي إلى البطاقة التي تعرضها الدالة createExpensesCard.
var newSheetSection = CardService.newCardSection();
var sheetName = CardService.newTextInput()
.setFieldName('Sheet Name')
.setTitle('Sheet Name');
var createExpensesSheet = CardService.newAction()
.setFunctionName('createExpensesSheet');
var newSheetButton = CardService.newTextButton()
.setText('New Sheet')
.setOnClickAction(createExpensesSheet);
newSheetSection.addWidget(sheetName);
newSheetSection.addWidget(CardService.newButtonSet().addButton(newSheetButton));
card.addSection(newSheetSection);
الآن، عندما ينقر المستخدم على الزر "ورقة جديدة"، تنشئ الإضافة جدول بيانات جديدًا منسّقًا مع صف عنوان ثابت يظهر دائمًا. يحدّد المستخدم عنوانًا لجدول البيانات الجديد في النموذج، على الرغم من أنّ تضمين قيمة تلقائية في حال كان النموذج فارغًا قد يكون خيارًا جيدًا. في عملية تنفيذ createExpensesSheet، أعِد بطاقة مطابقة تقريبًا للبطاقة الحالية، مع إضافة رسالة حالة مناسبة بالإضافة إلى ملء حقل عنوان URL مسبقًا بعنوان URL لجدول البيانات الجديد.
10. تهانينا!
لقد نجحت في تصميم وتنفيذ إضافة ميزات Gmail التي تعثر على نفقات في رسالة إلكترونية وتساعد المستخدمين في تسجيل النفقات في جدول بيانات في غضون ثوانٍ معدودة. لقد استخدمت "برمجة تطبيقات Google" للتفاعل مع عدة واجهات برمجة تطبيقات من Google والاحتفاظ بالبيانات بين عمليات تنفيذ متعددة للإضافة.
التحسينات المحتملة
استند إلى مخيلتك في تحسين تطبيق Expense It!، ولكن إليك بعض الأفكار لإنشاء منتج أكثر فائدة:
- رابط إلى جدول البيانات بعد أن يسجّل المستخدم نفقة
- إضافة إمكانية تعديل أو التراجع عن تسجيل نفقة
- دمج واجهات برمجة التطبيقات الخارجية للسماح للمستخدمين بإجراء عمليات الدفع وطلب الأموال