Отсутствует столбец журнала в электронной таблице назначения

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

код:

function updateShadowSKU() {
  var source = SpreadsheetApp.getActive().getSheetByName('Sheet1');
  var dest = SpreadsheetApp.openById('179PCrIWe1mvbbzOi9ySEHxzBlFaXpCB2i0wHlYVE2vg').getSheetByName('Sheet1');
  var destRange = dest.getDataRange();
  var destValues = destRange.getValues();
  var destHeaders = destValues[0];
  var destIds = destValues.map(e => e[0]);
  var values = source.getDataRange().getValues().map(e => e.filter((f, i) => !i || i > 10));
  var colMap = values[0].map(e => destHeaders.indexOf(e));
  Logger.log(colMap);
  values = values.map((e, i, arr) => e.map((f, j) => [e[0], colMap[j], f, values[0][j], i, j])).flat().filter(e => e[0] && e[1] && e[2] && e[3] && e[4] && e[5]);
  Logger.log(values);

  // Initialize an array to store log entries
  var logEntries = [];

  // Check for missing SKUs
  values.forEach(function(e) {
    if (!destIds.includes(e[0])) {
      logEntries.push(["Missing SKU", e[0], e[3]]);
    }
  });

  // Check for missing column headers
colMap.forEach(function(e, i) {
  if (e == -1) {
    var index = destHeaders.indexOf(values[0][i]);
    colMap[i] = index;
    if (index == -1) {
      logEntries.push(["Missing column header", values[0][e], ""]);
    }
  }
});

  if (!values.length) {
    logEntries.push(["No changes to make", "", ""]);
  } else {
    values = values.map(e => [destIds.indexOf(e[0]), e[1], e[2]]);
    Logger.log(values.length + ' changes to make');
    Logger.log(values);
    values.forEach(function(e) {
      try {
        destValues[e[0]][e[1]] = e[2];
      } catch (err) {}
    });
    destRange.setValues(destValues);
  }

  // Write log entries to the 'Shadow Log' sheet in the destination spreadsheet
  if (logEntries.length > 0) {
    var logSheet = SpreadsheetApp.openById('179PCrIWe1mvbbzOi9ySEHxzBlFaXpCB2i0wHlYVE2vg').getSheetByName("Shadow Log");
    if (logSheet == null) {
      logSheet = SpreadsheetApp.openById('179PCrIWe1mvbbzOi9ySEHxzBlFaXpCB2i0wHlYVE2vg').insertSheet("Shadow Log");
    }
    logSheet.clear();
    logSheet.getRange(1, 1, logEntries.length, 3).setValues(logEntries);
  }
}

блок кода для получения отсутствующих данных в электронной таблице назначения столбца A работает нормально, но мне трудно получить имя столбца. Блок кода ниже показывает только индекс столбца вместо заголовка/заголовка столбца:

// Check for missing column headers
colMap.forEach(function(e, i) {
  if (e == -1) {
    var index = destHeaders.indexOf(values[0][i]);
    colMap[i] = index;
    if (index == -1) {
      logEntries.push(["Missing column header", values[0][e], ""]);
    }
  }
});

образцы листов: источник: https://docs.google.com/spreadsheets/d/1zGqiYocUmSBRDPKRqI3iI3nIf7w3b9C7ykT-QffBROA/edit#gid=0

пункт назначения: https://docs.google.com/spreadsheets/d/1PjOvhscblzPxaBnJi1Q5oB6iCAt9_emljUR6vlAfIA0/edit#gid=0

пример:

источник данных:

|   SKU      |   walmart1   |   amazon 2   |   ebay1   |
|============|==============|==============|===========|
| SKUitem1   |    SKUwm1    |              |  SKUebay1 |
| SKUitem2   |              |              | SKUitem5  |
| SKUitem3   |   SKUwmi1    |              |           |

место назначения:

|   items    | **walmart2** | **amazon 1** |   ebay1   |
|============|==============|==============|===========|
| SKUitem1   |    SKUwm1    |              |  SKUebay1 |
|**SKUitem5**|              |              |           |
| SKUitem3   |              |              |           |

желаемый результат:

в этом случае лист «Shadow Log» должен привести к

|   Missing SKU    |   SKUitem2    |
|  Missing Column  |   walmart1    |

отсутствует SKU - потому что было обновление из источника, но не удалось найти его в месте назначения

отсутствует столбец - потому что в этом столбце было обновление, но не удалось найти этот столбец

вы также увидите, что есть столбец несоответствия amazon 2 -> amazon 1, но вы ничего не увидите в желаемых результатах, потому что нет новых данных для обновления.

Я надеюсь, что это прояснит ситуацию, пожалуйста, не стесняйтесь спрашивать меня.

Могу ли я подтвердить, что то, что вы хотите получить в качестве вывода, является ошибкой, а затем заголовком столбца? Например, Missing Column Header - walmart shadow 2?

PatrickdC 10.01.2023 00:38

Еще лучше, не могли бы вы отредактировать свои электронные таблицы, чтобы показать записи, которые должны появиться в «Журнале теней» каждой электронной таблицы.

Tedinoz 10.01.2023 06:14

извините, я обновил пост, чтобы показать желаемый результат

