- Fix a v2.8.0 regression bug, number format code apply result was empty
- Fix calculate formula functions CHITEST and MMULT panic in some cases
- Updated unit tests
This commit is contained in:
xuri 2023-09-14 22:56:28 +08:00
parent 49706c9018
commit 5a039f3045
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
4 changed files with 43 additions and 22 deletions

12
calc.go
View File

@ -4803,11 +4803,16 @@ func (fn *formulaFuncs) MMULT(argsList *list.List) formulaArg {
if argsList.Len() != 2 {
return newErrorFormulaArg(formulaErrorVALUE, "MMULT requires 2 argument")
}
numMtx1, errArg1 := newNumberMatrix(argsList.Front().Value.(formulaArg), false)
arr1 := argsList.Front().Value.(formulaArg)
arr2 := argsList.Back().Value.(formulaArg)
if arr1.Type == ArgNumber && arr2.Type == ArgNumber {
return newNumberFormulaArg(arr1.Number * arr2.Number)
}
numMtx1, errArg1 := newNumberMatrix(arr1, false)
if errArg1.Type == ArgError {
return errArg1
}
numMtx2, errArg2 := newNumberMatrix(argsList.Back().Value.(formulaArg), false)
numMtx2, errArg2 := newNumberMatrix(arr2, false)
if errArg2.Type == ArgError {
return errArg2
}
@ -7191,6 +7196,9 @@ func (fn *formulaFuncs) CHITEST(argsList *list.List) formulaArg {
actual, expected := argsList.Front().Value.(formulaArg), argsList.Back().Value.(formulaArg)
actualList, expectedList := actual.ToList(), expected.ToList()
rows := len(actual.Matrix)
if rows == 0 {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
columns := len(actualList) / rows
if len(actualList) != len(expectedList) || len(actualList) == 1 {
return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)

View File

@ -673,6 +673,8 @@ func TestCalcCellValue(t *testing.T) {
// MINVERSE
"=MINVERSE(A1:B2)": "-0",
// MMULT
"=MMULT(0,0)": "0",
"=MMULT(2,4)": "8",
"=MMULT(A4:A4,A4:A4)": "0",
// MOD
"=MOD(6,4)": "2",
@ -5139,16 +5141,17 @@ func TestCalcCHITESTandCHISQdotTEST(t *testing.T) {
assert.Equal(t, expected, result, formula)
}
calcError := map[string][]string{
"=CHITEST()": {"#VALUE!", "CHITEST requires 2 arguments"},
"=CHITEST(B3:C5,F3:F4)": {"#N/A", "#N/A"},
"=CHITEST(B3:B3,F3:F3)": {"#N/A", "#N/A"},
"=CHITEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"},
"=CHITEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"},
"=CHISQ.TEST()": {"#VALUE!", "CHISQ.TEST requires 2 arguments"},
"=CHISQ.TEST(B3:C5,F3:F4)": {"#N/A", "#N/A"},
"=CHISQ.TEST(B3:B3,F3:F3)": {"#N/A", "#N/A"},
"=CHISQ.TEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"},
"=CHISQ.TEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"},
"=CHITEST()": {"#VALUE!", "CHITEST requires 2 arguments"},
"=CHITEST(MUNIT(0),MUNIT(0))": {"#VALUE!", "#VALUE!"},
"=CHITEST(B3:C5,F3:F4)": {"#N/A", "#N/A"},
"=CHITEST(B3:B3,F3:F3)": {"#N/A", "#N/A"},
"=CHITEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"},
"=CHITEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"},
"=CHISQ.TEST()": {"#VALUE!", "CHISQ.TEST requires 2 arguments"},
"=CHISQ.TEST(B3:C5,F3:F4)": {"#N/A", "#N/A"},
"=CHISQ.TEST(B3:B3,F3:F3)": {"#N/A", "#N/A"},
"=CHISQ.TEST(F3:F5,B4:B6)": {"#NUM!", "#NUM!"},
"=CHISQ.TEST(F3:F5,C4:C6)": {"#DIV/0!", "#DIV/0!"},
}
for formula, expected := range calcError {
assert.NoError(t, f.SetCellFormula("Sheet1", "I1", formula))

View File

@ -4759,9 +4759,9 @@ func (nf *numberFormat) getNumberFmtConf() {
if token.TType == nfp.TokenTypeHashPlaceHolder {
if nf.usePointer {
nf.fracHolder += len(token.TValue)
} else {
nf.intHolder += len(token.TValue)
continue
}
nf.intHolder += len(token.TValue)
}
if token.TType == nfp.TokenTypeExponential {
nf.useScientificNotation = true
@ -4779,6 +4779,7 @@ func (nf *numberFormat) getNumberFmtConf() {
nf.switchArgument = token.TValue
}
if token.TType == nfp.TokenTypeZeroPlaceHolder {
nf.intHolder = 0
if nf.usePointer {
if nf.useScientificNotation {
nf.expBaseLen += len(token.TValue)
@ -4795,7 +4796,7 @@ func (nf *numberFormat) getNumberFmtConf() {
// printNumberLiteral apply literal tokens for the pre-formatted text.
func (nf *numberFormat) printNumberLiteral(text string) string {
var result string
var useLiteral, useZeroPlaceHolder bool
var useLiteral, usePlaceHolder bool
if nf.usePositive {
result += "-"
}
@ -4807,17 +4808,17 @@ func (nf *numberFormat) printNumberLiteral(text string) string {
result += nf.currencyString
}
if token.TType == nfp.TokenTypeLiteral {
if useZeroPlaceHolder {
if usePlaceHolder {
useLiteral = true
}
result += token.TValue
}
if token.TType == nfp.TokenTypeZeroPlaceHolder {
if useLiteral && useZeroPlaceHolder {
if token.TType == nfp.TokenTypeHashPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder {
if useLiteral && usePlaceHolder {
return nf.value
}
if !useZeroPlaceHolder {
useZeroPlaceHolder = true
if !usePlaceHolder {
usePlaceHolder = true
result += text
}
}
@ -4896,8 +4897,11 @@ func (nf *numberFormat) numberHandler() string {
result string
)
nf.getNumberFmtConf()
if intLen = intPart; nf.intPadding > intPart {
intLen = nf.intPadding
if nf.intHolder > intPart {
nf.intHolder = intPart
}
if intLen = intPart; nf.intPadding+nf.intHolder > intPart {
intLen = nf.intPadding + nf.intHolder
}
if fracLen = fracPart; fracPart > nf.fracHolder+nf.fracPadding {
fracLen = nf.fracHolder + nf.fracPadding

View File

@ -3504,6 +3504,12 @@ func TestNumFmt(t *testing.T) {
{"1234.5678", "#,##0 ;[red](#,##0)", "1,235 "},
{"1234.5678", "#,##0.00;(#,##0.00)", "1,234.57"},
{"1234.5678", "#,##0.00;[red](#,##0.00)", "1,234.57"},
{"1234.5678", "#", "1235"},
{"1234.5678", "#0", "1235"},
{"1234.5678", "##", "1235"},
{"1234.5678", "00000.00#", "01234.568"},
{"1234.5678", "00000####", "000001235"},
{"1234.5678", "00000######", "000001235"},
{"-1234.5678", "0.00", "-1234.57"},
{"-1234.5678", "0.00;-0.00", "-1234.57"},
{"-1234.5678", "0.00%%", "-12345678.00%%"},