Procházet zdrojové kódy

- Function `formattedValue()` performance improvement by avoid repeating deserialization, relate issue #64;
- Make function `ToAlphaString()` exportable, relate issue #63

Ri Xu před 8 roky
rodič
revize
35841caaf1
6 změnil soubory, kde provedl 46 přidání a 28 odebrání
  1. 3 4
      cell.go
  2. 4 3
      excelize.go
  3. 1 0
      file.go
  4. 6 3
      lib.go
  5. 29 15
      styles.go
  6. 3 3
      table.go

+ 3 - 4
cell.go

@@ -70,8 +70,7 @@ 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)
+	styleSheet := f.stylesReader()
 	ok := builtInNumFmtFunc[styleSheet.CellXfs.Xf[s].NumFmtID]
 	if ok != nil {
 		return ok(styleSheet.CellXfs.Xf[s].NumFmtID, v)
@@ -200,7 +199,7 @@ func (f *File) MergeCell(sheet, hcell, vcell string) {
 	if xlsx.MergeCells != nil {
 		mergeCell := xlsxMergeCell{}
 		// Correct the coordinate area, such correct C1:B3 to B1:C3.
-		mergeCell.Ref = toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
+		mergeCell.Ref = ToAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + ToAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
 		// Delete the merged cells of the overlapping area.
 		for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
 			if checkCellInArea(hcell, xlsx.MergeCells.Cells[i].Ref) || checkCellInArea(strings.Split(xlsx.MergeCells.Cells[i].Ref, ":")[0], mergeCell.Ref) {
@@ -213,7 +212,7 @@ func (f *File) MergeCell(sheet, hcell, vcell string) {
 	} else {
 		mergeCell := xlsxMergeCell{}
 		// Correct the coordinate area, such correct C1:B3 to B1:C3.
-		mergeCell.Ref = toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
+		mergeCell.Ref = ToAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + ToAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
 		mergeCells := xlsxMergeCells{}
 		mergeCells.Cells = append(mergeCells.Cells, &mergeCell)
 		xlsx.MergeCells = &mergeCells

+ 4 - 3
excelize.go

@@ -20,6 +20,7 @@ type File struct {
 	Path         string
 	Sheet        map[string]*xlsxWorksheet
 	SheetCount   int
+	Styles       *xlsxStyleSheet
 	WorkBook     *xlsxWorkbook
 	WorkBookRels *xlsxWorkbookRels
 	XLSX         map[string]string
@@ -268,7 +269,7 @@ func completeCol(xlsx *xlsxWorksheet, row, cell int) {
 		if len(v.C) < cell {
 			start := len(v.C)
 			for iii := start; iii < cell; iii++ {
-				buffer.WriteString(toAlphaString(iii + 1))
+				buffer.WriteString(ToAlphaString(iii + 1))
 				buffer.WriteString(strconv.Itoa(k + 1))
 				xlsx.SheetData.Row[k].C = append(xlsx.SheetData.Row[k].C, xlsxC{
 					R: buffer.String(),
@@ -300,7 +301,7 @@ func completeRow(xlsx *xlsxWorksheet, row, cell int) {
 		start := len(xlsx.SheetData.Row[ii].C)
 		if start == 0 {
 			for iii := start; iii < cell; iii++ {
-				buffer.WriteString(toAlphaString(iii + 1))
+				buffer.WriteString(ToAlphaString(iii + 1))
 				buffer.WriteString(strconv.Itoa(ii + 1))
 				xlsx.SheetData.Row[ii].C = append(xlsx.SheetData.Row[ii].C, xlsxC{
 					R: buffer.String(),
@@ -388,7 +389,7 @@ func checkRow(xlsx *xlsxWorksheet) {
 			xlsx.SheetData.Row[k].C = xlsx.SheetData.Row[k].C[:0]
 			tmp := []xlsxC{}
 			for i := 0; i <= endCol; i++ {
-				buffer.WriteString(toAlphaString(i + 1))
+				buffer.WriteString(ToAlphaString(i + 1))
 				buffer.WriteString(strconv.Itoa(endRow))
 				tmp = append(tmp, xlsxC{
 					R: buffer.String(),

+ 1 - 0
file.go

@@ -57,6 +57,7 @@ func (f *File) Write(w io.Writer) error {
 	f.workbookWriter()
 	f.workbookRelsWriter()
 	f.worksheetWriter()
+	f.styleSheetWriter()
 	for path, content := range f.XLSX {
 		fi, err := zw.Create(path)
 		if err != nil {

+ 6 - 3
lib.go

@@ -50,9 +50,12 @@ func readFile(file *zip.File) string {
 	return string(buff.Bytes())
 }
 
-// toAlphaString provides function to convert integer to Excel sheet column
-// title.
-func toAlphaString(value int) string {
+// ToAlphaString provides function to convert integer to Excel sheet column
+// title. For example convert 37 to column title AK:
+//
+//     excelize.ToAlphaString(37)
+//
+func ToAlphaString(value int) string {
 	if value < 0 {
 		return ""
 	}

+ 29 - 15
styles.go

@@ -224,6 +224,26 @@ func parseTime(i int, v string) string {
 	return val.Format(format)
 }
 
+// stylesReader provides function to get the pointer to the structure after
+// deserialization of workbook.
+func (f *File) stylesReader() *xlsxStyleSheet {
+	if f.Styles == nil {
+		var styleSheet xlsxStyleSheet
+		xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
+		f.Styles = &styleSheet
+	}
+	return f.Styles
+}
+
+// styleSheetWriter provides function to save xl/styles.xml after serialize
+// structure.
+func (f *File) styleSheetWriter() {
+	if f.Styles != nil {
+		output, _ := xml.Marshal(f.Styles)
+		f.saveFileList("xl/styles.xml", replaceWorkSheetsRelationshipsNameSpace(string(output)))
+	}
+}
+
 // parseFormatStyleSet provides function to parse the format settings of the
 // borders.
 func parseFormatStyleSet(style string) (*formatCellStyle, error) {
@@ -500,23 +520,17 @@ func parseFormatStyleSet(style string) (*formatCellStyle, error) {
 //    +-------+----------------------------------------------------+
 //
 func (f *File) SetCellStyle(sheet, hcell, vcell, style string) error {
-	var styleSheet xlsxStyleSheet
-	xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
+	styleSheet := f.stylesReader()
 	formatCellStyle, err := parseFormatStyleSet(style)
 	if err != nil {
 		return err
 	}
-	numFmtID := setNumFmt(&styleSheet, formatCellStyle)
-	fontID := setFont(&styleSheet, formatCellStyle)
-	borderID := setBorders(&styleSheet, formatCellStyle)
-	fillID := setFills(&styleSheet, formatCellStyle)
-	applyAlignment, alignment := setAlignment(&styleSheet, formatCellStyle)
-	cellXfsID := setCellXfs(&styleSheet, fontID, numFmtID, fillID, borderID, applyAlignment, alignment)
-	output, err := xml.Marshal(styleSheet)
-	if err != nil {
-		return err
-	}
-	f.saveFileList("xl/styles.xml", replaceWorkSheetsRelationshipsNameSpace(string(output)))
+	numFmtID := setNumFmt(styleSheet, formatCellStyle)
+	fontID := setFont(styleSheet, formatCellStyle)
+	borderID := setBorders(styleSheet, formatCellStyle)
+	fillID := setFills(styleSheet, formatCellStyle)
+	applyAlignment, alignment := setAlignment(styleSheet, formatCellStyle)
+	cellXfsID := setCellXfs(styleSheet, fontID, numFmtID, fillID, borderID, applyAlignment, alignment)
 	f.setCellStyle(sheet, hcell, vcell, cellXfsID)
 	return err
 }
@@ -771,8 +785,8 @@ func (f *File) setCellStyle(sheet, hcell, vcell string, styleID int) {
 	}
 
 	// Correct the coordinate area, such correct C1:B3 to B1:C3.
-	hcell = toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1)
-	vcell = toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
+	hcell = ToAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1)
+	vcell = ToAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
 
 	xlsx := f.workSheetReader(sheet)
 

+ 3 - 3
table.go

@@ -108,12 +108,12 @@ func (f *File) addTable(sheet, tableXML string, hxAxis, hyAxis, vxAxis, vyAxis,
 		vyAxis++
 	}
 	// Correct table reference coordinate area, such correct C1:B3 to B1:C3.
-	ref := toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
+	ref := ToAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + ToAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
 	tableColumn := []*xlsxTableColumn{}
 	idx := 0
 	for i := hxAxis; i <= vxAxis; i++ {
 		idx++
-		cell := toAlphaString(i+1) + strconv.Itoa(hyAxis+1)
+		cell := ToAlphaString(i+1) + strconv.Itoa(hyAxis+1)
 		name := f.GetCellValue(sheet, cell)
 		if _, err := strconv.Atoi(name); err == nil {
 			f.SetCellStr(sheet, cell, name)
@@ -254,7 +254,7 @@ func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
 	if vyAxis < hyAxis {
 		vyAxis, hyAxis = hyAxis, vyAxis
 	}
-	ref := toAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + toAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
+	ref := ToAlphaString(hxAxis+1) + strconv.Itoa(hyAxis+1) + ":" + ToAlphaString(vxAxis+1) + strconv.Itoa(vyAxis+1)
 	refRange := vxAxis - hxAxis
 	err := f.autoFilter(sheet, ref, refRange, hxAxis, formatSet)
 	return err