Files
organize_excel_data/docs/Node与Python处理Excel能力对照.md

121 lines
5.7 KiB
Markdown
Raw Permalink 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.

# 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 多 worksheetxlsx 多 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. 备选xlsxSheetJS
- **读**`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 有一定支持(视构建而定);若主要用 .xlsxexceljs 更易做「按行按格」的细粒度控制
### 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 格式略怪),再针对该格式微调即可。