Skip to content

Commit

Permalink
Cover with tests and fix some corner cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Hristov committed Jan 3, 2025
1 parent 8af092e commit c5de21d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 15 deletions.
14 changes: 4 additions & 10 deletions calc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,7 @@ func pickColumnInTableRef(tblRef tableRef, colName string) (string, error) {
return "", fmt.Errorf("column `%s` not in table: %w", colName, errNotExistingColumn)
}

// Tables having just a single cell are invalid. Hence it is safe to assume it should always be a range reference.
coords, err := rangeRefToCoordinates(tblRef.ref)
if err != nil {
return "", err
Expand All @@ -1540,14 +1541,14 @@ func pickColumnInTableRef(tblRef tableRef, colName string) (string, error) {

func tryParseAsTableRef(ref string, tableRefs *sync.Map) (string, error) {
submatch := tableRefRe.FindStringSubmatch(ref)
tableName := submatch[1]
colName := submatch[2]

// Fallback to regular ref.
if len(submatch) != tableRefPartsCnt {
return ref, nil
}

tableName := submatch[1]
colName := submatch[2]

rawTblRef, ok := tableRefs.Load(tableName)
if !ok {
return "", fmt.Errorf("referencing table `%s`: %w", tableName, errNotExistingTable)
Expand All @@ -1558,13 +1559,6 @@ func tryParseAsTableRef(ref string, tableRefs *sync.Map) (string, error) {
panic(fmt.Sprintf("unexpected reference type %T", ref))
}

if !strings.Contains(tblRef.ref, ":") {
if len(tblRef.columns) != 1 && tblRef.columns[0] != colName {
return "", fmt.Errorf("column `%s` not in table `%s`: %w", colName, tableName, errNotExistingColumn)
}
return tblRef.ref, nil
}

return pickColumnInTableRef(tblRef, colName)
}

Expand Down
53 changes: 48 additions & 5 deletions calc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6448,16 +6448,59 @@ func TestCalcCellResolver(t *testing.T) {
}

func TestTableReference(t *testing.T) {
f := sheetWithTables(t)

assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=INDEX(FieryTable[Column1], 2)"), "cell formula for A1")
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "=INDEX(FieryTable[Column2], 2)"), "cell formula for A2")
assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "=B1*2"), "cell formula for A3")
assert.NoError(t, f.SetCellFormula("Sheet1", "D1", "=INDEX(FrostyTable[Column1], 2)"), "cell formula for A1")

res, err := f.CalcCellValue("Sheet1", "A1")
assert.NoError(t, err, "calculating cell A1")
assert.Equal(t, res, "Foo", "A1 calc is wrong")

res, err = f.CalcCellValue("Sheet1", "B1")
assert.NoError(t, err, "calculating cell B1")
assert.Equal(t, res, "12.5", "B1 calc is wrong")

res, err = f.CalcCellValue("Sheet1", "C1")
assert.NoError(t, err, "calculating cell C1")
assert.Equal(t, res, "25", "C1 calc is wrong")

res, err = f.CalcCellValue("Sheet1", "D1")
assert.NoError(t, err, "calculating cell D1")
assert.Equal(t, res, "Hedgehog", "D1 calc is wrong")
}

func TestTableReferenceToNotExistingTable(t *testing.T) {
f := sheetWithTables(t)
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=INDEX(NotExisting[Column1], 2)"), "cell formula for A1")

_, err := f.CalcCellValue("Sheet1", "A1")
assert.Error(t, err, "A1 calc is wrong")
}

func TestTableReferenceToNotExistingColumn(t *testing.T) {
f := sheetWithTables(t)
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=INDEX(FieryTable[NotExisting], 2)"), "cell formula for A1")

_, err := f.CalcCellValue("Sheet1", "A1")
assert.Error(t, err, "A1 calc is wrong")
}

func sheetWithTables(t *testing.T) *File {
f := NewFile()

assert.NoError(t, f.AddTable("Sheet1", &Table{Range: "A2:C5", Name: "FieryTable"}), "adding table")
// Multi column with default column names
assert.NoError(t, f.AddTable("Sheet1", &Table{Range: "A2:C5", Name: "FieryTable"}), "adding FieryTable")
assert.NoError(t, f.SetCellValue("Sheet1", "A3", "Foo"), "set A3")
assert.NoError(t, f.SetCellValue("Sheet1", "B3", "12.5"), "set A3")

assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "=INDEX(FieryTable[Column1], 2)"), "set cell formula for A1")
// Single column with renamed column
assert.NoError(t, f.AddTable("Sheet1", &Table{Range: "A8:A9", Name: "FrostyTable"}), "adding FrostyTable")
assert.NoError(t, f.SetCellValue("Sheet1", "A9", "Hedgehog"), "set A3")

res, err := f.CalcCellValue("Sheet1", "A1")
assert.NoError(t, err, "calculating cell value")
assert.Equal(t, res, "Foo", "asserting cell value calculated by referencing a table")
return f
}

func TestEvalInfixExp(t *testing.T) {
Expand Down

0 comments on commit c5de21d

Please sign in to comment.