Скрипт листов Google запускается при добавлении строк и копирует результаты на другой лист - PullRequest
1 голос
/ 10 октября 2019

Я запустил скрипт, который разбивает данные через запятую на новые строки с помощью функции на листе, отличном от исходных данных. Количество данных выросло, и расчет занимает вечность.

с бесконечным индикатором выполнения

Пример электронной таблицы приведен здесь (с небольшим количеством данных): https://docs.google.com/spreadsheets/d/1e0YhJqHn62jju7KOOy5U2JZ5FLCv6_oeY-mc_jRF5-4/edit?usp=sharing

Сценарий следующий:

function extract(range, colToSplit, delimiter) {
var resArr = [], row;
range.forEach(function (r) {
    r[colToSplit-1].replace(/(?:\r\n|\r|\n)(\d|\w)/g," , ").split(delimiter)
        .forEach(function (s) {
            row = [];
            r.forEach(function (c, k) {               
                row.push( (k === colToSplit-1) ? s.trim() : c);
            })
            resArr.push(row);
        })
})
return resArr;}

Вопрос в том, как запустить этот сценарий только для новых данных и скопировать результат в другой лист «статические без формул» таким образом, чтобы сценарий не запускался при каждом изменении для ВСЕХ. данные.

Мои наилучшие пожелания богам сценариев.

Ответы [ 3 ]

0 голосов
/ 10 октября 2019

Вы можете создать html для своей функции на боковой панели очень просто следующим образом:

function showButtonDialog() {
  var ss=SpreadsheetApp.getActive();
  var html='<input type="text" id="rng" /> Range<br /><input type="text" id="col" /> Column<br /><input type="text" id="dlm" /> Delimiter<br /><input type="button" value="run extract" onClick="extract();" />';
  html+='<script>function extract() {google.script.run.extract(document.getElementById("rng").value,document.getElementById("col").value,document.getElementById("dlm").value);}</script>';
  var userInterface=HtmlService.createHtmlOutput(html);
  SpreadsheetApp.getUi().showSidebar(userInterface);
}

Это будет проверять, что вы получаете правильные параметры

function extract(a,b,c) {
  Logger.log('rng: %s col: %s del: %s',a,b,c);
}

Возможно, вам придется немного подправить свою функцию. Но, судя по всему, у вас не возникнет проблем с этим.

0 голосов
/ 07 ноября 2019

Я видел, что вы не приняли мой предыдущий ответ;Я предполагаю, что это больше не служит вашей цели. Здесь я предоставляю еще одно решение, которое делает то, что вы изначально просили - это обработка только новых строк. Это достигается с помощью Свойства скрипта .

См. Ниже весь код:

var COL_TO_SPLIT = 6;
var DELIMITER = " , ";
var NUM_COLUMNS = 16;

function extract(range, colToSplit, delimiter) {
  var resArr = [];
  range.forEach(function (r) {
    r[colToSplit-1].replace(/(?:\r\n|\r|\n)(\d|\w)/g," , ").split(delimiter)
      .forEach(function (s) {
          var row = [];
          r.forEach(function (c, k) {               
              row.push( (k === colToSplit-1) ? s.trim() : c);
          });
          resArr.push(row);
      });
  });
  return resArr;
}

function getCurrentRow() {
  var currentRow = PropertiesService.getScriptProperties().getProperty('currentRow');
  if (currentRow === null) {
    currentRow = 2;
  }
  return parseInt(currentRow);
}

function updateCurrentRow(newRow) {
  PropertiesService.getScriptProperties().setProperty('currentRow', newRow);
}

// Returns the new "currentRow"
function migrateRowsFrom(row) {
  var ss = SpreadsheetApp.getActive();
  var sourceSheet = ss.getSheetByName('Sheet1');
  var destinationSheet = ss.getSheetByName('Sheet2');

  var rowsToProcess = sourceSheet.getLastRow() - row + 1;
  if (rowsToProcess <= 0) return sourceSheet.getLastRow() + 1;
  var rows = sourceSheet.getRange(row, 1, rowsToProcess, NUM_COLUMNS).getDisplayValues();

  var extracted = extract(rows, COL_TO_SPLIT, DELIMITER);
  destinationSheet.getRange(destinationSheet.getLastRow() + 1, 1, extracted.length, extracted[0].length).setValues(extracted);

  return sourceSheet.getLastRow() + 1;
}

function update() {
  var lock = LockService.getDocumentLock();
  lock.waitLock(10000); // Wait (up to) 10s to acquire the lock

  var currentRow = getCurrentRow(); // currentRow is the row from which the script should run. i.e. if the last execution ended at row 2 (included), the value should be left to be 3. 1-indexed.
  var newCurrentRow = migrateRowsFrom(currentRow);
  updateCurrentRow(newCurrentRow);

  lock.releaseLock();
}

Функция, которую вы должны вызвать - update(). Он извлечет строку, в которой было остановлено последнее выполнение, обработает столько строк, сколько возможно, а затем обновит это значение, чтобы при следующем выполнении было известно, с чего начать.

Обратите внимание, что при этом данные будут перемещены из Sheet1, обработайте его, а затем вставьте в Sheet2. Конечно, вы можете изменить эти значения по мере необходимости. Также помните, что вам не следует изменять значения Sheet1;поскольку, поскольку они уже были обработаны, они больше не будут обрабатываться.

0 голосов
/ 10 октября 2019

Вместо использования функции ячейки вы можете использовать скрипт и запускать его через редактор или с помощью кнопки на вашем листе. Таким образом, вы получите преимущество от их 6-минутного ограничения времени (см. квоты ).

Функция может быть изменена как таковая, а затем назначена ее для кнопки, которая будет запускаться какСобытие onClick (подробнее об этом здесь ):

function extract() {
var resArr = [], row;
var colToSplit = 6;
var delimiter = " , ";
range = SpreadsheetApp.getActive().getSheets()[0].getDataRange().getValues();
range.forEach(function (r) {
    r[colToSplit-1].replace(/(?:\r\n|\r|\n)(\d|\w)/g," , ").split(delimiter)
        .forEach(function (s) {
            row = [];
            r.forEach(function (c, k) {               
                row.push( (k === colToSplit-1) ? s.trim() : c);
            })
            resArr.push(row);
        })
})
SpreadsheetApp.getActive().getSheets()[1].getRange(1, 1, resArr.length, resArr[0].length).setValues(resArr);
}

Пожалуйста, дайте мне знать, если у вас есть другие вопросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...