Giúp email trở nên hữu ích hơn bằng các tiện ích bổ sung của Google Workspace

1. Tổng quan

Trong lớp học lập trình này, bạn sẽ sử dụng Google Apps Script để viết một Tiện ích bổ sung của Google Workspace cho Gmail. Tiện ích này giúp người dùng thêm dữ liệu biên nhận từ email vào bảng tính ngay trong Gmail. Khi nhận được biên nhận qua email, người dùng sẽ mở tiện ích bổ sung và tự động nhận thông tin chi phí liên quan qua email. Người dùng có thể chỉnh sửa thông tin chi phí rồi gửi thông tin đó để ghi lại chi phí vào một bảng tính Google Trang tính.

Kiến thức bạn sẽ học được

  • Tạo một tiện ích bổ sung của Google Workspace cho Gmail bằng Google Apps Script
  • Phân tích cú pháp email bằng Google Apps Script
  • Tương tác với Google Trang tính qua Google Apps Script
  • Lưu trữ giá trị người dùng bằng dịch vụ Thuộc tính của Google Apps Script

Bạn cần có

  • Quyền truy cập vào Internet và trình duyệt web
  • Tài khoản Google
  • Một số thư, tốt nhất là biên nhận qua email, trong Gmail

2. Nhận mã mẫu

Khi thực hiện lớp học lập trình này, bạn nên tham khảo phiên bản đang hoạt động của mã bạn sẽ viết. Kho lưu trữ GitHub chứa mã mẫu mà bạn có thể dùng làm tài liệu tham khảo.

Để lấy mã mẫu, trong dòng lệnh, hãy chạy mã:

git clone https://github.com/googleworkspace/gmail-add-on-codelab.git

3. Tạo tiện ích bổ sung cơ bản

Bắt đầu bằng cách viết mã cho phiên bản đơn giản của tiện ích bổ sung hiển thị biểu mẫu chi phí cùng với email.

Trước tiên, hãy tạo một dự án Apps Script mới và mở tệp kê khai của dự án đó.

  1. Truy cập vào script.google.com. Tại đây, bạn có thể tạo, quản lý và giám sát các dự án Apps Script của mình.
  2. Để tạo một dự án mới, ở trên cùng bên trái, hãy nhấp vào New Project (Dự án mới). Dự án mới sẽ mở ra với một tệp mặc định có tên Code.gs. Bây giờ, hãy để Code.gs yên, bạn sẽ xử lý sau.
  3. Nhấp vào Dự án không có tiêu đề, đặt tên cho dự án là Expense It!, rồi nhấp vào Đổi tên.
  4. Ở bên trái, hãy nhấp vào biểu tượng Cài đặt dự án Cài đặt dự án.
  5. Chọn tệp Hiển thị "appscript.json" tệp kê khai trong trình chỉnh sửa".
  6. Nhấp vào biểu tượng Trình chỉnh sửa Người chỉnh sửa.
  7. Để mở tệp kê khai, hãy nhấp vào biểu tượng appscript.json ở bên trái.

Trong appscript.json, hãy chỉ định siêu dữ liệu liên kết với tiện ích bổ sung, chẳng hạn như tên và các quyền mà tiện ích bổ sung yêu cầu. Thay thế nội dung của appsscript.json bằng các chế độ cài đặt cấu hình sau:

{
  "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"
  }
}

Đặc biệt chú ý đến phần tệp kê khai có tên là contextualTriggers. Phần này của tệp kê khai xác định hàm do người dùng xác định cần gọi khi tiện ích bổ sung được kích hoạt lần đầu tiên. Trong trường hợp này, lệnh gọi getContextualAddOn để nhận thông tin chi tiết về email bạn đang mở và trả về một bộ thẻ để hiển thị cho người dùng.

Để tạo hàm getContextualAddOn, hãy làm theo các bước sau:

  1. Ở bên trái, hãy giữ con trỏ trên Code.gs, sau đó nhấp vào biểu tượng Trình đơn Trình đơn Thêm > Đổi tên.
  2. Nhập GetContextualAddOn rồi nhấn phím Enter. Apps Script tự động thêm .gs vào tên tệp, do đó, bạn không cần phải nhập đuôi tệp. Nếu bạn nhập GetContextualAddOn.gs thì Apps Script sẽ đặt tên cho tệp của bạn là GetContextualAddOn.gs.gs.
  3. Trong GetContextualAddOn.gs, hãy thay thế mã mặc định bằng hàm 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()];
}

