Google Apps Script批量设置谷歌表格指定文本颜色问题求助
问题描述
Sheet1中存在以下数据:
Sales count Increased to +12% in current Year
Sales Count Decreased to -12% in current Qtr
Florida Sales went Up Hawaii went Down
需求:通过Google Apps Script将指定文本标记为绿色加粗,目标文本数组为 pos_text = ['Increased','up','high','more','positive']。但修改后的代码仅数字部分变色,指定文本未生效,需排查原因并解决。
用户修改后的代码:
function changecolor() { var range = SpreadsheetApp.getActiveSpreadsheet() .getSheetByName("Sheet13").getRange("D2:H8"); var c_values = range.getValues(); var bold = SpreadsheetApp.newTextStyle().setBold(true).build(); var count = 0; var pos_text =['Increased','up','high','more','positive']; var colors; var srch_text='Increased'; Logger.log(pos_text.length); for(i=0;i<pos_text.length;i++){ const regex = new RegExp(pos_text[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),'gi'); const num_regex = new RegExp('[-]?[0-9]\&*','gi'); const format = SpreadsheetApp.newTextStyle().setBold(true).setForegroundColor('#55883B').build(); const values = range.getDisplayValues(); Logger.log(values); if(values!=null){ let match; const formattedText = values.map(row => row.map(value => { const richText = SpreadsheetApp.newRichTextValue().setText(value); while (match = regex.exec(value)) { Logger.log("While " + match); richText.setTextStyle(match.index, match.index + match[0].length, format); } while (match = num_regex.exec(value)) { richText.setTextStyle(match.index, match.index + match[0].length, format); } return richText.build(); })); range.setRichTextValues(formattedText); } } }
问题原因
- 循环覆盖样式:每次循环处理一个目标文本时,都会基于原始单元格文本重新生成富文本并覆盖整个区域的样式。例如第一次循环处理"Increased"时已生效,但第二次循环处理"up"时,会用原始文本重新构建富文本,之前设置的"Increased"样式被清空。最终只有最后一次循环的目标文本(若匹配到)会保留样式,若最后一个文本无匹配,就只剩数字的样式。
- 正则
g标志导致的匹配残留:使用带g标志的regex.exec()时,正则实例的lastIndex会记录上次匹配的位置,处理下一个单元格时不会自动重置,可能导致匹配失败。 - 数字正则表达式错误:原数字正则
[-]?[0-9]\&*中的\&是无效写法,实际是错误匹配,但巧合下能匹配数字部分,不过这不是核心问题。
解决方法
- 一次性处理所有目标文本:在单个单元格的富文本构建过程中,遍历所有目标文本进行匹配,避免循环覆盖整个区域的样式。
- 每次匹配时重置正则
lastIndex:避免g标志导致的匹配位置残留问题。 - 修正数字正则表达式:改为匹配带正负号、可选百分号的数字格式,如
[-+]?\d+%?。
修正后的代码
function changecolor() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const range = ss.getSheetByName("Sheet13").getRange("D2:H8"); const displayValues = range.getDisplayValues(); const pos_text = ['Increased','up','high','more','positive']; const format = SpreadsheetApp.newTextStyle() .setBold(true) .setForegroundColor('#55883B') .build(); // 预编译所有目标文本的正则,添加gi标志 const regexList = pos_text.map(text => new RegExp(text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi') ); // 修正数字正则:匹配带正负号、可选百分号的数字 const numRegex = new RegExp('[-+]?\\d+%?', 'gi'); const formattedText = displayValues.map(row => row.map(value => { const richText = SpreadsheetApp.newRichTextValue().setText(value); // 遍历所有目标文本正则进行匹配 regexList.forEach(regex => { let match; // 重置lastIndex,确保每次匹配从开头开始 regex.lastIndex = 0; while ((match = regex.exec(value)) !== null) { richText.setTextStyle(match.index, match.index + match[0].length, format); } }); // 匹配数字部分 let numMatch; numRegex.lastIndex = 0; while ((numMatch = numRegex.exec(value)) !== null) { richText.setTextStyle(numMatch.index, numMatch.index + numMatch[0].length, format); } return richText.build(); })); range.setRichTextValues(formattedText); }
内容的提问来源于stack exchange,提问作者Tpk43
相关产品推荐
相关产品推荐

