# Node 与 Python 处理 Excel 能力对照 针对当前项目(财报 Excel 解析、按配置重组、转亿、多 Sheet 输出),逐项对照:**你要实现的功能 Node 是否都支持**。 --- ## 一、当前 Python 用到的能力 | 能力 | 当前实现(Python) | Node 是否支持 | 说明 | |------|--------------------|---------------|------| | 读 .xlsx | pandas + openpyxl | ✅ 支持 | exceljs / xlsx 都支持 | | 读 .xls | pandas | ⚠️ 部分 | 见下文「.xls」 | | 读 .csv (UTF-8) | pandas read_csv | ✅ 支持 | fs + 按行解析,或 csv-parse / xlsx 读 csv | | 按行、按列访问 | df.iloc[i], df.iloc[:, 0] | ✅ 支持 | 工作表 = 二维数组或按行遍历 | | 按第一列匹配行 | first_col == item_name / str.strip() | ✅ 支持 | 数组 find/filter,字符串 trim | | 数字解析 | 去 `=`、逗号、空格,科学计数法 | ✅ 支持 | JS 的 Number/parseFloat 完全够用 | | 转「亿」、保留 2 位小数 | / 1e8, round(_, 2) | ✅ 支持 | 普通算术 + toFixed/round | | 多 Sheet 写入 | pd.ExcelWriter, sheet_name= | ✅ 支持 | exceljs 多 worksheet,xlsx 多 sheet | | 无表头写入 | header=False | ✅ 支持 | 按行写入,不写 header 即可 | | 按配置过滤行/列 | rows_to_delete, columns_to_keep | ✅ 支持 | 数组 filter / 列索引过滤 | 结论:**除「.xls 老格式」需单独处理外,你要实现的功能 Node 都支持。** --- ## 二、推荐库与用法摘要 ### 1. Excel 读写:exceljs(推荐) - **读**:`workbook.xlsx.readFile(path)` → `workbook.getWorksheet(1)` 或按名称 → `worksheet.eachRow` / `row.getCell(j).value` - **写**:`workbook.addWorksheet('资产负债表')` → `worksheet.addRow([...])`,可多次 addRow 实现「无表头」、多 Sheet - **格式**:主要支持 .xlsx;公式会得到计算后的值(与你当前用 pandas 读到的行为一致) - **中文/UTF-8**:无问题 ```bash npm i exceljs ``` ### 2. 备选:xlsx(SheetJS) - **读**:`XLSX.readFile(path)` → `workbook.Sheets[sheetName]` → `XLSX.utils.sheet_to_json(sheet, { header: 1 })` 得到「二维数组」,和你现在按 iloc 按行按列访问等价 - **写**:`XLSX.utils.aoa_to_sheet(rows)`,再 `XLSX.utils.book_append_sheet(workbook, sheet, '资产负债表')`,最后 `XLSX.writeFile(workbook, path)` - 社区版对 .xls 有一定支持(视构建而定);若主要用 .xlsx,exceljs 更易做「按行按格」的细粒度控制 ### 3. CSV - 用 `fs.readFileSync(path, 'utf-8')` + 按行 split + 按逗号/分隔符解析即可 - 或 `csv-parse`、或直接用 xlsx 读 csv 得到二维数组 ### 4. 数据处理(替代 pandas) - 不需要 DataFrame:当前脚本本质是「按第一列找行、按列做汇总、按配置过滤、组装新行」 - 用普通数组即可:`rows.find(r => String(r[0]).trim() === itemName)`、`rows.filter(...)`、`colValues.reduce((a, b) => a + safeFloat(b), 0)`、`resultRows.push([...])` - 不需要额外「数据分析」库 --- ## 三、你关心的几个点 ### 1. 「按第一列找行」在 Node 里怎么写? 和 Python 逻辑一致:把当前 Sheet 读成「行的数组」,每行是「单元格值数组」,用第一列匹配。 ```js // 读成二维数组后 function findRowByItemName(rows, itemName) { const t = itemName.trim(); return rows.find(r => String(r[0] || '').trim() === t); } ``` ### 2. 数字格式:等号、逗号、科学计数法 你现在的 `safe_float_convert` / `convert_to_yi` 在 Node 里用一段小函数即可等价实现: ```js function safeFloat(value) { if (value == null || value === '') return 0; let s = String(value).trim(); if (s.startsWith('=')) s = s.slice(1); s = s.replace(/,|,|\s/g, ''); if (!s || s.toLowerCase() === 'nan') return 0; const n = parseFloat(s); return Number.isFinite(n) ? n : 0; } ``` 科学计数法(如 `2.07327E+12`)`parseFloat` 直接支持。 ### 3. 多 Sheet 合并输出(main.py 的 merge_to_excel) exceljs 示例: ```js const ExcelJS = require('exceljs'); const wb = new ExcelJS.Workbook(); const ws1 = wb.addWorksheet('资产负债表'); const ws2 = wb.addWorksheet('利润表'); balanceSheetRows.forEach(row => ws1.addRow(row)); // 无表头就连续 addRow incomeStatementRows.forEach(row => ws2.addRow(row)); await wb.xlsx.writeFile(outputPath); ``` ### 4. .xls(老格式) - **exceljs**:只支持 .xlsx,不直接支持 .xls。 - **xlsx (SheetJS)**:部分版本/配置可读 .xls,但不如 .xlsx 稳定。 - 建议:若数据源仍会提供 .xls,要么在 Node 里用专门库(如 `xls` 等)只做「读成二维数组」再交给现有逻辑,要么在上传前用 Excel/脚本统一转成 .xlsx 再处理。对你当前「下载后上传到 Web」的流程,要求用户上传 .xlsx 或在后端用工具转一次,通常可接受。 --- ## 四、小结 | 问题 | 结论 | |------|------| | Node 能否完成你现在的 Excel 处理? | **能**。读 xlsx/csv、按行按列查找、数字清洗、转亿、多 Sheet 写出,都有对应库和写法。 | | 是否不如 Python 稳? | 对**这类**场景(报表级数据、几千行以内):Node + exceljs 足够稳;Python 优势在「超大数据、复杂统计、科学计算」,你当前用到的只是基础读写与简单运算。 | | 推荐方案 | **exceljs** 做主读写;数据处理用普通 JS 数组;CSV 用 fs + 解析或 csv-parse;.xls 单独处理或要求 .xlsx。 | 你更熟 Node 的话,用 Node 实现当前功能没有问题;若后面遇到具体文件解析异常(例如某个下载站的 xlsx 格式略怪),再针对该格式微调即可。