[英]How to speed up surprisingly slow Google Sheets Apps Script functions that copy formulas from one column to newly inserted column
I have a workbook with multiple sheets, and the main sheet has 123 rows and 90 columns currently.我有一个包含多张工作表的工作簿,主工作表目前有 123 行和 90 列。
I've coded the following functions (which work) to define an onChange
event handler for the INSERT_COLUMN
event that automatically populates the cells of the newly-inserted column with the contents of the column immediately to the left.我编写了以下函数(可以工作)来为INSERT_COLUMN
事件定义一个onChange
事件处理程序,该事件处理程序自动将新插入的列的单元格填充为紧靠左侧的列的内容。 Then it deletes the values of the cells that are not formulas.然后它删除不是公式的单元格的值。
It's painfully slow, and I'm not sure why.它非常缓慢,我不知道为什么。
How can I speed this up?我怎样才能加快速度? Thanks.谢谢。
function getColumnLetter(a1Notation) {
const letter = a1Notation.replace(/\d+/, '');
return letter;
}
function getColumnLetterFromNumber(sheet, colNum) {
const range = sheet.getRange(1, colNum);
return getColumnLetter(range.getA1Notation());
}
function forEachRangeCell(range, callback) {
const numRows = range.getNumRows();
const numCols = range.getNumColumns();
for (let i = 1; i <= numCols; i+=1) {
for (let j = 1; j <= numRows; j+=1) {
const cell = range.getCell(j, i);
callback(cell);
}
}
}
function deleteAllValuesAndNotesFromNonFormulaCells(range) {
forEachRangeCell(range, function (cell) {
if(!cell.getFormula()){
cell.setValue(null);
cell.clearNote();
}
});
}
function onInsertColumn(sheet, activeRng) {
if (activeRng.isBlank()) {
const minCol = 5;
const col = activeRng.getColumn();
if (col >= minCol) {
const prevCol = col - 1;
const colLetter = getColumnLetterFromNumber(sheet, col);
const prevColLetter = getColumnLetterFromNumber(sheet, prevCol);
//SpreadsheetApp.getUi().alert(`Please wait while formulas are copied to the new column...`);
const originRng = sheet.getRange(`${prevColLetter}:${prevColLetter}`);
originRng.copyTo(activeRng, SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
deleteAllValuesAndNotesFromNonFormulaCells(activeRng);
const completeMsg = `New column ${colLetter} has formulas copied and is ready for new values (such as address, Redfin link, data, ratings).`;
//SpreadsheetApp.getUi().alert(completeMsg);
// SpreadsheetApp.getActiveSpreadsheet().toast(completeMsg);
}
}
}
function onChange(event) {
if(event.changeType === 'INSERT_COLUMN'){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet()
const colNumber = sheet.getSelection().getActiveRange().getColumn();
const activeRng = sheet.getRange(1,colNumber,sheet.getMaxRows(),1);
const sheetName = sheet.getName();
if(sheetName === 'ratings'){
onInsertColumn(sheet, activeRng);
}
}
}
Not sure if I fully understand the problem.不确定我是否完全理解这个问题。 So here is a guess.所以这里有一个猜测。
I'd try to change the function with the fancy name deleteAllValuesAndNotesFromNonFormulaCells()
this way:我会尝试用这种花哨的名称deleteAllValuesAndNotesFromNonFormulaCells()
更改函数:
function deleteAllValuesAndNotesFromNonFormulaCells(range) {
// get the array with all formulas
var formulas = range.getFormulas();
// set all formulas back (it will clear all cells with no formula)
range.setFormulas(formulas);
// get the array with all notes and
// clear the ements of the 'notes' array that are empty in the array 'formulas'
var notes = range.getNotes().map((x,i) => formulas[i][0] ? x : ['']);
// set the modified array 'notes' back on the sheet
range.setNotes(notes);
}
If you don't need to keep the notes the function can be boiled down to just one line:如果您不需要保留注释,则该功能可以归结为一行:
function deleteAllValuesAndNotesFromNonFormulaCells(range) {
range.setFormulas(range.getFormulas()).clearNote();
}
Description描述
I don't understand the need for a lot of what the OP has developed.我不明白对 OP 开发的很多东西的需求。 But here is an example of inserting a column to the right, take the column to the left of it and copy it to the new column.但这里是一个在右侧插入一列的示例,将其左侧的列复制到新列中。 Then eliminate any values or notes leaving only the formulas.然后消除任何值或注释,只留下公式。
Since getFormulas() returns a 2D array of strings representing the formulas in the range simpy using setValues(formulas) places the formulas into the cells.由于 getFormulas() 返回代表范围内公式的二维字符串数组,因此使用 setValues(formulas) 将公式放入单元格中。
Code.gs代码.gs
function onChange(e) {
try {
if( e.changeType === "INSERT_COLUMN" ) {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let sheet = spread.getActiveSheet();
if( sheet.getName() === "Sheet1" ) {
// assume insert column to the right
let colNumber = sheet.getSelection().getActiveRange().getColumn();
if( colNumber >= 5 ) {
let activeRng = sheet.getRange(1,colNumber,sheet.getLastRow(),1);
let originRng = sheet.getRange(1,colNumber-1,sheet.getLastRow(),1);
originRng.copyTo(activeRng);
let formulas = activeRng.getFormulas();
activeRng.setValues(formulas);
activeRng.clearNote();
}
}
}
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
Reference参考
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.