เกี่ยวกับ Codelab นี้
1 บทนำ
ยินดีต้อนรับสู่ส่วนที่ 4 ของเพลย์ลิสต์ Codelab พื้นฐานของ Apps Script กับ Google ชีต
การทำ Codelab นี้จะช่วยให้คุณทราบวิธีจัดรูปแบบข้อมูลสเปรดชีตใน Apps Script และเขียนฟังก์ชันเพื่อสร้างสเปรดชีตที่มีการจัดระเบียบซึ่งเต็มไปด้วยข้อมูลที่จัดรูปแบบแล้วซึ่งดึงมาจาก API สาธารณะ
สิ่งที่คุณจะได้เรียนรู้
- วิธีใช้การจัดรูปแบบต่างๆ ของ Google ชีตใน Apps Script
- วิธีแปลงรายการออบเจ็กต์ JSON และแอตทริบิวต์ของออบเจ็กต์เหล่านั้นให้เป็นชีตข้อมูลที่มีการจัดระเบียบด้วย Apps Script
ก่อนเริ่มต้น
นี่คือโค้ดแล็บที่ 4 ในเพลย์ลิสต์พื้นฐานของ Apps Script กับ Google ชีต ก่อนเริ่ม Codelab นี้ โปรดทำ Codelab ก่อนหน้าให้เสร็จก่อน
สิ่งที่คุณต้องมี
- ความเข้าใจในหัวข้อพื้นฐานของ Apps Script ที่ได้เรียนรู้ใน Codelab ก่อนหน้าของเพลย์ลิสต์นี้
- คุ้นเคยกับเครื่องมือแก้ไข Apps Script ในระดับพื้นฐาน
- คุ้นเคยกับ Google ชีต ในระดับพื้นฐาน
- ความสามารถในการอ่านรูปแบบ A1 ของชีต
- มีความคุ้นเคยกับ JavaScript และคลาส
String
ในระดับพื้นฐาน
2 ตั้งค่า
ก่อนดำเนินการต่อ คุณต้องมีสเปรดชีตที่มีข้อมูลบางอย่าง เราได้จัดเตรียมชีตข้อมูลที่คุณสามารถคัดลอกเพื่อใช้ในการฝึกหัดเหล่านี้ไว้ให้แล้วเช่นเคย โปรดทำตามขั้นตอนต่อไปนี้
- คลิกลิงก์นี้เพื่อคัดลอกชีตข้อมูล แล้วคลิกทำสำเนา ระบบจะวางสเปรดชีตใหม่ไว้ในโฟลเดอร์ Google ไดรฟ์และตั้งชื่อว่า "สำเนาการจัดรูปแบบข้อมูล"
- คลิกชื่อสเปรดชีตและเปลี่ยนจาก "สำเนาการจัดรูปแบบข้อมูล" เป็น "การจัดรูปแบบข้อมูล" ชีตควรมีลักษณะดังนี้ โดยมีข้อมูลพื้นฐานเกี่ยวกับภาพยนตร์สตาร์วอร์ส 3 ภาคแรก
- เลือกส่วนขยาย> Apps Script เพื่อเปิดโปรแกรมแก้ไขสคริปต์
- คลิกชื่อโปรเจ็กต์ Apps Script แล้วเปลี่ยนจาก "โปรเจ็กต์ที่ไม่มีชื่อ" เป็น "การจัดรูปแบบข้อมูล" คลิกเปลี่ยนชื่อเพื่อบันทึกการเปลี่ยนชื่อ
เมื่อมีสเปรดชีตและโปรเจ็กต์นี้แล้ว คุณก็พร้อมที่จะเริ่ม Codelab ได้ ไปที่ส่วนถัดไปเพื่อเริ่มเรียนรู้เกี่ยวกับการจัดรูปแบบพื้นฐานใน Apps Script
3 สร้างเมนูที่กำหนดเอง
คุณใช้การจัดรูปแบบพื้นฐานหลายวิธีใน Apps Script กับชีตได้ แบบฝึกหัดต่อไปนี้จะแสดงวิธีจัดรูปแบบข้อมูลบางส่วน มาสร้างเมนูที่กำหนดเองซึ่งมีรายการที่คุณต้องการเพื่อช่วยควบคุมการดำเนินการจัดรูปแบบกัน กระบวนการสร้างเมนูที่กำหนดเองอธิบายไว้ใน Codelab การทำงานกับข้อมูล แต่เราจะสรุปอีกครั้งที่นี่
การใช้งาน
มาสร้างเมนูที่กำหนดเองกัน
- ในตัวแก้ไข Apps Script ให้แทนที่โค้ดในโปรเจ็กต์สคริปต์ด้วยโค้ดต่อไปนี้
/**
* A special function that runs when the spreadsheet is opened
* or reloaded, used to add a custom menu to the spreadsheet.
*/
function onOpen() {
// Get the spreadsheet's user-interface object.
var ui = SpreadsheetApp.getUi();
// Create and add a named menu and its items to the menu bar.
ui.createMenu('Quick formats')
.addItem('Format row header', 'formatRowHeader')
.addItem('Format column header', 'formatColumnHeader')
.addItem('Format dataset', 'formatDataset')
.addToUi();
}
- บันทึกโปรเจ็กต์สคริปต์
- ในตัวแก้ไขสคริปต์ ให้เลือก
onOpen
จากรายการฟังก์ชัน แล้วคลิกเรียกใช้ ซึ่งจะเรียกใช้onOpen()
เพื่อสร้างเมนูสเปรดชีตใหม่ คุณจึงไม่ต้องโหลดสเปรดชีตซ้ำ
การตรวจสอบโค้ด
มาดูโค้ดนี้เพื่อทำความเข้าใจวิธีการทำงานกัน ใน onOpen()
บรรทัดแรกใช้วิธี getUi()
เพื่อรับออบเจ็กต์ Ui
ที่แสดงอินเทอร์เฟซผู้ใช้ของสเปรดชีตที่ใช้งานอยู่ซึ่งสคริปต์นี้เชื่อมโยงอยู่
บรรทัดถัดไปจะสร้างเมนู (Quick formats
) เพิ่มรายการเมนู (Format row header
, Format column header
และ Format dataset
) ลงในเมนู แล้วเพิ่มเมนูลงในอินเทอร์เฟซของสเปรดชีต ซึ่งทำได้ด้วยเมธอด createMenu(caption)
, addItem(caption, functionName)
และ addToUi()
ตามลำดับ
เมธอด addItem(caption, functionName)
จะสร้างการเชื่อมต่อระหว่างป้ายกำกับรายการเมนูและฟังก์ชัน Apps Script ที่ทำงานเมื่อมีการเลือกรายการเมนู เช่น การเลือกรายการเมนู Format row header
จะทำให้ชีตพยายามเรียกใช้ฟังก์ชัน formatRowHeader()
(ซึ่งยังไม่มีอยู่)
ผลลัพธ์
ในสเปรดชีต ให้คลิกเมนู Quick formats
เพื่อดูรายการเมนูใหม่
การคลิกรายการเหล่านี้จะทำให้เกิดข้อผิดพลาดเนื่องจากคุณยังไม่ได้ใช้ฟังก์ชันที่เกี่ยวข้อง ดังนั้นเรามาดำเนินการในขั้นตอนถัดไปกัน
4 จัดรูปแบบแถวส่วนหัว
ชุดข้อมูลในสเปรดชีตมักจะมีแถวส่วนหัวเพื่อระบุข้อมูลในแต่ละคอลัมน์ คุณควรจัดรูปแบบแถวส่วนหัวเพื่อแยกออกจากข้อมูลที่เหลือในสเปรดชีตด้วยสายตา
ใน Codelab แรก คุณได้สร้างมาโครสำหรับส่วนหัวและปรับโค้ดของมาโคร ในที่นี้ คุณจะจัดรูปแบบแถวส่วนหัวตั้งแต่ต้นโดยใช้ Apps Script แถวส่วนหัวที่คุณสร้างจะทำให้ข้อความส่วนหัวเป็นตัวหนา เปลี่ยนสีพื้นหลังเป็นสีน้ำเงินเข้มแกมเขียว เปลี่ยนสีข้อความเป็นสีขาว และเพิ่มเส้นขอบแบบทึบบางส่วน
การใช้งาน
หากต้องการใช้การดำเนินการจัดรูปแบบ คุณจะต้องใช้วิธีการของบริการสเปรดชีตแบบเดียวกับที่เคยใช้ แต่ตอนนี้คุณจะต้องใช้วิธีการจัดรูปแบบบางอย่างของบริการด้วย โปรดทำตามขั้นตอนต่อไปนี้
- ในเครื่องมือแก้ไข Apps Script ให้เพิ่มฟังก์ชันต่อไปนี้ที่ส่วนท้ายของโปรเจ็กต์สคริปต์
/**
* Formats top row of sheet using our header row style.
*/
function formatRowHeader() {
// Get the current active sheet and the top row's range.
var sheet = SpreadsheetApp.getActiveSheet();
var headerRange = sheet.getRange(1, 1, 1, sheet.getLastColumn());
// Apply each format to the top row: bold white text,
// blue-green background, and a solid black border
// around the cells.
headerRange
.setFontWeight('bold')
.setFontColor('#ffffff')
.setBackground('#007272')
.setBorder(
true, true, true, true, null, null,
null,
SpreadsheetApp.BorderStyle.SOLID_MEDIUM);
}
- บันทึกโปรเจ็กต์สคริปต์
การตรวจสอบโค้ด
เช่นเดียวกับงานการจัดรูปแบบหลายอย่าง โค้ด Apps Script ที่ใช้ในการจัดรูปแบบนี้ก็ตรงไปตรงมา 2 บรรทัดแรกใช้วิธีที่คุณเคยเห็นมาก่อนเพื่อรับการอ้างอิงไปยังชีตที่ใช้งานอยู่ปัจจุบัน (sheet
) และแถวบนสุดของชีต (headerRange)
วิธี Sheet.getRange(row, column, numRows, numColumns)
จะระบุแถวบนสุด รวมถึงเฉพาะคอลัมน์ที่มีข้อมูล เมธอด Sheet.getLastColumn()
จะแสดงผลดัชนีคอลัมน์ของคอลัมน์สุดท้ายที่มีข้อมูลในชีต ในตัวอย่างของเราคือคอลัมน์ E (url)
ส่วนโค้ดที่เหลือจะเรียกใช้เมธอด Range
ต่างๆ เพื่อใช้ตัวเลือกการจัดรูปแบบกับเซลล์ทั้งหมดใน headerRange
เราใช้การเชื่อมโยงเมธอดเพื่อเรียกใช้เมธอดการจัดรูปแบบแต่ละรายการต่อๆ กันเพื่อให้โค้ดอ่านง่าย
Range.setFontWeight(fontWeight)
ใช้เพื่อตั้งค่าน้ำหนักแบบอักษรเป็นตัวหนาRange.setFontColor(color)
ใช้เพื่อตั้งค่าสีแบบอักษรเป็นสีขาวRange.setBackground(color)
ใช้เพื่อตั้งค่าสีพื้นหลังเป็นสีน้ำเงินเข้มแกมเขียวsetBorder(top, left, bottom, right, vertical, horizontal, color, style)
จะใส่เส้นขอบสีดำทึบรอบเซลล์ของช่วง
วิธีสุดท้ายมีพารามิเตอร์หลายรายการ ดังนั้นเรามาดูว่าแต่ละพารามิเตอร์ทำอะไรกัน พารามิเตอร์ 4 รายการแรกที่นี่ (ทั้งหมดตั้งค่าเป็น true
) จะบอก Apps Script ว่าควรเพิ่มเส้นขอบด้านบน ด้านล่าง ด้านซ้าย และด้านขวาของช่วง พารามิเตอร์ที่ 5 และ 6 (null
และ null
) จะสั่งให้ Apps Script หลีกเลี่ยงการเปลี่ยนเส้นขอบใดๆ ภายในช่วงที่เลือก พารามิเตอร์ที่ 7 (null
) ระบุว่าสีของเส้นขอบควรเป็นสีดำโดยค่าเริ่มต้น สุดท้าย พารามิเตอร์สุดท้ายจะระบุประเภทของรูปแบบเส้นขอบที่จะใช้ ซึ่งนำมาจากตัวเลือกที่ SpreadsheetApp.BorderStyle
ระบุ
ผลลัพธ์
คุณดูฟังก์ชันการจัดรูปแบบได้โดยทำดังนี้
- หากยังไม่ได้บันทึกโปรเจ็กต์สคริปต์ ให้บันทึกในเครื่องมือแก้ไข Apps Script
- คลิกรายการเมนูรูปแบบด่วน > จัดรูปแบบส่วนหัวของแถว
ผลลัพธ์ควรมีลักษณะดังนี้
ตอนนี้คุณได้ทำให้งานการจัดรูปแบบเป็นแบบอัตโนมัติแล้ว ส่วนถัดไปจะใช้เทคนิคเดียวกันเพื่อสร้างรูปแบบที่แตกต่างกันสำหรับส่วนหัวของคอลัมน์
5 จัดรูปแบบส่วนหัวของคอลัมน์
หากสร้างส่วนหัวของแถวที่ปรับเปลี่ยนในแบบของคุณได้ คุณก็สร้างส่วนหัวของคอลัมน์ได้เช่นกัน ส่วนหัวของคอลัมน์จะช่วยให้อ่านชุดข้อมูลบางชุดได้ง่ายขึ้น ตัวอย่างเช่น คุณสามารถปรับปรุงคอลัมน์ชื่อในสเปรดชีตนี้ได้ด้วยตัวเลือกรูปแบบต่อไปนี้
- การทำข้อความเป็นตัวหนา
- การทำข้อความเป็นตัวเอียง
- การเพิ่มเส้นขอบของเซลล์
- การแทรกไฮเปอร์ลิงก์โดยใช้เนื้อหาคอลัมน์ url เมื่อเพิ่มไฮเปอร์ลิงก์เหล่านี้แล้ว คุณสามารถนำคอลัมน์ url ออกเพื่อช่วยจัดระเบียบชีตได้
จากนั้นคุณจะใช้ฟังก์ชัน formatColumnHeader()
เพื่อใช้การเปลี่ยนแปลงเหล่านี้กับคอลัมน์แรกในชีต นอกจากนี้ คุณยังจะใช้ฟังก์ชันตัวช่วย 2 ฟังก์ชันเพื่อให้โค้ดอ่านง่ายขึ้นด้วย
การใช้งาน
เช่นเดียวกับก่อนหน้านี้ คุณต้องเพิ่มฟังก์ชันเพื่อจัดรูปแบบส่วนหัวของคอลัมน์โดยอัตโนมัติ โปรดทำตามขั้นตอนต่อไปนี้
- ในเครื่องมือแก้ไข Apps Script ให้เพิ่ม
formatColumnHeader()
ฟังก์ชันต่อไปนี้ที่ส่วนท้ายของโปรเจ็กต์สคริปต์
/**
* Formats the column header of the active sheet.
*/
function formatColumnHeader() {
var sheet = SpreadsheetApp.getActiveSheet();
// Get total number of rows in data range, not including
// the header row.
var numRows = sheet.getDataRange().getLastRow() - 1;
// Get the range of the column header.
var columnHeaderRange = sheet.getRange(2, 1, numRows, 1);
// Apply text formatting and add borders.
columnHeaderRange
.setFontWeight('bold')
.setFontStyle('italic')
.setBorder(
true, true, true, true, null, null,
null,
SpreadsheetApp.BorderStyle.SOLID_MEDIUM);
// Call helper method to hyperlink the first column contents
// to the url column contents.
hyperlinkColumnHeaders_(columnHeaderRange, numRows);
}
- เพิ่มฟังก์ชันตัวช่วยต่อไปนี้ที่ส่วนท้ายของโปรเจ็กต์สคริปต์ หลังจากฟังก์ชัน
formatColumnHeader()
/**
* Helper function that hyperlinks the column header with the
* 'url' column contents. The function then removes the column.
*
* @param {object} headerRange The range of the column header
* to update.
* @param {number} numRows The size of the column header.
*/
function hyperlinkColumnHeaders_(headerRange, numRows) {
// Get header and url column indices.
var headerColIndex = 1;
var urlColIndex = columnIndexOf_('url');
// Exit if the url column is missing.
if(urlColIndex == -1)
return;
// Get header and url cell values.
var urlRange =
headerRange.offset(0, urlColIndex - headerColIndex);
var headerValues = headerRange.getValues();
var urlValues = urlRange.getValues();
// Updates header values to the hyperlinked header values.
for(var row = 0; row < numRows; row++){
headerValues[row][0] = '=HYPERLINK("' + urlValues[row]
+ '","' + headerValues[row] + '")';
}
headerRange.setValues(headerValues);
// Delete the url column to clean up the sheet.
SpreadsheetApp.getActiveSheet().deleteColumn(urlColIndex);
}
/**
* Helper function that goes through the headers of all columns
* and returns the index of the column with the specified name
* in row 1. If a column with that name does not exist,
* this function returns -1. If multiple columns have the same
* name in row 1, the index of the first one discovered is
* returned.
*
* @param {string} colName The name to find in the column
* headers.
* @return The index of that column in the active sheet,
* or -1 if the name isn't found.
*/
function columnIndexOf_(colName) {
// Get the current column names.
var sheet = SpreadsheetApp.getActiveSheet();
var columnHeaders =
sheet.getRange(1, 1, 1, sheet.getLastColumn());
var columnNames = columnHeaders.getValues();
// Loops through every column and returns the column index
// if the row 1 value of that column matches colName.
for(var col = 1; col <= columnNames[0].length; col++)
{
if(columnNames[0][col-1] === colName)
return col;
}
// Returns -1 if a column named colName does not exist.
return -1;
}
- บันทึกโปรเจ็กต์สคริปต์
การตรวจสอบโค้ด
มาดูโค้ดในฟังก์ชันทั้ง 3 นี้แยกกัน
formatColumnHeader()
บรรทัดแรกๆ ของฟังก์ชันนี้จะตั้งค่าตัวแปรที่อ้างอิงชีตและช่วงที่เราสนใจ ดังที่คุณอาจคาดหวังไว้
- ระบบจะจัดเก็บชีตที่ใช้งานอยู่ใน
sheet
- ระบบจะคำนวณจำนวนแถวในส่วนหัวของคอลัมน์และบันทึกไว้ใน
numRows
ในที่นี้ โค้ดจะลบออก 1 เพื่อไม่ให้นับส่วนหัวของคอลัมน์ในจำนวนแถวtitle
- ระบบจะจัดเก็บช่วงที่ครอบคลุมส่วนหัวของคอลัมน์ไว้ใน
columnHeaderRange
จากนั้นโค้ดจะใช้เส้นขอบและการทำตัวหนากับช่วงส่วนหัวของคอลัมน์ เช่นเดียวกับใน formatRowHeader()
ในที่นี้ เราใช้ Range.setFontStyle(fontStyle)
เพื่อทำให้ข้อความเป็นตัวเอียงด้วย
การเพิ่มไฮเปอร์ลิงก์ไปยังคอลัมน์ส่วนหัวมีความซับซ้อนมากกว่า ดังนั้น formatColumnHeader()
จึงhyperlinkColumnHeaders_(headerRange, numRows)
ขอให้ช่วยจัดการงานนี้ ซึ่งจะช่วยให้โค้ดเป็นระเบียบและอ่านง่าย
hyperlinkColumnHeaders_(headerRange, numRows)
ฟังก์ชันช่วยนี้จะระบุดัชนีคอลัมน์ของส่วนหัว (สมมติว่าเป็นดัชนี 1) และคอลัมน์ url
ก่อน โดยจะเรียกใช้ columnIndexOf_('url')
เพื่อรับดัชนีคอลัมน์ URL หากไม่พบurl
ระบบจะออกจากเมธอดโดยไม่แก้ไขข้อมูลใดๆ
ฟังก์ชันจะรับช่วงใหม่ (urlRange
) ที่ครอบคลุม URL ที่สอดคล้องกับแถวคอลัมน์ส่วนหัว โดยใช้วิธี Range.offset(rowOffset, columnOffset)
ซึ่งรับประกันว่าช่วงทั้ง 2 จะมีขนาดเท่ากัน จากนั้นระบบจะดึงค่าในทั้งคอลัมน์ headerColumn
และ url
(headerValues
และ urlValues
)
จากนั้นฟังก์ชันจะวนซ้ำค่าของเซลล์ส่วนหัวของแต่ละคอลัมน์และแทนที่ด้วย=HYPERLINK()
สูตรชีตที่สร้างขึ้นจากส่วนหัวและurl
เนื้อหาของคอลัมน์ จากนั้นระบบจะแทรกค่าส่วนหัวที่แก้ไขแล้วลงในชีตโดยใช้ Range.setValues(values)
สุดท้ายนี้ เพื่อช่วยให้ชีตสะอาดและกำจัดข้อมูลที่ซ้ำซ้อน เราจะเรียกใช้ Sheet.deleteColumn(columnPosition)
เพื่อนำคอลัมน์ url
ออก
columnIndexOf_(colName)
ฟังก์ชันตัวช่วยนี้เป็นเพียงฟังก์ชันยูทิลิตีง่ายๆ ที่ค้นหาชื่อที่เฉพาะเจาะจงในแถวแรกของชีต 3 บรรทัดแรกใช้วิธีที่คุณเคยเห็นแล้วเพื่อรับรายการชื่อส่วนหัวของคอลัมน์จากแถวที่ 1 ของสเปรดชีต โดยระบบจะจัดเก็บชื่อเหล่านี้ไว้ในตัวแปร columnNames
จากนั้นฟังก์ชันจะตรวจสอบชื่อแต่ละชื่อตามลำดับ หากพบรายการที่ตรงกับชื่อที่กำลังค้นหา ฟังก์ชันจะหยุดและแสดงดัชนีของคอลัมน์ หากถึงจุดสิ้นสุดของรายการชื่อโดยไม่พบชื่อ ระบบจะแสดงผล -1 เพื่อส่งสัญญาณว่าไม่พบชื่อ
ผลลัพธ์
คุณดูฟังก์ชันการจัดรูปแบบได้โดยทำดังนี้
- หากยังไม่ได้บันทึกโปรเจ็กต์สคริปต์ ให้บันทึกในเครื่องมือแก้ไข Apps Script
- คลิกรายการเมนูรูปแบบด่วน > จัดรูปแบบส่วนหัวของคอลัมน์
ผลลัพธ์ควรมีลักษณะดังนี้
ตอนนี้คุณได้ทำให้งานการจัดรูปแบบอีกอย่างเป็นแบบอัตโนมัติแล้ว เมื่อจัดรูปแบบส่วนหัวของคอลัมน์และแถวแล้ว ส่วนถัดไปจะแสดงวิธีจัดรูปแบบข้อมูล
6 จัดรูปแบบชุดข้อมูล
เมื่อมีส่วนหัวแล้ว เรามาสร้างฟังก์ชันที่จัดรูปแบบข้อมูลที่เหลือในชีตกัน เราจะใช้ตัวเลือกการจัดรูปแบบต่อไปนี้
- สีพื้นหลังของแถวแบบสลับ (หรือที่เรียกว่าการแรเงา)
- การเปลี่ยนรูปแบบวันที่
- การใช้เส้นขอบ
- การปรับขนาดคอลัมน์และแถวทั้งหมดโดยอัตโนมัติ
ตอนนี้คุณจะสร้างฟังก์ชัน formatDataset()
และเมธอดตัวช่วยเพิ่มเติมเพื่อใช้รูปแบบเหล่านี้กับข้อมูลชีต
การใช้งาน
เช่นเดียวกับก่อนหน้านี้ ให้เพิ่มฟังก์ชันเพื่อจัดรูปแบบข้อมูลโดยอัตโนมัติ โปรดทำตามขั้นตอนต่อไปนี้
- ในเครื่องมือแก้ไข Apps Script ให้เพิ่ม
formatDataset()
ฟังก์ชันต่อไปนี้ที่ส่วนท้ายของโปรเจ็กต์สคริปต์
/**
* Formats the sheet data, excluding the header row and column.
* Applies the border and banding, formats the 'release_date'
* column, and autosizes the columns and rows.
*/
function formatDataset() {
// Get the active sheet and data range.
var sheet = SpreadsheetApp.getActiveSheet();
var fullDataRange = sheet.getDataRange();
// Apply row banding to the data, excluding the header
// row and column. Only apply the banding if the range
// doesn't already have banding set.
var noHeadersRange = fullDataRange.offset(
1, 1,
fullDataRange.getNumRows() - 1,
fullDataRange.getNumColumns() - 1);
if (! noHeadersRange.getBandings()[0]) {
// The range doesn't already have banding, so it's
// safe to apply it.
noHeadersRange.applyRowBanding(
SpreadsheetApp.BandingTheme.LIGHT_GREY,
false, false);
}
// Call a helper function to apply date formatting
// to the column labeled 'release_date'.
formatDates_( columnIndexOf_('release_date') );
// Set a border around all the data, and resize the
// columns and rows to fit.
fullDataRange.setBorder(
true, true, true, true, null, null,
null,
SpreadsheetApp.BorderStyle.SOLID_MEDIUM);
sheet.autoResizeColumns(1, fullDataRange.getNumColumns());
sheet.autoResizeRows(1, fullDataRange.getNumRows());
}
- เพิ่มฟังก์ชันตัวช่วยต่อไปนี้ที่ส่วนท้ายของโปรเจ็กต์สคริปต์ หลังจากฟังก์ชัน
formatDataset()
/**
* Helper method that applies a
* "Month Day, Year (Day of Week)" date format to the
* indicated column in the active sheet.
*
* @param {number} colIndex The index of the column
* to format.
*/
function formatDates_(colIndex) {
// Exit if the given column index is -1, indicating
// the column to format isn't present in the sheet.
if (colIndex < 0)
return;
// Set the date format for the date column, excluding
// the header row.
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(2, colIndex, sheet.getLastRow() - 1, 1)
.setNumberFormat("mmmm dd, yyyy (dddd)");
}
- บันทึกโปรเจ็กต์สคริปต์
การตรวจสอบโค้ด
มาดูโค้ดในฟังก์ชันทั้ง 2 นี้แยกกัน
formatDataset()
ฟังก์ชันนี้มีรูปแบบคล้ายกับฟังก์ชันรูปแบบก่อนหน้าที่คุณได้ใช้ไปแล้ว โดยขั้นแรกจะรับตัวแปรเพื่อเก็บการอ้างอิงไปยังชีตที่ใช้งานอยู่ (ชีต) และช่วงข้อมูล (fullDataRange)
ประการที่ 2 คือใช้เมธอด Range.offset(rowOffset, columnOffset, numRows, numColumns)
เพื่อสร้างช่วง (noHeadersRange
) ที่ครอบคลุมข้อมูลทั้งหมดในชีต ยกเว้นส่วนหัวของคอลัมน์และแถว จากนั้นโค้ดจะตรวจสอบว่าช่วงใหม่นี้มีการแบนด์ที่มีอยู่หรือไม่ (โดยใช้ Range.getBandings()
) ซึ่งจำเป็นเนื่องจาก Apps Script จะแสดงข้อผิดพลาดหากคุณพยายามใช้การแบนด์ใหม่ในที่ที่มีการแบนด์อยู่แล้ว หากไม่มีแถบสี ฟังก์ชันจะเพิ่มแถบสีเทาอ่อนโดยใช้ Range.applyRowBanding(bandingTheme, showHeader, showFooter)
ไม่เช่นนั้น ฟังก์ชันจะดำเนินการต่อ
ขั้นตอนถัดไปจะเรียกใช้ฟังก์ชันตัวช่วย formatDates_(colIndex)
เพื่อจัดรูปแบบวันที่ในคอลัมน์ที่มีป้ายกำกับว่า "release_date
" (อธิบายไว้ด้านล่าง) คอลัมน์จะระบุโดยใช้columnIndexOf_(colName)
ฟังก์ชันตัวช่วยที่คุณใช้ก่อนหน้านี้
สุดท้ายนี้ ให้จัดรูปแบบโดยการเพิ่มเส้นขอบอีกเส้น (เช่นเดียวกับก่อนหน้า) และปรับขนาดคอลัมน์และแถวทั้งหมดโดยอัตโนมัติให้พอดีกับข้อมูลที่มีอยู่โดยใช้วิธี Sheet.autoResizeColumns(columnPosition)
และ Sheet.autoResizeColumns(columnPosition)
formatDates_(colIndex)
ฟังก์ชันตัวช่วยนี้จะใช้รูปแบบวันที่ที่เฉพาะเจาะจงกับคอลัมน์โดยใช้ดัชนีคอลัมน์ที่ระบุ โดยจะจัดรูปแบบค่าวันที่เป็น "เดือน วัน ปี (วันในสัปดาห์)"
ก่อนอื่น ฟังก์ชันจะตรวจสอบว่าดัชนีคอลัมน์ที่ระบุถูกต้องหรือไม่ (กล่าวคือ 0 หรือมากกว่า) หากไม่ ระบบจะแสดงผลโดยไม่ดำเนินการใดๆ การตรวจสอบนี้จะป้องกันข้อผิดพลาดที่อาจเกิดขึ้นหากชีตไม่มีคอลัมน์ "release_date
" เป็นต้น
เมื่อตรวจสอบดัชนีคอลัมน์แล้ว ฟังก์ชันจะรับช่วงที่ครอบคลุมคอลัมน์นั้น (ไม่รวมแถวส่วนหัว) และใช้ Range.setNumberFormat(numberFormat)
เพื่อใช้การจัดรูปแบบ
ผลลัพธ์
คุณดูฟังก์ชันการจัดรูปแบบได้โดยทำดังนี้
- หากยังไม่ได้บันทึกโปรเจ็กต์สคริปต์ ให้บันทึกในเครื่องมือแก้ไข Apps Script
- คลิกรายการเมนูรูปแบบด่วน > จัดรูปแบบชุดข้อมูล
ผลลัพธ์ควรมีลักษณะดังนี้
คุณได้ตั้งค่าการทำงานอัตโนมัติสำหรับงานการจัดรูปแบบอีกอย่างหนึ่งแล้ว ตอนนี้คุณมีคำสั่งการจัดรูปแบบเหล่านี้แล้ว มาเพิ่มข้อมูลเพื่อนำไปใช้กัน
7 ดึงและจัดรูปแบบข้อมูล API
ใน Codelab นี้ คุณได้เห็นวิธีใช้ Apps Script เป็นอีกวิธีในการจัดรูปแบบสเปรดชีต จากนั้นคุณจะเขียนโค้ดที่ดึงข้อมูลจาก API สาธารณะ แทรกข้อมูลลงในสเปรดชีต และจัดรูปแบบเพื่อให้สามารถอ่านได้
ใน Codelab ที่แล้ว คุณได้เรียนรู้วิธีดึงข้อมูลจาก API คุณจะใช้เทคนิคเดียวกันนี้ที่นี่ ในแบบฝึกหัดนี้ เราจะใช้ Star Wars API (SWAPI) ที่เผยแพร่ต่อสาธารณะเพื่อป้อนข้อมูลลงในสเปรดชีต โดยคุณจะใช้ API เพื่อรับข้อมูลเกี่ยวกับตัวละครหลักที่ปรากฏในภาพยนตร์ Star Wars 3 ภาคแรก
โค้ดจะเรียก API เพื่อรับข้อมูล JSON จำนวนมาก แยกวิเคราะห์การตอบกลับ วางข้อมูลในชีตใหม่ แล้วจัดรูปแบบชีต
การใช้งาน
ในส่วนนี้ คุณจะเพิ่มรายการในเมนูเพิ่มเติม รายการในเมนูแต่ละรายการจะเรียกสคริปต์ Wrapper ที่ส่งตัวแปรเฉพาะรายการไปยังฟังก์ชันหลัก (createResourceSheet_()) คุณจะใช้ฟังก์ชันนี้และฟังก์ชันตัวช่วยเพิ่มเติมอีก 3 ฟังก์ชัน ฟังก์ชันตัวช่วยจะช่วยแยกส่วนต่างๆ ของงานตามตรรกะและช่วยให้โค้ดอ่านได้ง่ายเช่นเดิม
ดำเนินการดังนี้
- ในตัวแก้ไข Apps Script ให้อัปเดตฟังก์ชัน
onOpen()
ในโปรเจ็กต์สคริปต์ให้ตรงกับฟังก์ชันต่อไปนี้
/**
* A special function that runs when the spreadsheet is opened
* or reloaded, used to add a custom menu to the spreadsheet.
*/
function onOpen() {
// Get the Ui object.
var ui = SpreadsheetApp.getUi();
// Create and add a named menu and its items to the menu bar.
ui.createMenu('Quick formats')
.addItem('Format row header', 'formatRowHeader')
.addItem('Format column header', 'formatColumnHeader')
.addItem('Format dataset', 'formatDataset')
.addSeparator()
.addSubMenu(ui.createMenu('Create character sheet')
.addItem('Episode IV', 'createPeopleSheetIV')
.addItem('Episode V', 'createPeopleSheetV')
.addItem('Episode VI', 'createPeopleSheetVI')
)
.addToUi();
}
- บันทึกโปรเจ็กต์สคริปต์
- ในตัวแก้ไขสคริปต์ ให้เลือก
onOpen
จากรายการฟังก์ชัน แล้วคลิกเรียกใช้ ซึ่งจะเรียกใช้onOpen()
เพื่อสร้างเมนูสเปรดชีตใหม่ด้วยตัวเลือกใหม่ที่คุณเพิ่ม - หากต้องการสร้างไฟล์ Apps Script ให้คลิกเพิ่มไฟล์
> สคริปต์ ข้างไฟล์
- ตั้งชื่อสคริปต์ใหม่ว่า "API" แล้วกด Enter (Apps Script จะต่อท้ายนามสกุล
.gs
ให้กับชื่อไฟล์สคริปต์โดยอัตโนมัติ) - แทนที่โค้ดในไฟล์ API.gs ใหม่ด้วยโค้ดต่อไปนี้
/**
* Wrapper function that passes arguments to create a
* resource sheet describing the characters from Episode IV.
*/
function createPeopleSheetIV() {
createResourceSheet_('characters', 1, "IV");
}
/**
* Wrapper function that passes arguments to create a
* resource sheet describing the characters from Episode V.
*/
function createPeopleSheetV() {
createResourceSheet_('characters', 2, "V");
}
/**
* Wrapper function that passes arguments to create a
* resource sheet describing the characters from Episode VI.
*/
function createPeopleSheetVI() {
createResourceSheet_('characters', 3, "VI");
}
/**
* Creates a formatted sheet filled with user-specified
* information from the Star Wars API. If the sheet with
* this data exists, the sheet is overwritten with the API
* information.
*
* @param {string} resourceType The type of resource.
* @param {number} idNumber The identification number of the film.
* @param {number} episodeNumber The Star Wars film episode number.
* This is only used in the sheet name.
*/
function createResourceSheet_(
resourceType, idNumber, episodeNumber) {
// Fetch the basic film data from the API.
var filmData = fetchApiResourceObject_(
"https://swapi.dev/api/films/" + idNumber);
// Extract the API URLs for each resource so the code can
// call the API to get more data about each individually.
var resourceUrls = filmData[resourceType];
// Fetch each resource from the API individually and push
// them into a new object list.
var resourceDataList = [];
for(var i = 0; i < resourceUrls.length; i++){
resourceDataList.push(
fetchApiResourceObject_(resourceUrls[i])
);
}
// Get the keys used to reference each part of data within
// the resources. The keys are assumed to be identical for
// each object since they're all the same resource type.
var resourceObjectKeys = Object.keys(resourceDataList[0]);
// Create the sheet with the appropriate name. It
// automatically becomes the active sheet when it's created.
var resourceSheet = createNewSheet_(
"Episode " + episodeNumber + " " + resourceType);
// Add the API data to the new sheet, using each object
// key as a column header.
fillSheetWithData_(resourceSheet, resourceObjectKeys, resourceDataList);
// Format the new sheet using the same styles the
// 'Quick Formats' menu items apply. These methods all
// act on the active sheet, which is the one just created.
formatRowHeader();
formatColumnHeader();
formatDataset();
}
- เพิ่มฟังก์ชันตัวช่วยต่อไปนี้ที่ส่วนท้ายของไฟล์โปรเจ็กต์สคริปต์ API.gs
/**
* Helper function that retrieves a JSON object containing a
* response from a public API.
*
* @param {string} url The URL of the API object being fetched.
* @return {object} resourceObject The JSON object fetched
* from the URL request to the API.
*/
function fetchApiResourceObject_(url) {
// Make request to API and get response.
var response =
UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
// Parse and return the response as a JSON object.
var json = response.getContentText();
var responseObject = JSON.parse(json);
return responseObject;
}
/**
* Helper function that creates a sheet or returns an existing
* sheet with the same name.
*
* @param {string} name The name of the sheet.
* @return {object} The created or existing sheet
* of the same name. This sheet becomes active.
*/
function createNewSheet_(name) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Returns an existing sheet if it has the specified
// name. Activates the sheet before returning.
var sheet = ss.getSheetByName(name);
if (sheet) {
return sheet.activate();
}
// Otherwise it makes a sheet, set its name, and returns it.
// New sheets created this way automatically become the active
// sheet.
sheet = ss.insertSheet(name);
return sheet;
}
/**
* Helper function that adds API data to the sheet.
* Each object key is used as a column header in the new sheet.
*
* @param {object} resourceSheet The sheet object being modified.
* @param {object} objectKeys The list of keys for the resources.
* @param {object} resourceDataList The list of API
* resource objects containing data to add to the sheet.
*/
function fillSheetWithData_(
resourceSheet, objectKeys, resourceDataList) {
// Set the dimensions of the data range being added to the sheet.
var numRows = resourceDataList.length;
var numColumns = objectKeys.length;
// Get the resource range and associated values array. Add an
// extra row for the column headers.
var resourceRange =
resourceSheet.getRange(1, 1, numRows + 1, numColumns);
var resourceValues = resourceRange.getValues();
// Loop over each key value and resource, extracting data to
// place in the 2D resourceValues array.
for (var column = 0; column < numColumns; column++) {
// Set the column header.
var columnHeader = objectKeys[column];
resourceValues[0][column] = columnHeader;
// Read and set each row in this column.
for (var row = 1; row < numRows + 1; row++) {
var resource = resourceDataList[row - 1];
var value = resource[columnHeader];
resourceValues[row][column] = value;
}
}
// Remove any existing data in the sheet and set the new values.
resourceSheet.clear()
resourceRange.setValues(resourceValues);
}
- บันทึกโปรเจ็กต์สคริปต์
การตรวจสอบโค้ด
คุณเพิ่งเพิ่มโค้ดจำนวนมาก มาดูฟังก์ชันแต่ละอย่างกันทีละรายการเพื่อทำความเข้าใจวิธีการทำงาน
onOpen()
ในที่นี้ คุณได้เพิ่มรายการในเมนู 2-3 รายการลงในเมนู Quick formats
แล้ว คุณได้ตั้งค่าเส้นคั่นแล้วใช้วิธี Menu.addSubMenu(menu)
เพื่อสร้างโครงสร้างเมนูแบบซ้อนที่มีรายการใหม่ 3 รายการ ระบบจะเพิ่มรายการใหม่โดยใช้วิธี Menu.addItem(caption, functionName)
ฟังก์ชัน Wrapper
รายการเมนูที่เพิ่มเข้ามาทั้งหมดจะทำสิ่งที่คล้ายกัน นั่นคือพยายามสร้างชีตที่มีข้อมูลที่ดึงมาจาก SWAPI โดยทั้งสองจะมุ่งเน้นไปที่ภาพยนตร์ที่แตกต่างกัน
การเขียนฟังก์ชันเดียวเพื่อสร้างชีต และให้ฟังก์ชันยอมรับพารามิเตอร์เพื่อกำหนดภาพยนตร์ที่จะใช้จะสะดวกกว่า อย่างไรก็ตาม เมธอด Menu.addItem(caption, functionName)
จะไม่อนุญาตให้คุณส่งพารามิเตอร์ไปยังเมธอดเมื่อเรียกใช้จากเมนู แล้วคุณจะหลีกเลี่ยงการเขียนโค้ดเดียวกัน 3 ครั้งได้อย่างไร
คำตอบคือฟังก์ชัน Wrapper ฟังก์ชันเหล่านี้เป็นฟังก์ชันที่มีน้ำหนักเบาที่คุณเรียกใช้ได้ ซึ่งจะเรียกใช้ฟังก์ชันอื่นทันทีโดยมีการตั้งค่าพารามิเตอร์ที่เฉพาะเจาะจง
ในที่นี้ โค้ดใช้ฟังก์ชัน Wrapper 3 รายการ ได้แก่ createPeopleSheetIV()
, createPeopleSheetV()
และ createPeopleSheetVI()
รายการในเมนูจะลิงก์กับฟังก์ชันเหล่านี้ เมื่อคลิกรายการเมนู ฟังก์ชัน Wrapper จะทำงานและเรียกใช้ฟังก์ชันตัวสร้างชีตหลัก createResourceSheet_(resourceType, idNumber, episodeNumber)
ทันที โดยส่งพารามิเตอร์ที่เหมาะสมสำหรับรายการเมนู ในกรณีนี้ หมายถึงการขอให้ฟังก์ชันตัวสร้างชีตสร้างชีตที่เต็มไปด้วยข้อมูลตัวละครหลักจากภาพยนตร์ Star Wars ภาคใดภาคหนึ่ง
createResourceSheet_(resourceType, idNumber, episodeNumber)
นี่คือฟังก์ชันตัวสร้างชีตหลักสำหรับการฝึกหัดนี้ ฟังก์ชันตัวช่วยบางอย่างจะช่วยดึงข้อมูล API แยกวิเคราะห์ สร้างชีต เขียนข้อมูล API ลงในชีต แล้วจัดรูปแบบชีตโดยใช้ฟังก์ชันที่คุณสร้างไว้ในส่วนก่อนหน้า มาดูรายละเอียดกัน
ก่อนอื่น ฟังก์ชันจะใช้ fetchApiResourceObject_(url)
เพื่อส่งคำขอไปยัง API เพื่อดึงข้อมูลภาพยนตร์พื้นฐาน การตอบกลับของ API จะมีคอลเล็กชันของ URL ที่โค้ดใช้เพื่อดูรายละเอียดเพิ่มเติมเกี่ยวกับบุคคลที่เฉพาะเจาะจง (เรียกว่าทรัพยากรในที่นี้) จากภาพยนตร์ได้ โค้ดจะรวบรวมข้อมูลทั้งหมดไว้ในอาร์เรย์ resourceUrls
จากนั้นโค้ดจะใช้ fetchApiResourceObject_(url)
ซ้ำๆ เพื่อเรียก API สำหรับ URL ของทรัพยากรทุกรายการใน resourceUrls
ระบบจะจัดเก็บผลลัพธ์ไว้ในอาร์เรย์ resourceDataList
องค์ประกอบทุกรายการในอาร์เรย์นี้เป็นออบเจ็กต์ที่อธิบายตัวละครต่างๆ จากภาพยนตร์
ออบเจ็กต์ข้อมูลทรัพยากรมีคีย์ทั่วไปหลายรายการที่เชื่อมโยงกับข้อมูลเกี่ยวกับตัวละครนั้น เช่น คีย์ ‘name
' จะแมปกับชื่อตัวละครในภาพยนตร์ เราถือว่าคีย์สำหรับออบเจ็กต์ข้อมูลทรัพยากรแต่ละรายการเหมือนกันทั้งหมด เนื่องจากมีไว้เพื่อใช้โครงสร้างออบเจ็กต์ทั่วไป เราจะต้องใช้รายการคีย์ในภายหลัง ดังนั้นโค้ดจึงจัดเก็บรายการคีย์ใน resourceObjectKeys
โดยใช้เมธอด Object.keys() ของ JavaScript
จากนั้นฟังก์ชัน Builder จะเรียกใช้ฟังก์ชันตัวช่วย createNewSheet_(name)
เพื่อสร้างชีตที่จะวางข้อมูลใหม่ การเรียกใช้ฟังก์ชันตัวช่วยนี้จะเป็นการเปิดใช้งานชีตใหม่ด้วย
หลังจากสร้างชีตแล้ว ระบบจะเรียกใช้ฟังก์ชันตัวช่วย fillSheetWithData_(resourceSheet, objectKeys, resourceDataList)
เพื่อเพิ่มข้อมูล API ทั้งหมดลงในชีต
สุดท้ายนี้ ระบบจะเรียกใช้ฟังก์ชันการจัดรูปแบบทั้งหมดที่คุณสร้างไว้ก่อนหน้านี้เพื่อใช้กฎการจัดรูปแบบเดียวกันกับข้อมูลใหม่ เนื่องจากชีตใหม่เป็นชีตที่ใช้งานอยู่ โค้ดจึงใช้ฟังก์ชันเหล่านี้ซ้ำได้โดยไม่ต้องแก้ไข
fetchApiResourceObject_(url)
ฟังก์ชันตัวช่วยนี้คล้ายกับฟังก์ชันตัวช่วย fetchBookData_(ISBN)
ที่ใช้ในโค้ดแล็บก่อนหน้า การทำงานกับข้อมูล โดยจะใช้ URL ที่ระบุและใช้วิธี UrlFetchApp.fetch(url, params)
เพื่อรับการตอบกลับ จากนั้นระบบจะแยกวิเคราะห์การตอบกลับเป็นออบเจ็กต์ JSON โดยใช้เมธอด HTTPResponse.getContextText()
และ JavaScript JSON.parse(json)
จากนั้นระบบจะแสดงผลออบเจ็กต์ JSON ที่ได้
createNewSheet_(name)
ฟังก์ชันตัวช่วยนี้ค่อนข้างเรียบง่าย โดยจะตรวจสอบก่อนว่ามีชีตที่มีชื่อที่ระบุอยู่ในสเปรดชีตหรือไม่ หากมี ฟังก์ชันจะเปิดใช้งานชีตและแสดงผลชีต
หากไม่มีชีต ฟังก์ชันจะสร้างชีตที่มี Spreadsheet.insertSheet(sheetName)
เปิดใช้งาน และแสดงผลชีตใหม่
fillSheetWithData_(resourceSheet, objectKeys, resourceDataList)
ฟังก์ชันตัวช่วยนี้มีหน้าที่ในการป้อนข้อมูล API ลงในชีตใหม่ โดยจะใช้ชีตใหม่ รายการคีย์ออบเจ็กต์ และรายการออบเจ็กต์ทรัพยากร API เป็นพารามิเตอร์ คีย์ออบเจ็กต์แต่ละรายการแสดงคอลัมน์ในชีตใหม่ และออบเจ็กต์ทรัพยากรแต่ละรายการแสดงแถว
ก่อนอื่น ฟังก์ชันจะคำนวณจำนวนแถวและคอลัมน์ที่จำเป็นในการนำเสนอข้อมูล API ใหม่ นี่คือขนาดของรายการทรัพยากรและคีย์ตามลำดับ จากนั้นฟังก์ชันจะกำหนดช่วงเอาต์พุต (resourceRange
) ที่จะวางข้อมูล โดยเพิ่มแถวพิเศษเพื่อเก็บส่วนหัวของคอลัมน์ ตัวแปร resourceValues
มีอาร์เรย์ค่า 2 มิติที่ดึงมาจาก resourceRange
จากนั้นฟังก์ชันจะวนซ้ำคีย์ออบเจ็กต์ทุกรายการในลิสต์ objectKeys
โดยตั้งค่าคีย์เป็นส่วนหัวของคอลัมน์ จากนั้นลูปที่ 2 จะวนซ้ำผ่านออบเจ็กต์ทรัพยากรทุกรายการ สำหรับคู่ (แถว, คอลัมน์) แต่ละคู่ ระบบจะคัดลอกข้อมูล API ที่เกี่ยวข้องไปยังองค์ประกอบ resourceValues[row][column]
หลังจากกรอกข้อมูลใน resourceValues
แล้ว ระบบจะล้างชีตปลายทางโดยใช้ Sheet.clear()
ในกรณีที่มีข้อมูลจากการคลิกรายการเมนูก่อนหน้า สุดท้าย ระบบจะเขียนค่าใหม่ลงในชีต
ผลลัพธ์
คุณดูผลลัพธ์ของงานได้โดยทำดังนี้
- หากยังไม่ได้บันทึกโปรเจ็กต์สคริปต์ ให้บันทึกในเครื่องมือแก้ไข Apps Script
- คลิกรายการเมนูรูปแบบด่วน > สร้างชีตตัวละคร > ตอนที่ 4
ผลลัพธ์ควรมีลักษณะดังนี้
ตอนนี้คุณได้เขียนโค้ดเพื่อนำเข้าข้อมูลลงในชีตและจัดรูปแบบข้อมูลโดยอัตโนมัติแล้ว
8 บทสรุป
ขอแสดงความยินดีที่คุณทำ Codelab นี้เสร็จสมบูรณ์ คุณได้เห็นตัวเลือกการจัดรูปแบบชีตบางอย่างที่สามารถรวมไว้ในโปรเจ็กต์ Apps Script และสร้างแอปพลิเคชันที่น่าประทับใจซึ่งนำเข้าและจัดรูปแบบชุดข้อมูล API ขนาดใหญ่
คุณคิดว่า Codelab นี้มีประโยชน์ไหม
สิ่งที่คุณได้เรียนรู้
- วิธีใช้ Apps Script เพื่อดำเนินการจัดรูปแบบต่างๆ ในชีต
- วิธีสร้างเมนูย่อยด้วยฟังก์ชัน
onOpen()
- วิธีจัดรูปแบบรายการออบเจ็กต์ JSON ที่ดึงข้อมูลมาเป็นชีตข้อมูลใหม่ด้วย Apps Script
ขั้นตอนถัดไป
Codelab ถัดไปในเพลย์ลิสต์นี้จะแสดงวิธีใช้ Apps Script เพื่อแสดงข้อมูลในแผนภูมิและส่งออกแผนภูมิไปยังงานนำเสนอใน Google สไลด์
ดู Codelab ถัดไปได้ที่สร้างแผนภูมิและนำเสนอข้อมูลในสไลด์