@a3s-lab/office 0.13.0 → 0.14.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/README.md +40 -5
- package/dist/0~6090.js +63 -4
- package/dist/0~7048.js +14 -4
- package/dist/0~spreadsheet-editor.js +13936 -9125
- package/dist/4104.js +1094 -18
- package/dist/internal/features/work/editors/office-checkbox.d.ts +3 -2
- package/dist/internal/features/work/editors/office-menu-keyboard.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-auto-sum-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-auto-sum.d.ts +19 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border-per-cell.d.ts +5 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border.d.ts +15 -1
- package/dist/internal/features/work/editors/spreadsheet-cell-format-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-format.d.ts +36 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-mutation-guard.d.ts +4 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-style-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-style-ribbon.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-style.d.ts +41 -0
- package/dist/internal/features/work/editors/spreadsheet-clipboard-shortcuts.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-clipboard.d.ts +13 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +253 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +40 -0
- package/dist/internal/features/work/editors/spreadsheet-context-menu.d.ts +5 -15
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +3 -2
- package/dist/internal/features/work/editors/spreadsheet-format-cells-dialog-model.d.ts +86 -0
- package/dist/internal/features/work/editors/spreadsheet-format-cells-dialog-panels.d.ts +15 -0
- package/dist/internal/features/work/editors/spreadsheet-format-cells-dialog.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-go-to.d.ts +24 -0
- package/dist/internal/features/work/editors/spreadsheet-keyboard-navigation.d.ts +4 -0
- package/dist/internal/features/work/editors/spreadsheet-navigation-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-number-format-command.d.ts +24 -0
- package/dist/internal/features/work/editors/spreadsheet-number-format.d.ts +15 -3
- package/dist/internal/features/work/editors/spreadsheet-paste-special-cell.d.ts +17 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special-dialog.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special-mode.d.ts +11 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special-plan.d.ts +4 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special-sheet.d.ts +23 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special-snapshot.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special-types.d.ts +127 -0
- package/dist/internal/features/work/editors/spreadsheet-paste-special.d.ts +7 -0
- package/dist/internal/features/work/editors/use-spreadsheet-clipboard.d.ts +36 -0
- package/dist/internal/features/work/work-xlsx-cell-borders.d.ts +25 -0
- package/dist/internal/features/work/work-xlsx-cell-style-writer.d.ts +21 -0
- package/dist/internal/features/work/work-xlsx-cell-style-xml.d.ts +17 -0
- package/dist/internal/features/work/work-xlsx-cell-styles.d.ts +13 -0
- package/dist/internal/features/work/work-xlsx-colors.d.ts +6 -0
- package/dist/internal/features/work/work-xlsx-interop.d.ts +3 -1
- package/dist/internal/features/work/work-xlsx-worksheet-scan.d.ts +1 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +665 -1
- package/dist/work-spreadsheet-package-scan.worker.js +7 -3
- package/docs/latest/en/browser-editor-architecture.md +12 -1
- package/package.json +11 -3
package/dist/4104.js
CHANGED
|
@@ -3061,6 +3061,1006 @@ function work_xlsx_images_partNumber(path) {
|
|
|
3061
3061
|
function work_xlsx_images_escapeXml(value) {
|
|
3062
3062
|
return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", ''');
|
|
3063
3063
|
}
|
|
3064
|
+
const xlsxStyleByFortuneStyle = {
|
|
3065
|
+
1: 'thin',
|
|
3066
|
+
2: 'hair',
|
|
3067
|
+
3: 'dotted',
|
|
3068
|
+
4: 'dashed',
|
|
3069
|
+
5: 'dashDot',
|
|
3070
|
+
6: 'dashDotDot',
|
|
3071
|
+
7: 'double',
|
|
3072
|
+
8: 'medium',
|
|
3073
|
+
9: 'mediumDashed',
|
|
3074
|
+
10: 'mediumDashDot',
|
|
3075
|
+
11: 'mediumDashDotDot',
|
|
3076
|
+
12: 'slantDashDot',
|
|
3077
|
+
13: 'thick'
|
|
3078
|
+
};
|
|
3079
|
+
const fortuneStyleByXlsxStyle = new Map(Object.entries(xlsxStyleByFortuneStyle).map(([fortune, xlsx])=>[
|
|
3080
|
+
xlsx,
|
|
3081
|
+
fortune
|
|
3082
|
+
]));
|
|
3083
|
+
function collectXlsxCellBorders(sheet) {
|
|
3084
|
+
const targets = spreadsheetBorderTargets(sheet);
|
|
3085
|
+
const borders = new Map();
|
|
3086
|
+
const source = Array.isArray(sheet.config?.borderInfo) ? sheet.config.borderInfo : [];
|
|
3087
|
+
for (const candidate of source){
|
|
3088
|
+
if (!work_xlsx_cell_borders_isRecord(candidate)) continue;
|
|
3089
|
+
if ('cell' === candidate.rangeType) {
|
|
3090
|
+
applySpreadsheetCellBorderRecord(candidate, targets, borders);
|
|
3091
|
+
continue;
|
|
3092
|
+
}
|
|
3093
|
+
if ('range' !== candidate.rangeType || 'string' != typeof candidate.borderType || !Array.isArray(candidate.range)) continue;
|
|
3094
|
+
const line = spreadsheetBorderLine(candidate);
|
|
3095
|
+
for (const rangeCandidate of candidate.range){
|
|
3096
|
+
const range = spreadsheetBorderRange(rangeCandidate);
|
|
3097
|
+
if (range) {
|
|
3098
|
+
for (const target of targets.values())if (spreadsheetBorderRangeContains(range, target)) applySpreadsheetRangeBorder(borders, target, range, candidate.borderType, line);
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
return borders;
|
|
3103
|
+
}
|
|
3104
|
+
function fortuneBorderInfoFromXlsxCells(entries) {
|
|
3105
|
+
return entries.flatMap(({ border, column, row })=>{
|
|
3106
|
+
if (!border) return [];
|
|
3107
|
+
const value = {
|
|
3108
|
+
col_index: column,
|
|
3109
|
+
row_index: row
|
|
3110
|
+
};
|
|
3111
|
+
setFortuneBorderLine(value, 'l', border.left);
|
|
3112
|
+
setFortuneBorderLine(value, 'r', border.right);
|
|
3113
|
+
setFortuneBorderLine(value, 't', border.top);
|
|
3114
|
+
setFortuneBorderLine(value, 'b', border.bottom);
|
|
3115
|
+
if (border.diagonal) setFortuneBorderLine(value, 's', border.diagonal);
|
|
3116
|
+
return Object.keys(value).length > 2 ? [
|
|
3117
|
+
{
|
|
3118
|
+
rangeType: 'cell',
|
|
3119
|
+
value
|
|
3120
|
+
}
|
|
3121
|
+
] : [];
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
3124
|
+
function xlsxCellBorderKey(row, column) {
|
|
3125
|
+
return `${row}_${column}`;
|
|
3126
|
+
}
|
|
3127
|
+
function xlsxCellBorderLineFromFortune(value) {
|
|
3128
|
+
if (null === value) return null;
|
|
3129
|
+
if (!work_xlsx_cell_borders_isRecord(value)) return;
|
|
3130
|
+
const style = xlsxStyleByFortuneStyle[String(value.style ?? '')];
|
|
3131
|
+
const color = normalizeRgbColor(value.color);
|
|
3132
|
+
return style && color ? {
|
|
3133
|
+
color,
|
|
3134
|
+
style
|
|
3135
|
+
} : void 0;
|
|
3136
|
+
}
|
|
3137
|
+
function fortuneBorderStyle(style) {
|
|
3138
|
+
return fortuneStyleByXlsxStyle.get(style) ?? '1';
|
|
3139
|
+
}
|
|
3140
|
+
function spreadsheetBorderTargets(sheet) {
|
|
3141
|
+
const targets = new Map();
|
|
3142
|
+
for (const [row, values] of sparseArrayEntries(sheet.data))for (const [column, cell] of sparseArrayEntries(values))if (cell) targets.set(xlsxCellBorderKey(row, column), {
|
|
3143
|
+
column,
|
|
3144
|
+
row
|
|
3145
|
+
});
|
|
3146
|
+
for (const candidate of Array.isArray(sheet.config?.borderInfo) ? sheet.config.borderInfo : []){
|
|
3147
|
+
if (!work_xlsx_cell_borders_isRecord(candidate) || 'cell' !== candidate.rangeType) continue;
|
|
3148
|
+
const value = candidate.value;
|
|
3149
|
+
if (!work_xlsx_cell_borders_isRecord(value)) continue;
|
|
3150
|
+
const row = nonNegativeInteger(value.row_index);
|
|
3151
|
+
const column = nonNegativeInteger(value.col_index);
|
|
3152
|
+
if (null !== row && null !== column) targets.set(xlsxCellBorderKey(row, column), {
|
|
3153
|
+
column,
|
|
3154
|
+
row
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
3157
|
+
return targets;
|
|
3158
|
+
}
|
|
3159
|
+
function applySpreadsheetCellBorderRecord(record, targets, borders) {
|
|
3160
|
+
if (!work_xlsx_cell_borders_isRecord(record.value)) return;
|
|
3161
|
+
const row = nonNegativeInteger(record.value.row_index);
|
|
3162
|
+
const column = nonNegativeInteger(record.value.col_index);
|
|
3163
|
+
if (null === row || null === column) return;
|
|
3164
|
+
const key = xlsxCellBorderKey(row, column);
|
|
3165
|
+
if (!targets.has(key)) return;
|
|
3166
|
+
const border = {
|
|
3167
|
+
...borders.get(key) ?? {}
|
|
3168
|
+
};
|
|
3169
|
+
applyCellLine(border, 'left', record.value.l);
|
|
3170
|
+
applyCellLine(border, 'right', record.value.r);
|
|
3171
|
+
applyCellLine(border, 'top', record.value.t);
|
|
3172
|
+
applyCellLine(border, 'bottom', record.value.b);
|
|
3173
|
+
const diagonal = xlsxCellBorderLineFromFortune(record.value.s);
|
|
3174
|
+
if (void 0 !== diagonal) {
|
|
3175
|
+
border.diagonal = diagonal;
|
|
3176
|
+
border.diagonalUp = null !== diagonal;
|
|
3177
|
+
border.diagonalDown = false;
|
|
3178
|
+
}
|
|
3179
|
+
borders.set(key, border);
|
|
3180
|
+
}
|
|
3181
|
+
function applyCellLine(border, side, value) {
|
|
3182
|
+
const line = xlsxCellBorderLineFromFortune(value);
|
|
3183
|
+
if (void 0 !== line) border[side] = line;
|
|
3184
|
+
}
|
|
3185
|
+
function applySpreadsheetRangeBorder(borders, target, range, borderType, line) {
|
|
3186
|
+
const key = xlsxCellBorderKey(target.row, target.column);
|
|
3187
|
+
const border = {
|
|
3188
|
+
...borders.get(key) ?? {}
|
|
3189
|
+
};
|
|
3190
|
+
const onTop = target.row === range.row[0];
|
|
3191
|
+
const onBottom = target.row === range.row[1];
|
|
3192
|
+
const onLeft = target.column === range.column[0];
|
|
3193
|
+
const onRight = target.column === range.column[1];
|
|
3194
|
+
switch(borderType){
|
|
3195
|
+
case 'border-top':
|
|
3196
|
+
if (onTop) border.top = line;
|
|
3197
|
+
break;
|
|
3198
|
+
case 'border-bottom':
|
|
3199
|
+
if (onBottom) border.bottom = line;
|
|
3200
|
+
break;
|
|
3201
|
+
case 'border-left':
|
|
3202
|
+
if (onLeft) border.left = line;
|
|
3203
|
+
break;
|
|
3204
|
+
case 'border-right':
|
|
3205
|
+
if (onRight) border.right = line;
|
|
3206
|
+
break;
|
|
3207
|
+
case 'border-none':
|
|
3208
|
+
border.top = null;
|
|
3209
|
+
border.bottom = null;
|
|
3210
|
+
border.left = null;
|
|
3211
|
+
border.right = null;
|
|
3212
|
+
border.diagonal = null;
|
|
3213
|
+
border.diagonalUp = false;
|
|
3214
|
+
border.diagonalDown = false;
|
|
3215
|
+
break;
|
|
3216
|
+
case 'border-all':
|
|
3217
|
+
border.top = line;
|
|
3218
|
+
border.bottom = line;
|
|
3219
|
+
border.left = line;
|
|
3220
|
+
border.right = line;
|
|
3221
|
+
break;
|
|
3222
|
+
case 'border-outside':
|
|
3223
|
+
if (onTop) border.top = line;
|
|
3224
|
+
if (onBottom) border.bottom = line;
|
|
3225
|
+
if (onLeft) border.left = line;
|
|
3226
|
+
if (onRight) border.right = line;
|
|
3227
|
+
break;
|
|
3228
|
+
case 'border-inside':
|
|
3229
|
+
if (!onTop) border.top = line;
|
|
3230
|
+
if (!onBottom) border.bottom = line;
|
|
3231
|
+
if (!onLeft) border.left = line;
|
|
3232
|
+
if (!onRight) border.right = line;
|
|
3233
|
+
break;
|
|
3234
|
+
case 'border-horizontal':
|
|
3235
|
+
if (!onTop) border.top = line;
|
|
3236
|
+
if (!onBottom) border.bottom = line;
|
|
3237
|
+
break;
|
|
3238
|
+
case 'border-vertical':
|
|
3239
|
+
if (!onLeft) border.left = line;
|
|
3240
|
+
if (!onRight) border.right = line;
|
|
3241
|
+
break;
|
|
3242
|
+
case 'border-slash':
|
|
3243
|
+
border.diagonal = line;
|
|
3244
|
+
border.diagonalUp = null !== line;
|
|
3245
|
+
border.diagonalDown = false;
|
|
3246
|
+
break;
|
|
3247
|
+
default:
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
3250
|
+
borders.set(key, border);
|
|
3251
|
+
}
|
|
3252
|
+
function spreadsheetBorderLine(record) {
|
|
3253
|
+
const style = xlsxStyleByFortuneStyle[String(record.style ?? '')];
|
|
3254
|
+
const color = normalizeRgbColor(record.color);
|
|
3255
|
+
return style && color ? {
|
|
3256
|
+
color,
|
|
3257
|
+
style
|
|
3258
|
+
} : null;
|
|
3259
|
+
}
|
|
3260
|
+
function spreadsheetBorderRange(value) {
|
|
3261
|
+
if (!work_xlsx_cell_borders_isRecord(value)) return null;
|
|
3262
|
+
const row = spreadsheetBorderAxis(value.row);
|
|
3263
|
+
const column = spreadsheetBorderAxis(value.column);
|
|
3264
|
+
return row && column ? {
|
|
3265
|
+
column,
|
|
3266
|
+
row
|
|
3267
|
+
} : null;
|
|
3268
|
+
}
|
|
3269
|
+
function spreadsheetBorderAxis(value) {
|
|
3270
|
+
if (!Array.isArray(value) || 2 !== value.length) return null;
|
|
3271
|
+
const start = nonNegativeInteger(value[0]);
|
|
3272
|
+
const end = nonNegativeInteger(value[1]);
|
|
3273
|
+
return null !== start && null !== end && start <= end ? [
|
|
3274
|
+
start,
|
|
3275
|
+
end
|
|
3276
|
+
] : null;
|
|
3277
|
+
}
|
|
3278
|
+
function spreadsheetBorderRangeContains(range, target) {
|
|
3279
|
+
return target.row >= range.row[0] && target.row <= range.row[1] && target.column >= range.column[0] && target.column <= range.column[1];
|
|
3280
|
+
}
|
|
3281
|
+
function setFortuneBorderLine(target, name, line) {
|
|
3282
|
+
if (!line) return;
|
|
3283
|
+
target[name] = {
|
|
3284
|
+
color: normalizeRgbColor(line.color) ?? '#000000',
|
|
3285
|
+
style: fortuneBorderStyle(line.style)
|
|
3286
|
+
};
|
|
3287
|
+
}
|
|
3288
|
+
function normalizeRgbColor(value) {
|
|
3289
|
+
if ('string' != typeof value) return null;
|
|
3290
|
+
const color = value.trim().toLowerCase();
|
|
3291
|
+
if (/^#[0-9a-f]{6}$/.test(color)) return color;
|
|
3292
|
+
if (!/^#[0-9a-f]{3}$/.test(color)) return null;
|
|
3293
|
+
return `#${[
|
|
3294
|
+
...color.slice(1)
|
|
3295
|
+
].map((character)=>character.repeat(2)).join('')}`;
|
|
3296
|
+
}
|
|
3297
|
+
function nonNegativeInteger(value) {
|
|
3298
|
+
return 'number' == typeof value && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
3299
|
+
}
|
|
3300
|
+
function work_xlsx_cell_borders_isRecord(value) {
|
|
3301
|
+
return 'object' == typeof value && null !== value && !Array.isArray(value);
|
|
3302
|
+
}
|
|
3303
|
+
const borderChildOrder = [
|
|
3304
|
+
'start',
|
|
3305
|
+
'end',
|
|
3306
|
+
'left',
|
|
3307
|
+
'right',
|
|
3308
|
+
'top',
|
|
3309
|
+
'bottom',
|
|
3310
|
+
'diagonal',
|
|
3311
|
+
'vertical',
|
|
3312
|
+
'horizontal',
|
|
3313
|
+
'extLst'
|
|
3314
|
+
];
|
|
3315
|
+
function ensureXlsxStyleCollection(document1, name, anchors) {
|
|
3316
|
+
const root = document1.documentElement;
|
|
3317
|
+
const existing = directChild(root, name);
|
|
3318
|
+
if (existing) return existing;
|
|
3319
|
+
const collection = document1.createElementNS(root.namespaceURI, name);
|
|
3320
|
+
root.insertBefore(collection, directChildren(root).find((child)=>anchors.includes(child.localName)) ?? null);
|
|
3321
|
+
return collection;
|
|
3322
|
+
}
|
|
3323
|
+
function defaultXlsxFill(document1, patternType) {
|
|
3324
|
+
const fill = document1.createElementNS(document1.documentElement.namespaceURI, 'fill');
|
|
3325
|
+
const pattern = document1.createElementNS(document1.documentElement.namespaceURI, 'patternFill');
|
|
3326
|
+
pattern.setAttribute('patternType', patternType);
|
|
3327
|
+
fill.append(pattern);
|
|
3328
|
+
return fill;
|
|
3329
|
+
}
|
|
3330
|
+
function defaultXlsxBorder(document1) {
|
|
3331
|
+
const border = document1.createElementNS(document1.documentElement.namespaceURI, 'border');
|
|
3332
|
+
for (const name of [
|
|
3333
|
+
'left',
|
|
3334
|
+
'right',
|
|
3335
|
+
'top',
|
|
3336
|
+
'bottom',
|
|
3337
|
+
'diagonal'
|
|
3338
|
+
])border.append(document1.createElementNS(document1.documentElement.namespaceURI, name));
|
|
3339
|
+
return border;
|
|
3340
|
+
}
|
|
3341
|
+
function setXlsxBorderLine(document1, border, name, line) {
|
|
3342
|
+
removeXlsxChildren(border, name);
|
|
3343
|
+
const element = document1.createElementNS(document1.documentElement.namespaceURI, name);
|
|
3344
|
+
if (line) {
|
|
3345
|
+
element.setAttribute('style', line.style);
|
|
3346
|
+
const color = xlsxRgbColor(line.color);
|
|
3347
|
+
if (color) {
|
|
3348
|
+
const child = document1.createElementNS(document1.documentElement.namespaceURI, 'color');
|
|
3349
|
+
child.setAttribute('rgb', color);
|
|
3350
|
+
element.append(child);
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
insertXlsxOrderedChild(border, element, borderChildOrder);
|
|
3354
|
+
}
|
|
3355
|
+
function writeXlsxAlignment(document1, xf, style) {
|
|
3356
|
+
let alignment = directChild(xf, 'alignment');
|
|
3357
|
+
if (!alignment) {
|
|
3358
|
+
alignment = document1.createElementNS(document1.documentElement.namespaceURI, 'alignment');
|
|
3359
|
+
xf.insertBefore(alignment, directChildren(xf).find((child)=>[
|
|
3360
|
+
'protection',
|
|
3361
|
+
'extLst'
|
|
3362
|
+
].includes(child.localName)) ?? null);
|
|
3363
|
+
}
|
|
3364
|
+
if (void 0 !== style.horizontal) alignment.setAttribute('horizontal', style.horizontal);
|
|
3365
|
+
if (void 0 !== style.vertical) alignment.setAttribute('vertical', style.vertical);
|
|
3366
|
+
if (void 0 !== style.wrapText) alignment.setAttribute('wrapText', style.wrapText ? '1' : '0');
|
|
3367
|
+
if (void 0 !== style.textRotation) alignment.setAttribute('textRotation', String(style.textRotation));
|
|
3368
|
+
}
|
|
3369
|
+
function setXlsxValueChild(document1, parent, name, value, order) {
|
|
3370
|
+
removeXlsxChildren(parent, name);
|
|
3371
|
+
const child = document1.createElementNS(document1.documentElement.namespaceURI, name);
|
|
3372
|
+
child.setAttribute('val', value);
|
|
3373
|
+
insertXlsxOrderedChild(parent, child, order);
|
|
3374
|
+
}
|
|
3375
|
+
function setXlsxColorChild(document1, parent, color, order) {
|
|
3376
|
+
removeXlsxChildren(parent, 'color');
|
|
3377
|
+
const child = document1.createElementNS(document1.documentElement.namespaceURI, 'color');
|
|
3378
|
+
child.setAttribute('rgb', color);
|
|
3379
|
+
insertXlsxOrderedChild(parent, child, order);
|
|
3380
|
+
}
|
|
3381
|
+
function setXlsxToggleChild(document1, parent, name, enabled, order) {
|
|
3382
|
+
removeXlsxChildren(parent, name);
|
|
3383
|
+
if (!enabled) return;
|
|
3384
|
+
const child = document1.createElementNS(document1.documentElement.namespaceURI, name);
|
|
3385
|
+
child.setAttribute('val', '1');
|
|
3386
|
+
insertXlsxOrderedChild(parent, child, order);
|
|
3387
|
+
}
|
|
3388
|
+
function setXlsxUnderlineChild(document1, parent, enabled, order) {
|
|
3389
|
+
removeXlsxChildren(parent, 'u');
|
|
3390
|
+
if (!enabled) return;
|
|
3391
|
+
const child = document1.createElementNS(document1.documentElement.namespaceURI, 'u');
|
|
3392
|
+
child.setAttribute('val', 'single');
|
|
3393
|
+
insertXlsxOrderedChild(parent, child, order);
|
|
3394
|
+
}
|
|
3395
|
+
function xlsxRgbColor(value) {
|
|
3396
|
+
if ('string' != typeof value) return null;
|
|
3397
|
+
const color = value.trim().replace('#', '').toUpperCase();
|
|
3398
|
+
if (/^[0-9A-F]{6}$/.test(color)) return `FF${color}`;
|
|
3399
|
+
if (/^[0-9A-F]{8}$/.test(color)) return color;
|
|
3400
|
+
if (/^[0-9A-F]{3}$/.test(color)) return `FF${[
|
|
3401
|
+
...color
|
|
3402
|
+
].map((character)=>character.repeat(2)).join('')}`;
|
|
3403
|
+
return null;
|
|
3404
|
+
}
|
|
3405
|
+
function removeXlsxChildren(parent, name) {
|
|
3406
|
+
for (const child of directChildren(parent, name))child.remove();
|
|
3407
|
+
}
|
|
3408
|
+
function insertXlsxOrderedChild(parent, child, order) {
|
|
3409
|
+
const requested = order.indexOf(child.localName);
|
|
3410
|
+
const anchor = directChildren(parent).find((candidate)=>order.indexOf(candidate.localName) > requested);
|
|
3411
|
+
parent.insertBefore(child, anchor ?? null);
|
|
3412
|
+
}
|
|
3413
|
+
const fontChildOrder = [
|
|
3414
|
+
'name',
|
|
3415
|
+
'charset',
|
|
3416
|
+
'family',
|
|
3417
|
+
'b',
|
|
3418
|
+
'i',
|
|
3419
|
+
'strike',
|
|
3420
|
+
'outline',
|
|
3421
|
+
'shadow',
|
|
3422
|
+
'condense',
|
|
3423
|
+
'extend',
|
|
3424
|
+
'color',
|
|
3425
|
+
'sz',
|
|
3426
|
+
'u',
|
|
3427
|
+
'vertAlign',
|
|
3428
|
+
'scheme'
|
|
3429
|
+
];
|
|
3430
|
+
class XlsxDirectCellStyleWriter {
|
|
3431
|
+
styles;
|
|
3432
|
+
fonts;
|
|
3433
|
+
fills;
|
|
3434
|
+
borders;
|
|
3435
|
+
cellXfs;
|
|
3436
|
+
generatedFonts = new Map();
|
|
3437
|
+
generatedFills = new Map();
|
|
3438
|
+
generatedBorders = new Map();
|
|
3439
|
+
generatedStyles = new Map();
|
|
3440
|
+
changed = false;
|
|
3441
|
+
constructor(styles){
|
|
3442
|
+
this.styles = styles;
|
|
3443
|
+
const root = styles.documentElement;
|
|
3444
|
+
this.fonts = ensureXlsxStyleCollection(styles, 'fonts', [
|
|
3445
|
+
'fills',
|
|
3446
|
+
'borders',
|
|
3447
|
+
'cellStyleXfs',
|
|
3448
|
+
'cellXfs',
|
|
3449
|
+
'cellStyles',
|
|
3450
|
+
'dxfs',
|
|
3451
|
+
'tableStyles',
|
|
3452
|
+
'colors',
|
|
3453
|
+
'extLst'
|
|
3454
|
+
]);
|
|
3455
|
+
if (!directChildren(this.fonts, 'font').length) {
|
|
3456
|
+
this.fonts.append(styles.createElementNS(root.namespaceURI, 'font'));
|
|
3457
|
+
this.changed = true;
|
|
3458
|
+
}
|
|
3459
|
+
this.fills = ensureXlsxStyleCollection(styles, 'fills', [
|
|
3460
|
+
'borders',
|
|
3461
|
+
'cellStyleXfs',
|
|
3462
|
+
'cellXfs',
|
|
3463
|
+
'cellStyles',
|
|
3464
|
+
'dxfs',
|
|
3465
|
+
'tableStyles',
|
|
3466
|
+
'colors',
|
|
3467
|
+
'extLst'
|
|
3468
|
+
]);
|
|
3469
|
+
if (!directChildren(this.fills, 'fill').length) {
|
|
3470
|
+
this.fills.append(defaultXlsxFill(styles, 'none'));
|
|
3471
|
+
this.fills.append(defaultXlsxFill(styles, 'gray125'));
|
|
3472
|
+
this.changed = true;
|
|
3473
|
+
}
|
|
3474
|
+
this.borders = ensureXlsxStyleCollection(styles, 'borders', [
|
|
3475
|
+
'cellStyleXfs',
|
|
3476
|
+
'cellXfs',
|
|
3477
|
+
'cellStyles',
|
|
3478
|
+
'dxfs',
|
|
3479
|
+
'tableStyles',
|
|
3480
|
+
'colors',
|
|
3481
|
+
'extLst'
|
|
3482
|
+
]);
|
|
3483
|
+
if (!directChildren(this.borders, 'border').length) {
|
|
3484
|
+
this.borders.append(defaultXlsxBorder(styles));
|
|
3485
|
+
this.changed = true;
|
|
3486
|
+
}
|
|
3487
|
+
this.cellXfs = ensureXlsxStyleCollection(styles, 'cellXfs', [
|
|
3488
|
+
'cellStyles',
|
|
3489
|
+
'dxfs',
|
|
3490
|
+
'tableStyles',
|
|
3491
|
+
'colors',
|
|
3492
|
+
'extLst'
|
|
3493
|
+
]);
|
|
3494
|
+
if (!directChildren(this.cellXfs, 'xf').length) {
|
|
3495
|
+
const base = styles.createElementNS(root.namespaceURI, 'xf');
|
|
3496
|
+
base.setAttribute('numFmtId', '0');
|
|
3497
|
+
base.setAttribute('fontId', '0');
|
|
3498
|
+
base.setAttribute('fillId', '0');
|
|
3499
|
+
base.setAttribute('borderId', '0');
|
|
3500
|
+
base.setAttribute('xfId', '0');
|
|
3501
|
+
this.cellXfs.append(base);
|
|
3502
|
+
this.changed = true;
|
|
3503
|
+
}
|
|
3504
|
+
this.updateCounts();
|
|
3505
|
+
}
|
|
3506
|
+
styleId(baseStyleId, cell, border) {
|
|
3507
|
+
const styles = directChildren(this.cellXfs, 'xf');
|
|
3508
|
+
const baseIndex = Number.isInteger(baseStyleId) && styles[baseStyleId] ? baseStyleId : 0;
|
|
3509
|
+
const base = styles[baseIndex];
|
|
3510
|
+
const fontId = this.fontId(work_xlsx_cell_style_writer_nonNegativeInteger(work_ooxml_package_attribute(base, 'fontId')) ?? 0, cell);
|
|
3511
|
+
const fillId = this.fillId(work_xlsx_cell_style_writer_nonNegativeInteger(work_ooxml_package_attribute(base, 'fillId')) ?? 0, cell);
|
|
3512
|
+
const borderId = this.borderId(work_xlsx_cell_style_writer_nonNegativeInteger(work_ooxml_package_attribute(base, 'borderId')) ?? 0, border);
|
|
3513
|
+
const alignment = directAlignment(cell);
|
|
3514
|
+
const key = `${baseIndex}:${fontId}:${fillId}:${borderId}:${JSON.stringify(alignment)}`;
|
|
3515
|
+
const cached = this.generatedStyles.get(key);
|
|
3516
|
+
if (void 0 !== cached) return cached;
|
|
3517
|
+
const clone = base.cloneNode(true);
|
|
3518
|
+
clone.setAttribute('fontId', String(fontId));
|
|
3519
|
+
clone.setAttribute('fillId', String(fillId));
|
|
3520
|
+
clone.setAttribute('borderId', String(borderId));
|
|
3521
|
+
if (hasXlsxDirectFontStyle(cell)) clone.setAttribute('applyFont', '1');
|
|
3522
|
+
if (void 0 !== cell.bg) clone.setAttribute('applyFill', '1');
|
|
3523
|
+
if (border) clone.setAttribute('applyBorder', '1');
|
|
3524
|
+
if (alignment) {
|
|
3525
|
+
writeXlsxAlignment(this.styles, clone, alignment);
|
|
3526
|
+
clone.setAttribute('applyAlignment', '1');
|
|
3527
|
+
}
|
|
3528
|
+
const index = styles.length;
|
|
3529
|
+
this.cellXfs.append(clone);
|
|
3530
|
+
this.generatedStyles.set(key, index);
|
|
3531
|
+
this.changed = true;
|
|
3532
|
+
this.updateCounts();
|
|
3533
|
+
return index;
|
|
3534
|
+
}
|
|
3535
|
+
fontId(baseFontId, cell) {
|
|
3536
|
+
if (!hasXlsxDirectFontStyle(cell)) return baseFontId;
|
|
3537
|
+
const fonts = directChildren(this.fonts, 'font');
|
|
3538
|
+
const baseIndex = fonts[baseFontId] ? baseFontId : 0;
|
|
3539
|
+
const style = directFontStyle(cell);
|
|
3540
|
+
const key = `${baseIndex}:${JSON.stringify(style)}`;
|
|
3541
|
+
const cached = this.generatedFonts.get(key);
|
|
3542
|
+
if (void 0 !== cached) return cached;
|
|
3543
|
+
const font = fonts[baseIndex].cloneNode(true);
|
|
3544
|
+
if (void 0 !== style.name) setXlsxValueChild(this.styles, font, 'name', style.name, fontChildOrder);
|
|
3545
|
+
if (void 0 !== style.size) setXlsxValueChild(this.styles, font, 'sz', String(style.size), fontChildOrder);
|
|
3546
|
+
if (void 0 !== style.color) setXlsxColorChild(this.styles, font, style.color, fontChildOrder);
|
|
3547
|
+
if (void 0 !== style.bold) setXlsxToggleChild(this.styles, font, 'b', style.bold, fontChildOrder);
|
|
3548
|
+
if (void 0 !== style.italic) setXlsxToggleChild(this.styles, font, 'i', style.italic, fontChildOrder);
|
|
3549
|
+
if (void 0 !== style.strike) setXlsxToggleChild(this.styles, font, 'strike', style.strike, fontChildOrder);
|
|
3550
|
+
if (void 0 !== style.underline) setXlsxUnderlineChild(this.styles, font, style.underline, fontChildOrder);
|
|
3551
|
+
const index = fonts.length;
|
|
3552
|
+
this.fonts.append(font);
|
|
3553
|
+
this.generatedFonts.set(key, index);
|
|
3554
|
+
this.changed = true;
|
|
3555
|
+
this.updateCounts();
|
|
3556
|
+
return index;
|
|
3557
|
+
}
|
|
3558
|
+
fillId(baseFillId, cell) {
|
|
3559
|
+
if (void 0 === cell.bg) return baseFillId;
|
|
3560
|
+
const color = xlsxRgbColor(cell.bg);
|
|
3561
|
+
if (!color) return baseFillId;
|
|
3562
|
+
const cached = this.generatedFills.get(color);
|
|
3563
|
+
if (void 0 !== cached) return cached;
|
|
3564
|
+
const fill = this.styles.createElementNS(this.styles.documentElement.namespaceURI, 'fill');
|
|
3565
|
+
const pattern = this.styles.createElementNS(this.styles.documentElement.namespaceURI, 'patternFill');
|
|
3566
|
+
pattern.setAttribute('patternType', 'solid');
|
|
3567
|
+
const foreground = this.styles.createElementNS(this.styles.documentElement.namespaceURI, 'fgColor');
|
|
3568
|
+
foreground.setAttribute('rgb', color);
|
|
3569
|
+
const background = this.styles.createElementNS(this.styles.documentElement.namespaceURI, 'bgColor');
|
|
3570
|
+
background.setAttribute('indexed', '64');
|
|
3571
|
+
pattern.append(foreground, background);
|
|
3572
|
+
fill.append(pattern);
|
|
3573
|
+
const index = directChildren(this.fills, 'fill').length;
|
|
3574
|
+
this.fills.append(fill);
|
|
3575
|
+
this.generatedFills.set(color, index);
|
|
3576
|
+
this.changed = true;
|
|
3577
|
+
this.updateCounts();
|
|
3578
|
+
return index;
|
|
3579
|
+
}
|
|
3580
|
+
borderId(baseBorderId, update) {
|
|
3581
|
+
if (!update) return baseBorderId;
|
|
3582
|
+
const borders = directChildren(this.borders, 'border');
|
|
3583
|
+
const baseIndex = borders[baseBorderId] ? baseBorderId : 0;
|
|
3584
|
+
const key = `${baseIndex}:${JSON.stringify(update)}`;
|
|
3585
|
+
const cached = this.generatedBorders.get(key);
|
|
3586
|
+
if (void 0 !== cached) return cached;
|
|
3587
|
+
const border = borders[baseIndex].cloneNode(true);
|
|
3588
|
+
for (const [name, line] of [
|
|
3589
|
+
[
|
|
3590
|
+
'left',
|
|
3591
|
+
update.left
|
|
3592
|
+
],
|
|
3593
|
+
[
|
|
3594
|
+
'right',
|
|
3595
|
+
update.right
|
|
3596
|
+
],
|
|
3597
|
+
[
|
|
3598
|
+
'top',
|
|
3599
|
+
update.top
|
|
3600
|
+
],
|
|
3601
|
+
[
|
|
3602
|
+
'bottom',
|
|
3603
|
+
update.bottom
|
|
3604
|
+
],
|
|
3605
|
+
[
|
|
3606
|
+
'diagonal',
|
|
3607
|
+
update.diagonal
|
|
3608
|
+
]
|
|
3609
|
+
])if (void 0 !== line) setXlsxBorderLine(this.styles, border, name, line);
|
|
3610
|
+
if (void 0 !== update.diagonalUp) border.setAttribute('diagonalUp', update.diagonalUp ? '1' : '0');
|
|
3611
|
+
if (void 0 !== update.diagonalDown) border.setAttribute('diagonalDown', update.diagonalDown ? '1' : '0');
|
|
3612
|
+
const index = borders.length;
|
|
3613
|
+
this.borders.append(border);
|
|
3614
|
+
this.generatedBorders.set(key, index);
|
|
3615
|
+
this.changed = true;
|
|
3616
|
+
this.updateCounts();
|
|
3617
|
+
return index;
|
|
3618
|
+
}
|
|
3619
|
+
updateCounts() {
|
|
3620
|
+
this.fonts.setAttribute('count', String(directChildren(this.fonts, 'font').length));
|
|
3621
|
+
this.fills.setAttribute('count', String(directChildren(this.fills, 'fill').length));
|
|
3622
|
+
this.borders.setAttribute('count', String(directChildren(this.borders, 'border').length));
|
|
3623
|
+
this.cellXfs.setAttribute('count', String(directChildren(this.cellXfs, 'xf').length));
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
function hasXlsxDirectCellStyle(cell) {
|
|
3627
|
+
return Boolean(hasXlsxDirectFontStyle(cell) || void 0 !== cell.bg || void 0 !== cell.ht || void 0 !== cell.vt || void 0 !== cell.tb || void 0 !== cell.tr);
|
|
3628
|
+
}
|
|
3629
|
+
function hasXlsxDirectFontStyle(cell) {
|
|
3630
|
+
return Boolean(void 0 !== cell.bl || void 0 !== cell.it || void 0 !== cell.un || void 0 !== cell.cl || void 0 !== cell.ff || void 0 !== cell.fs || void 0 !== cell.fc);
|
|
3631
|
+
}
|
|
3632
|
+
function directFontStyle(cell) {
|
|
3633
|
+
const color = void 0 !== cell.fc ? xlsxRgbColor(cell.fc) : null;
|
|
3634
|
+
return {
|
|
3635
|
+
...void 0 !== cell.bl ? {
|
|
3636
|
+
bold: 1 === Number(cell.bl)
|
|
3637
|
+
} : {},
|
|
3638
|
+
...color ? {
|
|
3639
|
+
color
|
|
3640
|
+
} : {},
|
|
3641
|
+
...void 0 !== cell.it ? {
|
|
3642
|
+
italic: 1 === Number(cell.it)
|
|
3643
|
+
} : {},
|
|
3644
|
+
...'string' == typeof cell.ff && cell.ff.trim() ? {
|
|
3645
|
+
name: cell.ff.trim()
|
|
3646
|
+
} : {},
|
|
3647
|
+
...'number' == typeof cell.fs && Number.isFinite(cell.fs) && cell.fs > 0 ? {
|
|
3648
|
+
size: cell.fs
|
|
3649
|
+
} : {},
|
|
3650
|
+
...void 0 !== cell.cl ? {
|
|
3651
|
+
strike: 1 === Number(cell.cl)
|
|
3652
|
+
} : {},
|
|
3653
|
+
...void 0 !== cell.un ? {
|
|
3654
|
+
underline: 1 === Number(cell.un)
|
|
3655
|
+
} : {}
|
|
3656
|
+
};
|
|
3657
|
+
}
|
|
3658
|
+
function directAlignment(cell) {
|
|
3659
|
+
const alignment = {};
|
|
3660
|
+
if (void 0 !== cell.ht) alignment.horizontal = 0 === Number(cell.ht) ? 'center' : 2 === Number(cell.ht) ? 'right' : 'left';
|
|
3661
|
+
if (void 0 !== cell.vt) alignment.vertical = 0 === Number(cell.vt) ? 'center' : 1 === Number(cell.vt) ? 'top' : 'bottom';
|
|
3662
|
+
if (void 0 !== cell.tb) alignment.wrapText = '2' === cell.tb;
|
|
3663
|
+
if (void 0 !== cell.tr) {
|
|
3664
|
+
const rotation = Number(cell.tr);
|
|
3665
|
+
if (Number.isFinite(rotation) && rotation >= 0 && rotation <= 180) alignment.textRotation = Math.round(rotation);
|
|
3666
|
+
}
|
|
3667
|
+
return Object.keys(alignment).length ? alignment : null;
|
|
3668
|
+
}
|
|
3669
|
+
function work_xlsx_cell_style_writer_nonNegativeInteger(value) {
|
|
3670
|
+
if (null === value || !/^\d+$/.test(value)) return null;
|
|
3671
|
+
const parsed = Number(value);
|
|
3672
|
+
return Number.isSafeInteger(parsed) ? parsed : null;
|
|
3673
|
+
}
|
|
3674
|
+
const defaultThemeColors = [
|
|
3675
|
+
'ffffff',
|
|
3676
|
+
'000000',
|
|
3677
|
+
'e7e6e6',
|
|
3678
|
+
'44546a',
|
|
3679
|
+
'4472c4',
|
|
3680
|
+
'ed7d31',
|
|
3681
|
+
'a5a5a5',
|
|
3682
|
+
'ffc000',
|
|
3683
|
+
'5b9bd5',
|
|
3684
|
+
'70ad47',
|
|
3685
|
+
'0563c1',
|
|
3686
|
+
'954f72'
|
|
3687
|
+
];
|
|
3688
|
+
const themeColorNames = [
|
|
3689
|
+
'lt1',
|
|
3690
|
+
'dk1',
|
|
3691
|
+
'lt2',
|
|
3692
|
+
'dk2',
|
|
3693
|
+
'accent1',
|
|
3694
|
+
'accent2',
|
|
3695
|
+
'accent3',
|
|
3696
|
+
'accent4',
|
|
3697
|
+
'accent5',
|
|
3698
|
+
'accent6',
|
|
3699
|
+
'hlink',
|
|
3700
|
+
'folHlink'
|
|
3701
|
+
];
|
|
3702
|
+
const defaultIndexedColors = [
|
|
3703
|
+
'000000',
|
|
3704
|
+
'ffffff',
|
|
3705
|
+
'ff0000',
|
|
3706
|
+
'00ff00',
|
|
3707
|
+
'0000ff',
|
|
3708
|
+
'ffff00',
|
|
3709
|
+
'ff00ff',
|
|
3710
|
+
'00ffff',
|
|
3711
|
+
'000000',
|
|
3712
|
+
'ffffff',
|
|
3713
|
+
'ff0000',
|
|
3714
|
+
'00ff00',
|
|
3715
|
+
'0000ff',
|
|
3716
|
+
'ffff00',
|
|
3717
|
+
'ff00ff',
|
|
3718
|
+
'00ffff',
|
|
3719
|
+
'800000',
|
|
3720
|
+
'008000',
|
|
3721
|
+
'000080',
|
|
3722
|
+
'808000',
|
|
3723
|
+
'800080',
|
|
3724
|
+
'008080',
|
|
3725
|
+
'c0c0c0',
|
|
3726
|
+
'808080',
|
|
3727
|
+
'9999ff',
|
|
3728
|
+
'993366',
|
|
3729
|
+
'ffffcc',
|
|
3730
|
+
'ccffff',
|
|
3731
|
+
'660066',
|
|
3732
|
+
'ff8080',
|
|
3733
|
+
'0066cc',
|
|
3734
|
+
'ccccff',
|
|
3735
|
+
'000080',
|
|
3736
|
+
'ff00ff',
|
|
3737
|
+
'ffff00',
|
|
3738
|
+
'00ffff',
|
|
3739
|
+
'800080',
|
|
3740
|
+
'800000',
|
|
3741
|
+
'008080',
|
|
3742
|
+
'0000ff',
|
|
3743
|
+
'00ccff',
|
|
3744
|
+
'ccffff',
|
|
3745
|
+
'ccffcc',
|
|
3746
|
+
'ffff99',
|
|
3747
|
+
'99ccff',
|
|
3748
|
+
'ff99cc',
|
|
3749
|
+
'cc99ff',
|
|
3750
|
+
'ffcc99',
|
|
3751
|
+
'3366ff',
|
|
3752
|
+
'33cccc',
|
|
3753
|
+
'99cc00',
|
|
3754
|
+
'ffcc00',
|
|
3755
|
+
'ff9900',
|
|
3756
|
+
'ff6600',
|
|
3757
|
+
'666699',
|
|
3758
|
+
'969696',
|
|
3759
|
+
'003366',
|
|
3760
|
+
'339966',
|
|
3761
|
+
'003300',
|
|
3762
|
+
'333300',
|
|
3763
|
+
'993300',
|
|
3764
|
+
'993366',
|
|
3765
|
+
'333399',
|
|
3766
|
+
'333333'
|
|
3767
|
+
];
|
|
3768
|
+
function createXlsxColorResolver(styles, theme) {
|
|
3769
|
+
return {
|
|
3770
|
+
indexed: readIndexedColors(styles),
|
|
3771
|
+
theme: readThemeColors(theme)
|
|
3772
|
+
};
|
|
3773
|
+
}
|
|
3774
|
+
function resolveXlsxColor(element, resolver) {
|
|
3775
|
+
if (!element) return;
|
|
3776
|
+
const direct = normalizedHexColor(work_ooxml_package_attribute(element, 'rgb'));
|
|
3777
|
+
const themeIndex = boundedInteger(work_ooxml_package_attribute(element, 'theme'), 11);
|
|
3778
|
+
const indexed = boundedInteger(work_ooxml_package_attribute(element, 'indexed'), 65535);
|
|
3779
|
+
const automatic = work_xlsx_colors_booleanAttribute(element, 'auto');
|
|
3780
|
+
const source = direct ?? (null === themeIndex ? void 0 : resolver.theme[themeIndex]) ?? (null === indexed ? void 0 : resolver.indexed[indexed]) ?? (automatic ? '000000' : void 0);
|
|
3781
|
+
if (!source) return;
|
|
3782
|
+
const tint = Number(work_ooxml_package_attribute(element, 'tint'));
|
|
3783
|
+
return `#${Number.isFinite(tint) && tint >= -1 && tint <= 1 ? tintXlsxColor(source, tint) : source}`;
|
|
3784
|
+
}
|
|
3785
|
+
function readThemeColors(theme) {
|
|
3786
|
+
if (!theme) return defaultThemeColors;
|
|
3787
|
+
const scheme = firstDescendant(theme, 'clrScheme');
|
|
3788
|
+
if (!scheme) return defaultThemeColors;
|
|
3789
|
+
return themeColorNames.map((name, index)=>{
|
|
3790
|
+
const entry = directChild(scheme, name);
|
|
3791
|
+
const color = entry ? drawingColor(directChildren(entry)[0]) : void 0;
|
|
3792
|
+
return color ?? defaultThemeColors[index];
|
|
3793
|
+
});
|
|
3794
|
+
}
|
|
3795
|
+
function readIndexedColors(styles) {
|
|
3796
|
+
const indexed = firstDescendant(styles, 'indexedColors');
|
|
3797
|
+
if (!indexed) return defaultIndexedColors;
|
|
3798
|
+
const colors = directChildren(indexed, 'rgbColor').map((element)=>normalizedHexColor(work_ooxml_package_attribute(element, 'rgb')));
|
|
3799
|
+
return colors.every(Boolean) ? colors : defaultIndexedColors;
|
|
3800
|
+
}
|
|
3801
|
+
function drawingColor(element) {
|
|
3802
|
+
if (!element) return;
|
|
3803
|
+
return normalizedHexColor('sysClr' === element.localName ? work_ooxml_package_attribute(element, 'lastClr') : work_ooxml_package_attribute(element, 'val'));
|
|
3804
|
+
}
|
|
3805
|
+
function tintXlsxColor(color, tint) {
|
|
3806
|
+
const [hue, saturation, lightness] = rgbToHsl([
|
|
3807
|
+
0,
|
|
3808
|
+
2,
|
|
3809
|
+
4
|
|
3810
|
+
].map((offset)=>Number.parseInt(color.slice(offset, offset + 2), 16) / 255));
|
|
3811
|
+
const tintedLightness = tint < 0 ? lightness * (1 + tint) : 1 - (1 - lightness) * (1 - tint);
|
|
3812
|
+
return hslToRgb(hue, saturation, tintedLightness).map((channel)=>Math.round(255 * channel)).map((channel)=>channel.toString(16).padStart(2, '0')).join('');
|
|
3813
|
+
}
|
|
3814
|
+
function rgbToHsl([red, green, blue]) {
|
|
3815
|
+
const maximum = Math.max(red, green, blue);
|
|
3816
|
+
const minimum = Math.min(red, green, blue);
|
|
3817
|
+
const delta = maximum - minimum;
|
|
3818
|
+
const lightness = (maximum + minimum) / 2;
|
|
3819
|
+
if (0 === delta) return [
|
|
3820
|
+
0,
|
|
3821
|
+
0,
|
|
3822
|
+
lightness
|
|
3823
|
+
];
|
|
3824
|
+
const saturation = delta / (1 - Math.abs(2 * lightness - 1));
|
|
3825
|
+
const hue = maximum === red ? ((green - blue) / delta + (green < blue ? 6 : 0)) / 6 : maximum === green ? ((blue - red) / delta + 2) / 6 : ((red - green) / delta + 4) / 6;
|
|
3826
|
+
return [
|
|
3827
|
+
hue,
|
|
3828
|
+
saturation,
|
|
3829
|
+
lightness
|
|
3830
|
+
];
|
|
3831
|
+
}
|
|
3832
|
+
function hslToRgb(hue, saturation, lightness) {
|
|
3833
|
+
if (0 === saturation) return [
|
|
3834
|
+
lightness,
|
|
3835
|
+
lightness,
|
|
3836
|
+
lightness
|
|
3837
|
+
];
|
|
3838
|
+
const chroma = 2 * saturation * (lightness < 0.5 ? lightness : 1 - lightness);
|
|
3839
|
+
const minimum = lightness - chroma / 2;
|
|
3840
|
+
const channels = [
|
|
3841
|
+
minimum,
|
|
3842
|
+
minimum,
|
|
3843
|
+
minimum
|
|
3844
|
+
];
|
|
3845
|
+
const sector = 6 * hue;
|
|
3846
|
+
switch(Math.floor(sector)){
|
|
3847
|
+
case 0:
|
|
3848
|
+
case 6:
|
|
3849
|
+
channels[0] += chroma;
|
|
3850
|
+
channels[1] += chroma * sector;
|
|
3851
|
+
break;
|
|
3852
|
+
case 1:
|
|
3853
|
+
channels[0] += chroma * (2 - sector);
|
|
3854
|
+
channels[1] += chroma;
|
|
3855
|
+
break;
|
|
3856
|
+
case 2:
|
|
3857
|
+
channels[1] += chroma;
|
|
3858
|
+
channels[2] += chroma * (sector - 2);
|
|
3859
|
+
break;
|
|
3860
|
+
case 3:
|
|
3861
|
+
channels[1] += chroma * (4 - sector);
|
|
3862
|
+
channels[2] += chroma;
|
|
3863
|
+
break;
|
|
3864
|
+
case 4:
|
|
3865
|
+
channels[0] += chroma * (sector - 4);
|
|
3866
|
+
channels[2] += chroma;
|
|
3867
|
+
break;
|
|
3868
|
+
case 5:
|
|
3869
|
+
channels[0] += chroma;
|
|
3870
|
+
channels[2] += chroma * (6 - sector);
|
|
3871
|
+
break;
|
|
3872
|
+
}
|
|
3873
|
+
return channels;
|
|
3874
|
+
}
|
|
3875
|
+
function normalizedHexColor(value) {
|
|
3876
|
+
if (!value || !/^[0-9a-f]{6,8}$/i.test(value)) return;
|
|
3877
|
+
return value.slice(-6).toLowerCase();
|
|
3878
|
+
}
|
|
3879
|
+
function boundedInteger(value, maximum) {
|
|
3880
|
+
if (null === value || !/^\d+$/.test(value)) return null;
|
|
3881
|
+
const parsed = Number(value);
|
|
3882
|
+
return Number.isSafeInteger(parsed) && parsed <= maximum ? parsed : null;
|
|
3883
|
+
}
|
|
3884
|
+
function work_xlsx_colors_booleanAttribute(element, name) {
|
|
3885
|
+
const value = work_ooxml_package_attribute(element, name)?.trim().toLowerCase();
|
|
3886
|
+
return '1' === value || 'true' === value || 'on' === value;
|
|
3887
|
+
}
|
|
3888
|
+
const xlsxCellBorderStyles = new Set([
|
|
3889
|
+
'dashDot',
|
|
3890
|
+
'dashDotDot',
|
|
3891
|
+
'dashed',
|
|
3892
|
+
'dotted',
|
|
3893
|
+
'double',
|
|
3894
|
+
'hair',
|
|
3895
|
+
'medium',
|
|
3896
|
+
'mediumDashDot',
|
|
3897
|
+
'mediumDashDotDot',
|
|
3898
|
+
'mediumDashed',
|
|
3899
|
+
'slantDashDot',
|
|
3900
|
+
'thick',
|
|
3901
|
+
'thin'
|
|
3902
|
+
]);
|
|
3903
|
+
function readXlsxDirectCellStyles(worksheet, styles, theme = null) {
|
|
3904
|
+
if (!styles) return [];
|
|
3905
|
+
const colors = createXlsxColorResolver(styles, theme);
|
|
3906
|
+
const fonts = directChildren(directChild(styles.documentElement, 'fonts') ?? styles, 'font');
|
|
3907
|
+
const fills = directChildren(directChild(styles.documentElement, 'fills') ?? styles, 'fill');
|
|
3908
|
+
const borders = directChildren(directChild(styles.documentElement, 'borders') ?? styles, 'border');
|
|
3909
|
+
const cellXfs = directChildren(directChild(styles.documentElement, 'cellXfs') ?? styles, 'xf');
|
|
3910
|
+
if (!cellXfs.length) return [];
|
|
3911
|
+
return descendants(worksheet, 'c').flatMap((cell)=>{
|
|
3912
|
+
const coordinate = decodeCell(work_ooxml_package_attribute(cell, 'r'));
|
|
3913
|
+
const styleId = work_xlsx_cell_styles_nonNegativeInteger(work_ooxml_package_attribute(cell, 's'));
|
|
3914
|
+
const xf = null === styleId ? void 0 : cellXfs[styleId];
|
|
3915
|
+
if (!coordinate || !xf) return [];
|
|
3916
|
+
const style = readDirectCellStyle(xf, fonts, fills, colors);
|
|
3917
|
+
const border = readDirectCellBorder(xf, borders, colors);
|
|
3918
|
+
return Object.keys(style).length || border ? [
|
|
3919
|
+
{
|
|
3920
|
+
...coordinate,
|
|
3921
|
+
border,
|
|
3922
|
+
style
|
|
3923
|
+
}
|
|
3924
|
+
] : [];
|
|
3925
|
+
});
|
|
3926
|
+
}
|
|
3927
|
+
function sheetHasDirectCellStyles(sheet) {
|
|
3928
|
+
if (Array.isArray(sheet.config?.borderInfo) && sheet.config.borderInfo.length) return true;
|
|
3929
|
+
for (const [, row] of sparseArrayEntries(sheet.data))for (const [, cell] of sparseArrayEntries(row))if (cell && hasXlsxDirectCellStyle(cell)) return true;
|
|
3930
|
+
return false;
|
|
3931
|
+
}
|
|
3932
|
+
function writeXlsxDirectCellStyles(worksheet, sheet, styles) {
|
|
3933
|
+
const borders = collectXlsxCellBorders(sheet);
|
|
3934
|
+
const cells = new Map(descendants(worksheet, 'c').flatMap((element)=>{
|
|
3935
|
+
const reference = work_ooxml_package_attribute(element, 'r');
|
|
3936
|
+
return reference ? [
|
|
3937
|
+
[
|
|
3938
|
+
reference,
|
|
3939
|
+
element
|
|
3940
|
+
]
|
|
3941
|
+
] : [];
|
|
3942
|
+
}));
|
|
3943
|
+
for (const [row, values] of sparseArrayEntries(sheet.data))for (const [column, cell] of sparseArrayEntries(values)){
|
|
3944
|
+
const border = borders.get(xlsxCellBorderKey(row, column));
|
|
3945
|
+
if (!cell || !hasXlsxDirectCellStyle(cell) && !border) continue;
|
|
3946
|
+
const element = cells.get(encodeCell(row, column));
|
|
3947
|
+
if (!element) continue;
|
|
3948
|
+
const baseStyleId = work_xlsx_cell_styles_nonNegativeInteger(work_ooxml_package_attribute(element, 's')) ?? 0;
|
|
3949
|
+
const styleId = styles.styleId(baseStyleId, cell, border);
|
|
3950
|
+
if (styleId) element.setAttribute('s', String(styleId));
|
|
3951
|
+
else element.removeAttribute('s');
|
|
3952
|
+
}
|
|
3953
|
+
}
|
|
3954
|
+
function readDirectCellStyle(xf, fonts, fills, colors) {
|
|
3955
|
+
const style = {};
|
|
3956
|
+
const fontId = work_xlsx_cell_styles_nonNegativeInteger(work_ooxml_package_attribute(xf, 'fontId')) ?? 0;
|
|
3957
|
+
const font = fonts[fontId];
|
|
3958
|
+
if (font && (0 !== fontId || work_xlsx_cell_styles_booleanAttribute(xf, 'applyFont'))) readDirectFontStyle(style, font, colors);
|
|
3959
|
+
const fillId = work_xlsx_cell_styles_nonNegativeInteger(work_ooxml_package_attribute(xf, 'fillId')) ?? 0;
|
|
3960
|
+
const fill = fills[fillId];
|
|
3961
|
+
if (fill && (0 !== fillId || work_xlsx_cell_styles_booleanAttribute(xf, 'applyFill'))) readDirectFillStyle(style, fill, colors);
|
|
3962
|
+
const alignment = directChild(xf, 'alignment');
|
|
3963
|
+
if (alignment) readDirectAlignmentStyle(style, alignment);
|
|
3964
|
+
return style;
|
|
3965
|
+
}
|
|
3966
|
+
function readDirectFontStyle(style, font, colors) {
|
|
3967
|
+
const bold = directChild(font, 'b');
|
|
3968
|
+
if (bold && toggleEnabled(bold)) style.bl = 1;
|
|
3969
|
+
const italic = directChild(font, 'i');
|
|
3970
|
+
if (italic && toggleEnabled(italic)) style.it = 1;
|
|
3971
|
+
const strike = directChild(font, 'strike');
|
|
3972
|
+
if (strike && toggleEnabled(strike)) style.cl = 1;
|
|
3973
|
+
const underline = directChild(font, 'u');
|
|
3974
|
+
if (underline && underlineEnabled(underline)) style.un = 1;
|
|
3975
|
+
const name = work_ooxml_package_attribute(directChild(font, 'name') ?? font, 'val')?.trim();
|
|
3976
|
+
if (name) style.ff = name;
|
|
3977
|
+
const size = Number(work_ooxml_package_attribute(directChild(font, 'sz') ?? font, 'val'));
|
|
3978
|
+
if (Number.isFinite(size) && size > 0) style.fs = size;
|
|
3979
|
+
const color = resolveXlsxColor(directChild(font, 'color'), colors);
|
|
3980
|
+
if (color) style.fc = color;
|
|
3981
|
+
}
|
|
3982
|
+
function readDirectFillStyle(style, fill, colors) {
|
|
3983
|
+
const pattern = directChild(fill, 'patternFill');
|
|
3984
|
+
if (!pattern || 'solid' !== work_ooxml_package_attribute(pattern, 'patternType')) return;
|
|
3985
|
+
const color = resolveXlsxColor(directChild(pattern, 'fgColor'), colors);
|
|
3986
|
+
if (color) style.bg = color;
|
|
3987
|
+
}
|
|
3988
|
+
function readDirectAlignmentStyle(style, alignment) {
|
|
3989
|
+
const horizontal = work_ooxml_package_attribute(alignment, 'horizontal');
|
|
3990
|
+
if ('center' === horizontal) style.ht = 0;
|
|
3991
|
+
else if ('left' === horizontal) style.ht = 1;
|
|
3992
|
+
else if ('right' === horizontal) style.ht = 2;
|
|
3993
|
+
const vertical = work_ooxml_package_attribute(alignment, 'vertical');
|
|
3994
|
+
if ('center' === vertical) style.vt = 0;
|
|
3995
|
+
else if ('top' === vertical) style.vt = 1;
|
|
3996
|
+
else if ('bottom' === vertical) style.vt = 2;
|
|
3997
|
+
if (work_xlsx_cell_styles_booleanAttribute(alignment, 'wrapText')) style.tb = '2';
|
|
3998
|
+
const rotation = work_xlsx_cell_styles_nonNegativeInteger(work_ooxml_package_attribute(alignment, 'textRotation'));
|
|
3999
|
+
if (null !== rotation && rotation <= 180) style.tr = String(rotation);
|
|
4000
|
+
}
|
|
4001
|
+
function readDirectCellBorder(xf, borders, colors) {
|
|
4002
|
+
const borderId = work_xlsx_cell_styles_nonNegativeInteger(work_ooxml_package_attribute(xf, 'borderId')) ?? 0;
|
|
4003
|
+
const source = borders[borderId];
|
|
4004
|
+
if (!source || 0 === borderId && !work_xlsx_cell_styles_booleanAttribute(xf, 'applyBorder')) return;
|
|
4005
|
+
const border = {};
|
|
4006
|
+
readBorderLine(border, 'left', directChild(source, 'left'), colors);
|
|
4007
|
+
readBorderLine(border, 'right', directChild(source, 'right'), colors);
|
|
4008
|
+
readBorderLine(border, 'top', directChild(source, 'top'), colors);
|
|
4009
|
+
readBorderLine(border, 'bottom', directChild(source, 'bottom'), colors);
|
|
4010
|
+
readBorderLine(border, 'diagonal', directChild(source, 'diagonal'), colors);
|
|
4011
|
+
if (border.diagonal) {
|
|
4012
|
+
border.diagonalUp = work_xlsx_cell_styles_booleanAttribute(source, 'diagonalUp');
|
|
4013
|
+
border.diagonalDown = work_xlsx_cell_styles_booleanAttribute(source, 'diagonalDown');
|
|
4014
|
+
}
|
|
4015
|
+
return Object.keys(border).length ? border : void 0;
|
|
4016
|
+
}
|
|
4017
|
+
function readBorderLine(border, name, element, colors) {
|
|
4018
|
+
if (!element) return;
|
|
4019
|
+
const style = work_ooxml_package_attribute(element, 'style');
|
|
4020
|
+
if (!style || !xlsxCellBorderStyles.has(style)) return;
|
|
4021
|
+
border[name] = {
|
|
4022
|
+
color: resolveXlsxColor(directChild(element, 'color'), colors) ?? '#000000',
|
|
4023
|
+
style: style
|
|
4024
|
+
};
|
|
4025
|
+
}
|
|
4026
|
+
function toggleEnabled(element) {
|
|
4027
|
+
const value = work_ooxml_package_attribute(element, 'val')?.trim().toLowerCase();
|
|
4028
|
+
return '0' !== value && 'false' !== value && 'off' !== value;
|
|
4029
|
+
}
|
|
4030
|
+
function underlineEnabled(element) {
|
|
4031
|
+
const value = work_ooxml_package_attribute(element, 'val')?.trim().toLowerCase();
|
|
4032
|
+
return '0' !== value && 'false' !== value && 'none' !== value;
|
|
4033
|
+
}
|
|
4034
|
+
function work_xlsx_cell_styles_booleanAttribute(element, name) {
|
|
4035
|
+
const value = work_ooxml_package_attribute(element, name)?.trim().toLowerCase();
|
|
4036
|
+
return '1' === value || 'true' === value || 'on' === value;
|
|
4037
|
+
}
|
|
4038
|
+
function encodeCell(row, column) {
|
|
4039
|
+
let value = column + 1;
|
|
4040
|
+
let label = '';
|
|
4041
|
+
while(value > 0){
|
|
4042
|
+
value -= 1;
|
|
4043
|
+
label = String.fromCharCode(65 + value % 26) + label;
|
|
4044
|
+
value = Math.floor(value / 26);
|
|
4045
|
+
}
|
|
4046
|
+
return `${label}${row + 1}`;
|
|
4047
|
+
}
|
|
4048
|
+
function decodeCell(reference) {
|
|
4049
|
+
const match = /^([A-Z]{1,3})([1-9]\d{0,6})$/i.exec(reference ?? '');
|
|
4050
|
+
if (!match) return null;
|
|
4051
|
+
let column = 0;
|
|
4052
|
+
for (const character of match[1].toUpperCase())column = 26 * column + character.charCodeAt(0) - 64;
|
|
4053
|
+
const row = Number(match[2]);
|
|
4054
|
+
return column <= 16384 && row <= 1048576 ? {
|
|
4055
|
+
column: column - 1,
|
|
4056
|
+
row: row - 1
|
|
4057
|
+
} : null;
|
|
4058
|
+
}
|
|
4059
|
+
function work_xlsx_cell_styles_nonNegativeInteger(value) {
|
|
4060
|
+
if (null === value || !/^\d+$/.test(value)) return null;
|
|
4061
|
+
const parsed = Number(value);
|
|
4062
|
+
return Number.isSafeInteger(parsed) ? parsed : null;
|
|
4063
|
+
}
|
|
3064
4064
|
function readXlsxDifferentialFormats(styles) {
|
|
3065
4065
|
const container = styles ? firstDescendant(styles, 'dxfs') : null;
|
|
3066
4066
|
if (!container) return [];
|
|
@@ -3492,7 +4492,7 @@ function writeRule(document1, rule, priority, differentialFormats) {
|
|
|
3492
4492
|
if ('textContains' === rule.conditionName && values[0]) {
|
|
3493
4493
|
element.setAttribute('type', 'containsText');
|
|
3494
4494
|
element.setAttribute('text', values[0]);
|
|
3495
|
-
const firstCell =
|
|
4495
|
+
const firstCell = work_xlsx_conditional_format_write_encodeCell(rule.cellrange[0].row[0], rule.cellrange[0].column[0]);
|
|
3496
4496
|
appendFormula(document1, element, `NOT(ISERROR(SEARCH("${values[0].replaceAll('"', '""')}",${firstCell})))`);
|
|
3497
4497
|
return finish();
|
|
3498
4498
|
}
|
|
@@ -3609,11 +4609,11 @@ function validIndex(value) {
|
|
|
3609
4609
|
return 'number' == typeof value && Number.isInteger(value) && value >= 0;
|
|
3610
4610
|
}
|
|
3611
4611
|
function encodeRange(range) {
|
|
3612
|
-
const start =
|
|
3613
|
-
const end =
|
|
4612
|
+
const start = work_xlsx_conditional_format_write_encodeCell(range.row[0], range.column[0]);
|
|
4613
|
+
const end = work_xlsx_conditional_format_write_encodeCell(range.row[1], range.column[1]);
|
|
3614
4614
|
return start === end ? start : `${start}:${end}`;
|
|
3615
4615
|
}
|
|
3616
|
-
function
|
|
4616
|
+
function work_xlsx_conditional_format_write_encodeCell(row, column) {
|
|
3617
4617
|
let value = column + 1;
|
|
3618
4618
|
let label = '';
|
|
3619
4619
|
while(value > 0){
|
|
@@ -4405,7 +5405,7 @@ function writeCellProtectionStyles(worksheet, sheet, styles) {
|
|
|
4405
5405
|
const compact = compactProtectionAt(authority, row, column);
|
|
4406
5406
|
if (void 0 === cell.lo && void 0 === cell.hi && void 0 === compact) continue;
|
|
4407
5407
|
const element = ensureCellElement(worksheet, row, column);
|
|
4408
|
-
const baseStyle =
|
|
5408
|
+
const baseStyle = work_xlsx_protection_nonNegativeInteger(work_ooxml_package_attribute(element, 's')) ?? 0;
|
|
4409
5409
|
const styleId = styles.styleId(baseStyle, void 0 === cell.lo ? compact?.locked ?? true : 0 !== cell.lo, void 0 === cell.hi ? compact?.hidden ?? false : 1 === cell.hi);
|
|
4410
5410
|
if (styleId) element.setAttribute('s', String(styleId));
|
|
4411
5411
|
else element.removeAttribute('s');
|
|
@@ -4572,7 +5572,7 @@ function work_xlsx_protection_parseSqref(value) {
|
|
|
4572
5572
|
return value ? parseSpreadsheetCellRanges(value.trim().replace(/\s+/g, ',')) ?? [] : [];
|
|
4573
5573
|
}
|
|
4574
5574
|
function indexedStyle(styles, value) {
|
|
4575
|
-
const index =
|
|
5575
|
+
const index = work_xlsx_protection_nonNegativeInteger(value);
|
|
4576
5576
|
return null === index ? null : styles[index] ?? null;
|
|
4577
5577
|
}
|
|
4578
5578
|
function parseCellReference(value) {
|
|
@@ -4613,18 +5613,18 @@ function work_xlsx_protection_booleanAttribute(element, name, fallback) {
|
|
|
4613
5613
|
if ('0' === value || 'false' === value || 'off' === value) return false;
|
|
4614
5614
|
return fallback;
|
|
4615
5615
|
}
|
|
4616
|
-
function
|
|
5616
|
+
function work_xlsx_protection_nonNegativeInteger(value) {
|
|
4617
5617
|
if (null === value || !/^\d+$/.test(value)) return null;
|
|
4618
5618
|
return Number(value);
|
|
4619
5619
|
}
|
|
4620
5620
|
function work_xlsx_protection_positiveInteger(value) {
|
|
4621
|
-
const parsed =
|
|
5621
|
+
const parsed = work_xlsx_protection_nonNegativeInteger(value);
|
|
4622
5622
|
return null !== parsed && parsed > 0 ? parsed : null;
|
|
4623
5623
|
}
|
|
4624
5624
|
function sameProtection(left, right) {
|
|
4625
5625
|
return left.locked === right.locked && left.hidden === right.hidden;
|
|
4626
5626
|
}
|
|
4627
|
-
const
|
|
5627
|
+
const IMPORTED_WORKSHEET_ELEMENTS = new Set([
|
|
4628
5628
|
'pane',
|
|
4629
5629
|
'dataValidation',
|
|
4630
5630
|
'conditionalFormatting',
|
|
@@ -4638,10 +5638,51 @@ const XLSX_IMPORTED_WORKSHEET_ELEMENTS = [
|
|
|
4638
5638
|
'headerFooter',
|
|
4639
5639
|
'pageSetUpPr',
|
|
4640
5640
|
'drawing'
|
|
4641
|
-
];
|
|
5641
|
+
]);
|
|
5642
|
+
const DIAGNOSTIC_WORKSHEET_ELEMENTS = new Set([
|
|
5643
|
+
'conditionalFormatting',
|
|
5644
|
+
'dataValidation',
|
|
5645
|
+
'sheetProtection',
|
|
5646
|
+
'protectedRange',
|
|
5647
|
+
'pageSetup',
|
|
5648
|
+
'pageMargins',
|
|
5649
|
+
'printOptions',
|
|
5650
|
+
'headerFooter',
|
|
5651
|
+
'pageSetUpPr',
|
|
5652
|
+
'rowBreaks',
|
|
5653
|
+
'colBreaks'
|
|
5654
|
+
]);
|
|
5655
|
+
const WORKSHEET_SCAN_PATTERN = /<(?:[A-Za-z_][\w.-]*:)?(?:(cols|f|pane|dataValidation|conditionalFormatting|sheetProtection|protectedRange|rowBreaks|colBreaks|pageSetup|pageMargins|printOptions|headerFooter|pageSetUpPr|drawing)(?=[\s/>])|(row)(?=[\s/>])[^>]*\s(?:collapsed|customFormat|customHeight|hidden|ht|outlineLevel|thickBot|thickTop)\s*=|(c)(?=[\s/>])[^>]*\ss\s*=)/g;
|
|
5656
|
+
function scanXlsxWorksheetXml(source) {
|
|
5657
|
+
let hasDirectCellStyles = false;
|
|
5658
|
+
let hasDiagnosticFeatures = false;
|
|
5659
|
+
let hasFormulaFeatures = false;
|
|
5660
|
+
let hasImportedFeatures = false;
|
|
5661
|
+
let requiresSheetJsCellStyles = false;
|
|
5662
|
+
WORKSHEET_SCAN_PATTERN.lastIndex = 0;
|
|
5663
|
+
for(let match = WORKSHEET_SCAN_PATTERN.exec(source); match;){
|
|
5664
|
+
const element = match[1];
|
|
5665
|
+
if (match[3]) hasDirectCellStyles = true;
|
|
5666
|
+
if (match[2] || match[3] || 'cols' === element) requiresSheetJsCellStyles = true;
|
|
5667
|
+
if ('f' === element) hasFormulaFeatures = true;
|
|
5668
|
+
if (element && IMPORTED_WORKSHEET_ELEMENTS.has(element)) hasImportedFeatures = true;
|
|
5669
|
+
if (element && DIAGNOSTIC_WORKSHEET_ELEMENTS.has(element)) hasDiagnosticFeatures = true;
|
|
5670
|
+
if (hasDirectCellStyles && hasDiagnosticFeatures && hasFormulaFeatures && hasImportedFeatures && requiresSheetJsCellStyles) break;
|
|
5671
|
+
match = WORKSHEET_SCAN_PATTERN.exec(source);
|
|
5672
|
+
}
|
|
5673
|
+
WORKSHEET_SCAN_PATTERN.lastIndex = 0;
|
|
5674
|
+
return {
|
|
5675
|
+
hasDirectCellStyles,
|
|
5676
|
+
hasDiagnosticFeatures,
|
|
5677
|
+
hasFormulaFeatures,
|
|
5678
|
+
hasImportedFeatures,
|
|
5679
|
+
requiresSheetJsCellStyles
|
|
5680
|
+
};
|
|
5681
|
+
}
|
|
4642
5682
|
async function readXlsxSheetFeaturesFromPackage(archive, worksheetScans) {
|
|
4643
5683
|
const worksheetParts = await work_xlsx_interop_readWorksheetParts(archive);
|
|
4644
5684
|
const styles = archive.has('xl/styles.xml') ? await archive.xml('xl/styles.xml') : null;
|
|
5685
|
+
const theme = archive.has('xl/theme/theme1.xml') ? await archive.xml('xl/theme/theme1.xml') : null;
|
|
4645
5686
|
const differentialFormats = readXlsxDifferentialFormats(styles);
|
|
4646
5687
|
const features = new Map();
|
|
4647
5688
|
const imageBudget = {
|
|
@@ -4650,17 +5691,19 @@ async function readXlsxSheetFeaturesFromPackage(archive, worksheetScans) {
|
|
|
4650
5691
|
for (const [sheetName, partPath] of worksheetParts){
|
|
4651
5692
|
if (!archive.has(partPath)) continue;
|
|
4652
5693
|
const scan = worksheetScans?.[partPath];
|
|
4653
|
-
if (scan && !scan.hasImportedFeatures) {
|
|
5694
|
+
if (scan && !scan.hasImportedFeatures && !scan.hasDirectCellStyles) {
|
|
4654
5695
|
features.set(sheetName, emptyXlsxSheetFeatures());
|
|
4655
5696
|
continue;
|
|
4656
5697
|
}
|
|
4657
5698
|
const source = await archive.text(partPath);
|
|
4658
|
-
|
|
5699
|
+
const detected = scan ?? scanXlsxWorksheetXml(source);
|
|
5700
|
+
if (!detected.hasImportedFeatures && !detected.hasDirectCellStyles) {
|
|
4659
5701
|
features.set(sheetName, emptyXlsxSheetFeatures());
|
|
4660
5702
|
continue;
|
|
4661
5703
|
}
|
|
4662
5704
|
const document1 = parseXml(source, partPath);
|
|
4663
5705
|
features.set(sheetName, {
|
|
5706
|
+
directCellStyles: readXlsxDirectCellStyles(document1, styles, theme),
|
|
4664
5707
|
frozen: parseFrozenPane(document1) ?? void 0,
|
|
4665
5708
|
validations: parseDataValidations(document1),
|
|
4666
5709
|
conditionalFormats: readXlsxConditionalFormats(document1, differentialFormats),
|
|
@@ -4675,6 +5718,7 @@ async function readXlsxSheetFeaturesFromPackage(archive, worksheetScans) {
|
|
|
4675
5718
|
}
|
|
4676
5719
|
function emptyXlsxSheetFeatures() {
|
|
4677
5720
|
return {
|
|
5721
|
+
directCellStyles: [],
|
|
4678
5722
|
validations: [],
|
|
4679
5723
|
conditionalFormats: [],
|
|
4680
5724
|
protection: {
|
|
@@ -4698,17 +5742,18 @@ async function patchXlsxSheetFeatures(buffer, content) {
|
|
|
4698
5742
|
pageSetup.sheetId,
|
|
4699
5743
|
pageSetup
|
|
4700
5744
|
]));
|
|
4701
|
-
if (!sheets.some((sheet)=>sheet.frozen || Object.keys(sheet.dataVerification ?? {}).length || sheet.dataValidationRanges?.length || sheet.luckysheet_conditionformat_save?.length || sheetHasProtectionState(sheet) || Boolean(sheet.id && (pageBreaksBySheetId.get(sheet.id)?.rows?.length ?? 0) + (pageBreaksBySheetId.get(sheet.id)?.columns?.length ?? 0)) || Boolean(sheet.id && pageSetupsBySheetId.has(sheet.id)))) return buffer;
|
|
5745
|
+
if (!sheets.some((sheet)=>sheet.frozen || Object.keys(sheet.dataVerification ?? {}).length || sheet.dataValidationRanges?.length || sheet.luckysheet_conditionformat_save?.length || sheetHasDirectCellStyles(sheet) || sheetHasProtectionState(sheet) || Boolean(sheet.id && (pageBreaksBySheetId.get(sheet.id)?.rows?.length ?? 0) + (pageBreaksBySheetId.get(sheet.id)?.columns?.length ?? 0)) || Boolean(sheet.id && pageSetupsBySheetId.has(sheet.id)))) return buffer;
|
|
4702
5746
|
const archive = await work_ooxml_package_OoxmlPackage.load(buffer);
|
|
4703
5747
|
const worksheetParts = await work_xlsx_interop_readWorksheetParts(archive);
|
|
4704
5748
|
const zip = await jszip.loadAsync(buffer);
|
|
4705
5749
|
const styles = archive.has('xl/styles.xml') ? await archive.xml('xl/styles.xml') : null;
|
|
4706
5750
|
const differentialFormats = styles ? new XlsxDifferentialFormatWriter(styles) : void 0;
|
|
5751
|
+
const directCellStyles = styles ? new XlsxDirectCellStyleWriter(styles) : void 0;
|
|
4707
5752
|
const cellProtection = styles ? new XlsxCellProtectionWriter(styles) : void 0;
|
|
4708
5753
|
for (const sheet of sheets){
|
|
4709
5754
|
const pageBreaks = sheet.id ? pageBreaksBySheetId.get(sheet.id) : void 0;
|
|
4710
5755
|
const pageSetup = sheet.id ? pageSetupsBySheetId.get(sheet.id) : void 0;
|
|
4711
|
-
if (!sheet.frozen && !Object.keys(sheet.dataVerification ?? {}).length && !sheet.dataValidationRanges?.length && !sheet.luckysheet_conditionformat_save?.length && !sheetHasProtectionState(sheet) && !(pageBreaks?.rows?.length || pageBreaks?.columns?.length) && !pageSetup) continue;
|
|
5756
|
+
if (!sheet.frozen && !Object.keys(sheet.dataVerification ?? {}).length && !sheet.dataValidationRanges?.length && !sheet.luckysheet_conditionformat_save?.length && !sheetHasDirectCellStyles(sheet) && !sheetHasProtectionState(sheet) && !(pageBreaks?.rows?.length || pageBreaks?.columns?.length) && !pageSetup) continue;
|
|
4712
5757
|
const exportedName = sheet.name.slice(0, 31) || '工作表';
|
|
4713
5758
|
const partPath = worksheetParts.get(exportedName);
|
|
4714
5759
|
const entry = partPath ? zip.file(partPath) : null;
|
|
@@ -4717,12 +5762,13 @@ async function patchXlsxSheetFeatures(buffer, content) {
|
|
|
4717
5762
|
if (sheet.frozen) writeFrozenPane(document1, sheet.frozen);
|
|
4718
5763
|
writeDataValidations(document1, sheet.dataVerification, sheet.dataValidationRanges);
|
|
4719
5764
|
writeXlsxConditionalFormats(document1, sheet.luckysheet_conditionformat_save, differentialFormats);
|
|
5765
|
+
if (directCellStyles) writeXlsxDirectCellStyles(document1, sheet, directCellStyles);
|
|
4720
5766
|
writeXlsxProtection(document1, sheet, cellProtection);
|
|
4721
5767
|
writeXlsxPageSetup(document1, pageSetup);
|
|
4722
5768
|
writeXlsxManualPageBreaks(document1, pageBreaks);
|
|
4723
5769
|
zip.file(partPath, new XMLSerializer().serializeToString(document1));
|
|
4724
5770
|
}
|
|
4725
|
-
if (differentialFormats?.changed || cellProtection?.changed) zip.file('xl/styles.xml',
|
|
5771
|
+
if (styles && (differentialFormats?.changed || directCellStyles?.changed || cellProtection?.changed)) zip.file('xl/styles.xml', new XMLSerializer().serializeToString(styles));
|
|
4726
5772
|
return zip.generateAsync({
|
|
4727
5773
|
type: 'arraybuffer',
|
|
4728
5774
|
compression: 'DEFLATE'
|
|
@@ -6004,6 +7050,7 @@ function xlsxCellStyle(cell) {
|
|
|
6004
7050
|
font: {
|
|
6005
7051
|
bold: Boolean(cell.bl),
|
|
6006
7052
|
italic: Boolean(cell.it),
|
|
7053
|
+
strike: Boolean(cell.cl),
|
|
6007
7054
|
underline: Boolean(cell.un),
|
|
6008
7055
|
name: cell.ff,
|
|
6009
7056
|
sz: cell.fs,
|
|
@@ -6585,6 +7632,10 @@ async function importWorkSpreadsheetFile(file, extension, context) {
|
|
|
6585
7632
|
if (!worksheet) continue;
|
|
6586
7633
|
const plainWorksheet = packageScanResult?.plainWorksheets?.[name];
|
|
6587
7634
|
const features = sheetFeatures.get(name);
|
|
7635
|
+
const directCellStyles = new Map((features?.directCellStyles ?? []).map((entry)=>[
|
|
7636
|
+
spreadsheetCellKey(entry.row, entry.column),
|
|
7637
|
+
entry
|
|
7638
|
+
]));
|
|
6588
7639
|
const range = safeSpreadsheetRange(worksheet, XLSX);
|
|
6589
7640
|
let rowCount = Math.max(plainWorksheet?.rowCount ?? range.e.r + 1, 40);
|
|
6590
7641
|
let columnCount = Math.max(plainWorksheet?.columnCount ?? range.e.c + 1, 12);
|
|
@@ -6611,8 +7662,10 @@ async function importWorkSpreadsheetFile(file, extension, context) {
|
|
|
6611
7662
|
const comment = importXlsxCellComment(source.c);
|
|
6612
7663
|
updateSpreadsheetWorksheetCompatibilitySummary(compatibilitySummary, source);
|
|
6613
7664
|
if (hyperlink) hyperlinks[`${row}_${column}`] = hyperlink;
|
|
7665
|
+
const directCellStyle = directCellStyles.get(spreadsheetCellKey(row, column));
|
|
7666
|
+
directCellStyles.delete(spreadsheetCellKey(row, column));
|
|
6614
7667
|
data[row] ??= [];
|
|
6615
|
-
data[row][column] = freezeImportedSpreadsheetCell(fortuneCellFromXlsx(source, row, column, id, hyperlink, comment, XLSX));
|
|
7668
|
+
data[row][column] = freezeImportedSpreadsheetCell(fortuneCellFromXlsx(source, row, column, id, hyperlink, comment, XLSX, directCellStyle?.style));
|
|
6616
7669
|
if (source.f) formulaCells.push({
|
|
6617
7670
|
column,
|
|
6618
7671
|
row
|
|
@@ -6625,10 +7678,26 @@ async function importWorkSpreadsheetFile(file, extension, context) {
|
|
|
6625
7678
|
}
|
|
6626
7679
|
releaseImportedWorksheetCells(worksheet);
|
|
6627
7680
|
}
|
|
7681
|
+
for (const { column, row, style } of directCellStyles.values()){
|
|
7682
|
+
rowCount = Math.max(rowCount, row + 1);
|
|
7683
|
+
columnCount = Math.max(columnCount, column + 1);
|
|
7684
|
+
data[row] ??= [];
|
|
7685
|
+
const existing = data[row][column];
|
|
7686
|
+
data[row][column] = freezeImportedSpreadsheetCell({
|
|
7687
|
+
...existing ?? {},
|
|
7688
|
+
...style
|
|
7689
|
+
});
|
|
7690
|
+
if (!existing) entryIndex += 1;
|
|
7691
|
+
}
|
|
6628
7692
|
populatedCellCount += entryIndex;
|
|
6629
7693
|
worksheetCompatibility.set(name, compatibilitySummary);
|
|
6630
7694
|
data.length = Math.max(data.length, rowCount);
|
|
6631
7695
|
const config = fortuneSheetConfig(worksheet);
|
|
7696
|
+
const importedBorderInfo = fortuneBorderInfoFromXlsxCells(features?.directCellStyles ?? []);
|
|
7697
|
+
if (importedBorderInfo.length) config.borderInfo = [
|
|
7698
|
+
...Array.isArray(config.borderInfo) ? config.borderInfo : [],
|
|
7699
|
+
...importedBorderInfo
|
|
7700
|
+
];
|
|
6632
7701
|
registerImportedSpreadsheetMatrix(data, {
|
|
6633
7702
|
columnCount,
|
|
6634
7703
|
formulaCells,
|
|
@@ -6807,8 +7876,11 @@ function fortuneSheetConfig(worksheet) {
|
|
|
6807
7876
|
}
|
|
6808
7877
|
return config;
|
|
6809
7878
|
}
|
|
6810
|
-
function fortuneCellFromXlsx(source, row, column, sheetId, hyperlink, comment, XLSX) {
|
|
6811
|
-
const cell =
|
|
7879
|
+
function fortuneCellFromXlsx(source, row, column, sheetId, hyperlink, comment, XLSX, directStyle) {
|
|
7880
|
+
const cell = {
|
|
7881
|
+
...fortuneCellStyle(source),
|
|
7882
|
+
...directStyle
|
|
7883
|
+
};
|
|
6812
7884
|
if (void 0 !== source.v) cell.v = source.v;
|
|
6813
7885
|
const displayText = fortuneCellDisplayText(source, XLSX);
|
|
6814
7886
|
if (void 0 !== displayText) cell.m = displayText;
|
|
@@ -6825,6 +7897,9 @@ function fortuneCellFromXlsx(source, row, column, sheetId, hyperlink, comment, X
|
|
|
6825
7897
|
}
|
|
6826
7898
|
return cell;
|
|
6827
7899
|
}
|
|
7900
|
+
function spreadsheetCellKey(row, column) {
|
|
7901
|
+
return `${row}_${column}`;
|
|
7902
|
+
}
|
|
6828
7903
|
function fortuneCellStyle(source) {
|
|
6829
7904
|
const style = source.s;
|
|
6830
7905
|
const font = style && 'object' == typeof style ? style.font : void 0;
|
|
@@ -6833,6 +7908,7 @@ function fortuneCellStyle(source) {
|
|
|
6833
7908
|
const target = {};
|
|
6834
7909
|
if (font?.bold) target.bl = 1;
|
|
6835
7910
|
if (font?.italic) target.it = 1;
|
|
7911
|
+
if (font?.strike) target.cl = 1;
|
|
6836
7912
|
if (font?.underline) target.un = 1;
|
|
6837
7913
|
if (font?.name) target.ff = font.name;
|
|
6838
7914
|
if (font?.sz !== void 0) target.fs = font.sz;
|