Skip to content

Add formula function BAHTTEXT support #2187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 142 additions & 1 deletion calc.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,30 @@ var (
criteriaL,
criteriaG,
}
)
// defines numbers text in the Thai used for the BAHTTEXT formula function.
th0 = "\u0E28\u0E39\u0E19\u0E22\u0E4C"
th1 = "\u0E2B\u0E19\u0E36\u0E48\u0E07"
th2 = "\u0E2A\u0E2D\u0E07"
th3 = "\u0E2A\u0E32\u0E21"
th4 = "\u0E2A\u0E35\u0E48"
th5 = "\u0E2B\u0E49\u0E32"
th6 = "\u0E2B\u0E01"
th7 = "\u0E40\u0E08\u0E47\u0E14"
th8 = "\u0E41\u0E1B\u0E14"
th9 = "\u0E40\u0E01\u0E49\u0E32"
th10 = "\u0E2A\u0E34\u0E1A"
th11 = "\u0E40\u0E2D\u0E47\u0E14"
th20 = "\u0E22\u0E35\u0E48"
th1e2 = "\u0E23\u0E49\u0E2D\u0E22"
th1e3 = "\u0E1E\u0E31\u0E19"
th1e4 = "\u0E2B\u0E21\u0E37\u0E48\u0E19"
th1e5 = "\u0E41\u0E2A\u0E19"
th1e6 = "\u0E25\u0E49\u0E32\u0E19"
thDot0 = "\u0E16\u0E49\u0E27\u0E19"
thBaht = "\u0E1A\u0E32\u0E17"
thSatang = "\u0E2A\u0E15\u0E32\u0E07\u0E04\u0E4C"
thMinus = "\u0E25\u0E1A"
)

// calcContext defines the formula execution context.
type calcContext struct {
Expand Down Expand Up @@ -384,6 +407,7 @@ type formulaFuncs struct {
// AVERAGEA
// AVERAGEIF
// AVERAGEIFS
// BAHTTEXT
// BASE
// BESSELI
// BESSELJ
Expand Down Expand Up @@ -13532,6 +13556,123 @@ func (fn *formulaFuncs) ARRAYTOTEXT(argsList *list.List) formulaArg {
return newStringFormulaArg(strings.Join(text, ", "))
}

// splitBlock function split baht and satang
func splitBlock(val, size float64) (float64, int) {
integer, frac := math.Modf((val + 0.1) / size)
frac = frac*size + 0.1
return integer, int(frac)
}


// bahttextAppendDigit appends a digit to the passed string.
func bahttextAppendDigit(text string, digit int) string {
if 0 <= digit && digit <= 9 {
return text + []string{th0, th1, th2, th3, th4, th5, th6, th7, th8, th9}[digit]
}
return text
}

// bahttextAppendPow10 appends a value raised to a power of 10: digit*10^pow10.
func bahttextAppendPow10(text string, digit, pow10 int) string {
text = bahttextAppendDigit(text, digit)
switch pow10 {
case 2:
text += th1e2
case 3:
text += th1e3
case 4:
text += th1e4
case 5:
text += th1e5
}
return text
}

// bahttextAppendBlock appends a block of 6 digits to the passed string.
func bahttextAppendBlock(text string, val int) string {
if val >= 100000 {
text = bahttextAppendPow10(text, val/100000, 5)
val %= 100000
}
if val >= 10000 {
text = bahttextAppendPow10(text, val/10000, 4)
val %= 10000
}
if val >= 1000 {
text = bahttextAppendPow10(text, val/1000, 3)
val %= 1000
}
if val >= 100 {
text = bahttextAppendPow10(text, val/100, 2)
val %= 100
}
if val > 0 {
n10 := val / 10
n1 := val % 10
if n10 >= 1 {
if n10 >= 3 {
text = bahttextAppendDigit(text, n10)
} else if n10 == 2 {
text += th20
}
text += th10
}
if n10 > 0 && n1 == 1 {
text += th11
} else if n1 > 0 {
text = bahttextAppendDigit(text, n1)
}
}
return text
}

// BAHTTEXT function converts a number into Thai text, with the suffix "Baht".
// The syntax of the function is:
//
// BAHTTEXT(number)
func (fn *formulaFuncs) BAHTTEXT(argsList *list.List) formulaArg {
if argsList.Len() != 1 {
return newErrorFormulaArg(formulaErrorVALUE, "BAHTTEXT requires 1 numeric argument")
}
token := argsList.Front().Value.(formulaArg)
number := token.ToNumber()
if number.Type != ArgNumber {
return newErrorFormulaArg(formulaErrorVALUE, number.Error)
}
minus := number.Number < 0
num := math.Floor(math.Abs(number.Number)*100 + 0.5)
baht, satang := splitBlock(num, 100)
var text string
if baht == 0 {
if satang == 0 {
text += th0
}
} else {
for baht > 0 {
var block string
var nBlock int
baht, nBlock = splitBlock(baht, 1.0e6)
block = bahttextAppendBlock(block, nBlock)
if baht > 0 {
block = th1e6 + block
}
text = block + text
}
}
if len(text) > 0 {
text += thBaht
}
if satang == 0 {
text += thDot0
} else {
text += thSatang
}
if minus {
text = thMinus + text
}
return newStringFormulaArg(text)
}

// CHAR function returns the character relating to a supplied character set
// number (from 1 to 255). The syntax of the function is:
//
Expand Down
Loading