Skip to content

Commit 925e798

Browse files
committed
This closes #2297, fix custom number format with comma scaling not properly applied
1 parent 94f8a47 commit 925e798

2 files changed

Lines changed: 103 additions & 37 deletions

File tree

numfmt.go

Lines changed: 93 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type numberFormat struct {
4444
ap, localCode, result, value, valueSectionType string
4545
switchArgument, currencyString string
4646
fracHolder, fracPadding, intHolder, intPadding, expBaseLen int
47-
percent int
47+
percent, scalingFactor, scalingStart int
4848
useCommaSep, useFraction, usePointer, usePositive, useScientificNotation bool
4949
}
5050

@@ -5307,48 +5307,98 @@ func (nf *numberFormat) getNumberPartLen() (int, int) {
53075307
return intLen, fracLen
53085308
}
53095309

5310+
// getLastDigitIdx returns the last digit placeholder token index in the number
5311+
// format code section.
5312+
func (nf *numberFormat) getLastDigitIdx() int {
5313+
items := nf.section[nf.sectionIdx].Items
5314+
lastDigitIdx := -1
5315+
for i, token := range items {
5316+
if token.TType == nfp.TokenTypeZeroPlaceHolder || token.TType == nfp.TokenTypeHashPlaceHolder {
5317+
lastDigitIdx = i
5318+
}
5319+
}
5320+
return lastDigitIdx
5321+
}
5322+
53105323
// getNumberFmtConf generate the number format padding and placeholder
53115324
// configurations.
53125325
func (nf *numberFormat) getNumberFmtConf() {
5313-
for _, token := range nf.section[nf.sectionIdx].Items {
5314-
if token.TType == nfp.TokenTypeHashPlaceHolder {
5315-
if nf.usePointer {
5316-
nf.fracHolder += len(token.TValue)
5317-
continue
5318-
}
5319-
nf.intHolder += len(token.TValue)
5320-
}
5321-
if token.TType == nfp.TokenTypeExponential {
5322-
nf.useScientificNotation = true
5323-
}
5324-
if token.TType == nfp.TokenTypeThousandsSeparator {
5325-
nf.useCommaSep = true
5326-
}
5327-
if token.TType == nfp.TokenTypePercent {
5328-
nf.percent += len(token.TValue)
5329-
}
5330-
if token.TType == nfp.TokenTypeDecimalPoint {
5331-
nf.usePointer = true
5332-
}
5333-
if token.TType == nfp.TokenTypeFraction {
5334-
nf.useFraction = true
5335-
}
5336-
if token.TType == nfp.TokenTypeSwitchArgument {
5337-
nf.switchArgument = token.TValue
5326+
items := nf.section[nf.sectionIdx].Items
5327+
lastDigitIdx := nf.getLastDigitIdx()
5328+
for i, token := range items {
5329+
nf.applyNumberFmtToken(i, token, lastDigitIdx)
5330+
}
5331+
}
5332+
5333+
// applyNumberFmtToken applies a single token to the number format padding and
5334+
// placeholder configurations.
5335+
func (nf *numberFormat) applyNumberFmtToken(i int, token nfp.Token, lastDigitIdx int) {
5336+
switch token.TType {
5337+
case nfp.TokenTypeHashPlaceHolder:
5338+
nf.applyHashPlaceHolderToken(token)
5339+
case nfp.TokenTypeExponential:
5340+
nf.useScientificNotation = true
5341+
case nfp.TokenTypeThousandsSeparator:
5342+
nf.applyThousandsSeparatorToken(i, token, lastDigitIdx)
5343+
case nfp.TokenTypeLiteral:
5344+
nf.applyLiteralToken(i, token, lastDigitIdx)
5345+
case nfp.TokenTypePercent:
5346+
nf.percent += len(token.TValue)
5347+
case nfp.TokenTypeDecimalPoint:
5348+
nf.usePointer = true
5349+
case nfp.TokenTypeFraction:
5350+
nf.useFraction = true
5351+
case nfp.TokenTypeSwitchArgument:
5352+
nf.switchArgument = token.TValue
5353+
case nfp.TokenTypeZeroPlaceHolder:
5354+
nf.applyZeroPlaceHolderToken(token)
5355+
}
5356+
}
5357+
5358+
// applyHashPlaceHolderToken applies a hash placeholder token to the number
5359+
// format padding and placeholder configurations.
5360+
func (nf *numberFormat) applyHashPlaceHolderToken(token nfp.Token) {
5361+
if nf.usePointer {
5362+
nf.fracHolder += len(token.TValue)
5363+
return
5364+
}
5365+
nf.intHolder += len(token.TValue)
5366+
}
5367+
5368+
// applyThousandsSeparatorToken applies a thousands separator token to the
5369+
// number format padding and placeholder configurations.
5370+
func (nf *numberFormat) applyThousandsSeparatorToken(i int, token nfp.Token, lastDigitIdx int) {
5371+
if i > lastDigitIdx {
5372+
if nf.scalingFactor == 0 {
5373+
nf.scalingStart = i
53385374
}
5339-
if token.TType == nfp.TokenTypeZeroPlaceHolder {
5340-
nf.intHolder = 0
5341-
if nf.usePointer {
5342-
if nf.useScientificNotation {
5343-
nf.expBaseLen += len(token.TValue)
5344-
continue
5345-
}
5346-
nf.fracPadding += len(token.TValue)
5347-
continue
5348-
}
5349-
nf.intPadding += len(token.TValue)
5375+
nf.scalingFactor++
5376+
return
5377+
}
5378+
nf.useCommaSep = true
5379+
}
5380+
5381+
// applyLiteralToken applies a literal token to the number format padding and
5382+
// placeholder configurations.
5383+
func (nf *numberFormat) applyLiteralToken(i int, token nfp.Token, lastDigitIdx int) {
5384+
if token.TValue == "," && i > lastDigitIdx && nf.scalingFactor > 0 {
5385+
nf.scalingFactor++
5386+
}
5387+
}
5388+
5389+
// applyZeroPlaceHolderToken applies a zero placeholder token to the number
5390+
// format padding and placeholder configurations.
5391+
func (nf *numberFormat) applyZeroPlaceHolderToken(token nfp.Token) {
5392+
nf.intHolder = 0
5393+
if nf.usePointer {
5394+
if nf.useScientificNotation {
5395+
nf.expBaseLen += len(token.TValue)
5396+
return
53505397
}
5398+
nf.fracPadding += len(token.TValue)
5399+
return
53515400
}
5401+
nf.intPadding += len(token.TValue)
53525402
}
53535403

53545404
// handleDigitsLiteral apply digit placeholder tokens for the number literal.
@@ -5411,6 +5461,9 @@ func (nf *numberFormat) printNumberLiteral(text string) string {
54115461
result += nf.currencyString
54125462
}
54135463
if token.TType == nfp.TokenTypeLiteral {
5464+
if nf.scalingFactor > 0 && idx >= nf.scalingStart && token.TValue == "," {
5465+
continue
5466+
}
54145467
result += token.TValue
54155468
}
54165469
if token.TType == nfp.TokenTypeDigitalPlaceHolder && idx > lastNonFractionPartDigital {
@@ -5515,6 +5568,9 @@ func (nf *numberFormat) printBigNumber(decimal float64, fracLen int) string {
55155568
// numeric.
55165569
func (nf *numberFormat) numberHandler() string {
55175570
nf.getNumberFmtConf()
5571+
if nf.scalingFactor > 0 {
5572+
nf.number /= math.Pow(1000, float64(nf.scalingFactor))
5573+
}
55185574
var (
55195575
num = nf.number
55205576
intLen, fracLen = nf.getNumberPartLen()

numfmt_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4203,6 +4203,16 @@ func TestNumFmt(t *testing.T) {
42034203
{"-8.04506", "0_);[Red]\\(0\\)", "(8)"},
42044204
{"-8.04506", "$#,##0.00_);[Red]($#,##0.00)", "($8.05)"},
42054205
{"43543.5448726851", `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`, " $43,543.54 "},
4206+
{"9767948584", `#,##0,,;"-"#,##0,,;#,##0,,;_(@_)`, "9,768"},
4207+
{"9767948584", `#,##0,,;"-"#,##0,,;#,##0,,;_(@_)`, "9,768"},
4208+
{"-9767948584", `#,##0,,;"-"#,##0,,;#,##0,,;_(@_)`, "-9,768"},
4209+
{"0", `#,##0,,;"-"#,##0,,;#,##0,,;_(@_)`, "0"},
4210+
{"1500", "#,##0,", "2"},
4211+
{"1500000", "#,##0,,", "2"},
4212+
{"1500000", "0\",\"", "1500000,"},
4213+
{"1234567", "0.0,,", "1.2"},
4214+
{"1234567890", `#,##0,," M"`, "1,235 M"},
4215+
{"12345678901234567890", "#,##0,,", "12,345,678,901,235"},
42064216
{"1234.5678", "0", "1235"},
42074217
{"1234.125", "0.00", "1234.13"},
42084218
{"1234.5678", "0.00", "1234.57"},

0 commit comments

Comments
 (0)