Надо перенести данные из одного столбца в другой, но логика алгоритма не работает
Не могу найти ошибку, тк в Apps Script журнал выполнения(логи) у меня не подгружается. Я пишу алгоритм для склада. Мне нужно, чтобы при добавлении данных в столбик D в соседней ячейке(столбце E) появлялась дата создания этой информации. Я смог реализовать алгоритм вот так
function onEdit(e) {
if (!e || !e.range || !e.source || e.range.getSheet().getName() !== "все приходы") return;
var range = e.range;
var ss = e.source;
var sheet = range.getSheet();
var row = range.getRow();
var col = range.getColumn();
if (col === 4 && sheet.getRange(row, 5).isBlank()) {
sheet.getRange(row, 5).setValue(new Date());
}
}
Однако, мне также потребовалось добавить новую функцию. В столбце N хранится информация, которая через 20 дней устаревает и ее нужно записать в столбец M, дабы не возникало проблем на других листах где ведется учёт, на который влияет столбец N. Следовательно алгоритм должен быть таким: Сверяем сегодняшнюю дату и дату создания записанную в столбце E у последних 40 строк(чтобы не проверять каждый раз всю страницу); если старше 20 дней => копируем данные N вставляем в M и удаляем из N. Вот реализация с комментариями, постарался максимально подробно всё описать(алерты использую тк логи не работают, однако они не выводятся).
function onEdit(e) {
if (!e || !e.range || !e.source) return;
const sheet = e.range.getSheet();
const ui = SpreadsheetApp.getUi();
// Проверяем нужный лист
if (sheet.getName() !== "все приходы") return;
const range = e.range;
const row = range.getRow();
const col = range.getColumn();
const lastRow = sheet.getLastRow();
const startRow = Math.max(lastRow - 39, 1);
// Флаг для отслеживания добавления новой даты
let dateWasAdded = false;
// 1. Вставка даты в столбец E при изменении D (только если E пусто)
if (col === 4 && sheet.getRange(row, 5).isBlank()) {
try {
sheet.getRange(row, 5).setValue(new Date());
ui.alert("Дата добавлена", `В строке ${row} добавлена текущая дата`, ui.ButtonSet.OK);
dateWasAdded = true;
} catch (error) {
ui.alert("Ошибка", `Не удалось добавить дату в строке ${row}:\n${error.message}`, ui.ButtonSet.OK);
return;
}
}
// 2. Проверка даты и перемещение данных (для последних 40 строк)
if (col === 4 && row >= startRow) {
try {
const dateCell = range.offset(0, 1);
const dateValue = dateCell.getValue();
// Проверка что значение является датой
if (!dateValue) {
ui.alert("Ошибка", `Ячейка E${row} пустая!`, ui.ButtonSet.OK);
return;
}
let jsDate;
// Если мы только что добавили дату - используем её как объект Date
if (dateWasAdded) {
jsDate = new Date(dateValue);
}
// Если дата уже была - конвертируем из Excel формата
else if (typeof dateValue === 'number') {
jsDate = new Date(Math.round((dateValue - 25569) * 86400 * 1000));
}
// Если это строка - пытаемся распарсить
else if (typeof dateValue === 'string') {
jsDate = new Date(dateValue);
if (isNaN(jsDate.getTime())) {
ui.alert("Ошибка", `Неверный формат даты в E${row}: "${dateValue}"`, ui.ButtonSet.OK);
return;
}
}
// Если это объект Date - используем как есть
else if (dateValue instanceof Date) {
jsDate = new Date(dateValue);
}
// Неизвестный формат
else {
ui.alert("Ошибка", `Неизвестный формат даты в E${row}: ${typeof dateValue}`, ui.ButtonSet.OK);
return;
}
// Корректировка времени для сравнения
jsDate.setHours(0, 0, 0, 0);
const today = new Date();
today.setHours(0, 0, 0, 0);
// Вычисление разницы в днях
const diffDays = Math.floor((today - jsDate) / (1000 * 60 * 60 * 24));
// Перемещение данных при разнице >=20 дней
if (diffDays >= 20) {
const sourceColN = range.offset(0, 10);
const targetColM = range.offset(0, 9);
const dataToMove = sourceColN.getValue();
if (!dataToMove) {
ui.alert("Внимание", `В столбце N${row} нет данных для перемещения`, ui.ButtonSet.OK);
return;
}
// Выполняем перемещение
targetColM.setValue(dataToMove);
sourceColN.clearContent();
// Показываем успешное сообщение
ui.alert(
"Данные перемещены",
`В строке ${row} данные перемещены из N в M\n` +
`Дата: ${jsDate.toLocaleDateString()}\n` +
`Разница: ${diffDays} дней`,
ui.ButtonSet.OK
);
}
} catch (error) {
ui.alert("Критическая ошибка", `Ошибка в строке ${row}:\n${error.message}`, ui.ButtonSet.OK);
}
}
}
Собственно вопрос - где закралась ошибка? Алгоритм реализует только часть с добавлением даты, но перемещение из M в N не происходит. Может логика Apps Script не позволяет onEdit использовать таким образом? или всё проще?
Ответы (1 шт):
Надеюсь триггер настроен правильно. Некоторые действия излишни, пробуй:
function onEdit(e) {
if (!e || !e.range || !e.source) return;
const sheet = e.range.getSheet();
const ui = SpreadsheetApp.getUi();
// Проверяем нужный лист
if (sheet.getName() !== "все приходы") return;
const range = e.range;
const row = range.getRow();
const col = range.getColumn();
const lastRow = sheet.getLastRow();
const startRow = Math.max(lastRow - 39, 1);
// Проверка, что изменён столбец D
if (col !== 4) return;
// Флаг для отслеживания добавления новой даты
let dateWasAdded = false;
// 1. Вставка даты в столбец E при изменении D (только если E пусто)
const dateCell = sheet.getRange(row, 5);
const dateValue = dateCell.getValue();
if (dateValue === null || dateValue === "") {
try {
dateCell.setValue(new Date());
dateWasAdded = true;
// ui.alert("Дата добавлена", `В строке ${row} добавлена текущая дата`, ui.ButtonSet.OK);
} catch (error) {
ui.alert("Ошибка", `Не удалось добавить дату в строке ${row}:\n${error.message}`, ui.ButtonSet.OK);
return;
}
}
// 2. Проверка даты и перемещение данных (для последних 40 строк)
if (row >= startRow) {
try {
let jsDate;
if (dateWasAdded) {
jsDate = new Date(dateCell.getValue());
} else if (typeof dateValue === 'number') {
jsDate = new Date((dateValue - 25569) * 86400 * 1000);
} else if (typeof dateValue === 'string') {
jsDate = new Date(dateValue);
if (isNaN(jsDate.getTime())) {
ui.alert("Ошибка", `Неверный формат даты в E${row}: "${dateValue}"`, ui.ButtonSet.OK);
return;
}
} else if (dateValue instanceof Date) {
jsDate = new Date(dateValue);
} else {
ui.alert("Ошибка", `Неизвестный формат даты в E${row}: ${typeof dateValue}`, ui.ButtonSet.OK);
return;
}
// Корректировка времени для сравнения
jsDate.setHours(0, 0, 0, 0);
const today = new Date();
today.setHours(0, 0, 0, 0);
// Вычисление разницы в днях
const diffDays = Math.floor((today - jsDate) / (1000 * 60 * 60 * 24));
// Перемещение данных при разнице >=20 дней
if (diffDays >= 20) {
const sourceColN = sheet.getRange(row, 14); // N
const targetColM = sheet.getRange(row, 13); // M
const dataToMove = sourceColN.getValue();
if (!dataToMove) {
ui.alert("Внимание", `В столбце N${row} нет данных для перемещения`, ui.ButtonSet.OK);
return;
}
// Выполняем перемещение
targetColM.setValue(dataToMove);
sourceColN.clearContent();
// Показываем успешное сообщение
ui.alert(
"Данные перемещены",
`В строке ${row} данные перемещены из N в M\n` +
`Дата: ${jsDate.toLocaleDateString()}\n` +
`Разница: ${diffDays} дней`,
ui.ButtonSet.OK
);
}
} catch (error) {
ui.alert("Критическая ошибка", `Ошибка в строке ${row}:\n${error.message}`, ui.ButtonSet.OK);
}
}
}