Как сравнить два листа и удалить / добавить любой столбец с отличным значением в строке 1? Google Script - PullRequest
0 голосов
/ 16 февраля 2020

Я хочу сравнить два листа (на основе значений заголовка в строке 1) и удалить любой столбец с уникальным значением (без совпадения). Например, предполагая, что данные Sheet1, Row 1 и Sheet 2, Row 1 одинаковы, если пользователь добавляет / удаляет столбец на любом листе, я хочу всегда сопоставлять количество столбцов на обоих листах с их значениями

Скриншоты заголовков листов.

ЕСЛИ оба листа выглядят так enter image description here

И пользователь добавляет новый столбец N enter image description here

Или удалить столбец N

enter image description here

Как можно обеспечить совпадение обоих листов, удалив нечетный / отличный столбец на Листе 1?

Я попытался изменить этот код ниже, но я не могу просто получить уникальный. Этот код ищет только заголовки с определенным значением.

function deleteAloneColumns(){
  var sheet = SpreadsheetApp.getActiveSheet();
  var lastColumnPos = sheet.getLastColumn();
  var headers = sheet.getRange( 1 ,1, 1, lastColumnPos ).getValues()[0];
  for( var i = lastColumnPos ; i < 1; i--){
    if( headers[i] === "alone" ) sheet.deleteColumn(i);
  }
 SpreadsheetApp.getUi().alert( 'Job done!' );
}

Будет полезна любая помощь для сравнения и удаления столбца с уникальным значением.

1 Ответ

0 голосов
/ 17 февраля 2020

Проблема

Балансировка на основе несоответствия значений строки заголовка.

Решение

Если я вас правильно понял, у вас есть исходный лист, для которого выполняется проверка, и два основных варианта использования: пользователь добавляет новый столбец с именем, отличным от любого другого столбца (если вы хотите убедиться, что столбец строго соответствует столбцу в sheet1, его легко изменить) в исходный лист или удаляет тот, который должен быть там.

const balanceSheets = (sourceShName = 'Sheet1',targetShName = 'Sheet2') => {
  const ss = SpreadsheetApp.getActiveSpreadsheet();

  const s1 = ss.getSheetByName(sourceShName);
  const s2 = ss.getSheetByName(targetShName);

  const s2lcol = s2.getLastColumn();

  //keep all vals from source to reduce I/O
  const s1DataVals = s1.getDataRange().getValues();

  const s2Vals = s2.getRange(1, 1, 1, s2lcol).getValues();

  const h1Vals = s1DataVals[0];
  const h2Vals = s2Vals[0];

  //assume s1 is source (validation) sheet
  //assume s2 is target sheet that a user can edit

  //case 1: target has value not present in source -> delete column in target
  let colIdx = 0;
  h2Vals.forEach(value => {
    const isOK = h1Vals.some(val => val===value);

    isOK ? colIdx++ : s2.deleteColumn(colIdx+1);
  });

  //case 2: target does not have values present in source -> append column from source
  h1Vals.forEach((value,index) => {
    const isOK = h2Vals.some(val => val===value);
    !isOK && s2.insertColumnAfter(index);

    const valuesToInsert = s1DataVals.map(row => [row[index]]);

    const numRowsToInsert = valuesToInsert.length;

    s2.getRange(1,index+1, numRowsToInsert,1).setValues(valuesToInsert);
  });

};

Витрина

Вот небольшая демонстрация того, как он работает как макрос:

Balancer demo

Примечания

  1. Решение вашей проблемы с двумя forEach неоптимально, но я сохранил число I / O low (его можно еще больше снизить, например, перемещая deleteColum из l oop, сохраняя при этом только отслеживание индексов столбцов).
  2. Скрипт использует возможности ES6, предоставляемые V8, поэтому, пожалуйста, , будьте осторожны (хотя я бы порекомендовал мигрировать как можно скорее - даже если вы Вы можете столкнуться с ошибками / несоответствиями, это стоит больше, чем стоит.
  3. UPD делает скрипт более гибким, перемещая имена листов в список параметров.
  4. UPD2 после обсуждения проблемы с поведением deleteColumn() ответ обновляется, чтобы указатель столбца оставался в границах (для любопытных - forEach продолжал увеличивать index, тогда как deleteColumn уменьшал границы для любого заданного индекса) .

Ссылка

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