@odoo/o-spreadsheet 18.3.7 → 18.3.9
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 +125 -56
- package/dist/o-spreadsheet.esm.js +125 -56
- package/dist/o-spreadsheet.iife.js +125 -56
- package/dist/o-spreadsheet.iife.min.js +165 -165
- package/dist/o_spreadsheet.xml +3 -3
- 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 18.3.
|
|
6
|
-
* @date 2025-06-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.3.9
|
|
6
|
+
* @date 2025-06-19T18:24:02.754Z
|
|
7
|
+
* @hash a820230
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -5880,7 +5880,9 @@ function isTextFormat(format) {
|
|
|
5880
5880
|
}
|
|
5881
5881
|
|
|
5882
5882
|
function evaluateLiteral(literalCell, localeFormat) {
|
|
5883
|
-
const value = isTextFormat(localeFormat.format)
|
|
5883
|
+
const value = isTextFormat(localeFormat.format) && literalCell.parsedValue !== null
|
|
5884
|
+
? literalCell.content
|
|
5885
|
+
: literalCell.parsedValue;
|
|
5884
5886
|
const functionResult = { value, format: localeFormat.format };
|
|
5885
5887
|
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
5886
5888
|
}
|
|
@@ -5929,6 +5931,9 @@ function _createEvaluatedCell(functionResult, locale, cell) {
|
|
|
5929
5931
|
if (isEvaluationError(value)) {
|
|
5930
5932
|
return errorCell(value, message);
|
|
5931
5933
|
}
|
|
5934
|
+
if (value === null) {
|
|
5935
|
+
return emptyCell(format);
|
|
5936
|
+
}
|
|
5932
5937
|
if (isTextFormat(format)) {
|
|
5933
5938
|
// TO DO:
|
|
5934
5939
|
// with the next line, the value of the cell is transformed depending on the format.
|
|
@@ -5936,9 +5941,6 @@ function _createEvaluatedCell(functionResult, locale, cell) {
|
|
|
5936
5941
|
// to interpret the value as a number.
|
|
5937
5942
|
return textCell(toString(value), format, formattedValue);
|
|
5938
5943
|
}
|
|
5939
|
-
if (value === null) {
|
|
5940
|
-
return emptyCell(format);
|
|
5941
|
-
}
|
|
5942
5944
|
if (typeof value === "number") {
|
|
5943
5945
|
if (isDateTimeFormat(format || "")) {
|
|
5944
5946
|
return dateTimeCell(value, format, formattedValue);
|
|
@@ -20949,6 +20951,7 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
20949
20951
|
if (isTrendLineAxis(dataset.xAxisID) || dataset.hidden) {
|
|
20950
20952
|
continue;
|
|
20951
20953
|
}
|
|
20954
|
+
const yAxisScale = chart.scales[dataset.yAxisID];
|
|
20952
20955
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
20953
20956
|
const parsedValue = dataset._parsed[i];
|
|
20954
20957
|
const value = Number(chart.config.type === "radar" ? parsedValue.r : parsedValue.y);
|
|
@@ -20959,10 +20962,18 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
20959
20962
|
const xPosition = point.x;
|
|
20960
20963
|
let yPosition = 0;
|
|
20961
20964
|
if (chart.config.type === "line" || chart.config.type === "radar") {
|
|
20962
|
-
yPosition = point.y - 10;
|
|
20965
|
+
yPosition = value < 0 ? point.y + 10 : point.y - 10;
|
|
20963
20966
|
}
|
|
20964
20967
|
else {
|
|
20965
|
-
|
|
20968
|
+
const yZeroLine = yAxisScale.getPixelForValue(0);
|
|
20969
|
+
const distanceFromAxisOrigin = Math.abs(yZeroLine - point.y);
|
|
20970
|
+
const textHeight = 12; // ChartJS default text height
|
|
20971
|
+
if (distanceFromAxisOrigin < textHeight) {
|
|
20972
|
+
yPosition = value < 0 ? yZeroLine + textHeight / 2 : yZeroLine - textHeight / 2;
|
|
20973
|
+
}
|
|
20974
|
+
else {
|
|
20975
|
+
yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
|
|
20976
|
+
}
|
|
20966
20977
|
}
|
|
20967
20978
|
yPosition = Math.min(yPosition, yMax);
|
|
20968
20979
|
yPosition = Math.max(yPosition, yMin);
|
|
@@ -20972,7 +20983,7 @@ function drawLineOrBarOrRadarChartValues(chart, options, ctx) {
|
|
|
20972
20983
|
}
|
|
20973
20984
|
for (const otherPosition of textsPositions[xPosition] || []) {
|
|
20974
20985
|
if (Math.abs(otherPosition - yPosition) < 13) {
|
|
20975
|
-
yPosition = otherPosition - 13;
|
|
20986
|
+
yPosition = value < 0 ? otherPosition + 13 : otherPosition - 13;
|
|
20976
20987
|
}
|
|
20977
20988
|
}
|
|
20978
20989
|
textsPositions[xPosition].push(yPosition);
|
|
@@ -20991,6 +21002,8 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
|
20991
21002
|
if (isTrendLineAxis(dataset.xAxisID)) {
|
|
20992
21003
|
return; // ignore trend lines
|
|
20993
21004
|
}
|
|
21005
|
+
const xAxisScale = chart.scales[dataset.xAxisID];
|
|
21006
|
+
const xZeroLine = xAxisScale.getPixelForValue(0);
|
|
20994
21007
|
for (let i = 0; i < dataset._parsed.length; i++) {
|
|
20995
21008
|
const value = Number(dataset._parsed[i].x);
|
|
20996
21009
|
if (isNaN(value)) {
|
|
@@ -20999,17 +21012,27 @@ function drawHorizontalBarChartValues(chart, options, ctx) {
|
|
|
20999
21012
|
const displayValue = options.callback(value, dataset, i);
|
|
21000
21013
|
const point = dataset.data[i];
|
|
21001
21014
|
const yPosition = point.y;
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
|
|
21015
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
21016
|
+
const distanceFromAxisOrigin = Math.abs(point.x - xZeroLine);
|
|
21017
|
+
const PADDING = 3;
|
|
21018
|
+
let xPosition;
|
|
21019
|
+
if (distanceFromAxisOrigin < textWidth) {
|
|
21020
|
+
xPosition =
|
|
21021
|
+
value < 0 ? xZeroLine - textWidth / 2 - PADDING : xZeroLine + textWidth / 2 + PADDING;
|
|
21022
|
+
}
|
|
21023
|
+
else {
|
|
21024
|
+
xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
|
|
21025
|
+
xPosition = Math.min(xPosition, xMax);
|
|
21026
|
+
xPosition = Math.max(xPosition, xMin);
|
|
21027
|
+
}
|
|
21005
21028
|
// Avoid overlapping texts with same Y
|
|
21006
21029
|
if (!textsPositions[yPosition]) {
|
|
21007
21030
|
textsPositions[yPosition] = [];
|
|
21008
21031
|
}
|
|
21009
|
-
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
|
|
21010
21032
|
for (const otherPosition of textsPositions[yPosition]) {
|
|
21011
21033
|
if (Math.abs(otherPosition - xPosition) < textWidth) {
|
|
21012
|
-
xPosition =
|
|
21034
|
+
xPosition =
|
|
21035
|
+
value < 0 ? otherPosition - textWidth - PADDING : otherPosition + textWidth + PADDING;
|
|
21013
21036
|
}
|
|
21014
21037
|
}
|
|
21015
21038
|
textsPositions[yPosition].push(xPosition);
|
|
@@ -21031,10 +21054,22 @@ function drawPieChartValues(chart, options, ctx) {
|
|
|
21031
21054
|
const midAngle = (startAngle + endAngle) / 2;
|
|
21032
21055
|
const midRadius = (innerRadius + outerRadius) / 2;
|
|
21033
21056
|
const x = bar.x + midRadius * Math.cos(midAngle);
|
|
21034
|
-
const y = bar.y + midRadius * Math.sin(midAngle)
|
|
21057
|
+
const y = bar.y + midRadius * Math.sin(midAngle);
|
|
21058
|
+
const displayValue = options.callback(value, dataset, i);
|
|
21059
|
+
const textHeight = 12; // ChartJS default
|
|
21060
|
+
const textWidth = computeTextWidth(ctx, displayValue, { fontSize: textHeight }, "px");
|
|
21061
|
+
const radius = outerRadius - innerRadius;
|
|
21062
|
+
// Check if the text fits in the slice. Not perfect, but good enough heuristic.
|
|
21063
|
+
if (textWidth >= radius || radius < textHeight) {
|
|
21064
|
+
continue;
|
|
21065
|
+
}
|
|
21066
|
+
const sliceAngle = endAngle - startAngle;
|
|
21067
|
+
const midWidth = 2 * midRadius * Math.tan(sliceAngle / 2);
|
|
21068
|
+
if (sliceAngle < Math.PI / 2 && (textWidth >= midWidth || midWidth < textHeight)) {
|
|
21069
|
+
continue;
|
|
21070
|
+
}
|
|
21035
21071
|
ctx.fillStyle = chartFontColor(options.background);
|
|
21036
21072
|
ctx.strokeStyle = options.background || "#ffffff";
|
|
21037
|
-
const displayValue = options.callback(value, dataset, i);
|
|
21038
21073
|
drawTextWithBackground(displayValue, x, y, ctx);
|
|
21039
21074
|
}
|
|
21040
21075
|
}
|
|
@@ -26384,7 +26419,9 @@ function getPyramidChartShowValues(definition, args) {
|
|
|
26384
26419
|
background: definition.background,
|
|
26385
26420
|
callback: (value, dataset) => {
|
|
26386
26421
|
value = Math.abs(Number(value));
|
|
26387
|
-
return
|
|
26422
|
+
return value === 0
|
|
26423
|
+
? ""
|
|
26424
|
+
: formatChartDatasetValue(axisFormats, locale)(value, dataset.xAxisID || "x");
|
|
26388
26425
|
},
|
|
26389
26426
|
};
|
|
26390
26427
|
}
|
|
@@ -33170,7 +33207,7 @@ class XlsxBaseExtractor {
|
|
|
33170
33207
|
*/
|
|
33171
33208
|
handleMissingValue(parentElement, missingElementName, optionalArgs) {
|
|
33172
33209
|
if (optionalArgs?.required) {
|
|
33173
|
-
if (optionalArgs?.default) {
|
|
33210
|
+
if (optionalArgs?.default !== undefined) {
|
|
33174
33211
|
this.warningManager.addParsingWarning(`Missing required ${missingElementName} in element <${parentElement.tagName}> of ${this.currentFile}, replacing it by the default value ${optionalArgs.default}`);
|
|
33175
33212
|
}
|
|
33176
33213
|
else {
|
|
@@ -36123,19 +36160,26 @@ class FilterMenu extends Component {
|
|
|
36123
36160
|
.filter(({ row }) => !this.env.model.getters.isRowHidden(sheetId, row))
|
|
36124
36161
|
.map(({ col, row }) => this.env.model.getters.getEvaluatedCell({ sheetId, col, row }).formattedValue);
|
|
36125
36162
|
const filterValues = this.env.model.getters.getFilterHiddenValues({ sheetId, ...position });
|
|
36126
|
-
const
|
|
36127
|
-
const
|
|
36128
|
-
|
|
36129
|
-
const
|
|
36130
|
-
|
|
36131
|
-
|
|
36132
|
-
|
|
36133
|
-
|
|
36134
|
-
|
|
36135
|
-
|
|
36136
|
-
|
|
36137
|
-
|
|
36138
|
-
|
|
36163
|
+
const normalizedFilteredValues = new Set(filterValues.map(toLowerCase));
|
|
36164
|
+
const set = new Set();
|
|
36165
|
+
const values = [];
|
|
36166
|
+
const addValue = (value) => {
|
|
36167
|
+
const normalizedValue = toLowerCase(value);
|
|
36168
|
+
if (!set.has(normalizedValue)) {
|
|
36169
|
+
values.push({
|
|
36170
|
+
string: value || "",
|
|
36171
|
+
checked: !normalizedFilteredValues.has(normalizedValue),
|
|
36172
|
+
normalizedValue,
|
|
36173
|
+
});
|
|
36174
|
+
set.add(normalizedValue);
|
|
36175
|
+
}
|
|
36176
|
+
};
|
|
36177
|
+
cellValues.forEach(addValue);
|
|
36178
|
+
filterValues.forEach(addValue);
|
|
36179
|
+
return values.sort((val1, val2) => val1.normalizedValue.localeCompare(val2.normalizedValue, undefined, {
|
|
36180
|
+
numeric: true,
|
|
36181
|
+
sensitivity: "base",
|
|
36182
|
+
}));
|
|
36139
36183
|
}
|
|
36140
36184
|
checkValue(value) {
|
|
36141
36185
|
this.state.selectedValue = value.string;
|
|
@@ -37110,6 +37154,10 @@ const REMOVE_ROWS_ACTION = (env) => {
|
|
|
37110
37154
|
});
|
|
37111
37155
|
};
|
|
37112
37156
|
const CAN_REMOVE_COLUMNS_ROWS = (dimension, env) => {
|
|
37157
|
+
if ((dimension === "COL" && env.model.getters.getActiveRows().size > 0) ||
|
|
37158
|
+
(dimension === "ROW" && env.model.getters.getActiveCols().size > 0)) {
|
|
37159
|
+
return false;
|
|
37160
|
+
}
|
|
37113
37161
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
37114
37162
|
const selectedElements = env.model.getters.getElementsFromSelection(dimension);
|
|
37115
37163
|
const includesAllVisibleHeaders = env.model.getters.checkElementsIncludeAllVisibleHeaders(sheetId, dimension, selectedElements);
|
|
@@ -40007,11 +40055,11 @@ class OTRegistry extends Registry {
|
|
|
40007
40055
|
* transformation function given
|
|
40008
40056
|
*/
|
|
40009
40057
|
addTransformation(executed, toTransforms, fn) {
|
|
40010
|
-
|
|
40011
|
-
|
|
40012
|
-
|
|
40013
|
-
|
|
40014
|
-
this.content[
|
|
40058
|
+
if (!this.content[executed]) {
|
|
40059
|
+
this.content[executed] = new Map();
|
|
40060
|
+
}
|
|
40061
|
+
for (const toTransform of toTransforms) {
|
|
40062
|
+
this.content[executed].set(toTransform, fn);
|
|
40015
40063
|
}
|
|
40016
40064
|
return this;
|
|
40017
40065
|
}
|
|
@@ -40020,7 +40068,7 @@ class OTRegistry extends Registry {
|
|
|
40020
40068
|
* that the executed command happened.
|
|
40021
40069
|
*/
|
|
40022
40070
|
getTransformation(toTransform, executed) {
|
|
40023
|
-
return this.content[
|
|
40071
|
+
return this.content[executed] && this.content[executed].get(toTransform);
|
|
40024
40072
|
}
|
|
40025
40073
|
}
|
|
40026
40074
|
const otRegistry = new OTRegistry();
|
|
@@ -43310,6 +43358,12 @@ class Composer extends Component {
|
|
|
43310
43358
|
useEffect(() => {
|
|
43311
43359
|
this.processTokenAtCursor();
|
|
43312
43360
|
}, () => [this.props.composerStore.editionMode !== "inactive"]);
|
|
43361
|
+
useEffect(() => {
|
|
43362
|
+
this.contentHelper.scrollSelectionIntoView();
|
|
43363
|
+
}, () => [
|
|
43364
|
+
this.props.composerStore.composerSelection.start,
|
|
43365
|
+
this.props.composerStore.composerSelection.end,
|
|
43366
|
+
]);
|
|
43313
43367
|
}
|
|
43314
43368
|
// ---------------------------------------------------------------------------
|
|
43315
43369
|
// Handlers
|
|
@@ -43532,6 +43586,7 @@ class Composer extends Component {
|
|
|
43532
43586
|
// not main button, probably a context menu
|
|
43533
43587
|
return;
|
|
43534
43588
|
}
|
|
43589
|
+
this.debouncedHover.stopDebounce();
|
|
43535
43590
|
this.contentHelper.removeSelection();
|
|
43536
43591
|
}
|
|
43537
43592
|
onMouseup() {
|
|
@@ -43610,7 +43665,6 @@ class Composer extends Component {
|
|
|
43610
43665
|
const { start, end } = this.props.composerStore.composerSelection;
|
|
43611
43666
|
this.contentHelper.selectRange(start, end);
|
|
43612
43667
|
}
|
|
43613
|
-
this.contentHelper.scrollSelectionIntoView();
|
|
43614
43668
|
}
|
|
43615
43669
|
this.shouldProcessInputEvents = true;
|
|
43616
43670
|
}
|
|
@@ -61476,7 +61530,9 @@ class TablePlugin extends CorePlugin {
|
|
|
61476
61530
|
const ranges = cmd.ranges.map((rangeData) => this.getters.getRangeFromRangeData(rangeData));
|
|
61477
61531
|
const union = this.getters.getRangesUnion(ranges);
|
|
61478
61532
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
61479
|
-
|
|
61533
|
+
if (mergesInTarget.length) {
|
|
61534
|
+
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
61535
|
+
}
|
|
61480
61536
|
const id = this.consumeNextId();
|
|
61481
61537
|
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
61482
61538
|
const newTable = cmd.tableType === "dynamic"
|
|
@@ -61575,14 +61631,16 @@ class TablePlugin extends CorePlugin {
|
|
|
61575
61631
|
const zoneToCheckIfEmpty = direction === "down"
|
|
61576
61632
|
? { ...zone, bottom: zone.bottom + 1, top: zone.bottom + 1 }
|
|
61577
61633
|
: { ...zone, right: zone.right + 1, left: zone.right + 1 };
|
|
61578
|
-
for (
|
|
61579
|
-
|
|
61580
|
-
|
|
61581
|
-
|
|
61582
|
-
|
|
61583
|
-
|
|
61584
|
-
|
|
61585
|
-
|
|
61634
|
+
for (let row = zoneToCheckIfEmpty.top; row <= zoneToCheckIfEmpty.bottom; row++) {
|
|
61635
|
+
for (let col = zoneToCheckIfEmpty.left; col <= zoneToCheckIfEmpty.right; col++) {
|
|
61636
|
+
const cellPosition = { sheetId, col, row };
|
|
61637
|
+
// Since this plugin is loaded before CellPlugin, the getters still give us the old cell content
|
|
61638
|
+
const cellContent = this.getters.getCell(cellPosition)?.content;
|
|
61639
|
+
if (cellContent ||
|
|
61640
|
+
this.getters.isInMerge(cellPosition) ||
|
|
61641
|
+
this.getTablesOverlappingZones(sheetId, [positionToZone(cellPosition)]).length) {
|
|
61642
|
+
return "none";
|
|
61643
|
+
}
|
|
61586
61644
|
}
|
|
61587
61645
|
}
|
|
61588
61646
|
return direction;
|
|
@@ -67751,10 +67809,20 @@ function adaptTransform(toTransform, executed) {
|
|
|
67751
67809
|
*/
|
|
67752
67810
|
function transformAll(toTransform, executed) {
|
|
67753
67811
|
let transformedCommands = [...toTransform];
|
|
67812
|
+
const possibleTransformations = new Set(otRegistry.getKeys());
|
|
67754
67813
|
for (const executedCommand of executed) {
|
|
67755
|
-
|
|
67756
|
-
|
|
67757
|
-
|
|
67814
|
+
// If the executed command is not in the registry, we skip it
|
|
67815
|
+
// because we know there won't be any transformation impacting the
|
|
67816
|
+
// commands to transform.
|
|
67817
|
+
if (possibleTransformations.has(executedCommand.type)) {
|
|
67818
|
+
transformedCommands = transformedCommands.reduce((acc, cmd) => {
|
|
67819
|
+
const transformed = transform(cmd, executedCommand);
|
|
67820
|
+
if (transformed) {
|
|
67821
|
+
acc.push(transformed);
|
|
67822
|
+
}
|
|
67823
|
+
return acc;
|
|
67824
|
+
}, []);
|
|
67825
|
+
}
|
|
67758
67826
|
}
|
|
67759
67827
|
return transformedCommands;
|
|
67760
67828
|
}
|
|
@@ -69456,7 +69524,7 @@ class SheetUIPlugin extends UIPlugin {
|
|
|
69456
69524
|
}
|
|
69457
69525
|
const position = this.getters.getCellPosition(cell.id);
|
|
69458
69526
|
const colSize = this.getters.getColSize(sheetId, position.col);
|
|
69459
|
-
if (cell.isFormula) {
|
|
69527
|
+
if (cell.isFormula || this.getters.getArrayFormulaSpreadingOn(position)) {
|
|
69460
69528
|
const content = this.getters.getEvaluatedCell(position).formattedValue;
|
|
69461
69529
|
const evaluatedSize = getCellContentHeight(this.ctx, content, cell?.style, colSize);
|
|
69462
69530
|
if (evaluatedSize > evaluatedRowSize && evaluatedSize > DEFAULT_CELL_HEIGHT) {
|
|
@@ -71208,9 +71276,10 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
71208
71276
|
const filteredZone = filter.filteredRange?.zone;
|
|
71209
71277
|
if (!filteredValues || !filteredZone)
|
|
71210
71278
|
continue;
|
|
71279
|
+
const filteredValuesSet = new Set(filteredValues);
|
|
71211
71280
|
for (let row = filteredZone.top; row <= filteredZone.bottom; row++) {
|
|
71212
71281
|
const value = this.getCellValueAsString(sheetId, filter.col, row);
|
|
71213
|
-
if (
|
|
71282
|
+
if (filteredValuesSet.has(value)) {
|
|
71214
71283
|
hiddenRows.add(row);
|
|
71215
71284
|
}
|
|
71216
71285
|
}
|
|
@@ -80594,6 +80663,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
80594
80663
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
80595
80664
|
|
|
80596
80665
|
|
|
80597
|
-
__info__.version = "18.3.
|
|
80598
|
-
__info__.date = "2025-06-
|
|
80599
|
-
__info__.hash = "
|
|
80666
|
+
__info__.version = "18.3.9";
|
|
80667
|
+
__info__.date = "2025-06-19T18:24:02.754Z";
|
|
80668
|
+
__info__.hash = "a820230";
|