/** * Главная функция, вызывается при редактировании таблицы.
* Фиксирует историю изменений без дублей, определяя пользователя по его личной ячейке email.
*/
function onEditAllUsers(e) {
try {
if (!e) return;
// === Настройки ===
const sheet = e.range.getSheet();
const col = e.range.getColumn();
const row = e.range.getRow();
const headerRow = 1;
const trackedCols = [17, 23, 29, 35, 41, 47]; // Q, W, AC, AI, AO, AU
const logCol = 54; // BB
const tz = "Europe/Minsk";
// Только отслеживаемые колонки
if (trackedCols.indexOf(col) === -1 || row === headerRow) return;
// === Настраиваем пользователей и их email-ячейки ===
const userCells = {
"[URL=mailto:belrosbrest@gmail.com]belrosbrest@gmail.com[/URL]": "BB1",
"[URL=mailto:oleg.nesterovich74@gmail.com]oleg.nesterovich74@gmail.com[/URL]": "BB2",
"[URL=mailto:anna.example@gmail.com]anna.example@gmail.com[/URL]": "BB3",
};
// === Определяем текущего пользователя ===
const activeEmail = getActiveUserEmail_(userCells);
// === Антидубль по времени и контенту ===
const props = PropertiesService.getScriptProperties();
const key = sheet.getName() + "_" + row + "_" + col;
const newSig = [
e.range.getA1Notation(),
e.oldValue || "",
e.value || "",
activeEmail
].join("|");
const lastSig = props.getProperty("lastSig");
const lastTime = Number(props.getProperty("lastTime") || 0);
const now = Date.now();
if (newSig === lastSig && now - lastTime < 1500) return; // дубль → выходим
props.setProperty("lastSig", newSig);
props.setProperty("lastTime", now);
// === Формируем данные ===
const dateStr = Utilities.formatDate(new Date(), tz, "dd.MM.yyyy");
const timeStr = Utilities.formatDate(new Date(), tz, "HH:mm");
const region = String(sheet.getRange(headerRow, col).getDisplayValue() || ("Колонка " + col));
// === Запись в основную таблицу (BB) ===
const histCell = sheet.getRange(row, logCol);
const oldText = String(histCell.getValue() || "").trim();
const newText = oldText.startsWith(dateStr + ":")
? oldText + " | " + timeStr + " — " + region
: dateStr + ": " + timeStr + " — " + region;
histCell.setValue(newText);
// === Форматирование жирных регионов и даты ===
const builder = SpreadsheetApp.newRichTextValue().setText(newText);
const normal = SpreadsheetApp.newTextStyle().setBold(false).build();
const bold = SpreadsheetApp.newTextStyle().setBold(true).build();
builder.setTextStyle(0, newText.length, normal);
const dateMatch = newText.match(/^\d{2}\.\d{2}\.\d{4}/);
if (dateMatch) builder.setTextStyle(0, dateMatch[0].length, bold);
["Минск", "Брест", "Витебск", "Гродно", "Могилев", "Гомель"].forEach(regionName => {
let idx = -1;
while ((idx = newText.indexOf(regionName, idx + 1)) !== -1) {
builder.setTextStyle(idx, idx + regionName.length, bold);
}
});
histCell.setRichTextValue(builder.build());
// === Запись в лист "История" ===
const ss = SpreadsheetApp.getActiveSpreadsheet();
let historySheet = ss.getSheetByName("История");
if (!historySheet) {
historySheet = ss.insertSheet("История");
historySheet.appendRow(["Дата", "Время", "Регион", "Название строки", "Старое значение", "Новое значение", "Пользователь"]);
}
const oldVal = e.oldValue ? String(e.oldValue) : "";
const newVal = e.value ? String(e.value) : String(e.range.getDisplayValue());
const rowName = String(sheet.getRange(row, 1).getDisplayValue() || "");
historySheet.appendRow([dateStr, timeStr, region, rowName, oldVal, newVal, activeEmail || ""]);
clearOldHistory_(historySheet, tz);
} catch (err) {
Logger.log("Ошибка onEditAllUsers: " + err);
}
}
/**
* Определяет текущего пользователя по таблице и личным ячейкам email.
* Возвращает email, если он найден.
*/
function getActiveUserEmail_(userCells) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const mainSheet = ss.getSheets()[0];
for (let [email, cell] of Object.entries(userCells)) {
const storedEmail = String(mainSheet.getRange(cell).getValue() || "").trim().toLowerCase();
if (storedEmail === email.toLowerCase()) {
return email;
}
}
return "";
}
/**
* Удаляет старые записи истории (старше 30 дней).
*/
function clearOldHistory_(sheet, tz) {
try {
const today = new Date();
const cutoff = new Date(today.getTime() - 30 * 24 * 3600 * 1000);
const data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
for (let i = data.length - 1; i >= 0; i--) {
const dateStr = data[i][0];
if (!dateStr) continue;
const parts = dateStr.split(".");
if (parts.length === 3) {
const rowDate = new Date(parts[2], parts[1] - 1, parts[0]);
if (rowDate < cutoff) sheet.deleteRow(i + 2);
}
}
} catch (err) {
Logger.log("Ошибка очистки истории: " + err);
}
}
|