@odoo/o-spreadsheet 16.2.0 → 16.2.2
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/dist/o-spreadsheet.cjs.js +278 -181
- package/dist/o-spreadsheet.d.ts +116 -93
- package/dist/o-spreadsheet.esm.js +278 -181
- package/dist/o-spreadsheet.iife.js +278 -181
- package/dist/o-spreadsheet.iife.min.js +242 -243
- package/package.json +3 -3
|
@@ -113,88 +113,88 @@
|
|
|
113
113
|
const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
|
|
114
114
|
const BACKGROUND_HEADER_SELECTED_FILTER_COLOR = "#CEEAD6";
|
|
115
115
|
const SEPARATOR_COLOR = "#E0E2E4";
|
|
116
|
-
// Color picker
|
|
116
|
+
// Color picker defaults as upper case HEX to match `toHex`helper
|
|
117
117
|
const COLOR_PICKER_DEFAULTS = [
|
|
118
118
|
"#000000",
|
|
119
119
|
"#434343",
|
|
120
120
|
"#666666",
|
|
121
121
|
"#999999",
|
|
122
|
-
"#
|
|
123
|
-
"#
|
|
124
|
-
"#
|
|
125
|
-
"#
|
|
126
|
-
"#
|
|
127
|
-
"#
|
|
122
|
+
"#B7B7B7",
|
|
123
|
+
"#CCCCCC",
|
|
124
|
+
"#D9D9D9",
|
|
125
|
+
"#EFEFEF",
|
|
126
|
+
"#F3F3F3",
|
|
127
|
+
"#FFFFFF",
|
|
128
128
|
"#980000",
|
|
129
|
-
"#
|
|
130
|
-
"#
|
|
131
|
-
"#
|
|
132
|
-
"#
|
|
133
|
-
"#
|
|
134
|
-
"#
|
|
135
|
-
"#
|
|
136
|
-
"#
|
|
137
|
-
"#
|
|
138
|
-
"#
|
|
139
|
-
"#
|
|
140
|
-
"#
|
|
141
|
-
"#
|
|
142
|
-
"#
|
|
143
|
-
"#
|
|
144
|
-
"#
|
|
145
|
-
"#
|
|
146
|
-
"#
|
|
147
|
-
"#
|
|
148
|
-
"#
|
|
149
|
-
"#
|
|
150
|
-
"#
|
|
151
|
-
"#
|
|
152
|
-
"#
|
|
153
|
-
"#
|
|
154
|
-
"#
|
|
155
|
-
"#
|
|
156
|
-
"#
|
|
157
|
-
"#
|
|
158
|
-
"#
|
|
159
|
-
"#
|
|
160
|
-
"#
|
|
161
|
-
"#
|
|
162
|
-
"#
|
|
163
|
-
"#
|
|
164
|
-
"#
|
|
165
|
-
"#
|
|
166
|
-
"#
|
|
167
|
-
"#
|
|
168
|
-
"#
|
|
169
|
-
"#
|
|
170
|
-
"#
|
|
171
|
-
"#
|
|
172
|
-
"#
|
|
173
|
-
"#
|
|
174
|
-
"#
|
|
175
|
-
"#
|
|
176
|
-
"#
|
|
177
|
-
"#
|
|
178
|
-
"#
|
|
129
|
+
"#FF0000",
|
|
130
|
+
"#FF9900",
|
|
131
|
+
"#FFFF00",
|
|
132
|
+
"#00FF00",
|
|
133
|
+
"#00FFFF",
|
|
134
|
+
"#4A86E8",
|
|
135
|
+
"#0000FF",
|
|
136
|
+
"#9900FF",
|
|
137
|
+
"#FF00FF",
|
|
138
|
+
"#E6B8AF",
|
|
139
|
+
"#F4CCCC",
|
|
140
|
+
"#FCE5CD",
|
|
141
|
+
"#FFF2CC",
|
|
142
|
+
"#D9EAD3",
|
|
143
|
+
"#D0E0E3",
|
|
144
|
+
"#C9DAF8",
|
|
145
|
+
"#CFE2F3",
|
|
146
|
+
"#D9D2E9",
|
|
147
|
+
"#EAD1DC",
|
|
148
|
+
"#DD7E6B",
|
|
149
|
+
"#EA9999",
|
|
150
|
+
"#F9CB9C",
|
|
151
|
+
"#FFE599",
|
|
152
|
+
"#B6D7A8",
|
|
153
|
+
"#A2C4C9",
|
|
154
|
+
"#A4C2F4",
|
|
155
|
+
"#9FC5E8",
|
|
156
|
+
"#B4A7D6",
|
|
157
|
+
"#D5A6BD",
|
|
158
|
+
"#CC4125",
|
|
159
|
+
"#E06666",
|
|
160
|
+
"#F6B26B",
|
|
161
|
+
"#FFD966",
|
|
162
|
+
"#93C47D",
|
|
163
|
+
"#76A5AF",
|
|
164
|
+
"#6D9EEB",
|
|
165
|
+
"#6FA8DC",
|
|
166
|
+
"#8E7CC3",
|
|
167
|
+
"#C27BA0",
|
|
168
|
+
"#A61C00",
|
|
169
|
+
"#CC0000",
|
|
170
|
+
"#E69138",
|
|
171
|
+
"#F1C232",
|
|
172
|
+
"#6AA84F",
|
|
173
|
+
"#45818E",
|
|
174
|
+
"#3C78D8",
|
|
175
|
+
"#3D85C6",
|
|
176
|
+
"#674EA7",
|
|
177
|
+
"#A64D79",
|
|
178
|
+
"#85200C",
|
|
179
179
|
"#990000",
|
|
180
|
-
"#
|
|
181
|
-
"#
|
|
182
|
-
"#
|
|
183
|
-
"#
|
|
184
|
-
"#
|
|
185
|
-
"#
|
|
186
|
-
"#
|
|
187
|
-
"#
|
|
188
|
-
"#
|
|
180
|
+
"#B45F06",
|
|
181
|
+
"#BF9000",
|
|
182
|
+
"#38761D",
|
|
183
|
+
"#134F5C",
|
|
184
|
+
"#1155CC",
|
|
185
|
+
"#0B5394",
|
|
186
|
+
"#351C75",
|
|
187
|
+
"#741B47",
|
|
188
|
+
"#5B0F00",
|
|
189
189
|
"#660000",
|
|
190
|
-
"#
|
|
191
|
-
"#
|
|
192
|
-
"#
|
|
193
|
-
"#
|
|
194
|
-
"#
|
|
190
|
+
"#783F04",
|
|
191
|
+
"#7F6000",
|
|
192
|
+
"#274E13",
|
|
193
|
+
"#0C343D",
|
|
194
|
+
"#1C4587",
|
|
195
195
|
"#073763",
|
|
196
|
-
"#
|
|
197
|
-
"#
|
|
196
|
+
"#20124D",
|
|
197
|
+
"#4C1130",
|
|
198
198
|
];
|
|
199
199
|
// Dimensions
|
|
200
200
|
const MIN_ROW_HEIGHT = 10;
|
|
@@ -234,7 +234,7 @@
|
|
|
234
234
|
const DEFAULT_BORDER_DESC = ["thin", "#000"];
|
|
235
235
|
const DEFAULT_FILTER_BORDER_DESC = ["thin", FILTERS_COLOR];
|
|
236
236
|
// DateTimeRegex
|
|
237
|
-
const DATETIME_FORMAT = /[
|
|
237
|
+
const DATETIME_FORMAT = /[ymdhs:]/;
|
|
238
238
|
// Ranges
|
|
239
239
|
const INCORRECT_RANGE_STRING = CellErrorType.InvalidReference;
|
|
240
240
|
// Max Number of history steps kept in memory
|
|
@@ -271,11 +271,12 @@
|
|
|
271
271
|
ComponentsImportance[ComponentsImportance["Highlight"] = 5] = "Highlight";
|
|
272
272
|
ComponentsImportance[ComponentsImportance["Figure"] = 10] = "Figure";
|
|
273
273
|
ComponentsImportance[ComponentsImportance["ScrollBar"] = 15] = "ScrollBar";
|
|
274
|
-
ComponentsImportance[ComponentsImportance["
|
|
274
|
+
ComponentsImportance[ComponentsImportance["GridPopover"] = 19] = "GridPopover";
|
|
275
275
|
ComponentsImportance[ComponentsImportance["GridComposer"] = 20] = "GridComposer";
|
|
276
|
-
ComponentsImportance[ComponentsImportance["
|
|
276
|
+
ComponentsImportance[ComponentsImportance["Dropdown"] = 21] = "Dropdown";
|
|
277
277
|
ComponentsImportance[ComponentsImportance["IconPicker"] = 25] = "IconPicker";
|
|
278
|
-
ComponentsImportance[ComponentsImportance["
|
|
278
|
+
ComponentsImportance[ComponentsImportance["TopBarComposer"] = 30] = "TopBarComposer";
|
|
279
|
+
ComponentsImportance[ComponentsImportance["Popover"] = 35] = "Popover";
|
|
279
280
|
ComponentsImportance[ComponentsImportance["ChartAnchor"] = 1000] = "ChartAnchor";
|
|
280
281
|
})(ComponentsImportance || (ComponentsImportance = {}));
|
|
281
282
|
const DEFAULT_SHEETVIEW_SIZE = 1000;
|
|
@@ -702,8 +703,9 @@
|
|
|
702
703
|
return DEFAULT_CELL_HEIGHT;
|
|
703
704
|
}
|
|
704
705
|
const fontSize = computeTextFontSizeInPixels(cell.style);
|
|
705
|
-
|
|
706
|
-
|
|
706
|
+
// the number of lines should be computed from the formula result, but it's not evaluated at this point
|
|
707
|
+
const numberOfLines = cell.isFormula ? 1 : cell.content.split(NEWLINE).length;
|
|
708
|
+
return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
|
|
707
709
|
}
|
|
708
710
|
function computeTextWidth(context, text, style) {
|
|
709
711
|
context.save();
|
|
@@ -1055,6 +1057,8 @@
|
|
|
1055
1057
|
return text;
|
|
1056
1058
|
}
|
|
1057
1059
|
|
|
1060
|
+
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
1061
|
+
const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/g;
|
|
1058
1062
|
const colors$1 = [
|
|
1059
1063
|
"#eb6d00",
|
|
1060
1064
|
"#0074d9",
|
|
@@ -1080,7 +1084,10 @@
|
|
|
1080
1084
|
}
|
|
1081
1085
|
/**
|
|
1082
1086
|
* Converts any CSS color value to a standardized hex6 value.
|
|
1083
|
-
* Accepts: hex3, hex6, hex8 and
|
|
1087
|
+
* Accepts: hex3, hex6, hex8, rgb[1] and rgba[1].
|
|
1088
|
+
*
|
|
1089
|
+
* [1] under the form rgb(r, g, b, a?) or rgba(r, g, b, a?)
|
|
1090
|
+
* with r,g,b ∈ [0, 255] and a ∈ [0, 1]
|
|
1084
1091
|
*
|
|
1085
1092
|
* toHex("#ABC")
|
|
1086
1093
|
* >> "#AABBCC"
|
|
@@ -1091,27 +1098,31 @@
|
|
|
1091
1098
|
* toHex("rgb(30, 80, 16)")
|
|
1092
1099
|
* >> "#1E5010"
|
|
1093
1100
|
*
|
|
1101
|
+
* * toHex("rgb(30, 80, 16, 0.5)")
|
|
1102
|
+
* >> "#1E501080"
|
|
1103
|
+
*
|
|
1094
1104
|
*/
|
|
1095
1105
|
function toHex(color) {
|
|
1096
|
-
|
|
1097
|
-
|
|
1106
|
+
let hexColor = color;
|
|
1107
|
+
if (color.startsWith("rgb")) {
|
|
1108
|
+
hexColor = rgbaStringToHex(color);
|
|
1098
1109
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1110
|
+
else {
|
|
1111
|
+
hexColor = color.replace("#", "").toUpperCase();
|
|
1112
|
+
if (hexColor.length === 3 || hexColor.length === 4) {
|
|
1113
|
+
hexColor = hexColor.split("").reduce((acc, h) => acc + h + h, "");
|
|
1114
|
+
}
|
|
1115
|
+
hexColor = `#${hexColor}`;
|
|
1105
1116
|
}
|
|
1106
|
-
if (
|
|
1107
|
-
throw new Error(
|
|
1117
|
+
if (!hexColor.match(HEX_MATCH)) {
|
|
1118
|
+
throw new Error(`invalid color input: ${color}`);
|
|
1108
1119
|
}
|
|
1109
|
-
return
|
|
1120
|
+
return hexColor;
|
|
1110
1121
|
}
|
|
1111
1122
|
function isColorValid(color) {
|
|
1112
1123
|
try {
|
|
1113
|
-
|
|
1114
|
-
return
|
|
1124
|
+
toHex(color);
|
|
1125
|
+
return true;
|
|
1115
1126
|
}
|
|
1116
1127
|
catch (error) {
|
|
1117
1128
|
return false;
|
|
@@ -1144,15 +1155,29 @@
|
|
|
1144
1155
|
/**
|
|
1145
1156
|
* Convert a CSS rgb color string to a standardized hex6 color value.
|
|
1146
1157
|
*
|
|
1147
|
-
*
|
|
1158
|
+
* rgbaStringToHex("rgb(30, 80, 16)")
|
|
1148
1159
|
* >> "#1E5010"
|
|
1160
|
+
*
|
|
1161
|
+
* rgbaStringToHex("rgba(30, 80, 16, 0.5)")
|
|
1162
|
+
* >> "#1E501080"
|
|
1163
|
+
*
|
|
1164
|
+
* DOES NOT SUPPORT NON INTEGER RGB VALUES
|
|
1149
1165
|
*/
|
|
1150
|
-
function
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1166
|
+
function rgbaStringToHex(color) {
|
|
1167
|
+
const stringVals = color.replace(RBA_REGEX, "").split(",");
|
|
1168
|
+
let alphaHex = 255;
|
|
1169
|
+
if (stringVals.length !== 3 && stringVals.length !== 4) {
|
|
1170
|
+
throw new Error("invalid color");
|
|
1171
|
+
}
|
|
1172
|
+
else if (stringVals.length === 4) {
|
|
1173
|
+
const alpha = parseFloat(stringVals.pop() || "1");
|
|
1174
|
+
alphaHex = Math.round((alpha || 1) * 255);
|
|
1175
|
+
}
|
|
1176
|
+
const vals = stringVals.map((val) => parseInt(val, 10));
|
|
1177
|
+
if (alphaHex !== 255) {
|
|
1178
|
+
vals.push(alphaHex);
|
|
1179
|
+
}
|
|
1180
|
+
return "#" + concat(vals.map((value) => value.toString(16).padStart(2, "0"))).toUpperCase();
|
|
1156
1181
|
}
|
|
1157
1182
|
/**
|
|
1158
1183
|
* RGBA to HEX representation (#RRGGBBAA).
|
|
@@ -1174,7 +1199,7 @@
|
|
|
1174
1199
|
a = "0" + a;
|
|
1175
1200
|
if (a === "ff")
|
|
1176
1201
|
a = "";
|
|
1177
|
-
return "#" + r + g + b + a;
|
|
1202
|
+
return ("#" + r + g + b + a).toUpperCase();
|
|
1178
1203
|
}
|
|
1179
1204
|
/**
|
|
1180
1205
|
* Color string to RGBA representation
|
|
@@ -1295,6 +1320,9 @@
|
|
|
1295
1320
|
s = +(s * 100).toFixed(1);
|
|
1296
1321
|
l = +(l * 100).toFixed(1);
|
|
1297
1322
|
return { a: rgba.a, h, s, l };
|
|
1323
|
+
}
|
|
1324
|
+
function isSameColor(color1, color2) {
|
|
1325
|
+
return isColorValid(color1) && isColorValid(color2) && toHex(color1) === toHex(color2);
|
|
1298
1326
|
}
|
|
1299
1327
|
|
|
1300
1328
|
/** Reference of a cell (eg. A1, $B$5) */
|
|
@@ -1446,7 +1474,7 @@
|
|
|
1446
1474
|
* formula, commas are used to separate arguments
|
|
1447
1475
|
* - it does not support % symbol, in formulas % is an operator
|
|
1448
1476
|
*/
|
|
1449
|
-
const formulaNumberRegexp =
|
|
1477
|
+
const formulaNumberRegexp = /(^-?\d+(\.?\d*(e\d+)?)?|^-?\.\d+)(?!\w|!)/;
|
|
1450
1478
|
const pIntegerAndDecimals = "(\\d+(,\\d{3,})*(\\.\\d*)?)"; // pattern that match integer number with or without decimal digits
|
|
1451
1479
|
const pOnlyDecimals = "(\\.\\d+)"; // pattern that match only expression with decimal digits
|
|
1452
1480
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -3052,6 +3080,7 @@
|
|
|
3052
3080
|
const LINE_HEIGHT = 1.2;
|
|
3053
3081
|
css /* scss */ `
|
|
3054
3082
|
div.o-scorecard {
|
|
3083
|
+
font-family: ${DEFAULT_FONT};
|
|
3055
3084
|
user-select: none;
|
|
3056
3085
|
background-color: white;
|
|
3057
3086
|
display: flex;
|
|
@@ -5102,6 +5131,11 @@
|
|
|
5102
5131
|
this.currentPosition = newPosition;
|
|
5103
5132
|
});
|
|
5104
5133
|
}
|
|
5134
|
+
get popoverStyle() {
|
|
5135
|
+
return cssPropertiesToCss({
|
|
5136
|
+
"z-index": `${this.props.zIndex}`,
|
|
5137
|
+
});
|
|
5138
|
+
}
|
|
5105
5139
|
}
|
|
5106
5140
|
Popover.template = "o-spreadsheet-Popover";
|
|
5107
5141
|
Popover.defaultProps = {
|
|
@@ -5110,6 +5144,7 @@
|
|
|
5110
5144
|
onMouseWheel: () => { },
|
|
5111
5145
|
onPopoverMoved: () => { },
|
|
5112
5146
|
onPopoverHidden: () => { },
|
|
5147
|
+
zIndex: ComponentsImportance.Popover,
|
|
5113
5148
|
};
|
|
5114
5149
|
Popover.props = {
|
|
5115
5150
|
anchorRect: Object,
|
|
@@ -5121,6 +5156,7 @@
|
|
|
5121
5156
|
onMouseWheel: { type: Function, optional: true },
|
|
5122
5157
|
onPopoverHidden: { type: Function, optional: true },
|
|
5123
5158
|
onPopoverMoved: { type: Function, optional: true },
|
|
5159
|
+
zIndex: { type: Number, optional: true },
|
|
5124
5160
|
slots: Object,
|
|
5125
5161
|
};
|
|
5126
5162
|
class PopoverPositionContext {
|
|
@@ -17011,6 +17047,9 @@
|
|
|
17011
17047
|
top,
|
|
17012
17048
|
});
|
|
17013
17049
|
}
|
|
17050
|
+
isSameColor(color1, color2) {
|
|
17051
|
+
return isSameColor(color1, color2);
|
|
17052
|
+
}
|
|
17014
17053
|
}
|
|
17015
17054
|
ColorPicker.template = "o-spreadsheet-ColorPicker";
|
|
17016
17055
|
ColorPicker.defaultProps = {
|
|
@@ -19252,6 +19291,8 @@
|
|
|
19252
19291
|
start = 0;
|
|
19253
19292
|
if (end > textLength)
|
|
19254
19293
|
end = textLength;
|
|
19294
|
+
if (start > textLength)
|
|
19295
|
+
start = textLength;
|
|
19255
19296
|
}
|
|
19256
19297
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
19257
19298
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
@@ -19521,6 +19562,7 @@
|
|
|
19521
19562
|
padding-right: 2px;
|
|
19522
19563
|
|
|
19523
19564
|
box-sizing: border-box;
|
|
19565
|
+
font-family: ${DEFAULT_FONT};
|
|
19524
19566
|
|
|
19525
19567
|
caret-color: black;
|
|
19526
19568
|
padding-left: 3px;
|
|
@@ -20731,6 +20773,9 @@
|
|
|
20731
20773
|
owl.onMounted(() => {
|
|
20732
20774
|
resizeObserver.observe(this.gridOverlayEl);
|
|
20733
20775
|
});
|
|
20776
|
+
owl.onWillUnmount(() => {
|
|
20777
|
+
resizeObserver.disconnect();
|
|
20778
|
+
});
|
|
20734
20779
|
useTouchMove(this.gridOverlay, this.props.onGridMoved, () => {
|
|
20735
20780
|
const { scrollY } = this.env.model.getters.getActiveSheetDOMScrollInfo();
|
|
20736
20781
|
return scrollY > 0;
|
|
@@ -20787,6 +20832,10 @@
|
|
|
20787
20832
|
};
|
|
20788
20833
|
|
|
20789
20834
|
class GridPopover extends owl.Component {
|
|
20835
|
+
constructor() {
|
|
20836
|
+
super(...arguments);
|
|
20837
|
+
this.zIndex = ComponentsImportance.GridPopover;
|
|
20838
|
+
}
|
|
20790
20839
|
get cellPopover() {
|
|
20791
20840
|
const popover = this.env.model.getters.getCellPopover(this.props.hoveredCell);
|
|
20792
20841
|
if (!popover.isOpen) {
|
|
@@ -22151,6 +22200,10 @@
|
|
|
22151
22200
|
}
|
|
22152
22201
|
}
|
|
22153
22202
|
onInput(ev) {
|
|
22203
|
+
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
22204
|
+
if (!ev.isComposing && ev.inputType === "insertFromPaste") {
|
|
22205
|
+
return;
|
|
22206
|
+
}
|
|
22154
22207
|
if (ev.data) {
|
|
22155
22208
|
// if the user types a character on the grid, it means he wants to start composing the selected cell with that
|
|
22156
22209
|
// character
|
|
@@ -22999,6 +23052,70 @@
|
|
|
22999
23052
|
});
|
|
23000
23053
|
}
|
|
23001
23054
|
|
|
23055
|
+
const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
|
|
23056
|
+
/**
|
|
23057
|
+
* Convert excel format to o_spreadsheet format
|
|
23058
|
+
*
|
|
23059
|
+
* Excel format are defined in openXML §18.8.31
|
|
23060
|
+
*/
|
|
23061
|
+
function convertXlsxFormat(numFmtId, formats, warningManager) {
|
|
23062
|
+
var _a, _b, _c;
|
|
23063
|
+
if (numFmtId === 0) {
|
|
23064
|
+
return undefined;
|
|
23065
|
+
}
|
|
23066
|
+
// Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
|
|
23067
|
+
let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
|
|
23068
|
+
if (format) {
|
|
23069
|
+
try {
|
|
23070
|
+
let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
|
|
23071
|
+
convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
|
|
23072
|
+
convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
|
|
23073
|
+
// Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
|
|
23074
|
+
const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
23075
|
+
const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
|
|
23076
|
+
if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
|
|
23077
|
+
throw new Error("Multiple escaped blocks in format");
|
|
23078
|
+
}
|
|
23079
|
+
convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
|
|
23080
|
+
convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore width of next char for align purposes. Not supported ATM
|
|
23081
|
+
convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
|
|
23082
|
+
convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
|
|
23083
|
+
convertedFormat = convertedFormat.replace(/\\./g, (match) => match[1]); // unescape other characters
|
|
23084
|
+
if (isXlsxDateFormat(convertedFormat)) {
|
|
23085
|
+
convertedFormat = convertDateFormat$1(convertedFormat);
|
|
23086
|
+
}
|
|
23087
|
+
if (isFormatSupported(convertedFormat)) {
|
|
23088
|
+
return convertedFormat;
|
|
23089
|
+
}
|
|
23090
|
+
}
|
|
23091
|
+
catch (e) { }
|
|
23092
|
+
}
|
|
23093
|
+
warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
|
|
23094
|
+
return undefined;
|
|
23095
|
+
}
|
|
23096
|
+
function isFormatSupported(format) {
|
|
23097
|
+
try {
|
|
23098
|
+
formatValue(0, format);
|
|
23099
|
+
return true;
|
|
23100
|
+
}
|
|
23101
|
+
catch (e) {
|
|
23102
|
+
return false;
|
|
23103
|
+
}
|
|
23104
|
+
}
|
|
23105
|
+
function isXlsxDateFormat(format) {
|
|
23106
|
+
return format.match(XLSX_DATE_FORMAT_REGEX) !== null;
|
|
23107
|
+
}
|
|
23108
|
+
function convertDateFormat$1(format) {
|
|
23109
|
+
// Some of these aren't defined neither in the OpenXML spec not the Xlsx extension of OpenXML,
|
|
23110
|
+
// but can still occur and are supported by Excel/Google sheets
|
|
23111
|
+
format = format.toLowerCase();
|
|
23112
|
+
format = format.replace(/mmmmm/g, "mmm");
|
|
23113
|
+
format = format.replace(/am\/pm|a\/m/g, "a");
|
|
23114
|
+
format = format.replace(/hhhh/g, "hh");
|
|
23115
|
+
format = format.replace(/\bh\b/g, "hh");
|
|
23116
|
+
return format;
|
|
23117
|
+
}
|
|
23118
|
+
|
|
23002
23119
|
function convertBorders(data, warningManager) {
|
|
23003
23120
|
const borderArray = data.borders.map((border) => {
|
|
23004
23121
|
addBorderWarnings(border, warningManager);
|
|
@@ -23061,41 +23178,6 @@
|
|
|
23061
23178
|
}
|
|
23062
23179
|
return arrayToObject(formats, 1);
|
|
23063
23180
|
}
|
|
23064
|
-
/**
|
|
23065
|
-
* Convert excel format to o_spreadsheet format
|
|
23066
|
-
*
|
|
23067
|
-
* Excel format are defined in openXML §18.8.31
|
|
23068
|
-
*/
|
|
23069
|
-
function convertXlsxFormat(numFmtId, formats, warningManager) {
|
|
23070
|
-
var _a, _b, _c;
|
|
23071
|
-
if (numFmtId === 0) {
|
|
23072
|
-
return undefined;
|
|
23073
|
-
}
|
|
23074
|
-
// Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
|
|
23075
|
-
let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
|
|
23076
|
-
if (format) {
|
|
23077
|
-
try {
|
|
23078
|
-
let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
|
|
23079
|
-
convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
|
|
23080
|
-
convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
|
|
23081
|
-
// Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
|
|
23082
|
-
const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
23083
|
-
const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
|
|
23084
|
-
if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
|
|
23085
|
-
throw new Error("Multiple escaped blocks in format");
|
|
23086
|
-
}
|
|
23087
|
-
convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
|
|
23088
|
-
convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore with of next char for align purposes. Not supported ATM
|
|
23089
|
-
convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
|
|
23090
|
-
convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
|
|
23091
|
-
formatValue(0, convertedFormat);
|
|
23092
|
-
return convertedFormat;
|
|
23093
|
-
}
|
|
23094
|
-
catch (e) { }
|
|
23095
|
-
}
|
|
23096
|
-
warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
|
|
23097
|
-
return undefined;
|
|
23098
|
-
}
|
|
23099
23181
|
// ---------------------------------------------------------------------------
|
|
23100
23182
|
// Warnings
|
|
23101
23183
|
// ---------------------------------------------------------------------------
|
|
@@ -30087,6 +30169,7 @@
|
|
|
30087
30169
|
}
|
|
30088
30170
|
else if (range.zone[start] >= min && range.zone[end] <= max) {
|
|
30089
30171
|
changeType = "REMOVE";
|
|
30172
|
+
newRange = range.clone({ ...this.getInvalidRange() });
|
|
30090
30173
|
}
|
|
30091
30174
|
else if (range.zone[start] <= max && range.zone[end] >= max) {
|
|
30092
30175
|
const toRemove = max - range.zone[start] + 1;
|
|
@@ -30152,8 +30235,10 @@
|
|
|
30152
30235
|
return { changeType: "NONE" };
|
|
30153
30236
|
}
|
|
30154
30237
|
const invalidSheetName = this.getters.getSheetName(cmd.sheetId);
|
|
30155
|
-
|
|
30156
|
-
|
|
30238
|
+
range = range.clone({
|
|
30239
|
+
...this.getInvalidRange(),
|
|
30240
|
+
invalidSheetName,
|
|
30241
|
+
});
|
|
30157
30242
|
return { changeType: "REMOVE", range };
|
|
30158
30243
|
}, cmd.sheetId);
|
|
30159
30244
|
break;
|
|
@@ -30413,6 +30498,15 @@
|
|
|
30413
30498
|
}
|
|
30414
30499
|
return str;
|
|
30415
30500
|
}
|
|
30501
|
+
getInvalidRange() {
|
|
30502
|
+
return {
|
|
30503
|
+
parts: [],
|
|
30504
|
+
prefixSheet: false,
|
|
30505
|
+
zone: { left: -1, top: -1, right: -1, bottom: -1 },
|
|
30506
|
+
sheetId: "",
|
|
30507
|
+
invalidXc: INCORRECT_RANGE_STRING,
|
|
30508
|
+
};
|
|
30509
|
+
}
|
|
30416
30510
|
}
|
|
30417
30511
|
RangeAdapter.getters = [
|
|
30418
30512
|
"getRangeString",
|
|
@@ -31382,9 +31476,7 @@
|
|
|
31382
31476
|
// remove duplicates first to check validity on a reduced
|
|
31383
31477
|
// set of colors, then normalize to HEX and remove duplicates
|
|
31384
31478
|
// again
|
|
31385
|
-
[...new Set([...usedColors, ...this.customColors])]
|
|
31386
|
-
.filter(isColorValid)
|
|
31387
|
-
.map((c) => toHex(c).toLowerCase())),
|
|
31479
|
+
[...new Set([...usedColors, ...this.customColors])].filter(isColorValid).map(toHex)),
|
|
31388
31480
|
]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
|
|
31389
31481
|
}
|
|
31390
31482
|
getColorsFromCells(cells) {
|
|
@@ -31445,7 +31537,7 @@
|
|
|
31445
31537
|
return [...chartsColors];
|
|
31446
31538
|
}
|
|
31447
31539
|
tryToAddColor(color) {
|
|
31448
|
-
const formattedColor = toHex(color)
|
|
31540
|
+
const formattedColor = toHex(color);
|
|
31449
31541
|
if (color && !COLOR_PICKER_DEFAULTS.includes(formattedColor)) {
|
|
31450
31542
|
this.customColors.add(formattedColor);
|
|
31451
31543
|
}
|
|
@@ -32460,8 +32552,8 @@
|
|
|
32460
32552
|
this.getters = getters;
|
|
32461
32553
|
this.sheetId = sheetId;
|
|
32462
32554
|
this.boundaries = boundaries;
|
|
32463
|
-
this.
|
|
32464
|
-
this.
|
|
32555
|
+
this.viewportWidth = sizeInGrid.width;
|
|
32556
|
+
this.viewportHeight = sizeInGrid.height;
|
|
32465
32557
|
this.offsetScrollbarX = offsets.x;
|
|
32466
32558
|
this.offsetScrollbarY = offsets.y;
|
|
32467
32559
|
this.canScrollVertically = options.canScrollVertically;
|
|
@@ -32472,6 +32564,10 @@
|
|
|
32472
32564
|
this.adjustViewportOffsetY();
|
|
32473
32565
|
}
|
|
32474
32566
|
// PUBLIC
|
|
32567
|
+
/** Returns the maximum size (in Pixels) of the viewport relative to its allocated client size
|
|
32568
|
+
* When the viewport grid size is smaller than its client width (resp. height), it will return
|
|
32569
|
+
* the client width (resp. height).
|
|
32570
|
+
*/
|
|
32475
32571
|
getMaxSize() {
|
|
32476
32572
|
const lastCol = this.getters.findLastVisibleColRowIndex(this.sheetId, "COL", {
|
|
32477
32573
|
first: this.boundaries.left,
|
|
@@ -32483,20 +32579,24 @@
|
|
|
32483
32579
|
});
|
|
32484
32580
|
const { end: lastColEnd, size: lastColSize } = this.getters.getColDimensions(this.sheetId, lastCol);
|
|
32485
32581
|
const { end: lastRowEnd, size: lastRowSize } = this.getters.getRowDimensions(this.sheetId, lastRow);
|
|
32486
|
-
const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.
|
|
32582
|
+
const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.viewportWidth, 0);
|
|
32487
32583
|
const leftColSize = this.getters.getColSize(this.sheetId, leftColIndex);
|
|
32488
|
-
const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.
|
|
32584
|
+
const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.viewportHeight, 0);
|
|
32489
32585
|
const topRowSize = this.getters.getRowSize(this.sheetId, leftRowIndex);
|
|
32490
|
-
|
|
32491
|
-
|
|
32492
|
-
(
|
|
32493
|
-
|
|
32494
|
-
|
|
32495
|
-
|
|
32496
|
-
|
|
32497
|
-
|
|
32498
|
-
|
|
32499
|
-
|
|
32586
|
+
let width = lastColEnd - this.offsetCorrectionX;
|
|
32587
|
+
if (this.canScrollHorizontally) {
|
|
32588
|
+
width += Math.max(DEFAULT_CELL_WIDTH, // leave some minimal space to let the user know they scrolled all the way
|
|
32589
|
+
Math.min(leftColSize, this.viewportWidth - lastColSize) // Add pixels that allows the snapping at maximum horizontal scroll
|
|
32590
|
+
);
|
|
32591
|
+
width = Math.max(width, this.viewportWidth); // if the viewport grid size is smaller than its client width, return client width
|
|
32592
|
+
}
|
|
32593
|
+
let height = lastRowEnd - this.offsetCorrectionY;
|
|
32594
|
+
if (this.canScrollVertically) {
|
|
32595
|
+
height += Math.max(DEFAULT_CELL_HEIGHT + 5, // leave some space to let the user know they scrolled all the way
|
|
32596
|
+
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
32597
|
+
);
|
|
32598
|
+
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
32599
|
+
}
|
|
32500
32600
|
return { width, height };
|
|
32501
32601
|
}
|
|
32502
32602
|
/**
|
|
@@ -32505,7 +32605,7 @@
|
|
|
32505
32605
|
* It returns -1 if no column is found.
|
|
32506
32606
|
*/
|
|
32507
32607
|
getColIndex(x, absolute = false) {
|
|
32508
|
-
if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.
|
|
32608
|
+
if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.viewportWidth) {
|
|
32509
32609
|
return -1;
|
|
32510
32610
|
}
|
|
32511
32611
|
return this.searchHeaderIndex("COL", x - this.offsetCorrectionX, this.left, absolute);
|
|
@@ -32516,7 +32616,7 @@
|
|
|
32516
32616
|
* It returns -1 if no row is found.
|
|
32517
32617
|
*/
|
|
32518
32618
|
getRowIndex(y, absolute = false) {
|
|
32519
|
-
if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.
|
|
32619
|
+
if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.viewportHeight) {
|
|
32520
32620
|
return -1;
|
|
32521
32621
|
}
|
|
32522
32622
|
return this.searchHeaderIndex("ROW", y - this.offsetCorrectionY, this.top, absolute);
|
|
@@ -32543,7 +32643,7 @@
|
|
|
32543
32643
|
adjustPositionX(col) {
|
|
32544
32644
|
const sheetId = this.sheetId;
|
|
32545
32645
|
const { start, end } = this.getters.getColDimensions(sheetId, col);
|
|
32546
|
-
while (end > this.offsetX + this.offsetCorrectionX + this.
|
|
32646
|
+
while (end > this.offsetX + this.offsetCorrectionX + this.viewportWidth &&
|
|
32547
32647
|
this.offsetX + this.offsetCorrectionX < start) {
|
|
32548
32648
|
this.offsetX = this.getters.getColDimensions(sheetId, this.left).end - this.offsetCorrectionX;
|
|
32549
32649
|
this.offsetScrollbarX = this.offsetX;
|
|
@@ -32565,7 +32665,7 @@
|
|
|
32565
32665
|
adjustPositionY(row) {
|
|
32566
32666
|
const sheetId = this.sheetId;
|
|
32567
32667
|
while (this.getters.getRowDimensions(sheetId, row).end >
|
|
32568
|
-
this.offsetY + this.
|
|
32668
|
+
this.offsetY + this.viewportHeight + this.offsetCorrectionY &&
|
|
32569
32669
|
this.offsetY + this.offsetCorrectionY < this.getters.getRowDimensions(sheetId, row).start) {
|
|
32570
32670
|
this.offsetY = this.getters.getRowDimensions(sheetId, this.top).end - this.offsetCorrectionY;
|
|
32571
32671
|
this.offsetScrollbarY = this.offsetY;
|
|
@@ -32603,8 +32703,8 @@
|
|
|
32603
32703
|
const x = this.getters.getColRowOffset("COL", this.zone.left, targetZone.left) +
|
|
32604
32704
|
this.offsetCorrectionX;
|
|
32605
32705
|
const y = this.getters.getColRowOffset("ROW", this.zone.top, targetZone.top) + this.offsetCorrectionY;
|
|
32606
|
-
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.
|
|
32607
|
-
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.
|
|
32706
|
+
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
|
|
32707
|
+
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
|
|
32608
32708
|
return {
|
|
32609
32709
|
x,
|
|
32610
32710
|
y,
|
|
@@ -32667,12 +32767,12 @@
|
|
|
32667
32767
|
adjustViewportOffsetX() {
|
|
32668
32768
|
if (this.canScrollHorizontally) {
|
|
32669
32769
|
const { width: viewportWidth } = this.getMaxSize();
|
|
32670
|
-
if (this.
|
|
32671
|
-
this.offsetScrollbarX = Math.max(0, viewportWidth - this.
|
|
32770
|
+
if (this.viewportWidth + this.offsetScrollbarX > viewportWidth) {
|
|
32771
|
+
this.offsetScrollbarX = Math.max(0, viewportWidth - this.viewportWidth);
|
|
32672
32772
|
}
|
|
32673
32773
|
}
|
|
32674
32774
|
this.left = this.getColIndex(this.offsetScrollbarX, true);
|
|
32675
|
-
this.right = this.getColIndex(this.offsetScrollbarX + this.
|
|
32775
|
+
this.right = this.getColIndex(this.offsetScrollbarX + this.viewportWidth, true);
|
|
32676
32776
|
if (this.right === -1) {
|
|
32677
32777
|
this.right = this.boundaries.right;
|
|
32678
32778
|
}
|
|
@@ -32684,12 +32784,12 @@
|
|
|
32684
32784
|
adjustViewportOffsetY() {
|
|
32685
32785
|
if (this.canScrollVertically) {
|
|
32686
32786
|
const { height: paneHeight } = this.getMaxSize();
|
|
32687
|
-
if (this.
|
|
32688
|
-
this.offsetScrollbarY = Math.max(0, paneHeight - this.
|
|
32787
|
+
if (this.viewportHeight + this.offsetScrollbarY > paneHeight) {
|
|
32788
|
+
this.offsetScrollbarY = Math.max(0, paneHeight - this.viewportHeight);
|
|
32689
32789
|
}
|
|
32690
32790
|
}
|
|
32691
32791
|
this.top = this.getRowIndex(this.offsetScrollbarY, true);
|
|
32692
|
-
this.bottom = this.getRowIndex(this.offsetScrollbarY + this.
|
|
32792
|
+
this.bottom = this.getRowIndex(this.offsetScrollbarY + this.viewportWidth, true);
|
|
32693
32793
|
if (this.bottom === -1) {
|
|
32694
32794
|
this.bottom = this.boundaries.bottom;
|
|
32695
32795
|
}
|
|
@@ -32700,7 +32800,7 @@
|
|
|
32700
32800
|
adjustViewportZoneX() {
|
|
32701
32801
|
const sheetId = this.sheetId;
|
|
32702
32802
|
this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
|
|
32703
|
-
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.
|
|
32803
|
+
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
|
|
32704
32804
|
if (this.right === -1) {
|
|
32705
32805
|
this.right = this.getters.getNumberCols(sheetId) - 1;
|
|
32706
32806
|
}
|
|
@@ -32713,7 +32813,7 @@
|
|
|
32713
32813
|
adjustViewportZoneY() {
|
|
32714
32814
|
const sheetId = this.sheetId;
|
|
32715
32815
|
this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
|
|
32716
|
-
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.
|
|
32816
|
+
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
|
|
32717
32817
|
if (this.bottom === -1) {
|
|
32718
32818
|
this.bottom = this.getters.getNumberRows(sheetId) - 1;
|
|
32719
32819
|
}
|
|
@@ -32976,8 +33076,7 @@
|
|
|
32976
33076
|
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
32977
33077
|
}
|
|
32978
33078
|
/**
|
|
32979
|
-
* Return the main viewport maximum size
|
|
32980
|
-
* with some bottom and right padding.
|
|
33079
|
+
* Return the main viewport maximum size relative to the client size.
|
|
32981
33080
|
*/
|
|
32982
33081
|
getMainViewportRect() {
|
|
32983
33082
|
const sheetId = this.getters.getActiveSheetId();
|
|
@@ -32993,8 +33092,8 @@
|
|
|
32993
33092
|
const { width, height } = this.getMainViewportRect();
|
|
32994
33093
|
const viewport = this.getMainInternalViewport(sheetId);
|
|
32995
33094
|
return {
|
|
32996
|
-
maxOffsetX: Math.max(0, width - viewport.
|
|
32997
|
-
maxOffsetY: Math.max(0, height - viewport.
|
|
33095
|
+
maxOffsetX: Math.max(0, width - viewport.viewportWidth + 1),
|
|
33096
|
+
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
32998
33097
|
};
|
|
32999
33098
|
}
|
|
33000
33099
|
getColRowOffsetInViewport(dimension, referenceIndex, index) {
|
|
@@ -40893,6 +40992,7 @@
|
|
|
40893
40992
|
this.state.menuState.parentMenu = menu;
|
|
40894
40993
|
this.isSelectingMenu = true;
|
|
40895
40994
|
this.openedEl = ev.target;
|
|
40995
|
+
this.env.model.dispatch("STOP_EDITION");
|
|
40896
40996
|
}
|
|
40897
40997
|
closeMenus() {
|
|
40898
40998
|
this.state.activeTool = "";
|
|
@@ -41106,9 +41206,6 @@
|
|
|
41106
41206
|
color: #333;
|
|
41107
41207
|
}
|
|
41108
41208
|
|
|
41109
|
-
* {
|
|
41110
|
-
font-family: "Roboto", "RobotoDraft", Helvetica, Arial, sans-serif;
|
|
41111
|
-
}
|
|
41112
41209
|
&,
|
|
41113
41210
|
*,
|
|
41114
41211
|
*:before,
|
|
@@ -44976,9 +45073,9 @@
|
|
|
44976
45073
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
44977
45074
|
|
|
44978
45075
|
|
|
44979
|
-
__info__.version = '16.2.
|
|
44980
|
-
__info__.date = '2023-
|
|
44981
|
-
__info__.hash = '
|
|
45076
|
+
__info__.version = '16.2.2';
|
|
45077
|
+
__info__.date = '2023-04-13T08:29:22.236Z';
|
|
45078
|
+
__info__.hash = 'a38f31a';
|
|
44982
45079
|
|
|
44983
45080
|
|
|
44984
45081
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|