Skip to content

Commit 8973874

Browse files
committed
Improve cell autofit calculation
1 parent 4cb1e52 commit 8973874

File tree

2 files changed

+112
-11
lines changed

2 files changed

+112
-11
lines changed

source/json-to-excel.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ const ALIGNMENT_STYLE: Partial<Excel.Alignment> = {
1212
wrapText: true
1313
};
1414

15+
const FONT_STYLE: Partial<Excel.Font> = {
16+
name: 'Calibri',
17+
size: 11
18+
};
19+
1520
export async function jsonToExcel(jsonSheets: ExpandedJsonSheet[], path: string, options: ExpandedJsonToExcelOptions): Promise<void> {
1621
if (jsonSheets.length === 0) {
1722
throw new TypeError('Expected non-empty list of json sheets, got empty list');
@@ -59,8 +64,10 @@ export async function jsonToExcel(jsonSheets: ExpandedJsonSheet[], path: string,
5964
for (let ri = 0; ri < rowCount; ri++) {
6065
for (let ci = 0; ci < columnCount; ci++) {
6166
assertValidCellContent(data[ri][ci], options.linefeedLimitChecking);
62-
sheet.getCell(ri + 1, ci + 1).value = data[ri][ci];
63-
sheet.getCell(ri + 1, ci + 1).alignment = ALIGNMENT_STYLE;
67+
const cell = sheet.getCell(ri + 1, ci + 1);
68+
cell.value = data[ri][ci];
69+
cell.alignment = ALIGNMENT_STYLE;
70+
cell.font = FONT_STYLE;
6471
}
6572
}
6673

source/visual-string-width.ts

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,110 @@
11
import { getMax } from './numeric-helpers';
22
import assert = require('assert');
33

4-
const MAX_CHAR_VISUAL_WIDTH = 1.75;
4+
// Calculations in this file assume 'Calibri 11'
5+
6+
/* eslint-disable quote-props */
7+
const CHAR_WIDTHS_IN_PX: { [key: string]: number } = {
8+
// 'a': 1, // 1 is the default and can be omitted
9+
'b': 8 / 7,
10+
'c': 6 / 7,
11+
'd': 8 / 7,
12+
'e': 8 / 7,
13+
'f': 5 / 7,
14+
// 'g': 1, // 1 is the default and can be omitted
15+
'h': 8 / 7,
16+
'i': 4 / 7,
17+
'j': 4 / 7,
18+
// 'k': 1, // 1 is the default and can be omitted
19+
'l': 4 / 7,
20+
'm': 12 / 7,
21+
'n': 8 / 7,
22+
'o': 8 / 7,
23+
'p': 8 / 7,
24+
'q': 8 / 7,
25+
'r': 5 / 7,
26+
's': 6 / 7,
27+
't': 5 / 7,
28+
'u': 8 / 7,
29+
// 'v': 1, // 1 is the default and can be omitted
30+
'w': 11 / 7,
31+
// 'x': 1, // 1 is the default and can be omitted
32+
// 'y': 1, // 1 is the default and can be omitted
33+
'z': 6 / 7,
34+
'A': 9 / 7,
35+
'B': 8 / 7,
36+
'C': 8 / 7,
37+
'D': 9 / 7,
38+
// 'E': 1, // 1 is the default and can be omitted
39+
// 'F': 1, // 1 is the default and can be omitted
40+
'G': 9 / 7,
41+
'H': 9 / 7,
42+
'I': 4 / 7,
43+
'J': 5 / 7,
44+
'K': 8 / 7,
45+
'L': 6 / 7,
46+
'M': 12 / 7,
47+
'N': 10 / 7,
48+
'O': 10 / 7,
49+
'P': 8 / 7,
50+
'Q': 10 / 7,
51+
'R': 8 / 7,
52+
// 'S': 1, // 1 is the default and can be omitted
53+
// 'T': 1, // 1 is the default and can be omitted
54+
'U': 9 / 7,
55+
'V': 9 / 7,
56+
'W': 13 / 7,
57+
'X': 8 / 7,
58+
// 'Y': 1, // 1 is the default and can be omitted
59+
// 'Z': 1, // 1 is the default and can be omitted
60+
// '0': 1, // 1 is the default and can be omitted
61+
// '1': 1, // 1 is the default and can be omitted
62+
// '2': 1, // 1 is the default and can be omitted
63+
// '3': 1, // 1 is the default and can be omitted
64+
// '4': 1, // 1 is the default and can be omitted
65+
// '5': 1, // 1 is the default and can be omitted
66+
// '6': 1, // 1 is the default and can be omitted
67+
// '7': 1, // 1 is the default and can be omitted
68+
// '8': 1, // 1 is the default and can be omitted
69+
// '9': 1, // 1 is the default and can be omitted
70+
// '_': 1, // 1 is the default and can be omitted
71+
'-': 5 / 7,
72+
' ': 3 / 7,
73+
'\'': 3 / 7,
74+
'"': 6 / 7,
75+
'!': 5 / 7,
76+
'@': 13 / 7,
77+
// '#': 1, // 1 is the default and can be omitted
78+
// '$': 1, // 1 is the default and can be omitted
79+
'%': 11 / 7,
80+
'&': 10 / 7,
81+
// '*': 1, // 1 is the default and can be omitted
82+
'(': 5 / 7,
83+
')': 5 / 7,
84+
// '+': 1, // 1 is the default and can be omitted
85+
// '=': 1, // 1 is the default and can be omitted
86+
'{': 5 / 7,
87+
'}': 5 / 7,
88+
'[': 5 / 7,
89+
']': 5 / 7,
90+
// '|': 1, // 1 is the default and can be omitted
91+
'/': 6 / 7,
92+
'\\': 6 / 7,
93+
'.': 4 / 7,
94+
',': 4 / 7,
95+
';': 4 / 7,
96+
':': 4 / 7
97+
};
98+
/* eslint-enable quote-props */
99+
100+
const MAX_CHAR_VISUAL_WIDTH = Math.max(...Object.values(CHAR_WIDTHS_IN_PX));
5101

6102
function getCharVisualWidth(char: string): number {
7-
const specials: { [key: string]: number } = {
8-
' ': 0.4,
9-
f: 0.7,
10-
m: 1.75
11-
};
12-
const half = ['i', 'j', 'l', '\'', '!'];
13-
return specials[char] ?? (half.includes(char) ? 0.5 : 1);
103+
return CHAR_WIDTHS_IN_PX[char] ?? 1;
104+
}
105+
106+
function roundCents(number: number): number {
107+
return Number.parseFloat(number.toFixed(2));
14108
}
15109

16110
export function getLineVisualWidth(line: string): number {
@@ -22,7 +116,7 @@ export function getLineVisualWidth(line: string): number {
22116
width += getCharVisualWidth(char);
23117
}
24118

25-
return width;
119+
return roundCents(width);
26120
}
27121

28122
export function getStringVisualWidth(string: string): number {

0 commit comments

Comments
 (0)