Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/mergeRefTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ const matcher = (
return best;
};

function isBangAfter (tokenlist: Token[], i: number): boolean {
const next = tokenlist[i + 1];
return !!next && next.type === OPERATOR && next.value === '!';
}

function commonMergeRefTokens (tokenlist: Token[], xlsx: boolean): Token[] {
const finalTokens = [];
// this seeks backwards because it's really the range part
Expand All @@ -217,6 +222,11 @@ function commonMergeRefTokens (tokenlist: Token[], xlsx: boolean): Token[] {
i -= valid - 1;
}
}
// A quoted scope with no `!` after it is a name, not a scope. One that has its `!` stays a
// scope, merged or not.
if (token.type === CONTEXT_QUOTE && !isBangAfter(tokenlist, i)) {
token = { ...token, type: REF_NAMED };
}
finalTokens[finalTokens.length] = token;
}
return finalTokens.reverse();
Expand Down
22 changes: 22 additions & 0 deletions lib/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,28 @@ describe('parser', () => {
isParsed("'A1:B2'!C3", { type: 'ReferenceIdentifier', value: "'A1:B2'!C3", kind: 'range' });
});

// Excel reads both as the range operator over the quoted name, and stores them with the
// second name quoted: `'Alpha:Beta':'Gamma'!A1` and `Alpha:'[1]Gamma'!A1`. In the second it
// is the workbook bracket that rules out a sheet range, not the quote, which Excel drops.
test('a quoted scope with no bang after it is a name operand', () => {
isParsed("'Alpha':[Book.xlsx]Gamma!A1", {
type: 'BinaryExpression',
operator: ':',
arguments: [
{ type: 'ReferenceIdentifier', value: "'Alpha'", kind: 'name' },
{ type: 'ReferenceIdentifier', value: '[Book.xlsx]Gamma!A1', kind: 'range' }
]
});
isParsed("'Alpha:Beta':Gamma!A1", {
type: 'BinaryExpression',
operator: ':',
arguments: [
{ type: 'ReferenceIdentifier', value: "'Alpha:Beta'", kind: 'name' },
{ type: 'ReferenceIdentifier', value: 'Gamma!A1', kind: 'range' }
]
});
});

test('"$" is not allowed on an unquoted sheet name', () => {
isInvalidExpr('=SUM($Jan:$Mar!A1)');
isParsed("'$Jan:$Mar'!A1", { type: 'ReferenceIdentifier', value: "'$Jan:$Mar'!A1", kind: 'range' });
Expand Down
10 changes: 6 additions & 4 deletions lib/tokenize-3d.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ describe('lexer: 3d ranges', () => {
{ type: REF_RANGE, value: 'A1' }
]);
expect(tokenize("'Alpha:Beta':Gamma!A1")).toEqual([
{ type: CONTEXT_QUOTE, value: "'Alpha:Beta'" },
{ type: REF_NAMED, value: "'Alpha:Beta'" },
{ type: OPERATOR, value: ':' },
{ type: REF_RANGE, value: 'Gamma!A1' }
]);
Expand Down Expand Up @@ -200,7 +200,7 @@ describe('lexer: 3d ranges', () => {
expect(tokenize("Alpha:'Beta:Gamma':Delta!A1")).toEqual([
{ type: REF_NAMED, value: 'Alpha' },
{ type: OPERATOR, value: ':' },
{ type: CONTEXT_QUOTE, value: "'Beta:Gamma'" },
{ type: REF_NAMED, value: "'Beta:Gamma'" },
{ type: OPERATOR, value: ':' },
{ type: REF_RANGE, value: 'Delta!A1' }
]);
Expand Down Expand Up @@ -317,8 +317,10 @@ describe('lexer: 3d ranges', () => {
{ type: OPERATOR, value: '!' },
{ type: REF_RANGE, value: 'A1' }
]);
// Nothing merges the first scope, because a workbook specifier is not allowed in the
// second. What is left has no `!` after it, so it is the operand Excel reads as a name.
expect(tokenize("'Alpha':[Book.xlsx]Gamma!A1")).toEqual([
{ type: CONTEXT_QUOTE, value: "'Alpha'" },
{ type: REF_NAMED, value: "'Alpha'" },
{ type: OPERATOR, value: ':' },
{ type: REF_RANGE, value: '[Book.xlsx]Gamma!A1' }
]);
Expand Down Expand Up @@ -380,7 +382,7 @@ describe('lexer: 3d ranges', () => {
{ type: REF_RANGE, value: 'A1' }
]);
expect(tokenize("'Alpha':'[Book.xlsx]Gamma'!A1")).toEqual([
{ type: CONTEXT_QUOTE, value: "'Alpha'" },
{ type: REF_NAMED, value: "'Alpha'" },
{ type: OPERATOR, value: ':' },
{ type: REF_RANGE, value: "'[Book.xlsx]Gamma'!A1" }
]);
Expand Down