浏览代码

#826, support merge cell in streaming mode

xuri 4 年之前
父节点
当前提交
af5e87dbcf
共有 2 个文件被更改,包括 39 次插入7 次删除
  1. 27 7
      stream.go
  2. 12 0
      stream_test.go

+ 27 - 7
stream.go

@@ -26,12 +26,14 @@ import (
 
 // StreamWriter defined the type of stream writer.
 type StreamWriter struct {
-	File       *File
-	Sheet      string
-	SheetID    int
-	worksheet  *xlsxWorksheet
-	rawData    bufferedWriter
-	tableParts string
+	File            *File
+	Sheet           string
+	SheetID         int
+	worksheet       *xlsxWorksheet
+	rawData         bufferedWriter
+	mergeCellsCount int
+	mergeCells      string
+	tableParts      string
 }
 
 // NewStreamWriter return stream writer struct by given worksheet name for
@@ -322,6 +324,19 @@ func (sw *StreamWriter) SetRow(axis string, values []interface{}) error {
 	return sw.rawData.Sync()
 }
 
+// MergeCell provides a function to merge cells by a given coordinate area for
+// the StreamWriter. Don't create a merged cell that overlaps with another
+// existing merged cell.
+func (sw *StreamWriter) MergeCell(hcell, vcell string) error {
+	_, err := areaRangeToCoordinates(hcell, vcell)
+	if err != nil {
+		return err
+	}
+	sw.mergeCellsCount++
+	sw.mergeCells += fmt.Sprintf(`<mergeCell ref="%s:%s"/>`, hcell, vcell)
+	return nil
+}
+
 // setCellFormula provides a function to set formula of a cell.
 func setCellFormula(c *xlsxC, formula string) {
 	if formula != "" {
@@ -413,7 +428,12 @@ func writeCell(buf *bufferedWriter, c xlsxC) {
 // Flush ending the streaming writing process.
 func (sw *StreamWriter) Flush() error {
 	_, _ = sw.rawData.WriteString(`</sheetData>`)
-	bulkAppendFields(&sw.rawData, sw.worksheet, 8, 38)
+	bulkAppendFields(&sw.rawData, sw.worksheet, 8, 15)
+	if sw.mergeCellsCount > 0 {
+		sw.mergeCells = fmt.Sprintf(`<mergeCells count="%d">%s</mergeCells>`, sw.mergeCellsCount, sw.mergeCells)
+	}
+	_, _ = sw.rawData.WriteString(sw.mergeCells)
+	bulkAppendFields(&sw.rawData, sw.worksheet, 17, 38)
 	_, _ = sw.rawData.WriteString(sw.tableParts)
 	bulkAppendFields(&sw.rawData, sw.worksheet, 40, 40)
 	_, _ = sw.rawData.WriteString(`</worksheet>`)

+ 12 - 0
stream_test.go

@@ -134,6 +134,18 @@ func TestStreamTable(t *testing.T) {
 	assert.EqualError(t, streamWriter.AddTable("A1", "B", `{}`), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
 }
 
+func TestStreamMergeCells(t *testing.T) {
+	file := NewFile()
+	streamWriter, err := file.NewStreamWriter("Sheet1")
+	assert.NoError(t, err)
+	assert.NoError(t, streamWriter.MergeCell("A1", "D1"))
+	// Test merge cells with illegal cell coordinates.
+	assert.EqualError(t, streamWriter.MergeCell("A", "D1"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
+	assert.NoError(t, streamWriter.Flush())
+	// Save spreadsheet by the given path.
+	assert.NoError(t, file.SaveAs(filepath.Join("test", "TestStreamMergeCells.xlsx")))
+}
+
 func TestNewStreamWriter(t *testing.T) {
 	// Test error exceptions
 	file := NewFile()