Sfoglia il codice sorgente

Resolve #492, init support for insert and remove page break

xuri 5 anni fa
parent
commit
1d87da57ec
4 ha cambiato i file con 150 aggiunte e 3 eliminazioni
  1. 1 0
      .travis.yml
  2. 109 0
      sheet.go
  3. 37 0
      sheet_test.go
  4. 3 3
      xmlWorksheet.go

+ 1 - 0
.travis.yml

@@ -8,6 +8,7 @@ go:
   - 1.11.x
   - 1.12.x
   - 1.13.x
+  - 1.14.x
 
 os:
   - linux

+ 109 - 0
sheet.go

@@ -1437,6 +1437,115 @@ func (f *File) UngroupSheets() error {
 	return nil
 }
 
+// InsertPageBreak create a page break to determine where the printed page
+// ends and where begins the next one by given worksheet name and axis, so the
+// content before the page break will be printed on one page and after the
+// page break on another.
+func (f *File) InsertPageBreak(sheet, cell string) (err error) {
+	var ws *xlsxWorksheet
+	var row, col int
+	var rowBrk, colBrk = -1, -1
+	if ws, err = f.workSheetReader(sheet); err != nil {
+		return
+	}
+	if col, row, err = CellNameToCoordinates(cell); err != nil {
+		return
+	}
+	col--
+	row--
+	if col == row && col == 0 {
+		return
+	}
+	if ws.RowBreaks == nil {
+		ws.RowBreaks = &xlsxBreaks{}
+	}
+	if ws.ColBreaks == nil {
+		ws.ColBreaks = &xlsxBreaks{}
+	}
+
+	for idx, brk := range ws.RowBreaks.Brk {
+		if brk.ID == row {
+			rowBrk = idx
+		}
+	}
+	for idx, brk := range ws.ColBreaks.Brk {
+		if brk.ID == col {
+			colBrk = idx
+		}
+	}
+
+	if row != 0 && rowBrk == -1 {
+		ws.RowBreaks.Brk = append(ws.RowBreaks.Brk, &xlsxBrk{
+			ID:  row,
+			Max: 16383,
+			Man: true,
+		})
+		ws.RowBreaks.ManualBreakCount++
+	}
+	if col != 0 && colBrk == -1 {
+		ws.ColBreaks.Brk = append(ws.ColBreaks.Brk, &xlsxBrk{
+			ID:  col,
+			Max: 1048575,
+			Man: true,
+		})
+		ws.ColBreaks.ManualBreakCount++
+	}
+	ws.RowBreaks.Count = len(ws.RowBreaks.Brk)
+	ws.ColBreaks.Count = len(ws.ColBreaks.Brk)
+	return
+}
+
+// RemovePageBreak remove a page break by given worksheet name and axis.
+func (f *File) RemovePageBreak(sheet, cell string) (err error) {
+	var ws *xlsxWorksheet
+	var row, col int
+	if ws, err = f.workSheetReader(sheet); err != nil {
+		return
+	}
+	if col, row, err = CellNameToCoordinates(cell); err != nil {
+		return
+	}
+	col--
+	row--
+	if col == row && col == 0 {
+		return
+	}
+	removeBrk := func(ID int, brks []*xlsxBrk) []*xlsxBrk {
+		for i, brk := range brks {
+			if brk.ID == ID {
+				brks = append(brks[:i], brks[i+1:]...)
+			}
+		}
+		return brks
+	}
+	if ws.RowBreaks == nil || ws.ColBreaks == nil {
+		return
+	}
+	rowBrks := len(ws.RowBreaks.Brk)
+	colBrks := len(ws.ColBreaks.Brk)
+	if rowBrks > 0 && rowBrks == colBrks {
+		ws.RowBreaks.Brk = removeBrk(row, ws.RowBreaks.Brk)
+		ws.ColBreaks.Brk = removeBrk(col, ws.ColBreaks.Brk)
+		ws.RowBreaks.Count = len(ws.RowBreaks.Brk)
+		ws.ColBreaks.Count = len(ws.ColBreaks.Brk)
+		ws.RowBreaks.ManualBreakCount--
+		ws.ColBreaks.ManualBreakCount--
+		return
+	}
+	if rowBrks > 0 && rowBrks > colBrks {
+		ws.RowBreaks.Brk = removeBrk(row, ws.RowBreaks.Brk)
+		ws.RowBreaks.Count = len(ws.RowBreaks.Brk)
+		ws.RowBreaks.ManualBreakCount--
+		return
+	}
+	if colBrks > 0 && colBrks > rowBrks {
+		ws.ColBreaks.Brk = removeBrk(col, ws.ColBreaks.Brk)
+		ws.ColBreaks.Count = len(ws.ColBreaks.Brk)
+		ws.ColBreaks.ManualBreakCount--
+	}
+	return
+}
+
 // relsReader provides a function to get the pointer to the structure
 // after deserialization of xl/worksheets/_rels/sheet%d.xml.rels.
 func (f *File) relsReader(path string) *xlsxRelationships {

+ 37 - 0
sheet_test.go

@@ -264,6 +264,43 @@ func TestUngroupSheets(t *testing.T) {
 	assert.NoError(t, f.UngroupSheets())
 }
 
+func TestInsertPageBreak(t *testing.T) {
+	f := excelize.NewFile()
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "A1"))
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "B2"))
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
+	assert.EqualError(t, f.InsertPageBreak("Sheet1", "A"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
+	assert.EqualError(t, f.InsertPageBreak("SheetN", "C3"), "sheet SheetN is not exist")
+	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertPageBreak.xlsx")))
+}
+
+func TestRemovePageBreak(t *testing.T) {
+	f := excelize.NewFile()
+	assert.NoError(t, f.RemovePageBreak("Sheet1", "A2"))
+
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "A2"))
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "B2"))
+	assert.NoError(t, f.RemovePageBreak("Sheet1", "A1"))
+	assert.NoError(t, f.RemovePageBreak("Sheet1", "B2"))
+
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "C3"))
+	assert.NoError(t, f.RemovePageBreak("Sheet1", "C3"))
+
+	assert.NoError(t, f.InsertPageBreak("Sheet1", "A3"))
+	assert.NoError(t, f.RemovePageBreak("Sheet1", "B3"))
+	assert.NoError(t, f.RemovePageBreak("Sheet1", "A3"))
+
+	f.NewSheet("Sheet2")
+	assert.NoError(t, f.InsertPageBreak("Sheet2", "B2"))
+	assert.NoError(t, f.InsertPageBreak("Sheet2", "C2"))
+	assert.NoError(t, f.RemovePageBreak("Sheet2", "B2"))
+
+	assert.EqualError(t, f.RemovePageBreak("Sheet1", "A"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
+	assert.EqualError(t, f.RemovePageBreak("SheetN", "C3"), "sheet SheetN is not exist")
+	assert.NoError(t, f.SaveAs(filepath.Join("test", "TestRemovePageBreak.xlsx")))
+}
+
 func TestGetSheetName(t *testing.T) {
 	f, _ := excelize.OpenFile(filepath.Join("test", "Book1.xlsx"))
 	assert.Equal(t, "Sheet1", f.GetSheetName(1))

+ 3 - 3
xmlWorksheet.go

@@ -357,9 +357,9 @@ type xlsxBrk struct {
 
 // xlsxBreaks directly maps a collection of the row or column breaks.
 type xlsxBreaks struct {
-	Brk              *xlsxBrk `xml:"brk"`
-	Count            int      `xml:"count,attr,omitempty"`
-	ManualBreakCount int      `xml:"manualBreakCount,attr,omitempty"`
+	Brk              []*xlsxBrk `xml:"brk"`
+	Count            int        `xml:"count,attr,omitempty"`
+	ManualBreakCount int        `xml:"manualBreakCount,attr,omitempty"`
 }
 
 // xlsxCustomSheetView directly maps the customSheetView element.