diff --git a/calc.go b/calc.go index c36e500942..b656145fed 100644 --- a/calc.go +++ b/calc.go @@ -18842,3 +18842,93 @@ func (fn *formulaFuncs) DISPIMG(argsList *list.List) formulaArg { } return argsList.Front().Value.(formulaArg) } + +// 定义泰语数字到泰语字符的映射 +var thaiDigits = map[int]string{0: "ศูนย์", 1: "หนึ่ง", 2: "สอง", 3: "สาม", 4: "สี่", 5: "ห้า", 6: "หก", 7: "เจ็ด", 8: "แปด", 9: "เก้า"} + +// 定义泰语数位单位 +var thaiUnits = []string{"", "สิบ", "ร้อย", "พัน", "หมื่น", "แสน", "ล้าน"} + +// numToThaiText 将数字转换为泰语数字文本 +func numToThaiText(num int) string { + if num == 0 { + return thaiDigits[0] + } + var result string + var pos int + for num > 0 { + digit := num % 10 + if digit > 0 { + if pos == 1 && digit == 2 { + result = "ยี่" + thaiUnits[pos] + result + } else if pos == 1 && digit == 1 { + result = thaiUnits[pos] + result + } else if pos == 0 && num > 10 && digit == 1 { + result = "เอ็ด" + result + } else { + result = thaiDigits[digit] + thaiUnits[pos] + result + } + } + num /= 10 + pos++ + } + return result +} + +// func (fn *formulaFuncs) BAHTTEXT 将数字转换为泰铢货币格式的文本 +func (fn *formulaFuncs) BAHTTEXT(argsList *list.List) formulaArg { + // 定义错误信息变量 + const ( + errNoArgMsg = "BAHTTEXT requires at least 1 argument" + errTooManyArgs = "BAHTTEXT requires 1 argument" + ) + + // 验证参数数量 + if argsList.Len() == 0 { + return newErrorFormulaArg(formulaErrorVALUE, errNoArgMsg) + } + if argsList.Len() > 1 { + return newErrorFormulaArg(formulaErrorVALUE, errTooManyArgs) + } + + // 提取并转换参数为数字 + numArg := argsList.Front().Value.(formulaArg) + num := numArg.ToNumber() + + // 检查转换结果是否为数字类型 + if num.Type != ArgNumber { + return num + } + + // 分离整数部分和小数部分 + integerPart := int(num.Number) + decimalPart := int((num.Number - float64(integerPart)) * 100) + + // 定义泰语货币单位变量 + const ( + bahtUnit = "บาท" + satangUnit = "สตางค์" + zeroBahtMsg = "ศูนย์บาทถ้วน" + ) + + // 转换整数部分为泰语文本 + // 转换整数部分为泰语文本 + var integerText string + if integerPart > 0 { + integerText = numToThaiText(integerPart) + bahtUnit + } + + // 转换小数部分为泰语文本 + var decimalText string + if decimalPart > 0 { + decimalText = numToThaiText(decimalPart) + satangUnit + } + + // 组合最终结果 + result := integerText + decimalText + if result == "" { + result = zeroBahtMsg + } + + return newStringFormulaArg(result) +} diff --git a/calc_test.go b/calc_test.go index 4aef37094b..c988a4ea2c 100644 --- a/calc_test.go +++ b/calc_test.go @@ -2,6 +2,7 @@ package excelize import ( "container/list" + "fmt" "math" "path/filepath" "strings" @@ -6502,3 +6503,170 @@ func TestParseToken(t *testing.T) { efp.Token{TSubType: efp.TokenSubTypeRange, TValue: "1A"}, nil, nil, ).Error()) } + +// TestBAHTTEXT 测试 BAHTTEXT 函数 +func TestBAHTTEXT(t *testing.T) { + // 创建一个空的 File 实例和计算上下文 + f := NewFile() + ctx := &calcContext{} + fn := &formulaFuncs{ + f: f, + ctx: ctx, + sheet: "Sheet1", + cell: "A1", + } + + // 定义测试用例结构体 + type testCase struct { + input float64 + expected string + name string + } + + // 定义测试用例 + testCases := []testCase{ + { + input: 0, + expected: "ศูนย์บาทถ้วน", + name: "Zero value", + }, + { + input: 123, + expected: "หนึ่งร้อยยี่สิบสามบาท", + name: "Integer value", + }, + { + input: 123.45, + expected: "หนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์", + name: "Value with decimal", + }, + { + input: 1000000, + expected: "หนึ่งล้านบาท", + name: "Large integer value", + }, + { + input: 0.50, + expected: "ห้าสิบสตางค์", + name: "Only decimal value", + }, + } + + // 执行测试用例 + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + argsList := list.New() + argsList.PushFront(newNumberFormulaArg(tc.input)) + result := fn.BAHTTEXT(argsList) + + if result.Type != ArgString || result.String != tc.expected { + t.Errorf("Expected %q, but got %q", tc.expected, result.String) + } + }) + } +} + +// TestDOLLAR 测试 DOLLAR 函数 +func TestDOLLAR(t *testing.T) { + // 测试不同区域设置 + cultureInfos := []CultureName{ + CultureNameUnknown, + CultureNameEnUS, + CultureNameJaJP, + CultureNameKoKR, + CultureNameZhCN, + CultureNameZhTW, + } + + // 定义测试用例结构体 + type testCase struct { + inputArgs []float64 + culture CultureName + expected string + name string + expectErr bool + } + + // 定义测试用例 + testCases := []testCase{ + { + inputArgs: []float64{1234.5678}, + culture: CultureNameEnUS, + expected: "$1,234.57", + name: "Single argument, default decimals", + expectErr: false, + }, + { + inputArgs: []float64{1234.5678, 3}, + culture: CultureNameJaJP, + expected: "¥1,234.568", + name: "Two arguments, specified decimals", + expectErr: false, + }, + { + inputArgs: []float64{1234.5678, -1}, + culture: CultureNameZhCN, + expected: "¥1,230", + name: "Negative decimal places", + expectErr: false, + }, + { + inputArgs: []float64{1234.5678, 128}, + culture: CultureNameKoKR, + expected: "#VALUE!", + name: "Decimal value >= 128", + expectErr: true, + }, + { + inputArgs: []float64{}, + culture: CultureNameEnUS, + expected: "#VALUE!", + name: "No arguments", + expectErr: true, + }, + { + inputArgs: []float64{1234.5678, 1, 2}, + culture: CultureNameZhTW, + expected: "#VALUE!", + name: "More than 2 arguments", + expectErr: true, + }, + } + + for _, culture := range cultureInfos { + // 为每个区域设置创建新的 File 实例和计算上下文 + f := NewFile() + f.options.CultureInfo = culture + ctx := &calcContext{} + fn := &formulaFuncs{ + f: f, + ctx: ctx, + sheet: "Sheet1", + cell: "A1", + } + + for _, tc := range testCases { + if tc.culture != culture { + continue + } + t.Run(fmt.Sprintf("%d_%s", tc.culture, tc.name), func(t *testing.T) { + argsList := list.New() + for _, arg := range tc.inputArgs { + argsList.PushBack(newNumberFormulaArg(arg)) + } + + result := fn.DOLLAR(argsList) + + if tc.expectErr { + if result.Type != ArgError { + t.Errorf("Expected error, but got %v", result) + } + } else { + if result.Type != ArgString || result.String != tc.expected { + t.Errorf("Expected %q, but got %q", tc.expected, result.String) + } + } + }) + } + } +}