Как ускорить перенос отфильтрованного набора данных из одной таблицы Google в другую с помощью AppScript

#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-х строках в вашем скрипте.
  • В качестве метода снижения стоимости вашего скрипта я хотел бы предложить следующий поток.
    1. Извлеките значения из «sheet1».
    2. Извлеките отфильтрованные значения.
    3. Поместите отфильтрованные значения в «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!