@odoo/o-spreadsheet 17.1.24 → 17.1.26
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 +70 -67
- package/dist/o-spreadsheet.d.ts +2 -1
- package/dist/o-spreadsheet.esm.js +70 -67
- package/dist/o-spreadsheet.iife.js +70 -67
- package/dist/o-spreadsheet.iife.min.js +224 -224
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +8 -11
|
@@ -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 17.1.
|
|
6
|
-
* @date 2024-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.1.26
|
|
6
|
+
* @date 2024-08-02T08:23:08.499Z
|
|
7
|
+
* @hash 4ba7e55
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -480,7 +480,7 @@
|
|
|
480
480
|
let timeout;
|
|
481
481
|
return function () {
|
|
482
482
|
const context = this;
|
|
483
|
-
const args = arguments;
|
|
483
|
+
const args = Array.from(arguments);
|
|
484
484
|
function later() {
|
|
485
485
|
timeout = null;
|
|
486
486
|
if (!immediate) {
|
|
@@ -683,7 +683,7 @@
|
|
|
683
683
|
*/
|
|
684
684
|
function largeMax(array) {
|
|
685
685
|
let len = array.length;
|
|
686
|
-
if (len <
|
|
686
|
+
if (len < 100_000)
|
|
687
687
|
return Math.max(...array);
|
|
688
688
|
let max = -Infinity;
|
|
689
689
|
while (len--) {
|
|
@@ -697,7 +697,7 @@
|
|
|
697
697
|
*/
|
|
698
698
|
function largeMin(array) {
|
|
699
699
|
let len = array.length;
|
|
700
|
-
if (len <
|
|
700
|
+
if (len < 100_000)
|
|
701
701
|
return Math.min(...array);
|
|
702
702
|
let min = +Infinity;
|
|
703
703
|
while (len--) {
|
|
@@ -2614,13 +2614,16 @@
|
|
|
2614
2614
|
}
|
|
2615
2615
|
return new RegExp("^" + exp + "$", "i");
|
|
2616
2616
|
}
|
|
2617
|
-
function evaluatePredicate(value = "", criterion) {
|
|
2617
|
+
function evaluatePredicate(value = "", criterion, locale) {
|
|
2618
2618
|
const { operator, operand } = criterion;
|
|
2619
2619
|
if (operand === undefined || value === null || operand === null) {
|
|
2620
2620
|
return false;
|
|
2621
2621
|
}
|
|
2622
2622
|
if (typeof operand === "number" && operator === "=") {
|
|
2623
|
-
|
|
2623
|
+
if (typeof value === "string" && (isNumber(value, locale) || isDateTime(value, locale))) {
|
|
2624
|
+
return toNumber(value, locale) === operand;
|
|
2625
|
+
}
|
|
2626
|
+
return value === operand;
|
|
2624
2627
|
}
|
|
2625
2628
|
if (operator === "<>" || operator === "=") {
|
|
2626
2629
|
let result;
|
|
@@ -2698,7 +2701,7 @@
|
|
|
2698
2701
|
for (let k = 0; k < countArg - 1; k += 2) {
|
|
2699
2702
|
const criteriaValue = toMatrix(args[k])[i][j].value;
|
|
2700
2703
|
const criterion = predicates[k / 2];
|
|
2701
|
-
validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
|
|
2704
|
+
validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion, locale);
|
|
2702
2705
|
if (!validatedPredicates) {
|
|
2703
2706
|
break;
|
|
2704
2707
|
}
|
|
@@ -5980,7 +5983,7 @@
|
|
|
5980
5983
|
function numberCell(value, localeFormat) {
|
|
5981
5984
|
return {
|
|
5982
5985
|
type: CellValueType.number,
|
|
5983
|
-
value: value || 0,
|
|
5986
|
+
value: value || 0, // necessary to avoid "-0" and NaN values,
|
|
5984
5987
|
format: localeFormat.format,
|
|
5985
5988
|
isAutoSummable: true,
|
|
5986
5989
|
defaultAlign: "right",
|
|
@@ -8471,8 +8474,8 @@
|
|
|
8471
8474
|
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
8472
8475
|
const options = {
|
|
8473
8476
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
8474
|
-
responsive: true,
|
|
8475
|
-
maintainAspectRatio: false,
|
|
8477
|
+
responsive: true, // will resize when its container is resized
|
|
8478
|
+
maintainAspectRatio: false, // doesn't maintain the aspect ration (width/height =2 by default) so the user has the choice of the exact layout
|
|
8476
8479
|
layout: {
|
|
8477
8480
|
padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
|
|
8478
8481
|
},
|
|
@@ -8518,7 +8521,7 @@
|
|
|
8518
8521
|
labels: truncateLabels ? labels.map(truncateLabel) : labels,
|
|
8519
8522
|
datasets: [],
|
|
8520
8523
|
},
|
|
8521
|
-
platform: undefined,
|
|
8524
|
+
platform: undefined, // This key is optional and will be set by chart.js
|
|
8522
8525
|
plugins: [],
|
|
8523
8526
|
};
|
|
8524
8527
|
}
|
|
@@ -8782,7 +8785,7 @@
|
|
|
8782
8785
|
},
|
|
8783
8786
|
y: {
|
|
8784
8787
|
position: chart.verticalAxisPosition,
|
|
8785
|
-
beginAtZero: true,
|
|
8788
|
+
beginAtZero: true, // the origin of the y axis is always zero
|
|
8786
8789
|
ticks: {
|
|
8787
8790
|
color: fontColor,
|
|
8788
8791
|
callback: (value) => {
|
|
@@ -9436,7 +9439,7 @@
|
|
|
9436
9439
|
},
|
|
9437
9440
|
y: {
|
|
9438
9441
|
position: chart.verticalAxisPosition,
|
|
9439
|
-
beginAtZero: true,
|
|
9442
|
+
beginAtZero: true, // the origin of the y axis is always zero
|
|
9440
9443
|
ticks: {
|
|
9441
9444
|
color: fontColor,
|
|
9442
9445
|
callback: (value) => {
|
|
@@ -9524,7 +9527,7 @@
|
|
|
9524
9527
|
const dataset = {
|
|
9525
9528
|
label,
|
|
9526
9529
|
data,
|
|
9527
|
-
tension: 0,
|
|
9530
|
+
tension: 0, // 0 -> render straight lines, which is much faster
|
|
9528
9531
|
borderColor: color,
|
|
9529
9532
|
backgroundColor,
|
|
9530
9533
|
pointBackgroundColor: color,
|
|
@@ -9635,7 +9638,7 @@
|
|
|
9635
9638
|
...this.getDefinition(),
|
|
9636
9639
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
9637
9640
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
9638
|
-
verticalAxisPosition: "left",
|
|
9641
|
+
verticalAxisPosition: "left", //TODO ExcelChartDefinition should be adapted, but can be done later
|
|
9639
9642
|
dataSets,
|
|
9640
9643
|
labelRange,
|
|
9641
9644
|
};
|
|
@@ -27202,7 +27205,9 @@
|
|
|
27202
27205
|
argToFocus: 0,
|
|
27203
27206
|
});
|
|
27204
27207
|
compositionActive = false;
|
|
27208
|
+
spreadsheetRect = useSpreadsheetRect();
|
|
27205
27209
|
get assistantStyle() {
|
|
27210
|
+
const composerRect = this.composerRef.el.getBoundingClientRect();
|
|
27206
27211
|
const assistantStyle = {};
|
|
27207
27212
|
assistantStyle["min-width"] = `${this.props.rect?.width || ASSISTANT_WIDTH}px`;
|
|
27208
27213
|
if (this.autoCompleteState.type === "function") {
|
|
@@ -27225,6 +27230,10 @@
|
|
|
27225
27230
|
assistantStyle.right = `0px`;
|
|
27226
27231
|
}
|
|
27227
27232
|
}
|
|
27233
|
+
if (this.props.focus === "contentFocus" &&
|
|
27234
|
+
composerRect.left + ASSISTANT_WIDTH > this.spreadsheetRect.width) {
|
|
27235
|
+
assistantStyle.right = "0px";
|
|
27236
|
+
}
|
|
27228
27237
|
return cssPropertiesToCss(assistantStyle);
|
|
27229
27238
|
}
|
|
27230
27239
|
// we can't allow input events to be triggered while we remove and add back the content of the composer in processContent
|
|
@@ -28870,10 +28879,13 @@
|
|
|
28870
28879
|
row: undefined,
|
|
28871
28880
|
};
|
|
28872
28881
|
const { Date } = window;
|
|
28873
|
-
let x =
|
|
28874
|
-
let y =
|
|
28882
|
+
let x = undefined;
|
|
28883
|
+
let y = undefined;
|
|
28875
28884
|
let lastMoved = 0;
|
|
28876
28885
|
function getPosition() {
|
|
28886
|
+
if (x === undefined || y === undefined) {
|
|
28887
|
+
return { col: -1, row: -1 };
|
|
28888
|
+
}
|
|
28877
28889
|
const col = env.model.getters.getColIndex(x);
|
|
28878
28890
|
const row = env.model.getters.getRowIndex(y);
|
|
28879
28891
|
return { col, row };
|
|
@@ -30055,7 +30067,7 @@
|
|
|
30055
30067
|
onScroll(offset) {
|
|
30056
30068
|
const { scrollX } = this.env.model.getters.getActiveSheetDOMScrollInfo();
|
|
30057
30069
|
this.env.model.dispatch("SET_VIEWPORT_OFFSET", {
|
|
30058
|
-
offsetX: scrollX,
|
|
30070
|
+
offsetX: scrollX, // offsetX is the same
|
|
30059
30071
|
offsetY: offset,
|
|
30060
30072
|
});
|
|
30061
30073
|
}
|
|
@@ -30268,8 +30280,8 @@
|
|
|
30268
30280
|
"Ctrl+Shift+L": () => this.setHorizontalAlign("left"),
|
|
30269
30281
|
"Ctrl+Shift+R": () => this.setHorizontalAlign("right"),
|
|
30270
30282
|
"Ctrl+Shift+V": () => PASTE_AS_VALUE_ACTION(this.env),
|
|
30271
|
-
"Ctrl+Shift+<": () => this.clearFormatting(),
|
|
30272
|
-
"Ctrl+<": () => this.clearFormatting(),
|
|
30283
|
+
"Ctrl+Shift+<": () => this.clearFormatting(), // for qwerty
|
|
30284
|
+
"Ctrl+<": () => this.clearFormatting(), // for azerty
|
|
30273
30285
|
"Ctrl+Shift+ ": () => {
|
|
30274
30286
|
this.env.model.selection.selectAll();
|
|
30275
30287
|
},
|
|
@@ -31067,10 +31079,10 @@
|
|
|
31067
31079
|
const CF_TYPE_CONVERSION_MAP = {
|
|
31068
31080
|
aboveAverage: undefined,
|
|
31069
31081
|
expression: undefined,
|
|
31070
|
-
cellIs: undefined,
|
|
31071
|
-
colorScale: undefined,
|
|
31082
|
+
cellIs: undefined, // exist but isn't an operator in o_spreadsheet
|
|
31083
|
+
colorScale: undefined, // exist but isn't an operator in o_spreadsheet
|
|
31072
31084
|
dataBar: undefined,
|
|
31073
|
-
iconSet: undefined,
|
|
31085
|
+
iconSet: undefined, // exist but isn't an operator in o_spreadsheet
|
|
31074
31086
|
top10: undefined,
|
|
31075
31087
|
uniqueValues: undefined,
|
|
31076
31088
|
duplicateValues: undefined,
|
|
@@ -31305,7 +31317,7 @@
|
|
|
31305
31317
|
61: "993366",
|
|
31306
31318
|
62: "333399",
|
|
31307
31319
|
63: "333333",
|
|
31308
|
-
64: "000000",
|
|
31320
|
+
64: "000000", // system foreground
|
|
31309
31321
|
65: "FFFFFF", // system background
|
|
31310
31322
|
};
|
|
31311
31323
|
const IMAGE_MIMETYPE_TO_EXTENSION_MAPPING = {
|
|
@@ -34975,12 +34987,13 @@
|
|
|
34975
34987
|
this.clearBorders(cmd.sheetId, cmd.target);
|
|
34976
34988
|
break;
|
|
34977
34989
|
case "REMOVE_COLUMNS_ROWS":
|
|
34978
|
-
|
|
34990
|
+
const elements = [...cmd.elements].sort((a, b) => b - a);
|
|
34991
|
+
for (const group of groupConsecutive(elements)) {
|
|
34979
34992
|
if (cmd.dimension === "COL") {
|
|
34980
|
-
this.shiftBordersHorizontally(cmd.sheetId,
|
|
34993
|
+
this.shiftBordersHorizontally(cmd.sheetId, group[group.length - 1] + 1, -group.length);
|
|
34981
34994
|
}
|
|
34982
34995
|
else {
|
|
34983
|
-
this.shiftBordersVertically(cmd.sheetId,
|
|
34996
|
+
this.shiftBordersVertically(cmd.sheetId, group[group.length - 1] + 1, -group.length);
|
|
34984
34997
|
}
|
|
34985
34998
|
}
|
|
34986
34999
|
break;
|
|
@@ -40012,12 +40025,7 @@
|
|
|
40012
40025
|
});
|
|
40013
40026
|
}
|
|
40014
40027
|
if (colIndex > deletedColumn) {
|
|
40015
|
-
this.
|
|
40016
|
-
sheetId: sheet.id,
|
|
40017
|
-
cellId: cellId,
|
|
40018
|
-
col: colIndex - 1,
|
|
40019
|
-
row: rowIndex,
|
|
40020
|
-
});
|
|
40028
|
+
this.setNewPosition(cellId, sheet.id, colIndex - 1, rowIndex);
|
|
40021
40029
|
}
|
|
40022
40030
|
}
|
|
40023
40031
|
}
|
|
@@ -40027,7 +40035,7 @@
|
|
|
40027
40035
|
* Move the cells after a column or rows insertion
|
|
40028
40036
|
*/
|
|
40029
40037
|
moveCellsOnAddition(sheet, addedElement, quantity, dimension) {
|
|
40030
|
-
const
|
|
40038
|
+
const updates = [];
|
|
40031
40039
|
for (let rowIndex = 0; rowIndex < sheet.rows.length; rowIndex++) {
|
|
40032
40040
|
const row = sheet.rows[rowIndex];
|
|
40033
40041
|
if (dimension !== "rows" || rowIndex >= addedElement) {
|
|
@@ -40036,20 +40044,20 @@
|
|
|
40036
40044
|
const cellId = row.cells[i];
|
|
40037
40045
|
if (cellId) {
|
|
40038
40046
|
if (dimension === "rows" || colIndex >= addedElement) {
|
|
40039
|
-
|
|
40040
|
-
type: "UPDATE_CELL_POSITION",
|
|
40047
|
+
updates.push({
|
|
40041
40048
|
sheetId: sheet.id,
|
|
40042
40049
|
cellId: cellId,
|
|
40043
40050
|
col: colIndex + (dimension === "columns" ? quantity : 0),
|
|
40044
40051
|
row: rowIndex + (dimension === "rows" ? quantity : 0),
|
|
40052
|
+
type: "UPDATE_CELL_POSITION",
|
|
40045
40053
|
});
|
|
40046
40054
|
}
|
|
40047
40055
|
}
|
|
40048
40056
|
}
|
|
40049
40057
|
}
|
|
40050
40058
|
}
|
|
40051
|
-
for (let
|
|
40052
|
-
this.
|
|
40059
|
+
for (let update of updates.reverse()) {
|
|
40060
|
+
this.updateCellPosition(update);
|
|
40053
40061
|
}
|
|
40054
40062
|
}
|
|
40055
40063
|
/**
|
|
@@ -40082,12 +40090,7 @@
|
|
|
40082
40090
|
const colIndex = Number(i);
|
|
40083
40091
|
const cellId = row.cells[i];
|
|
40084
40092
|
if (cellId) {
|
|
40085
|
-
this.
|
|
40086
|
-
sheetId: sheet.id,
|
|
40087
|
-
cellId: cellId,
|
|
40088
|
-
col: colIndex,
|
|
40089
|
-
row: rowIndex - numberRows,
|
|
40090
|
-
});
|
|
40093
|
+
this.setNewPosition(cellId, sheet.id, colIndex, rowIndex - numberRows);
|
|
40091
40094
|
}
|
|
40092
40095
|
}
|
|
40093
40096
|
}
|
|
@@ -42696,17 +42699,17 @@
|
|
|
42696
42699
|
*/
|
|
42697
42700
|
function sortWithClusters(colorsToSort) {
|
|
42698
42701
|
const clusters = [
|
|
42699
|
-
{ leadColor: rgba(255, 0, 0), colors: [] },
|
|
42700
|
-
{ leadColor: rgba(255, 128, 0), colors: [] },
|
|
42701
|
-
{ leadColor: rgba(128, 128, 0), colors: [] },
|
|
42702
|
-
{ leadColor: rgba(128, 255, 0), colors: [] },
|
|
42703
|
-
{ leadColor: rgba(0, 255, 0), colors: [] },
|
|
42704
|
-
{ leadColor: rgba(0, 255, 128), colors: [] },
|
|
42705
|
-
{ leadColor: rgba(0, 255, 255), colors: [] },
|
|
42706
|
-
{ leadColor: rgba(0, 127, 255), colors: [] },
|
|
42707
|
-
{ leadColor: rgba(0, 0, 255), colors: [] },
|
|
42708
|
-
{ leadColor: rgba(127, 0, 255), colors: [] },
|
|
42709
|
-
{ leadColor: rgba(128, 0, 128), colors: [] },
|
|
42702
|
+
{ leadColor: rgba(255, 0, 0), colors: [] }, // red
|
|
42703
|
+
{ leadColor: rgba(255, 128, 0), colors: [] }, // orange
|
|
42704
|
+
{ leadColor: rgba(128, 128, 0), colors: [] }, // yellow
|
|
42705
|
+
{ leadColor: rgba(128, 255, 0), colors: [] }, // chartreuse
|
|
42706
|
+
{ leadColor: rgba(0, 255, 0), colors: [] }, // green
|
|
42707
|
+
{ leadColor: rgba(0, 255, 128), colors: [] }, // spring green
|
|
42708
|
+
{ leadColor: rgba(0, 255, 255), colors: [] }, // cyan
|
|
42709
|
+
{ leadColor: rgba(0, 127, 255), colors: [] }, // azure
|
|
42710
|
+
{ leadColor: rgba(0, 0, 255), colors: [] }, // blue
|
|
42711
|
+
{ leadColor: rgba(127, 0, 255), colors: [] }, // violet
|
|
42712
|
+
{ leadColor: rgba(128, 0, 128), colors: [] }, // magenta
|
|
42710
42713
|
{ leadColor: rgba(255, 0, 128), colors: [] }, // rose
|
|
42711
42714
|
];
|
|
42712
42715
|
for (const color of colorsToSort.map(colorToRGBA)) {
|
|
@@ -52493,7 +52496,7 @@
|
|
|
52493
52496
|
.map((sheetEl) => sheetEl.getBoundingClientRect())
|
|
52494
52497
|
.map((rect) => ({
|
|
52495
52498
|
x: rect.x,
|
|
52496
|
-
width: rect.width - 1,
|
|
52499
|
+
width: rect.width - 1, // -1 to compensate negative margin
|
|
52497
52500
|
y: rect.y,
|
|
52498
52501
|
height: rect.height,
|
|
52499
52502
|
}));
|
|
@@ -52715,7 +52718,7 @@
|
|
|
52715
52718
|
}
|
|
52716
52719
|
return cssPropertiesToCss({
|
|
52717
52720
|
top: `${groupBox.headerRect.height / 2}px`,
|
|
52718
|
-
left: `calc(50% - 1px)`,
|
|
52721
|
+
left: `calc(50% - 1px)`, // -1px: we want the border to be on the center
|
|
52719
52722
|
width: `30%`,
|
|
52720
52723
|
height: `calc(100% - ${groupBox.headerRect.height / 2}px)`,
|
|
52721
52724
|
"border-left": `1px solid ${HEADER_GROUPING_BORDER_COLOR}`,
|
|
@@ -52767,7 +52770,7 @@
|
|
|
52767
52770
|
return "";
|
|
52768
52771
|
}
|
|
52769
52772
|
return cssPropertiesToCss({
|
|
52770
|
-
top: `calc(50% - 1px)`,
|
|
52773
|
+
top: `calc(50% - 1px)`, // -1px: we want the border to be on the center
|
|
52771
52774
|
left: `${groupBox.headerRect.width / 2}px`,
|
|
52772
52775
|
width: `calc(100% - ${groupBox.headerRect.width / 2}px)`,
|
|
52773
52776
|
height: `30%`,
|
|
@@ -54178,7 +54181,7 @@
|
|
|
54178
54181
|
const gridColSize = GROUP_LAYER_WIDTH * this.rowLayers.length;
|
|
54179
54182
|
const gridRowSize = GROUP_LAYER_WIDTH * this.colLayers.length;
|
|
54180
54183
|
return cssPropertiesToCss({
|
|
54181
|
-
"grid-template-columns": `${gridColSize ? gridColSize + 2 : 0}px auto`,
|
|
54184
|
+
"grid-template-columns": `${gridColSize ? gridColSize + 2 : 0}px auto`, // +2: margins
|
|
54182
54185
|
"grid-template-rows": `${gridRowSize ? gridRowSize + 2 : 0}px auto`,
|
|
54183
54186
|
});
|
|
54184
54187
|
}
|
|
@@ -55623,7 +55626,7 @@
|
|
|
55623
55626
|
}
|
|
55624
55627
|
|
|
55625
55628
|
class StateObserver {
|
|
55626
|
-
changes
|
|
55629
|
+
changes;
|
|
55627
55630
|
commands = [];
|
|
55628
55631
|
/**
|
|
55629
55632
|
* Record the changes which could happen in the given callback, save them in a
|
|
@@ -55655,7 +55658,7 @@
|
|
|
55655
55658
|
if (value[key] === val) {
|
|
55656
55659
|
return;
|
|
55657
55660
|
}
|
|
55658
|
-
this.changes
|
|
55661
|
+
this.changes?.push({
|
|
55659
55662
|
path: args,
|
|
55660
55663
|
before: value[key],
|
|
55661
55664
|
after: val,
|
|
@@ -56786,7 +56789,7 @@
|
|
|
56786
56789
|
const colHeaderXc = toXC(tableZone.left + i, tableZone.top);
|
|
56787
56790
|
const colName = sheetData.cells[colHeaderXc]?.content || `col${i}`;
|
|
56788
56791
|
const colAttributes = [
|
|
56789
|
-
["id", i + 1],
|
|
56792
|
+
["id", i + 1], // id cannot be 0
|
|
56790
56793
|
["name", colName],
|
|
56791
56794
|
];
|
|
56792
56795
|
columns.push(escapeXml /*xml*/ `<tableColumn ${formatAttributes(colAttributes)}/>`);
|
|
@@ -57878,9 +57881,9 @@
|
|
|
57878
57881
|
exports.tokenize = tokenize;
|
|
57879
57882
|
|
|
57880
57883
|
|
|
57881
|
-
__info__.version = "17.1.
|
|
57882
|
-
__info__.date = "2024-
|
|
57883
|
-
__info__.hash = "
|
|
57884
|
+
__info__.version = "17.1.26";
|
|
57885
|
+
__info__.date = "2024-08-02T08:23:08.499Z";
|
|
57886
|
+
__info__.hash = "4ba7e55";
|
|
57884
57887
|
|
|
57885
57888
|
|
|
57886
57889
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|