Skip to content

Commit 3e49298

Browse files
shcabinshcabin
authored andcommitted
fix DigitPlaceholder, put a space for insignificant zeros
1 parent 1d381d7 commit 3e49298

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

excelize_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -779,10 +779,10 @@ func TestSetCellStyleNumberFormat(t *testing.T) {
779779
idxTbl := []int{0, 1, 2, 3, 4, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
780780
value := []string{"37947.7500001", "-37947.7500001", "0.007", "2.1", "String"}
781781
expected := [][]string{
782-
{"37947.75", "37948", "37947.75", "37,948", "37,947.75", "3794775%", "3794775.00%", "3.79E+04", "37947 3/4", "37947 3/4", "11-22-03", "22-Nov-03", "22-Nov", "Nov-03", "6:00 PM", "6:00:00 PM", "18:00", "18:00:00", "11/22/03 18:00", "37,948 ", "37,948 ", "37,947.75 ", "37,947.75 ", " 37,948 ", " $37,948 ", " 37,947.75 ", " $37,947.75 ", "00:00", "910746:00:00", "00:00.0", "37947.7500001", "37947.7500001"},
783-
{"-37947.75", "-37948", "-37947.75", "-37,948", "-37,947.75", "-3794775%", "-3794775.00%", "-3.79E+04", "-37947 3/4", "-37947 3/4", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "(37,948)", "(37,948)", "(37,947.75)", "(37,947.75)", " (37,948)", " $(37,948)", " (37,947.75)", " $(37,947.75)", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001"},
784-
{"0.007", "0", "0.01", "0", "0.01", "1%", "0.70%", "7.00E-03", "0 ", "0 ", "01-00-00", "0-Jan-00", "0-Jan", "Jan-00", "12:10 AM", "12:10:05 AM", "00:10", "00:10:05", "1/0/00 00:10", "0 ", "0 ", "0.01 ", "0.01 ", " 0 ", " $0 ", " 0.01 ", " $0.01 ", "10:05", "0:10:05", "10:04.8", "0.007", "0.007"},
785-
{"2.1", "2", "2.10", "2", "2.10", "210%", "210.00%", "2.10E+00", "2 1/9", "2 1/10", "01-02-00", "2-Jan-00", "2-Jan", "Jan-00", "2:24 AM", "2:24:00 AM", "02:24", "02:24:00", "1/2/00 02:24", "2 ", "2 ", "2.10 ", "2.10 ", " 2 ", " $2 ", " 2.10 ", " $2.10 ", "24:00", "50:24:00", "24:00.0", "2.1", "2.1"},
782+
{"37947.75", "37948", "37947.75", "37,948", "37,947.75", "3794775%", "3794775.00%", "3.79E+04", "37947 3/4", "37947 3/4 ", "11-22-03", "22-Nov-03", "22-Nov", "Nov-03", "6:00 PM", "6:00:00 PM", "18:00", "18:00:00", "11/22/03 18:00", "37,948 ", "37,948 ", "37,947.75 ", "37,947.75 ", " 37,948 ", " $37,948 ", " 37,947.75 ", " $37,947.75 ", "00:00", "910746:00:00", "00:00.0", "37947.7500001", "37947.7500001"},
783+
{"-37947.75", "-37948", "-37947.75", "-37,948", "-37,947.75", "-3794775%", "-3794775.00%", "-3.79E+04", "-37947 3/4", "-37947 3/4 ", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "(37,948)", "(37,948)", "(37,947.75)", "(37,947.75)", " (37,948)", " $(37,948)", " (37,947.75)", " $(37,947.75)", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001"},
784+
{"0.007", "0", "0.01", "0", "0.01", "1%", "0.70%", "7.00E-03", "0 ", "0 ", "01-00-00", "0-Jan-00", "0-Jan", "Jan-00", "12:10 AM", "12:10:05 AM", "00:10", "00:10:05", "1/0/00 00:10", "0 ", "0 ", "0.01 ", "0.01 ", " 0 ", " $0 ", " 0.01 ", " $0.01 ", "10:05", "0:10:05", "10:04.8", "0.007", "0.007"},
785+
{"2.1", "2", "2.10", "2", "2.10", "210%", "210.00%", "2.10E+00", "2 1/9", "2 1/10", "01-02-00", "2-Jan-00", "2-Jan", "Jan-00", "2:24 AM", "2:24:00 AM", "02:24", "02:24:00", "1/2/00 02:24", "2 ", "2 ", "2.10 ", "2.10 ", " 2 ", " $2 ", " 2.10 ", " $2.10 ", "24:00", "50:24:00", "24:00.0", "2.1", "2.1"},
786786
{"String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", "String", " String ", " String ", " String ", " String ", "String", "String", "String", "String", "String"},
787787
}
788788

numfmt.go

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5351,9 +5351,8 @@ func (nf *numberFormat) getNumberFmtConf() {
53515351
}
53525352
}
53535353

5354-
// handleDigitsLiteral apply hash and zero place holder tokens for the number
5355-
// literal.
5356-
func handleDigitsLiteral(text string, tokenValueLen, intPartLen, hashZeroPartLen int) (int, string) {
5354+
// handleDigitsLiteral apply digit placeholder tokens for the number literal
5355+
func handleDigitsLiteral(text string, tokenValueLen, intPartLen, hashZeroPartLen int, fill bool) (int, string) {
53575356
var result string
53585357
l := tokenValueLen
53595358
if intPartLen == 0 && len(text) > hashZeroPartLen {
@@ -5366,6 +5365,8 @@ func handleDigitsLiteral(text string, tokenValueLen, intPartLen, hashZeroPartLen
53665365
j := i + intPartLen
53675366
if 0 <= j && j < len([]rune(text)) {
53685367
result += string([]rune(text)[j])
5368+
} else if fill {
5369+
result += " "
53695370
}
53705371
}
53715372
return l, result
@@ -5382,21 +5383,43 @@ func (nf *numberFormat) printNumberLiteral(text string) string {
53825383
if nf.usePositive {
53835384
result += "-"
53845385
}
5385-
for _, token := range nf.section[nf.sectionIdx].Items {
5386+
lastNonFractionPartDigital := math.MaxInt
5387+
appearedFraction := false
5388+
numeratorPlaceHolder := 0
5389+
for idx := len(nf.section[nf.sectionIdx].Items) - 1; idx >= 0; idx-- {
5390+
token := nf.section[nf.sectionIdx].Items[idx]
5391+
if token.TType == nfp.TokenTypeFraction {
5392+
appearedFraction = true
5393+
} else if appearedFraction && (token.TType == nfp.TokenTypeHashPlaceHolder || token.TType == nfp.TokenTypeDigitalPlaceHolder) {
5394+
lastNonFractionPartDigital = idx - 1 // current idx belongs to the fraction part(numerator)
5395+
break
5396+
}
5397+
}
5398+
for idx, token := range nf.section[nf.sectionIdx].Items {
53865399
if token.TType == nfp.TokenTypeHashPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder {
53875400
hashZeroPartLen += len(token.TValue)
5401+
} else if token.TType == nfp.TokenTypeDigitalPlaceHolder {
5402+
if lastNonFractionPartDigital >= 0 && idx < lastNonFractionPartDigital {
5403+
hashZeroPartLen += len(token.TValue)
5404+
}
53885405
}
53895406
}
5390-
for _, token := range nf.section[nf.sectionIdx].Items {
5407+
for idx, token := range nf.section[nf.sectionIdx].Items {
53915408
if token.TType == nfp.TokenTypeCurrencyLanguage {
53925409
_, _ = nf.currencyLanguageHandler(token)
53935410
result += nf.currencyString
53945411
}
53955412
if token.TType == nfp.TokenTypeLiteral {
53965413
result += token.TValue
53975414
}
5398-
if token.TType == nfp.TokenTypeHashPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder || token.TType == nfp.TokenTypeDigitalPlaceHolder {
5399-
digits, str := handleDigitsLiteral(text, len(token.TValue), intPartLen, hashZeroPartLen)
5415+
if token.TType == nfp.TokenTypeDigitalPlaceHolder && idx > lastNonFractionPartDigital {
5416+
//If it is a fraction part, it will be filled in by the fractalHandler()
5417+
//If not, fill placeHolder in directly here
5418+
if !useFraction { // numerator part
5419+
numeratorPlaceHolder = len(token.TValue)
5420+
}
5421+
} else if token.TType == nfp.TokenTypeHashPlaceHolder || token.TType == nfp.TokenTypeZeroPlaceHolder || token.TType == nfp.TokenTypeDigitalPlaceHolder {
5422+
digits, str := handleDigitsLiteral(text, len(token.TValue), intPartLen, hashZeroPartLen, token.TType == nfp.TokenTypeDigitalPlaceHolder)
54005423
intPartLen += digits
54015424
result += str
54025425
}
@@ -5405,27 +5428,37 @@ func (nf *numberFormat) printNumberLiteral(text string) string {
54055428
frac, useFraction = math.Abs(frac), true
54065429
}
54075430
if useFraction {
5408-
result += nf.fractionHandler(frac, token)
5431+
result += nf.fractionHandler(frac, token, numeratorPlaceHolder)
54095432
}
54105433
}
54115434
return nf.printSwitchArgument(result)
54125435
}
54135436

54145437
// fractionHandler handling fraction number format expression for positive and
54155438
// negative numeric.
5416-
func (nf *numberFormat) fractionHandler(frac float64, token nfp.Token) string {
5439+
func (nf *numberFormat) fractionHandler(frac float64, token nfp.Token, numeratorPlaceHolder int) string {
54175440
var rat, result string
5441+
var lastRat *big.Rat
54185442
if token.TType == nfp.TokenTypeDigitalPlaceHolder {
5419-
fracPlaceHolder := len(token.TValue)
5443+
denominatorPlaceHolder := len(token.TValue)
54205444
for i := 0; i < 5000; i++ {
5421-
if r := newRat(frac, int64(i), 0); len(r.Denom().String()) <= fracPlaceHolder {
5422-
if rat = r.String(); strings.HasPrefix(rat, "0/") {
5423-
rat = strings.Repeat(" ", 3)
5424-
}
5445+
if r := newRat(frac, int64(i), 0); len(r.Denom().String()) <= denominatorPlaceHolder {
5446+
lastRat = r // record the last valid ratio, and delay conversion to string
54255447
continue
54265448
}
54275449
break
54285450
}
5451+
if lastRat != nil {
5452+
if lastRat.Num().Int64() == 0 {
5453+
rat = strings.Repeat(" ", numeratorPlaceHolder+denominatorPlaceHolder+1)
5454+
} else {
5455+
num := lastRat.Num().String()
5456+
den := lastRat.Denom().String()
5457+
numeratorPlaceHolder = max(numeratorPlaceHolder-len(num), 0)
5458+
denominatorPlaceHolder = max(denominatorPlaceHolder-len(den), 0)
5459+
rat = fmt.Sprintf("%s%s/%s%s", strings.Repeat(" ", numeratorPlaceHolder), num, den, strings.Repeat(" ", denominatorPlaceHolder))
5460+
}
5461+
}
54295462
result += rat
54305463
}
54315464
if token.TType == nfp.TokenTypeDenominator {

numfmt_test.go

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4255,7 +4255,7 @@ func TestNumFmt(t *testing.T) {
42554255
{"1.234E-16", "0.000000000000000000%%%%", "0.000000000000012340%"},
42564256
{"-123.4567", "# ?/?", "-123 1/2"},
42574257
{"123.4567", "# ??/??", "123 37/81"},
4258-
{"123.4567", "#\\ ???/???", "123 58/127"},
4258+
{"123.4567", "#\\ ???/???", "123 58/127"},
42594259
{"123.4567", "#\\ ?/2", "123 1/2"},
42604260
{"123.4567", "#\\ ?/4", "123 2/4"},
42614261
{"123.4567", "#\\ ?/8", "123 4/8"},
@@ -4268,7 +4268,6 @@ func TestNumFmt(t *testing.T) {
42684268
{"123", "[$x.-unknown]MM/DD/YYYY", "x.05/02/1900"},
42694269
{"1234.5678", "0.0xxx00", "1234.5xxx68"},
42704270
{"80145.899999999994", "[$¥-8004]\" \"#\" \"####\"\"", "¥ 8 0146"},
4271-
{"1", "?", "1"},
42724271
// Unsupported number format
42734272
{"37947.7500001", "0.00000000E+000", "37947.7500001"},
42744273
{"123", "[DBNum4][$-804]yyyy\"\"m\"\";@", "123"},
@@ -4287,6 +4286,27 @@ func TestNumFmt(t *testing.T) {
42874286
result := format(item[0], item[1], false, CellTypeNumber, nil)
42884287
assert.Equal(t, item[2], result, item)
42894288
}
4289+
// Test format number with Digit placeholder format
4290+
// ? shall put a space for insignificant zeros
4291+
// # shall not display extra zeros
4292+
for _, item := range [][]string{
4293+
{"1", "?", "1"},
4294+
{"1", "???", " 1"},
4295+
{"0", "# ?/?", "0 "},
4296+
{"0", "# ??/??", "0 "},
4297+
{"0", "# ??/???", "0 "},
4298+
{"31.69", "?#???", " 32"},
4299+
{"314159.26535", "#,### ??/??", "314,159 13/49"},
4300+
{"314159.26535", "# ??? ????/??", "314 159 13/49"},
4301+
{"-3.14159265358979323", "# ?/?", "-3 1/7"},
4302+
{"-3.14159265358979323", "# ??/??", "-3 1/7 "},
4303+
{"-3.14159265358979323", "# ???/???", "-3 16/113"},
4304+
{"5.81999", `???? ????`, " 6"},
4305+
{"4.6", `# #### ####`, " 5"},
4306+
} {
4307+
result := format(item[0], item[1], false, CellTypeNumber, nil)
4308+
assert.Equal(t, item[2], result, item)
4309+
}
42904310
// Test format number with specified date and time format code
42914311
for _, item := range [][]string{
42924312
{"43543.503206018519", "[$-F800]dddd, mmmm dd, yyyy", "2019年3月19日"},
@@ -4320,3 +4340,26 @@ func TestNumFmt(t *testing.T) {
43204340
assert.Equal(t, ErrUnsupportedNumberFormat, err)
43214341
assert.False(t, changeNumFmtCode)
43224342
}
4343+
4344+
func BenchmarkNumFmtPlaceHolder(b *testing.B) {
4345+
items := [][]string{
4346+
{"1", "?", "1"},
4347+
{"1", "???", " 1"},
4348+
{"0", "# ?/?", "0 "},
4349+
{"0", "# ??/??", "0 "},
4350+
{"0", "# ??/???", "0 "},
4351+
{"31.69", "?#???", " 32"},
4352+
{"314159.26535", "#,### ??/??", "314,159 13/49"},
4353+
{"314159.26535", "# ??? ????/??", "314 159 13/49"},
4354+
{"-3.14159265358979323", "# ?/?", "-3 1/7"},
4355+
{"-3.14159265358979323", "# ??/??", "-3 1/7 "},
4356+
{"123.4567", "#\\ ?/10", "123 5/10"},
4357+
}
4358+
b.ReportAllocs()
4359+
for i := 0; i < b.N; i++ {
4360+
for _, item := range items {
4361+
result := format(item[0], item[1], false, CellTypeNumber, nil)
4362+
_ = result
4363+
}
4364+
}
4365+
}

0 commit comments

Comments
 (0)