Mọi giao diện người dùng của tiện ích bổ sung của Google Workspace đều bao gồm thẻ được chia thành một hoặc nhiều phần, mỗi phần chứa các tiện ích có thể hiển thị và nhận thông tin của người dùng. Hàm getContextualAddOn tạo một thẻ duy nhất chứa thông tin chi tiết về một khoản chi phí có trong email. Thẻ này có một mục chứa các trường nhập dữ liệu văn bản cho dữ liệu có liên quan. Hàm trả về một mảng thẻ của tiện ích bổ sung. Trong trường hợp này, mảng được trả về chỉ bao gồm một thẻ.

Trước khi triển khai Expense It! tiện ích bổ sung, bạn cần có một Dự án Google Cloud Platform (GCP) mà các dự án Apps Script dùng để quản lý hoạt động uỷ quyền, dịch vụ nâng cao và các thông tin chi tiết khác. Để tìm hiểu thêm, hãy truy cập vào phần Các dự án trên Google Cloud Platform.

Để triển khai và chạy tiện ích bổ sung, hãy làm theo các bước sau:

  1. Mở dự án GCP rồi sao chép số dự án của dự án đó.
  2. Trong dự án Apps Script, hãy nhấp vào biểu tượng Cài đặt dự án Cài đặt dự án ở bên trái.
  3. Trong phần "Dự án Google Cloud Platform (GCP)", hãy nhấp vào Thay đổi dự án.
  4. Nhập số dự án của dự án GCP, sau đó nhấp vào Đặt dự án.
  5. Nhấp vào Triển khai > Kiểm thử bản triển khai.
  6. Đảm bảo rằng loại triển khai là Tiện ích bổ sung của Google Workspace. Nếu cần, ở đầu hộp thoại, hãy nhấp vào Bật loại triển khai Bật các hình thức triển khai rồi chọn Tiện ích bổ sung của Google Workspace làm loại triển khai.
  7. Bên cạnh (Các) Ứng dụng: Gmail, hãy nhấp vào Cài đặt.
  8. Nhấp vào Xong.

Giờ đây, bạn có thể thấy tiện ích bổ sung này trong hộp thư đến của Gmail.

  1. Trên máy tính, hãy mở Gmail.
  2. Trên bảng điều khiển bên phải, mục Expense It! Tiện ích bổ sung Chi tiêu! biểu tượng biên nhận sẽ xuất hiện. Bạn có thể phải nhấp vào biểu tượng Tiện ích bổ sung khác Tiện ích bổ sung khác để tìm tiện ích này.
  3. Mở email, tốt nhất là biên nhận có thông tin chi phí.
  4. Để mở tiện ích bổ sung, trong bảng điều khiển bên phải, hãy nhấp vào Chi tiêu! Chi tiêu! biểu tượng biên nhận.
  5. Chi tiêu! truy cập vào Tài khoản Google của bạn bằng cách nhấp vào Uỷ quyền truy cập và làm theo lời nhắc.

Tiện ích bổ sung này hiển thị một biểu mẫu đơn giản cùng với thư đang mở trong Gmail. Hiện chưa có gì khác, nhưng bạn sẽ xây dựng chức năng của nó trong phần tiếp theo.

Để xem nội dung cập nhật cho tiện ích bổ sung của mình khi bạn tiếp tục thông qua phòng thí nghiệm này, bạn chỉ cần lưu mã của mình và làm mới Gmail. Bạn không cần triển khai thêm.

4. Truy cập vào nội dung email

Thêm mã tìm nạp nội dung email và mô-đun hoá mã để tổ chức tốt hơn.

Bên cạnh Tệp, hãy nhấp vào biểu tượng Thêm Thêm một tệp > Tập lệnh và tạo một tệp có tên Cards. Tạo tệp tập lệnh thứ hai có tên là Helpers. Cards.gs tạo thẻ và dùng các hàm của Helpers.gs để điền các trường vào biểu mẫu dựa trên nội dung email.

Thay thế mã mặc định trong Cards.gs bằng mã sau:

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;
}

