#google-apps-script #google-sheets
#google-apps-script #google-sheets
Вопрос:
Я написал короткий скрипт для копирования определенных строк с одного листа на другой. Начальный лист представляет собой набор данных большего размера, а второй лист должен быть фильтрованным набором, чтобы было проще создавать пользовательские графики в наборе данных.
Текущий код:
function updateChartRows() {
var sheetOriginal = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet1");
var sheetChart = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet2");
var filterValue = "someValue";
var matches = sheetOriginal.createTextFinder(filterValue);
var match = null;
var i = 0;
while ((match = matches.findNext()) != null) {
var search_range = sheetOriginal.getRange(match.getRowIndex(), 1,1,3);
var update_range = sheetChart.getRange(i 3,1,1,3);
update_range.setValues(search_range.getValues());
i ;
}
}
Код довольно прост. Он переходит к исходному листу и выполняет поиск данных на основе ключевого слова. Он получает массив ячеек, соответствующих ключевому слову.
Затем я перебираю массив совпадений и копирую значения всей строки этой ячейки в новую строку на втором листе. Нам нужны только значения из первых трех столбцов. (Мы можем предположить, что новый лист пуст, и мы начинаем с третьей строки из-за маркировки в первой и второй строке.)
Я замечаю, что время выполнения кода теперь составляет примерно 30 секунд. Что я нахожу довольно медленным, поскольку текущий исходный набор данных все еще находится на небольшой стороне. Примерно 60 записей.
Я предполагаю, что медлительность связана с циклом while. Для каждого совпадения необходимо выполнить поиск в исходном листе, чтобы найти правильные строки и значения.
Есть ли способ улучшить это? Например, вместо создания текстового навигатора есть ли лучший способ получить все соответствующие данные, включая фактические значения вместо ссылок на ячейку?
Я также попробовал функцию findAll() в текстовом навигаторе, но я по-прежнему получаю только ячейки ссылок, соответствующие ключевому слову. Таким образом, мне все еще нужно выполнить поиск, чтобы получить значения из всей строки.
Комментарии:
1. Я предложил модифицированный скрипт для снижения затрат на обработку скрипта. Не могли бы вы подтвердить это, пожалуйста? Если это было не то направление, которое вы ожидали, я приношу извинения.
2. Привет, @Tanaike, спасибо за качественный ответ. Собираюсь проверить ваше предложение позже сегодня. Но на первый взгляд это именно то, что я искал. Что касается ошибки «chosen_stock», хороший улов! Я попытался упростить код для целей вопроса. Итак, я переименовал некоторые переменные и хотел удалить параметры. Думаю, что-то пошло не так. Изменит это в вопросе.
Ответ №1:
Я считаю, что ваша цель заключается в следующем.
- Вы хотите получить значения из «sheet1».
- Вы хотите выполнить поиск значений с помощью
filterValue
. - Вы хотите поместить отфильтрованные значения в «sheet2».
- Вы хотите снизить стоимость процесса скрипта.
Точки модификации:
- Например,
SpreadsheetApp.getActiveSpreadsheet()
может использоваться какvar ss = SpreadsheetApp.getActiveSpreadsheet()
. Благодаря этому стоимость может быть снижена на 1-й и 2-х строках в вашем скрипте. - В качестве метода снижения стоимости вашего скрипта я хотел бы предложить следующий поток.
- Извлеките значения из «sheet1».
- Извлеките отфильтрованные значения.
- Поместите отфильтрованные значения в «sheet2».
- Я подумал, что стоимость может быть снижена за счет обработки процесса фильтрации в массиве.
Когда вышеуказанные пункты отражены в вашем скрипте, это становится следующим.
Модифицированный скрипт:
function updateChartRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetOriginal = ss.getSheetByName("sheet1");
var sheetChart = ss.getSheetByName("sheet2");
var filterValue = "someValue";
// 1. Retrieve the values from "sheet1".
var srcValues = sheetOriginal.getDataRange().getValues();
// 2. Retrieve the filtered values.
var dstValues = srcValues.reduce((ar, e) => {
if (e.some(f => f === filterValue)) ar.push(e.splice(0, 3));
return ar;
}, []);
// 3. Put the filtered values to "sheet2".
sheetChart.getRange(3, 1, dstValues.length, dstValues[0].length).setValues(dstValues);
}
Ссылки:
Комментарии:
1. Я не мог дождаться, чтобы протестировать ваш код. Увеличение скорости составляет примерно от 30 секунд до примерно 1 секунды. Большое спасибо @Tanaike!