diff options
| author | xuri <xuri.me@gmail.com> | 2022-02-13 00:06:30 +0800 | 
|---|---|---|
| committer | xuri <xuri.me@gmail.com> | 2022-02-13 00:06:30 +0800 | 
| commit | 4b64b26c52932a51ca97a2bb6bf372a07020e52b (patch) | |
| tree | 0d5b88ab9db7b459de73e65b022871ef69fe2cd6 /styles.go | |
| parent | 3f8f4f52e68d408da5a2e5108af3cc99bf8586bc (diff) | |
Ref: #660, #764, #1093, #1112, #1133 This improve number format support
- Introduced NFP (number format parser) dependencies module
- Initialize custom dates and times number format support
- Dependencies module upgraded
Diffstat (limited to 'styles.go')
| -rw-r--r-- | styles.go | 185 | 
1 files changed, 20 insertions, 165 deletions
| @@ -20,7 +20,6 @@ import (  	"log"  	"math"  	"reflect" -	"regexp"  	"strconv"  	"strings"  ) @@ -756,7 +755,7 @@ var currencyNumFmt = map[int]string{  // builtInNumFmtFunc defined the format conversion functions map. Partial format  // code doesn't support currently and will return original string.  var builtInNumFmtFunc = map[int]func(v string, format string) string{ -	0:  formatToString, +	0:  format,  	1:  formatToInt,  	2:  formatToFloat,  	3:  formatToInt, @@ -764,30 +763,30 @@ var builtInNumFmtFunc = map[int]func(v string, format string) string{  	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, +	12: format, // Doesn't support currently +	13: format, // Doesn't support currently +	14: format, +	15: format, +	16: format, +	17: format, +	18: format, +	19: format, +	20: format, +	21: format, +	22: format,  	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, +	41: format, // Doesn't support currently +	42: format, // Doesn't support currently +	43: format, // Doesn't support currently +	44: format, // Doesn't support currently +	45: format, +	46: format, +	47: format,  	48: formatToE, -	49: formatToString, +	49: format,  }  // validType defined the list of valid validation types. @@ -845,12 +844,6 @@ var criteriaType = map[string]string{  	"continue month":           "continueMonth",  } -// formatToString provides a function to return original string by given -// built-in number formats code and cell string. -func formatToString(v string, format string) string { -	return v -} -  // formatToInt provides a function to convert original string to integer  // format as string type by given built-in number formats code and cell  // string. @@ -933,144 +926,6 @@ func formatToE(v string, format string) string {  	return fmt.Sprintf("%.2E", f)  } -// parseTime provides a 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. Based off: -// http://www.ozgrid.com/Excel/CustomFormats.htm -func parseTime(v string, format string) string { -	var ( -		f     float64 -		err   error -		goFmt string -	) -	f, err = strconv.ParseFloat(v, 64) -	if err != nil { -		return v -	} -	val := timeFromExcelTime(f, false) - -	if format == "" { -		return v -	} - -	goFmt = format - -	if strings.Contains(goFmt, "[") { -		re := regexp.MustCompile(`\[.+\]`) -		goFmt = re.ReplaceAllLiteralString(goFmt, "") -	} - -	// use only first variant -	if strings.Contains(goFmt, ";") { -		goFmt = goFmt[:strings.IndexByte(goFmt, ';')] -	} - -	replacements := []struct{ xltime, gotime string }{ -		{"YYYY", "2006"}, -		{"YY", "06"}, -		{"MM", "01"}, -		{"M", "1"}, -		{"DD", "02"}, -		{"D", "2"}, -		{"yyyy", "2006"}, -		{"yy", "06"}, -		{"MMMM", "%%%%"}, -		{"mmmm", "%%%%"}, -		{"DDDD", "&&&&"}, -		{"dddd", "&&&&"}, -		{"DD", "02"}, -		{"dd", "02"}, -		{"D", "2"}, -		{"d", "2"}, -		{"MMM", "Jan"}, -		{"mmm", "Jan"}, -		{"MMSS", "0405"}, -		{"mmss", "0405"}, -		{"SS", "05"}, -		{"ss", "05"}, -		{"s", "5"}, -		{"MM:", "04:"}, -		{"mm:", "04:"}, -		{":MM", ":04"}, -		{":mm", ":04"}, -		{"m:", "4:"}, -		{":m", ":4"}, -		{"MM", "01"}, -		{"mm", "01"}, -		{"AM/PM", "PM"}, -		{"am/pm", "PM"}, -		{"M/", "1/"}, -		{"m/", "1/"}, -		{"%%%%", "January"}, -		{"&&&&", "Monday"}, -	} - -	replacementsGlobal := []struct{ xltime, gotime string }{ -		{"\\-", "-"}, -		{"\\ ", " "}, -		{"\\.", "."}, -		{"\\", ""}, -		{"\"", ""}, -	} -	// It is the presence of the "am/pm" indicator that determines if this is -	// a 12 hour or 24 hours time format, not the number of 'h' characters. -	var padding bool -	if val.Hour() == 0 && !strings.Contains(format, "hh") && !strings.Contains(format, "HH") { -		padding = true -	} -	if is12HourTime(format) { -		goFmt = strings.Replace(goFmt, "hh", "3", 1) -		goFmt = strings.Replace(goFmt, "h", "3", 1) -		goFmt = strings.Replace(goFmt, "HH", "3", 1) -		goFmt = strings.Replace(goFmt, "H", "3", 1) -	} else { -		goFmt = strings.Replace(goFmt, "hh", "15", 1) -		goFmt = strings.Replace(goFmt, "HH", "15", 1) -		if 0 < val.Hour() && val.Hour() < 12 { -			goFmt = strings.Replace(goFmt, "h", "3", 1) -			goFmt = strings.Replace(goFmt, "H", "3", 1) -		} else { -			goFmt = strings.Replace(goFmt, "h", "15", 1) -			goFmt = strings.Replace(goFmt, "H", "15", 1) -		} -	} - -	for _, repl := range replacements { -		goFmt = strings.Replace(goFmt, repl.xltime, repl.gotime, 1) -	} -	for _, repl := range replacementsGlobal { -		goFmt = strings.Replace(goFmt, 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 { -		goFmt = strings.Replace(goFmt, "]:", "]", 1) -		goFmt = strings.Replace(goFmt, "[03]", "", 1) -		goFmt = strings.Replace(goFmt, "[3]", "", 1) -		goFmt = strings.Replace(goFmt, "[15]", "", 1) -	} else { -		goFmt = strings.Replace(goFmt, "[3]", "3", 1) -		goFmt = strings.Replace(goFmt, "[15]", "15", 1) -	} -	s := val.Format(goFmt) -	if padding { -		s = strings.Replace(s, "00:", "0:", 1) -	} -	return s -} - -// is12HourTime checks whether an Excel time format string is a 12 hours form. -func is12HourTime(format string) bool { -	return strings.Contains(format, "am/pm") || strings.Contains(format, "AM/PM") || strings.Contains(format, "a/p") || strings.Contains(format, "A/P") -} -  // stylesReader provides a function to get the pointer to the structure after  // deserialization of xl/styles.xml.  func (f *File) stylesReader() *xlsxStyleSheet { | 
