Skrip Google Apps Untuk Pengaya

Mari kita kembangkan Google Drive dengan Apps Script untuk membuat add-on sederhana, gunakan CardService untuk UI, di mana kita akan memilih beberapa spreadsheet dan meneruskannya ke kartu berikutnya dengan navigasi. Anda dapat menemukan blog saya yang lain di Google Apps Scripts tepat di sini.

Pendahuluan

Hai, Ini Nibes Khadka, dari Coding Lounge Khadka. Saya menulis blog ini karena menurut saya pribadi dokumentasinya sangat banyak untuk pemula. Juga sangat sulit menemukan blog dengan skrip aplikasi Google. Jadi, blog tingkat pemula ini dibuat untuk membantu Anda memulai. Saya yakin blog ini akan memberi Anda hampir 20% yang Anda perlukan untuk menyelesaikan hampir 80% proyek Anda.

Prasyarat

Anda memerlukan pengetahuan tentang JavaScript dan Akses ke Google Drive. Saya menggunakan ide skrip aplikasi, tetapi jika Anda ingin mengembangkannya di lingkungan lokal, panduan "penyiapan" ini akan berguna bagi Anda.

Pengaturan

Buka dasbor, dan buat file skrip baru untuk proyek tersebut. Setelah itu, kita perlu mempersiapkan proyek kita seperti yang diinstruksikan di bawah ini.

Halaman Beranda

Menurut dokumentasi, ada dua jenis beranda saat Anda mengembangkan add-on untuk drive: Kontekstual dan Non-Kontekstual.

Non-Kontekstual adalah tampilan awal ketika tidak terjadi apa-apa seperti layar pertama yang ditampilkan setelah ikon add-on diklik. Kontekstual adalah halaman beranda/tampilan yang muncul setelah kita melakukan tindakan tertentu seperti memilih file di drive.

Agar fungsi skrip aplikasi dipanggil di drive, kita perlu menetapkan fungsi tersebut ke pemicu yang sesuai untuk add-on drive di file manifes (appsscript.json).

Pemicu Beranda

Saat pengguna mengklik ikon add-on, metode drive.homepageTrigger dipanggil. Metode ini kemudian mencari suatu fungsi kemudian memanggil fungsi yang ditentukan dalam manifes (appsscript.json) untuk operasi lebih lanjut.

Pemicu Item yang Dipilih

Untuk pemicu kontekstual, kami akan menetapkan fungsi dalam skrip aplikasi kami ke drive.onItemSelectedTrigger di file manifes.

Lingkup Oauth

Agar add-on drive berfungsi, pengguna harus memberikan izin akses. Daftar izin dikenal sebagai Cakupan. Detail tentang cakupan khusus drive dapat ditemukan di sini. Kita perlu menyediakan cakupan lagi di file appsscript.json sebagai daftar dengan "oauthScopes".

Catatan: Jika file appsscript.json Anda disembunyikan, buka pengaturan, lalu centang kotak centang Tampilkan file manifes “appsscript.json” di editor.

Lihat file manifes untuk proyek ini di bawah.

{
 "timeZone": "Asia/Kathmandu",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
  "oauthScopes": [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/script.storage",
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/drive.addons.metadata.readonly"
  ],
  "addOns": {
    "common": {
      "name": "Drive Extension with Apps Script",
      "logoUrl": "provide image URL to be used as logo",
      "layoutProperties": {
        "primaryColor": "#41f470",
        "secondaryColor": "#ab2699"
      }
    },
    "drive": {
      "homepageTrigger": {
        "runFunction": "onDriveHomePageOpen",
        "enabled": true
      },
      "onItemsSelectedTrigger": {
        "runFunction": "onDriveItemsSelected"
      }
    }
  }
}

Menggunakan Skrip Aplikasi untuk Mengakses Google Drive

Sekarang, di folder proyek root buat dua file, kartu dan utama.

Menetapkan Fungsi Skrip Aplikasi ke Pemicu

utama

// On homepage trigger function
let onDriveHomePageOpen = () => homepageCard();
// On Item selected Trigger function
let onDriveItemsSelected = (e) => itemSelectedCard(e);

onDriveHomePageOpen dan onDriveItemsSelected adalah dua fungsi yang kami tetapkan di file manifes sebelumnya. Fungsi-fungsi ini pada gilirannya memanggil fungsi-fungsi lain yang akan kita buat sebentar lagi. Jika Anda mendapatkan pesan kesalahan saat menyimpan file, abaikan saja untuk saat ini.

Merancang Perilaku Kartu

Mari kita buat kartu beranda sederhana untuk ditetapkan ke pemicu non-kontekstual pada file kartu.

Buat Kartu Beranda

