@odoo/o-spreadsheet 18.3.19 → 18.3.21
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 +90 -56
- package/dist/o-spreadsheet.d.ts +4 -3
- package/dist/o-spreadsheet.esm.js +90 -56
- package/dist/o-spreadsheet.iife.js +90 -56
- package/dist/o-spreadsheet.iife.min.js +5 -5
- package/dist/o_spreadsheet.xml +10 -7
- package/package.json +15 -2
|
@@ -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 18.3.
|
|
6
|
-
* @date 2025-09-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.3.21
|
|
6
|
+
* @date 2025-09-19T07:25:12.089Z
|
|
7
|
+
* @hash b64ee85
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -863,8 +863,19 @@
|
|
|
863
863
|
},
|
|
864
864
|
}[funcName];
|
|
865
865
|
}
|
|
866
|
+
/**
|
|
867
|
+
* Removes the specified indexes from the array.
|
|
868
|
+
* Sparse (empty) elements are transformed to undefined (unless their index is explicitly removed).
|
|
869
|
+
*/
|
|
866
870
|
function removeIndexesFromArray(array, indexes) {
|
|
867
|
-
|
|
871
|
+
const toRemove = new Set(indexes);
|
|
872
|
+
const newArray = [];
|
|
873
|
+
for (let i = 0; i < array.length; i++) {
|
|
874
|
+
if (!toRemove.has(i)) {
|
|
875
|
+
newArray.push(array[i]);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return newArray;
|
|
868
879
|
}
|
|
869
880
|
function insertItemsAtIndex(array, items, index) {
|
|
870
881
|
const newArray = [...array];
|
|
@@ -7208,7 +7219,7 @@
|
|
|
7208
7219
|
this.getters = getters;
|
|
7209
7220
|
this.dispatch = dispatch;
|
|
7210
7221
|
}
|
|
7211
|
-
copy(data, isCutOperation) {
|
|
7222
|
+
copy(data, isCutOperation, mode = "copyPaste") {
|
|
7212
7223
|
return;
|
|
7213
7224
|
}
|
|
7214
7225
|
paste(target, clippedContent, options) { }
|
|
@@ -7227,7 +7238,7 @@
|
|
|
7227
7238
|
}
|
|
7228
7239
|
|
|
7229
7240
|
class AbstractCellClipboardHandler extends ClipboardHandler {
|
|
7230
|
-
copy(data) {
|
|
7241
|
+
copy(data, isCutOperation, mode = "copyPaste") {
|
|
7231
7242
|
return;
|
|
7232
7243
|
}
|
|
7233
7244
|
pasteFromCopy(sheetId, target, content, options) {
|
|
@@ -8950,7 +8961,7 @@
|
|
|
8950
8961
|
}
|
|
8951
8962
|
return "Success" /* CommandResult.Success */;
|
|
8952
8963
|
}
|
|
8953
|
-
copy(data) {
|
|
8964
|
+
copy(data, isCutOperation, mode = "copyPaste") {
|
|
8954
8965
|
const sheetId = data.sheetId;
|
|
8955
8966
|
const { clippedZones, rowsIndexes, columnsIndexes } = data;
|
|
8956
8967
|
const clippedCells = [];
|
|
@@ -8963,7 +8974,7 @@
|
|
|
8963
8974
|
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
8964
8975
|
const pivotId = this.getters.getPivotIdFromPosition(position);
|
|
8965
8976
|
const spreader = this.getters.getArrayFormulaSpreadingOn(position);
|
|
8966
|
-
if (pivotId && spreader) {
|
|
8977
|
+
if (mode !== "shiftCells" && pivotId && spreader) {
|
|
8967
8978
|
const pivotZone = this.getters.getSpreadZone(spreader);
|
|
8968
8979
|
if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
|
|
8969
8980
|
pivotZone &&
|
|
@@ -8981,7 +8992,7 @@
|
|
|
8981
8992
|
};
|
|
8982
8993
|
}
|
|
8983
8994
|
}
|
|
8984
|
-
else {
|
|
8995
|
+
else if (mode !== "shiftCells") {
|
|
8985
8996
|
if (spreader && !deepEquals(spreader, position)) {
|
|
8986
8997
|
const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
|
|
8987
8998
|
const content = isSpreaderCopied
|
|
@@ -9681,7 +9692,7 @@
|
|
|
9681
9692
|
}
|
|
9682
9693
|
|
|
9683
9694
|
class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
9684
|
-
copy(data, isCutOperation) {
|
|
9695
|
+
copy(data, isCutOperation, mode = "copyPaste") {
|
|
9685
9696
|
const sheetId = data.sheetId;
|
|
9686
9697
|
const { rowsIndexes, columnsIndexes, zones } = data;
|
|
9687
9698
|
const copiedTablesIds = new Set();
|
|
@@ -9719,11 +9730,13 @@
|
|
|
9719
9730
|
type: coreTable.type,
|
|
9720
9731
|
};
|
|
9721
9732
|
}
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9733
|
+
if (mode !== "shiftCells") {
|
|
9734
|
+
tableCellsInRow.push({
|
|
9735
|
+
table: copiedTable,
|
|
9736
|
+
style: this.getTableStyleToCopy(position),
|
|
9737
|
+
isWholeTableCopied: copiedTablesIds.has(table.id),
|
|
9738
|
+
});
|
|
9739
|
+
}
|
|
9727
9740
|
}
|
|
9728
9741
|
}
|
|
9729
9742
|
return {
|
|
@@ -14807,8 +14820,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
14807
14820
|
}
|
|
14808
14821
|
|
|
14809
14822
|
function sortMatrix(matrix, locale, ...criteria) {
|
|
14810
|
-
for (
|
|
14811
|
-
|
|
14823
|
+
for (let i = 0; i < criteria.length; i++) {
|
|
14824
|
+
const param = i % 2 === 0 ? "sort_column" : "is_ascending";
|
|
14825
|
+
assert(() => criteria[i] !== undefined, _t("Value for parameter %s is missing in [[FUNCTION_NAME]].", param));
|
|
14812
14826
|
}
|
|
14813
14827
|
const sortingOrders = [];
|
|
14814
14828
|
const sortColumns = [];
|
|
@@ -30885,7 +30899,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30885
30899
|
];
|
|
30886
30900
|
const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
|
|
30887
30901
|
const SUPPORTED_FONTS = ["Arial"];
|
|
30888
|
-
const SUPPORTED_FILL_PATTERNS = ["solid"];
|
|
30902
|
+
const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
|
|
30889
30903
|
const SUPPORTED_CF_TYPES = [
|
|
30890
30904
|
"expression",
|
|
30891
30905
|
"cellIs",
|
|
@@ -31070,7 +31084,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31070
31084
|
};
|
|
31071
31085
|
/** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
|
|
31072
31086
|
const XLSX_FORMATS_CONVERSION_MAP = {
|
|
31073
|
-
0: "",
|
|
31087
|
+
0: "General",
|
|
31074
31088
|
1: "0",
|
|
31075
31089
|
2: "0.00",
|
|
31076
31090
|
3: "#,#00",
|
|
@@ -31396,11 +31410,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31396
31410
|
* Excel format are defined in openXML §18.8.31
|
|
31397
31411
|
*/
|
|
31398
31412
|
function convertXlsxFormat(numFmtId, formats, warningManager) {
|
|
31399
|
-
if (numFmtId === 0) {
|
|
31400
|
-
return undefined;
|
|
31401
|
-
}
|
|
31402
31413
|
// Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
|
|
31403
31414
|
let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
|
|
31415
|
+
if (format === "General") {
|
|
31416
|
+
return undefined;
|
|
31417
|
+
}
|
|
31404
31418
|
if (format) {
|
|
31405
31419
|
try {
|
|
31406
31420
|
let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
|
|
@@ -34245,10 +34259,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34245
34259
|
});
|
|
34246
34260
|
}
|
|
34247
34261
|
extractRows(worksheet) {
|
|
34262
|
+
const spilledCells = new Set();
|
|
34248
34263
|
return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
|
|
34249
34264
|
return {
|
|
34250
34265
|
index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
|
|
34251
|
-
cells: this.extractCells(rowElement),
|
|
34266
|
+
cells: this.extractCells(rowElement, spilledCells),
|
|
34252
34267
|
height: this.extractAttr(rowElement, "ht")?.asNum(),
|
|
34253
34268
|
customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
|
|
34254
34269
|
hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
|
|
@@ -34258,14 +34273,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34258
34273
|
};
|
|
34259
34274
|
});
|
|
34260
34275
|
}
|
|
34261
|
-
extractCells(row) {
|
|
34276
|
+
extractCells(row, spilledCells) {
|
|
34262
34277
|
return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
|
|
34278
|
+
const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
|
|
34279
|
+
const formula = this.extractCellFormula(cellElement);
|
|
34280
|
+
if (formula?.ref && formula.sharedIndex === undefined) {
|
|
34281
|
+
const zone = toZone(formula.ref);
|
|
34282
|
+
for (const { col, row } of positions(zone)) {
|
|
34283
|
+
const followerXc = toXC(col, row);
|
|
34284
|
+
if (followerXc !== xc) {
|
|
34285
|
+
spilledCells.add(followerXc);
|
|
34286
|
+
}
|
|
34287
|
+
}
|
|
34288
|
+
}
|
|
34289
|
+
const isSpilled = spilledCells.has(xc);
|
|
34263
34290
|
return {
|
|
34264
|
-
xc
|
|
34291
|
+
xc,
|
|
34265
34292
|
styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
|
|
34266
34293
|
type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
|
|
34267
|
-
value: this.extractChildTextContent(cellElement, "v"),
|
|
34268
|
-
formula:
|
|
34294
|
+
value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
|
|
34295
|
+
formula: isSpilled ? undefined : formula,
|
|
34269
34296
|
};
|
|
34270
34297
|
});
|
|
34271
34298
|
}
|
|
@@ -34273,11 +34300,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34273
34300
|
const formulaElement = this.querySelector(cellElement, "f");
|
|
34274
34301
|
if (!formulaElement)
|
|
34275
34302
|
return undefined;
|
|
34276
|
-
|
|
34277
|
-
|
|
34278
|
-
|
|
34279
|
-
|
|
34280
|
-
|
|
34303
|
+
const content = this.extractTextContent(formulaElement);
|
|
34304
|
+
const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
|
|
34305
|
+
const ref = this.extractAttr(formulaElement, "ref")?.asString();
|
|
34306
|
+
// This is the case of spilled cells of array formulas where <f> is empty
|
|
34307
|
+
if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
|
|
34308
|
+
return undefined;
|
|
34309
|
+
}
|
|
34310
|
+
return { content, sharedIndex, ref };
|
|
34281
34311
|
}
|
|
34282
34312
|
extractHyperLinks(worksheet) {
|
|
34283
34313
|
return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
|
|
@@ -48860,12 +48890,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48860
48890
|
addCalculatedMeasure() {
|
|
48861
48891
|
const { measures } = this.props.definition;
|
|
48862
48892
|
const measureName = this.env.model.getters.generateNewCalculatedMeasureName(measures);
|
|
48893
|
+
const aggregator = "sum";
|
|
48863
48894
|
this.props.onDimensionsUpdated({
|
|
48864
48895
|
measures: measures.concat([
|
|
48865
48896
|
{
|
|
48866
|
-
id: this.getMeasureId(measureName),
|
|
48897
|
+
id: this.getMeasureId(measureName, aggregator),
|
|
48867
48898
|
fieldName: measureName,
|
|
48868
|
-
aggregator
|
|
48899
|
+
aggregator,
|
|
48869
48900
|
computedBy: {
|
|
48870
48901
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
48871
48902
|
formula: "=0",
|
|
@@ -66216,7 +66247,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66216
66247
|
return { value: 0 };
|
|
66217
66248
|
}
|
|
66218
66249
|
const { columns, rows } = super.definition;
|
|
66219
|
-
if (columns.length + rows.length !== domain.length) {
|
|
66250
|
+
if (measure.aggregator && columns.length + rows.length !== domain.length) {
|
|
66220
66251
|
const values = this.getValuesToAggregate(measure, domain);
|
|
66221
66252
|
const aggregator = AGGREGATORS_FN[measure.aggregator];
|
|
66222
66253
|
if (!aggregator) {
|
|
@@ -66235,11 +66266,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66235
66266
|
if (columns.find((col) => col.nameWithGranularity === symbolName)) {
|
|
66236
66267
|
const { colDomain } = domainToColRowDomain(this, domain);
|
|
66237
66268
|
const symbolIndex = colDomain.findIndex((node) => node.field === symbolName);
|
|
66269
|
+
if (symbolIndex === -1) {
|
|
66270
|
+
return new NotAvailableError();
|
|
66271
|
+
}
|
|
66238
66272
|
return this.getPivotHeaderValueAndFormat(colDomain.slice(0, symbolIndex + 1));
|
|
66239
66273
|
}
|
|
66240
66274
|
if (rows.find((row) => row.nameWithGranularity === symbolName)) {
|
|
66241
66275
|
const { rowDomain } = domainToColRowDomain(this, domain);
|
|
66242
66276
|
const symbolIndex = rowDomain.findIndex((row) => row.field === symbolName);
|
|
66277
|
+
if (symbolIndex === -1) {
|
|
66278
|
+
return new NotAvailableError();
|
|
66279
|
+
}
|
|
66243
66280
|
return this.getPivotHeaderValueAndFormat(rowDomain.slice(0, symbolIndex + 1));
|
|
66244
66281
|
}
|
|
66245
66282
|
return this.getPivotCellValueAndFormat(symbolName, domain);
|
|
@@ -68830,7 +68867,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68830
68867
|
bottom: rowIndex,
|
|
68831
68868
|
}));
|
|
68832
68869
|
const handler = new CellClipboardHandler(this.getters, this.dispatch);
|
|
68833
|
-
const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep));
|
|
68870
|
+
const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep), false);
|
|
68834
68871
|
if (!data) {
|
|
68835
68872
|
return;
|
|
68836
68873
|
}
|
|
@@ -70870,12 +70907,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70870
70907
|
}
|
|
70871
70908
|
case "INSERT_CELL": {
|
|
70872
70909
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
70873
|
-
const copiedData = this.copy(cut);
|
|
70910
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
70874
70911
|
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
70875
70912
|
}
|
|
70876
70913
|
case "DELETE_CELL": {
|
|
70877
70914
|
const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
70878
|
-
const copiedData = this.copy(cut);
|
|
70915
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
70879
70916
|
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
70880
70917
|
}
|
|
70881
70918
|
}
|
|
@@ -70986,13 +71023,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70986
71023
|
});
|
|
70987
71024
|
break;
|
|
70988
71025
|
}
|
|
70989
|
-
const copiedData = this.copy(cut);
|
|
71026
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
70990
71027
|
this.paste(paste, copiedData, { isCutOperation: true });
|
|
70991
71028
|
break;
|
|
70992
71029
|
}
|
|
70993
71030
|
case "INSERT_CELL": {
|
|
70994
71031
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
70995
|
-
const copiedData = this.copy(cut);
|
|
71032
|
+
const copiedData = this.copy(cut, "shiftCells");
|
|
70996
71033
|
this.paste(paste, copiedData, { isCutOperation: true });
|
|
70997
71034
|
break;
|
|
70998
71035
|
}
|
|
@@ -71107,11 +71144,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71107
71144
|
}
|
|
71108
71145
|
return false;
|
|
71109
71146
|
}
|
|
71110
|
-
copy(zones) {
|
|
71147
|
+
copy(zones, mode = "copyPaste") {
|
|
71111
71148
|
let copiedData = {};
|
|
71112
71149
|
const clipboardData = this.getClipboardData(zones);
|
|
71113
71150
|
for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
|
|
71114
|
-
const data = handler.copy(clipboardData, this._isCutOperation);
|
|
71151
|
+
const data = handler.copy(clipboardData, this._isCutOperation, mode);
|
|
71115
71152
|
copiedData[handlerName] = data;
|
|
71116
71153
|
const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
|
|
71117
71154
|
for (const key of minimalKeys) {
|
|
@@ -72035,13 +72072,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72035
72072
|
const deltaCol = isBasedBefore && isCol ? thickness : 0;
|
|
72036
72073
|
const deltaRow = isBasedBefore && !isCol ? thickness : 0;
|
|
72037
72074
|
const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
|
|
72038
|
-
const originalSize =
|
|
72039
|
-
|
|
72040
|
-
|
|
72041
|
-
|
|
72042
|
-
const isDefaultCol = isCol && size === DEFAULT_CELL_WIDTH;
|
|
72043
|
-
return [element, isDefaultCol ? undefined : size];
|
|
72044
|
-
}));
|
|
72075
|
+
const originalSize = {};
|
|
72076
|
+
for (const element of toRemove) {
|
|
72077
|
+
originalSize[element] = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
|
|
72078
|
+
}
|
|
72045
72079
|
const target = [
|
|
72046
72080
|
{
|
|
72047
72081
|
left: isCol ? start + deltaCol : 0,
|
|
@@ -72062,7 +72096,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72062
72096
|
];
|
|
72063
72097
|
for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
|
|
72064
72098
|
const handler = new Handler(this.getters, this.dispatch);
|
|
72065
|
-
const data = handler.copy(getClipboardDataPositions(sheetId, target));
|
|
72099
|
+
const data = handler.copy(getClipboardDataPositions(sheetId, target), false, "shiftCells");
|
|
72066
72100
|
if (!data) {
|
|
72067
72101
|
continue;
|
|
72068
72102
|
}
|
|
@@ -72077,11 +72111,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72077
72111
|
for (const element of toRemove) {
|
|
72078
72112
|
const size = originalSize[element];
|
|
72079
72113
|
const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
|
|
72080
|
-
if (size
|
|
72114
|
+
if (size != currentSize) {
|
|
72081
72115
|
resizingGroups[size] ??= [];
|
|
72082
72116
|
resizingGroups[size].push(currentIndex);
|
|
72083
|
-
currentIndex += 1;
|
|
72084
72117
|
}
|
|
72118
|
+
currentIndex += 1;
|
|
72085
72119
|
}
|
|
72086
72120
|
for (const size in resizingGroups) {
|
|
72087
72121
|
this.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
@@ -80253,7 +80287,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
80253
80287
|
handlers = [];
|
|
80254
80288
|
uiHandlers = [];
|
|
80255
80289
|
coreHandlers = [];
|
|
80256
|
-
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport =
|
|
80290
|
+
constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
|
|
80257
80291
|
const start = performance.now();
|
|
80258
80292
|
console.debug("##### Model creation #####");
|
|
80259
80293
|
super();
|
|
@@ -80996,9 +81030,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
80996
81030
|
exports.tokenize = tokenize;
|
|
80997
81031
|
|
|
80998
81032
|
|
|
80999
|
-
__info__.version = "18.3.
|
|
81000
|
-
__info__.date = "2025-09-
|
|
81001
|
-
__info__.hash = "
|
|
81033
|
+
__info__.version = "18.3.21";
|
|
81034
|
+
__info__.date = "2025-09-19T07:25:12.089Z";
|
|
81035
|
+
__info__.hash = "b64ee85";
|
|
81002
81036
|
|
|
81003
81037
|
|
|
81004
81038
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|