diff --git a/col.go b/col.go index 1e78734e38..781e9a3b09 100644 --- a/col.go +++ b/col.go @@ -390,21 +390,28 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error { if err != nil { return err } + ws, err := f.workSheetReader(sheet) + if err != nil { + return err + } + ws.setColOutlineLevel(colNum, level) + return err +} + +// setColOutlineLevel provides a function to set the outline level of a single +// column by given column number. +func (ws *xlsxWorksheet) setColOutlineLevel(colNum int, level uint8) { colData := xlsxCol{ Min: colNum, Max: colNum, OutlineLevel: level, CustomWidth: true, } - ws, err := f.workSheetReader(sheet) - if err != nil { - return err - } if ws.Cols == nil { cols := xlsxCols{} cols.Col = append(cols.Col, colData) ws.Cols = &cols - return err + return } ws.Cols.Col = flatCols(colData, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol { fc.BestFit = c.BestFit @@ -416,7 +423,6 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error { fc.Width = c.Width return fc }) - return err } // SetColStyle provides a function to set style of columns by given worksheet diff --git a/errors.go b/errors.go index b29f456b94..833f990e6f 100644 --- a/errors.go +++ b/errors.go @@ -136,18 +136,6 @@ var ( // ErrSparklineType defined the error message on receive the invalid // sparkline Type parameters. ErrSparklineType = errors.New("parameter 'Type' value must be one of 'line', 'column' or 'win_loss'") - // ErrStreamSetColVisible defined the error message on set columns - // visibility in stream writing mode. - ErrStreamSetColVisible = errors.New("must call the SetColVisible function before the SetRow function") - // ErrStreamSetColStyle defined the error message on set column style in - // stream writing mode. - ErrStreamSetColStyle = errors.New("must call the SetColStyle function before the SetRow function") - // ErrStreamSetColWidth defined the error message on set column width in - // stream writing mode. - ErrStreamSetColWidth = errors.New("must call the SetColWidth function before the SetRow function") - // ErrStreamSetPanes defined the error message on set panes in stream - // writing mode. - ErrStreamSetPanes = errors.New("must call the SetPanes function before the SetRow function") // ErrTotalSheetHyperlinks defined the error message on hyperlinks count // overflow. ErrTotalSheetHyperlinks = errors.New("over maximum limit hyperlinks in a worksheet") @@ -328,6 +316,12 @@ func newStreamSetRowError(row int) error { return fmt.Errorf("row %d has already been written", row) } +// newStreamSetRowOrderError defined the error message on calling the SetRow +// function before the order function. +func newStreamSetRowOrderError(name string) error { + return fmt.Errorf("must call the %s function before the SetRow function", name) +} + // newUnknownFilterTokenError defined the error message on receiving a unknown // filter operator token. func newUnknownFilterTokenError(token string) error { diff --git a/stream.go b/stream.go index cf07340b78..6f035606a5 100644 --- a/stream.go +++ b/stream.go @@ -448,7 +448,7 @@ func (sw *StreamWriter) SetRow(cell string, values []interface{}, opts ...RowOpt // err := sw.SetColVisible(4, 6, false) func (sw *StreamWriter) SetColVisible(minVal, maxVal int, visible bool) error { if sw.sheetWritten { - return ErrStreamSetColVisible + return newStreamSetRowOrderError("SetColVisible") } if minVal < MinColumns || minVal > MaxColumns || maxVal < MinColumns || maxVal > MaxColumns { return ErrColumnNumber @@ -460,6 +460,25 @@ func (sw *StreamWriter) SetColVisible(minVal, maxVal int, visible bool) error { return nil } +// SetColOutlineLevel provides a function to set outline level of a single +// column for the StreamWriter. The value of parameter 'level' is 1-7. For +// example, set outline level of column D in Sheet1 to 2: +// +// err := sw.SetColOutlineLevel(4, 2) +func (sw *StreamWriter) SetColOutlineLevel(col int, level uint8) error { + if sw.sheetWritten { + return newStreamSetRowOrderError("SetColOutlineLevel") + } + if col < MinColumns || col > MaxColumns { + return ErrColumnNumber + } + if level > 7 || level < 1 { + return ErrOutlineLevel + } + sw.worksheet.setColOutlineLevel(col, level) + return nil +} + // SetColStyle provides a function to set the style of a single column or // multiple columns for the StreamWriter. Note that you must call // the 'SetColStyle' function before the 'SetRow' function. For example set @@ -468,7 +487,7 @@ func (sw *StreamWriter) SetColVisible(minVal, maxVal int, visible bool) error { // err := sw.SetColStyle(8, 8, style) func (sw *StreamWriter) SetColStyle(minVal, maxVal, styleID int) error { if sw.sheetWritten { - return ErrStreamSetColStyle + return newStreamSetRowOrderError("SetColStyle") } if minVal < MinColumns || minVal > MaxColumns || maxVal < MinColumns || maxVal > MaxColumns { return ErrColumnNumber @@ -495,7 +514,7 @@ func (sw *StreamWriter) SetColStyle(minVal, maxVal, styleID int) error { // err := sw.SetColWidth(2, 3, 20) func (sw *StreamWriter) SetColWidth(minVal, maxVal int, width float64) error { if sw.sheetWritten { - return ErrStreamSetColWidth + return newStreamSetRowOrderError("SetColWidth") } if minVal < MinColumns || minVal > MaxColumns || maxVal < MinColumns || maxVal > MaxColumns { return ErrColumnNumber @@ -523,7 +542,7 @@ func (sw *StreamWriter) InsertPageBreak(cell string) error { // the 'SetPanes' function before the 'SetRow' function. func (sw *StreamWriter) SetPanes(panes *Panes) error { if sw.sheetWritten { - return ErrStreamSetPanes + return newStreamSetRowOrderError("SetPanes") } return sw.worksheet.setPanes(panes) } @@ -710,6 +729,11 @@ func (sw *StreamWriter) writeSheetData() { if col.Hidden { sw.rawData.WriteString(` hidden="1"`) } + if col.OutlineLevel > 0 { + sw.rawData.WriteString(` outlineLevel="`) + sw.rawData.WriteString(strconv.FormatUint(uint64(col.OutlineLevel), 10)) + sw.rawData.WriteString(`"`) + } sw.rawData.WriteString(`/>`) } _, _ = sw.rawData.WriteString("") diff --git a/stream_test.go b/stream_test.go index e1b200d630..090f2712ac 100644 --- a/stream_test.go +++ b/stream_test.go @@ -165,7 +165,24 @@ func TestStreamSetColVisible(t *testing.T) { assert.Equal(t, ErrColumnNumber, streamWriter.SetColVisible(0, 3, false)) assert.Equal(t, ErrColumnNumber, streamWriter.SetColVisible(MaxColumns+1, 3, false)) assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"})) - assert.Equal(t, ErrStreamSetColVisible, streamWriter.SetColVisible(2, 3, false)) + assert.Equal(t, newStreamSetRowOrderError("SetColVisible"), streamWriter.SetColVisible(2, 3, false)) + assert.NoError(t, streamWriter.Flush()) +} + +func TestStreamSetColOutlineLevel(t *testing.T) { + file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() + streamWriter, err := file.NewStreamWriter("Sheet1") + assert.NoError(t, err) + assert.NoError(t, streamWriter.SetColOutlineLevel(4, 2)) + assert.Equal(t, ErrOutlineLevel, streamWriter.SetColOutlineLevel(4, 0)) + assert.Equal(t, ErrOutlineLevel, streamWriter.SetColOutlineLevel(4, 8)) + assert.Equal(t, ErrColumnNumber, streamWriter.SetColOutlineLevel(0, 2)) + assert.Equal(t, ErrColumnNumber, streamWriter.SetColOutlineLevel(MaxColumns+1, 2)) + assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"})) + assert.Equal(t, newStreamSetRowOrderError("SetColOutlineLevel"), streamWriter.SetColOutlineLevel(4, 2)) assert.NoError(t, streamWriter.Flush()) } @@ -181,7 +198,7 @@ func TestStreamSetColStyle(t *testing.T) { assert.Equal(t, ErrColumnNumber, streamWriter.SetColStyle(MaxColumns+1, 3, 20)) assert.Equal(t, newInvalidStyleID(2), streamWriter.SetColStyle(1, 3, 2)) assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"})) - assert.Equal(t, ErrStreamSetColStyle, streamWriter.SetColStyle(2, 3, 0)) + assert.Equal(t, newStreamSetRowOrderError("SetColStyle"), streamWriter.SetColStyle(2, 3, 0)) file = NewFile() defer func() { @@ -214,7 +231,7 @@ func TestStreamSetColWidth(t *testing.T) { assert.Equal(t, ErrColumnNumber, streamWriter.SetColWidth(MaxColumns+1, 3, 20)) assert.Equal(t, ErrColumnWidth, streamWriter.SetColWidth(1, 3, MaxColumnWidth+1)) assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"})) - assert.Equal(t, ErrStreamSetColWidth, streamWriter.SetColWidth(2, 3, 20)) + assert.Equal(t, newStreamSetRowOrderError("SetColWidth"), streamWriter.SetColWidth(2, 3, 20)) assert.NoError(t, streamWriter.Flush()) } @@ -238,7 +255,7 @@ func TestStreamSetPanes(t *testing.T) { assert.NoError(t, streamWriter.SetPanes(paneOpts)) assert.Equal(t, ErrParameterInvalid, streamWriter.SetPanes(nil)) assert.NoError(t, streamWriter.SetRow("A1", []interface{}{"A", "B", "C"})) - assert.Equal(t, ErrStreamSetPanes, streamWriter.SetPanes(paneOpts)) + assert.Equal(t, newStreamSetRowOrderError("SetPanes"), streamWriter.SetPanes(paneOpts)) } func TestStreamTable(t *testing.T) {