Browse Source

AddSheetWithStyle no longer add the first row of a sheet

AddSheetWithStyle now takes as input a slice of StreamStyles. These stream styles define the number of columns that will be made and the default style of the columns.
DamianSzkuat 6 years ago
parent
commit
3b64955439
6 changed files with 76 additions and 66 deletions
  1. 6 0
      col.go
  2. 8 7
      stream_file.go
  3. 17 15
      stream_file_builder.go
  4. 40 39
      stream_style_test.go
  5. 1 1
      stream_test.go
  6. 4 4
      xmlStyle.go

+ 6 - 0
col.go

@@ -47,3 +47,9 @@ func (c *Col) GetStyle() *Style {
 func (c *Col) SetStyle(style *Style) {
 	c.style = style
 }
+
+// SetStreamStyle sets the style and number format id to the ones specified in the given StreamStyle
+func (c *Col) SetStreamStyle(style StreamStyle) {
+	c.style = style.style
+	c.numFmt = builtInNumFmt[style.xNumFmtId]
+}

+ 8 - 7
stream_file.go

@@ -15,7 +15,7 @@ type StreamFile struct {
 	zipWriter      *zip.Writer
 	currentSheet   *streamSheet
 	styleIds       [][]int
-	styleIdMap	   map[StreamStyle]int
+	styleIdMap     map[StreamStyle]int
 	err            error
 }
 
@@ -86,7 +86,7 @@ func (sf *StreamFile) WriteAll(records [][]string) error {
 // WriteAllWithStyle will write all the rows provided in records. All rows must have the same number of cells as
 // the headers. This function will always trigger a flush on success. WriteWithStyle supports all data types and
 // styles that are supported by StreamCell.
-func (sf *StreamFile) WriteAllWithStyle(records [][]StreamCell) error{
+func (sf *StreamFile) WriteAllWithStyle(records [][]StreamCell) error {
 	if sf.err != nil {
 		return sf.err
 	}
@@ -154,6 +154,7 @@ func (sf *StreamFile) writeWithStyle(cells []StreamCell) error {
 	if len(cells) != sf.currentSheet.columnCount {
 		return WrongNumberOfRowsError
 	}
+
 	sf.currentSheet.rowCount++
 	// Write the row opening
 	if err := sf.currentSheet.write(`<row r="` + strconv.Itoa(sf.currentSheet.rowCount) + `">`); err != nil {
@@ -201,7 +202,7 @@ func (sf *StreamFile) writeWithStyle(cells []StreamCell) error {
 		}
 
 		// Write cell contents
-		if err:= xml.EscapeText(sf.currentSheet.writer, []byte(cell.cellData)); err != nil {
+		if err := xml.EscapeText(sf.currentSheet.writer, []byte(cell.cellData)); err != nil {
 			return err
 		}
 
@@ -232,7 +233,7 @@ func getCellTypeAsString(cellType CellType) (string, error) {
 	// n (Number): Cell containing a number.
 	// s (Shared String): Cell containing a shared string.
 	// str (String): Cell containing a formula string.
-	switch cellType{
+	switch cellType {
 	case CellTypeBool:
 		return "b", nil
 	case CellTypeDate:
@@ -255,7 +256,7 @@ func getCellTypeAsString(cellType CellType) (string, error) {
 }
 
 func getCellContentOpenAncCloseTags(cellType CellType) (string, string, error) {
-	switch cellType{
+	switch cellType {
 	case CellTypeString:
 		// TODO Currently shared strings are types as inline strings
 		return `<is><t>`, `</t></is>`, nil
@@ -304,7 +305,7 @@ func (sf *StreamFile) NextSheet() error {
 		index:       sheetIndex,
 		columnCount: len(sf.xlsxFile.Sheets[sheetIndex-1].Cols),
 		styleIds:    sf.styleIds[sheetIndex-1],
-		rowCount:    1,
+		rowCount:    len(sf.xlsxFile.Sheets[sheetIndex-1].Rows),
 	}
 	sheetPath := sheetFilePathPrefix + strconv.Itoa(sf.currentSheet.index) + sheetFilePathSuffix
 	fileWriter, err := sf.zipWriter.Create(sheetPath)
@@ -371,4 +372,4 @@ func (sf *StreamFile) writeSheetEnd() error {
 func (ss *streamSheet) write(data string) error {
 	_, err := ss.writer.Write([]byte(data))
 	return err
-}
+}

+ 17 - 15
stream_file_builder.go

@@ -125,11 +125,11 @@ func (sb *StreamFileBuilder) AddSheet(name string, headers []string, cellTypes [
 	return nil
 }
 
-// TODO update comments
-// AddSheetWithStyle will add sheets with the given name with the provided headers. The headers cannot be edited later, and all
-// rows written to the sheet must contain the same number of cells as the header. Sheet names must be unique, or an
-// error will be thrown. Additionally AddSheetWithStyle allows to add Style information to the headers.
-func (sb *StreamFileBuilder) AddSheetWithStyle(name string, cells []StreamCell) error {
+// AddSheetWithStyle will add a sheet with the given name and column styles. The number of column styles given
+// is the number of columns that will be created, and thus the number of cell each row has to have.
+// columnStyles[0] becomes the style of the first column, columnStyles[1] the style of the second column etc.
+// Sheet names must be unique, or an error will be thrown.
+func (sb *StreamFileBuilder) AddSheetWithStyle(name string, columnStyles []StreamStyle) error {
 	if sb.built {
 		return BuiltStreamFileBuilderError
 	}
@@ -143,8 +143,8 @@ func (sb *StreamFileBuilder) AddSheetWithStyle(name string, cells []StreamCell)
 	sb.firstSheetAdded = true
 
 	// Check if all styles in the headers have been created
-	for _, cell := range cells {
-		if _, ok := sb.customStreamStyles[cell.cellStyle]; !ok {
+	for _, colStyle := range columnStyles {
+		if _, ok := sb.customStreamStyles[colStyle]; !ok {
 			return errors.New("trying to make use of a style that has not been added")
 		}
 	}
@@ -159,11 +159,11 @@ func (sb *StreamFileBuilder) AddSheetWithStyle(name string, cells []StreamCell)
 	//	sb.built = true
 	//	return errors.New("failed to write headers")
 	//}
-	sheet.maybeAddCol(len(cells))
+	sheet.maybeAddCol(len(columnStyles))
 
 	// Set default column types based on the cel types in the first row
-	for i, cell := range cells {
-		sheet.Cols[i].SetType(cell.cellType)
+	for i, colStyle := range columnStyles {
+		sheet.Cols[i].SetStreamStyle(colStyle)
 		sheet.Cols[i].Width = 11
 	}
 	return nil
@@ -201,7 +201,7 @@ func (sb *StreamFileBuilder) Build() (*StreamFile, error) {
 		// If the part is a sheet, don't write it yet. We only want to write the XLSX metadata files, since at this
 		// point the sheets are still empty. The sheet files will be written later as their rows come in.
 		if strings.HasPrefix(path, sheetFilePathPrefix) {
-			if err := sb.processEmptySheetXML(es, path, data); err != nil {
+			if err := sb.processEmptySheetXML(es, path, data, !sb.customStylesAdded); err != nil {
 				return nil, err
 			}
 			continue
@@ -270,7 +270,7 @@ func (sb *StreamFileBuilder) AddStreamStyleList(streamStyles []StreamStyle) erro
 
 // processEmptySheetXML will take in the path and XML data of an empty sheet, and will save the beginning and end of the
 // XML file so that these can be written at the right time.
-func (sb *StreamFileBuilder) processEmptySheetXML(sf *StreamFile, path, data string) error {
+func (sb *StreamFileBuilder) processEmptySheetXML(sf *StreamFile, path, data string, removeDimensionTagFlag bool) error {
 	// Get the sheet index from the path
 	sheetIndex, err := getSheetIndex(sf, path)
 	if err != nil {
@@ -279,9 +279,11 @@ func (sb *StreamFileBuilder) processEmptySheetXML(sf *StreamFile, path, data str
 
 	// Remove the Dimension tag. Since more rows are going to be written to the sheet, it will be wrong.
 	// It is valid to for a sheet to be missing a Dimension tag, but it is not valid for it to be wrong.
-	data, err = removeDimensionTag(data, sf.xlsxFile.Sheets[sheetIndex])
-	if err != nil {
-		return err
+	if removeDimensionTagFlag {
+		data, err = removeDimensionTag(data, sf.xlsxFile.Sheets[sheetIndex])
+		if err != nil {
+			return err
+		}
 	}
 
 	// Split the sheet at the end of its SheetData tag so that more rows can be added inside.

+ 40 - 39
stream_style_test.go

@@ -10,7 +10,7 @@ import (
 )
 
 const (
-	StyleStreamTestsShouldMakeRealFiles = false
+	StyleStreamTestsShouldMakeRealFiles = true
 )
 
 type StreamStyleSuite struct{}
@@ -252,7 +252,7 @@ func (s *StreamSuite) TestXlsxStreamWriteWithStyle(t *C) {
 						MakeIntegerStreamCell(300), MakeStringStreamCell(`<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>`)},
 					// Upside down text and Right to Left Arabic text
 					{MakeIntegerStreamCell(123), MakeStringStreamCell(`˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥
-					00˙Ɩ$-`), MakeIntegerStreamCell(300), MakeStringStreamCell(`ﷺ`)} ,
+					00˙Ɩ$-`), MakeIntegerStreamCell(300), MakeStringStreamCell(`ﷺ`)},
 					{MakeIntegerStreamCell(123), MakeStringStreamCell("Taco"),
 						MakeIntegerStreamCell(300), MakeIntegerStreamCell(123)},
 				},
@@ -288,9 +288,9 @@ func (s *StreamSuite) TestXlsxStreamWriteWithStyle(t *C) {
 		}
 
 		expectedWorkbookDataStrings := [][][]string{}
-		for j,_ := range testCase.workbookData {
+		for j, _ := range testCase.workbookData {
 			expectedWorkbookDataStrings = append(expectedWorkbookDataStrings, [][]string{})
-			for k,_ := range testCase.workbookData[j]{
+			for k, _ := range testCase.workbookData[j] {
 				expectedWorkbookDataStrings[j] = append(expectedWorkbookDataStrings[j], []string{})
 				for _, cell := range testCase.workbookData[j][k] {
 					expectedWorkbookDataStrings[j][k] = append(expectedWorkbookDataStrings[j][k], cell.cellData)
@@ -306,7 +306,7 @@ func (s *StreamSuite) TestXlsxStreamWriteWithStyle(t *C) {
 
 // writeStreamFile will write the file using this stream package
 func writeStreamFileWithStyle(filePath string, fileBuffer io.Writer, sheetNames []string, workbookData [][][]StreamCell,
-								shouldMakeRealFiles bool, customStyles []StreamStyle) error {
+	shouldMakeRealFiles bool, customStyles []StreamStyle) error {
 	var file *StreamFileBuilder
 	var err error
 	if shouldMakeRealFiles {
@@ -319,8 +319,8 @@ func writeStreamFileWithStyle(filePath string, fileBuffer io.Writer, sheetNames
 	}
 
 	defaultStyles := []StreamStyle{Strings, BoldStrings, ItalicStrings, UnderlinedStrings,
-						Integers, BoldIntegers, ItalicIntegers, UnderlinedIntegers,
-						Dates}
+		Integers, BoldIntegers, ItalicIntegers, UnderlinedIntegers,
+		Dates}
 	allStylesToBeAdded := append(defaultStyles, customStyles...)
 	err = file.AddStreamStyleList(allStylesToBeAdded)
 	if err != nil {
@@ -328,8 +328,12 @@ func writeStreamFileWithStyle(filePath string, fileBuffer io.Writer, sheetNames
 	}
 
 	for i, sheetName := range sheetNames {
-		header := workbookData[i][0]
-		err := file.AddSheetWithStyle(sheetName, header)
+		colStyles := []StreamStyle{}
+		for _, cell := range workbookData[i][0] {
+			colStyles = append(colStyles, cell.cellStyle)
+		}
+
+		err := file.AddSheetWithStyle(sheetName, colStyles)
 		if err != nil {
 			return err
 		}
@@ -346,10 +350,10 @@ func writeStreamFileWithStyle(filePath string, fileBuffer io.Writer, sheetNames
 				return err
 			}
 		}
-		for i, row := range sheetData {
-			if i == 0 {
-				continue
-			}
+		for _, row := range sheetData {
+			//if i == 0 {
+			//	continue
+			//}
 			err = streamFile.WriteWithStyle(row)
 			if err != nil {
 				return err
@@ -419,11 +423,11 @@ func (s *StreamSuite) TestMakeNewStylesAndUseIt(t *C) {
 	// read the file back with the xlsx package
 	var bufReader *bytes.Reader
 	var size int64
-	if !TestsShouldMakeRealFiles {
+	if !StyleStreamTestsShouldMakeRealFiles {
 		bufReader = bytes.NewReader(buffer.Bytes())
 		size = bufReader.Size()
 	}
-	actualSheetNames, actualWorkbookData := readXLSXFile(t, filePath, bufReader, size, TestsShouldMakeRealFiles)
+	actualSheetNames, actualWorkbookData := readXLSXFile(t, filePath, bufReader, size, StyleStreamTestsShouldMakeRealFiles)
 	// check if data was able to be read correctly
 	if !reflect.DeepEqual(actualSheetNames, sheetNames) {
 		t.Fatal("Expected sheet names to be equal")
@@ -455,7 +459,7 @@ func (s *StreamSuite) TestCloseWithNothingWrittenToSheetsWithStyle(t *C) {
 		{{MakeStringStreamCell("Header3"), MakeStringStreamCell("Header4")}},
 	}
 
-	defaultStyles := []StreamStyle{Strings,BoldStrings,ItalicIntegers,UnderlinedStrings,
+	defaultStyles := []StreamStyle{Strings, BoldStrings, ItalicIntegers, UnderlinedStrings,
 		Integers, BoldIntegers, ItalicIntegers, UnderlinedIntegers,
 		Dates}
 	err := file.AddStreamStyleList(defaultStyles)
@@ -463,11 +467,21 @@ func (s *StreamSuite) TestCloseWithNothingWrittenToSheetsWithStyle(t *C) {
 		t.Fatal(err)
 	}
 
-	err = file.AddSheetWithStyle(sheetNames[0], workbookData[0][0])
+	colStyles0 := []StreamStyle{}
+	for _, cell := range workbookData[0][0] {
+		colStyles0 = append(colStyles0, cell.cellStyle)
+	}
+
+	colStyles1 := []StreamStyle{}
+	for _, cell := range workbookData[1][0] {
+		colStyles1 = append(colStyles1, cell.cellStyle)
+	}
+
+	err = file.AddSheetWithStyle(sheetNames[0], colStyles0)
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheetWithStyle(sheetNames[1], workbookData[1][0])
+	err = file.AddSheetWithStyle(sheetNames[1], colStyles1)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -489,15 +503,8 @@ func (s *StreamSuite) TestCloseWithNothingWrittenToSheetsWithStyle(t *C) {
 		t.Fatal("Expected sheet names to be equal")
 	}
 	expectedWorkbookDataStrings := [][][]string{}
-	for j,_ := range workbookData {
+	for range workbookData {
 		expectedWorkbookDataStrings = append(expectedWorkbookDataStrings, [][]string{})
-		for k,_ := range workbookData[j]{
-			expectedWorkbookDataStrings[j] = append(expectedWorkbookDataStrings[j], []string{})
-			for _, cell := range workbookData[j][k] {
-				expectedWorkbookDataStrings[j][k] = append(expectedWorkbookDataStrings[j][k], cell.cellData)
-			}
-		}
-
 	}
 	if !reflect.DeepEqual(actualWorkbookData, expectedWorkbookDataStrings) {
 		t.Fatal("Expected workbook data to be equal")
@@ -507,7 +514,7 @@ func (s *StreamSuite) TestCloseWithNothingWrittenToSheetsWithStyle(t *C) {
 func (s *StreamSuite) TestBuildErrorsAfterBuildWithStyle(t *C) {
 	file := NewStreamFileBuilder(bytes.NewBuffer(nil))
 
-	defaultStyles := []StreamStyle{Strings,BoldStrings,ItalicIntegers,UnderlinedStrings,
+	defaultStyles := []StreamStyle{Strings, BoldStrings, ItalicIntegers, UnderlinedStrings,
 		Integers, BoldIntegers, ItalicIntegers, UnderlinedIntegers,
 		Dates}
 	err := file.AddStreamStyleList(defaultStyles)
@@ -515,11 +522,11 @@ func (s *StreamSuite) TestBuildErrorsAfterBuildWithStyle(t *C) {
 		t.Fatal(err)
 	}
 
-	err = file.AddSheetWithStyle("Sheet1", []StreamCell{MakeStringStreamCell("Header")})
+	err = file.AddSheetWithStyle("Sheet1", []StreamStyle{Strings})
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheetWithStyle("Sheet2", []StreamCell{MakeStringStreamCell("Header")})
+	err = file.AddSheetWithStyle("Sheet2", []StreamStyle{Strings})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -537,7 +544,7 @@ func (s *StreamSuite) TestBuildErrorsAfterBuildWithStyle(t *C) {
 func (s *StreamSuite) TestAddSheetWithStyleErrorsAfterBuild(t *C) {
 	file := NewStreamFileBuilder(bytes.NewBuffer(nil))
 
-	defaultStyles := []StreamStyle{Strings,BoldStrings,ItalicIntegers,UnderlinedStrings,
+	defaultStyles := []StreamStyle{Strings, BoldStrings, ItalicIntegers, UnderlinedStrings,
 		Integers, BoldIntegers, ItalicIntegers, UnderlinedIntegers,
 		Dates}
 	err := file.AddStreamStyleList(defaultStyles)
@@ -545,11 +552,11 @@ func (s *StreamSuite) TestAddSheetWithStyleErrorsAfterBuild(t *C) {
 		t.Fatal(err)
 	}
 
-	err = file.AddSheetWithStyle("Sheet1", []StreamCell{MakeStringStreamCell("Header")})
+	err = file.AddSheetWithStyle("Sheet1", []StreamStyle{Strings})
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheetWithStyle("Sheet2", []StreamCell{MakeStringStreamCell("Header2")})
+	err = file.AddSheetWithStyle("Sheet2", []StreamStyle{Strings})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -558,14 +565,8 @@ func (s *StreamSuite) TestAddSheetWithStyleErrorsAfterBuild(t *C) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheetWithStyle("Sheet3", []StreamCell{MakeStringStreamCell("Header3")})
+	err = file.AddSheetWithStyle("Sheet3", []StreamStyle{Strings})
 	if err != BuiltStreamFileBuilderError {
 		t.Fatal(err)
 	}
 }
-
-
-
-
-
-

+ 1 - 1
stream_test.go

@@ -484,4 +484,4 @@ func (s *StreamSuite) TestCloseWithNothingWrittenToSheets(t *C) {
 	if !reflect.DeepEqual(actualWorkbookData, workbookData) {
 		t.Fatal("Expected workbook data to be equal")
 	}
-}
+}

+ 4 - 4
xmlStyle.go

@@ -103,7 +103,7 @@ type xlsxStyleSheet struct {
 
 	theme *theme
 
-	sync.RWMutex      // protects the following
+	sync.RWMutex // protects the following
 	styleCache        map[int]*Style
 	numFmtRefTable    map[int]xlsxNumFmt
 	parsedNumFmtTable map[string]*parsedNumberFormat
@@ -211,9 +211,9 @@ func (styles *xlsxStyleSheet) getStyle(styleIndex int) *Style {
 			style.Alignment.Vertical = xf.Alignment.Vertical
 		}
 		style.Alignment.WrapText = xf.Alignment.WrapText
-        	style.Alignment.TextRotation = xf.Alignment.TextRotation
-		
-        	styles.Lock()
+		style.Alignment.TextRotation = xf.Alignment.TextRotation
+
+		styles.Lock()
 		styles.styleCache[styleIndex] = style
 		styles.Unlock()
 	}