#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() перед настройкой триггера.
Комментарии:
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 Вы тестировали первый вариант?