This closes #1476, support double-byte chars for formula functions LEFT,RIGHT, LEN and MID (#1477)

This commit is contained in:
Shugo Kawamura 2023-02-20 14:59:05 +09:00 committed by GitHub
parent cb0c1b012b
commit 983cd76485
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 8 deletions

15
calc.go
View File

@ -29,6 +29,7 @@ import (
"sync"
"time"
"unicode"
"unicode/utf8"
"unsafe"
"github.com/xuri/efp"
@ -13446,11 +13447,11 @@ func (fn *formulaFuncs) leftRight(name string, argsList *list.List) formulaArg {
}
numChars = int(numArg.Number)
}
if len(text) > numChars {
if utf8.RuneCountInString(text) > numChars {
if name == "LEFT" || name == "LEFTB" {
return newStringFormulaArg(text[:numChars])
return newStringFormulaArg(string([]rune(text)[:numChars]))
}
return newStringFormulaArg(text[len(text)-numChars:])
return newStringFormulaArg(string([]rune(text)[utf8.RuneCountInString(text)-numChars:]))
}
return newStringFormulaArg(text)
}
@ -13463,7 +13464,7 @@ func (fn *formulaFuncs) LEN(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "LEN requires 1 string argument")
}
return newStringFormulaArg(strconv.Itoa(len(argsList.Front().Value.(formulaArg).String)))
return newStringFormulaArg(strconv.Itoa(utf8.RuneCountInString(argsList.Front().Value.(formulaArg).String)))
}
// LENB returns the number of bytes used to represent the characters in a text
@ -13510,9 +13511,7 @@ func (fn *formulaFuncs) MIDB(argsList *list.List) formulaArg {
return fn.mid("MIDB", argsList)
}
// mid is an implementation of the formula functions MID and MIDB. TODO:
// support DBCS include Japanese, Chinese (Simplified), Chinese
// (Traditional), and Korean.
// mid is an implementation of the formula functions MID and MIDB.
func (fn *formulaFuncs) mid(name string, argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 3 arguments", name))
@ -13529,7 +13528,7 @@ func (fn *formulaFuncs) mid(name string, argsList *list.List) formulaArg {
if startNum < 0 {
return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
}
textLen := len(text)
textLen := utf8.RuneCountInString(text)
if startNum > textLen {
return newStringFormulaArg("")
}

View File

@ -1697,6 +1697,11 @@ func TestCalcCellValue(t *testing.T) {
"=LEFT(\"Original Text\",0)": "",
"=LEFT(\"Original Text\",13)": "Original Text",
"=LEFT(\"Original Text\",20)": "Original Text",
"=LEFT(\"オリジナルテキスト\")": "オ",
"=LEFT(\"オリジナルテキスト\",2)": "オリ",
"=LEFT(\"オリジナルテキスト\",5)": "オリジナル",
"=LEFT(\"オリジナルテキスト\",7)": "オリジナルテキ",
"=LEFT(\"オリジナルテキスト\",20)": "オリジナルテキスト",
// LEFTB
"=LEFTB(\"Original Text\")": "O",
"=LEFTB(\"Original Text\",4)": "Orig",
@ -1751,6 +1756,11 @@ func TestCalcCellValue(t *testing.T) {
"=RIGHT(\"Original Text\",0)": "",
"=RIGHT(\"Original Text\",13)": "Original Text",
"=RIGHT(\"Original Text\",20)": "Original Text",
"=RIGHT(\"オリジナルテキスト\")": "ト",
"=RIGHT(\"オリジナルテキスト\",2)": "スト",
"=RIGHT(\"オリジナルテキスト\",4)": "テキスト",
"=RIGHT(\"オリジナルテキスト\",7)": "ジナルテキスト",
"=RIGHT(\"オリジナルテキスト\",20)": "オリジナルテキスト",
// RIGHTB
"=RIGHTB(\"Original Text\")": "t",
"=RIGHTB(\"Original Text\",4)": "Text",