谷歌表格批量替换学期代码超时问题优化求助
谷歌表格批量替换学期代码超时问题优化求助
我最近在谷歌表格里折腾一个批量替换的脚本,想把一堆数字格式的学期代码(比如把201305换成Summer Semester 2013)转换成易读的学期名称。数据量不小,有25000多条记录,但其实我只需要处理R到U列,而且是行号大于14374的部分——前面的行已经处理过了,不用再碰。
之前我找了个类似问题的脚本改了改,少量替换的时候没问题,但现在替换的学期代码超过25个之后,脚本老是超时崩溃。我试着想限定处理的列和行,结果老是报错,实在搞不定了,来求助大家怎么调整代码才能高效运行,不超时。
先给大家看看我现在用的代码:
function runReplaceInSheet(){ var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Enrolled"); // 获取全表数据数组 var values = sheet.getDataRange().getValues(); // 一堆替换规则,逐个调用替换函数 replaceInSheet(values, 201301, 'Spring Semester 2013'); replaceInSheet(values, 201305, 'Summer Semester 2013'); replaceInSheet(values, 201308, 'Fall Semester 2013'); replaceInSheet(values, 201401, 'Spring Semester 2014'); replaceInSheet(values, 201405, 'Summer Semester 2014'); replaceInSheet(values, 201408, 'Fall Semester 2014'); replaceInSheet(values, 201501, 'Spring Semester 2015'); replaceInSheet(values, 201505, 'Summer Semester 2015'); replaceInSheet(values, 201508, 'Fall Semester 2015'); replaceInSheet(values, 201601, 'Spring Semester 2016'); replaceInSheet(values, 201605, 'Summer Semester 2016'); replaceInSheet(values, 201608, 'Fall Semester 2016'); replaceInSheet(values, 201701, 'Spring Semester 2017'); replaceInSheet(values, 201705, 'Summer Semester 2017'); replaceInSheet(values, 201708, 'Fall Semester 2017'); replaceInSheet(values, 201801, 'Spring Semester 2018'); replaceInSheet(values, 201805, 'Summer Semester 2018'); replaceInSheet(values, 201808, 'Fall Semester 2018'); replaceInSheet(values, 201901, 'Spring Semester 2019'); replaceInSheet(values, 201905, 'Summer Semester 2019'); replaceInSheet(values, 201908, 'Fall Semester 2019'); replaceInSheet(values, 202001, 'Spring Semester 2020'); replaceInSheet(values, 202005, 'Summer Semester 2020'); replaceInSheet(values, 202008, 'Fall Semester 2020'); replaceInSheet(values, 202101, 'Spring Semester 2021'); replaceInSheet(values, 202105, 'Summer Semester 2021'); replaceInSheet(values, 202108, 'Fall Semester 2021'); replaceInSheet(values, 202201, 'Spring Semester 2022'); replaceInSheet(values, 202205, 'Summer Semester 2022'); replaceInSheet(values, 202208, 'Fall Semester 2022'); replaceInSheet(values, 202301, 'Spring Semester 2023'); replaceInSheet(values, 202305, 'Summer Semester 2023'); replaceInSheet(values, 202308, 'Fall Semester 2023'); replaceInSheet(values, 202401, 'Spring Semester 2024'); replaceInSheet(values, 202405, 'Summer Semester 2024'); replaceInSheet(values, 202408, 'Fall Semester 2024'); replaceInSheet(values, 202501, 'Spring Semester 2025'); replaceInSheet(values, 202505, 'Summer Semester 2025'); replaceInSheet(values, 202508, 'Fall Semester 2025'); // 把修改后的数据写回全表 sheet.getDataRange().setValues(values); } function replaceInSheet(values, to_replace, replace_with) { // 遍历每一行 for(var row in values){ // 遍历该行每个单元格,执行替换 var replaced_values = values[row].map(function(original_value) { return original_value.toString().replace(to_replace,replace_with); }); values[row] = replaced_values; } }
我琢磨着超时的原因主要有两个:一是现在脚本要遍历全表所有列(从A到CB列),但其实只有R-U列需要处理;二是每一条替换规则都要完整遍历一遍整个数据数组,25+条规则就等于把全表扫了25+次,这肯定慢得离谱。
给大家分享几个优化思路,我调整后的代码应该能解决超时问题:
优化点1:只处理需要的范围
直接获取R-U列、行号>14374的区域数据,不用碰全表。谷歌表格的列号是从1开始算的,R列是第18列,U列是第21列,所以我们只需要取这个范围的数组来处理。
优化点2:用映射表一次完成所有替换
把所有替换规则做成一个对象,遍历数据的时候只需要查一次映射表,就能完成所有替换,不用反复遍历数组。
优化点3:减少不必要的字符串转换
只有当单元格的值匹配映射表里的键时才替换,避免每次都把单元格转成字符串,节省资源。
下面是修改后的完整代码:
function runReplaceInSheet() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Enrolled"); const startRow = 14375; // 从第14375行开始处理 const startCol = 18; // R列对应的列号 const endCol = 21; // U列对应的列号 const numCols = endCol - startCol + 1; const numRows = sheet.getLastRow() - startRow + 1; // 只获取需要处理的区域数据 var range = sheet.getRange(startRow, startCol, numRows, numCols); var values = range.getValues(); // 把所有替换规则做成映射表,一次遍历就能完成所有替换 const semesterMap = { 201301: 'Spring Semester 2013', 201305: 'Summer Semester 2013', 201308: 'Fall Semester 2013', 201401: 'Spring Semester 2014', 201405: 'Summer Semester 2014', 201408: 'Fall Semester 2014', 201501: 'Spring Semester 2015', 201505: 'Summer Semester 2015', 201508: 'Fall Semester 2015', 201601: 'Spring Semester 2016', 201605: 'Summer Semester 2016', 201608: 'Fall Semester 2016', 201701: 'Spring Semester 2017', 201705: 'Summer Semester 2017', 201708: 'Fall Semester 2017', 201801: 'Spring Semester 2018', 201805: 'Summer Semester 2018', 201808: 'Fall Semester 2018', 201901: 'Spring Semester 2019', 201905: 'Summer Semester 2019', 201908: 'Fall Semester 2019', 202001: 'Spring Semester 2020', 202005: 'Summer Semester 2020', 202008: 'Fall Semester 2020', 202101: 'Spring Semester 2021', 202105: 'Summer Semester 2021', 202108: 'Fall Semester 2021', 202201: 'Spring Semester 2022', 202205: 'Summer Semester 2022', 202208: 'Fall Semester 2022', 202301: 'Spring Semester 2023', 202305: 'Summer Semester 2023', 202308: 'Fall Semester 2023', 202401: 'Spring Semester 2024', 202405: 'Summer Semester 2024', 202408: 'Fall Semester 2024', 202501: 'Spring Semester 2025', 202505: 'Summer Semester 2025', 202508: 'Fall Semester 2025' }; // 遍历数据,一次完成所有替换 for (let i = 0; i < values.length; i++) { for (let j = 0; j < values[i].length; j++) { const cellValue = values[i][j]; // 如果单元格的值在映射表里存在,就替换 if (semesterMap.hasOwnProperty(cellValue)) { values[i][j] = semesterMap[cellValue]; } } } // 只把修改后的数据写回原来的区域,不用动全表 range.setValues(values); }
这个修改后的脚本做了这几件事:
- 精准定位需要处理的R-U列、14375行及以后的区域,避免处理无关数据
- 用一个映射表存储所有替换规则,只需要遍历一次数据就能完成所有替换,减少了25+次的全数组遍历
- 只替换匹配映射表的单元格,减少不必要的操作
- 最后只把修改后的区域写回表格,而不是全表写入,进一步节省资源
这样应该就能解决超时的问题了,亲测比原来的脚本快很多!
备注:内容来源于stack exchange,提问作者Matt Varga
相关产品推荐
相关产品推荐

