update generateXlsx
This commit is contained in:
parent
97dfbf1e35
commit
2b5a602b49
@ -1,43 +1,162 @@
|
||||
import ExcelJS from 'exceljs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Generates an XLSX file from the given data.
|
||||
* @param {Array<Object>} data - The data to convert to XLSX.
|
||||
* @param {string} filePath - The path to save the XLSX file.
|
||||
* Flattens the nested JSON data into separate arrays for projects, licenses, and buildings.
|
||||
* @param {Array<Object>} data - The nested data from merged_data.json.
|
||||
* @returns {{projects: Array<Object>, licenses: Array<Object>, buildings: Array<Object>}}
|
||||
*/
|
||||
function flattenData(data) {
|
||||
const projects = [];
|
||||
const licenses = [];
|
||||
const buildings = [];
|
||||
|
||||
async function generateXlsx(data, filePath) {
|
||||
data.forEach(project => {
|
||||
// Create a shallow copy to avoid modifying the original object in memory
|
||||
const projectCopy = { ...project };
|
||||
const licensesData = projectCopy['预售许可证'];
|
||||
// The nested array will not be included in the flattened project data
|
||||
delete projectCopy['预售许可证'];
|
||||
projects.push(projectCopy);
|
||||
|
||||
if (licensesData && Array.isArray(licensesData)) {
|
||||
licensesData.forEach(license => {
|
||||
const licenseCopy = { ...license };
|
||||
const buildingsData = licenseCopy['楼幢'];
|
||||
// The nested array will not be included in the flattened license data
|
||||
delete licenseCopy['楼幢'];
|
||||
|
||||
// Add a key to link back to the parent project
|
||||
licenseCopy['项目名称_key'] = project['项目名称'];
|
||||
licenses.push(licenseCopy);
|
||||
|
||||
if (buildingsData && Array.isArray(buildingsData)) {
|
||||
buildingsData.forEach(building => {
|
||||
// Add keys to link back to the parent license and project
|
||||
const buildingCopy = {
|
||||
...building,
|
||||
'许可证号_key': license['许可证号'],
|
||||
'项目名称_key': project['项目名称'],
|
||||
};
|
||||
buildings.push(buildingCopy);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return { projects, licenses, buildings };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a worksheet to the workbook with the given data, headers, and styling.
|
||||
* @param {ExcelJS.Workbook} workbook - The workbook instance.
|
||||
* @param {string} sheetName - The name for the new worksheet.
|
||||
* @param {Array<Object>} data - The array of data for the sheet.
|
||||
*/
|
||||
function addSheet(workbook, sheetName, data) {
|
||||
if (data.length === 0) {
|
||||
console.log(`没有数据可生成 XLSX 文件 (${filePath})。`);
|
||||
console.log(`- 注意: 没有数据可用于工作表 '${sheetName}'`);
|
||||
return;
|
||||
}
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const worksheet = workbook.addWorksheet('Data');
|
||||
const worksheet = workbook.addWorksheet(sheetName);
|
||||
// Get all unique keys from all objects to form a complete header
|
||||
const allKeys = data.reduce((keys, item) => {
|
||||
if (item) {
|
||||
Object.keys(item).forEach(key => {
|
||||
if (!keys.includes(key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
return keys;
|
||||
}, []);
|
||||
|
||||
const headers = Object.keys(data[0]);
|
||||
worksheet.columns = headers.map(key => ({
|
||||
worksheet.columns = allKeys.map(key => ({
|
||||
header: key,
|
||||
key: key,
|
||||
width: key.includes('地址') || key.includes('链接') ? 40 : 20
|
||||
width: key.includes('地址') || key.includes('链接') || key.includes('简介') ? 50 : 25
|
||||
}));
|
||||
|
||||
worksheet.addRows(data);
|
||||
|
||||
// Style header row
|
||||
worksheet.getRow(1).eachCell(cell => {
|
||||
cell.font = { bold: true };
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFDDDDDD' }
|
||||
fgColor: { argb: 'FFD3D3D3' }
|
||||
};
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' };
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };
|
||||
});
|
||||
|
||||
// Add autofilter to the header row
|
||||
worksheet.autoFilter = {
|
||||
from: 'A1',
|
||||
to: {
|
||||
row: 1,
|
||||
column: headers.length
|
||||
column: allKeys.length
|
||||
}
|
||||
};
|
||||
await workbook.xlsx.writeFile(filePath);
|
||||
console.log(`已生成 ${filePath} 文件。`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a multi-sheet XLSX file from the nested real estate data.
|
||||
* @param {Array<Object>} data - The nested data from merged_data.json.
|
||||
* @param {string} filePath - The path to save the XLSX file.
|
||||
*/
|
||||
async function generateXlsx(data, filePath) {
|
||||
if (!data || data.length === 0) {
|
||||
console.log(`没有数据可生成 XLSX 文件 (${filePath})。`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('正在将数据处理成多个工作表...');
|
||||
const { projects, licenses, buildings } = flattenData(data);
|
||||
console.log(`- 项目: ${projects.length} 条`);
|
||||
console.log(`- 许可证: ${licenses.length} 条`);
|
||||
console.log(`- 楼幢: ${buildings.length} 条`);
|
||||
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
workbook.creator = 'Gemini Assistant';
|
||||
workbook.created = new Date();
|
||||
workbook.modified = new Date();
|
||||
|
||||
console.log('正在创建 Excel 工作表...');
|
||||
addSheet(workbook, '项目', projects);
|
||||
addSheet(workbook, '预售许可证', licenses);
|
||||
addSheet(workbook, '楼幢', buildings);
|
||||
|
||||
await workbook.xlsx.writeFile(filePath);
|
||||
console.log(`✅ 成功生成多工作表 Excel 文件: ${filePath}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function to read data and trigger XLSX generation.
|
||||
*/
|
||||
async function run() {
|
||||
console.log('🚀 开始生成 Excel 分析文件...');
|
||||
const dataPath = path.join(process.cwd(), 'data', 'merged_data.json');
|
||||
const outputPath = path.join(process.cwd(), '普宁房产数据分析.xlsx');
|
||||
|
||||
try {
|
||||
await fs.access(dataPath);
|
||||
console.log(`读取数据源: ${dataPath}`);
|
||||
const jsonData = JSON.parse(await fs.readFile(dataPath, 'utf-8'));
|
||||
await generateXlsx(jsonData, outputPath);
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
console.error(`❌ 错误: 未找到数据文件 '${path.basename(dataPath)}'。`);
|
||||
console.error('请先运行 `npm start` 来生成完整的数据文件。');
|
||||
} else {
|
||||
console.error('❌ 生成 XLSX 文件时发生错误:', error);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user