Hàm createExpensesCard lấy một mảng các giá trị để điền sẵn vào biểu mẫu dưới dạng một đối số không bắt buộc. Hàm này có thể hiển thị thông báo trạng thái không bắt buộc, có màu đỏ nếu trạng thái bắt đầu bằng "Error:" và có màu xanh lục nếu trạng thái không bắt đầu bằng "Error:" (Lỗi:). Thay vì thêm từng trường vào biểu mẫu theo cách thủ công, hàm trợ giúp có tên là createFormSection sẽ lặp lại quy trình tạo tiện ích nhập văn bản, đặt từng giá trị mặc định bằng setValue, sau đó thêm tiện ích vào các phần tương ứng trên thẻ.

Bây giờ, hãy thay thế mã mặc định trong Helpers.gs bằng mã sau:

/**
 * 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';
}

Các hàm trong Helpers.gs được getContextualAddon gọi để xác định các giá trị điền sẵn trên biểu mẫu. Hiện tại, các hàm này sẽ chỉ trả về chuỗi "TODO" vì bạn sẽ triển khai logic điền sẵn trong bước sau.

Tiếp theo, hãy cập nhật mã trong GetContextualAddon.gs để tận dụng mã trong Cards.gsHelpers.gs. Thay thế mã trong GetContextualAddon.gs bằng mã sau:

/**
 * 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);
}

Hãy lưu ý rằng hàm getCurrentMessage mới. Hàm này sử dụng sự kiện do Gmail cung cấp để đọc thư hiện đang mở của người dùng. Để hàm này hoạt động, hãy thêm một phạm vi khác vào tệp kê khai tập lệnh để cho phép quyền chỉ có thể đọc đối với thư trong Gmail.

Trong appscript.json, hãy cập nhật oauthScopes để cũng yêu cầu phạm vi 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"
],

Trong Gmail, hãy chạy tiện ích bổ sung của bạn và cấp quyền truy cập cho Expense It! để xem email. Các trường trong biểu mẫu hiện đã được điền sẵn bằng "TODO".

5. Tương tác với Google Trang tính

Rất tốn kém! tiện ích bổ sung có biểu mẫu để người dùng nhập chi tiết về một khoản phí nhưng không có thông tin chi tiết nào ở đây. Hãy thêm một nút để gửi dữ liệu biểu mẫu tới Google Trang tính.

Để thêm một nút, chúng ta sẽ sử dụng lớp ButtonSet. Để tương tác với Google Trang tính, chúng ta sẽ sử dụng dịch vụ Google Trang tính.

Sửa đổi createFormSection để trả về một nút có nhãn "Gửi" trong phần biểu mẫu của thẻ. Hãy làm theo các bước sau:

  1. Tạo một nút văn bản bằng CardService.newTextButton(), gắn nhãn cho nút này là "Submit" (Gửi) đang sử dụng CardService.TextButton.setText().
  2. Hãy thiết kế nút này sao cho khi người dùng nhấp vào nút này, hành động submitForm sau đây sẽ được gọi qua 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];
  });
}
  1. Tạo tiện ích bộ nút bằng CardService.newButtonSet() và thêm nút văn bản vào bộ nút bằng CardService.ButtonSet.addButton().
  2. Thêm tiện ích tập hợp nút vào phần biểu mẫu của thẻ bằng cách sử dụng CardService.CardSection.addWidget().

Chỉ bằng vài dòng mã, chúng ta có thể mở bảng tính theo URL của bảng tính và sau đó thêm một hàng dữ liệu vào trang tính đó. Xin lưu ý rằng thông tin nhập vào biểu mẫu được chuyển vào hàm này như một phần của sự kiện e, đồng thời chúng ta sẽ kiểm tra để đảm bảo rằng người dùng đã cung cấp tất cả các trường. Giả sử không có lỗi nào xảy ra, chúng tôi sẽ tạo một thẻ chi phí trống với trạng thái tốt. Trong trường hợp phát hiện lỗi, chúng tôi sẽ trả về thẻ đã điền ban đầu cùng với thông báo lỗi. Hàm trợ giúp objToArray giúp bạn dễ dàng chuyển đổi câu trả lời của biểu mẫu thành một mảng, sau đó các mảng này có thể được thêm vào bảng tính.

Cuối cùng, hãy cập nhật phần oauthScopes trong appsscript.json một lần nữa để yêu cầu phạm vi https://www.googleapis.com/auth/spreadsheets. Khi được cho phép, phạm vi này sẽ cho phép tiện ích bổ sung đọc và sửa đổi Google Trang tính của người dùng.

"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"
],

Nếu bạn chưa tạo bảng tính mới, hãy tạo một bảng tính tại https://docs.google.com/spreadsheets/.

Bây giờ, hãy chạy lại tiện ích bổ sung và thử gửi biểu mẫu. Đảm bảo rằng bạn nhập URL đầy đủ của URL đích vào trường biểu mẫu URL bảng tính.

6. Lưu trữ giá trị bằng dịch vụ Thuộc tính

Thông thường, người dùng sẽ ghi nhiều chi phí vào cùng một bảng tính, do đó sẽ thuận tiện hơn khi cung cấp URL của bảng tính gần đây nhất làm giá trị mặc định trong thẻ. Để biết URL của bảng tính gần đây nhất, chúng tôi cần lưu trữ thông tin đó mỗi khi sử dụng tiện ích bổ sung.

Dịch vụ Tài sản cho phép chúng ta lưu trữ các cặp khoá-giá trị. Trong trường hợp của chúng ta, khoá hợp lý sẽ là "SPREADSHEET_URL" trong khi giá trị sẽ là chính URL đó. Để lưu trữ giá trị này, bạn cần sửa đổi submitForm trong Cards.gs để URL của bảng tính được lưu trữ dưới dạng thuộc tính khi thêm một hàng mới vào trang tính.

Xin lưu ý rằng tài sản có thể có một trong 3 phạm vi: tập lệnh, người dùng hoặc tài liệu. Phạm vi tài liệu không áp dụng cho tiện ích bổ sung dành cho Gmail, mặc dù phạm vi này liên quan đến một loại tiện ích bổ sung riêng biệt khi lưu trữ thông tin dành riêng cho một tệp Google Tài liệu hoặc Trang tính cụ thể. Đối với tiện ích bổ sung của chúng ta, hành vi mong muốn là để một cá nhân xem bảng tính gần đây nhất của mình (thay vì bảng tính gần đây nhất của người khác) dưới dạng tuỳ chọn mặc định trên biểu mẫu. Do đó, chúng tôi chọn phạm vi người dùng thay vì phạm vi tập lệnh.

Sử dụng PropertiesService.getUserProperties().setProperty() để lưu trữ URL bảng tính. Thêm các dòng sau vào submitForm trong Cards.gs:

PropertiesService.getUserProperties().setProperty('SPREADSHEET_URL', 
    res['Spreadsheet URL']);

Sau đó, hãy sửa đổi hàm getSheetUrl trong Helpers.gs để trả về thuộc tính được lưu trữ sao cho người dùng sẽ nhìn thấy URL gần đây nhất mỗi khi họ sử dụng tiện ích bổ sung. Sử dụng PropertiesService.getUserProperties().getProperty() để nhận giá trị của thuộc tính.

/**
 * Determines most recent spreadsheet URL.
 * Returns null if no URL was previously submitted.
 *
 * @returns {String}
 */