let homepageCard = () => {
// Create a card with a header section
  let card = CardService.newCardBuilder().setHeader(CardService.newCardHeader());
// create card section 
  let section = CardService.newCardSection();
// add heading 
  let decoratedText = CardService.newDecoratedText()
    .setText("Select Files To Update");
// add text as a widget to the card section
  section.addWidget(decoratedText);
// add the section to the card 
  card.addSection(section);
// return card as build
  return card.build();
}

Kartu dapat digunakan untuk membuat UI untuk add-on untuk Google Drive.

Ini adalah blog pemula jadi saya tidak fokus pada penataan gaya.

Buat Kartu Non-Kontekstual

Sekarang, mari kita punya kartu lain yang akan menjadi tanggung jawab kita untuk pemicu kontekstual pada file yang sama. Namun mari kita bagi kode ini menjadi beberapa bagian agar dapat dipahami dengan jelas.

1. Buat UI kartu sederhana.

let itemSelectedCard = (e) => {
  // Initial UI
  let card = CardService.newCardBuilder().setHeader(CardService.newCardHeader().setTitle("Select Sheets Update Master Sheet"));
  let filesSection = CardService.newCardSection()
  filesSection.setHeader("Selected Files");
  return card.build();
}

2. Tampilkan file yang Dipilih di UI.

let itemSelectedCard = (e) => {
  // Initial UI
  let card = CardService.newCardBuilder().setHeader(CardService.newCardHeader().setTitle("Select Sheets Update Master Sheet"));
  let filesSection = CardService.newCardSection()
  filesSection.setHeader("Selected Files");
 // New Code starts here 
// # 1
// Create a new array to hold selected files and data
  let selectedSheets = [];
// #2
// Fetch selected files data from drive through event objects
  if (e.drive.selectedItems.length > 0) {
    // Selected spreadsheets
// #3
// Among the selected items we'll be selecting only spreadsheets and push them to selected sheets
    e.drive.selectedItems.forEach(item => {
      if (item.mimeType === "application/vnd.google-apps.spreadsheet")
        selectedSheets.push(item)
    }
    );
  }
  // Create a counter to count the number of widgets added
// #4
// COunter is required to prevent error when pushing the file names into UI incase array is empty
  let widgetCounter = 0;
  for (let i = 0; i < selectedSheets.length; i++) {
    // #5
    // Create decorated text with selected files and 
    // add the decorated text to the card section
    filesSection.addWidget(CardService.newDecoratedText()
      //.setText(selectedSheets[i].title)
      .setText(e.drive.selectedItems[0].title)
    );
 // Increase widget counter per loop
 // #4
    widgetCounter += 1;
  }
  // #6
  // Add files as widgets only if widgetCounter is 1+
  //  It prevent error in case only non-spreadsheet files are selected 
  if (widgetCounter >= 1) {
    card.addSection(filesSection)
 }
  // Create Another card that has files list 
  return card.build();
}

