@odoo/o-spreadsheet 19.3.15 → 19.3.17
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 +62 -40
- package/dist/o_spreadsheet.css +5 -3
- package/dist/o_spreadsheet.esm.js +62 -40
- package/dist/o_spreadsheet.iife.js +62 -40
- package/dist/o_spreadsheet.min.iife.js +252 -252
- package/dist/o_spreadsheet.xml +3 -3
- package/dist/types/functions/function_registry.d.ts +3 -0
- package/dist/types/functions/helpers.d.ts +4 -0
- package/dist/types/functions/module_operators.d.ts +1 -1
- package/dist/types/functions/module_text.d.ts +11 -11
- package/dist/types/functions/module_web.d.ts +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/plugins/core/squisher.d.ts +2 -1
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 19.3.
|
|
6
|
-
* @date 2026-08-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.3.17
|
|
6
|
+
* @date 2026-08-21T15:31:50.940Z
|
|
7
|
+
* @hash cf8c614
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function(exports, _odoo_owl) {
|
|
@@ -4071,6 +4071,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
4071
4071
|
default: return "";
|
|
4072
4072
|
}
|
|
4073
4073
|
}
|
|
4074
|
+
/**
|
|
4075
|
+
* Only converts the decimal separator, ignore number format such as % or dates
|
|
4076
|
+
*/
|
|
4077
|
+
function toLocaleString(data, locale) {
|
|
4078
|
+
const value = toValue(data);
|
|
4079
|
+
switch (typeof value) {
|
|
4080
|
+
case "string": return value;
|
|
4081
|
+
case "number": return value.toString().replace(".", locale.decimalSeparator);
|
|
4082
|
+
case "boolean": return value ? "TRUE" : "FALSE";
|
|
4083
|
+
default: return "";
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4074
4086
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
4075
4087
|
const normalizeString = memoize(function normalizeString(str) {
|
|
4076
4088
|
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
@@ -4745,6 +4757,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
4745
4757
|
}
|
|
4746
4758
|
};
|
|
4747
4759
|
const functionRegistry = new FunctionRegistry();
|
|
4760
|
+
/** Formulas using one of these functions are never squished: they are always exported
|
|
4761
|
+
* as a full formula string, and they don't become the base formula of the next cells. */
|
|
4762
|
+
const NonSquishableFunctionRegistry = new Registry();
|
|
4748
4763
|
|
|
4749
4764
|
//#endregion
|
|
4750
4765
|
//#region src/types/locale.ts
|
|
@@ -29086,12 +29101,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29086
29101
|
}
|
|
29087
29102
|
sortFilterZone(sortDirection) {
|
|
29088
29103
|
const filterPosition = this.props.filterPosition;
|
|
29089
|
-
const
|
|
29104
|
+
const table = this.table;
|
|
29105
|
+
const tableZone = table?.range.zone;
|
|
29090
29106
|
if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
|
|
29091
29107
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
29092
29108
|
const contentZone = {
|
|
29093
29109
|
...tableZone,
|
|
29094
|
-
top: tableZone.top +
|
|
29110
|
+
top: tableZone.top + table.config.numberOfHeaders
|
|
29095
29111
|
};
|
|
29096
29112
|
const sortAnchor = {
|
|
29097
29113
|
col: filterPosition.col,
|
|
@@ -49865,7 +49881,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49865
49881
|
* The result of this method is:
|
|
49866
49882
|
* - if the cell is not a formula, returns the content as is and resets the base formula
|
|
49867
49883
|
* - if the cell is a formula:
|
|
49868
|
-
* - if there is no previous formula, or the normalized formula is different from the previous one
|
|
49884
|
+
* - if there is no previous formula, or the normalized formula is different from the previous one or it contains blacklisted functions (see NonSquishableFunctionRegistry),
|
|
49885
|
+
* resets the base formula to this one and returns the full formula string
|
|
49869
49886
|
* - else, compares the literal values and range dependencies to the previous formula, and for each parameter:
|
|
49870
49887
|
* - for numbers: returns a relative change (+N or -N) if possible, else the full number or "=" if unchanged
|
|
49871
49888
|
* - for strings: returns the full string if changed, else "="
|
|
@@ -49873,6 +49890,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
49873
49890
|
* */
|
|
49874
49891
|
squish(cell, forSheetId) {
|
|
49875
49892
|
if (cell.isFormula) {
|
|
49893
|
+
if (NonSquishableFunctionRegistry.getAll().some((functionName) => cell.compiledFormula.usesSymbol(functionName))) {
|
|
49894
|
+
this.resetBaseFormula();
|
|
49895
|
+
return cell.compiledFormula.toFormulaString(this.getters, this.rangeToStringOptions);
|
|
49896
|
+
}
|
|
49876
49897
|
let numbers = [];
|
|
49877
49898
|
let strings = [];
|
|
49878
49899
|
let references = [];
|
|
@@ -61054,7 +61075,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61054
61075
|
}
|
|
61055
61076
|
message = {
|
|
61056
61077
|
...message,
|
|
61057
|
-
commands:
|
|
61078
|
+
commands: revision.commands
|
|
61058
61079
|
};
|
|
61059
61080
|
}
|
|
61060
61081
|
if (this.isReplayingInitialRevisions) throw new Error(`Trying to send a new revision while replaying initial revision. This can lead to endless dispatches every time the spreadsheet is open.
|
|
@@ -77208,7 +77229,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
77208
77229
|
else if (_format === 0) {
|
|
77209
77230
|
const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
|
|
77210
77231
|
return transposeMatrix(_array).flatMap((row) => row.map((value) => {
|
|
77211
|
-
return isEvaluationError(value.value) ? value.value :
|
|
77232
|
+
return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
|
|
77212
77233
|
})).join(rowSeparator);
|
|
77213
77234
|
} else return new EvaluationError(_t("Format must be 0 or 1"));
|
|
77214
77235
|
},
|
|
@@ -82969,7 +82990,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
82969
82990
|
description: _t("Concatenation of two values."),
|
|
82970
82991
|
args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
|
|
82971
82992
|
compute: function(value1, value2) {
|
|
82972
|
-
return
|
|
82993
|
+
return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
|
|
82973
82994
|
},
|
|
82974
82995
|
isExported: true
|
|
82975
82996
|
};
|
|
@@ -83834,7 +83855,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83834
83855
|
description: _t("Remove non-printable characters from a piece of text."),
|
|
83835
83856
|
args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
|
|
83836
83857
|
compute: function(text) {
|
|
83837
|
-
const _text =
|
|
83858
|
+
const _text = toLocaleString(text, this.locale);
|
|
83838
83859
|
let cleanedStr = "";
|
|
83839
83860
|
for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
|
|
83840
83861
|
return cleanedStr;
|
|
@@ -83845,7 +83866,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83845
83866
|
description: _t("Appends strings to one another."),
|
|
83846
83867
|
args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
|
|
83847
83868
|
compute: function(...datas) {
|
|
83848
|
-
return reduceAny(datas, (acc, a) => acc +
|
|
83869
|
+
return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
|
|
83849
83870
|
},
|
|
83850
83871
|
isExported: true
|
|
83851
83872
|
};
|
|
@@ -83853,7 +83874,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83853
83874
|
description: _t("Tests whether two strings are identical."),
|
|
83854
83875
|
args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
|
|
83855
83876
|
compute: function(string1, string2) {
|
|
83856
|
-
return
|
|
83877
|
+
return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
|
|
83857
83878
|
},
|
|
83858
83879
|
isExported: true
|
|
83859
83880
|
};
|
|
@@ -83865,8 +83886,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83865
83886
|
arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
|
|
83866
83887
|
],
|
|
83867
83888
|
compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
|
|
83868
|
-
const _searchFor =
|
|
83869
|
-
const _textToSearch =
|
|
83889
|
+
const _searchFor = toLocaleString(searchFor, this.locale);
|
|
83890
|
+
const _textToSearch = toLocaleString(textToSearch, this.locale);
|
|
83870
83891
|
const _startingAt = toNumber(startingAt, this.locale);
|
|
83871
83892
|
if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
|
|
83872
83893
|
if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
|
|
@@ -83903,8 +83924,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83903
83924
|
description: _t("Concatenates elements of arrays with delimiter."),
|
|
83904
83925
|
args: [arg("delimiter (string)", _t("The character or string to place between each concatenated value.")), arg("value_or_array (string, range<string>, repeating)", _t("Value to be appended using delimiter."))],
|
|
83905
83926
|
compute: function(delimiter, ...valuesOrArrays) {
|
|
83906
|
-
const _delimiter =
|
|
83907
|
-
return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") +
|
|
83927
|
+
const _delimiter = toLocaleString(delimiter, this.locale);
|
|
83928
|
+
return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
|
|
83908
83929
|
}
|
|
83909
83930
|
};
|
|
83910
83931
|
const LEFT = {
|
|
@@ -83913,7 +83934,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83913
83934
|
compute: function(text, ...args) {
|
|
83914
83935
|
const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
|
|
83915
83936
|
if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
|
|
83916
|
-
return
|
|
83937
|
+
return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
|
|
83917
83938
|
},
|
|
83918
83939
|
isExported: true
|
|
83919
83940
|
};
|
|
@@ -83921,7 +83942,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83921
83942
|
description: _t("Length of a string."),
|
|
83922
83943
|
args: [arg("text (string)", _t("The string whose length will be returned."))],
|
|
83923
83944
|
compute: function(text) {
|
|
83924
|
-
return
|
|
83945
|
+
return toLocaleString(text, this.locale).length;
|
|
83925
83946
|
},
|
|
83926
83947
|
isExported: true
|
|
83927
83948
|
};
|
|
@@ -83929,7 +83950,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83929
83950
|
description: _t("Converts a specified string to lowercase."),
|
|
83930
83951
|
args: [arg("text (string)", _t("The string to convert to lowercase."))],
|
|
83931
83952
|
compute: function(text) {
|
|
83932
|
-
return
|
|
83953
|
+
return toLocaleString(text, this.locale).toLowerCase();
|
|
83933
83954
|
},
|
|
83934
83955
|
isExported: true
|
|
83935
83956
|
};
|
|
@@ -83941,7 +83962,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83941
83962
|
arg("extract_length (number)", _t("The length of the segment to extract."))
|
|
83942
83963
|
],
|
|
83943
83964
|
compute: function(text, starting_at, extract_length) {
|
|
83944
|
-
const _text =
|
|
83965
|
+
const _text = toLocaleString(text, this.locale);
|
|
83945
83966
|
const _starting_at = toNumber(starting_at, this.locale);
|
|
83946
83967
|
const _extract_length = toNumber(extract_length, this.locale);
|
|
83947
83968
|
if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
|
|
@@ -83954,7 +83975,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83954
83975
|
description: _t("Capitalizes each word in a specified string."),
|
|
83955
83976
|
args: [arg("text_to_capitalize (string)", _t("The text which will be returned with the first letter of each word in uppercase and all other letters in lowercase."))],
|
|
83956
83977
|
compute: function(text) {
|
|
83957
|
-
return
|
|
83978
|
+
return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
|
|
83958
83979
|
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
83959
83980
|
});
|
|
83960
83981
|
},
|
|
@@ -84102,9 +84123,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84102
84123
|
compute: function(text, position, length, newText) {
|
|
84103
84124
|
const _position = toNumber(position, this.locale);
|
|
84104
84125
|
if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
|
|
84105
|
-
const _text =
|
|
84126
|
+
const _text = toLocaleString(text, this.locale);
|
|
84106
84127
|
const _length = toNumber(length, this.locale);
|
|
84107
|
-
const _newText =
|
|
84128
|
+
const _newText = toLocaleString(newText, this.locale);
|
|
84108
84129
|
return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
|
|
84109
84130
|
},
|
|
84110
84131
|
isExported: true
|
|
@@ -84115,7 +84136,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84115
84136
|
compute: function(text, ...args) {
|
|
84116
84137
|
const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
|
|
84117
84138
|
if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
|
|
84118
|
-
const _text =
|
|
84139
|
+
const _text = toLocaleString(text, this.locale);
|
|
84119
84140
|
const stringLength = _text.length;
|
|
84120
84141
|
return _text.substring(stringLength - _numberOfCharacters, stringLength);
|
|
84121
84142
|
},
|
|
@@ -84129,8 +84150,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84129
84150
|
arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
|
|
84130
84151
|
],
|
|
84131
84152
|
compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
|
|
84132
|
-
const _searchFor =
|
|
84133
|
-
const _textToSearch =
|
|
84153
|
+
const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
|
|
84154
|
+
const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
|
|
84134
84155
|
const _startingAt = toNumber(startingAt, this.locale);
|
|
84135
84156
|
if (_textToSearch === "") return {
|
|
84136
84157
|
value: CellErrorType.GenericError,
|
|
@@ -84160,8 +84181,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84160
84181
|
arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _t("Whether or not to remove empty text messages from the split results. The default behavior is to treat consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters."))
|
|
84161
84182
|
],
|
|
84162
84183
|
compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
|
|
84163
|
-
const _text =
|
|
84164
|
-
const _delimiter = escapeRegExp(
|
|
84184
|
+
const _text = toLocaleString(text, this.locale);
|
|
84185
|
+
const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
|
|
84165
84186
|
const _splitByEach = toBoolean(splitByEach);
|
|
84166
84187
|
const _removeEmptyText = toBoolean(removeEmptyText);
|
|
84167
84188
|
if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
|
|
@@ -84183,10 +84204,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84183
84204
|
compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
|
|
84184
84205
|
const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
|
|
84185
84206
|
if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
|
|
84186
|
-
const _textToSearch =
|
|
84187
|
-
const _searchFor =
|
|
84207
|
+
const _textToSearch = toLocaleString(textToSearch, this.locale);
|
|
84208
|
+
const _searchFor = toLocaleString(searchFor, this.locale);
|
|
84188
84209
|
if (_searchFor === "") return _textToSearch;
|
|
84189
|
-
const _replaceWith =
|
|
84210
|
+
const _replaceWith = toLocaleString(replaceWith, this.locale);
|
|
84190
84211
|
const reg = new RegExp(escapeRegExp(_searchFor), "g");
|
|
84191
84212
|
if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
|
|
84192
84213
|
let n = 0;
|
|
@@ -84209,10 +84230,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84209
84230
|
arg("texts (string, range<string>, repeating)", _t("Text item to join."))
|
|
84210
84231
|
],
|
|
84211
84232
|
compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
|
|
84212
|
-
const _delimiter =
|
|
84233
|
+
const _delimiter = toLocaleString(delimiter, this.locale);
|
|
84213
84234
|
const _ignoreEmpty = toBoolean(ignoreEmpty);
|
|
84214
84235
|
let n = 0;
|
|
84215
|
-
return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty &&
|
|
84236
|
+
return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
|
|
84216
84237
|
},
|
|
84217
84238
|
isExported: true
|
|
84218
84239
|
};
|
|
@@ -84265,7 +84286,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84265
84286
|
description: _t("Removes space characters."),
|
|
84266
84287
|
args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
|
|
84267
84288
|
compute: function(text) {
|
|
84268
|
-
return trimContent(
|
|
84289
|
+
return trimContent(toLocaleString(text, this.locale));
|
|
84269
84290
|
},
|
|
84270
84291
|
isExported: true
|
|
84271
84292
|
};
|
|
@@ -84273,7 +84294,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84273
84294
|
description: _t("Converts a specified string to uppercase."),
|
|
84274
84295
|
args: [arg("text (string)", _t("The string to convert to uppercase."))],
|
|
84275
84296
|
compute: function(text) {
|
|
84276
|
-
return
|
|
84297
|
+
return toLocaleString(text, this.locale).toUpperCase();
|
|
84277
84298
|
},
|
|
84278
84299
|
isExported: true
|
|
84279
84300
|
};
|
|
@@ -84370,7 +84391,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84370
84391
|
args: [arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")), arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks."))],
|
|
84371
84392
|
compute: function(url, linkLabel) {
|
|
84372
84393
|
const processedUrl = toString(url).trim();
|
|
84373
|
-
const processedLabel =
|
|
84394
|
+
const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
|
|
84374
84395
|
if (processedUrl === "") return processedLabel;
|
|
84375
84396
|
return markdownLink(processedLabel, processedUrl);
|
|
84376
84397
|
},
|
|
@@ -84513,7 +84534,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84513
84534
|
supportedPivotPositionalFormulaRegistry,
|
|
84514
84535
|
pivotToFunctionValueRegistry,
|
|
84515
84536
|
migrationStepRegistry,
|
|
84516
|
-
chartJsExtensionRegistry
|
|
84537
|
+
chartJsExtensionRegistry,
|
|
84538
|
+
NonSquishableFunctionRegistry
|
|
84517
84539
|
};
|
|
84518
84540
|
const helpers = {
|
|
84519
84541
|
arg,
|
|
@@ -84766,8 +84788,8 @@ exports.stores = stores;
|
|
|
84766
84788
|
exports.tokenColors = tokenColors;
|
|
84767
84789
|
exports.tokenize = tokenize;
|
|
84768
84790
|
|
|
84769
|
-
__info__.version = "19.3.
|
|
84770
|
-
__info__.date = "2026-08-
|
|
84771
|
-
__info__.hash = "
|
|
84791
|
+
__info__.version = "19.3.17";
|
|
84792
|
+
__info__.date = "2026-08-21T15:31:50.940Z";
|
|
84793
|
+
__info__.hash = "cf8c614";
|
|
84772
84794
|
|
|
84773
84795
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|