Browse Source

- Set text in cell align support, note that the parameters of the `SetCellStyle` function have changed;
- go test updated

Ri Xu 8 years ago
parent
commit
b6254209fe
3 changed files with 142 additions and 59 deletions
  1. 21 12
      excelize_test.go
  2. 109 46
      styles.go
  3. 12 1
      xmlStyles.go

+ 21 - 12
excelize_test.go

@@ -272,7 +272,19 @@ func TestSetRowHeight(t *testing.T) {
 	}
 	}
 }
 }
 
 
-func TestSetCellStyle(t *testing.T) {
+func TestSetCellStyleAlignment(t *testing.T) {
+	xlsx, err := OpenFile("./test/Workbook_2.xlsx")
+	if err != nil {
+		t.Log(err)
+	}
+	err = xlsx.SetCellStyle("Sheet1", "A22", "A22", `{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"top","wrap_text":true}}`)
+	err = xlsx.Save()
+	if err != nil {
+		t.Log(err)
+	}
+}
+
+func TestSetCellStyleBorder(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)
@@ -287,20 +299,17 @@ func TestSetCellStyle(t *testing.T) {
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
-	if err != nil {
-		t.Log(err)
-	}
 	// Test set border on overlapping area with vertical variants shading styles gradient fill.
 	// Test set border on overlapping area with vertical variants shading styles gradient fill.
 	err = xlsx.SetCellStyle("Sheet1", "J21", "L25", `{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":12},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":9},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
 	err = xlsx.SetCellStyle("Sheet1", "J21", "L25", `{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":12},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":9},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
-	err = xlsx.SetCellStyle("Sheet1", "M28", "K24", `{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":[{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "M28", "K24", `{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
 	// Test set border and solid style pattern fill for a single cell.
 	// Test set border and solid style pattern fill for a single cell.
-	err = xlsx.SetCellStyle("Sheet1", "O22", "O22", `{"border":[{"type":"left","color":"0000FF","style":8},{"type":"top","color":"00FF00","style":9},{"type":"bottom","color":"FFFF00","style":10},{"type":"right","color":"FF0000","style":11},{"type":"diagonalDown","color":"A020F0","style":12},{"type":"diagonalUp","color":"A020F0","style":13}],"fill":[{"type":"pattern","color":["#E0EBF5"],"pattern":1}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "O22", "O22", `{"border":[{"type":"left","color":"0000FF","style":8},{"type":"top","color":"00FF00","style":9},{"type":"bottom","color":"FFFF00","style":10},{"type":"right","color":"FF0000","style":11},{"type":"diagonalDown","color":"A020F0","style":12},{"type":"diagonalUp","color":"A020F0","style":13}],"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
@@ -316,28 +325,28 @@ func TestSetCellStyleFill(t *testing.T) {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
 	// Test only set fill for a cell.
 	// Test only set fill for a cell.
-	err = xlsx.SetCellStyle("Sheet1", "N23", "N23", `{"fill":[{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":4}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "N23", "N23", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":4}}`)
 	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}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "N24", "N24", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":5}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
 	// Test set fill for cell with invalid parameter.
 	// Test set fill for cell with invalid parameter.
-	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":[{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":6}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
-	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":[{"type":"gradient","color":["#FFFFFF"],"shading":1}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
-	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":[{"type":"pattern","color":[],"pattern":1}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":{"type":"pattern","color":[],"pattern":1}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}
-	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":[{"type":"pattern","color":["#E0EBF5"],"pattern":19}]}`)
+	err = xlsx.SetCellStyle("Sheet1", "O23", "O23", `{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
 	if err != nil {
 	if err != nil {
 		t.Log(err)
 		t.Log(err)
 	}
 	}

+ 109 - 46
styles.go

@@ -15,7 +15,7 @@ func parseFormatStyleSet(style string) (*formatCellStyle, error) {
 	return &format, err
 	return &format, err
 }
 }
 
 
-// SetCellStyle provides function to get value from cell by given sheet index
+// SetCellStyle provides function to set style for cells by given sheet index
 // and coordinate area in XLSX file. Note that the color field uses RGB color
 // and coordinate area in XLSX file. Note that the color field uses RGB color
 // code and diagonalDown and diagonalUp type border should be use same color in
 // code and diagonalDown and diagonalUp type border should be use same color in
 // the same coordinate area.
 // the same coordinate area.
@@ -30,14 +30,21 @@ func parseFormatStyleSet(style string) (*formatCellStyle, error) {
 // Set gradient fill with vertical variants shading styles for cell H9 on
 // Set gradient fill with vertical variants shading styles for cell H9 on
 // Sheet1:
 // Sheet1:
 //
 //
-//    err := xlsx.SetBorder("Sheet1", "H9", "H9", `{"fill":[{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}]}`)
+//    err := xlsx.SetBorder("Sheet1", "H9", "H9", `{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
 //    if err != nil {
 //    if err != nil {
 //        fmt.Println(err)
 //        fmt.Println(err)
 //    }
 //    }
 //
 //
 // Set solid style pattern fill for cell H9 on Sheet1:
 // Set solid style pattern fill for cell H9 on Sheet1:
 //
 //
-//    err := xlsx.SetBorder("Sheet1", "H9", "H9", `{"fill":[{"type":"pattern","color":["#E0EBF5"],"pattern":1}]}`)
+//    err := xlsx.SetBorder("Sheet1", "H9", "H9", `{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
+//    if err != nil {
+//        fmt.Println(err)
+//    }
+//
+// Set alignment style for cell H9 on Sheet1:
+//
+//    err = xlsx.SetCellStyle("Sheet2", "H9", "H9", `{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"","wrap_text":true}}`)
 //    if err != nil {
 //    if err != nil {
 //        fmt.Println(err)
 //        fmt.Println(err)
 //    }
 //    }
@@ -134,6 +141,40 @@ func parseFormatStyleSet(style string) (*formatCellStyle, error) {
 //    | 9     | darkGrid        |       |                 |
 //    | 9     | darkGrid        |       |                 |
 //    +-------+-----------------+-------+-----------------+
 //    +-------+-----------------+-------+-----------------+
 //
 //
+// The following the type of horizontal alignment in cells:
+//
+//    +------------------+
+//    | Style            |
+//    +==================+
+//    | left             |
+//    +------------------+
+//    | center           |
+//    +------------------+
+//    | right            |
+//    +------------------+
+//    | fill             |
+//    +------------------+
+//    | justify          |
+//    +------------------+
+//    | centerContinuous |
+//    +------------------+
+//    | distributed      |
+//    +------------------+
+//
+// The following the type of vertical alignment in cells:
+//
+//    +------------------+
+//    | Style            |
+//    +==================+
+//    | top              |
+//    +------------------+
+//    | center           |
+//    +------------------+
+//    | justify          |
+//    +------------------+
+//    | distributed      |
+//    +------------------+
+//
 func (f *File) SetCellStyle(sheet, hcell, vcell, style string) error {
 func (f *File) SetCellStyle(sheet, hcell, vcell, style string) error {
 	var styleSheet xlsxStyleSheet
 	var styleSheet xlsxStyleSheet
 	xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
 	xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
@@ -143,7 +184,8 @@ func (f *File) SetCellStyle(sheet, hcell, vcell, style string) error {
 	}
 	}
 	borderID := setBorders(&styleSheet, formatCellStyle)
 	borderID := setBorders(&styleSheet, formatCellStyle)
 	fillID := setFills(&styleSheet, formatCellStyle)
 	fillID := setFills(&styleSheet, formatCellStyle)
-	cellXfsID := setCellXfs(&styleSheet, fillID, borderID)
+	applyAlignment, alignment := setAlignment(&styleSheet, formatCellStyle)
+	cellXfsID := setCellXfs(&styleSheet, fillID, borderID, applyAlignment, alignment)
 	output, err := xml.Marshal(styleSheet)
 	output, err := xml.Marshal(styleSheet)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -186,54 +228,73 @@ func setFills(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
 	}
 	}
 
 
 	var fill xlsxFill
 	var fill xlsxFill
-	for _, v := range formatCellStyle.Fill {
-		switch v.Type {
-		case "gradient":
-			if len(v.Color) != 2 {
-				continue
-			}
-			var gradient xlsxGradientFill
-			switch v.Shading {
-			case 0, 1, 2, 3:
-				gradient.Degree = variants[v.Shading]
-			case 4:
-				gradient.Type = "path"
-			case 5:
-				gradient.Type = "path"
-				gradient.Bottom = 0.5
-				gradient.Left = 0.5
-				gradient.Right = 0.5
-				gradient.Top = 0.5
-			default:
-				continue
-			}
-			var stops []*xlsxGradientFillStop
-			for index, color := range v.Color {
-				var stop xlsxGradientFillStop
-				stop.Position = float64(index)
-				stop.Color.RGB = getPaletteColor(color)
-				stops = append(stops, &stop)
-			}
-			gradient.Stop = stops
-			fill.GradientFill = &gradient
-		case "pattern":
-			if v.Pattern > 18 || v.Pattern < 0 {
-				continue
-			}
-			if len(v.Color) < 1 {
-				continue
-			}
-			var pattern xlsxPatternFill
-			pattern.PatternType = patterns[v.Pattern]
-			pattern.FgColor.RGB = getPaletteColor(v.Color[0])
-			fill.PatternFill = &pattern
+	switch formatCellStyle.Fill.Type {
+	case "gradient":
+		if len(formatCellStyle.Fill.Color) != 2 {
+			break
+		}
+		var gradient xlsxGradientFill
+		switch formatCellStyle.Fill.Shading {
+		case 0, 1, 2, 3:
+			gradient.Degree = variants[formatCellStyle.Fill.Shading]
+		case 4:
+			gradient.Type = "path"
+		case 5:
+			gradient.Type = "path"
+			gradient.Bottom = 0.5
+			gradient.Left = 0.5
+			gradient.Right = 0.5
+			gradient.Top = 0.5
+		default:
+			break
+		}
+		var stops []*xlsxGradientFillStop
+		for index, color := range formatCellStyle.Fill.Color {
+			var stop xlsxGradientFillStop
+			stop.Position = float64(index)
+			stop.Color.RGB = getPaletteColor(color)
+			stops = append(stops, &stop)
+		}
+		gradient.Stop = stops
+		fill.GradientFill = &gradient
+	case "pattern":
+		if formatCellStyle.Fill.Pattern > 18 || formatCellStyle.Fill.Pattern < 0 {
+			break
 		}
 		}
+		if len(formatCellStyle.Fill.Color) < 1 {
+			break
+		}
+		var pattern xlsxPatternFill
+		pattern.PatternType = patterns[formatCellStyle.Fill.Pattern]
+		pattern.FgColor.RGB = getPaletteColor(formatCellStyle.Fill.Color[0])
+		fill.PatternFill = &pattern
 	}
 	}
 	style.Fills.Count++
 	style.Fills.Count++
 	style.Fills.Fill = append(style.Fills.Fill, &fill)
 	style.Fills.Fill = append(style.Fills.Fill, &fill)
 	return style.Fills.Count - 1
 	return style.Fills.Count - 1
 }
 }
 
 
+// setAlignment provides function to formatting information pertaining to text
+// alignment in cells. There are a variety of choices for how text is aligned
+// both horizontally and vertically, as well as indentation settings, and so on.
+func setAlignment(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) (bool, *xlsxAlignment) {
+	if formatCellStyle.Alignment == nil {
+		return false, &xlsxAlignment{}
+	}
+	var alignment = xlsxAlignment{
+		Horizontal:      formatCellStyle.Alignment.Horizontal,
+		Indent:          formatCellStyle.Alignment.Indent,
+		JustifyLastLine: formatCellStyle.Alignment.JustifyLastLine,
+		ReadingOrder:    formatCellStyle.Alignment.ReadingOrder,
+		RelativeIndent:  formatCellStyle.Alignment.RelativeIndent,
+		ShrinkToFit:     formatCellStyle.Alignment.ShrinkToFit,
+		TextRotation:    formatCellStyle.Alignment.TextRotation,
+		Vertical:        formatCellStyle.Alignment.Vertical,
+		WrapText:        formatCellStyle.Alignment.WrapText,
+	}
+	return true, &alignment
+}
+
 // setBorders provides function to add border elements in the styles.xml by
 // setBorders provides function to add border elements in the styles.xml by
 // given borders format settings.
 // given borders format settings.
 func setBorders(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
 func setBorders(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
@@ -291,11 +352,13 @@ func setBorders(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
 
 
 // setCellXfs provides function to set describes all of the formatting for a
 // setCellXfs provides function to set describes all of the formatting for a
 // cell.
 // cell.
-func setCellXfs(style *xlsxStyleSheet, fillID, borderID int) int {
+func setCellXfs(style *xlsxStyleSheet, fillID, borderID int, applyAlignment bool, alignment *xlsxAlignment) int {
 	var xf xlsxXf
 	var xf xlsxXf
 	xf.FillID = fillID
 	xf.FillID = fillID
 	xf.BorderID = borderID
 	xf.BorderID = borderID
 	style.CellXfs.Count++
 	style.CellXfs.Count++
+	xf.Alignment = alignment
+	xf.ApplyAlignment = applyAlignment
 	style.CellXfs.Xf = append(style.CellXfs.Xf, xf)
 	style.CellXfs.Xf = append(style.CellXfs.Xf, xf)
 	return style.CellXfs.Count - 1
 	return style.CellXfs.Count - 1
 }
 }

+ 12 - 1
xmlStyles.go

@@ -277,10 +277,21 @@ type formatCellStyle struct {
 		Color string `json:"color"`
 		Color string `json:"color"`
 		Style int    `json:"style"`
 		Style int    `json:"style"`
 	} `json:"border"`
 	} `json:"border"`
-	Fill []struct {
+	Fill struct {
 		Type    string   `json:"type"`
 		Type    string   `json:"type"`
 		Pattern int      `json:"pattern"`
 		Pattern int      `json:"pattern"`
 		Color   []string `json:"color"`
 		Color   []string `json:"color"`
 		Shading int      `json:"shading"`
 		Shading int      `json:"shading"`
 	} `json:"fill"`
 	} `json:"fill"`
+	Alignment *struct {
+		Horizontal      string `json:"horizontal"`
+		Indent          int    `json:"indent,omitempty"`
+		JustifyLastLine bool   `json:"justify_last_line"`
+		ReadingOrder    uint64 `json:"reading_order"`
+		RelativeIndent  int    `json:"relative_indent"`
+		ShrinkToFit     bool   `json:"shrink_to_fit"`
+		TextRotation    int    `json:"text_rotation"`
+		Vertical        string `json:"vertical"`
+		WrapText        bool   `json:"wrap_text"`
+	} `json:"alignment"`
 }
 }