ty-mozhesh-sravnit-2-excel-f/compare.js

198 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const XLSX = require("xlsx");
const fs = require("fs");
// Чтение файлов
const wb1 = XLSX.readFile("БП_2026_НСВМ.xlsx");
const wb2 = XLSX.readFile("Шаблон БП_ БКВ 2027 с займами.xlsx");
// Получение списка всех листов
const sheets1 = wb1.SheetNames;
const sheets2 = wb2.SheetNames;
console.log("Файл 1 листы:", sheets1);
console.log("Файл 2 листы:", sheets2);
// Сравнительные данные
const comparisonResults = [];
// Сравниваем листы
const allSheets = [...new Set([...sheets1, ...sheets2])];
allSheets.forEach(sheetName => {
const sheet1Exists = sheets1.includes(sheetName);
const sheet2Exists = sheets2.includes(sheetName);
if (!sheet1Exists) {
comparisonResults.push({
"Лист": sheetName,
"Статус": "Отсутствует в файле 1 (БП_2026_НСВМ)",
"Различия": "Лист есть только во втором файле"
});
return;
}
if (!sheet2Exists) {
comparisonResults.push({
"Лист": sheetName,
"Статус": "Отсутствует в файле 2 (Шаблон БП_ БКВ 2027 с займами)",
"Различия": "Лист есть только в первом файле"
});
return;
}
// Получаем данные листов
const data1 = XLSX.utils.sheet_to_json(wb1.Sheets[sheetName], { header: 1 });
const data2 = XLSX.utils.sheet_to_json(wb2.Sheets[sheetName], { header: 1 });
// Сравниваем размеры
const rows1 = data1.length;
const rows2 = data2.length;
const cols1 = data1.length > 0 ? Math.max(...data1.map(r => r.length)) : 0;
const cols2 = data2.length > 0 ? Math.max(...data2.map(r => r.length)) : 0;
if (rows1 !== rows2 || cols1 !== cols2) {
comparisonResults.push({
"Лист": sheetName,
"Статус": "Разные размеры",
"Различия": `Файл 1: ${rows1} строк x ${cols1} колонок | Файл 2: ${rows2} строк x ${cols2} колонок`
});
}
// Построчное сравнение (первые 100 строк для производительности)
const maxRows = Math.min(Math.max(rows1, rows2), 100);
let diffCount = 0;
const diffDetails = [];
for (let i = 0; i < maxRows; i++) {
const row1 = data1[i] || [];
const row2 = data2[i] || [];
const maxCols = Math.max(row1.length, row2.length);
for (let j = 0; j < maxCols; j++) {
const val1 = row1[j] !== undefined ? row1[j] : null;
const val2 = row2[j] !== undefined ? row2[j] : null;
if (val1 !== val2 && val1 !== null && val2 !== null) {
diffCount++;
if (diffDetails.length < 20) { // Сохраняем первые 20 различий
const colLabel = String.fromCharCode(65 + j); // A, B, C...
const rowNum = i + 1;
diffDetails.push(`Ячейка ${colLabel}${rowNum}: "${val1}" ≠ "${val2}"`);
}
}
}
}
if (diffCount > 0) {
comparisonResults.push({
"Лист": sheetName,
"Статус": "Есть различия",
"Различия": `Найдено различий: ${diffCount}. Примеры: ${diffDetails.slice(0, 5).join("; ")}`
});
} else {
comparisonResults.push({
"Лист": sheetName,
"Статус": "Идентичен",
"Различия": "Нет"
});
}
});
// Создаём итоговый файл с результатами сравнения
const resultWorkbook = XLSX.utils.book_new();
// Лист 1: Сводная таблица сравнения
const summaryData = [
["СРАВНЕНИЕ ФАЙЛОВ"],
["Файл 1:", "БП_2026_НСВМ.xlsx"],
["Файл 2:", "Шаблон БП_ БКВ 2027 с займами.xlsx"],
["Дата сравнения:", new Date().toLocaleString("ru-RU")],
[],
["СВОДНАЯ ТАБЛИЦА РАЗЛИЧИЙ"],
["Лист", "Статус", "Различия"]
];
comparisonResults.forEach(r => {
summaryData.push([r["Лист"], r["Статус"], r["Различия"]]);
});
const summarySheet = XLSX.utils.json_to_sheet(summaryData.slice(7), { skipHeader: false });
XLSX.utils.sheet_add_aoa(summarySheet, summaryData.slice(0, 7), { origin: "A1" });
XLSX.utils.book_append_sheet(resultWorkbook, summarySheet, "Сводка");
// Лист 2: Детальное сравнение по ячейкам
const detailData = [["Лист", "Ячейка", "Значение в файле 1", "Значение в файле 2", "Тип различия"]];
sheets1.forEach(sheetName => {
if (!sheets2.includes(sheetName)) return;
const data1 = XLSX.utils.sheet_to_json(wb1.Sheets[sheetName], { header: 1 });
const data2 = XLSX.utils.sheet_to_json(wb2.Sheets[sheetName], { header: 1 });
const maxRows = Math.min(Math.max(data1.length, data2.length), 200);
for (let i = 0; i < maxRows; i++) {
const row1 = data1[i] || [];
const row2 = data2[i] || [];
const maxCols = Math.max(row1.length, row2.length);
for (let j = 0; j < maxCols; j++) {
const val1 = row1[j] !== undefined ? row1[j] : null;
const val2 = row2[j] !== undefined ? row2[j] : null;
if (val1 !== val2 && val1 !== null && val2 !== null) {
const colLabel = String.fromCharCode(65 + j);
const rowNum = i + 1;
detailData.push([
sheetName,
`${colLabel}${rowNum}`,
String(val1),
String(val2),
typeof val1 !== typeof val2 ? "Разный тип данных" : "Разное значение"
]);
}
}
}
});
const detailSheet = XLSX.utils.json_to_sheet(detailData.slice(1), { skipHeader: false });
XLSX.utils.sheet_add_aoa(detailSheet, [detailData[0]], { origin: "A1" });
XLSX.utils.book_append_sheet(resultWorkbook, detailSheet, "Детали различий");
// Лист 3: Структура файлов
const structureData = [
["СТРУКТУРА ФАЙЛОВ"],
[],
["Файл 1: БП_2026_НСВМ.xlsx"],
["№", "Название листа", "Строк", "Колонок"]
];
sheets1.forEach((name, idx) => {
const sheet = XLSX.utils.sheet_to_json(wb1.Sheets[name], { header: 1 });
const rows = sheet.length;
const cols = rows > 0 ? Math.max(...sheet.map(r => r.length)) : 0;
structureData.push([idx + 1, name, rows, cols]);
});
structureData.push([], [], ["Файл 2: Шаблон БП_ БКВ 2027 с займами.xlsx"], ["№", "Название листа", "Строк", "Колонок"]);
sheets2.forEach((name, idx) => {
const sheet = XLSX.utils.sheet_to_json(wb2.Sheets[name], { header: 1 });
const rows = sheet.length;
const cols = rows > 0 ? Math.max(...sheet.map(r => r.length)) : 0;
structureData.push([idx + 1, name, rows, cols]);
});
const structureSheet = XLSX.utils.json_to_sheet(structureData.slice(4), { skipHeader: false });
XLSX.utils.sheet_add_aoa(structureSheet, structureData.slice(0, 4), { origin: "A1" });
XLSX.utils.book_append_sheet(resultWorkbook, structureSheet, "Структура файлов");
// Сохраняем результат
const outputFile = "Сравнение_БП_2026_НСВМ_и_Шаблон_БП_БКВ_2027.xlsx";
XLSX.writeFile(resultWorkbook, outputFile);
console.log(`\n✅ Сравнение завершено!`);
console.log(`📊 Файл с результатами: ${outputFile}`);
console.log(`📈 Всего листов сравнено: ${allSheets.length}`);
console.log(`⚠️ Листов с различиями: ${comparisonResults.filter(r => r["Статус"] === "Есть различия").length}`);
console.log(`📋 Листов без различий: ${comparisonResults.filter(r => r["Статус"] === "Идентичен").length}`);