stream-sheet-export
v1.1.0
Published
Browser-side streaming Excel/CSV exporter. Supports remote CSV/Excel URLs (CORS transform or direct download), JSON rows, AsyncIterable, custom formats and cell styles.
Maintainers
Readme
stream-sheet-export
浏览器端 流式 Excel / CSV 导出工具库。
仓库:chenscDev/stream-sheet-export
- 支持 S3 / 预签名 CSV 或 Excel URL:解析转换(需 CORS)或直链下载
- 远程 Excel 可按表头字段匹配后自定义格式 / 单元格样式再导出
- 支持 JSON 行数据、AsyncIterable 分页边拉边导
- 支持列格式:
numFmt格式串 / 内置format枚举 /render自定义展示 - 支持单元格(行 / 列)自定义样式:背景色、字体色、加粗、对齐等
- 支持导出行数上限(默认 300 万)、单 Sheet 拆分(默认 100 万行)
- 提供 Vite 插件自动拷贝 CSV Service Worker;也可用 npm /
<script>CDN 引入
仅浏览器环境。不依赖 Vue / React。
安装
npm install stream-sheet-export
# 或
pnpm add stream-sheet-exportCDN(UMD):
<script src="https://unpkg.com/stream-sheet-export/dist/index.global.js"></script>
<script>
const { createExporter } = StreamSheetExport;
</script>快速开始
JSON → Excel
import { createExporter } from 'stream-sheet-export';
const exporter = createExporter({
fileName: '订单明细',
maxRows: 3_000_000,
rowsPerSheet: 1_000_000,
columns: [
{ key: 'id', title: '订单号', format: 'text', width: 18 },
{
key: 'amount',
title: '金额',
format: 'currency_cny',
style: { align: 'right' },
},
{
key: 'rate',
title: '转化率',
// 也可直接传 Excel 格式串
numFmt: '0.00%',
render: (v) => (typeof v === 'number' ? v : Number(v) || 0),
},
{
key: 'status',
title: '状态',
render: (v) => (v === 1 ? '成功' : '失败'),
},
],
headerStyle: { bold: true, fill: '#F2F3F5' },
stripeFill: '#FAFAFA',
cellStyleResolver: ({ column, displayValue }) => {
if (column.key === 'status' && displayValue === '失败') {
return { fontColor: '#F56C6C', bold: true };
}
return null;
},
onProgress: (p) => console.log(p.phase, p.rows),
});
await exporter.exportExcelFromRows([
{ id: 'A001', amount: 12.5, rate: 0.128, status: 1 },
{ id: 'A002', amount: 9, rate: 0.02, status: 0 },
]);远程 CSV / Excel URL → Excel(解析转换)
transform 模式(默认)会拉取并解析远程文件,再按 columns 做格式/样式后重新导出。
需要下载链接允许浏览器跨域读取(CORS),不限 CSV,Excel(.xlsx)同样支持。
// CSV 预签名链接
await exporter.exportExcelFromUrl(
'https://your-bucket.s3.amazonaws.com/result.csv?X-Amz-Signature=...',
{
fileName: '报表导出',
sourceType: 'auto', // auto | csv | xlsx
fieldMap: { f_1001: '日期', f_1002: 'GMV' },
formatMap: { f_1002: '"$"#,##0.00' },
}
);
// Excel 下载链接:按源表头匹配列,再自定义格式/样式
await exporter.exportExcelFromUrl(
'https://cdn.example.com/reports/orders.xlsx',
{
fileName: '订单导出',
sourceType: 'xlsx',
sheet: 0, // 或 sheet 名称
columns: [
{
key: 'orderId',
matchHeaders: ['订单号', 'Order ID'], // 匹配源表头
title: '订单编号',
format: 'text',
},
{
key: 'amount',
matchHeaders: ['金额', 'GMV'],
title: '成交金额',
format: 'currency_cny',
style: { align: 'right' },
},
{
key: 'status',
matchHeaders: ['状态'],
render: (v) => (String(v) === '1' ? '成功' : '失败'),
},
],
cellStyleResolver: ({ column, displayValue }) =>
column.key === 'status' && displayValue === '失败'
? { fontColor: '#F56C6C', bold: true }
: null,
}
);直链下载(不解析)
不改内容、不要求能解析表格;适合「只是把可下载链接存到本地」:
// 方式 1:专用 API
await exporter.downloadFromUrl(fileUrl, { fileName: '原始文件' });
// 方式 2:在 export*FromUrl 上指定 urlMode
await exporter.exportExcelFromUrl(fileUrl, { urlMode: 'direct', fileName: '原始文件' });
await exporter.exportCsvFromUrl(fileUrl, { urlMode: 'direct' });
transform需要 CORS;direct在 CORS 失败时会自动降级为<a download>直链。
AsyncIterable 分页边拉边导
async function* fetchPages() {
let page = 1;
while (true) {
const { list, hasMore } = await api.getPage(page);
for (const row of list) yield row;
if (!hasMore) break;
page += 1;
}
}
await exporter.exportExcelFromAsyncIterable(fetchPages(), {
fileName: '分页导出',
columns: [/* ... */],
});CSV 导出(URL 流式 / JSON)
// URL:仅替换表头,其余字节零拷贝 pipe 给 Service Worker,触发浏览器原生下载
await exporter.exportCsvFromUrl(csvUrl, {
fileName: '报表',
fieldMap: { id: '编号', name: '名称' },
});
// JSON → CSV
await exporter.exportCsvFromRows(rows, { fileName: '报表', columns });Vite 插件(自动拷贝 SW)
CSV 流式下载依赖同源 Service Worker 文件。
// vite.config.ts
import { defineConfig } from 'vite';
import { streamSheetExport } from 'stream-sheet-export/vite';
export default defineConfig({
plugins: [streamSheetExport()],
});插件会:
- 将
csv-export-sw.js写入public/ - 构建时写入
outDir - Dev Server 中间件直接响应
/csv-export-sw.js
非 Vite 项目可手动拷贝:
cp node_modules/stream-sheet-export/dist/sw/csv-export-sw.js public/csv-export-sw.js或通过选项自定义路径:
createExporter({
serviceWorkerUrl: '/assets/csv-export-sw.js',
csvFallback: 'direct', // 'direct' | 'blob' | 'throw'
});API
createExporter(config?)
返回:
| 方法 | 说明 |
|------|------|
| exportExcelFromUrl(url, options?) | 远程 CSV/Excel → xlsx(urlMode: transform\|direct) |
| exportExcelFromRows(rows, options?) | JSON/二维数组 → xlsx |
| exportExcelFromAsyncIterable(source, options?) | 异步迭代 → xlsx |
| exportCsvFromUrl(url, options?) | 远程 CSV 流式下载或直链 |
| exportCsvFromRows(rows, options?) | JSON → csv |
| downloadFromUrl(url, options?) | 任意可下载链接直链导出 |
常用选项
| 选项 | 默认 | 说明 |
|------|------|------|
| fileName | export_${Date.now()} | 文件名(自动补扩展名) |
| columns | — | 列定义(title / format / numFmt / render / style) |
| maxRows | 3000000 | 最大数据行 |
| rowsPerSheet | 1000000 | 单 Sheet 拆分行数 |
| sheetNamePrefix | Sheet | Sheet 名前缀 |
| autoDownload | true | 是否自动触发下载 |
| onProgress | — | 进度回调 |
| signal | — | AbortSignal 取消 |
| cellStyleResolver | — | 逐单元格样式 |
| headerStyle / stripeFill | — | 表头 / 斑马纹 |
| fieldMap / formatMap | — | URL 源快捷表头与格式映射 |
| urlMode | transform | transform 解析转换 / direct 直链下载 |
| sourceType | auto | auto / csv / xlsx |
| sheet | 0 | 远程 Excel 读取的 sheet 下标或名称 |
| matchHeaders(列上) | — | 匹配源表头别名 |
格式枚举 format
text | integer | number | number_2 | percent | percent_2 | currency_usd | currency_cny | date | datetime
优先级:numFmt > format > formatMap[key]。
错误类型
ExportError:通用错误(含code)ExportLimitError:超过maxRowsExportAbortError:被AbortSignal取消
浏览器兼容性
- 现代 Chromium / Firefox / Safari(需
ReadableStream、fetch) - CSV SW 方案需 HTTPS 或 localhost,并支持 transferable
ReadableStream - 不支持 SW 时按
csvFallback降级