yae 10.01.2023 07:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проверьте и исправьте индекс при доступе к нужным данным

Я заметил, что когда вы пытались получить доступ к данным из values, вы использовали [e] в качестве индекса, который приведет к значению undefined, поскольку [e] всегда будет -1 в вашем случае, а в массивах нет индекса -1.

Кроме того, при использовании метода forEach первая переменная (e в вашем случае) будет значением для обработки, а вторая переменная будет значением индекса (i в вашем случае). Следовательно, вы должны использовать [i] при доступе к данным с помощью циклов.

При этом я добавил переменную sourceCol для хранения всех нужных заголовков столбцов из источника.

Вы можете изменить диапазон, если вам нужно добавить больше столбцов. Я изменил values[0][e] на sourceCol[0][i], чтобы получить доступ к заголовку нужного столбца.

Новый код должен выглядеть так: (я добавил комментарии для дальнейшего руководства)

function updateShadowSKU() {
  var source = SpreadsheetApp.getActive().getSheetByName('Sheet1');
  var dest = SpreadsheetApp.openById('Destination Sheet ID').getSheetByName('Sheet1');
  var destRange = dest.getDataRange();
  var destValues = destRange.getValues();
  var destHeaders = destValues[0];
  var destIds = destValues.map(e => e[0]);
  var values = source.getDataRange().getValues().map(e => e.filter((f, i) => !i || i > 10));

  //-----------------------------------------------------------------------------------------------
  //added sourceCol variable to specifically get the array of all Column Headers from the Source
  var sourceCol = source.getDataRange().getValues().map(e => e.filter((f, i) => i >= 3 && i <= 17));
  var colMap = sourceCol[0].map(e => destHeaders.indexOf(e));
  //-----------------------------------------------------------------------------------------------

  values = values.map((e, i, arr) => e.map((f, j) => [e[0], colMap[j], f, values[0][j], i, j])).flat().filter(e => e[0] && e[1] && e[2] && e[3] && e[4] && e[5]);


  // Initialize an array to store log entries
  var logEntries = [];

  // Check for missing SKUs
  values.forEach(function (e) {
    if (!destIds.includes(e[0])) {
      logEntries.push(["Missing SKU", e[0], e[3]]);
    }
  });

  // Check for missing column headers
  colMap.forEach(function (e, i) {
    if (e == -1) {
      //--------------------------------------------------------------
      //change values[0][e] to sourceCol[0][i]
      logEntries.push(["Missing column header", sourceCol[0][i], ""]);
      //--------------------------------------------------------------
    }
  });

  if (!values.length) {
    logEntries.push(["No changes to make", "", ""]);
  } else {
    values = values.map(e => [destIds.indexOf(e[0]), e[1], e[2]]);
    Logger.log(values.length + ' changes to make');
    Logger.log(values);
    values.forEach(function (e) {
      try {
        destValues[e[0]][e[1]] = e[2];
      } catch (err) { }
    });
    destRange.setValues(destValues);
  }
    // Write log entries to the 'Shadow Log' sheet in the destination spreadsheet
    // Added an else statement to clear the 'Shadow Log` when the log is empty.
  var logSheet = SpreadsheetApp.openById('Destination Sheet ID').getSheetByName("Shadow Log");
  if (logEntries.length > 0) {
    if (logSheet == null) {
      logSheet = SpreadsheetApp.openById('Destination Sheet ID').insertSheet("Shadow Log");
    }
    logSheet.clear();
    logSheet.getRange(1, 1, logEntries.length, 3).setValues(logEntries);
  }
  else {
    logSheet.clear();
  }
    }

Выход

При тестировании кода я удалил 5 заголовков столбцов (как показано ниже):

Когда я запустил код с модификацией, я получил следующий вывод:

Рекомендации

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

PatrickdC 10.01.2023 06:37

Здравствуйте, @PatrickdC, да, именно такого результата я и хочу добиться, но при проверке результат в «Shadow Log» отличается, например, когда я удалил «ebay shadow 3» в месте назначения, это привело к 'группон тень 2'. Я отредактировал пост, и надеюсь, что все прояснится, я также добавил образцы листов

yae 10.01.2023 07:42

Я обновил ответ и добавил некоторые коррективы в код. Я добавил новую переменную, чтобы она не мешала переменной values.

PatrickdC 10.01.2023 10:11

Другие вопросы по теме

Как отложить запуск времени в листах Google с помощью скрипта Google Apps?
Добавить дату и текст в последнюю строку после копирования и вставки
Исключение: доступ запрещен: DriveApp при запуске скрипта из отдельной учетной записи Google
Как автоматически заполнить список задач листа Google в динамический календарь листа Google
Отфильтровать/извлечь текст из листа Excel, имеющего аналогичные значения
Как найти строку по значению и обновить ее содержимое из API Google Таблиц в javascript nodejs
Добавьте несколько фреймов данных и комментариев над фреймом данных в один рабочий лист, используя Gspread и python
В раскрывающемся списке применяется больше, чем отредактированная строка в appscript
Регулярное выражение в таблицах Google, соответствует предыдущему периоду или точке с запятой
Поиск по всему листу Google, возврат значения из соответствующей ячейки относительно положения соответствующей ячейки – Follow U