Skip to content

Commit c95ba17

Browse files
authored
Add formula function BAHTTEXT support (#2187)
- Update unit tests
1 parent 9e0c94e commit c95ba17

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

calc.go

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,30 @@ var (
212212
criteriaL,
213213
criteriaG,
214214
}
215-
)
215+
// defines numbers text in the Thai used for the BAHTTEXT formula function.
216+
th0 = "\u0E28\u0E39\u0E19\u0E22\u0E4C"
217+
th1 = "\u0E2B\u0E19\u0E36\u0E48\u0E07"
218+
th2 = "\u0E2A\u0E2D\u0E07"
219+
th3 = "\u0E2A\u0E32\u0E21"
220+
th4 = "\u0E2A\u0E35\u0E48"
221+
th5 = "\u0E2B\u0E49\u0E32"
222+
th6 = "\u0E2B\u0E01"
223+
th7 = "\u0E40\u0E08\u0E47\u0E14"
224+
th8 = "\u0E41\u0E1B\u0E14"
225+
th9 = "\u0E40\u0E01\u0E49\u0E32"
226+
th10 = "\u0E2A\u0E34\u0E1A"
227+
th11 = "\u0E40\u0E2D\u0E47\u0E14"
228+
th20 = "\u0E22\u0E35\u0E48"
229+
th1e2 = "\u0E23\u0E49\u0E2D\u0E22"
230+
th1e3 = "\u0E1E\u0E31\u0E19"
231+
th1e4 = "\u0E2B\u0E21\u0E37\u0E48\u0E19"
232+
th1e5 = "\u0E41\u0E2A\u0E19"
233+
th1e6 = "\u0E25\u0E49\u0E32\u0E19"
234+
thDot0 = "\u0E16\u0E49\u0E27\u0E19"
235+
thBaht = "\u0E1A\u0E32\u0E17"
236+
thSatang = "\u0E2A\u0E15\u0E32\u0E07\u0E04\u0E4C"
237+
thMinus = "\u0E25\u0E1A"
238+
)
216239