Di sini (lihat kode penomoran seperti #1),

  1. Membuat array untuk menyimpan data pada item yang dipilih.
  2. Menggunakan "objek acara drive" untuk mengambil data pada file yang dipilih.
  3. Di antara item yang dipilih, kami hanya memfilter spreadsheet menggunakan mimeType.
  4. Kami membuat penghitung untuk digunakan sebagai kondisi sambil menambahkan file sebagai widget di kartu untuk mencegah kesalahan.
  5. Membuat teks yang dihias, sebuah widget, yang akan menampung nama file dari setiap file.
  6. Sekarang akhirnya menambahkan seluruh bagian file ke pembuat kartu.

Hasilkan Tindakan Dengan Tombol

Di Card, interaktivitas dimungkinkan dengan tindakan. Juga, periksa kode contoh ini. Jangan lupa untuk menambahkan cakupan yang diberikan di sana, untuk mengarahkan cakupan pada file manifes Anda.

Mari tambahkan tombol di bawah bagian file. Tombol ini akan mengumpulkan file yang dipilih dan meneruskannya ke kartu lain yang akan kita buat nanti. Untuk mengurangi kerumitannya, saya akan memecah kode menjadi beberapa bagian yang lebih kecil.

1. Buat Ui Tombol dengan Aksi

let nxtButtonSection = CardService.newCardSection();
  let nxtButtonAction = CardService.newAction()
    .setFunctionName("handleNextButtonClick");

Anda telah memperhatikan bahwa handleNextButtonClick telah ditetapkan sebagai fungsi yang dipicu saat tombol diklik. Ini akan menangani navigasi, dan menunjuk ke arah kartu berikutnya. Kami akan membuat fungsi ini nanti.

2. Tetapkan Parameter yang akan diteruskan.

// We'll pass only pass ids of files to the next card so that we can fetch them there with id
// #1
  let selectedSheetsIDAsStr = selectedSheets.map(item => item.id).join();
// pass the values as params
// #2
  nxtButtonAction.setParameters({
    "nextCard": "nextCard",
    "selectedSheetsIDAsStr": selectedSheetsIDAsStr,
  });
// add button to the button set 
// #3
  let nxtButton = CardService.newTextButton().setText("Next").setOnClickAction(nxtButtonAction);
  let nxtButtonSet = CardService.newButtonSet().addButton(nxtButton);

Di kartu, parameter harus diteruskan melalui tindakan dengan metode setParameters sebagai objek (#2). Penting untuk diingat bahwa kunci dan nilai harus berupa string (karenanya #1). Tombol dapat ditambahkan sebagai kumpulan tombol di kartu (#3).

Anda telah memperhatikan bahwa nextCard telah ditetapkan sebagai parameter. Itu karena fungsi handleNextButtonClick adalah fungsi umum yang menggunakan nama kartu sebagai parameter, bukan hardcoding. Dengan cara ini akan lebih efisien dalam jangka panjang.

Tambahkan Tombol Ke Kartu

//  It prevent error in case only non-spreadsheet files are selected 
  if (widgetCounter >= 1) {
    card.addSection(filesSection)
    // new line
    nxtButtonSection.addWidget(nxtButtonSet);
    card.addSection(nxtButtonSection);
  }

Navigasi Kartu

Dari apa yang saya pahami, "navigasi kartu", singkatnya, mengambil daftar kartu sebagai tumpukan. Kartu baru untuk dinavigasi ditambahkan ke bagian atas tumpukan, sedangkan kartu dikeluarkan dari tumpukan untuk kembali ke kartu sebelumnya.

Mari buat file baru, saya beri nama helper, dan tambahkan instruksi berikut.

pembantu

/* This is a greneral nav function
You use it with card action and as a response, it will supply card functions from cardsInventory */
let handleNextButtonClick = (e) => {
// #1
// Extract string nextCard to pass it as key in cards inventory obj
  let nxtCard = cardsInventory[e.commonEventObject.parameters.nextCard];
  // #2
  // Convert String into List of files selected by the user
  let selectFilesIdList = e.commonEventObject.parameters['selectedSheetsIDAsStr'].split(",");
// #3
// use actionResponse to create a navigation route to the next card
  let nxtActionResponse = CardService.newActionResponseBuilder()
    .setNavigation(CardService.newNavigation().pushCard(nxtCard(selectFilesIdList))) // #4, Passing the mastersheet with params
    .setStateChanged(true)
    .build();
  return nxtActionResponse;
}

/**
 *  Create a dictionary that
 is consist of cards for navigation with appropriate keys  
 */
var cardsInventory = {
  'nextCard': nextCard
}

Mari kita bahas dulu tentang objek cardsInventory. Jika Anda ingat, kami meneruskan parameter nextCard sebelumnya sebagai string dalam fungsi itemSelectedCard. NextCard ini adalah fungsi yang akan kita buat selanjutnya. Tapi masalahnya adalah Anda tidak bisa meneruskan string dan menggunakannya untuk mereferensikan variabel (centang #1 pada kode). Jadi, kami membuat kamus yang akan mencocokkan tombol yang sesuai dengan fungsi navigasi.

Di dalam fungsi handleNextButtonClick:

  1. Ekstrak string yang merupakan kunci objek cardInventory untuk mengambil kartu yang tepat untuk dipanggil. Kami menggunakan Events Comment Object untuk mengekstrak parameter yang diteruskan sebelumnya.
  2. String yang diteruskan sebagai id file yang dipilih, kami mengubahnya lagi menjadi array.
  3. Gabungan "NewActionResponseBuilder, SetNavigation, NewNavigation, dan PushCard" digunakan untuk menetapkan "jalur" baru ke kartu pilihan kita.
  4. Di sini, kami meneruskan daftar id sebagai params.

Kartu Berikutnya Untuk Dinavigasi

Kami akan membuat kartu yang sangat sederhana untuk menampilkan daftar ID, untuk memberi tahu kami bahwa kode kami berfungsi.

Pertama, mari buat file baru next_card.

var nextCard = function (lst) {
  let cardService = CardService.newCardBuilder().setHeader(CardService.newCardHeader().setTitle("Select Master Sheet To Update"));
  let filesSection = CardService.newCardSection();
  filesSection.setHeader("Selected Files");
  let widgetCounter = 0;
  let selectedFilesList = [...lst];
  selectedFilesList.forEach(id => {
    filesSection.addWidget(CardService.newDecoratedText()
      .setText(id));
    widgetCounter += 1;
  });
  if (widgetCounter >= 1) {
    cardService.addSection(filesSection);
  }

  return cardService.build();
}

Satu-satunya hal baru yang perlu diperhatikan di sini adalah saya tidak menggunakan sintaks es6 untuk mendeklarasikan suatu fungsi. Itu karena penggunaannya menyebabkan masalah pelingkupan dan kesalahan, fungsi tidak ditentukan. Oleh karena itu, saya bersekolah di sekolah lama dengan var.

Publikasikan Add-On di GCP untuk Pengujian

Untuk memublikasikan add-on ke GCP, ikuti dua petunjuk berikut di sini.

  1. Buat proyek GCP standar.
  2. Integrasikan proyek dengan proyek skrip aplikasi.

Kode Akhir

kartu

let itemSelectedCard = (e) => {
  // Initial UI
  let card = CardService.newCardBuilder().setHeader(CardService.newCardHeader().setTitle("Select Sheets Update Master Sheet"));
  let filesSection = CardService.newCardSection()
  filesSection.setHeader("Selected Files");
  let nxtButtonSection = CardService.newCardSection();
  let nxtButtonAction = CardService.newAction()
    .setFunctionName("handleNextButtonClick");
  let selectedSheets = [];
  if (e.drive.selectedItems.length > 0) {
    // hostApp,clientPlatform,drive,commonEventObject
    // Selected spreadsheets
    e.drive.selectedItems.forEach(item => {
      if (item.mimeType === "application/vnd.google-apps.spreadsheet")
        selectedSheets.push(item)
    }
    );
  }
  // Create a counter to count number of widgets added
  let widgetCounter = 0;
  for (let i = 0; i < selectedSheets.length; i++) {
    // Create decorated text with selected files and 
    // add the decorated text to card section
    filesSection.addWidget(CardService.newDecoratedText()
      //.setText(selectedSheets[i].title)
      .setText(e.drive.selectedItems[0].title)
    );
    widgetCounter += 1;
  }

  // Change list of  selected sheet's id  as string to pass to next card 
  let selectedSheetsIDAsStr = selectedSheets.map(item => item.id).join();
  nxtButtonAction.setParameters({
    "nextCard": "nextCard",
    "selectedSheetsIDAsStr": selectedSheetsIDAsStr,
  });
  let nxtButton = CardService.newTextButton().setText("Next").setOnClickAction(nxtButtonAction);
  let nxtButtonSet = CardService.newButtonSet().addButton(nxtButton);

  // Add files and button section only if the widgets are present
  //  It prevent error in case only non-spreadsheet files are selected 
  if (widgetCounter >= 1) {
    card.addSection(filesSection)
    nxtButtonSection.addWidget(nxtButtonSet);
    card.addSection(nxtButtonSection);
  }
  // Create Another card that has files list 
  return card.build();
}

pembantu

/* THis is a greneral nav function
You use it with card action and as reponse it will supply card functions from cardsInventory */
let handleNextButtonClick = (e) => {
  let nextCard = cardsInventory[e.commonEventObject.parameters.nextCard];
  console.log(nextCard)
  // Convert String into List
  let selectFilesIdList = e.commonEventObject.parameters['selectedSheetsIDAsStr'].split(",");
  let nxtActionResponse = CardService.newActionResponseBuilder()
    .setNavigation(CardService.newNavigation().pushCard(nextCard(selectFilesIdList)))
    .setStateChanged(true)
    .build();
  return nxtActionResponse;
}

/**
 *  Create a dictionary that
 is consist of cards for navigation with appropriate keys  
 */
var cardsInventory = {
  'nextCard': nextCard
}

Ringkasan

Baiklah, mari kita mengingat kembali hal-hal yang kita lakukan dalam proyek ini.

  1. File appscrits.json yang ditentukan dengan cakupan dan pemicu yang sesuai yang diperlukan untuk Add-on Drive.
  2. Membuat UI kartu sederhana untuk berinteraksi dengan pengguna.
  3. Mengambil file yang dipilih dari drive dengan skrip aplikasi.
  4. Menggunakan Tindakan dan Kumpulan Tombol untuk memungkinkan pengguna berinteraksi dengan UI kartu kami.
  5. Membuat logika navigasi sederhana untuk berpindah di antara dua kartu.

Tunjukkan Beberapa Dukungan

Ini Nibesh Khadka dari Coding Lounge Khadka. Temukan blog saya yang lain di Skrip Google Apps di sini. Saya adalah pemilik Khadka's Coding Lounge. Kami membuat situs web, aplikasi seluler, add-on Google, dan blog teknologi yang berharga. Pekerjakan kami!, Sukai, Bagikan, dan Berlangganan buletin kami.