styled-exceljs 0.21.0 → 0.21.1
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/CHANGELOG.md +17 -0
- package/README.md +8 -2
- package/bower.json +1 -1
- package/dist/xlsx.core.min.js +18 -18
- package/dist/xlsx.core.min.map +1 -1
- package/dist/xlsx.extendscript.js +238 -17
- package/dist/xlsx.full.min.js +17 -17
- package/dist/xlsx.full.min.map +1 -1
- package/dist/xlsx.mini.min.js +10 -10
- package/dist/xlsx.mini.min.map +1 -1
- package/docs/visual-fidelity.md +38 -2
- package/docs/visual-fidelity.zh-CN.md +35 -1
- package/package.json +1 -1
- package/types/index.d.ts +53 -0
- package/xlsx.js +238 -17
- package/xlsx.mjs +238 -17
package/docs/visual-fidelity.md
CHANGED
|
@@ -26,6 +26,7 @@ const wb = XLSX.read(data, {
|
|
|
26
26
|
const html = XLSX.utils.sheet_to_html(ws, {
|
|
27
27
|
cellStyles: true,
|
|
28
28
|
browserPixels: true,
|
|
29
|
+
autoFit: true,
|
|
29
30
|
charts: true,
|
|
30
31
|
drawings: true
|
|
31
32
|
});
|
|
@@ -35,6 +36,8 @@ const html = XLSX.utils.sheet_to_html(ws, {
|
|
|
35
36
|
| --- | --- | --- |
|
|
36
37
|
| `cellStyles` | read / HTML | Resolves full styles into `cell.s`, row styles, and column styles. |
|
|
37
38
|
| `browserPixels` | read / HTML | Converts XLSX/XLS column widths and row heights to CSS pixels. |
|
|
39
|
+
| `autoFit` | HTML / utilities | Measures formatted cell text and computes best-fit column widths. |
|
|
40
|
+
| `overflow` | HTML | Controls unwrapped text overflow (`excel` / `visible` / `clip` / `hidden`). |
|
|
38
41
|
| `charts` | read / HTML | Parses chart models and renders supported chart types as inline SVG. |
|
|
39
42
|
| `drawings` | read / HTML | Parses image/drawing anchors and renders supported images as `<img>`. |
|
|
40
43
|
| `validateMerges` | read | Throws on invalid, duplicate, overlapping, or out-of-bounds merge ranges. |
|
|
@@ -116,6 +119,34 @@ XLSX.utils.row_height_to_px(points);
|
|
|
116
119
|
XLSX.utils.px_to_row_height(px);
|
|
117
120
|
```
|
|
118
121
|
|
|
122
|
+
Best-fit widths can be computed with browser text measurement:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
XLSX.utils.auto_fit_columns(ws, {
|
|
126
|
+
set: true,
|
|
127
|
+
measureText(text, font, style) {
|
|
128
|
+
ctx.font = font;
|
|
129
|
+
return ctx.measureText(text).width;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`auto_fit_columns` scans formatted display text (`cell.w` after formatting),
|
|
135
|
+
composes column, row, and cell styles, and applies Excel-like layout rules:
|
|
136
|
+
|
|
137
|
+
- `alignment.wrapText` measures the longest explicit line or word segment
|
|
138
|
+
instead of expanding to the full paragraph width.
|
|
139
|
+
- `alignment.shrinkToFit` does not force a wider column when an existing width
|
|
140
|
+
is available.
|
|
141
|
+
- merged cells distribute additional width across the merged column span.
|
|
142
|
+
- widths are clamped to the Excel column width range and converted through MDW.
|
|
143
|
+
|
|
144
|
+
`XLSX.utils.measure_text_width(text, style, opts)` is also public. In browsers
|
|
145
|
+
it uses `opts.measureText` or Canvas `measureText`; in Node or headless
|
|
146
|
+
environments it uses a deterministic font-aware approximation. For pixel-close
|
|
147
|
+
Excel rendering, pass a browser Canvas callback using the same font stack as the
|
|
148
|
+
rendered table.
|
|
149
|
+
|
|
119
150
|
### Drawings
|
|
120
151
|
|
|
121
152
|
When `drawings:true` is set, worksheets may expose `ws["!drawings"]`:
|
|
@@ -210,11 +241,11 @@ Tolerant reads attach non-fatal errors to `ws["!mergeErrors"]`. Reads with
|
|
|
210
241
|
## HTML Output
|
|
211
242
|
|
|
212
243
|
`XLSX.utils.sheet_to_html(ws, {cellStyles:true, browserPixels:true,
|
|
213
|
-
charts:true, drawings:true})` emits:
|
|
244
|
+
autoFit:true, charts:true, drawings:true})` emits:
|
|
214
245
|
|
|
215
246
|
- `<colgroup>` entries with browser pixel widths
|
|
216
247
|
- inline row heights
|
|
217
|
-
- font, fill, border, alignment, wrap, shrink, and rotation CSS
|
|
248
|
+
- font, fill, border, alignment, wrap, shrink-to-fit, overflow, and rotation CSS
|
|
218
249
|
- hidden row/column behavior
|
|
219
250
|
- `rowspan` / `colspan` for merged cells
|
|
220
251
|
- an absolutely positioned drawing layer with images and chart SVG
|
|
@@ -222,6 +253,11 @@ charts:true, drawings:true})` emits:
|
|
|
222
253
|
The renderer does not materialize empty grid cells for row/column styles. Row
|
|
223
254
|
and column styles are composed with real cell styles at render time.
|
|
224
255
|
|
|
256
|
+
When `autoFit` is enabled, the generated table uses fixed layout and a computed
|
|
257
|
+
`<colgroup>`. Unwrapped text defaults to Excel-like visible overflow. Use
|
|
258
|
+
`overflow:"clip"` or `overflow:"hidden"` when the host page must constrain cell
|
|
259
|
+
content to the calculated column width.
|
|
260
|
+
|
|
225
261
|
## Completeness Report
|
|
226
262
|
|
|
227
263
|
The release includes a local report helper:
|
|
@@ -25,6 +25,7 @@ const ws = wb.Sheets[wb.SheetNames[0]];
|
|
|
25
25
|
const html = XLSX.utils.sheet_to_html(ws, {
|
|
26
26
|
cellStyles: true,
|
|
27
27
|
browserPixels: true,
|
|
28
|
+
autoFit: true,
|
|
28
29
|
charts: true,
|
|
29
30
|
drawings: true
|
|
30
31
|
});
|
|
@@ -39,6 +40,8 @@ const html = XLSX.utils.sheet_to_html(ws, {
|
|
|
39
40
|
| --- | --- | --- |
|
|
40
41
|
| `cellStyles` | 读取 / HTML | 将完整样式解析到 `cell.s`,并读取行样式和列样式。 |
|
|
41
42
|
| `browserPixels` | 读取 / HTML | 按 XLSX / XLS 规范将列宽、行高换算为浏览器 CSS 像素。 |
|
|
43
|
+
| `autoFit` | HTML / 工具函数 | 按格式化后的文字宽度计算最优列宽。 |
|
|
44
|
+
| `overflow` | HTML | 控制非换行文字溢出方式:`excel` / `visible` / `clip` / `hidden`。 |
|
|
42
45
|
| `charts` | 读取 / HTML | 解析图表模型,并将支持的图表类型以内联 SVG 渲染。 |
|
|
43
46
|
| `drawings` | 读取 / HTML | 解析图片、绘图锚点,支持的内嵌图片渲染为 `<img>`。 |
|
|
44
47
|
| `validateMerges` | 读取 | 读取时校验合并单元格,发现非法、重复、重叠或越界范围时抛错。 |
|
|
@@ -207,6 +210,32 @@ XLSX.utils.row_height_to_px(points);
|
|
|
207
210
|
XLSX.utils.px_to_row_height(px);
|
|
208
211
|
```
|
|
209
212
|
|
|
213
|
+
自动列宽可以接入浏览器真实文字测量:
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
XLSX.utils.auto_fit_columns(ws, {
|
|
217
|
+
set: true,
|
|
218
|
+
measureText(text, font, style) {
|
|
219
|
+
ctx.font = font;
|
|
220
|
+
return ctx.measureText(text).width;
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`auto_fit_columns` 会扫描格式化后的显示文字(`cell.w`),合成列、行、
|
|
226
|
+
单元格样式,并尽量遵循 Excel 的布局行为:
|
|
227
|
+
|
|
228
|
+
- `alignment.wrapText` 开启时,按最长显式行或最长词段计算,而不是按整段
|
|
229
|
+
文本强行拉宽列。
|
|
230
|
+
- `alignment.shrinkToFit` 开启且已有列宽时,不再强制扩大列宽。
|
|
231
|
+
- 合并单元格会把额外宽度分摊到覆盖的列。
|
|
232
|
+
- 最终列宽会限制在 Excel 允许范围内,并通过 MDW 公式转换。
|
|
233
|
+
|
|
234
|
+
`XLSX.utils.measure_text_width(text, style, opts)` 也可单独使用。在浏览器中
|
|
235
|
+
会优先使用 `opts.measureText` 或 Canvas `measureText`;在 Node / 无 DOM
|
|
236
|
+
环境中使用稳定的字体近似算法。若需要尽量贴近 Excel,请传入与页面实际
|
|
237
|
+
字体一致的 Canvas 测量回调。
|
|
238
|
+
|
|
210
239
|
## 图片和绘图
|
|
211
240
|
|
|
212
241
|
开启 `drawings:true` 后,工作表可能暴露 `ws["!drawings"]`:
|
|
@@ -329,6 +358,7 @@ interface MergeError {
|
|
|
329
358
|
XLSX.utils.sheet_to_html(ws, {
|
|
330
359
|
cellStyles: true,
|
|
331
360
|
browserPixels: true,
|
|
361
|
+
autoFit: true,
|
|
332
362
|
charts: true,
|
|
333
363
|
drawings: true
|
|
334
364
|
});
|
|
@@ -339,7 +369,7 @@ XLSX.utils.sheet_to_html(ws, {
|
|
|
339
369
|
- `<colgroup>` 列宽
|
|
340
370
|
- 行高 CSS
|
|
341
371
|
- 字体、字号、颜色、填充、边框
|
|
342
|
-
- 水平 /
|
|
372
|
+
- 水平 / 垂直对齐、换行、缩进、旋转、收缩适应、溢出控制
|
|
343
373
|
- 隐藏行列
|
|
344
374
|
- 合并单元格的 `rowspan` / `colspan`
|
|
345
375
|
- 绝对定位图片层
|
|
@@ -348,6 +378,10 @@ XLSX.utils.sheet_to_html(ws, {
|
|
|
348
378
|
渲染器不会为了行样式或列样式物化整张空白网格。真实单元格渲染时会按
|
|
349
379
|
cell XF > row XF > column XF > default XF 的思路合成最终样式。
|
|
350
380
|
|
|
381
|
+
开启 `autoFit` 后,HTML 表格会使用固定布局和计算后的 `<colgroup>`。
|
|
382
|
+
未换行文本默认使用接近 Excel 的可见溢出效果;如果宿主页面必须把内容
|
|
383
|
+
限制在列宽内,可以设置 `overflow:"clip"` 或 `overflow:"hidden"`。
|
|
384
|
+
|
|
351
385
|
## 完整度报告
|
|
352
386
|
|
|
353
387
|
仓库提供本地完整度报告脚本:
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -629,6 +629,38 @@ export interface CellStyle extends FillStyle {
|
|
|
629
629
|
bgColor?: StyleColor;
|
|
630
630
|
}
|
|
631
631
|
|
|
632
|
+
export interface TextMeasureOpts {
|
|
633
|
+
/** Browser-compatible text measurement callback. Receives text, CSS font string, and resolved style. */
|
|
634
|
+
measureText?: (text: string, font: string, style: CellStyle) => number;
|
|
635
|
+
/** Optional canvas-like object used for browser measureText fallback */
|
|
636
|
+
canvas?: any;
|
|
637
|
+
/** Maximum digit width in CSS pixels for Excel width conversion */
|
|
638
|
+
MDW?: number;
|
|
639
|
+
/** Additional pixel padding used when measuring cell text */
|
|
640
|
+
padding?: number;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
export interface AutoFitColumnOpts extends TextMeasureOpts {
|
|
644
|
+
/** Range to scan. Defaults to worksheet !ref */
|
|
645
|
+
range?: string | Range;
|
|
646
|
+
/** Minimum column width in Excel characters */
|
|
647
|
+
min?: number;
|
|
648
|
+
/** Maximum column width in Excel characters */
|
|
649
|
+
max?: number;
|
|
650
|
+
/** Minimum column width in browser pixels */
|
|
651
|
+
minPx?: number;
|
|
652
|
+
/** Maximum column width in browser pixels */
|
|
653
|
+
maxPx?: number;
|
|
654
|
+
/** Include merged cells when measuring width. Defaults to true */
|
|
655
|
+
includeMerged?: boolean;
|
|
656
|
+
/** Skip hidden rows and columns */
|
|
657
|
+
skipHidden?: boolean;
|
|
658
|
+
/** If false, return computed columns without mutating worksheet !cols */
|
|
659
|
+
set?: boolean;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export type HTMLOverflowMode = "excel" | "visible" | "clip" | "hidden";
|
|
663
|
+
|
|
632
664
|
/** Drawing relationship entry */
|
|
633
665
|
export interface DrawingRelationship {
|
|
634
666
|
Type?: string;
|
|
@@ -1119,6 +1151,18 @@ export interface Sheet2HTMLOpts {
|
|
|
1119
1151
|
|
|
1120
1152
|
/** If true, render parsed drawing images */
|
|
1121
1153
|
drawings?: boolean;
|
|
1154
|
+
|
|
1155
|
+
/** If true or an options object, auto-fit columns using measured text widths */
|
|
1156
|
+
autoFit?: boolean | AutoFitColumnOpts;
|
|
1157
|
+
|
|
1158
|
+
/** Unwrapped text overflow behavior for browser rendering */
|
|
1159
|
+
overflow?: HTMLOverflowMode;
|
|
1160
|
+
|
|
1161
|
+
/** Browser-compatible text measurement callback used by autoFit and shrink-to-fit */
|
|
1162
|
+
measureText?: (text: string, font: string, style: CellStyle) => number;
|
|
1163
|
+
|
|
1164
|
+
/** Optional canvas-like object used for text measurement */
|
|
1165
|
+
canvas?: any;
|
|
1122
1166
|
}
|
|
1123
1167
|
|
|
1124
1168
|
export interface Sheet2JSONOpts extends DateNFOption {
|
|
@@ -1260,6 +1304,15 @@ export interface XLSX$Utils {
|
|
|
1260
1304
|
/** Validate worksheet merge ranges */
|
|
1261
1305
|
validate_merges(worksheet: WorkSheet, opts?: CommonOptions): MergeError[];
|
|
1262
1306
|
|
|
1307
|
+
/** Measure text width in browser pixels using Canvas when available */
|
|
1308
|
+
measure_text_width(text: string, style?: CellStyle, opts?: TextMeasureOpts): number;
|
|
1309
|
+
|
|
1310
|
+
/** Auto-fit worksheet columns based on formatted cell text */
|
|
1311
|
+
auto_fit_columns(worksheet: WorkSheet, opts?: AutoFitColumnOpts): ColInfo[];
|
|
1312
|
+
|
|
1313
|
+
/** Alias for auto_fit_columns */
|
|
1314
|
+
autofit_columns(worksheet: WorkSheet, opts?: AutoFitColumnOpts): ColInfo[];
|
|
1315
|
+
|
|
1263
1316
|
/** Convert XLSX column width to browser pixels */
|
|
1264
1317
|
col_width_to_px(width: number): number;
|
|
1265
1318
|
|
package/xlsx.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false, Set:false, Float32Array:false */
|
|
5
5
|
var XLSX = {};
|
|
6
6
|
function make_xlsx_lib(XLSX){
|
|
7
|
-
XLSX.version = '0.21.
|
|
7
|
+
XLSX.version = '0.21.1';
|
|
8
8
|
var current_codepage = 1200, current_ansi = 1252;
|
|
9
9
|
/*global cptable:true, window */
|
|
10
10
|
var $cptable;
|
|
@@ -11152,6 +11152,188 @@ function process_col(coll) {
|
|
|
11152
11152
|
if(coll.customWidth) delete coll.customWidth;
|
|
11153
11153
|
}
|
|
11154
11154
|
|
|
11155
|
+
var XLSX_COL_WIDTH_MAX = 255, XLSX_COL_WIDTH_PADDING = 5;
|
|
11156
|
+
function clamp_col_width(width) {
|
|
11157
|
+
return width > XLSX_COL_WIDTH_MAX ? XLSX_COL_WIDTH_MAX : width < 0 ? 0 : width;
|
|
11158
|
+
}
|
|
11159
|
+
function px2col(px) {
|
|
11160
|
+
var width = char2width(px2char(Math.max(0, px)));
|
|
11161
|
+
return clamp_col_width(width);
|
|
11162
|
+
}
|
|
11163
|
+
function col2px(col) {
|
|
11164
|
+
if(!col) return 64;
|
|
11165
|
+
if(col.wpx != null) return col.wpx;
|
|
11166
|
+
if(col.width != null) return width2px(col.width);
|
|
11167
|
+
if(col.wch != null) return width2px(char2width(col.wch));
|
|
11168
|
+
return 64;
|
|
11169
|
+
}
|
|
11170
|
+
function set_col_width_from_px(col, px) {
|
|
11171
|
+
if(!col) col = ({});
|
|
11172
|
+
col.wpx = Math.max(0, Math.ceil(px));
|
|
11173
|
+
col.wch = px2char(col.wpx);
|
|
11174
|
+
col.width = px2col(col.wpx);
|
|
11175
|
+
col.MDW = MDW;
|
|
11176
|
+
col.bestFit = true;
|
|
11177
|
+
col.customWidth = true;
|
|
11178
|
+
return col;
|
|
11179
|
+
}
|
|
11180
|
+
function style_font_size_pt(style) {
|
|
11181
|
+
var font = style && style.font || {};
|
|
11182
|
+
var sz = +font.sz;
|
|
11183
|
+
return sz > 0 ? sz : 11;
|
|
11184
|
+
}
|
|
11185
|
+
function style_font_family(style) {
|
|
11186
|
+
var font = style && style.font || {};
|
|
11187
|
+
return font.name || "Calibri";
|
|
11188
|
+
}
|
|
11189
|
+
function css_font_from_style(style) {
|
|
11190
|
+
var font = style && style.font || {};
|
|
11191
|
+
var parts = [];
|
|
11192
|
+
if(font.italic) parts.push("italic");
|
|
11193
|
+
if(font.bold) parts.push("bold");
|
|
11194
|
+
parts.push(style_font_size_pt(style) + "pt");
|
|
11195
|
+
var name = style_font_family(style);
|
|
11196
|
+
if(/[,\s'"]/.test(name)) name = '"' + String(name).replace(/"/g, '\\"') + '"';
|
|
11197
|
+
parts.push(name);
|
|
11198
|
+
return parts.join(" ");
|
|
11199
|
+
}
|
|
11200
|
+
function fallback_char_width(ch, fpx) {
|
|
11201
|
+
var cc = ch.charCodeAt(0);
|
|
11202
|
+
if(cc == 9 || cc == 32) return fpx * 0.33;
|
|
11203
|
+
if(cc >= 48 && cc <= 57) return fpx * 0.52;
|
|
11204
|
+
if(cc >= 65 && cc <= 90) return fpx * 0.62;
|
|
11205
|
+
if(cc >= 97 && cc <= 122) {
|
|
11206
|
+
if("iljtfr".indexOf(ch) > -1) return fpx * 0.28;
|
|
11207
|
+
if("mw".indexOf(ch) > -1) return fpx * 0.82;
|
|
11208
|
+
return fpx * 0.50;
|
|
11209
|
+
}
|
|
11210
|
+
if(cc >= 0x2E80) return fpx;
|
|
11211
|
+
return fpx * 0.52;
|
|
11212
|
+
}
|
|
11213
|
+
function fallback_text_width(text, style) {
|
|
11214
|
+
var fpx = pt2px_browser(style_font_size_pt(style)), width = 0;
|
|
11215
|
+
for(var i = 0; i < text.length; ++i) width += fallback_char_width(text.charAt(i), fpx);
|
|
11216
|
+
return width;
|
|
11217
|
+
}
|
|
11218
|
+
function measure_text_width(text, style, opts) {
|
|
11219
|
+
var o = opts || {};
|
|
11220
|
+
var str = text == null ? "" : String(text);
|
|
11221
|
+
var lines = str.split(/\r\n|\n|\r/g), max = 0, i = 0, w = 0;
|
|
11222
|
+
if(o.measureText) for(i = 0; i < lines.length; ++i) {
|
|
11223
|
+
w = +o.measureText(lines[i], css_font_from_style(style), style || {});
|
|
11224
|
+
if(isFinite(w) && w > max) max = w;
|
|
11225
|
+
}
|
|
11226
|
+
else {
|
|
11227
|
+
var canvas = o.canvas, ctx = null;
|
|
11228
|
+
if(!canvas && typeof document !== "undefined" && document.createElement) try { canvas = document.createElement("canvas"); } catch(e) {}
|
|
11229
|
+
try { ctx = canvas && canvas.getContext && canvas.getContext("2d"); } catch(e) { ctx = null; }
|
|
11230
|
+
if(ctx && ctx.measureText) {
|
|
11231
|
+
ctx.font = css_font_from_style(style);
|
|
11232
|
+
for(i = 0; i < lines.length; ++i) {
|
|
11233
|
+
w = ctx.measureText(lines[i]).width;
|
|
11234
|
+
if(isFinite(w) && w > max) max = w;
|
|
11235
|
+
}
|
|
11236
|
+
} else for(i = 0; i < lines.length; ++i) {
|
|
11237
|
+
w = fallback_text_width(lines[i], style || {});
|
|
11238
|
+
if(isFinite(w) && w > max) max = w;
|
|
11239
|
+
}
|
|
11240
|
+
}
|
|
11241
|
+
return max;
|
|
11242
|
+
}
|
|
11243
|
+
function auto_fit_cell_text(cell, opts) {
|
|
11244
|
+
if(!cell || cell.v == null) return "";
|
|
11245
|
+
if(cell.w == null && cell.t != 'z') format_cell(cell);
|
|
11246
|
+
return String(cell.w != null ? cell.w : cell.v);
|
|
11247
|
+
}
|
|
11248
|
+
function text_width_segments(text, wrap) {
|
|
11249
|
+
var lines = String(text == null ? "" : text).split(/\r\n|\n|\r/g), out = [], i = 0, j = 0, parts = null;
|
|
11250
|
+
if(!wrap) return lines;
|
|
11251
|
+
for(i = 0; i < lines.length; ++i) {
|
|
11252
|
+
parts = lines[i].split(/[\t \u00A0\-\/]+/);
|
|
11253
|
+
for(j = 0; j < parts.length; ++j) if(parts[j]) out.push(parts[j]);
|
|
11254
|
+
if(!parts.length || (parts.length == 1 && !parts[0])) out.push(lines[i]);
|
|
11255
|
+
}
|
|
11256
|
+
return out.length ? out : [""];
|
|
11257
|
+
}
|
|
11258
|
+
function effective_cell_style(ws, cell, R, C) {
|
|
11259
|
+
var out = ({}), cols = ws["!cols"] || [], rows = ws["!rows"] || [];
|
|
11260
|
+
if(cols[C] && cols[C].s) extend_style_obj(out, cols[C].s);
|
|
11261
|
+
if(rows[R] && rows[R].s) extend_style_obj(out, rows[R].s);
|
|
11262
|
+
if(cell && cell.s) extend_style_obj(out, cell.s);
|
|
11263
|
+
return out;
|
|
11264
|
+
}
|
|
11265
|
+
function measure_cell_text_width(cell, style, opts) {
|
|
11266
|
+
var o = opts || {}, text = auto_fit_cell_text(cell, o), align = style && style.alignment || {};
|
|
11267
|
+
var wrap = !!align.wrapText, segments = text_width_segments(text, wrap), max = 0, w = 0;
|
|
11268
|
+
for(var i = 0; i < segments.length; ++i) {
|
|
11269
|
+
w = measure_text_width(segments[i], style, o);
|
|
11270
|
+
if(w > max) max = w;
|
|
11271
|
+
}
|
|
11272
|
+
var indent = +align.indent || 0;
|
|
11273
|
+
if(indent > 0) max += indent * 3 * Math.max(1, MDW);
|
|
11274
|
+
var rotation = +align.textRotation || 0;
|
|
11275
|
+
if(rotation == 255) rotation = 90;
|
|
11276
|
+
if(rotation > 90) rotation = 90 - rotation;
|
|
11277
|
+
if(rotation < 0) rotation = -rotation;
|
|
11278
|
+
if(rotation > 0 && rotation < 90) {
|
|
11279
|
+
var rad = rotation * Math.PI / 180, fpx = pt2px_browser(style_font_size_pt(style));
|
|
11280
|
+
max = Math.abs(max * Math.cos(rad)) + Math.abs(fpx * Math.sin(rad));
|
|
11281
|
+
} else if(rotation >= 90) max = Math.max(MDW + XLSX_COL_WIDTH_PADDING, pt2px_browser(style_font_size_pt(style)) + 2);
|
|
11282
|
+
return max + (o.padding != null ? +o.padding : XLSX_COL_WIDTH_PADDING);
|
|
11283
|
+
}
|
|
11284
|
+
function merge_start_map(merges) {
|
|
11285
|
+
var out = {};
|
|
11286
|
+
for(var i = 0; i < merges.length; ++i) out[merges[i].s.r + ":" + merges[i].s.c] = merges[i];
|
|
11287
|
+
return out;
|
|
11288
|
+
}
|
|
11289
|
+
function is_covered_merge(merges, R, C) {
|
|
11290
|
+
for(var i = 0; i < merges.length; ++i) {
|
|
11291
|
+
var m = merges[i];
|
|
11292
|
+
if(m.s.r <= R && R <= m.e.r && m.s.c <= C && C <= m.e.c) return !(m.s.r == R && m.s.c == C);
|
|
11293
|
+
}
|
|
11294
|
+
return false;
|
|
11295
|
+
}
|
|
11296
|
+
function auto_fit_columns(ws, opts) {
|
|
11297
|
+
var o = opts || {}, oldMDW = MDW;
|
|
11298
|
+
if(o.MDW) MDW = +o.MDW || MDW;
|
|
11299
|
+
var r = o.range ? (typeof o.range == "string" ? decode_range(o.range) : o.range) : decode_range(ws["!ref"] || "A1");
|
|
11300
|
+
var base = ws["!cols"] || [], rows = ws["!rows"] || [], cols = [], widths = [];
|
|
11301
|
+
var minpx = o.minPx != null ? +o.minPx : o.min != null ? width2px(char2width(+o.min)) : 0;
|
|
11302
|
+
var maxpx = o.maxPx != null ? +o.maxPx : width2px(XLSX_COL_WIDTH_MAX);
|
|
11303
|
+
var merges = o.includeMerged === false ? [] : (ws["!merges"] || []);
|
|
11304
|
+
var starts = merge_start_map(merges), dense = ws["!data"] != null;
|
|
11305
|
+
var C = 0, R = 0, span = 0, m = null, j = 0, cell = null, style = null, need = 0, have = 0;
|
|
11306
|
+
for(C = r.s.c; C <= r.e.c; ++C) {
|
|
11307
|
+
cols[C] = dup(base[C] || {});
|
|
11308
|
+
if(cols[C] && cols[C].hidden && o.skipHidden) continue;
|
|
11309
|
+
widths[C] = cols[C] && (cols[C].wpx != null || cols[C].width != null || cols[C].wch != null) ? col2px(cols[C]) : minpx;
|
|
11310
|
+
}
|
|
11311
|
+
for(R = r.s.r; R <= r.e.r; ++R) {
|
|
11312
|
+
if(rows[R] && rows[R].hidden && o.skipHidden) continue;
|
|
11313
|
+
for(C = r.s.c; C <= r.e.c; ++C) {
|
|
11314
|
+
if(cols[C] && cols[C].hidden && o.skipHidden) continue;
|
|
11315
|
+
if(is_covered_merge(merges, R, C)) continue;
|
|
11316
|
+
cell = dense ? (ws["!data"][R]||[])[C] : ws[encode_cell({r:R,c:C})];
|
|
11317
|
+
if(!cell || cell.v == null) continue;
|
|
11318
|
+
style = effective_cell_style(ws, cell, R, C);
|
|
11319
|
+
need = measure_cell_text_width(cell, style, o);
|
|
11320
|
+
if(style && style.alignment && style.alignment.shrinkToFit && widths[C]) need = Math.min(need, widths[C]);
|
|
11321
|
+
m = starts[R + ":" + C];
|
|
11322
|
+
span = m ? m.e.c - m.s.c + 1 : 1;
|
|
11323
|
+
if(span > 1) {
|
|
11324
|
+
have = 0;
|
|
11325
|
+
for(j = 0; j < span; ++j) have += widths[C+j] || minpx;
|
|
11326
|
+
if(need > have) for(j = 0; j < span; ++j) widths[C+j] = Math.min(maxpx, Math.max(widths[C+j] || minpx, (widths[C+j] || minpx) + (need - have) / span));
|
|
11327
|
+
} else widths[C] = Math.min(maxpx, Math.max(widths[C] || minpx, need));
|
|
11328
|
+
}
|
|
11329
|
+
}
|
|
11330
|
+
for(C = r.s.c; C <= r.e.c; ++C) if(widths[C] != null) cols[C] = set_col_width_from_px(cols[C] || {}, Math.min(maxpx, Math.max(minpx, widths[C])));
|
|
11331
|
+
if(o.set === false) { MDW = oldMDW; return cols; }
|
|
11332
|
+
ws["!cols"] = cols;
|
|
11333
|
+
MDW = oldMDW;
|
|
11334
|
+
return cols;
|
|
11335
|
+
}
|
|
11336
|
+
|
|
11155
11337
|
var DEF_PPI = 96, PPI = DEF_PPI;
|
|
11156
11338
|
function px2pt(px) { return px * 96 / PPI; }
|
|
11157
11339
|
function pt2px(pt) { return pt * PPI / 96; }
|
|
@@ -16208,8 +16390,11 @@ function col_obj_w(C, col) {
|
|
|
16208
16390
|
else if(col.wch != null) wch = col.wch;
|
|
16209
16391
|
if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
|
|
16210
16392
|
else if(col.width != null) p.width = col.width;
|
|
16393
|
+
if(p.width != null) p.width = clamp_col_width(p.width);
|
|
16211
16394
|
if(col.hidden) p.hidden = true;
|
|
16212
16395
|
if(col.level != null) { p.outlineLevel = p.level = col.level; }
|
|
16396
|
+
if(col.bestFit || col.bestfit) p.bestFit = true;
|
|
16397
|
+
if(col.customWidth || col.customwidth) p.customWidth = 1;
|
|
16213
16398
|
return p;
|
|
16214
16399
|
}
|
|
16215
16400
|
|
|
@@ -16567,6 +16752,8 @@ function parse_ws_xml_cols(columns, cols) {
|
|
|
16567
16752
|
for(var coli = 0; coli != cols.length; ++coli) {
|
|
16568
16753
|
var coll = parsexmltag(cols[coli], true);
|
|
16569
16754
|
if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
|
|
16755
|
+
if(coll.bestFit) coll.bestFit = parsexmlbool(coll.bestFit);
|
|
16756
|
+
if(coll.customWidth) coll.customWidth = parsexmlbool(coll.customWidth);
|
|
16570
16757
|
var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
|
|
16571
16758
|
if(coll.outlineLevel) coll.level = (+coll.outlineLevel || 0);
|
|
16572
16759
|
delete coll.min; delete coll.max; coll.width = +coll.width;
|
|
@@ -23708,8 +23895,6 @@ function html_cell_style(cell, opts) {
|
|
|
23708
23895
|
var alignment = s.alignment || {};
|
|
23709
23896
|
if(alignment.horizontal) css.push("text-align:" + alignment.horizontal);
|
|
23710
23897
|
if(alignment.vertical) css.push("vertical-align:" + alignment.vertical);
|
|
23711
|
-
if(alignment.wrapText) css.push("white-space:normal");
|
|
23712
|
-
if(alignment.shrinkToFit) css.push("font-size:smaller");
|
|
23713
23898
|
if(alignment.textRotation != null && alignment.textRotation !== 0) {
|
|
23714
23899
|
var deg = alignment.textRotation == 255 ? 90 : alignment.textRotation > 90 ? 90 - alignment.textRotation : alignment.textRotation;
|
|
23715
23900
|
css.push("transform:rotate(" + deg + "deg)");
|
|
@@ -23722,12 +23907,29 @@ function html_cell_style(cell, opts) {
|
|
|
23722
23907
|
add_html_border(css, "bottom", border.bottom);
|
|
23723
23908
|
return css.join(";");
|
|
23724
23909
|
}
|
|
23910
|
+
function html_cell_layout_style(cell, opts, C, CS, cols) {
|
|
23911
|
+
if(!opts || !cell) return "";
|
|
23912
|
+
var s = cell.s || {}, alignment = s.alignment || {}, css = [];
|
|
23913
|
+
if(opts.browserPixels || opts.autoFit) css.push("box-sizing:border-box;padding:0 2px;min-width:0");
|
|
23914
|
+
if(alignment.wrapText) css.push("white-space:pre-wrap;overflow-wrap:normal;word-break:normal");
|
|
23915
|
+
else {
|
|
23916
|
+
css.push("white-space:pre");
|
|
23917
|
+
if(alignment.shrinkToFit || opts.overflow == "clip" || opts.overflow == "hidden") css.push("overflow:hidden;text-overflow:clip");
|
|
23918
|
+
else css.push("overflow:visible");
|
|
23919
|
+
}
|
|
23920
|
+
if(alignment.shrinkToFit && cols && C != null) {
|
|
23921
|
+
var have = 0, span = CS || 1;
|
|
23922
|
+
for(var j = 0; j < span; ++j) have += html_col_width(cols[C+j]);
|
|
23923
|
+
var need = measure_cell_text_width(cell, s, opts);
|
|
23924
|
+
if(have > 0 && need > have) {
|
|
23925
|
+
var scale = Math.max(0.25, Math.min(1, have / need));
|
|
23926
|
+
css.push("font-size:" + Math.max(1, style_font_size_pt(s) * scale) + "pt");
|
|
23927
|
+
}
|
|
23928
|
+
}
|
|
23929
|
+
return css.join(";");
|
|
23930
|
+
}
|
|
23725
23931
|
function html_col_width(col) {
|
|
23726
|
-
|
|
23727
|
-
if(col.wpx != null) return col.wpx;
|
|
23728
|
-
if(col.width != null) return width2px(col.width);
|
|
23729
|
-
if(col.wch != null) return width2px(char2width(col.wch));
|
|
23730
|
-
return 64;
|
|
23932
|
+
return col2px(col);
|
|
23731
23933
|
}
|
|
23732
23934
|
function html_row_height(row) {
|
|
23733
23935
|
if(!row) return 20;
|
|
@@ -23742,7 +23944,7 @@ function make_html_row(ws, r, R, o) {
|
|
|
23742
23944
|
var sp = ({});
|
|
23743
23945
|
var dense = ws["!data"] != null;
|
|
23744
23946
|
var row = (ws["!rows"]||[])[R];
|
|
23745
|
-
var cols = ws["!cols"] || [];
|
|
23947
|
+
var cols = o && o._htmlCols || ws["!cols"] || [];
|
|
23746
23948
|
for(var C = r.s.c; C <= r.e.c; ++C) {
|
|
23747
23949
|
var RS = 0, CS = 0;
|
|
23748
23950
|
for(var j = 0; j < M.length; ++j) {
|
|
@@ -23785,6 +23987,8 @@ function make_html_row(ws, r, R, o) {
|
|
|
23785
23987
|
if(cell.l && (cell.l.Target || "#").charAt(0) != "#" && (!o.sanitizeLinks || (cell.l.Target || "").slice(0, 11).toLowerCase() != 'javascript:')) w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
|
23786
23988
|
}
|
|
23787
23989
|
var cstyle = html_cell_style(stylecell, o);
|
|
23990
|
+
var lstyle = html_cell_layout_style(stylecell, o, C, CS, cols);
|
|
23991
|
+
if(lstyle) cstyle = cstyle ? cstyle + ";" + lstyle : lstyle;
|
|
23788
23992
|
if(cstyle) sp.style = cstyle;
|
|
23789
23993
|
sp.id = (o.id || "sjs") + "-" + coord;
|
|
23790
23994
|
oo.push(writextag('td', w, sp));
|
|
@@ -23816,9 +24020,9 @@ function html_to_workbook(str, opts) {
|
|
|
23816
24020
|
}
|
|
23817
24021
|
|
|
23818
24022
|
var HTML_EMU_PER_PIXEL = 9525;
|
|
23819
|
-
function html_anchor_pos(ws, anchor) {
|
|
24023
|
+
function html_anchor_pos(ws, anchor, opts) {
|
|
23820
24024
|
var out = {left:0, top:0, width:480, height:288};
|
|
23821
|
-
var cols = ws["!cols"] || [], rows = ws["!rows"] || [];
|
|
24025
|
+
var cols = opts && opts._htmlCols || ws["!cols"] || [], rows = ws["!rows"] || [];
|
|
23822
24026
|
var from = anchor && anchor.from || {col:0,row:0,colOff:0,rowOff:0};
|
|
23823
24027
|
var to = anchor && anchor.to;
|
|
23824
24028
|
for(var C = 0; C < (from.col||0); ++C) out.left += html_col_width(cols[C]);
|
|
@@ -23931,11 +24135,11 @@ function render_html_drawings(ws, opts) {
|
|
|
23931
24135
|
var out = [], drawings = ws["!drawings"] || {}, charts = ws["!charts"] || [];
|
|
23932
24136
|
if(opts && opts.drawings && drawings.images) drawings.images.forEach(function(img) {
|
|
23933
24137
|
if(!img || !img.dataURI) return;
|
|
23934
|
-
var pos = html_anchor_pos(ws, img.anchor);
|
|
24138
|
+
var pos = html_anchor_pos(ws, img.anchor, opts);
|
|
23935
24139
|
out.push('<img class="sjs-drawing-image" src="' + img.dataURI + '" style="' + html_abs_style(pos) + '"/>');
|
|
23936
24140
|
});
|
|
23937
24141
|
if(opts && opts.charts) charts.forEach(function(chart) {
|
|
23938
|
-
var pos = html_anchor_pos(ws, chart.anchor);
|
|
24142
|
+
var pos = html_anchor_pos(ws, chart.anchor, opts);
|
|
23939
24143
|
out.push('<div class="sjs-chart" style="' + html_abs_style(pos) + '">' + render_chart_svg(chart, pos.width, pos.height) + '</div>');
|
|
23940
24144
|
});
|
|
23941
24145
|
if(!out.length) return "";
|
|
@@ -23943,11 +24147,16 @@ function render_html_drawings(ws, opts) {
|
|
|
23943
24147
|
}
|
|
23944
24148
|
function make_html_preamble(ws, R, o) {
|
|
23945
24149
|
var out = [];
|
|
23946
|
-
var
|
|
23947
|
-
if(o && o.
|
|
24150
|
+
var tattr = ({}), tstyle = [];
|
|
24151
|
+
if(o && o.id) tattr.id = o.id;
|
|
24152
|
+
if(o && (o.browserPixels || o.autoFit)) tstyle.push("border-collapse:collapse;table-layout:fixed");
|
|
24153
|
+
if(tstyle.length) tattr.style = tstyle.join(";");
|
|
24154
|
+
var table = writextag("table", "", tattr).replace(/<\/table>$/, "");
|
|
24155
|
+
var cols = o && o._htmlCols || ws["!cols"];
|
|
24156
|
+
if(o && (o.browserPixels || o.autoFit) && cols) {
|
|
23948
24157
|
out.push("<colgroup>");
|
|
23949
24158
|
for(var C = R.s.c; C <= R.e.c; ++C) {
|
|
23950
|
-
var col =
|
|
24159
|
+
var col = cols[C], style = [];
|
|
23951
24160
|
style.push("width:" + html_col_width(col) + "px");
|
|
23952
24161
|
if(col && col.hidden) style.push("display:none");
|
|
23953
24162
|
out.push(writextag("col", null, {style:style.join(";")}));
|
|
@@ -23958,7 +24167,16 @@ function make_html_preamble(ws, R, o) {
|
|
|
23958
24167
|
}
|
|
23959
24168
|
|
|
23960
24169
|
function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
|
|
23961
|
-
var o =
|
|
24170
|
+
var o = {};
|
|
24171
|
+
if(opts) for(var k in opts) if(Object.prototype.hasOwnProperty.call(opts, k)) o[k] = opts[k];
|
|
24172
|
+
if(o.autoFit) {
|
|
24173
|
+
var af = {set:false};
|
|
24174
|
+
if(typeof o.autoFit == "object") for(k in o.autoFit) if(Object.prototype.hasOwnProperty.call(o.autoFit, k)) af[k] = o.autoFit[k];
|
|
24175
|
+
if(o.measureText && af.measureText == null) af.measureText = o.measureText;
|
|
24176
|
+
if(o.canvas && af.canvas == null) af.canvas = o.canvas;
|
|
24177
|
+
o._htmlCols = auto_fit_columns(ws, af);
|
|
24178
|
+
if(o.browserPixels == null) o.browserPixels = true;
|
|
24179
|
+
}
|
|
23962
24180
|
var header = o.header != null ? o.header : HTML_BEGIN;
|
|
23963
24181
|
var footer = o.footer != null ? o.footer : HTML_END;
|
|
23964
24182
|
var out = [header];
|
|
@@ -29186,6 +29404,9 @@ var utils = {
|
|
|
29186
29404
|
sheet_to_formulae: sheet_to_formulae,
|
|
29187
29405
|
sheet_to_row_object_array: sheet_to_json,
|
|
29188
29406
|
validate_merges: validate_merges,
|
|
29407
|
+
measure_text_width: measure_text_width,
|
|
29408
|
+
auto_fit_columns: auto_fit_columns,
|
|
29409
|
+
autofit_columns: auto_fit_columns,
|
|
29189
29410
|
col_width_to_px: width2px,
|
|
29190
29411
|
px_to_col_width: function(px) { return char2width(px2char(px)); },
|
|
29191
29412
|
row_height_to_px: pt2px_browser,
|