function getSheetUrl() {
  return PropertiesService.getUserProperties().getProperty('SPREADSHEET_URL');
}

Cuối cùng, để truy cập vào dịch vụ Thuộc tính, tập lệnh cũng cần được cấp quyền. Thêm phạm vi https://www.googleapis.com/auth/script.storage vào tệp kê khai như trước đây để cho phép tiện ích bổ sung của bạn đọc và ghi thông tin thuộc tính.

7. Phân tích cú pháp thư Gmail

Để thực sự tiết kiệm thời gian giờ, hãy điền sẵn thông tin liên quan đến các khoản chi phí này qua email vào biểu mẫu. Chúng ta đã tạo các hàm trong Helpers.gs đóng vai trò này, nhưng cho đến nay chúng ta chỉ trả về "TODO" đối với ngày, số tiền và nội dung mô tả chi phí.

Ví dụ: chúng tôi có thể lấy ngày nhận email và sử dụng ngày đó làm giá trị mặc định cho ngày phát sinh chi phí.

/**
 * Determines date the email was received.
 *
 * @param {Message} message - The message currently open.
 * @returns {String}
 */
function getReceivedDate(message) {
  return message.getDate().toLocaleDateString();
}

Triển khai hai hàm còn lại:

  1. getExpenseDescription có thể đòi hỏi phải kết hợp cả tên người gửi và chủ đề thư, mặc dù đã có nhiều cách tinh vi hơn để phân tích cú pháp nội dung thư và đưa ra nội dung mô tả chính xác hơn nữa.
  2. Đối với getLargestAmount, hãy cân nhắc việc tìm các biểu tượng liên quan đến tiền. Biên nhận thường có nhiều giá trị được liệt kê, chẳng hạn như thuế và các khoản phí khác. Hãy nghĩ cách xác định đúng số tiền bạn cần bỏ ra. Biểu thức chính quy cũng có thể hữu ích.

