- Formatted cell data support, fix issue #48;
- Function `SetCellValue()` support `time.Time` data type parameter, relate issue #49; - go doc and go test updated
This commit is contained in:
parent
7f30a6c943
commit
8fbab47444
24
cell.go
24
cell.go
|
@ -6,8 +6,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetCellValue provides function to get value from cell by given sheet index
|
// GetCellValue provides function to get formatted value from cell by given
|
||||||
// and axis in XLSX file.
|
// sheet index and axis in XLSX file. If it is possible to apply a format to the
|
||||||
|
// cell value, it will do so, if not then an error will be returned, along with
|
||||||
|
// the raw value of the cell.
|
||||||
func (f *File) GetCellValue(sheet, axis string) string {
|
func (f *File) GetCellValue(sheet, axis string) string {
|
||||||
xlsx := f.workSheetReader(sheet)
|
xlsx := f.workSheetReader(sheet)
|
||||||
axis = strings.ToUpper(axis)
|
axis = strings.ToUpper(axis)
|
||||||
|
@ -44,17 +46,29 @@ func (f *File) GetCellValue(sheet, axis string) string {
|
||||||
xlsxSI := 0
|
xlsxSI := 0
|
||||||
xlsxSI, _ = strconv.Atoi(r.V)
|
xlsxSI, _ = strconv.Atoi(r.V)
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/sharedStrings.xml")), &shardStrings)
|
xml.Unmarshal([]byte(f.readXML("xl/sharedStrings.xml")), &shardStrings)
|
||||||
return shardStrings.SI[xlsxSI].T
|
return f.formattedValue(r.S, shardStrings.SI[xlsxSI].T)
|
||||||
case "str":
|
case "str":
|
||||||
return r.V
|
return f.formattedValue(r.S, r.V)
|
||||||
default:
|
default:
|
||||||
return r.V
|
return f.formattedValue(r.S, r.V)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formattedValue provides function to returns a value after formatted. If it is
|
||||||
|
// possible to apply a format to the cell value, it will do so, if not then an
|
||||||
|
// error will be returned, along with the raw value of the cell.
|
||||||
|
func (f *File) formattedValue(s int, v string) string {
|
||||||
|
if s == 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
var styleSheet xlsxStyleSheet
|
||||||
|
xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
|
||||||
|
return builtInNumFmtFunc[styleSheet.CellXfs.Xf[s].NumFmtID](styleSheet.CellXfs.Xf[s].NumFmtID, v)
|
||||||
|
}
|
||||||
|
|
||||||
// GetCellFormula provides function to get formula from cell by given sheet
|
// GetCellFormula provides function to get formula from cell by given sheet
|
||||||
// index and axis in XLSX file.
|
// index and axis in XLSX file.
|
||||||
func (f *File) GetCellFormula(sheet, axis string) string {
|
func (f *File) GetCellFormula(sheet, axis string) string {
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package excelize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// timeLocationUTC defined the UTC time location.
|
||||||
|
var timeLocationUTC, _ = time.LoadLocation("UTC")
|
||||||
|
|
||||||
|
// timeToUTCTime provides function to convert time to UTC time.
|
||||||
|
func timeToUTCTime(t time.Time) time.Time {
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), timeLocationUTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeToExcelTime provides function to convert time to Excel time.
|
||||||
|
func timeToExcelTime(t time.Time) float64 {
|
||||||
|
return float64(t.UnixNano())/8.64e13 + 25569.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// shiftJulianToNoon provides function to process julian date to noon.
|
||||||
|
func shiftJulianToNoon(julianDays, julianFraction float64) (float64, float64) {
|
||||||
|
switch {
|
||||||
|
case -0.5 < julianFraction && julianFraction < 0.5:
|
||||||
|
julianFraction += 0.5
|
||||||
|
case julianFraction >= 0.5:
|
||||||
|
julianDays++
|
||||||
|
julianFraction -= 0.5
|
||||||
|
case julianFraction <= -0.5:
|
||||||
|
julianDays--
|
||||||
|
julianFraction += 1.5
|
||||||
|
}
|
||||||
|
return julianDays, julianFraction
|
||||||
|
}
|
||||||
|
|
||||||
|
// fractionOfADay provides function to return the integer values for hour,
|
||||||
|
// minutes, seconds and nanoseconds that comprised a given fraction of a day.
|
||||||
|
// values would round to 1 us.
|
||||||
|
func fractionOfADay(fraction float64) (hours, minutes, seconds, nanoseconds int) {
|
||||||
|
|
||||||
|
const (
|
||||||
|
c1us = 1e3
|
||||||
|
c1s = 1e9
|
||||||
|
c1day = 24 * 60 * 60 * c1s
|
||||||
|
)
|
||||||
|
|
||||||
|
frac := int64(c1day*fraction + c1us/2)
|
||||||
|
nanoseconds = int((frac%c1s)/c1us) * c1us
|
||||||
|
frac /= c1s
|
||||||
|
seconds = int(frac % 60)
|
||||||
|
frac /= 60
|
||||||
|
minutes = int(frac % 60)
|
||||||
|
hours = int(frac / 60)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// julianDateToGregorianTime provides function to convert julian date to
|
||||||
|
// gregorian time.
|
||||||
|
func julianDateToGregorianTime(part1, part2 float64) time.Time {
|
||||||
|
part1I, part1F := math.Modf(part1)
|
||||||
|
part2I, part2F := math.Modf(part2)
|
||||||
|
julianDays := part1I + part2I
|
||||||
|
julianFraction := part1F + part2F
|
||||||
|
julianDays, julianFraction = shiftJulianToNoon(julianDays, julianFraction)
|
||||||
|
day, month, year := doTheFliegelAndVanFlandernAlgorithm(int(julianDays))
|
||||||
|
hours, minutes, seconds, nanoseconds := fractionOfADay(julianFraction)
|
||||||
|
return time.Date(year, time.Month(month), day, hours, minutes, seconds, nanoseconds, time.UTC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// By this point generations of programmers have repeated the algorithm sent to
|
||||||
|
// the editor of "Communications of the ACM" in 1968 (published in CACM, volume
|
||||||
|
// 11, number 10, October 1968, p.657). None of those programmers seems to have
|
||||||
|
// found it necessary to explain the constants or variable names set out by
|
||||||
|
// Henry F. Fliegel and Thomas C. Van Flandern. Maybe one day I'll buy that
|
||||||
|
// jounal and expand an explanation here - that day is not today.
|
||||||
|
func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
|
||||||
|
l := jd + 68569
|
||||||
|
n := (4 * l) / 146097
|
||||||
|
l = l - (146097*n+3)/4
|
||||||
|
i := (4000 * (l + 1)) / 1461001
|
||||||
|
l = l - (1461*i)/4 + 31
|
||||||
|
j := (80 * l) / 2447
|
||||||
|
d := l - (2447*j)/80
|
||||||
|
l = j / 11
|
||||||
|
m := j + 2 - (12 * l)
|
||||||
|
y := 100*(n-49) + i + l
|
||||||
|
return d, m, y
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeFromExcelTime provides function to convert an excelTime representation
|
||||||
|
// (stored as a floating point number) to a time.Time.
|
||||||
|
func timeFromExcelTime(excelTime float64, date1904 bool) time.Time {
|
||||||
|
var date time.Time
|
||||||
|
var intPart = int64(excelTime)
|
||||||
|
// Excel uses Julian dates prior to March 1st 1900, and Gregorian
|
||||||
|
// thereafter.
|
||||||
|
if intPart <= 61 {
|
||||||
|
const OFFSET1900 = 15018.0
|
||||||
|
const OFFSET1904 = 16480.0
|
||||||
|
const MJD0 float64 = 2400000.5
|
||||||
|
var date time.Time
|
||||||
|
if date1904 {
|
||||||
|
date = julianDateToGregorianTime(MJD0, excelTime+OFFSET1904)
|
||||||
|
} else {
|
||||||
|
date = julianDateToGregorianTime(MJD0, excelTime+OFFSET1900)
|
||||||
|
}
|
||||||
|
return date
|
||||||
|
}
|
||||||
|
var floatPart = excelTime - float64(intPart)
|
||||||
|
var dayNanoSeconds float64 = 24 * 60 * 60 * 1000 * 1000 * 1000
|
||||||
|
if date1904 {
|
||||||
|
date = time.Date(1904, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
} else {
|
||||||
|
date = time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
|
||||||
|
}
|
||||||
|
durationDays := time.Duration(intPart) * time.Hour * 24
|
||||||
|
durationPart := time.Duration(dayNanoSeconds * floatPart)
|
||||||
|
return date.Add(durationDays).Add(durationPart)
|
||||||
|
}
|
|
@ -4,11 +4,13 @@ import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// File define a populated XLSX file struct.
|
// File define a populated XLSX file struct.
|
||||||
|
@ -84,8 +86,13 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) {
|
||||||
f.SetCellStr(sheet, axis, t)
|
f.SetCellStr(sheet, axis, t)
|
||||||
case []byte:
|
case []byte:
|
||||||
f.SetCellStr(sheet, axis, string(t))
|
f.SetCellStr(sheet, axis, string(t))
|
||||||
default:
|
case time.Time:
|
||||||
|
f.SetCellDefault(sheet, axis, strconv.FormatFloat(float64(timeToExcelTime(timeToUTCTime(value.(time.Time)))), 'f', -1, 32))
|
||||||
|
f.SetCellStyle(sheet, axis, axis, `{"number_format": 22}`)
|
||||||
|
case nil:
|
||||||
f.SetCellStr(sheet, axis, "")
|
f.SetCellStr(sheet, axis, "")
|
||||||
|
default:
|
||||||
|
f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOpenFile(t *testing.T) {
|
func TestOpenFile(t *testing.T) {
|
||||||
|
@ -66,6 +67,8 @@ func TestOpenFile(t *testing.T) {
|
||||||
xlsx.SetCellValue("Sheet2", "F2", float32(42))
|
xlsx.SetCellValue("Sheet2", "F2", float32(42))
|
||||||
xlsx.SetCellValue("Sheet2", "F2", float64(42))
|
xlsx.SetCellValue("Sheet2", "F2", float64(42))
|
||||||
xlsx.SetCellValue("Sheet2", "G2", nil)
|
xlsx.SetCellValue("Sheet2", "G2", nil)
|
||||||
|
xlsx.SetCellValue("Sheet2", "G3", uint8(8))
|
||||||
|
xlsx.SetCellValue("Sheet2", "G4", time.Now())
|
||||||
// Test completion column.
|
// Test completion column.
|
||||||
xlsx.SetCellValue("Sheet2", "M2", nil)
|
xlsx.SetCellValue("Sheet2", "M2", nil)
|
||||||
// Test read cell value with given axis large than exists row.
|
// Test read cell value with given axis large than exists row.
|
||||||
|
@ -322,18 +325,40 @@ func TestSetCellStyleBorder(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetCellStyleFill(t *testing.T) {
|
func TestSetCellStyleNumberFormat(t *testing.T) {
|
||||||
xlsx, err := OpenFile("./test/Workbook_2.xlsx")
|
xlsx, err := OpenFile("./test/Workbook_2.xlsx")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
xlsx.SetCellValue("Sheet1", "N23", 42920.5)
|
|
||||||
// Test only set fill and number format for a cell.
|
// Test only set fill and number format for a cell.
|
||||||
err = xlsx.SetCellStyle("Sheet1", "N23", "N23", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":4},"number_format":22}`)
|
col := []string{"L", "M", "N", "O", "P"}
|
||||||
|
data := []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"}
|
||||||
|
for i, v := range value {
|
||||||
|
for k, d := range data {
|
||||||
|
c := col[i] + strconv.Itoa(k+1)
|
||||||
|
var val float64
|
||||||
|
val, err = strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
xlsx.SetCellValue("Sheet2", c, v)
|
||||||
|
} else {
|
||||||
|
xlsx.SetCellValue("Sheet2", c, val)
|
||||||
|
}
|
||||||
|
err := xlsx.SetCellStyle("Sheet2", c, c, `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format": `+strconv.Itoa(d)+`}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
t.Log(xlsx.GetCellValue("Sheet2", c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = xlsx.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
err = xlsx.SetCellStyle("Sheet1", "N24", "N24", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5},"number_format":23}`)
|
}
|
||||||
|
|
||||||
|
func TestSetCellStyleFill(t *testing.T) {
|
||||||
|
xlsx, err := OpenFile("./test/Workbook_2.xlsx")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
|
|
6
rows.go
6
rows.go
|
@ -141,10 +141,10 @@ func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
|
||||||
}
|
}
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
return d.SI[xlsxSI].T, nil
|
return f.formattedValue(xlsx.S, d.SI[xlsxSI].T), nil
|
||||||
case "str":
|
case "str":
|
||||||
return xlsx.V, nil
|
return f.formattedValue(xlsx.S, xlsx.V), nil
|
||||||
default:
|
default:
|
||||||
return xlsx.V, nil
|
return f.formattedValue(xlsx.S, xlsx.V), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
179
styles.go
179
styles.go
|
@ -3,6 +3,8 @@ package excelize
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -45,6 +47,183 @@ var builtInNumFmt = map[int]string{
|
||||||
49: "@",
|
49: "@",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// builtInNumFmtFunc defined the format conversion functions map. Partial format
|
||||||
|
// code doesn't support currently and will return original string.
|
||||||
|
var builtInNumFmtFunc = map[int]func(i int, v string) string{
|
||||||
|
0: formatToString,
|
||||||
|
1: formatToInt,
|
||||||
|
2: formatToFloat,
|
||||||
|
3: formatToInt,
|
||||||
|
4: formatToFloat,
|
||||||
|
9: formatToC,
|
||||||
|
10: formatToD,
|
||||||
|
11: formatToE,
|
||||||
|
12: formatToString, // Doesn't support currently
|
||||||
|
13: formatToString, // Doesn't support currently
|
||||||
|
14: parseTime,
|
||||||
|
15: parseTime,
|
||||||
|
16: parseTime,
|
||||||
|
17: parseTime,
|
||||||
|
18: parseTime,
|
||||||
|
19: parseTime,
|
||||||
|
20: parseTime,
|
||||||
|
21: parseTime,
|
||||||
|
22: parseTime,
|
||||||
|
37: formatToA,
|
||||||
|
38: formatToA,
|
||||||
|
39: formatToB,
|
||||||
|
40: formatToB,
|
||||||
|
41: formatToString, // Doesn't support currently
|
||||||
|
42: formatToString, // Doesn't support currently
|
||||||
|
43: formatToString, // Doesn't support currently
|
||||||
|
44: formatToString, // Doesn't support currently
|
||||||
|
45: parseTime,
|
||||||
|
46: parseTime,
|
||||||
|
47: parseTime,
|
||||||
|
48: formatToE,
|
||||||
|
49: formatToString,
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToString provides function to return original string by given built-in
|
||||||
|
// number formats code and cell string.
|
||||||
|
func formatToString(i int, v string) string {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToInt provides function to convert original string to integer format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToInt(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d", int(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToFloat provides function to convert original string to float format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToFloat(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.2f", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToA provides function to convert original string to special format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToA(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
if f < 0 {
|
||||||
|
t := int(math.Abs(f))
|
||||||
|
return fmt.Sprintf("(%d)", t)
|
||||||
|
}
|
||||||
|
t := int(f)
|
||||||
|
return fmt.Sprintf("%d", t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToB provides function to convert original string to special format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToB(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
if f < 0 {
|
||||||
|
return fmt.Sprintf("(%.2f)", f)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.2f", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToC provides function to convert original string to special format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToC(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
f = f * 100
|
||||||
|
return fmt.Sprintf("%d%%", int(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToD provides function to convert original string to special format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToD(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
f = f * 100
|
||||||
|
return fmt.Sprintf("%.2f%%", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatToE provides function to convert original string to special format as
|
||||||
|
// string type by given built-in number formats code and cell string.
|
||||||
|
func formatToE(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.e", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseTime provides function to returns a string parsed using time.Time.
|
||||||
|
// Replace Excel placeholders with Go time placeholders. For example, replace
|
||||||
|
// yyyy with 2006. These are in a specific order, due to the fact that m is used
|
||||||
|
// in month, minute, and am/pm. It would be easier to fix that with regular
|
||||||
|
// expressions, but if it's possible to keep this simple it would be easier to
|
||||||
|
// maintain. Full-length month and days (e.g. March, Tuesday) have letters in
|
||||||
|
// them that would be replaced by other characters below (such as the 'h' in
|
||||||
|
// March, or the 'd' in Tuesday) below. First we convert them to arbitrary
|
||||||
|
// characters unused in Excel Date formats, and then at the end, turn them to
|
||||||
|
// what they should actually be.
|
||||||
|
func parseTime(i int, v string) string {
|
||||||
|
f, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
val := timeFromExcelTime(f, false)
|
||||||
|
format := builtInNumFmt[i]
|
||||||
|
|
||||||
|
replacements := []struct{ xltime, gotime string }{
|
||||||
|
{"yyyy", "2006"},
|
||||||
|
{"yy", "06"},
|
||||||
|
{"mmmm", "%%%%"},
|
||||||
|
{"dddd", "&&&&"},
|
||||||
|
{"dd", "02"},
|
||||||
|
{"d", "2"},
|
||||||
|
{"mmm", "Jan"},
|
||||||
|
{"mmss", "0405"},
|
||||||
|
{"ss", "05"},
|
||||||
|
{"hh", "15"},
|
||||||
|
{"h", "3"},
|
||||||
|
{"mm:", "04:"},
|
||||||
|
{":mm", ":04"},
|
||||||
|
{"mm", "01"},
|
||||||
|
{"am/pm", "pm"},
|
||||||
|
{"m/", "1/"},
|
||||||
|
{"%%%%", "January"},
|
||||||
|
{"&&&&", "Monday"},
|
||||||
|
}
|
||||||
|
for _, repl := range replacements {
|
||||||
|
format = strings.Replace(format, repl.xltime, repl.gotime, 1)
|
||||||
|
}
|
||||||
|
// If the hour is optional, strip it out, along with the possible dangling
|
||||||
|
// colon that would remain.
|
||||||
|
if val.Hour() < 1 {
|
||||||
|
format = strings.Replace(format, "]:", "]", 1)
|
||||||
|
format = strings.Replace(format, "[3]", "", 1)
|
||||||
|
format = strings.Replace(format, "[15]", "", 1)
|
||||||
|
} else {
|
||||||
|
format = strings.Replace(format, "[3]", "3", 1)
|
||||||
|
format = strings.Replace(format, "[15]", "15", 1)
|
||||||
|
}
|
||||||
|
return val.Format(format)
|
||||||
|
}
|
||||||
|
|
||||||
// parseFormatStyleSet provides function to parse the format settings of the
|
// parseFormatStyleSet provides function to parse the format settings of the
|
||||||
// borders.
|
// borders.
|
||||||
func parseFormatStyleSet(style string) (*formatCellStyle, error) {
|
func parseFormatStyleSet(style string) (*formatCellStyle, error) {
|
||||||
|
|
Loading…
Reference in New Issue