Как определить количество строк, вставленных в лист с помощью триггера onChange?

#google-apps-script #google-sheets #google-apps-script-editor

#google-apps-script #google-sheets #google-apps-script-editor

Вопрос:

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

Я хотел бы вставлять / удалять строки во втором в зависимости от строк, вставленных или удаленных в первом. Они должны соответствовать предыдущим данным.

Я пытался использовать триггер onChange для определения того, когда был обнаружен тип изменения INSERT_ROW или REMOVE_ROW. Он отлично работает, когда вставляется только строка, но не тогда, когда вставляется более одной. Кроме того, когда они вставляют строку и после отмены действия, тип изменения — EDIT, а не REMOVE_ROW. Сбой.

Затем я решил добавить скрытый столбец с номером индекса в каждой строке, поэтому, если между строками 5 и 6 есть разрыв в числах, это означает, что я должен вставить 3 строки на втором листе после 5-й строки, затем я перестроил индекс, чтобы проверить дальнейшие изменения… Это также работает, если было удалено несколько строк.

Казалось, что этот способ работает нормально, пока я не понял, что пользователи могут дублировать строки или копировать / вставлять полную строку, а затем изменять данные с новой информацией, НО индекс также копируется, и когда я проверяю разницу, чтобы проверить, была ли удалена какая-либо строка, происходит сбой.

Первая попытка:

   if (event.changeType == 'INSERT_ROW' amp;amp; tab =='Hoja 1') {
    for (var i = 0 ; i < indexes.length ; i  ) {
      if (indexes[i] =='') {
        destSheet.insertRowAfter(i 1);
      }
    }
  }
  if (event.changeType == 'REMOVE_ROW' amp;amp; tab =='Hoja 1') {
    for (var i = 0 ; i < indexes.length ; i  ) {
      if (indexes[i]-indexes[i 1] < -1 amp;amp; indexes[i] != 0) {
        if (indexes[i] != lastRow) {
          destSheet.deleteRows(i 3,(indexes[i]-indexes[i 1])*-1-1)
        }
      }
    }
  }
  for (var j = 0; j < lastRow-1; j  ) {
    indexs.getCell(j 1, 1).setValue(j 1);
  }
}
  

Вторая попытка:

 function checkLines (sheet, destSheet)  {
  for (var i = 0 ; i < indexes.length ; i  ) {
    if (indexes[i] =='') {
      destSheet.insertRowAfter(i 1);
    }
    if (indexes[i]-indexes[i 1] < -1 amp;amp; indexes[i] != 0) {
      if (indexes[i] != lastRow) {
        destSheet.deleteRows(i 3,(indexes[i]-indexes[i 1])*-1-1)
      }
    }
  }
}
  

Я хотел бы иметь копию выбранных столбцов исходного листа на целевом листе, и если первый изменит свои строки, то же самое должно произойти и во втором.

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

Вот ссылка на пример исходного листа: https://docs.google.com/spreadsheets/d/19OnwKIEm2OFymjsjqeoQYWcA9BNAJTM0ap2rdpQlZoQ/edit?usp=sharing

И вот пункт назначения: https://docs.google.com/spreadsheets/d/10vbMIqQE1miNfuJXQ1f_MSJnVs9MJrAOcg5_ZrAPWP8/edit?usp=sharing

Я буду признателен за любое предложение… И, пожалуйста, дайте мне знать, если вам понадобятся дополнительные пояснения… английский не является моим родным языком, и я не уверен, понимаете ли вы мою проблему.

Большое вам спасибо.

V.

Комментарии:

1. Как они вставляют больше, чем строку?

Ответ №1:

Вы можете использовать что-то вроде этого:

 function initRows() {//run once before first use
  var lastrow=SpreadsheetApp.getActiveSheet().getLastRow();
  PropertiesService.getScriptProperties().setProperty('ROWS',lastrow);
  return lastrow;
}

function getRows() {
  return PropertiesService.getScriptProperties().getProperty('ROWS');
}

function setRows(value) {
  PropertiesService.getScriptProperties().setProperty('ROWS',value);
}

function detectRowChange(e) {//attach to onChange installable trigger
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getActiveSheet();
  var number=Math.abs(getRows()-sh.getLastRow());
  var html=Utilities.formatString('Change Type: %s Number: %s', e.changeType,number);
  var ui=HtmlService.createHtmlOutput(html);
  SpreadsheetApp.getUi().showModelessDialog(ui, 'Change');
  setRows(sh.getLastRow());
}
  

При этом используется диалоговое окно для определения типа изменения и количества произведенных строк. Вероятно, вы захотите настроить его для своих конкретных нужд. Не забудьте запустить initRows() перед настройкой триггера.

PropertiesService

Комментарии:

1. Спасибо, Купер, но это решение сообщает мне только, сколько строк было добавлено или удалено, а не позицию.

Ответ №2:

Активный диапазон 1 содержит количество вставленных строк.

Фрагмент:

 function onChange(e){
  if (e.changeType === 'INSERT_ROW'){
    const rng = SpreadsheetApp.getActiveRange();
    const row = rng.getRow();//Row where insert row is done
    const lrow = rng.getLastRow();//Last row in the newly active range
    const numRows = 1 lrow-row;//number of rows inserted
  }
}
  

Также обратите внимание на добавление метаданных разработчика2 к строкам, чтобы при их перемещении вы могли их распознать.

Я хотел бы иметь копию выбранных столбцов исходного листа на целевом листе, и если первый изменит свои строки, то же самое должно произойти и во втором.

Самый простой способ — просто получить все данные и вставить их в лист назначения ( getValues и setValues ).

Комментарии:

1. Привет, мастер, спасибо за ваш ответ. Я попробую второй вариант (добавление метаданных), но это кажется довольно сложным (я новичок). Я сейчас посмотрю.

2. @VictorBoveelrowfamily Вы тестировали первый вариант?