Nếu bạn cần thêm ý tưởng, hãy xem tài liệu tham khảo về GmailMessage hoặc xem đoạn mã giải pháp mà bạn đã tải xuống ở đầu lớp học lập trình này. Sau khi bạn nghĩ ra cách triển khai của riêng mình cho tất cả các hàm trong Helpers.gs, hãy dùng thử tiện ích bổ sung của bạn! Hãy mở biên nhận và bắt đầu ghi chúng vào một bảng tính!

8. Xóa biểu mẫu bằng các thao tác với thẻ

Điều gì sẽ xảy ra nếu Chi tiêu nó! xác định nhầm một khoản chi phí trong một email mở và điền sẵn thông tin không chính xác vào biểu mẫu? Người dùng xoá biểu mẫu. Lớp CardAction cho phép chúng ta chỉ định một hàm được gọi khi người dùng nhấp vào hành động đó. Hãy sử dụng thuộc tính này để giúp người dùng nhanh chóng xoá biểu mẫu.

Sửa đổi createExpensesCard để thẻ trả về có thao tác đối với thẻ được gắn nhãn "Xoá biểu mẫu" còn khi được nhấp vào, hàm này sẽ gọi hàm clearForm (bạn có thể dán vào Cards.gs). Bạn sẽ cần truyền opt_status dưới dạng một thông số có tên là "Status" (Trạng thái) vào hành động để đảm bảo rằng khi biểu mẫu bị xoá, thông báo trạng thái vẫn giữ nguyên. Lưu ý rằng các tham số không bắt buộc cho thao tác phải thuộc kiểu Đối tượng.<string, string>, vì vậy, nếu không có opt_status, bạn nên truyền {'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. Tạo bảng tính

Ngoài việc sử dụng Google Apps Script để chỉnh sửa bảng tính hiện có, bạn còn có thể tạo bảng tính hoàn toàn mới theo phương thức lập trình. Đối với tiện ích bổ sung, hãy cho phép người dùng tạo một bảng tính tính chi phí. Để bắt đầu, hãy thêm mục thẻ sau vào thẻ mà createExpensesCard trả về.

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);

Giờ đây, khi người dùng nhấp vào "Trang tính mới" nút tiện ích bổ sung sẽ tạo một bảng tính mới được định dạng với hàng tiêu đề được cố định để luôn hiển thị. Người dùng chỉ định tiêu đề cho bảng tính mới trong biểu mẫu, mặc dù việc đưa vào giá trị mặc định trong trường hợp biểu mẫu trống có thể là một lựa chọn phù hợp. Trong quá trình triển khai createExpensesSheet, hãy trả lại một thẻ gần giống với thẻ hiện có, đồng thời bổ sung một thông báo trạng thái thích hợp cũng như điền sẵn URL của bảng tính mới vào trường URL.

10. Xin chúc mừng!

Bạn đã thiết kế và triển khai thành công một tiện ích bổ sung của Gmail giúp tìm một khoản chi phí trong email và giúp người dùng ghi khoản chi phí đó vào bảng tính chỉ trong vài giây. Bạn đã sử dụng Google Apps Script để giao tiếp với nhiều API của Google và duy trì dữ liệu giữa nhiều lần thực thi tiện ích bổ sung.

Những điểm có thể cải thiện

Hãy để trí tưởng tượng của bạn dẫn dắt khi bạn cải tiến Chi phí!, nhưng sau đây là một số ý tưởng để tạo ra sản phẩm hữu ích hơn nữa:

  • Liên kết đến bảng tính sau khi người dùng đã ghi lại chi phí
  • Thêm khả năng chỉnh sửa/hoàn tác việc ghi nhật ký chi phí
  • Tích hợp API bên ngoài để cho phép người dùng thanh toán và yêu cầu tiền

Tìm hiểu thêm