217240
// calcContext defines the formula execution context.
218241
type calcContext struct {
@@ -385,6 +408,7 @@ type formulaFuncs struct {
385408
// AVERAGEA
386409
// AVERAGEIF
387410
// AVERAGEIFS
411+
// BAHTTEXT
388412
// BASE
389413
// BESSELI
390414
// BESSELJ
@@ -13533,6 +13557,124 @@ func (fn *formulaFuncs) ARRAYTOTEXT(argsList *list.List) formulaArg {
1353313557
return newStringFormulaArg(strings.Join(text, ", "))
1353413558
}
1353513559

13560+
// bahttextAppendDigit appends a digit to the passed string.
13561+
func bahttextAppendDigit(text string, digit int) string {
13562+
if 0 <= digit && digit <= 9 {
13563+
return text + []string{th0, th1, th2, th3, th4, th5, th6, th7, th8, th9}[digit]
13564+
}
13565+
return text
13566+
}
13567+
13568+
// bahttextAppendPow10 appends a value raised to a power of 10: digit*10^pow10.
13569+
func bahttextAppendPow10(text string, digit, pow10 int) string {
13570+
text = bahttextAppendDigit(text, digit)
13571+
switch pow10 {
13572+
case 2:
13573+
text += th1e2
13574+
case 3:
13575+
text += th1e3
13576+
case 4:
13577+
text += th1e4
13578+
case 5:
13579+
text += th1e5
13580+
}
13581+
return text
13582+
}
13583+
13584+
// bahttextAppendBlock appends a block of 6 digits to the passed string.
13585+
func bahttextAppendBlock(text string, val int) string {
13586+
if val >= 100000 {
13587+
text = bahttextAppendPow10(text, val/100000, 5)
13588+
val %= 100000
13589+
}
13590+
if val >= 10000 {
13591+
text = bahttextAppendPow10(text, val/10000, 4)
13592+
val %= 10000
13593+
}
13594+
if val >= 1000 {
13595+
text = bahttextAppendPow10(text, val/1000, 3)
13596+
val %= 1000
13597+
}
13598+
if val >= 100 {
13599+
text = bahttextAppendPow10(text, val/100, 2)
13600+
val %= 100
13601+
}
13602+
if val > 0 {
13603+
n10 := val / 10
13604+
n1 := val % 10
13605+
if n10 >= 1 {
13606+
if n10 >= 3 {
13607+
text = bahttextAppendDigit(text, n10)
13608+
} else if n10 == 2 {
13609+
text += th20
13610+
}
13611+
text += th10
13612+
}
13613+
if n10 > 0 && n1 == 1 {
13614+
text += th11
13615+
} else if n1 > 0 {
13616+
text = bahttextAppendDigit(text, n1)
13617+
}
13618+
}
13619+
return text
13620+
}
13621+
13622+
// BAHTTEXT function converts a number into Thai text, with the suffix "Baht".
13623+
// The syntax of the function is:
13624+
//
13625+
// BAHTTEXT(number)
13626+
func (fn *formulaFuncs) BAHTTEXT(argsList *list.List) formulaArg {
13627+
if argsList.Len() != 1 {
13628+
return newErrorFormulaArg(formulaErrorVALUE, "BAHTTEXT requires 1 numeric argument")
13629+
}
13630+
token := argsList.Front().Value.(formulaArg)
13631+
number := token.ToNumber()
13632+
if number.Type != ArgNumber {
13633+
return newErrorFormulaArg(formulaErrorVALUE, number.Error)
13634+
}
13635+
minus := number.Number < 0
13636+
num := math.Floor(math.Abs(number.Number)*100 + 0.5)
13637+
// split baht and satang
13638+
splitBlock := func(val, size float64) (float64, int) {
13639+
integer, frac := math.Modf((val + 0.1) / size)
13640+
frac = frac*size + 0.1
13641+
return integer, int(frac)
13642+
}
13643+
baht, satang := splitBlock(num, 100)
13644+
var text string
13645+
if baht == 0 {
13646+
if satang == 0 {
13647+
text += th0
13648+
}
13649+
} else {
13650+
for baht > 0 {
13651+
var block string
13652+
var nBlock int
13653+
baht, nBlock = splitBlock(baht, 1.0e6)
13654+
if nBlock > 0 {
13655+
block = bahttextAppendBlock(block, nBlock)
13656+
}
13657+
if baht > 0 {
13658+
block = th1e6 + block
13659+
}
13660+
text = block + text
13661+
}
13662+
}
13663+
if len(text) > 0 {
13664+
text += thBaht
13665+
}
13666+
if satang == 0 {
13667+
text += thDot0
13668+
} else {
13669+
text = bahttextAppendBlock(text, satang)
13670+
text += thSatang
13671+
}
13672+
if minus {
13673+
text = thMinus + text
13674+
}
13675+
return newStringFormulaArg(text)
13676+
}
13677+
1353613678
// CHAR function returns the character relating to a supplied character set
1353713679
// number (from 1 to 255). The syntax of the function is:
1353813680
//

calc_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3839,6 +3839,9 @@ func TestCalcCellValue(t *testing.T) {
38393839
"ARRAYTOTEXT(A1,0,0)": {"#VALUE!", "ARRAYTOTEXT allows at most 2 arguments"},
38403840
"ARRAYTOTEXT(A1,\"\")": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
38413841
"ARRAYTOTEXT(A1,2)": {"#VALUE!", "#VALUE!"},
3842+
// BAHTTEXT
3843+
"BAHTTEXT()": {"#VALUE!", "BAHTTEXT requires 1 numeric argument"},
3844+
"BAHTTEXT(\"\")": {"#VALUE!", "strconv.ParseFloat: parsing \"\": invalid syntax"},
38423845
// CHAR
38433846
"CHAR()": {"#VALUE!", "CHAR requires 1 argument"},
38443847
"CHAR(-1)": {"#VALUE!", "#VALUE!"},
@@ -6341,6 +6344,10 @@ func TestCalcRangeResolver(t *testing.T) {
63416344
assert.Equal(t, ErrMaxRows, err)
63426345
}
63436346

6347+
func TestCalcBahttextAppendDigit(t *testing.T) {
6348+
assert.Empty(t, bahttextAppendDigit("", -1))
6349+
}
6350+
63446351
func TestNestedFunctionsWithOperators(t *testing.T) {
63456352
f := NewFile()
63466353
formulaList := map[string]string{

0 commit comments

Comments
 (0)