DamianSzkuat %!s(int64=6) %!d(string=hai) anos
pai
achega
b7384e1ff5
Modificáronse 5 ficheiros con 144 adicións e 52 borrados
  1. 5 6
      stream_file.go
  2. 10 28
      stream_file_builder.go
  3. 101 0
      stream_style.go
  4. 18 18
      stream_test.go
  5. 10 0
      style.go

+ 5 - 6
stream_file.go

@@ -16,6 +16,7 @@ type StreamFile struct {
 	currentSheet   *streamSheet
 	styleIds       [][]int
 	err            error
+	styleIdMap	   map[*StreamStyle]int
 }
 
 type streamSheet struct {
@@ -43,7 +44,7 @@ var (
 // same number of cells as the header provided when the sheet was created or an error will be returned. This function
 // will always trigger a flush on success. Currently the only supported data type is string data.
 // TODO update comment
-func (sf *StreamFile) Write(cells []string, cellTypes []*CellType, cellStyles []int) error {
+func (sf *StreamFile) Write(cells []string, cellTypes []*CellType, cellStyles []*StreamStyle) error {
 	if sf.err != nil {
 		return sf.err
 	}
@@ -56,7 +57,7 @@ func (sf *StreamFile) Write(cells []string, cellTypes []*CellType, cellStyles []
 }
 
 //TODO Add comment
-func (sf *StreamFile) WriteAll(records [][]string, cellTypes []*CellType, cellStyles []int) error {
+func (sf *StreamFile) WriteAll(records [][]string, cellTypes []*CellType, cellStyles []*StreamStyle) error {
 	if sf.err != nil {
 		return sf.err
 	}
@@ -70,10 +71,8 @@ func (sf *StreamFile) WriteAll(records [][]string, cellTypes []*CellType, cellSt
 	return sf.zipWriter.Flush()
 }
 
-
-
 // TODO Add comment
-func (sf *StreamFile) write(cells []string, cellTypes []*CellType, cellStyles []int) error {
+func (sf *StreamFile) write(cells []string, cellTypes []*CellType, cellStyles []*StreamStyle) error {
 	if sf.currentSheet == nil {
 		return NoCurrentSheetError
 	}
@@ -104,7 +103,7 @@ func (sf *StreamFile) write(cells []string, cellTypes []*CellType, cellStyles []
 		// Build the XML cell opening
 		cellOpen := `<c r="` + cellCoordinate + `" t="` + cellType + `"`
 		// Add in the style id if the cell isn't using the default style
-		cellOpen += ` s="` + strconv.Itoa(cellStyles[colIndex]) + `"`
+		cellOpen += ` s="` + strconv.Itoa(sf.styleIdMap[cellStyles[colIndex]]) + `"`
 
 		cellOpen += `>`
 

+ 10 - 28
stream_file_builder.go

@@ -39,7 +39,7 @@ type StreamFileBuilder struct {
 	// cellTypeToStyleIds map[CellType]int
 	maxStyleId         int
 	styleIds           [][]int
-	styleIdMap		   map[*Style]int
+	styleIdMap		   map[*StreamStyle]int
 }
 
 const (
@@ -62,7 +62,7 @@ func NewStreamFileBuilder(writer io.Writer) *StreamFileBuilder {
 		xlsxFile:           NewFile(),
 		// cellTypeToStyleIds: make(map[CellType]int),
 		maxStyleId:         initMaxStyleId,
-		styleIdMap:			make(map[*Style]int),
+		styleIdMap:			make(map[*StreamStyle]int),
 	}
 }
 
@@ -79,7 +79,7 @@ func NewStreamFileBuilderForPath(path string) (*StreamFileBuilder, error) {
 // AddSheet 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.
-func (sb *StreamFileBuilder) AddSheet(name string, headers []string, cellStyles []int, cellTypes []*CellType) error {
+func (sb *StreamFileBuilder) AddSheet(name string, headers []string, cellStyles []*StreamStyle, cellTypes []*CellType) error {
 	if sb.built {
 		return BuiltStreamFileBuilderError
 	}
@@ -100,7 +100,7 @@ func (sb *StreamFileBuilder) AddSheet(name string, headers []string, cellStyles
 		return errors.New("failed to write headers")
 	}
 	for i, cellType := range cellTypes {
-		cellStyleIndex := cellStyles[i]
+		cellStyleIndex := sb.styleIdMap[cellStyles[i]]
 		//var ok bool
 		if cellType != nil {
 			// The cell type is one of the attributes of a Style.
@@ -144,6 +144,7 @@ func (sb *StreamFileBuilder) Build() (*StreamFile, error) {
 		sheetXmlPrefix: make([]string, len(sb.xlsxFile.Sheets)),
 		sheetXmlSuffix: make([]string, len(sb.xlsxFile.Sheets)),
 		styleIds:       sb.styleIds,
+		styleIdMap:		sb.styleIdMap,
 	}
 	for path, data := range parts {
 		// If the part is a sheet, don't write it yet. We only want to write the XLSX metadata files, since at this
@@ -173,30 +174,11 @@ func (sb *StreamFileBuilder) Build() (*StreamFile, error) {
 func (sb *StreamFileBuilder) addDefaultStyles(parts map[string]string) (map[string]string, error) {
 	var err error
 
-	// Default style - Bold
-	defaultBold := NewStyle()
-	defaultBold.Font.Bold = true
-	if defaultBold != nil {
-		xNumFmtId := 0 // GENERAL FORMATTING
-		XfId := handleStyleForXLSX(defaultBold, xNumFmtId, sb.xlsxFile.styles)
-		sb.styleIdMap[defaultBold] = XfId
-	}
-
-	// Default style - Italic
-	defaultItalic := NewStyle()
-	defaultItalic.Font.Italic = true
-	if defaultItalic != nil {
-		xNumFmtId := 0 // GENERAL FORMATTING
-		XfId := handleStyleForXLSX(defaultItalic, xNumFmtId, sb.xlsxFile.styles)
-		sb.styleIdMap[defaultItalic] = XfId
-	}
-
-	// Default date
-	defaultDate := NewStyle()
-	if defaultDate != nil {
-		xNumFmtId := 14
-		XfId := handleStyleForXLSX(defaultDate, xNumFmtId, sb.xlsxFile.styles)
-		sb.styleIdMap[defaultDate] = XfId
+	for _,streamStyle := range DefaultStyles{
+		if streamStyle != nil{
+			XfId := handleStyleForXLSX(streamStyle.style, streamStyle.xNumFmtId, sb.xlsxFile.styles)
+			sb.styleIdMap[streamStyle] = XfId
+		}
 	}
 
 	parts["xl/styles.xml"], err = sb.xlsxFile.styles.Marshal()

+ 101 - 0
stream_style.go

@@ -0,0 +1,101 @@
+package xlsx
+
+// StreamStyle has style and formatting information.
+// Used to store a style for streaming
+type StreamStyle struct {
+	xNumFmtId	int
+	style 		*Style
+}
+
+var DefaultStringStyle *StreamStyle
+var DefaultStringBoldStyle *StreamStyle
+var DefaultStringItalicStyle *StreamStyle
+var DefaultStringUnderlinedStyle *StreamStyle
+
+var DefaultNumericStyle *StreamStyle
+var DefaultNumericBoldStyle *StreamStyle
+var DefaultNumericItalicStyle *StreamStyle
+var DefaultNumericUnderlinedStyle *StreamStyle
+
+var DefaultStyles []*StreamStyle
+
+func init(){
+	// default string styles
+	DefaultStringStyle = &StreamStyle{
+		xNumFmtId: 0,
+		style: NewStyle(),
+	}
+	DefaultStringBoldStyle = &StreamStyle{
+		xNumFmtId: 0,
+		style: NewStyle(),
+	}
+	DefaultStringBoldStyle.style.Font.Bold = true
+	DefaultStringItalicStyle = &StreamStyle{
+		xNumFmtId: 0,
+		style: NewStyle(),
+	}
+	DefaultStringItalicStyle.style.Font.Italic = true
+	DefaultStringUnderlinedStyle = &StreamStyle{
+		xNumFmtId: 0,
+		style: NewStyle(),
+	}
+	DefaultStringUnderlinedStyle.style.Font.Underline = true
+
+	DefaultStyles = append(DefaultStyles, DefaultStringStyle)
+	DefaultStyles = append(DefaultStyles, DefaultStringBoldStyle)
+	DefaultStyles = append(DefaultStyles, DefaultStringItalicStyle)
+	DefaultStyles = append(DefaultStyles, DefaultStringUnderlinedStyle)
+
+	// default string styles
+	DefaultNumericStyle = &StreamStyle{
+		xNumFmtId: 1,
+		style: NewStyle(),
+	}
+	DefaultNumericBoldStyle = &StreamStyle{
+		xNumFmtId: 1,
+		style: NewStyle(),
+	}
+	DefaultNumericBoldStyle.style.Font.Bold = true
+	DefaultNumericItalicStyle = &StreamStyle{
+		xNumFmtId: 1,
+		style: NewStyle(),
+	}
+	DefaultNumericItalicStyle.style.Font.Italic = true
+	DefaultNumericUnderlinedStyle = &StreamStyle{
+		xNumFmtId: 1,
+		style: NewStyle(),
+	}
+	DefaultNumericUnderlinedStyle.style.Font.Underline = true
+
+	DefaultStyles = append(DefaultStyles, DefaultNumericStyle)
+	DefaultStyles = append(DefaultStyles, DefaultNumericBoldStyle)
+	DefaultStyles = append(DefaultStyles, DefaultNumericItalicStyle)
+	DefaultStyles = append(DefaultStyles, DefaultNumericUnderlinedStyle)
+
+
+}
+
+// MakeStyle creates a new StreamStyle and add it to the styles that will be streamed
+// This function returns a reference to the created StreamStyle
+func MakeStyle(formatStyleId int, font Font, fill Fill, alignment Alignment, border Border) *StreamStyle {
+	newStyle := NewStyle()
+
+	newStyle.Font = font
+	newStyle.Fill = fill
+	newStyle.Alignment = alignment
+	newStyle.Border = border
+
+	newStyle.ApplyFont = true
+	newStyle.ApplyFill = true
+	newStyle.ApplyAlignment = true
+	newStyle.ApplyBorder = true
+
+	newStreamStyle := &StreamStyle{
+		xNumFmtId: 	formatStyleId,
+		style: 		newStyle,
+	}
+
+	DefaultStyles = append(DefaultStyles, newStreamStyle)
+	return newStreamStyle
+}
+

+ 18 - 18
stream_test.go

@@ -11,7 +11,7 @@ import (
 )
 
 const (
-	TestsShouldMakeRealFiles = false
+	TestsShouldMakeRealFiles = true
 )
 
 type StreamSuite struct{}
@@ -33,7 +33,7 @@ func (s *StreamSuite) TestXlsxStreamWrite(t *C) {
 		testName      string
 		sheetNames    []string
 		workbookData  [][][]string
-		cellStyles    [][][]int
+		cellStyles    [][][]*StreamStyle
 		cellTypes     [][][]*CellType
 		expectedError error
 	}{
@@ -48,10 +48,10 @@ func (s *StreamSuite) TestXlsxStreamWrite(t *C) {
 					{"1234", "98", "34", "26032019"},
 				},
 			},
-			cellStyles: [][][]int{
+			cellStyles: [][][]*StreamStyle{
 				{
-					{0,0,0,0},
-					{0,2,3,0},
+					{DefaultStringStyle,  DefaultStringBoldStyle,  DefaultStringItalicStyle,  DefaultStringUnderlinedStyle},
+					{DefaultNumericStyle, DefaultNumericBoldStyle, DefaultNumericItalicStyle, DefaultNumericUnderlinedStyle},
 				},
 			},
 			cellTypes: [][][]*CellType{
@@ -269,13 +269,13 @@ func (s *StreamSuite) TestXlsxStreamWrite(t *C) {
 		}
 
 		if testCase.cellStyles == nil {
-			testCase.cellStyles = [][][]int{}
+			testCase.cellStyles = [][][]*StreamStyle{}
 			for j,_ := range testCase.workbookData{
-				testCase.cellStyles = append(testCase.cellStyles, [][]int{})
+				testCase.cellStyles = append(testCase.cellStyles, [][]*StreamStyle{})
 				for k,_ := range testCase.workbookData[j]{
-					testCase.cellStyles[j] = append(testCase.cellStyles[j], []int{})
+					testCase.cellStyles[j] = append(testCase.cellStyles[j], []*StreamStyle{})
 					for  _,_ = range testCase.workbookData[j][k]{
-						testCase.cellStyles[j][k] = append(testCase.cellStyles[j][k], 0)
+						testCase.cellStyles[j][k] = append(testCase.cellStyles[j][k], DefaultStringStyle)
 					}
 				}
 			}
@@ -373,7 +373,7 @@ func (s *StreamSuite) TestXlsxStyleBehavior(t *C) {
 }
 
 // writeStreamFile will write the file using this stream package
-func writeStreamFile(filePath string, fileBuffer io.Writer, sheetNames []string, workbookData [][][]string, cellStyles [][][]int, cellTypes [][][]*CellType, shouldMakeRealFiles bool) error {
+func writeStreamFile(filePath string, fileBuffer io.Writer, sheetNames []string, workbookData [][][]string, cellStyles [][][]*StreamStyle, cellTypes [][][]*CellType, shouldMakeRealFiles bool) error {
 	var file *StreamFileBuilder
 	var err error
 	if shouldMakeRealFiles {
@@ -469,11 +469,11 @@ func readXLSXFile(t *C, filePath string, fileBuffer io.ReaderAt, size int64, sho
 func (s *StreamSuite) TestAddSheetErrorsAfterBuild(t *C) {
 	file := NewStreamFileBuilder(bytes.NewBuffer(nil))
 
-	err := file.AddSheet("Sheet1", []string{"Header"}, []int{0}, nil)
+	err := file.AddSheet("Sheet1", []string{"Header"}, []*StreamStyle{DefaultStringStyle}, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheet("Sheet2", []string{"Header2"}, []int{0}, nil)
+	err = file.AddSheet("Sheet2", []string{"Header2"}, []*StreamStyle{DefaultStringStyle}, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -482,7 +482,7 @@ func (s *StreamSuite) TestAddSheetErrorsAfterBuild(t *C) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheet("Sheet3", []string{"Header3"}, []int{0}, nil)
+	err = file.AddSheet("Sheet3", []string{"Header3"}, []*StreamStyle{DefaultStringStyle}, nil)
 	if err != BuiltStreamFileBuilderError {
 		t.Fatal(err)
 	}
@@ -491,11 +491,11 @@ func (s *StreamSuite) TestAddSheetErrorsAfterBuild(t *C) {
 func (s *StreamSuite) TestBuildErrorsAfterBuild(t *C) {
 	file := NewStreamFileBuilder(bytes.NewBuffer(nil))
 
-	err := file.AddSheet("Sheet1", []string{"Header"}, []int{0}, nil)
+	err := file.AddSheet("Sheet1", []string{"Header"}, []*StreamStyle{DefaultStringStyle}, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = file.AddSheet("Sheet2", []string{"Header2"}, []int{0}, nil)
+	err = file.AddSheet("Sheet2", []string{"Header2"}, []*StreamStyle{DefaultStringStyle}, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -519,9 +519,9 @@ func (s *StreamSuite) TestCloseWithNothingWrittenToSheets(t *C) {
 		{{"Header1", "Header2"}},
 		{{"Header3", "Header4"}},
 	}
-	cellStyles := [][][]int{
-		{{0, 0}},
-		{{0, 0}},
+	cellStyles := [][][]*StreamStyle{
+		{{DefaultStringStyle, DefaultStringStyle}},
+		{{DefaultStringStyle, DefaultStringStyle}},
 	}
 	cellTypes := [][][]*CellType{
 		{{CellTypeString.Ptr(), CellTypeString.Ptr()}},

+ 10 - 0
style.go

@@ -2,6 +2,16 @@ package xlsx
 
 import "strconv"
 
+// Several popular font names that can be used to create fonts
+const (
+	Helvetica = "Helvetica"
+	Baskerville = "Baskerville Old Face"
+	TimesNewRoman = "Times New Roman"
+	Bodoni = "Bodoni MT"
+	GillSans = "Gill Sans MT"
+	Courier = "Courier"
+)
+
 // Style is a high level structure intended to provide user access to
 // the contents of Style within an XLSX file.
 type Style struct {