diff --git a/col_test.go b/col_test.go index 0e686a95..335bee06 100644 --- a/col_test.go +++ b/col_test.go @@ -407,7 +407,7 @@ func TestInsertCols(t *testing.T) { f := NewFile() sheet1 := f.GetSheetName(0) - fillCells(f, sheet1, 10, 10) + assert.NoError(t, fillCells(f, sheet1, 10, 10)) assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/xuri/excelize", "External")) assert.NoError(t, f.MergeCell(sheet1, "A1", "C3")) @@ -430,7 +430,7 @@ func TestRemoveCol(t *testing.T) { f := NewFile() sheet1 := f.GetSheetName(0) - fillCells(f, sheet1, 10, 15) + assert.NoError(t, fillCells(f, sheet1, 10, 15)) assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/xuri/excelize", "External")) assert.NoError(t, f.SetCellHyperLink(sheet1, "C5", "https://github.com", "External")) diff --git a/excelize_test.go b/excelize_test.go index 59ce3dfc..6116b425 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -750,10 +750,10 @@ func TestSetCellStyleNumberFormat(t *testing.T) { 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} value := []string{"37947.7500001", "-37947.7500001", "0.007", "2.1", "String"} expected := [][]string{ - {"37947.7500001", "37948", "37947.75", "37,948", "37,947.75", "3794775%", "3794775.00%", "3.79E+04", "37947.7500001", "37947.7500001", "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 ", "37947.7500001", "37947.7500001", "37947.7500001", "37947.7500001", "00:00", "910746:00:00", "0000.0", "37947.7500001", "37947.7500001"}, + {"37947.7500001", "37948", "37947.75", "37,948", "37,947.75", "3794775%", "3794775.00%", "3.79E+04", "37947.7500001", "37947.7500001", "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 ", "37947.7500001", "37947.7500001", "37947.7500001", "37947.7500001", "00:00", "910746:00:00", "00:00.0", "37947.7500001", "37947.7500001"}, {"-37947.7500001", "-37948", "-37947.75", "-37,948", "-37,947.75", "-3794775%", "-3794775.00%", "-3.79E+04", "-37947.7500001", "-37947.7500001", "-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)", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001", "-37947.7500001"}, - {"0.007", "0", "0.01", "0", "0.01", "1%", "0.70%", "7.00E-03", "0.007", "0.007", "12-30-99", "30-Dec-99", "30-Dec", "Dec-99", "0:10 am", "0:10:04 am", "00:10", "00:10:04", "12/30/99 00:10", "0 ", "0 ", "0.01 ", "0.01 ", "0.007", "0.007", "0.007", "0.007", "10:04", "0:10:04", "1004.0", "0.007", "0.007"}, - {"2.1", "2", "2.10", "2", "2.10", "210%", "210.00%", "2.10E+00", "2.1", "2.1", "01-01-00", "1-Jan-00", "1-Jan", "Jan-00", "2:24 am", "2:24:00 am", "02:24", "02:24:00", "1/1/00 02:24", "2 ", "2 ", "2.10 ", "2.10 ", "2.1", "2.1", "2.1", "2.1", "24:00", "50:24:00", "2400.0", "2.1", "2.1"}, + {"0.007", "0", "0.01", "0", "0.01", "1%", "0.70%", "7.00E-03", "0.007", "0.007", "12-30-99", "30-Dec-99", "30-Dec", "Dec-99", "0:10 AM", "0:10:05 AM", "00:10", "00:10:05", "12/30/99 00:10", "0 ", "0 ", "0.01 ", "0.01 ", "0.007", "0.007", "0.007", "0.007", "10:05", "0:10:05", "10:04.8", "0.007", "0.007"}, + {"2.1", "2", "2.10", "2", "2.10", "210%", "210.00%", "2.10E+00", "2.1", "2.1", "01-01-00", "1-Jan-00", "1-Jan", "Jan-00", "2:24 AM", "2:24:00 AM", "02:24", "02:24:00", "1/1/00 02:24", "2 ", "2 ", "2.10 ", "2.10 ", "2.1", "2.1", "2.1", "2.1", "24:00", "50:24:00", "24:00.0", "2.1", "2.1"}, {"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"}, } diff --git a/go.mod b/go.mod index a266969a..176c00a8 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/richardlehane/mscfb v1.0.4 github.com/stretchr/testify v1.8.0 github.com/xuri/efp v0.0.0-20230422071738-01f4e37c47e9 - github.com/xuri/nfp v0.0.0-20230428090735-b50b0f0358f4 + github.com/xuri/nfp v0.0.0-20230503010013-3f38cdbb0b83 golang.org/x/crypto v0.8.0 golang.org/x/image v0.5.0 golang.org/x/net v0.9.0 diff --git a/go.sum b/go.sum index c57411bd..c5062b39 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/xuri/efp v0.0.0-20230422071738-01f4e37c47e9 h1:ge5g8vsTQclA5lXDi+PuiAFw5GMIlMHOB/5e1hsf96E= github.com/xuri/efp v0.0.0-20230422071738-01f4e37c47e9/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= -github.com/xuri/nfp v0.0.0-20230428090735-b50b0f0358f4 h1:YoU/1S7L25dvNepEir3Fg2aU9iGmDyE4gWKoEswWXts= -github.com/xuri/nfp v0.0.0-20230428090735-b50b0f0358f4/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= +github.com/xuri/nfp v0.0.0-20230503010013-3f38cdbb0b83 h1:xVwnvkzzi+OiwhIkWOXvh1skFI6bagk8OvGuazM80Rw= +github.com/xuri/nfp v0.0.0-20230503010013-3f38cdbb0b83/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= diff --git a/numfmt.go b/numfmt.go index 5f5f180f..283a4f88 100644 --- a/numfmt.go +++ b/numfmt.go @@ -36,9 +36,10 @@ type numberFormat struct { section []nfp.Section t time.Time sectionIdx int - date1904, isNumeric, hours, seconds bool + date1904, isNumeric, hours, seconds, useMillisecond bool number float64 ap, localCode, result, value, valueSectionType string + switchArgument, currencyString string fracHolder, fracPadding, intHolder, intPadding, expBaseLen int percent int useCommaSep, usePointer, usePositive, useScientificNotation bool @@ -47,6 +48,7 @@ type numberFormat struct { var ( // supportedTokenTypes list the supported number format token types currently. supportedTokenTypes = []string{ + nfp.TokenSubTypeCurrencyString, nfp.TokenSubTypeLanguageInfo, nfp.TokenTypeColor, nfp.TokenTypeCurrencyLanguage, @@ -58,23 +60,20 @@ var ( nfp.TokenTypeHashPlaceHolder, nfp.TokenTypeLiteral, nfp.TokenTypePercent, + nfp.TokenTypeSwitchArgument, nfp.TokenTypeTextPlaceHolder, nfp.TokenTypeThousandsSeparator, nfp.TokenTypeZeroPlaceHolder, } // supportedNumberTokenTypes list the supported number token types. supportedNumberTokenTypes = []string{ - nfp.TokenTypeColor, - nfp.TokenTypeDecimalPoint, + nfp.TokenTypeExponential, nfp.TokenTypeHashPlaceHolder, - nfp.TokenTypeLiteral, nfp.TokenTypePercent, - nfp.TokenTypeThousandsSeparator, nfp.TokenTypeZeroPlaceHolder, } // supportedDateTimeTokenTypes list the supported date and time token types. supportedDateTimeTokenTypes = []string{ - nfp.TokenTypeCurrencyLanguage, nfp.TokenTypeDateTimes, nfp.TokenTypeElapsedDateTimes, } @@ -357,6 +356,30 @@ var ( apFmtYi = "\ua3b8\ua111/\ua06f\ua2d2" // apFmtWelsh defined the AM/PM name in the Welsh. apFmtWelsh = "yb/yh" + // switchArgumentFunc defined the switch argument printer function + switchArgumentFunc = map[string]func(s string) string{ + "[DBNum1]": func(s string) string { + r := strings.NewReplacer( + "0", "\u25cb", "1", "\u4e00", "2", "\u4e8c", "3", "\u4e09", "4", "\u56db", + "5", "\u4e94", "6", "\u516d", "7", "\u4e03", "8", "\u516b", "9", "\u4e5d", + ) + return r.Replace(s) + }, + "[DBNum2]": func(s string) string { + r := strings.NewReplacer( + "0", "\u96f6", "1", "\u58f9", "2", "\u8d30", "3", "\u53c1", "4", "\u8086", + "5", "\u4f0d", "6", "\u9646", "7", "\u67d2", "8", "\u634c", "9", "\u7396", + ) + return r.Replace(s) + }, + "[DBNum3]": func(s string) string { + r := strings.NewReplacer( + "0", "\uff10", "1", "\uff11", "2", "\uff12", "3", "\uff13", "4", "\uff14", + "5", "\uff15", "6", "\uff16", "7", "\uff17", "8", "\uff18", "9", "\uff19", + ) + return r.Replace(s) + }, + } ) // prepareNumberic split the number into two before and after parts by a @@ -431,6 +454,9 @@ func (nf *numberFormat) getNumberFmtConf() { if token.TType == nfp.TokenTypeDecimalPoint { nf.usePointer = true } + if token.TType == nfp.TokenTypeSwitchArgument { + nf.switchArgument = token.TValue + } if token.TType == nfp.TokenTypeZeroPlaceHolder { if nf.usePointer { if nf.useScientificNotation { @@ -448,20 +474,34 @@ func (nf *numberFormat) getNumberFmtConf() { // printNumberLiteral apply literal tokens for the pre-formatted text. func (nf *numberFormat) printNumberLiteral(text string) string { var result string - var useZeroPlaceHolder bool + var useLiteral, useZeroPlaceHolder bool if nf.usePositive { result += "-" } - for _, token := range nf.section[nf.sectionIdx].Items { + for i, token := range nf.section[nf.sectionIdx].Items { + if token.TType == nfp.TokenTypeCurrencyLanguage { + if err := nf.currencyLanguageHandler(i, token); err != nil { + return nf.value + } + result += nf.currencyString + } if token.TType == nfp.TokenTypeLiteral { + if useZeroPlaceHolder { + useLiteral = true + } result += token.TValue } - if !useZeroPlaceHolder && token.TType == nfp.TokenTypeZeroPlaceHolder { - useZeroPlaceHolder = true - result += text + if token.TType == nfp.TokenTypeZeroPlaceHolder { + if useLiteral && useZeroPlaceHolder { + return nf.value + } + if !useZeroPlaceHolder { + useZeroPlaceHolder = true + result += text + } } } - return result + return nf.printSwitchArgument(result) } // printCommaSep format number with thousands separator. @@ -484,6 +524,17 @@ func printCommaSep(text string) string { return target.String() } +// printSwitchArgument format number with switch argument. +func (nf *numberFormat) printSwitchArgument(text string) string { + if nf.switchArgument == "" { + return text + } + if fn, ok := switchArgumentFunc[nf.switchArgument]; ok { + return fn(text) + } + return nf.value +} + // printBigNumber format number which precision great than 15 with fraction // zero padding and percentage symbol. func (nf *numberFormat) printBigNumber(decimal float64, fracLen int) string { @@ -561,14 +612,14 @@ func (nf *numberFormat) numberHandler() string { // dateTimeHandler handling data and time number format expression for a // positive numeric. -func (nf *numberFormat) dateTimeHandler() (result string) { +func (nf *numberFormat) dateTimeHandler() string { nf.t, nf.hours, nf.seconds = timeFromExcelTime(nf.number, nf.date1904), false, false for i, token := range nf.section[nf.sectionIdx].Items { if token.TType == nfp.TokenTypeCurrencyLanguage { if err := nf.currencyLanguageHandler(i, token); err != nil { - result = nf.value - return + return nf.value } + nf.result += nf.currencyString } if token.TType == nfp.TokenTypeDateTimes { nf.dateTimesHandler(i, token) @@ -583,15 +634,18 @@ func (nf *numberFormat) dateTimeHandler() (result string) { if token.TType == nfp.TokenTypeDecimalPoint { nf.result += "." } + if token.TType == nfp.TokenTypeSwitchArgument { + nf.switchArgument = token.TValue + } if token.TType == nfp.TokenTypeZeroPlaceHolder { zeroHolderLen := len(token.TValue) if zeroHolderLen > 3 { zeroHolderLen = 3 } - nf.result += strings.Repeat("0", zeroHolderLen) + nf.result += fmt.Sprintf("%03d", nf.t.Nanosecond()/1e6)[:zeroHolderLen] } } - return nf.result + return nf.printSwitchArgument(nf.result) } // positiveHandler will be handling positive selection for a number format @@ -609,13 +663,26 @@ func (nf *numberFormat) positiveHandler() string { if fmtNum || nf.number < 0 { return nf.value } + var useDateTimeTokens bool + for _, token := range nf.section[nf.sectionIdx].Items { + if inStrSlice(supportedDateTimeTokenTypes, token.TType, false) != -1 { + if useDateTimeTokens && nf.useMillisecond { + return nf.value + } + useDateTimeTokens = true + } + if inStrSlice(supportedNumberTokenTypes, token.TType, false) != -1 { + if token.TType == nfp.TokenTypeZeroPlaceHolder { + nf.useMillisecond = true + continue + } + return nf.value + } + } return nf.dateTimeHandler() } } - if fmtNum { - return nf.numberHandler() - } - return nf.value + return nf.numberHandler() } // currencyLanguageHandler will be handling currency and language types tokens @@ -626,11 +693,16 @@ func (nf *numberFormat) currencyLanguageHandler(i int, token nfp.Token) (err err err = ErrUnsupportedNumberFormat return } - if _, ok := supportedLanguageInfo[strings.ToUpper(part.Token.TValue)]; !ok { - err = ErrUnsupportedNumberFormat - return + if part.Token.TType == nfp.TokenSubTypeLanguageInfo { + if _, ok := supportedLanguageInfo[strings.ToUpper(part.Token.TValue)]; !ok { + err = ErrUnsupportedNumberFormat + return + } + nf.localCode = strings.ToUpper(part.Token.TValue) + } + if part.Token.TType == nfp.TokenSubTypeCurrencyString { + nf.currencyString = part.Token.TValue } - nf.localCode = strings.ToUpper(part.Token.TValue) } return } @@ -1039,17 +1111,17 @@ func (nf *numberFormat) minutesHandler(token nfp.Token) { // secondsHandler will be handling seconds in the date and times types tokens // for a number format expression. func (nf *numberFormat) secondsHandler(token nfp.Token) { - nf.seconds = strings.Contains(strings.ToUpper(token.TValue), "S") - if nf.seconds { - switch len(token.TValue) { - case 1: - nf.result += strconv.Itoa(nf.t.Second()) - return - default: - nf.result += fmt.Sprintf("%02d", nf.t.Second()) - return - } + if nf.seconds = strings.Contains(strings.ToUpper(token.TValue), "S"); !nf.seconds { + return } + if !nf.useMillisecond { + nf.t = nf.t.Add(time.Duration(math.Round(float64(nf.t.Nanosecond())/1e9)) * time.Second) + } + if len(token.TValue) == 1 { + nf.result += strconv.Itoa(nf.t.Second()) + return + } + nf.result += fmt.Sprintf("%02d", nf.t.Second()) } // elapsedDateTimesHandler will be handling elapsed date and times types tokens @@ -1114,23 +1186,15 @@ func (nf *numberFormat) secondsNext(i int) bool { // negativeHandler will be handling negative selection for a number format // expression. func (nf *numberFormat) negativeHandler() (result string) { - fmtNum := true for _, token := range nf.section[nf.sectionIdx].Items { if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral { return nf.value } - if inStrSlice(supportedNumberTokenTypes, token.TType, true) != -1 { - continue - } if inStrSlice(supportedDateTimeTokenTypes, token.TType, true) != -1 { return nf.value } - fmtNum = false } - if fmtNum { - return nf.numberHandler() - } - return nf.value + return nf.numberHandler() } // zeroHandler will be handling zero selection for a number format expression. diff --git a/numfmt_test.go b/numfmt_test.go index bf5cbd28..a8c90047 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/xuri/nfp" ) func TestNumFmt(t *testing.T) { @@ -67,7 +68,7 @@ func TestNumFmt(t *testing.T) { {"43528", "[$-409]MM/DD/YYYY", "03/04/2019"}, {"43528", "[$-409]MM/DD/YYYY am/pm", "03/04/2019 AM"}, {"43528", "[$-111]MM/DD/YYYY", "43528"}, - {"43528", "[$US-409]MM/DD/YYYY", "43528"}, + {"43528", "[$US-409]MM/DD/YYYY", "US03/04/2019"}, {"43543.586539351854", "AM/PM h h:mm", "PM 14 2:04"}, {"text", "AM/PM h h:mm", "text"}, {"44562.189571759256", "[$-36]mmm dd yyyy h:mm AM/PM", "Jan. 01 2022 4:32 vm."}, @@ -1017,6 +1018,18 @@ func TestNumFmt(t *testing.T) { {"-1234.5678", "0.00;-0.00", "-1234.57"}, {"-1234.5678", "0.00%%", "-12345678.00%%"}, {"2.1", "mmss.0000", "2400.000"}, + {"0.007", "[h]:mm:ss.0", "0:10:04.8"}, + {"0.007", "[h]:mm:ss.00", "0:10:04.80"}, + {"0.007", "[h]:mm:ss.000", "0:10:04.800"}, + {"0.007", "[h]:mm:ss.0000", "0:10:04.800"}, + {"123", "[h]:mm,:ss.0", "2952:00,:00.0"}, + {"123", "yy-.dd", "00-.02"}, + {"123", "[DBNum1][$-804]yyyy\"年\"m\"月\";@", "\u4e00\u4e5d\u25cb\u25cb\u5e74\u4e94\u6708"}, + {"123", "[DBNum2][$-804]yyyy\"年\"m\"月\";@", "\u58f9\u7396\u96f6\u96f6\u5e74\u4f0d\u6708"}, + {"123", "[DBNum3][$-804]yyyy\"年\"m\"月\";@", "\uff11\uff19\uff10\uff10\u5e74\uff15\u6708"}, + {"1234567890", "[DBNum1][$-804]0.00", "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u25cb.\u25cb\u25cb"}, + {"1234567890", "[DBNum2][$-804]0.00", "\u58f9\u8d30\u53c1\u8086\u4f0d\u9646\u67d2\u634c\u7396\u96f6.\u96f6\u96f6"}, + {"1234567890", "[DBNum3][$-804]0.00", "\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19\uff10.\uff10\uff10"}, {"1234.5678", "0.00###", "1234.5678"}, {"1234.5678", "00000.00###", "01234.5678"}, {"-1234.5678", "00000.00###;;", ""}, @@ -1029,14 +1042,23 @@ func TestNumFmt(t *testing.T) { {"1.234E-16", "0.000000000000000000", "0.000000000000000123"}, {"1.234E-16", "0.000000000000000000%", "0.000000000000012340%"}, {"1.234E-16", "0.000000000000000000%%%%", "0.000000000000012340%"}, + {"1234.5678", "[$$-409]#,##0.00", "$1,234.57"}, // Unsupported number format {"37947.7500001", "0.00000000E+000", "37947.7500001"}, + {"123", "[$kr.-46F]#,##0.00", "123"}, + {"123", "[$kr.-46F]MM/DD/YYYY", "123"}, + {"123", "[DBNum4][$-804]yyyy\"年\"m\"月\";@", "123"}, // Invalid number format {"123", "x0.00s", "123"}, + {"123", "[h]:m00m:ss", "123"}, + {"123", "yy-00dd", "123"}, + {"123", "yy-##dd", "123"}, + {"123", "xx[h]:mm,:ss.0xx", "xx2952:00,:00.0xx"}, {"-123", "x0.00s", "-123"}, {"-1234.5678", ";E+;", "-1234.5678"}, {"1234.5678", "E+;", "1234.5678"}, {"1234.5678", "00000.00###s", "1234.5678"}, + {"1234.5678", "0.0xxx00", "1234.5678"}, {"-1234.5678", "00000.00###;s;", "-1234.5678"}, } { result := format(item[0], item[1], false, CellTypeNumber) @@ -1055,4 +1077,6 @@ func TestNumFmt(t *testing.T) { assert.Equal(t, item[2], result, item) } } + nf := numberFormat{} + assert.Equal(t, ErrUnsupportedNumberFormat, nf.currencyLanguageHandler(0, nfp.Token{Parts: []nfp.Part{{}}})) } diff --git a/rows_test.go b/rows_test.go index 4a91ab99..5a9dc824 100644 --- a/rows_test.go +++ b/rows_test.go @@ -305,7 +305,7 @@ func TestRemoveRow(t *testing.T) { colCount = 10 rowCount = 10 ) - fillCells(f, sheet1, colCount, rowCount) + assert.NoError(t, fillCells(f, sheet1, colCount, rowCount)) assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/xuri/excelize", "External")) @@ -368,7 +368,7 @@ func TestInsertRows(t *testing.T) { colCount = 10 rowCount = 10 ) - fillCells(f, sheet1, colCount, rowCount) + assert.NoError(t, fillCells(f, sheet1, colCount, rowCount)) assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/xuri/excelize", "External")) diff --git a/styles.go b/styles.go index cb1210e1..bfef6a96 100644 --- a/styles.go +++ b/styles.go @@ -41,8 +41,8 @@ var builtInNumFmt = map[int]string{ 15: "d-mmm-yy", 16: "d-mmm", 17: "mmm-yy", - 18: "h:mm am/pm", - 19: "h:mm:ss am/pm", + 18: "h:mm AM/PM", + 19: "h:mm:ss AM/PM", 20: "hh:mm", 21: "hh:mm:ss", 22: "m/d/yy hh:mm", @@ -56,7 +56,7 @@ var builtInNumFmt = map[int]string{ 44: `_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)`, 45: "mm:ss", 46: "[h]:mm:ss", - 47: "mmss.0", + 47: "mm:ss.0", 48: "##0.0E+0", 49: "@", }