quickspeadsheet 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +1072 -0
- package/dist/chunks/decryptOle-CCR7y3ED.js +76 -0
- package/dist/chunks/decryptOoxml-_5lSrxRZ.js +60 -0
- package/dist/chunks/dragMerge-DHUQYNgo.js +70794 -0
- package/dist/chunks/encryptOoxml-Bk1DbPbq.js +82 -0
- package/dist/chunks/udocMetafileBundle-DOq3GGY1.js +1121 -0
- package/dist/community.css +1 -0
- package/dist/community.js +559 -0
- package/dist/enterprise.css +1 -0
- package/dist/enterprise.js +559 -0
- package/dist/pro.css +1 -0
- package/dist/pro.js +559 -0
- package/dist/quickspeadsheet.js +562 -0
- package/dist/style.css +1 -0
- package/dist/types/community.d.ts +10 -0
- package/dist/types/enterprise.d.ts +10 -0
- package/dist/types/excel/core/excelio.d.ts +415 -0
- package/dist/types/index.d.ts +33 -0
- package/dist/types/pro.d.ts +10 -0
- package/dist/types/runtime-public.d.ts +501 -0
- package/dist/types/spread.d.ts +1147 -0
- package/package.json +144 -0
package/README.md
ADDED
|
@@ -0,0 +1,1072 @@
|
|
|
1
|
+
# QuickSpeadsheet
|
|
2
|
+
|
|
3
|
+
一个基于 Vue 3 的 Excel 在线表格编辑器,支持完整的 OOXML 格式解析与写入,提供 DOM 和 Canvas 两种渲染模式。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/quickspeadsheet)
|
|
6
|
+
[](https://github.com/your-repo/quickspeadsheet/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## 目录
|
|
9
|
+
|
|
10
|
+
- [特性](#特性)
|
|
11
|
+
- [安装](#安装)
|
|
12
|
+
- [产品版本与发版说明](#产品版本与发版说明)
|
|
13
|
+
- [商业授权服务(License Server)](#商业授权服务license-server)
|
|
14
|
+
- [快速开始](#快速开始)
|
|
15
|
+
- [项目结构](#项目结构)
|
|
16
|
+
- [渲染模式](#渲染模式)
|
|
17
|
+
- [图片处理配置](#图片处理配置)
|
|
18
|
+
- [详细用法](#详细用法)
|
|
19
|
+
- [TypeScript 支持](#typescript-支持)
|
|
20
|
+
- [国际化](#国际化)
|
|
21
|
+
- [性能优化](#性能优化)
|
|
22
|
+
- [已知限制](#已知限制)
|
|
23
|
+
- [常见问题](#常见问题)
|
|
24
|
+
- [API 文档](#api-文档)
|
|
25
|
+
- [贡献指南](#贡献指南)
|
|
26
|
+
- [许可证](#许可证)
|
|
27
|
+
|
|
28
|
+
## 特性
|
|
29
|
+
|
|
30
|
+
### 核心功能
|
|
31
|
+
- **完整的 Excel 文件支持**:解析和写入 `.xlsx`、`.xlsm` 格式文件
|
|
32
|
+
- **双渲染引擎**:支持 DOM 和 Canvas 两种渲染模式,Canvas 模式支持大文件虚拟滚动
|
|
33
|
+
- **公式引擎**:支持常用 Excel 函数计算
|
|
34
|
+
- **图表支持**:集成 Chart.js,支持柱状图、折线图、饼图等多种图表类型
|
|
35
|
+
- **条件格式**:支持数据条、色阶、图标集等条件格式
|
|
36
|
+
- **数据验证**:支持下拉列表、数字范围、日期等多种验证规则
|
|
37
|
+
- **打印预览**:支持打印预览和 PDF 导出
|
|
38
|
+
|
|
39
|
+
### 图片格式支持
|
|
40
|
+
- **浏览器原生支持**:PNG、JPEG、GIF、WebP、SVG、BMP
|
|
41
|
+
- **前端解码**:
|
|
42
|
+
- TIFF(utif)
|
|
43
|
+
- HEIC/HEIF(heic2any + libheif wasm)
|
|
44
|
+
- JPEG 2000(jpeg2000)
|
|
45
|
+
- PSD/PSB(@webtoon/psd)
|
|
46
|
+
- PDF(pdfjs-dist)
|
|
47
|
+
- EMF/WMF(emf-converter)
|
|
48
|
+
|
|
49
|
+
### 高级特性
|
|
50
|
+
- **加密文件支持**:支持加密 Excel 文件的解密和加密
|
|
51
|
+
- **数据透视表**:支持数据透视表的解析和渲染
|
|
52
|
+
- **切片器**:支持数据切片器的交互
|
|
53
|
+
- **批注**:支持单元格批注的显示和编辑
|
|
54
|
+
- **形状与图片**:支持工作表中的形状和图片渲染
|
|
55
|
+
|
|
56
|
+
## 安装
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install quickspeadsheet
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 产品版本与发版说明
|
|
63
|
+
|
|
64
|
+
本包在 **同一 npm 包** 下通过 `package.json` 的 `exports` 提供三个子路径,对应不同 capability 预设:
|
|
65
|
+
|
|
66
|
+
| 子路径 | 典型用途 |
|
|
67
|
+
|--------|----------|
|
|
68
|
+
| `quickspeadsheet/community` | 基础编辑、导入、JSON 导出;无 Excel 导出 / 打印预览 / 协同等 |
|
|
69
|
+
| `quickspeadsheet/pro` | 单机增强(含 Excel 导出、打印、图表设计、设置面板等);仍无协同 |
|
|
70
|
+
| `quickspeadsheet/enterprise` | 完整协同能力 |
|
|
71
|
+
|
|
72
|
+
- **接入步骤与能力对照**:[docs/product-editions-guide.md](./docs/product-editions-guide.md)
|
|
73
|
+
- **三大产品与授权 Playbook**(子路径 + `licenseContext`):[docs/product-license-playbook.md](./docs/product-license-playbook.md)
|
|
74
|
+
- **客户接入与商业交付 SOP**(试用 -> 转付费 -> 续费 -> 回收):[docs/customer-onboarding-sop.md](./docs/customer-onboarding-sop.md)
|
|
75
|
+
- **客户对外接入简版**(可直接给客户):[docs/customer-onboarding-external.md](./docs/customer-onboarding-external.md)
|
|
76
|
+
- **三档版本功能矩阵**(官网/报价单):[docs/version-feature-matrix.md](./docs/version-feature-matrix.md)
|
|
77
|
+
- **客户接入指南 v1**(前端示例 + 后端时序图):[docs/customer-integration-guide-v1.md](./docs/customer-integration-guide-v1.md)
|
|
78
|
+
- **销售报价文案模板**:[docs/sales-quote-template.md](./docs/sales-quote-template.md)
|
|
79
|
+
- **客户邮件模板**(试用/转付费/续费):[docs/customer-email-templates.md](./docs/customer-email-templates.md)
|
|
80
|
+
- **集成场景总览**(Vue / 纯 JS / 授权 / 扩展;协同为可选):[docs/integration-scenarios-overview.md](./docs/integration-scenarios-overview.md)
|
|
81
|
+
- **Runtime 分层架构**(mermaid):[docs/architecture-runtime-edition.md](./docs/architecture-runtime-edition.md)
|
|
82
|
+
- **阶段 E/F 验收台账**(产品包、发版摘要要点、授权预留勾选):[docs/product-release-license-acceptance.md](./docs/product-release-license-acceptance.md)
|
|
83
|
+
|
|
84
|
+
## 商业授权服务(License Server)
|
|
85
|
+
|
|
86
|
+
仓库已提供可独立运行的授权后端示例:`license-server`,包含:
|
|
87
|
+
|
|
88
|
+
- PostgreSQL 持久化(license、token、billing event)
|
|
89
|
+
- 授权签发/刷新/吊销/状态查询
|
|
90
|
+
- 服务端验签(含 strict token 校验)与 DB 状态守卫
|
|
91
|
+
- Stripe webhook 签名校验、事件归一化、动作分发
|
|
92
|
+
- 管理接口 Bearer 鉴权、provider 白名单、字段策略校验
|
|
93
|
+
|
|
94
|
+
快速使用:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cd license-server
|
|
98
|
+
npm install
|
|
99
|
+
cp .env.example .env
|
|
100
|
+
npm start
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
更多细节见:[`license-server/README.md`](./license-server/README.md)。
|
|
104
|
+
|
|
105
|
+
## 快速开始
|
|
106
|
+
|
|
107
|
+
### 基础用法
|
|
108
|
+
|
|
109
|
+
```vue
|
|
110
|
+
<template>
|
|
111
|
+
<SpreadExcelViewer
|
|
112
|
+
ref="viewerRef"
|
|
113
|
+
:renderer="renderer"
|
|
114
|
+
@workbook-loaded="onWorkbookLoaded"
|
|
115
|
+
/>
|
|
116
|
+
</template>
|
|
117
|
+
|
|
118
|
+
<script setup>
|
|
119
|
+
import { ref } from 'vue'
|
|
120
|
+
import { SpreadExcelViewer, useSpread } from 'quickspeadsheet'
|
|
121
|
+
|
|
122
|
+
const viewerRef = ref(null)
|
|
123
|
+
const renderer = ref('canvas') // 'dom' | 'canvas'
|
|
124
|
+
|
|
125
|
+
function onWorkbookLoaded(workbook) {
|
|
126
|
+
console.log('Workbook loaded:', workbook)
|
|
127
|
+
}
|
|
128
|
+
</script>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 协同连接真实后端(替换 mock)
|
|
132
|
+
|
|
133
|
+
`SpreadExcelViewer` 支持直接传入 `documentId` 与 `collaborationServices`。
|
|
134
|
+
未显式开启 `mode: 'mock'` 时,默认按远端模式创建适配器:
|
|
135
|
+
|
|
136
|
+
- REST 默认:`/api/v1`
|
|
137
|
+
- WS 默认:`ws(s)://<当前 host>/realtime/documents/{documentId}`
|
|
138
|
+
|
|
139
|
+
```vue
|
|
140
|
+
<template>
|
|
141
|
+
<SpreadExcelViewer
|
|
142
|
+
document-id="doc_prod_001"
|
|
143
|
+
:collaboration-services="collabConfig"
|
|
144
|
+
:warnings-clear-merge-window-ms="30000"
|
|
145
|
+
/>
|
|
146
|
+
</template>
|
|
147
|
+
|
|
148
|
+
<script setup>
|
|
149
|
+
const collabConfig = {
|
|
150
|
+
mode: 'remote',
|
|
151
|
+
// 生产建议开启:避免误连默认地址
|
|
152
|
+
strictRemote: true,
|
|
153
|
+
apiBaseUrl: 'http://127.0.0.1:3848/api/v1',
|
|
154
|
+
realtimeUrl: 'ws://127.0.0.1:3848/realtime/documents/doc_prod_001',
|
|
155
|
+
// 支持 async,可用于 token 刷新
|
|
156
|
+
getAuthHeader: async () => ({ Authorization: `Bearer ${await getAccessToken()}` }),
|
|
157
|
+
// 可选:WS 额外 query(默认会尝试从 Authorization Bearer 自动提取 access_token)
|
|
158
|
+
getAuthQuery: async () => ({ tenant: await getTenantId() }),
|
|
159
|
+
// 可选:修改 token query 字段名,默认 access_token
|
|
160
|
+
authQueryTokenKey: 'token',
|
|
161
|
+
// 默认 false;仅在后端要求 hello 携带 token 时开启
|
|
162
|
+
exposeAuthInHello: false,
|
|
163
|
+
}
|
|
164
|
+
</script>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`warningsClearMergeWindowMs` 用于控制“清空最近协同吸收”写入审计历史时的合并窗口(毫秒):
|
|
168
|
+
|
|
169
|
+
- 默认 `30000`:同一用户在 30 秒内连续清空会合并为一条历史记录并累计数量。
|
|
170
|
+
- 传 `0`:禁用合并,每次清空都保留独立历史记录。
|
|
171
|
+
|
|
172
|
+
连接/发送失败时,协同状态中的 `lastError` 会提供分级字段,便于联调定位:
|
|
173
|
+
|
|
174
|
+
- `status`:HTTP 状态码(如 `401` / `403` / `5xx`)
|
|
175
|
+
- `code`:错误分类(如 `AUTH_UNAUTHORIZED`、`AUTH_FORBIDDEN`、`NETWORK_ERROR`)
|
|
176
|
+
- `retryable`:是否建议重试
|
|
177
|
+
- `stage`:失败阶段(如 `connectAuth`、`connectNetwork`、`connectServer`)
|
|
178
|
+
|
|
179
|
+
Viewer 的“重试连接/重发队列”会优先检查 `lastError.retryable`;当为 `false`(如 403/404)时会直接提示并拦截无效重试。
|
|
180
|
+
|
|
181
|
+
### 使用 Composable
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<template>
|
|
185
|
+
<div ref="containerRef" class="spread-container"></div>
|
|
186
|
+
<button @click="importFile">导入 Excel</button>
|
|
187
|
+
<button @click="exportFile">导出 Excel</button>
|
|
188
|
+
</template>
|
|
189
|
+
|
|
190
|
+
<script setup>
|
|
191
|
+
import { ref } from 'vue'
|
|
192
|
+
import { useSpread } from 'quickspeadsheet'
|
|
193
|
+
|
|
194
|
+
const containerRef = ref(null)
|
|
195
|
+
const { spread, excelIO, initSpread, importFile, exportFile } = useSpread()
|
|
196
|
+
|
|
197
|
+
// 初始化
|
|
198
|
+
initSpread(containerRef.value)
|
|
199
|
+
|
|
200
|
+
// 导入文件
|
|
201
|
+
async function importFile() {
|
|
202
|
+
const input = document.createElement('input')
|
|
203
|
+
input.type = 'file'
|
|
204
|
+
input.accept = '.xlsx,.xlsm'
|
|
205
|
+
input.onchange = async (e) => {
|
|
206
|
+
const file = e.target.files[0]
|
|
207
|
+
await excelIO.value.open(file, (json) => {
|
|
208
|
+
spread.value.fromJSON(json)
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
input.click()
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// 导出文件
|
|
215
|
+
async function exportFile() {
|
|
216
|
+
const json = spread.value.toJSON()
|
|
217
|
+
const blob = await excelIO.value.save(json, { fileExtension: 'xlsx' })
|
|
218
|
+
// 下载文件...
|
|
219
|
+
}
|
|
220
|
+
</script>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 使用核心 API
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
import { createWorkbook, createExcelIO } from 'quickspeadsheet'
|
|
227
|
+
|
|
228
|
+
// 创建工作簿
|
|
229
|
+
const container = document.getElementById('spread-container')
|
|
230
|
+
const workbook = createWorkbook(container, {
|
|
231
|
+
renderer: 'canvas',
|
|
232
|
+
tabStripRatio: 0.88,
|
|
233
|
+
enableCanvasScrollBlit: true,
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
// 获取活动工作表
|
|
237
|
+
const sheet = workbook.getActiveSheet()
|
|
238
|
+
|
|
239
|
+
// 设置单元格值
|
|
240
|
+
sheet.setValue(0, 0, 'Hello World')
|
|
241
|
+
sheet.setValue(1, 0, 123.45)
|
|
242
|
+
|
|
243
|
+
// 设置公式
|
|
244
|
+
sheet.getCell(2, 0).formula('SUM(A1:A10)')
|
|
245
|
+
|
|
246
|
+
// 设置样式
|
|
247
|
+
sheet.setStyle(0, 0, {
|
|
248
|
+
font: 'bold 14px Arial',
|
|
249
|
+
backColor: '#FFD700',
|
|
250
|
+
foreColor: '#000000',
|
|
251
|
+
hAlign: 'center',
|
|
252
|
+
vAlign: 'center',
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
// 合并单元格
|
|
256
|
+
sheet.addSpan(0, 0, 2, 3) // 合并 2 行 3 列
|
|
257
|
+
|
|
258
|
+
// 添加图表
|
|
259
|
+
sheet.charts.add('Chart1', 'barChart', {
|
|
260
|
+
from: { col: 5, row: 0 },
|
|
261
|
+
to: { col: 12, row: 12 },
|
|
262
|
+
chartData: {
|
|
263
|
+
categories: ['A', 'B', 'C', 'D'],
|
|
264
|
+
series: [
|
|
265
|
+
{ name: 'Series 1', values: [10, 20, 30, 40] },
|
|
266
|
+
{ name: 'Series 2', values: [15, 25, 35, 45] },
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// 导入 Excel 文件
|
|
272
|
+
const excelIO = createExcelIO()
|
|
273
|
+
const file = document.querySelector('input[type="file"]').files[0]
|
|
274
|
+
await excelIO.open(file, (json) => {
|
|
275
|
+
workbook.fromJSON(json)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
// 导出 Excel 文件
|
|
279
|
+
const json = workbook.toJSON()
|
|
280
|
+
const blob = await excelIO.save(json)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## 项目结构
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
src/
|
|
287
|
+
├── excel/
|
|
288
|
+
│ ├── components/ # Vue 组件
|
|
289
|
+
│ │ ├── SpreadExcelViewer.vue # 主视图组件
|
|
290
|
+
│ │ ├── SpreadToolbar.vue # 工具栏
|
|
291
|
+
│ │ ├── SpreadFormulaBar.vue # 公式栏
|
|
292
|
+
│ │ ├── SpreadSheetTabs.vue # 工作表标签
|
|
293
|
+
│ │ ├── SpreadContainer.vue # 容器组件
|
|
294
|
+
│ │ ├── SpreadPrintPreview.vue # 打印预览
|
|
295
|
+
│ │ ├── SpreadSearchDialog.vue # 搜索对话框
|
|
296
|
+
│ │ └── SpreadInspector/ # 属性检查器
|
|
297
|
+
│ │
|
|
298
|
+
│ ├── composables/ # Vue Composables
|
|
299
|
+
│ │ └── useSpread.js # Spread 逻辑封装
|
|
300
|
+
│ │
|
|
301
|
+
│ ├── core/ # 核心模块
|
|
302
|
+
│ │ ├── workbook.js # 工作簿模型
|
|
303
|
+
│ │ ├── worksheet.js # 工作表模型
|
|
304
|
+
│ │ ├── cell.js # 单元格模型
|
|
305
|
+
│ │ ├── excelio.js # Excel IO(主线程)
|
|
306
|
+
│ │ ├── excelioWorker.js # Excel IO(Worker)
|
|
307
|
+
│ │ ├── formulaEngine.js # 公式引擎
|
|
308
|
+
│ │ ├── styles.js # 样式处理
|
|
309
|
+
│ │ ├── imageDisplay.js # 图片格式处理
|
|
310
|
+
│ │ ├── charts.js # 图表支持
|
|
311
|
+
│ │ ├── print.js # 打印功能
|
|
312
|
+
│ │ │
|
|
313
|
+
│ │ ├── ooxml/ # OOXML 解析/写入
|
|
314
|
+
│ │ │ ├── parseWorkbook.js
|
|
315
|
+
│ │ │ ├── parseWorksheet.js
|
|
316
|
+
│ │ │ ├── parseDrawing.js
|
|
317
|
+
│ │ │ ├── parseChart.js
|
|
318
|
+
│ │ │ ├── writeWorkbook.js
|
|
319
|
+
│ │ │ ├── writeWorksheet.js
|
|
320
|
+
│ │ │ └── ...
|
|
321
|
+
│ │ │
|
|
322
|
+
│ │ └── renderer/ # 渲染器
|
|
323
|
+
│ │ ├── domRenderer.js # DOM 渲染
|
|
324
|
+
│ │ ├── canvasRenderer.js # Canvas 渲染
|
|
325
|
+
│ │ └── canvasTileCache.js # 瓦片缓存
|
|
326
|
+
│ │
|
|
327
|
+
│ ├── styles/ # 样式文件
|
|
328
|
+
│ └── utils/ # 工具函数
|
|
329
|
+
│
|
|
330
|
+
└── types/ # TypeScript 类型定义
|
|
331
|
+
└── spread.d.ts
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## 渲染模式
|
|
335
|
+
|
|
336
|
+
### DOM 模式
|
|
337
|
+
- 适用于小型表格
|
|
338
|
+
- 完整的 CSS 样式支持
|
|
339
|
+
- 更好的可访问性
|
|
340
|
+
|
|
341
|
+
### Canvas 模式
|
|
342
|
+
- 适用于大型表格
|
|
343
|
+
- 虚拟滚动支持
|
|
344
|
+
- 瓦片缓存优化
|
|
345
|
+
- 滚动位图 blit 优化
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
const workbook = createWorkbook(container, {
|
|
349
|
+
renderer: 'canvas',
|
|
350
|
+
enableCanvasScrollBlit: true, // 启用滚动位图优化
|
|
351
|
+
enableCanvasTileCachePrototype: true, // 启用瓦片缓存
|
|
352
|
+
})
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## 图片处理配置
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
const workbook = createWorkbook(container, {
|
|
359
|
+
imageDisplay: {
|
|
360
|
+
strategy: 'frontend', // 'frontend' | 'native' | 'custom'
|
|
361
|
+
tryCustomAfterFrontend: true, // 前端解码失败后尝试自定义解析器
|
|
362
|
+
maxDecodePixels: 16_000_000, // 最大解码像素数
|
|
363
|
+
pdfMaxCanvasSide: 2048, // PDF 渲染最大边长
|
|
364
|
+
frontendTiff: true, // 启用 TIFF 解码
|
|
365
|
+
frontendPdf: true, // 启用 PDF 解码
|
|
366
|
+
frontendHeic: true, // 启用 HEIC 解码
|
|
367
|
+
frontendJp2: true, // 启用 JPEG 2000 解码
|
|
368
|
+
frontendPsd: true, // 启用 PSD 解码
|
|
369
|
+
frontendEmf: true, // 启用 EMF/WMF 解码
|
|
370
|
+
},
|
|
371
|
+
})
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## 自定义图片解析器
|
|
375
|
+
|
|
376
|
+
```javascript
|
|
377
|
+
const workbook = createWorkbook(container, {
|
|
378
|
+
imageDisplay: {
|
|
379
|
+
frontendEmf: false, // 禁用前端 EMF 解码
|
|
380
|
+
resolver: async ({ src, mime, ext }) => {
|
|
381
|
+
if (mime === 'image/x-emf' || mime === 'image/x-wmf') {
|
|
382
|
+
// 调用后端 API 转换
|
|
383
|
+
const response = await fetch('/api/convert-emf', {
|
|
384
|
+
method: 'POST',
|
|
385
|
+
body: JSON.stringify({ image: src }),
|
|
386
|
+
})
|
|
387
|
+
return await response.text()
|
|
388
|
+
}
|
|
389
|
+
return null
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## 事件
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
// 工作簿事件
|
|
399
|
+
workbook.bind('SheetChanged', (e) => {})
|
|
400
|
+
workbook.bind('SelectionChanged', (e) => {})
|
|
401
|
+
workbook.bind('CellChanged', (e) => {})
|
|
402
|
+
|
|
403
|
+
// 工作表事件
|
|
404
|
+
sheet.bind('ValueChanged', (e) => {})
|
|
405
|
+
sheet.bind('SelectionChanged', (e) => {})
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## 开发
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
# 安装依赖
|
|
412
|
+
npm install
|
|
413
|
+
|
|
414
|
+
# 启动开发服务器
|
|
415
|
+
npm run dev
|
|
416
|
+
|
|
417
|
+
# 运行测试
|
|
418
|
+
npm run test
|
|
419
|
+
|
|
420
|
+
# 构建生产版本
|
|
421
|
+
npm run build
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## 依赖
|
|
425
|
+
|
|
426
|
+
### 核心依赖
|
|
427
|
+
- `vue` ^3.4.0
|
|
428
|
+
- `jszip` ^3.10.1
|
|
429
|
+
|
|
430
|
+
### 可选依赖
|
|
431
|
+
- `chart.js` ^4.5.1 - 图表支持
|
|
432
|
+
- `chartjs-chart-financial` - 金融图表
|
|
433
|
+
|
|
434
|
+
### 图片解码依赖
|
|
435
|
+
- `utif` - TIFF 解码
|
|
436
|
+
- `heic2any` - HEIC/HEIF 解码
|
|
437
|
+
- `jpeg2000` - JPEG 2000 解码
|
|
438
|
+
- `@webtoon/psd` - PSD 解码
|
|
439
|
+
- `pdfjs-dist` - PDF 渲染
|
|
440
|
+
- `emf-converter` - EMF/WMF 解码
|
|
441
|
+
|
|
442
|
+
## 浏览器支持
|
|
443
|
+
|
|
444
|
+
- Chrome >= 80
|
|
445
|
+
- Firefox >= 75
|
|
446
|
+
- Safari >= 14
|
|
447
|
+
- Edge >= 80
|
|
448
|
+
|
|
449
|
+
## 详细用法
|
|
450
|
+
|
|
451
|
+
### 单元格操作
|
|
452
|
+
|
|
453
|
+
```javascript
|
|
454
|
+
const sheet = workbook.getActiveSheet()
|
|
455
|
+
|
|
456
|
+
// 设置值
|
|
457
|
+
sheet.setValue(0, 0, '文本')
|
|
458
|
+
sheet.setValue(1, 0, 123)
|
|
459
|
+
sheet.setValue(2, 0, new Date())
|
|
460
|
+
|
|
461
|
+
// 获取值
|
|
462
|
+
const value = sheet.getValue(0, 0)
|
|
463
|
+
|
|
464
|
+
// 批量设置
|
|
465
|
+
for (let r = 0; r < 10; r++) {
|
|
466
|
+
for (let c = 0; c < 5; c++) {
|
|
467
|
+
sheet.setValue(r, c, `R${r}C${c}`)
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// 使用单元格对象
|
|
472
|
+
const cell = sheet.getCell(0, 0)
|
|
473
|
+
cell.setValue('Hello')
|
|
474
|
+
cell.formula('A1+B1')
|
|
475
|
+
cell.setStyle({ font: 'bold 12px Arial' })
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### 样式设置
|
|
479
|
+
|
|
480
|
+
```javascript
|
|
481
|
+
// 单个单元格样式
|
|
482
|
+
sheet.setStyle(0, 0, {
|
|
483
|
+
font: 'bold 14px Arial',
|
|
484
|
+
fontSize: 14,
|
|
485
|
+
fontFamily: 'Arial',
|
|
486
|
+
fontWeight: 'bold',
|
|
487
|
+
fontStyle: 'italic',
|
|
488
|
+
backColor: '#FFD700',
|
|
489
|
+
foreColor: '#000000',
|
|
490
|
+
hAlign: 'center',
|
|
491
|
+
vAlign: 'center',
|
|
492
|
+
borderLeft: { color: '#000000', style: 'thin' },
|
|
493
|
+
borderRight: { color: '#000000', style: 'thin' },
|
|
494
|
+
borderTop: { color: '#000000', style: 'thin' },
|
|
495
|
+
borderBottom: { color: '#000000', style: 'thin' },
|
|
496
|
+
wordWrap: true,
|
|
497
|
+
})
|
|
498
|
+
|
|
499
|
+
// 范围样式
|
|
500
|
+
const range = sheet.getRange(0, 0, 5, 5)
|
|
501
|
+
range.setStyle({ backColor: '#F0F0F0' })
|
|
502
|
+
|
|
503
|
+
// 条件格式
|
|
504
|
+
sheet.setConditionalFormats([
|
|
505
|
+
{
|
|
506
|
+
sqref: 'A1:A100',
|
|
507
|
+
rules: [{
|
|
508
|
+
type: 'cellIs',
|
|
509
|
+
operator: 'greaterThan',
|
|
510
|
+
value: 100,
|
|
511
|
+
style: { backColor: '#FF6B6B' }
|
|
512
|
+
}]
|
|
513
|
+
}
|
|
514
|
+
])
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### 合并单元格
|
|
518
|
+
|
|
519
|
+
```javascript
|
|
520
|
+
// 合并单元格
|
|
521
|
+
sheet.addSpan(0, 0, 2, 3) // 从 A1 开始,合并 2 行 3 列
|
|
522
|
+
|
|
523
|
+
// 取消合并
|
|
524
|
+
sheet.removeSpan(0, 0)
|
|
525
|
+
|
|
526
|
+
// 获取所有合并区域
|
|
527
|
+
const spans = sheet.getSpans()
|
|
528
|
+
|
|
529
|
+
// 检查单元格是否在合并区域内
|
|
530
|
+
const span = sheet.getSpan(0, 0)
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### 行列操作
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
// 设置行高列宽
|
|
537
|
+
sheet.setRowHeight(0, 30) // 第一行高度 30px
|
|
538
|
+
sheet.setColumnWidth(0, 100) // 第一列宽度 100px
|
|
539
|
+
|
|
540
|
+
// 获取行高列宽
|
|
541
|
+
const rowHeight = sheet.getRowHeight(0)
|
|
542
|
+
const colWidth = sheet.getColumnWidth(0)
|
|
543
|
+
|
|
544
|
+
// 隐藏/显示行列
|
|
545
|
+
sheet.setRowVisible(0, false)
|
|
546
|
+
sheet.setColumnVisible(0, true)
|
|
547
|
+
|
|
548
|
+
// 设置行列数
|
|
549
|
+
sheet.setRowCount(1000)
|
|
550
|
+
sheet.setColumnCount(50)
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### 公式使用
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
// 基础公式
|
|
557
|
+
sheet.getCell(0, 0).formula('SUM(A1:A10)')
|
|
558
|
+
sheet.getCell(1, 0).formula('AVERAGE(B1:B10)')
|
|
559
|
+
sheet.getCell(2, 0).formula('MAX(C1:C10)')
|
|
560
|
+
|
|
561
|
+
// 条件公式
|
|
562
|
+
sheet.getCell(0, 1).formula('IF(A1>100, "高", "低")')
|
|
563
|
+
|
|
564
|
+
// 跨工作表引用
|
|
565
|
+
sheet.getCell(0, 2).formula('Sheet2!A1 + Sheet3!B2')
|
|
566
|
+
|
|
567
|
+
// 嵌套公式
|
|
568
|
+
sheet.getCell(0, 3).formula('IF(SUM(A1:A10)>100, MAX(B1:B10), MIN(B1:B10))')
|
|
569
|
+
|
|
570
|
+
// 数组公式
|
|
571
|
+
sheet.getCell(0, 4).formula('SUMPRODUCT(A1:A10, B1:B10)')
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### 图表创建
|
|
575
|
+
|
|
576
|
+
```javascript
|
|
577
|
+
// 柱状图
|
|
578
|
+
sheet.charts.add('SalesChart', 'barChart', {
|
|
579
|
+
from: { col: 5, row: 0 },
|
|
580
|
+
to: { col: 12, row: 15 },
|
|
581
|
+
title: '月度销售额',
|
|
582
|
+
chartData: {
|
|
583
|
+
categories: ['一月', '二月', '三月', '四月', '五月'],
|
|
584
|
+
series: [
|
|
585
|
+
{ name: '产品A', values: [120, 150, 180, 200, 170] },
|
|
586
|
+
{ name: '产品B', values: [80, 100, 120, 140, 160] }
|
|
587
|
+
]
|
|
588
|
+
},
|
|
589
|
+
legend: { position: 'bottom' }
|
|
590
|
+
})
|
|
591
|
+
|
|
592
|
+
// 折线图
|
|
593
|
+
sheet.charts.add('TrendChart', 'lineChart', {
|
|
594
|
+
from: { col: 0, row: 20 },
|
|
595
|
+
colCount: 10,
|
|
596
|
+
rowCount: 12,
|
|
597
|
+
chartData: {
|
|
598
|
+
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
599
|
+
series: [
|
|
600
|
+
{ name: '收入', values: [1000, 1200, 1500, 1800] }
|
|
601
|
+
]
|
|
602
|
+
}
|
|
603
|
+
})
|
|
604
|
+
|
|
605
|
+
// 饼图
|
|
606
|
+
sheet.charts.add('PieChart', 'pieChart', {
|
|
607
|
+
from: { col: 0, row: 0 },
|
|
608
|
+
colCount: 6,
|
|
609
|
+
rowCount: 10,
|
|
610
|
+
chartData: {
|
|
611
|
+
categories: ['技术', '市场', '销售', '运营'],
|
|
612
|
+
series: [{ values: [35, 25, 30, 10] }]
|
|
613
|
+
}
|
|
614
|
+
})
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### 数据验证
|
|
618
|
+
|
|
619
|
+
```javascript
|
|
620
|
+
// 下拉列表
|
|
621
|
+
sheet.setDataValidator(0, 0, {
|
|
622
|
+
type: 'list',
|
|
623
|
+
formula1: '"选项1,选项2,选项3"',
|
|
624
|
+
showDropDown: true,
|
|
625
|
+
showErrorMessage: true,
|
|
626
|
+
errorTitle: '输入错误',
|
|
627
|
+
errorMessage: '请从下拉列表中选择'
|
|
628
|
+
})
|
|
629
|
+
|
|
630
|
+
// 数字范围验证
|
|
631
|
+
sheet.setDataValidator(1, 0, {
|
|
632
|
+
type: 'number',
|
|
633
|
+
operator: 'between',
|
|
634
|
+
value1: 0,
|
|
635
|
+
value2: 100,
|
|
636
|
+
showErrorMessage: true,
|
|
637
|
+
errorTitle: '数值超出范围',
|
|
638
|
+
errorMessage: '请输入 0-100 之间的数字'
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
// 日期验证
|
|
642
|
+
sheet.setDataValidator(2, 0, {
|
|
643
|
+
type: 'date',
|
|
644
|
+
operator: 'greaterThan',
|
|
645
|
+
value1: '2024-01-01',
|
|
646
|
+
showErrorMessage: true
|
|
647
|
+
})
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
### 批注操作
|
|
651
|
+
|
|
652
|
+
```javascript
|
|
653
|
+
// 添加批注
|
|
654
|
+
sheet.setComment(0, 0, {
|
|
655
|
+
text: '这是一个批注',
|
|
656
|
+
author: '用户名',
|
|
657
|
+
width: 200,
|
|
658
|
+
height: 100
|
|
659
|
+
})
|
|
660
|
+
|
|
661
|
+
// 获取批注
|
|
662
|
+
const comment = sheet.getComment(0, 0)
|
|
663
|
+
|
|
664
|
+
// 删除批注
|
|
665
|
+
sheet.removeComment(0, 0)
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
### 打印配置
|
|
669
|
+
|
|
670
|
+
```javascript
|
|
671
|
+
import { PrintInfo, print } from 'quickspeadsheet'
|
|
672
|
+
|
|
673
|
+
// 配置打印信息
|
|
674
|
+
const printInfo = new PrintInfo()
|
|
675
|
+
printInfo.paperSize = 'a4'
|
|
676
|
+
printInfo.orientation = 'portrait'
|
|
677
|
+
printInfo.fitPagesWide = 1
|
|
678
|
+
printInfo.fitPagesTall = 0
|
|
679
|
+
printInfo.header = '&C&"Arial,Bold"&18销售报表'
|
|
680
|
+
printInfo.footer = '&L&D&C第 &P 页,共 &N 页&R&T'
|
|
681
|
+
printInfo.showGridLine = true
|
|
682
|
+
printInfo.centerHorizontal = true
|
|
683
|
+
printInfo.centerVertical = true
|
|
684
|
+
|
|
685
|
+
// 设置打印区域
|
|
686
|
+
printInfo.printArea = 'A1:F50'
|
|
687
|
+
|
|
688
|
+
// 设置重复标题行
|
|
689
|
+
printInfo.repeatRowStart = 0
|
|
690
|
+
printInfo.repeatRowEnd = 2
|
|
691
|
+
|
|
692
|
+
// 执行打印
|
|
693
|
+
await print(workbook)
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### 撤销/重做
|
|
697
|
+
|
|
698
|
+
```javascript
|
|
699
|
+
const undoManager = workbook.undoManager()
|
|
700
|
+
|
|
701
|
+
// 撤销
|
|
702
|
+
if (undoManager.canUndo()) {
|
|
703
|
+
undoManager.undo()
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// 重做
|
|
707
|
+
if (undoManager.canRedo()) {
|
|
708
|
+
undoManager.redo()
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// 清空历史
|
|
712
|
+
undoManager.clear()
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
### 搜索替换
|
|
716
|
+
|
|
717
|
+
```javascript
|
|
718
|
+
import { findInSheet, replaceInSheet, findAllInSheet } from 'quickspeadsheet'
|
|
719
|
+
|
|
720
|
+
// 查找
|
|
721
|
+
const matches = findInSheet(sheet, '搜索文本', {
|
|
722
|
+
matchCase: false,
|
|
723
|
+
matchWholeWord: false
|
|
724
|
+
})
|
|
725
|
+
|
|
726
|
+
// 查找所有
|
|
727
|
+
const allMatches = findAllInSheet(sheet, '搜索文本')
|
|
728
|
+
|
|
729
|
+
// 替换
|
|
730
|
+
const count = replaceInSheet(sheet, '旧文本', '新文本', {
|
|
731
|
+
matchCase: false,
|
|
732
|
+
replaceAll: true
|
|
733
|
+
})
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
## 性能优化
|
|
737
|
+
|
|
738
|
+
### Canvas 模式优化
|
|
739
|
+
|
|
740
|
+
```javascript
|
|
741
|
+
const workbook = createWorkbook(container, {
|
|
742
|
+
renderer: 'canvas',
|
|
743
|
+
// 启用滚动位图优化,减少重绘
|
|
744
|
+
enableCanvasScrollBlit: true,
|
|
745
|
+
// 启用瓦片缓存(实验性)
|
|
746
|
+
enableCanvasTileCachePrototype: true,
|
|
747
|
+
})
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### 大文件处理
|
|
751
|
+
|
|
752
|
+
```javascript
|
|
753
|
+
// 使用 Worker 线程解析大文件
|
|
754
|
+
const excelIO = createExcelIO()
|
|
755
|
+
await excelIO.open(file, (json) => {
|
|
756
|
+
workbook.fromJSON(json)
|
|
757
|
+
}, {
|
|
758
|
+
useWorker: true,
|
|
759
|
+
onProgress: (progress) => {
|
|
760
|
+
console.log(`进度: ${Math.round(progress.progress * 100)}%`)
|
|
761
|
+
}
|
|
762
|
+
})
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
### 按需加载
|
|
766
|
+
|
|
767
|
+
```javascript
|
|
768
|
+
// 设置最大行数限制
|
|
769
|
+
await excelIO.open(file, callback, {
|
|
770
|
+
maxRows: 10000
|
|
771
|
+
})
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
### 图片处理优化
|
|
775
|
+
|
|
776
|
+
```javascript
|
|
777
|
+
const workbook = createWorkbook(container, {
|
|
778
|
+
imageDisplay: {
|
|
779
|
+
// 限制最大解码像素,防止内存溢出
|
|
780
|
+
maxDecodePixels: 16_000_000,
|
|
781
|
+
// PDF 渲染最大边长
|
|
782
|
+
pdfMaxCanvasSide: 2048,
|
|
783
|
+
// 按需启用格式支持
|
|
784
|
+
frontendTiff: true,
|
|
785
|
+
frontendPdf: false, // 不需要时可关闭
|
|
786
|
+
frontendHeic: false,
|
|
787
|
+
}
|
|
788
|
+
})
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
## 已知限制
|
|
792
|
+
|
|
793
|
+
### 功能限制
|
|
794
|
+
|
|
795
|
+
| 功能 | 状态 | 说明 |
|
|
796
|
+
|------|------|------|
|
|
797
|
+
| 公式计算 | 部分支持 | 支持 80+ 常用函数,部分高级函数未实现 |
|
|
798
|
+
| 图表渲染 | 部分支持 | 基于 Chart.js,部分 Excel 图表类型不支持 |
|
|
799
|
+
| 数据透视表 | 只读 | 支持解析和渲染,不支持编辑 |
|
|
800
|
+
| 切片器 | 只读 | 支持解析和交互,不支持创建 |
|
|
801
|
+
| VBA 宏 | 不支持 | `.xlsm` 文件中的宏代码不会执行 |
|
|
802
|
+
| ActiveX | 不支持 | ActiveX 控件无法在浏览器中运行 |
|
|
803
|
+
|
|
804
|
+
### 格式限制
|
|
805
|
+
|
|
806
|
+
| 格式 | 状态 | 说明 |
|
|
807
|
+
|------|------|------|
|
|
808
|
+
| `.xlsx` | 完全支持 | Office Open XML 格式 |
|
|
809
|
+
| `.xlsm` | 部分支持 | 宏代码不执行 |
|
|
810
|
+
| `.xls` | 不支持 | 旧版二进制(BIFF);**不提供导入**,请另存为 `.xlsx` |
|
|
811
|
+
| `.csv` | 不支持 | 可通过其他库转换 |
|
|
812
|
+
| `.ods` | 不支持 | OpenDocument 格式 |
|
|
813
|
+
|
|
814
|
+
### 浏览器限制
|
|
815
|
+
|
|
816
|
+
- **IE 浏览器**:不支持
|
|
817
|
+
- **移动端浏览器**:功能受限,建议使用桌面浏览器
|
|
818
|
+
- **Safari**:部分图片格式(如 HEIC)可能需要额外配置
|
|
819
|
+
|
|
820
|
+
## 常见问题
|
|
821
|
+
|
|
822
|
+
### 1. 图片不显示
|
|
823
|
+
|
|
824
|
+
检查图片格式是否支持,EMF/WMF 等格式需要启用前端解码:
|
|
825
|
+
|
|
826
|
+
```javascript
|
|
827
|
+
const workbook = createWorkbook(container, {
|
|
828
|
+
imageDisplay: {
|
|
829
|
+
frontendEmf: true
|
|
830
|
+
}
|
|
831
|
+
})
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
### 2. 大文件加载慢
|
|
835
|
+
|
|
836
|
+
启用 Worker 线程和进度提示:
|
|
837
|
+
|
|
838
|
+
```javascript
|
|
839
|
+
await excelIO.open(file, callback, {
|
|
840
|
+
useWorker: true,
|
|
841
|
+
onProgress: (p) => console.log(p)
|
|
842
|
+
})
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
### 3. 公式计算错误
|
|
846
|
+
|
|
847
|
+
检查公式语法和引用范围,部分函数可能未实现。
|
|
848
|
+
|
|
849
|
+
### 4. 样式丢失
|
|
850
|
+
|
|
851
|
+
确保导出时包含样式信息:
|
|
852
|
+
|
|
853
|
+
```javascript
|
|
854
|
+
const json = workbook.toJSON({ includeStyles: true })
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
### 5. 能否导入 `.xls` 文件?
|
|
858
|
+
|
|
859
|
+
不能。`.xls` 为旧版二进制格式,当前版本 **不提供导入**(界面与 `importFile` 均不接受该扩展名)。请使用 Excel、WPS 等 **另存为 `.xlsx`** 后再导入。
|
|
860
|
+
|
|
861
|
+
## 贡献指南
|
|
862
|
+
|
|
863
|
+
### 开发环境
|
|
864
|
+
|
|
865
|
+
```bash
|
|
866
|
+
# 克隆仓库
|
|
867
|
+
git clone https://github.com/your-repo/quickspeadsheet.git
|
|
868
|
+
|
|
869
|
+
# 安装依赖
|
|
870
|
+
npm install
|
|
871
|
+
|
|
872
|
+
# 启动开发服务器
|
|
873
|
+
npm run dev
|
|
874
|
+
|
|
875
|
+
# 运行测试
|
|
876
|
+
npm run test
|
|
877
|
+
|
|
878
|
+
# 构建生产版本
|
|
879
|
+
npm run build
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
### 代码规范
|
|
883
|
+
|
|
884
|
+
- 使用 ESLint 进行代码检查
|
|
885
|
+
- 使用 Prettier 进行代码格式化
|
|
886
|
+
- 提交前请确保通过所有测试
|
|
887
|
+
|
|
888
|
+
### 提交规范
|
|
889
|
+
|
|
890
|
+
```
|
|
891
|
+
feat: 新功能
|
|
892
|
+
fix: 修复 bug
|
|
893
|
+
docs: 文档更新
|
|
894
|
+
style: 代码格式调整
|
|
895
|
+
refactor: 代码重构
|
|
896
|
+
test: 测试相关
|
|
897
|
+
chore: 构建/工具相关
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
## TypeScript 支持
|
|
901
|
+
|
|
902
|
+
本项目提供完整的 TypeScript 类型定义。
|
|
903
|
+
|
|
904
|
+
### 类型导入
|
|
905
|
+
|
|
906
|
+
```typescript
|
|
907
|
+
import type {
|
|
908
|
+
Workbook,
|
|
909
|
+
Worksheet,
|
|
910
|
+
Cell,
|
|
911
|
+
CellStyle,
|
|
912
|
+
Span,
|
|
913
|
+
Selection,
|
|
914
|
+
DataValidator,
|
|
915
|
+
Comment,
|
|
916
|
+
Chart,
|
|
917
|
+
Table,
|
|
918
|
+
Shape,
|
|
919
|
+
Theme,
|
|
920
|
+
PrintInfo,
|
|
921
|
+
WorkbookJSON,
|
|
922
|
+
SheetJSON,
|
|
923
|
+
} from 'quickspeadsheet'
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
### 类型定义示例
|
|
927
|
+
|
|
928
|
+
```typescript
|
|
929
|
+
import { createWorkbook, createExcelIO } from 'quickspeadsheet'
|
|
930
|
+
import type { WorkbookOptions, CellStyle } from 'quickspeadsheet'
|
|
931
|
+
|
|
932
|
+
const options: WorkbookOptions = {
|
|
933
|
+
renderer: 'canvas',
|
|
934
|
+
tabStripRatio: 0.88,
|
|
935
|
+
enableCanvasScrollBlit: true,
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
const workbook = createWorkbook(container, options)
|
|
939
|
+
|
|
940
|
+
const style: CellStyle = {
|
|
941
|
+
font: 'bold 14px Arial',
|
|
942
|
+
backColor: '#FFD700',
|
|
943
|
+
foreColor: '#000000',
|
|
944
|
+
hAlign: 'center',
|
|
945
|
+
vAlign: 'center',
|
|
946
|
+
}
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
### 泛型支持
|
|
950
|
+
|
|
951
|
+
```typescript
|
|
952
|
+
import type { Worksheet } from 'quickspeadsheet'
|
|
953
|
+
|
|
954
|
+
function processSheet<T>(sheet: Worksheet, data: T[]): void {
|
|
955
|
+
data.forEach((item, index) => {
|
|
956
|
+
sheet.setValue(index, 0, item)
|
|
957
|
+
})
|
|
958
|
+
}
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
## 国际化
|
|
962
|
+
|
|
963
|
+
### 内置语言
|
|
964
|
+
|
|
965
|
+
项目内置中文资源:
|
|
966
|
+
|
|
967
|
+
```javascript
|
|
968
|
+
import { resourcesZh, getResourceZh } from 'quickspeadsheet'
|
|
969
|
+
|
|
970
|
+
// 获取中文资源
|
|
971
|
+
const resource = getResourceZh('key')
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
### 自定义语言
|
|
975
|
+
|
|
976
|
+
```javascript
|
|
977
|
+
import { cultureManager } from 'quickspeadsheet'
|
|
978
|
+
|
|
979
|
+
// 设置语言
|
|
980
|
+
cultureManager.culture('zh-CN')
|
|
981
|
+
|
|
982
|
+
// 添加自定义资源
|
|
983
|
+
cultureManager.addCulture('ja-JP', {
|
|
984
|
+
// 日文资源
|
|
985
|
+
})
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
### 日期格式化
|
|
989
|
+
|
|
990
|
+
```javascript
|
|
991
|
+
import { cultureManager } from 'quickspeadsheet'
|
|
992
|
+
|
|
993
|
+
// 格式化日期
|
|
994
|
+
const formatted = cultureManager.formatDate(new Date(), 'yyyy-MM-dd')
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
### 数字格式化
|
|
998
|
+
|
|
999
|
+
```javascript
|
|
1000
|
+
import { cultureManager } from 'quickspeadsheet'
|
|
1001
|
+
|
|
1002
|
+
// 格式化数字
|
|
1003
|
+
const formatted = cultureManager.formatNumber(1234567.89, '#,##0.00')
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
## API 文档
|
|
1007
|
+
|
|
1008
|
+
详细的 API 文档请参阅 [API.md](./docs/API.md)。产品与授权验收状态见 [product-release-license-acceptance.md](./docs/product-release-license-acceptance.md)。
|
|
1009
|
+
|
|
1010
|
+
### 核心模块
|
|
1011
|
+
|
|
1012
|
+
| 模块 | 描述 |
|
|
1013
|
+
|------|------|
|
|
1014
|
+
| [Workbook](./docs/API.md#workbook) | 工作簿类,管理多个工作表 |
|
|
1015
|
+
| [Worksheet](./docs/API.md#worksheet) | 工作表类,管理单元格数据 |
|
|
1016
|
+
| [Cell](./docs/API.md#cell) | 单元格类,管理单个单元格 |
|
|
1017
|
+
| [ExcelIO](./docs/API.md#excelio) | Excel 文件读写类 |
|
|
1018
|
+
|
|
1019
|
+
### Vue 组件
|
|
1020
|
+
|
|
1021
|
+
| 组件 | 描述 |
|
|
1022
|
+
|------|------|
|
|
1023
|
+
| [SpreadExcelViewer](./docs/API.md#spreadexcelviewer) | 主视图组件 |
|
|
1024
|
+
| [SpreadToolbar](./docs/API.md#spreadtoolbar) | 工具栏组件 |
|
|
1025
|
+
| [SpreadFormulaBar](./docs/API.md#spreadformulabar) | 公式栏组件 |
|
|
1026
|
+
|
|
1027
|
+
### Composables
|
|
1028
|
+
|
|
1029
|
+
| 函数 | 描述 |
|
|
1030
|
+
|------|------|
|
|
1031
|
+
| [useSpread](./docs/API.md#usespread) | Spread 逻辑封装 |
|
|
1032
|
+
|
|
1033
|
+
### 高级功能
|
|
1034
|
+
|
|
1035
|
+
| 功能 | 描述 |
|
|
1036
|
+
|------|------|
|
|
1037
|
+
| [条件格式](./docs/API.md#条件格式) | 根据条件自动应用样式 |
|
|
1038
|
+
| [图表](./docs/API.md#图表) | 创建和操作图表 |
|
|
1039
|
+
| [公式引擎](./docs/API.md#公式引擎) | 公式计算支持 |
|
|
1040
|
+
| [打印功能](./docs/API.md#打印功能) | 打印预览和配置 |
|
|
1041
|
+
| [撤销管理](./docs/API.md#撤销管理) | 撤销/重做操作 |
|
|
1042
|
+
|
|
1043
|
+
## 更新日志
|
|
1044
|
+
|
|
1045
|
+
### v1.0.0
|
|
1046
|
+
|
|
1047
|
+
- 初始版本发布
|
|
1048
|
+
- 支持基本的 Excel 文件读写
|
|
1049
|
+
- 支持 DOM 和 Canvas 双渲染模式
|
|
1050
|
+
- 支持公式计算
|
|
1051
|
+
- 支持图表渲染
|
|
1052
|
+
- 支持条件格式
|
|
1053
|
+
- 支持数据验证
|
|
1054
|
+
- 支持打印预览
|
|
1055
|
+
|
|
1056
|
+
## 相关项目
|
|
1057
|
+
|
|
1058
|
+
- [SheetJS](https://github.com/SheetJS/sheetjs) - Excel 文件解析库
|
|
1059
|
+
- [ExcelJS](https://github.com/exceljs/exceljs) - Excel 文件读写库
|
|
1060
|
+
- [Luckysheet](https://github.com/dream-num/Luckysheet) - 在线表格库
|
|
1061
|
+
- [Handsontable](https://github.com/handsontable/handsontable) - 数据表格组件
|
|
1062
|
+
|
|
1063
|
+
## 许可证
|
|
1064
|
+
|
|
1065
|
+
Proprietary License - 专有许可证
|
|
1066
|
+
|
|
1067
|
+
- ❌ 禁止商业使用
|
|
1068
|
+
- ❌ 禁止分发源代码
|
|
1069
|
+
- ❌ 禁止公开源代码
|
|
1070
|
+
- ✅ 仅限个人非商业用途
|
|
1071
|
+
|
|
1072
|
+
如需商业授权,请联系版权所有者。
|