handsontable / handsontable/hyperformula

Wrong result when using `ROW()` function inside a named expression

Open
#1,208 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Impact: Medium Named Expressions
Dominant language
TypeScript
Stars
2.8k
Forks
171
Avg merge
1d 22h
Merged PRs (30d)
7

Description

Description

I am seeing unexpected results with Named Expressions.

Given an expression

const getRowExpression = "=ROW()"

And a Named Expression registered on sheet 0

engine.addNamedExpression('GetRowNumber', getRowExpression, 0)

The following usage returns different results

const engine = HyperFormula.buildFromArray([
  [getRowExpression, "=GetRowNumber"],
  [getRowExpression, "=GetRowNumber"],
  [getRowExpression, "=GetRowNumber"],
  [getRowExpression, "=GetRowNumber"],
  [getRowExpression, "=GetRowNumber"],
])

A1:A5 => [0, 1, 2, 3, 4, 5]
B1:B5 => [2, 2, 2, 2, 2, 2]

I expected these values to be equal.

You can see a full example on JSFiddle (hyperformula-named-references-bug)

Or you can drop the following unit test into hyperformula/test/named-expressions.spec.ts on either the hyperformula::master or hyperformula:develop branches

  describe('bug', () => {
    it('basic example', () => {
      const getRowExpression = "=ROW()"

      const engine = HyperFormula.buildFromArray([
        [getRowExpression, "=GetRowNumber"],
        [getRowExpression, "=GetRowNumber"],
        [getRowExpression, "=GetRowNumber"],
        [getRowExpression, "=GetRowNumber"],
        [getRowExpression, "=GetRowNumber"],
      ])

      engine.addNamedExpression('GetRowNumber', getRowExpression, 0)

      console.log(engine.getRangeValues(AbsoluteCellRange.spanFrom(adr('A1', 0), 2, 5)))

      expect(engine.getCellValue(adr('A1', 0))).toEqual(1)
      expect(engine.getCellValue(adr('A2', 0))).toEqual(2)
      expect(engine.getCellValue(adr('A3', 0))).toEqual(3)
      expect(engine.getCellValue(adr('A4', 0))).toEqual(4)
      expect(engine.getCellValue(adr('A5', 0))).toEqual(5)

      /* all the values in B are equal to 2 - maybe an issue with caching the named expression? */
      expect(engine.getCellValue(adr('B1', 0))).toEqual(1)
      expect(engine.getCellValue(adr('B2', 0))).toEqual(2)
      expect(engine.getCellValue(adr('B3', 0))).toEqual(3)
      expect(engine.getCellValue(adr('B4', 0))).toEqual(4)
      expect(engine.getCellValue(adr('B5', 0))).toEqual(5)
    })

    it('moderate example', () => {
      const accountLookupExpression = "=IFNA(VLOOKUP(INDEX(ledger!$A:$A, ROW()),accounts!$A:$B,2,FALSE()),\"\")"

      const engine = HyperFormula.buildFromSheets({
        ledger: [
          [23, accountLookupExpression, "=AccountLookup"],
          [30, accountLookupExpression, "=AccountLookup"],
          [13, accountLookupExpression, "=AccountLookup"],
        ],
        accounts: [
          [23, "Office Supplies"],
          [13, "Rent"],
          [26, "Gas"],
          [20, "Maintenance"],
          [30, "Capital Improvements"],
        ]
      })

      engine.addNamedExpression('AccountLookup', accountLookupExpression, 0)

      console.log(engine.getRangeValues(AbsoluteCellRange.spanFrom(adr('A1', 0), 3, 3)))

      expect(engine.getCellValue(adr('B1', 0))).toEqual('Office Supplies')
      expect(engine.getCellValue(adr('B2', 0))).toEqual('Capital Improvements')
      expect(engine.getCellValue(adr('B3', 0))).toEqual('Rent')

      /* all the values in C are equal to 'Capital Improvements' - maybe an issue with caching the named expression? */
      expect(engine.getCellValue(adr('C1', 0))).toEqual('Office Supplies')
      expect(engine.getCellValue(adr('C2', 0))).toEqual('Capital Improvements')
      expect(engine.getCellValue(adr('C3', 0))).toEqual('Rent')
    })
  })
Steps to reproduce
  1. Run the provided JSFiddle (hyperformula-named-references-bug)
  2. Drop the provided unit test into named-expressions.spec.ts.
Your environment
  • HyperFormula version: 2.3.1, hyperformula::master, hyperformula:develop
  • Browser Name and version: Chrome
  • Operating System: Mac

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided reproductions in named-expressions.spec.ts, using HyperFormula.buildFromArray and buildFromSheets with ROW() inside named expressions. Run the basic and moderate examples, then compare the direct formula results with the named-expression results; done means both sets of assertions pass with row-relative values.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.