Skip to content

Commit

Permalink
[FIX] tokenizer: recognized fixed full headers
Browse files Browse the repository at this point in the history
References with a fixed ($) right-hand part such as "1:$1", "A:$A"
or "$B$2:$2" are not recognized as REFERENCE tokens.

Task: 3571633
X-original-commit: c6ec93a
Part-of: #3306
  • Loading branch information
LucasLefevre committed Dec 1, 2023
1 parent 80760bb commit acedfb0
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/formulas/range_tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
concat,
isColHeader,
isColReference,
isRowHeader,
isRowReference,
isSingleCellReference,
} from "../helpers";
Expand Down Expand Up @@ -93,7 +94,7 @@ const machine: Machine = {
SPACE: goTo(State.RightRef),
NUMBER: goTo(State.Found),
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
},
[State.RightColumnRef]: {
SPACE: goTo(State.RightColumnRef),
Expand All @@ -104,6 +105,7 @@ const machine: Machine = {
SPACE: goTo(State.RightRowRef),
NUMBER: goTo(State.Found),
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
},
[State.Found]: {},
};
Expand Down
11 changes: 9 additions & 2 deletions src/helpers/references.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ export const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
// Same as above, but matches the exact string (nothing before or after)
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");

/** Reference of a column header (eg. A, AB) */
const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
/** Reference of a column header (eg. A, AB, $A) */
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");

/** Reference of a row header (eg. 1, $1) */
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");

/** Reference of a column (eg. A, $CA, Sheet1!B) */
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
Expand Down Expand Up @@ -49,6 +52,10 @@ export function isColHeader(str: string): boolean {
return colHeader.test(str);
}

export function isRowHeader(str: string): boolean {
return rowHeader.test(str);
}

/**
* Return true if the given xc is the reference of a single cell,
* without any specified sheet (e.g. A1)
Expand Down
24 changes: 22 additions & 2 deletions tests/formulas/range_tokenizer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("rangeTokenizer", () => {
]);
});

test.each(["A:A", "A1:A", "A:A1"])("full column", (xc) => {
test.each(["A:A", "A1:A", "A:A1", "$A:$A", "A:$A", "$A:A", "$B$2:$C"])("full column", (xc) => {
expect(rangeTokenize(`=${xc}`)).toEqual([
{ type: "OPERATOR", value: "=" },
{ type: "REFERENCE", value: xc },
Expand All @@ -89,7 +89,7 @@ describe("rangeTokenizer", () => {
]);
});

test.each(["1:1", "A1:1", "1:A1"])("full row", (xc) => {
test.each(["1:1", "A1:1", "1:A1", "$1:$1", "1:$1", "$1:1", "$B$1:$2"])("full row", (xc) => {
expect(rangeTokenize(`=${xc}`)).toEqual([
{ type: "OPERATOR", value: "=" },
{ type: "REFERENCE", value: xc },
Expand All @@ -112,11 +112,31 @@ describe("rangeTokenizer", () => {
{ type: "OPERATOR", value: ":" },
{ type: "SYMBOL", value: "A" },
]);
expect(rangeTokenize("1:$A")).toEqual([
{ type: "NUMBER", value: "1" },
{ type: "OPERATOR", value: ":" },
{ type: "SYMBOL", value: "$A" },
]);
expect(rangeTokenize("A:1")).toEqual([
{ type: "SYMBOL", value: "A" },
{ type: "OPERATOR", value: ":" },
{ type: "NUMBER", value: "1" },
]);
expect(rangeTokenize("A:$1")).toEqual([
{ type: "SYMBOL", value: "A" },
{ type: "OPERATOR", value: ":" },
{ type: "SYMBOL", value: "$1" },
]);
expect(rangeTokenize("1:Sheet1!2")).toEqual([
{ type: "NUMBER", value: "1" },
{ type: "OPERATOR", value: ":" },
{ type: "SYMBOL", value: "Sheet1!2" },
]);
expect(rangeTokenize("A:Sheet1!A")).toEqual([
{ type: "SYMBOL", value: "A" },
{ type: "OPERATOR", value: ":" },
{ type: "SYMBOL", value: "Sheet1!A" },
]);
});
});

Expand Down

0 comments on commit acedfb0

Please sign in to comment.