这是一个专门收集和整理 Google Apps Script(GAS)常用代码片段的网站。每个代码片段都附带详细的说明和注释,方便理解和使用,帮助优化工作流程,提高开发效率,让脚本编写更加轻松高效。
需要添加 Drive 服务,并且设置为 v2 版本。
/**
* @description 识别图片中的文字
* @param {string} imageUrl - 图片链接
* @returns {string} 返回识别出的文本内容
*/
function imageOCR (imageUrl) {
const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob()
const options = { ocr: true }
const resource = {
title: imageBlob.getName(),
mimeType: imageBlob.getContentType()
}
const docFile = Drive.Files.insert(resource, imageBlob, options)
const doc = DocumentApp.openById(docFile.id)
const text = doc.getBody().getText().replace(/\n+/g, ' ').trim()
Drive.Files.remove(docFile.id)
return text
}
通过表格链接中的 gid 参数匹配出指定的工作表对象。
/**
* @description 根据 Google Sheets 链接的 gid 参数获取指定表格
* @param {string} sheetUrl - Google Sheets 的 URL 地址
* @returns {GoogleAppsScript.Spreadsheet.Sheet} 返回匹配的工作表对象
*/
function getSheet (sheetUrl) {
const ss = SpreadsheetApp.openByUrl(sheetUrl)
const gid = sheetUrl.match(/(?<=gid=).*[0-9]/g, '')[0]
return ss.getSheets().find(function (s) {
return s.getSheetId() === parseInt(gid)
})
}
将数字转换成表格列字母;把表格列字母转换为数字。
/**
* @description 将列字母转换为数字
* @param {string} column - 列名称(如 'A', 'Z', 'AA')
* @returns {number} 对应的数字(如 1, 26, 27)
*/
const columnToNumber = column => {
let number = 0
for (let i = 0; i < column.length; i++) {
number = number * 26 + (column.charCodeAt(i) - 64)
}
return number
}
/**
* @description 将数字转换为列字母
* @param {number} num - Excel 列号(如 1, 26, 27)
* @returns {string} 对应的 Excel 列名称(如 'A', 'Z', 'AA')
*/
const numberToColumn = num => {
let column = ''
while (num > 0) {
const remainder = (num - 1) % 26
column = String.fromCharCode(65 + remainder) + column
num = Math.floor((num - 1) / 26)
}
return column
}
从另外一个电子表格把数据同步到当前表格。需要修改「数据表格ID」、「数据表格名字」、「当前表格名字」和同步数据的范围。
// 同步数据到当前表格
function syncData () {
const dataSheet = SpreadsheetApp.openById('数据表格ID').getSheetByName('数据表格名字')
const data = dataSheet.getRange('A:F').getValues()
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('当前表格名字')
// 清空原始内容
currentSheet.getRange('A:F').clearContent()
currentSheet.getRange(1, 1, data.length, data[0].length).setValues(data)
}
在菜单栏加载自定义菜单,打开表格后自动加载。需要需要改对应的函数名称才会有功能。
// 启动菜单
function onOpen () {
const ui = SpreadsheetApp.getUi()
// 菜单栏显示按钮
ui.createMenu('主菜单')
.addItem('按钮1', 'menuItem1')
.addItem('按钮2', 'menuItem2')
// 分割线
.addSeparator()
// 添加子菜单
.addSubMenu(ui.createMenu('子菜单')
.addItem('子菜单1', 'menuItem2')
.addItem('子菜单2', 'menuItem2'))
.addToUi()
}
在菜单栏加载自定义菜单,打开表格后自动加载。需要需要改对应的函数名称才会有功能。
const menuConfig = [
['按钮1', 'menuItem1'],
['按钮2', 'menuItem2'],
'---', // 分隔线
['分类1', [
['归档1', [
['按钮3', 'menuItem3'],
['按钮4', 'menuItem4'],
['按钮5', 'menuItem5']
]],
['归档2', [
['按钮6', 'menuItem6'],
['按钮7', 'menuItem7'],
['按钮8', 'menuItem8']
]],
['归档3', [
['按钮9', 'menuItem9'],
['按钮10', 'menuItem10'],
['按钮11', 'menuItem11']
]]
]],
['分类2', [
['按钮12', 'menuItem12'],
['按钮13', 'menuItem13']
]],
['分类3', [
['按钮14', 'menuItem14'],
['按钮15', 'menuItem15'],
'---',
['按钮16', 'menuItem16'],
['按钮17', 'menuItem17']
]]
]
function onOpen () {
const ui = SpreadsheetApp.getUi()
const rootMenu = ui.createMenu('🧰 主菜单')
buildMenu(ui, rootMenu, menuConfig)
rootMenu.addToUi()
}
/**
* @description 递归构建菜单和子菜单,根据传入的配置动态生成层级结构。
* @param {Object} ui - SpreadsheetApp 的 UI 实例,用于创建菜单项和子菜单。
* @param {Object} parent - 当前正在构建的菜单或子菜单对象。
* @param {Array} menuConfig - 当前层级的菜单配置数组,支持普通项、分隔线和嵌套结构。
*/
function buildMenu (ui, parent, menuConfig) {
menuConfig.forEach(item => {
if (item === '---') {
parent.addSeparator()
} else if (Array.isArray(item[1])) {
// 子菜单
const subMenu = ui.createMenu(item[0])
buildMenu(ui, subMenu, item[1])
parent.addSubMenu(subMenu)
} else {
// 普通菜单项
parent.addItem(item[0], item[1])
}
})
}
下面例子介绍了前端不同的请求类型和 GAS 的不同处理数据的方式。
1. JSON 格式的 POST 请求
// GAS 服务端
function doPost (request) {
const json = JSON.parse(request.postData.contents)
return ContentService.createTextOutput('success')
}
// 前端 fetch
const params = {
action: '写入',
content: '测试'
}
await fetch(api, {
body: JSON.stringify(params),
method: 'POST'
}).then(response => response.text())
2. FormData 格式的 POST 请求
// GAS 服务端
function doPost (request) {
const json = request.parameter
return ContentService.createTextOutput('ok')
}
// 前端 fetch
const body = new FormData()
body.append('action', '写入')
body.append('content', '测试')
await fetch(api, {
body,
method: 'POST'
}).then(response => response.text())
3. GET 请求(参数拼接在 URL 里)
function doGet (request) {
const params = request.parameter
return ContentService.createTextOutput('ok')
}
// 前端 fetch
const params = {
action: '写入',
content: '测试'
}
await fetch(`${api}?${new URLSearchParams(params).toString()}`, {
body,
method: 'POST'
}).then(response => response.text())
在菜单栏加载自定义菜单,打开表格后自动加载。需要需要改对应的函数名称才会有功能。
// 删除多余行和列
function clearRowsColumns () {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('表格名字')
// 删除多余行
const maxRows = sheet.getMaxRows()
const lastRow = sheet.getLastRow()
if (lastRow !== 0 && maxRows - lastRow !== 0) sheet.deleteRows(lastRow + 1, maxRows - lastRow)
// 删除多余列
const maxColumns = sheet.getMaxColumns()
const lastColumn = sheet.getLastColumn()
if (lastColumn !== 0 && maxColumns - lastColumn !== 0) sheet.deleteColumns(lastColumn + 1, maxColumns - lastColumn)
}
根据指定内容删除行或者列,需要设置完整的范围,例如一整行或者一整列。
根据指定内容删除行
// 根据指定内容删除行
function deleteRowByContent () {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('表格名字')
// 检测的范围
const title = sheet.getRange('A:A').getValues()
for (let i = title.length - 1; i >= 0; i--) {
console.log(title[i], i)
// 判断的内容
if (title[i][0] === '备注') {
sheet.deleteRow(i + 1)
}
}
}
根据指定内容删除列
// 根据指定内容删除列
function deleteColumnByContent () {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('表格名字')
// 检测的范围
const title = sheet.getRange('1:1').getValues()[0]
for (let i = title.length - 1; i >= 0; i--) {
// 判断的内容
if (title[i] === '备注') {
sheet.deleteColumns(i + 1)
}
}
}
移除重复内容。
// 移除重复内容
function removeDuplicate () {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('表格名字')
sheet.getRange('A:R').removeDuplicates()
// 根据指定列内容排除重复
// sheet.getRange('A:R').removeDuplicates([4, 10])
}
根据函数名批量添加定时器。函数名为数组格式。
// 批量添加定时器
function setupTriggers () {
const funcList = ['函数名']
// 遍历函数名称数组,为每个函数设置定时器
funcList.forEach(funcName => {
ScriptApp.newTrigger(funcName)
.timeBased()
// 天定时器
// .atHour(2) // 0 ~ 23
// .everyDays(1)
// 小时定时器
// .everyHours(3) // 1, 2, 4, 6, 8, 12
// 分钟定时器
// .everyMinutes(2) // 1, 5, 10, 15 or 30
.create()
})
}
删除指定名字的定时器。
// 删除指定名字的定时器
function deleteTriggersByName () {
// 获取所有定时器
const triggers = ScriptApp.getProjectTriggers()
// 遍历所有触发器
for (let i = 0; i < triggers.length; i++) {
const trigger = triggers[i]
// 获取定时器名称
const triggerFunctionName = trigger.getHandlerFunction()
// 检测是否包含指定名字
if (triggerFunctionName.includes('需要删除的定时器名字')) {
ScriptApp.deleteTrigger(trigger)
}
}
}
删除所有定时器。
// 删除所有定时器
function deleteAllTriggers () {
// 获取所有定时器
const triggers = ScriptApp.getProjectTriggers()
for (let i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i])
}
}