У меня есть приведенный ниже код, который позволяет мне обновить существующую электронную таблицу (очень похоже на матричный поиск). И что я делаю прямо сейчас, так это включаю журнал ошибок, который будет обновляться на другом листе, включая отсутствующие данные в столбце 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, но вы ничего не увидите в желаемых результатах, потому что нет новых данных для обновления.
Я надеюсь, что это прояснит ситуацию, пожалуйста, не стесняйтесь спрашивать меня.
Еще лучше, не могли бы вы отредактировать свои электронные таблицы, чтобы показать записи, которые должны появиться в «Журнале теней» каждой электронной таблицы.
извините, я обновил пост, чтобы показать желаемый результат
Я заметил, что когда вы пытались получить доступ к данным из 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, да, именно такого результата я и хочу добиться, но при проверке результат в «Shadow Log» отличается, например, когда я удалил «ebay shadow 3» в месте назначения, это привело к 'группон тень 2'. Я отредактировал пост, и надеюсь, что все прояснится, я также добавил образцы листов
Я обновил ответ и добавил некоторые коррективы в код. Я добавил новую переменную, чтобы она не мешала переменной values
.
Могу ли я подтвердить, что то, что вы хотите получить в качестве вывода, является ошибкой, а затем заголовком столбца? Например,
Missing Column Header - walmart shadow 2
?