diff options
author | xuri <xuri.me@gmail.com> | 2021-02-09 00:12:53 +0800 |
---|---|---|
committer | xuri <xuri.me@gmail.com> | 2021-02-09 00:12:53 +0800 |
commit | 23c73ab527731f9d414e81f7ea15e2ae1a72a290 (patch) | |
tree | 82a213f884c2b0bbc8458843d9f6fb84d5fff38f /calc.go | |
parent | 30549c5e90884789fff6599d6e773d1ca56ba962 (diff) |
init new formula function: HLOOKUP
Diffstat (limited to 'calc.go')
-rw-r--r-- | calc.go | 62 |
1 files changed, 60 insertions, 2 deletions
@@ -2214,11 +2214,12 @@ func (fn *formulaFuncs) MDETERM(argsList *list.List) (result formulaArg) { num float64 numMtx = [][]float64{} err error - strMtx = argsList.Front().Value.(formulaArg).Matrix + strMtx [][]formulaArg ) if argsList.Len() < 1 { - return + return newErrorFormulaArg(formulaErrorVALUE, "MDETERM requires at least 1 argument") } + strMtx = argsList.Front().Value.(formulaArg).Matrix var rows = len(strMtx) for _, row := range argsList.Front().Value.(formulaArg).Matrix { if len(row) != rows { @@ -3705,6 +3706,63 @@ func compareFormulaArgMatrix(lhs, rhs formulaArg, caseSensitive, exactMatch bool return criteriaEq } +// HLOOKUP function 'looks up' a given value in the top row of a data array +// (or table), and returns the corresponding value from another row of the +// array. The syntax of the function is: +// +// HLOOKUP(lookup_value,table_array,row_index_num,[range_lookup]) +// +func (fn *formulaFuncs) HLOOKUP(argsList *list.List) formulaArg { + if argsList.Len() < 3 { + return newErrorFormulaArg(formulaErrorVALUE, "HLOOKUP requires at least 3 arguments") + } + if argsList.Len() > 4 { + return newErrorFormulaArg(formulaErrorVALUE, "HLOOKUP requires at most 4 arguments") + } + lookupValue := argsList.Front().Value.(formulaArg) + tableArray := argsList.Front().Next().Value.(formulaArg) + if tableArray.Type != ArgMatrix { + return newErrorFormulaArg(formulaErrorVALUE, "HLOOKUP requires second argument of table array") + } + rowArg := argsList.Front().Next().Next().Value.(formulaArg).ToNumber() + if rowArg.Type != ArgNumber { + return newErrorFormulaArg(formulaErrorVALUE, "HLOOKUP requires numeric row argument") + } + rowIdx, matchIdx, wasExact, exactMatch := int(rowArg.Number)-1, -1, false, false + if argsList.Len() == 4 { + rangeLookup := argsList.Back().Value.(formulaArg).ToBool() + if rangeLookup.Type == ArgError { + return newErrorFormulaArg(formulaErrorVALUE, rangeLookup.Error) + } + if rangeLookup.Number == 0 { + exactMatch = true + } + } + row := tableArray.Matrix[0] +start: + for idx, mtx := range row { + switch compareFormulaArg(mtx, lookupValue, false, exactMatch) { + case criteriaL: + matchIdx = idx + case criteriaEq: + matchIdx = idx + wasExact = true + break start + } + } + if matchIdx == -1 { + return newErrorFormulaArg(formulaErrorNA, "HLOOKUP no result found") + } + if rowIdx < 0 || rowIdx >= len(tableArray.Matrix) { + return newErrorFormulaArg(formulaErrorNA, "HLOOKUP has invalid row index") + } + row = tableArray.Matrix[rowIdx] + if wasExact || !exactMatch { + return row[matchIdx] + } + return newErrorFormulaArg(formulaErrorNA, "HLOOKUP no result found") +} + // VLOOKUP function 'looks up' a given value in the left-hand column of a // data array (or table), and returns the corresponding value from another // column of the array. The syntax of the function is: |