Сравните 4 разных столбца в 2 разных Google Sheets - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь сравнить данные с 2 листов Google.На каждом листе есть столбец, который является идентификатором (sheet1: H и sheet2: C), если они совпадают, я хочу изменить sheet1: I на значение в sheet2: E.Я запускаю этот код, но не получаю ошибок.Это не работает, хотя.

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

function changestatus() {
  // gets spreadsheet A and the range of data
  ssA = SpreadsheetApp.openById('IDHERE');
  sheetA = ssA.getSheetByName('Sheet1');
  dataA = sheetA.getRange('H2:H').getValues();
  dataD = sheetA.getRange('I2:I').getValues();

  // gets spreadsheet B and the range of data
  ssB = SpreadsheetApp.openById('IDHERE');
  sheetB = ssB.getSheetByName('responses');
  dataB = sheetB.getRange('C2:C').getValues();
  dataC = sheetB.getRange('E2:E').getValues();

  for (var i = 0; i > sheetA.getLastRow(); i++) {
    if (dataA[1][i] == dataB[1][i] && dataC[1][i] != dataD[1][i]){
      var value = sheetA.getRange(i+1, 2).getValue(dataD);
      sheetB.getRange(i+1, 2).setValue(value);
    } // end if
  } // end i

Начальные результаты файлов листов будутчто-то вроде:

Лист 1
H: (ID) 1 I: (оценка) проход

Лист 2
C: (ID) 1 E: (оценка) ошибка

После функции:

Лист 1
H: (ID) 1 I: (класс), сбой

1 Ответ

1 голос
/ 28 марта 2019

@ tehhowch совершенно верно;вам нужно просмотреть операторы сравнения JavaScript, синтаксис цикла, формат объекта, возвращаемого Range # getValues, и способы доступа к индексам массива JavaScript.Каждый из них вносит свой вклад в проблемы с кодом, но разумно, что мы поможем вам в дальнейшем.

Синтаксис цикла
Это очень просто.Вместо «i> sheetA.getLastRow ()» он должен читать i < sheetA.getLastRow().i начинается со значения ноль, и его значение увеличивается на единицу в конце каждого цикла;поэтому вы хотите, чтобы цикл обрабатывал все значения i, которые меньше значения последней строки.

Значения массива
getValues возвращает двумерный массив, нооператор IF не выполняется, поскольку значения массива возвращаются вперед.

Например, вместо «dataA [1] [i]» должно быть dataA[i][0].Здесь есть два изменения:
1 - «i» перемещается в первую половину значения массива (значение 'row');и
2 - вторая половина значения массива равна [0] (не «[1]»).Это потому, что каждая переменная имеет ширину всего в один столбец.Например, dataA только возвращает значение столбца H;То же самое верно для dataB, dataC и dataD - все они возвращают значение только одного столбца.

Устранение неполадок
Как вы можете определить, была ли инструкция IF проблемой?Это "выглядит" хорошо.Одним из способов является отображение (или запись) возвращаемых значений.Я использую Logger.log() (есть другие варианты) для отображения информации в редакторе сценариев в разделе «Просмотр, журналы».Каждый раз, когда скрипт запускается, операторы «Logger» обновляются, и вы можете проверить их значение.

Например, вы можете вставить этот код в строку 13 (перед циклом), чтобы проверить некоторые значения переменных данных.
Logger.log("dataA[1][0] = "+dataA[1][0]);
В этой строке будет показано: "dataA [1][0] = 2 ".Это правильный результат, но вы можете заметить, что он сообщает об ID = 2, но, скажем, вы ожидали результата с ID = 1.

Поэтому измените строку на:
Logger.log("dataA[1][1] = "+dataA[1][1]);
Эта строка показывает «dataA [1] [1] = undefined».ОК, что-то определенно не так.

Итак, давайте попробуем:
Logger.log("dataA[0][0] = "+dataA[0][0]);
В этой строке показано «dataA [0] [0] = 1».Теперь это больше похоже на это.

Вы можете сделать Logger длинным или коротким;Например, вы можете оценить результаты переменных в одной строке.Таким образом, регистратор может выглядеть так:
Logger.log("dataA[0][0] = "+dataA[0][0]+", dataB[0][0] = "+dataB[0][0]+", dataC[0][0] = "+dataC[0][0]+", dataD[0][0] = "+dataD[0][0]);
И он будет возвращать:
"dataA [0] [0] = 1, dataB [0] [0] = 1, dataC [0][0] = Fail, dataD [0] [0] = Pass ".
Это может подтвердить, что вы находитесь на правильном пути, или что вам нужно продолжить отладку

The Failing IFоператор
Исходная строка = "(dataA [1] [i] == dataB [1] [i] && dataC [1] [i]! = dataD [1] [i])"
Исправленная строка = (dataA[i][0] == dataB[i][0] && dataC[i][0] != dataD[i][0])

Обновление результатов на листе 1
Код здесь:
var value = sheetA.getRange(i+1, 2).getValue(dataD);
sheetB.getRange(i+1, 2).setValue(value);

Это сбивает с толку и усложняет несколько вещей.
1 - значение просто должно быть "значением на листе 2: E - это было в операторе IF: dataC[i][0]. Так что value = dataC[i][0]
2- Цель состоит в том, чтобы «изменить sheet1: I на значение в sheet2: E». Вы уже получили это значение, поэтому сосредоточитесь сейчас на sheet1: I. В некоторых случаях проще определить диапазон, а затем на секундустрока, обновите значение для этого диапазона.

  • целевой лист - sheetA;
  • целевойСтрока t: i + 1 (это было правильно);
  • целевой столбец: I (или столбец 9).

Итак, var range = sheetA.getRange(i+2, 9); Вы можете проверить это с помощью «Logger»:
Logger.log("range = "+range.getA1Notation()); может вернуться "range = I2 ".

Затем обновите значение: range.setValue(value);

Значимые имена переменных
Это помогает (МНОГО) использовать значимые имена переменных.Например, оригинальный код использует:
"dataA" = Sheet1, столбец H (содержит идентификатор);поэтому, возможно, это может быть «data1_H» или даже «targetID.
« dataD »= Sheet1, столбец I (содержит оценку), поэтому, возможно, это может быть« data1_I »или targetGrade.
« dataB "= Sheet2, ColumnC (содержит идентификатор), поэтому, возможно, это может быть «data2_C» или sourceID.
«dataC» = Sheet2, столбец E (содержит оценку);так что, возможно, это может быть "data2_E" или sourceGrade.


Сводка изменений

function so_changestatus() {
  // gets spreadsheet A and the range of data
  ssA = SpreadsheetApp.openById('IDHERE');
  sheetA = ssA.getSheetByName('Sheet1');
  dataA = sheetA.getRange('H2:H').getValues();
  dataD = sheetA.getRange('I2:I').getValues();

  // gets spreadsheet B and the range of data
  ssB = SpreadsheetApp.openById('IDHERE');
  sheetB = ssB.getSheetByName('responses');
  dataB = sheetB.getRange('C2:C').getValues();
  dataC = sheetB.getRange('E2:E').getValues();


  for (var i = 0; i < sheetA.getLastRow(); i++) {
    if (dataA[i][0] == dataB[i][0] && dataC[i][0] != dataD[i][0]){
      var value = dataC[i][0];
      var range = sheetA.getRange(i+2, 9);
       range.setValue(value);
    } // end if
  } 
}

ОБНОВЛЕНИЕ - 1 апреля 2019
ID на Листе Avs SheetB НЕ соответствует строка за строкой
Оригинальный код был написан на основе того, что идентификатор совпадает строка за строкой.Это не вариант.Таким образом, изменение кода необходимо для проверки того, существует ли идентификатор SheetA на SheetB, а затем для проверки соответствующего состояния.

Оценка идентификатора SheetA на sheetB выполняется с помощью [indexof] Docs.ссылка .

В этом коде я также воспользовался возможностью, чтобы сделать имена переменных диапазонов данных более значимыми.

Обратите также внимание: цикл продолжается, пока i меньше, чемlastrow минус один"i <(lastrow-1);".Это необходимо, поскольку первая строка является заголовком, а диапазон данных начинается со строки 2, поэтому число строк данных будет «последняя строка минус один» (с учетом строки заголовка). </p>

function ejb2so_changestatus() {
  // gets spreadsheet A and the range of data

  //  ssA = SpreadsheetApp.openById('IDHERE');
  ssA = SpreadsheetApp.getActive();
  sheetA = ssA.getSheetByName('Sheet1');
  dataA_ID = sheetA.getRange('H2:H').getValues();
  data_Status = sheetA.getRange('I2:I').getValues();
  //Logger.log("DEBUG: H3 = "+dataA_ID[4][0]+", I3 = "+data_Status[4][0]);//DEBUG

  // gets spreadsheet B and the range of data
  //ssB = SpreadsheetApp.openById('IDHERE');
  ssB = SpreadsheetApp.getActive();
  sheetB = ssB.getSheetByName('Responses');
  dataB_ID = sheetB.getRange('C2:C').getValues();
  dataB_Status = sheetB.getRange('E2:E').getValues();
  // Logger.log("DEBUG: C3 = "+dataB_ID[0][0]+", E3 = "+dataB_Status[0][0]);//DEBUG

  var lastrow = sheetA.getLastRow()
  // Logger.log("DEBUG: sheetA last row = "+lastrow);//DEBUG

  // Flatten the array
  var dataB_IDFlat = dataB_ID.map(function(row) {
    return row[0];
  });

  //Loop through values on sheetA; check if they exist on sheetB
  for (var i = 0; i < (lastrow - 1); i++) {
    var A_ID = dataA_ID[i][0];
    // Logger.log("DEBUG: id = "+A_ID);//DEBUG

    // assign variable to return value index
    var result = dataB_IDFlat.indexOf(A_ID);

    if (result != -1) {
      // it's there 
      // Logger.log("DEBUG: i: "+i+", ID: "+A_ID+", it's there"+", result#: "+result);//DEBUG
      // Logger.log("DEBUG: Sheet1 status: "+data_Status[i][0]+" Vs Sheet2 status = "+dataB_Status[result][0]);//DEBUG

      // compare status from sheetsA to sheetB
      if (data_Status[i][0] != dataB_Status[result][0]) {
        // Logger.log("DEBUG: status change to: "+dataB_Status[result][0]);//DEBUG
        var range = sheetA.getRange(i + 2, 9);
        //Logger.log("DEBUG: value = "+value);//DEBUG
        //Logger.log("DEBUG: range = "+range.getA1Notation());//DEBUG
        range.setValue(dataB_Status[result][0]);
      }
    } else {
      // it's not there
      // Logger.log("DEBUG: i: "+i+", ID: "+A_ID+", it's not there");//DEBUG
    }
  }
}

// Credit: Flatten array: https://stackoverflow.com/a/49354635/1330560
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...