forked from p30928647/excelize
Fix #724, standardize variable naming and update unit tests
This commit is contained in:
parent
5dd0b4aec2
commit
2514bb16c6
|
@ -13,6 +13,7 @@ go:
|
|||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
|
||||
env:
|
||||
jobs:
|
||||
|
|
|
@ -51,7 +51,7 @@ func main() {
|
|||
f.SetCellValue("Sheet1", "B2", 100)
|
||||
// Set active sheet of the workbook.
|
||||
f.SetActiveSheet(index)
|
||||
// Save xlsx file by the given path.
|
||||
// Save spreadsheet by the given path.
|
||||
if err := f.SaveAs("Book1.xlsx"); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func main() {
|
|||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
// Save xlsx file by the given path.
|
||||
// Save spreadsheet by the given path.
|
||||
if err := f.SaveAs("Book1.xlsx"); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ func main() {
|
|||
if err := f.AddPicture("Sheet1", "H2", "image.gif", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Save the xlsx file with the origin path.
|
||||
// Save the spreadsheet with the origin path.
|
||||
if err = f.Save(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
|
95
adjust.go
95
adjust.go
|
@ -35,30 +35,30 @@ const (
|
|||
// TODO: adjustPageBreaks, adjustComments, adjustDataValidations, adjustProtectedCells
|
||||
//
|
||||
func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dir == rows {
|
||||
f.adjustRowDimensions(xlsx, num, offset)
|
||||
f.adjustRowDimensions(ws, num, offset)
|
||||
} else {
|
||||
f.adjustColDimensions(xlsx, num, offset)
|
||||
f.adjustColDimensions(ws, num, offset)
|
||||
}
|
||||
f.adjustHyperlinks(xlsx, sheet, dir, num, offset)
|
||||
if err = f.adjustMergeCells(xlsx, dir, num, offset); err != nil {
|
||||
f.adjustHyperlinks(ws, sheet, dir, num, offset)
|
||||
if err = f.adjustMergeCells(ws, dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = f.adjustAutoFilter(xlsx, dir, num, offset); err != nil {
|
||||
if err = f.adjustAutoFilter(ws, dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = f.adjustCalcChain(dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
checkSheet(xlsx)
|
||||
_ = checkRow(xlsx)
|
||||
checkSheet(ws)
|
||||
_ = checkRow(ws)
|
||||
|
||||
if xlsx.MergeCells != nil && len(xlsx.MergeCells.Cells) == 0 {
|
||||
xlsx.MergeCells = nil
|
||||
if ws.MergeCells != nil && len(ws.MergeCells.Cells) == 0 {
|
||||
ws.MergeCells = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -66,13 +66,13 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
|
|||
|
||||
// adjustColDimensions provides a function to update column dimensions when
|
||||
// inserting or deleting rows or columns.
|
||||
func (f *File) adjustColDimensions(xlsx *xlsxWorksheet, col, offset int) {
|
||||
for rowIdx := range xlsx.SheetData.Row {
|
||||
for colIdx, v := range xlsx.SheetData.Row[rowIdx].C {
|
||||
func (f *File) adjustColDimensions(ws *xlsxWorksheet, col, offset int) {
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
for colIdx, v := range ws.SheetData.Row[rowIdx].C {
|
||||
cellCol, cellRow, _ := CellNameToCoordinates(v.R)
|
||||
if col <= cellCol {
|
||||
if newCol := cellCol + offset; newCol > 0 {
|
||||
xlsx.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
|
||||
ws.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,9 @@ func (f *File) adjustColDimensions(xlsx *xlsxWorksheet, col, offset int) {
|
|||
|
||||
// adjustRowDimensions provides a function to update row dimensions when
|
||||
// inserting or deleting rows or columns.
|
||||
func (f *File) adjustRowDimensions(xlsx *xlsxWorksheet, row, offset int) {
|
||||
for i := range xlsx.SheetData.Row {
|
||||
r := &xlsx.SheetData.Row[i]
|
||||
func (f *File) adjustRowDimensions(ws *xlsxWorksheet, row, offset int) {
|
||||
for i := range ws.SheetData.Row {
|
||||
r := &ws.SheetData.Row[i]
|
||||
if newRow := r.R + offset; r.R >= row && newRow > 0 {
|
||||
f.ajustSingleRowDimensions(r, newRow)
|
||||
}
|
||||
|
@ -101,38 +101,35 @@ func (f *File) ajustSingleRowDimensions(r *xlsxRow, num int) {
|
|||
|
||||
// adjustHyperlinks provides a function to update hyperlinks when inserting or
|
||||
// deleting rows or columns.
|
||||
func (f *File) adjustHyperlinks(xlsx *xlsxWorksheet, sheet string, dir adjustDirection, num, offset int) {
|
||||
func (f *File) adjustHyperlinks(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset int) {
|
||||
// short path
|
||||
if xlsx.Hyperlinks == nil || len(xlsx.Hyperlinks.Hyperlink) == 0 {
|
||||
if ws.Hyperlinks == nil || len(ws.Hyperlinks.Hyperlink) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// order is important
|
||||
if offset < 0 {
|
||||
for i := len(xlsx.Hyperlinks.Hyperlink) - 1; i >= 0; i-- {
|
||||
linkData := xlsx.Hyperlinks.Hyperlink[i]
|
||||
for i := len(ws.Hyperlinks.Hyperlink) - 1; i >= 0; i-- {
|
||||
linkData := ws.Hyperlinks.Hyperlink[i]
|
||||
colNum, rowNum, _ := CellNameToCoordinates(linkData.Ref)
|
||||
|
||||
if (dir == rows && num == rowNum) || (dir == columns && num == colNum) {
|
||||
f.deleteSheetRelationships(sheet, linkData.RID)
|
||||
if len(xlsx.Hyperlinks.Hyperlink) > 1 {
|
||||
xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink[:i],
|
||||
xlsx.Hyperlinks.Hyperlink[i+1:]...)
|
||||
if len(ws.Hyperlinks.Hyperlink) > 1 {
|
||||
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink[:i],
|
||||
ws.Hyperlinks.Hyperlink[i+1:]...)
|
||||
} else {
|
||||
xlsx.Hyperlinks = nil
|
||||
ws.Hyperlinks = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if xlsx.Hyperlinks == nil {
|
||||
if ws.Hyperlinks == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := range xlsx.Hyperlinks.Hyperlink {
|
||||
link := &xlsx.Hyperlinks.Hyperlink[i] // get reference
|
||||
for i := range ws.Hyperlinks.Hyperlink {
|
||||
link := &ws.Hyperlinks.Hyperlink[i] // get reference
|
||||
colNum, rowNum, _ := CellNameToCoordinates(link.Ref)
|
||||
|
||||
if dir == rows {
|
||||
if rowNum >= num {
|
||||
link.Ref, _ = CoordinatesToCellName(colNum, rowNum+offset)
|
||||
|
@ -147,21 +144,21 @@ func (f *File) adjustHyperlinks(xlsx *xlsxWorksheet, sheet string, dir adjustDir
|
|||
|
||||
// adjustAutoFilter provides a function to update the auto filter when
|
||||
// inserting or deleting rows or columns.
|
||||
func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) error {
|
||||
if xlsx.AutoFilter == nil {
|
||||
func (f *File) adjustAutoFilter(ws *xlsxWorksheet, dir adjustDirection, num, offset int) error {
|
||||
if ws.AutoFilter == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
coordinates, err := f.areaRefToCoordinates(xlsx.AutoFilter.Ref)
|
||||
coordinates, err := f.areaRefToCoordinates(ws.AutoFilter.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
|
||||
|
||||
if (dir == rows && y1 == num && offset < 0) || (dir == columns && x1 == num && x2 == num) {
|
||||
xlsx.AutoFilter = nil
|
||||
for rowIdx := range xlsx.SheetData.Row {
|
||||
rowData := &xlsx.SheetData.Row[rowIdx]
|
||||
ws.AutoFilter = nil
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
rowData := &ws.SheetData.Row[rowIdx]
|
||||
if rowData.R > y1 && rowData.R <= y2 {
|
||||
rowData.Hidden = false
|
||||
}
|
||||
|
@ -172,7 +169,7 @@ func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, o
|
|||
coordinates = f.adjustAutoFilterHelper(dir, coordinates, num, offset)
|
||||
x1, y1, x2, y2 = coordinates[0], coordinates[1], coordinates[2], coordinates[3]
|
||||
|
||||
if xlsx.AutoFilter.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
|
||||
if ws.AutoFilter.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -251,13 +248,13 @@ func (f *File) coordinatesToAreaRef(coordinates []int) (string, error) {
|
|||
|
||||
// adjustMergeCells provides a function to update merged cells when inserting
|
||||
// or deleting rows or columns.
|
||||
func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) error {
|
||||
if xlsx.MergeCells == nil {
|
||||
func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, offset int) error {
|
||||
if ws.MergeCells == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
|
||||
areaData := xlsx.MergeCells.Cells[i]
|
||||
for i := 0; i < len(ws.MergeCells.Cells); i++ {
|
||||
areaData := ws.MergeCells.Cells[i]
|
||||
coordinates, err := f.areaRefToCoordinates(areaData.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -265,21 +262,21 @@ func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, o
|
|||
x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
|
||||
if dir == rows {
|
||||
if y1 == num && y2 == num && offset < 0 {
|
||||
f.deleteMergeCell(xlsx, i)
|
||||
f.deleteMergeCell(ws, i)
|
||||
i--
|
||||
}
|
||||
y1 = f.adjustMergeCellsHelper(y1, num, offset)
|
||||
y2 = f.adjustMergeCellsHelper(y2, num, offset)
|
||||
} else {
|
||||
if x1 == num && x2 == num && offset < 0 {
|
||||
f.deleteMergeCell(xlsx, i)
|
||||
f.deleteMergeCell(ws, i)
|
||||
i--
|
||||
}
|
||||
x1 = f.adjustMergeCellsHelper(x1, num, offset)
|
||||
x2 = f.adjustMergeCellsHelper(x2, num, offset)
|
||||
}
|
||||
if x1 == x2 && y1 == y2 {
|
||||
f.deleteMergeCell(xlsx, i)
|
||||
f.deleteMergeCell(ws, i)
|
||||
i--
|
||||
}
|
||||
if areaData.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil {
|
||||
|
@ -304,10 +301,10 @@ func (f *File) adjustMergeCellsHelper(pivot, num, offset int) int {
|
|||
}
|
||||
|
||||
// deleteMergeCell provides a function to delete merged cell by given index.
|
||||
func (f *File) deleteMergeCell(sheet *xlsxWorksheet, idx int) {
|
||||
if len(sheet.MergeCells.Cells) > idx {
|
||||
sheet.MergeCells.Cells = append(sheet.MergeCells.Cells[:idx], sheet.MergeCells.Cells[idx+1:]...)
|
||||
sheet.MergeCells.Count = len(sheet.MergeCells.Cells)
|
||||
func (f *File) deleteMergeCell(ws *xlsxWorksheet, idx int) {
|
||||
if len(ws.MergeCells.Cells) > idx {
|
||||
ws.MergeCells.Cells = append(ws.MergeCells.Cells[:idx], ws.MergeCells.Cells[idx+1:]...)
|
||||
ws.MergeCells.Count = len(ws.MergeCells.Cells)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
calc_test.go
13
calc_test.go
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/xuri/efp"
|
||||
)
|
||||
|
||||
func TestCalcCellValue(t *testing.T) {
|
||||
|
@ -854,6 +855,18 @@ func TestCalcCellValue(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func TestCalculate(t *testing.T) {
|
||||
err := `strconv.ParseFloat: parsing "string": invalid syntax`
|
||||
opd := NewStack()
|
||||
opd.Push(efp.Token{TValue: "string"})
|
||||
opt := efp.Token{TValue: "-", TType: efp.TokenTypeOperatorPrefix}
|
||||
assert.EqualError(t, calculate(opd, opt), err)
|
||||
opd.Push(efp.Token{TValue: "string"})
|
||||
opd.Push(efp.Token{TValue: "string"})
|
||||
opt = efp.Token{TValue: "-", TType: efp.TokenTypeOperatorInfix}
|
||||
assert.EqualError(t, calculate(opd, opt), err)
|
||||
}
|
||||
|
||||
func TestCalcCellValueWithDefinedName(t *testing.T) {
|
||||
cellData := [][]interface{}{
|
||||
{"A1 value", "B1 value", nil},
|
||||
|
|
112
cell.go
112
cell.go
|
@ -131,15 +131,15 @@ func (f *File) setCellIntFunc(sheet, axis string, value interface{}) error {
|
|||
// setCellTimeFunc provides a method to process time type of value for
|
||||
// SetCellValue.
|
||||
func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
|
||||
var isNum bool
|
||||
cellData.T, cellData.V, isNum, err = setCellTime(value)
|
||||
|
@ -178,15 +178,15 @@ func setCellDuration(value time.Duration) (t string, v string) {
|
|||
// SetCellInt provides a function to set int type value of a cell by given
|
||||
// worksheet name, cell coordinates and cell value.
|
||||
func (f *File) SetCellInt(sheet, axis string, value int) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellInt(value)
|
||||
return err
|
||||
}
|
||||
|
@ -199,15 +199,15 @@ func setCellInt(value int) (t string, v string) {
|
|||
// SetCellBool provides a function to set bool type value of a cell by given
|
||||
// worksheet name, cell name and cell value.
|
||||
func (f *File) SetCellBool(sheet, axis string, value bool) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellBool(value)
|
||||
return err
|
||||
}
|
||||
|
@ -232,15 +232,15 @@ func setCellBool(value bool) (t string, v string) {
|
|||
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
|
||||
//
|
||||
func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
|
||||
return err
|
||||
}
|
||||
|
@ -253,15 +253,15 @@ func setCellFloat(value float64, prec, bitSize int) (t string, v string) {
|
|||
// SetCellStr provides a function to set string type value of a cell. Total
|
||||
// number of characters that a cell can contain 32767 characters.
|
||||
func (f *File) SetCellStr(sheet, axis, value string) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = f.setCellString(value)
|
||||
return err
|
||||
}
|
||||
|
@ -321,15 +321,15 @@ func setCellStr(value string) (t string, v string, ns xml.Attr) {
|
|||
// SetCellDefault provides a function to set string type value of a cell as
|
||||
// default format without escaping the cell.
|
||||
func (f *File) SetCellDefault(sheet, axis, value string) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellDefault(value)
|
||||
return err
|
||||
}
|
||||
|
@ -362,11 +362,11 @@ type FormulaOpts struct {
|
|||
// SetCellFormula provides a function to set cell formula by given string and
|
||||
// worksheet name.
|
||||
func (f *File) SetCellFormula(sheet, axis, formula string, opts ...FormulaOpts) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, _, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, _, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -409,16 +409,16 @@ func (f *File) GetCellHyperLink(sheet, axis string) (bool, string, error) {
|
|||
return false, "", err
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
axis, err = f.mergeCellsParser(xlsx, axis)
|
||||
axis, err = f.mergeCellsParser(ws, axis)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
if xlsx.Hyperlinks != nil {
|
||||
for _, link := range xlsx.Hyperlinks.Hyperlink {
|
||||
if ws.Hyperlinks != nil {
|
||||
for _, link := range ws.Hyperlinks.Hyperlink {
|
||||
if link.Ref == axis {
|
||||
if link.RID != "" {
|
||||
return true, f.getSheetRelationshipsTargetByID(sheet, link.RID), err
|
||||
|
@ -451,22 +451,22 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
axis, err = f.mergeCellsParser(xlsx, axis)
|
||||
axis, err = f.mergeCellsParser(ws, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var linkData xlsxHyperlink
|
||||
|
||||
if xlsx.Hyperlinks == nil {
|
||||
xlsx.Hyperlinks = new(xlsxHyperlinks)
|
||||
if ws.Hyperlinks == nil {
|
||||
ws.Hyperlinks = new(xlsxHyperlinks)
|
||||
}
|
||||
|
||||
if len(xlsx.Hyperlinks.Hyperlink) > TotalSheetHyperlinks {
|
||||
if len(ws.Hyperlinks.Hyperlink) > TotalSheetHyperlinks {
|
||||
return errors.New("over maximum limit hyperlinks in a worksheet")
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error {
|
|||
return fmt.Errorf("invalid link type %q", linkType)
|
||||
}
|
||||
|
||||
xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink, linkData)
|
||||
ws.Hyperlinks.Hyperlink = append(ws.Hyperlinks.Hyperlink, linkData)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -685,11 +685,11 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
|
|||
}
|
||||
|
||||
// getCellInfo does common preparation for all SetCell* methods.
|
||||
func (f *File) prepareCell(xlsx *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int, error) {
|
||||
xlsx.Lock()
|
||||
defer xlsx.Unlock()
|
||||
func (f *File) prepareCell(ws *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int, error) {
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
var err error
|
||||
cell, err = f.mergeCellsParser(xlsx, cell)
|
||||
cell, err = f.mergeCellsParser(ws, cell)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
@ -698,19 +698,19 @@ func (f *File) prepareCell(xlsx *xlsxWorksheet, sheet, cell string) (*xlsxC, int
|
|||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
prepareSheetXML(xlsx, col, row)
|
||||
prepareSheetXML(ws, col, row)
|
||||
|
||||
return &xlsx.SheetData.Row[row-1].C[col-1], col, row, err
|
||||
return &ws.SheetData.Row[row-1].C[col-1], col, row, err
|
||||
}
|
||||
|
||||
// getCellStringFunc does common value extraction workflow for all GetCell*
|
||||
// methods. Passed function implements specific part of required logic.
|
||||
func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c *xlsxC) (string, bool, error)) (string, error) {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
axis, err = f.mergeCellsParser(xlsx, axis)
|
||||
axis, err = f.mergeCellsParser(ws, axis)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -719,12 +719,12 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
|
|||
return "", err
|
||||
}
|
||||
|
||||
xlsx.Lock()
|
||||
defer xlsx.Unlock()
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
|
||||
lastRowNum := 0
|
||||
if l := len(xlsx.SheetData.Row); l > 0 {
|
||||
lastRowNum = xlsx.SheetData.Row[l-1].R
|
||||
if l := len(ws.SheetData.Row); l > 0 {
|
||||
lastRowNum = ws.SheetData.Row[l-1].R
|
||||
}
|
||||
|
||||
// keep in mind: row starts from 1
|
||||
|
@ -732,8 +732,8 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
|
|||
return "", nil
|
||||
}
|
||||
|
||||
for rowIdx := range xlsx.SheetData.Row {
|
||||
rowData := &xlsx.SheetData.Row[rowIdx]
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
rowData := &ws.SheetData.Row[rowIdx]
|
||||
if rowData.R != row {
|
||||
continue
|
||||
}
|
||||
|
@ -742,7 +742,7 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
|
|||
if axis != colData.R {
|
||||
continue
|
||||
}
|
||||
val, ok, err := fn(xlsx, colData)
|
||||
val, ok, err := fn(ws, colData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -776,7 +776,7 @@ func (f *File) formattedValue(s int, v string) string {
|
|||
for _, xlsxFmt := range styleSheet.NumFmts.NumFmt {
|
||||
if xlsxFmt.NumFmtID == numFmtId {
|
||||
format := strings.ToLower(xlsxFmt.FormatCode)
|
||||
if strings.Contains(format, "y") || strings.Contains(format, "m") || strings.Contains(format, "d") || strings.Contains(format, "h") {
|
||||
if strings.Contains(format, "y") || strings.Contains(format, "m") || strings.Contains(strings.Replace(format, "red", "", -1), "d") || strings.Contains(format, "h") {
|
||||
return parseTime(v, format)
|
||||
}
|
||||
|
||||
|
@ -788,9 +788,9 @@ func (f *File) formattedValue(s int, v string) string {
|
|||
|
||||
// prepareCellStyle provides a function to prepare style index of cell in
|
||||
// worksheet by given column index and style index.
|
||||
func (f *File) prepareCellStyle(xlsx *xlsxWorksheet, col, style int) int {
|
||||
if xlsx.Cols != nil && style == 0 {
|
||||
for _, c := range xlsx.Cols.Col {
|
||||
func (f *File) prepareCellStyle(ws *xlsxWorksheet, col, style int) int {
|
||||
if ws.Cols != nil && style == 0 {
|
||||
for _, c := range ws.Cols.Col {
|
||||
if c.Min <= col && col <= c.Max {
|
||||
style = c.Style
|
||||
}
|
||||
|
@ -801,16 +801,16 @@ func (f *File) prepareCellStyle(xlsx *xlsxWorksheet, col, style int) int {
|
|||
|
||||
// mergeCellsParser provides a function to check merged cells in worksheet by
|
||||
// given axis.
|
||||
func (f *File) mergeCellsParser(xlsx *xlsxWorksheet, axis string) (string, error) {
|
||||
func (f *File) mergeCellsParser(ws *xlsxWorksheet, axis string) (string, error) {
|
||||
axis = strings.ToUpper(axis)
|
||||
if xlsx.MergeCells != nil {
|
||||
for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
|
||||
ok, err := f.checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref)
|
||||
if ws.MergeCells != nil {
|
||||
for i := 0; i < len(ws.MergeCells.Cells); i++ {
|
||||
ok, err := f.checkCellInArea(axis, ws.MergeCells.Cells[i].Ref)
|
||||
if err != nil {
|
||||
return axis, err
|
||||
}
|
||||
if ok {
|
||||
axis = strings.Split(xlsx.MergeCells.Cells[i].Ref, ":")[0]
|
||||
axis = strings.Split(ws.MergeCells.Cells[i].Ref, ":")[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -863,8 +863,8 @@ func isOverlap(rect1, rect2 []int) bool {
|
|||
//
|
||||
// Note that this function not validate ref tag to check the cell if or not in
|
||||
// allow area, and always return origin shared formula.
|
||||
func getSharedForumula(xlsx *xlsxWorksheet, si string) string {
|
||||
for _, r := range xlsx.SheetData.Row {
|
||||
func getSharedForumula(ws *xlsxWorksheet, si string) string {
|
||||
for _, r := range ws.SheetData.Row {
|
||||
for _, c := range r.C {
|
||||
if c.F != nil && c.F.Ref != "" && c.F.T == STCellFormulaTypeShared && c.F.Si == si {
|
||||
return c.F.Content
|
||||
|
|
8
chart.go
8
chart.go
|
@ -527,7 +527,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
|
|||
// fmt.Println(err)
|
||||
// return
|
||||
// }
|
||||
// // Save xlsx file by the given path.
|
||||
// // Save spreadsheet by the given path.
|
||||
// if err := f.SaveAs("Book1.xlsx"); err != nil {
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
|
@ -725,7 +725,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
|
|||
// fmt.Println(err)
|
||||
// return
|
||||
// }
|
||||
// // Save xlsx file by the given path.
|
||||
// // Save spreadsheet file by the given path.
|
||||
// if err := f.SaveAs("Book1.xlsx"); err != nil {
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
|
@ -733,7 +733,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
|
|||
//
|
||||
func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
||||
// Read sheet data.
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -745,7 +745,7 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error {
|
|||
drawingID := f.countDrawings() + 1
|
||||
chartID := f.countCharts() + 1
|
||||
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
|
||||
drawingID, drawingXML = f.prepareDrawing(xlsx, drawingID, sheet, drawingXML)
|
||||
drawingID, drawingXML = f.prepareDrawing(ws, drawingID, sheet, drawingXML)
|
||||
drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels"
|
||||
drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "")
|
||||
err = f.addDrawingChart(sheet, drawingXML, cell, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format)
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
)
|
||||
|
||||
func TestChartSize(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
sheet1 := xlsx.GetSheetName(0)
|
||||
f := NewFile()
|
||||
sheet1 := f.GetSheetName(0)
|
||||
|
||||
categories := map[string]string{
|
||||
"A2": "Small",
|
||||
|
@ -23,7 +23,7 @@ func TestChartSize(t *testing.T) {
|
|||
"D1": "Pear",
|
||||
}
|
||||
for cell, v := range categories {
|
||||
assert.NoError(t, xlsx.SetCellValue(sheet1, cell, v))
|
||||
assert.NoError(t, f.SetCellValue(sheet1, cell, v))
|
||||
}
|
||||
|
||||
values := map[string]int{
|
||||
|
@ -38,10 +38,10 @@ func TestChartSize(t *testing.T) {
|
|||
"D4": 8,
|
||||
}
|
||||
for cell, v := range values {
|
||||
assert.NoError(t, xlsx.SetCellValue(sheet1, cell, v))
|
||||
assert.NoError(t, f.SetCellValue(sheet1, cell, v))
|
||||
}
|
||||
|
||||
assert.NoError(t, xlsx.AddChart("Sheet1", "E4", `{"type":"col3DClustered","dimension":{"width":640, "height":480},`+
|
||||
assert.NoError(t, f.AddChart("Sheet1", "E4", `{"type":"col3DClustered","dimension":{"width":640, "height":480},`+
|
||||
`"series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},`+
|
||||
`{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},`+
|
||||
`{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],`+
|
||||
|
@ -49,8 +49,8 @@ func TestChartSize(t *testing.T) {
|
|||
|
||||
var buffer bytes.Buffer
|
||||
|
||||
// Save xlsx file by the given path.
|
||||
assert.NoError(t, xlsx.Write(&buffer))
|
||||
// Save spreadsheet by the given path.
|
||||
assert.NoError(t, f.Write(&buffer))
|
||||
|
||||
newFile, err := OpenReader(&buffer)
|
||||
assert.NoError(t, err)
|
||||
|
@ -256,8 +256,8 @@ func TestDeleteChart(t *testing.T) {
|
|||
|
||||
func TestChartWithLogarithmicBase(t *testing.T) {
|
||||
// Create test XLSX file with data
|
||||
xlsx := NewFile()
|
||||
sheet1 := xlsx.GetSheetName(0)
|
||||
f := NewFile()
|
||||
sheet1 := f.GetSheetName(0)
|
||||
categories := map[string]float64{
|
||||
"A1": 1,
|
||||
"A2": 2,
|
||||
|
@ -281,46 +281,46 @@ func TestChartWithLogarithmicBase(t *testing.T) {
|
|||
"B10": 5000,
|
||||
}
|
||||
for cell, v := range categories {
|
||||
assert.NoError(t, xlsx.SetCellValue(sheet1, cell, v))
|
||||
assert.NoError(t, f.SetCellValue(sheet1, cell, v))
|
||||
}
|
||||
|
||||
// Add two chart, one without and one with log scaling
|
||||
assert.NoError(t, xlsx.AddChart(sheet1, "C1",
|
||||
assert.NoError(t, f.AddChart(sheet1, "C1",
|
||||
`{"type":"line","dimension":{"width":640, "height":480},`+
|
||||
`"series":[{"name":"value","categories":"Sheet1!$A$1:$A$19","values":"Sheet1!$B$1:$B$10"}],`+
|
||||
`"title":{"name":"Line chart without log scaling"}}`))
|
||||
assert.NoError(t, xlsx.AddChart(sheet1, "M1",
|
||||
assert.NoError(t, f.AddChart(sheet1, "M1",
|
||||
`{"type":"line","dimension":{"width":640, "height":480},`+
|
||||
`"series":[{"name":"value","categories":"Sheet1!$A$1:$A$19","values":"Sheet1!$B$1:$B$10"}],`+
|
||||
`"y_axis":{"logbase":10.5},`+
|
||||
`"title":{"name":"Line chart with log 10 scaling"}}`))
|
||||
assert.NoError(t, xlsx.AddChart(sheet1, "A25",
|
||||
assert.NoError(t, f.AddChart(sheet1, "A25",
|
||||
`{"type":"line","dimension":{"width":320, "height":240},`+
|
||||
`"series":[{"name":"value","categories":"Sheet1!$A$1:$A$19","values":"Sheet1!$B$1:$B$10"}],`+
|
||||
`"y_axis":{"logbase":1.9},`+
|
||||
`"title":{"name":"Line chart with log 1.9 scaling"}}`))
|
||||
assert.NoError(t, xlsx.AddChart(sheet1, "F25",
|
||||
assert.NoError(t, f.AddChart(sheet1, "F25",
|
||||
`{"type":"line","dimension":{"width":320, "height":240},`+
|
||||
`"series":[{"name":"value","categories":"Sheet1!$A$1:$A$19","values":"Sheet1!$B$1:$B$10"}],`+
|
||||
`"y_axis":{"logbase":2},`+
|
||||
`"title":{"name":"Line chart with log 2 scaling"}}`))
|
||||
assert.NoError(t, xlsx.AddChart(sheet1, "K25",
|
||||
assert.NoError(t, f.AddChart(sheet1, "K25",
|
||||
`{"type":"line","dimension":{"width":320, "height":240},`+
|
||||
`"series":[{"name":"value","categories":"Sheet1!$A$1:$A$19","values":"Sheet1!$B$1:$B$10"}],`+
|
||||
`"y_axis":{"logbase":1000.1},`+
|
||||
`"title":{"name":"Line chart with log 1000.1 scaling"}}`))
|
||||
assert.NoError(t, xlsx.AddChart(sheet1, "P25",
|
||||
assert.NoError(t, f.AddChart(sheet1, "P25",
|
||||
`{"type":"line","dimension":{"width":320, "height":240},`+
|
||||
`"series":[{"name":"value","categories":"Sheet1!$A$1:$A$19","values":"Sheet1!$B$1:$B$10"}],`+
|
||||
`"y_axis":{"logbase":1000},`+
|
||||
`"title":{"name":"Line chart with log 1000 scaling"}}`))
|
||||
|
||||
// Export XLSX file for human confirmation
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestChartWithLogarithmicBase10.xlsx")))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestChartWithLogarithmicBase10.xlsx")))
|
||||
|
||||
// Write the XLSX file to a buffer
|
||||
var buffer bytes.Buffer
|
||||
assert.NoError(t, xlsx.Write(&buffer))
|
||||
assert.NoError(t, f.Write(&buffer))
|
||||
|
||||
// Read back the XLSX file from the buffer
|
||||
newFile, err := OpenReader(&buffer)
|
||||
|
|
62
col.go
62
col.go
|
@ -224,16 +224,16 @@ func (f *File) GetColVisible(sheet, col string) (bool, error) {
|
|||
return visible, err
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if xlsx.Cols == nil {
|
||||
if ws.Cols == nil {
|
||||
return visible, err
|
||||
}
|
||||
|
||||
for c := range xlsx.Cols.Col {
|
||||
colData := &xlsx.Cols.Col[c]
|
||||
for c := range ws.Cols.Col {
|
||||
colData := &ws.Cols.Col[c]
|
||||
if colData.Min <= colNum && colNum <= colData.Max {
|
||||
visible = !colData.Hidden
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ func (f *File) SetColVisible(sheet, columns string, visible bool) error {
|
|||
if max < min {
|
||||
min, max = max, min
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -282,13 +282,13 @@ func (f *File) SetColVisible(sheet, columns string, visible bool) error {
|
|||
Hidden: !visible,
|
||||
CustomWidth: true,
|
||||
}
|
||||
if xlsx.Cols == nil {
|
||||
if ws.Cols == nil {
|
||||
cols := xlsxCols{}
|
||||
cols.Col = append(cols.Col, colData)
|
||||
xlsx.Cols = &cols
|
||||
ws.Cols = &cols
|
||||
return nil
|
||||
}
|
||||
xlsx.Cols.Col = flatCols(colData, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
ws.Cols.Col = flatCols(colData, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
fc.BestFit = c.BestFit
|
||||
fc.Collapsed = c.Collapsed
|
||||
fc.CustomWidth = c.CustomWidth
|
||||
|
@ -313,15 +313,15 @@ func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
|
|||
if err != nil {
|
||||
return level, err
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if xlsx.Cols == nil {
|
||||
if ws.Cols == nil {
|
||||
return level, err
|
||||
}
|
||||
for c := range xlsx.Cols.Col {
|
||||
colData := &xlsx.Cols.Col[c]
|
||||
for c := range ws.Cols.Col {
|
||||
colData := &ws.Cols.Col[c]
|
||||
if colData.Min <= colNum && colNum <= colData.Max {
|
||||
level = colData.OutlineLevel
|
||||
}
|
||||
|
@ -349,17 +349,17 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
|
|||
OutlineLevel: level,
|
||||
CustomWidth: true,
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if xlsx.Cols == nil {
|
||||
if ws.Cols == nil {
|
||||
cols := xlsxCols{}
|
||||
cols.Col = append(cols.Col, colData)
|
||||
xlsx.Cols = &cols
|
||||
ws.Cols = &cols
|
||||
return err
|
||||
}
|
||||
xlsx.Cols.Col = flatCols(colData, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
ws.Cols.Col = flatCols(colData, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
fc.BestFit = c.BestFit
|
||||
fc.Collapsed = c.Collapsed
|
||||
fc.CustomWidth = c.CustomWidth
|
||||
|
@ -384,7 +384,7 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
|
|||
// err = f.SetColStyle("Sheet1", "C:F", style)
|
||||
//
|
||||
func (f *File) SetColStyle(sheet, columns string, styleID int) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -408,15 +408,15 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
|
|||
if max < min {
|
||||
min, max = max, min
|
||||
}
|
||||
if xlsx.Cols == nil {
|
||||
xlsx.Cols = &xlsxCols{}
|
||||
if ws.Cols == nil {
|
||||
ws.Cols = &xlsxCols{}
|
||||
}
|
||||
xlsx.Cols.Col = flatCols(xlsxCol{
|
||||
ws.Cols.Col = flatCols(xlsxCol{
|
||||
Min: min,
|
||||
Max: max,
|
||||
Width: 9,
|
||||
Style: styleID,
|
||||
}, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
}, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
fc.BestFit = c.BestFit
|
||||
fc.Collapsed = c.Collapsed
|
||||
fc.CustomWidth = c.CustomWidth
|
||||
|
@ -451,7 +451,7 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error
|
|||
min, max = max, min
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -461,13 +461,13 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error
|
|||
Width: width,
|
||||
CustomWidth: true,
|
||||
}
|
||||
if xlsx.Cols == nil {
|
||||
if ws.Cols == nil {
|
||||
cols := xlsxCols{}
|
||||
cols.Col = append(cols.Col, col)
|
||||
xlsx.Cols = &cols
|
||||
ws.Cols = &cols
|
||||
return err
|
||||
}
|
||||
xlsx.Cols.Col = flatCols(col, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
ws.Cols.Col = flatCols(col, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
|
||||
fc.BestFit = c.BestFit
|
||||
fc.Collapsed = c.Collapsed
|
||||
fc.Hidden = c.Hidden
|
||||
|
@ -623,13 +623,13 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) {
|
|||
if err != nil {
|
||||
return defaultColWidthPixels, err
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return defaultColWidthPixels, err
|
||||
}
|
||||
if xlsx.Cols != nil {
|
||||
if ws.Cols != nil {
|
||||
var width float64
|
||||
for _, v := range xlsx.Cols.Col {
|
||||
for _, v := range ws.Cols.Col {
|
||||
if v.Min <= colNum && colNum <= v.Max {
|
||||
width = v.Width
|
||||
}
|
||||
|
@ -670,12 +670,12 @@ func (f *File) RemoveCol(sheet, col string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for rowIdx := range xlsx.SheetData.Row {
|
||||
rowData := &xlsx.SheetData.Row[rowIdx]
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
rowData := &ws.SheetData.Row[rowIdx]
|
||||
for colIdx := range rowData.C {
|
||||
colName, _, _ := SplitCellName(rowData.C[colIdx].R)
|
||||
if colName == col {
|
||||
|
|
|
@ -91,7 +91,7 @@ func (f *File) AddComment(sheet, cell, format string) error {
|
|||
return err
|
||||
}
|
||||
// Read sheet data.
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -99,9 +99,9 @@ func (f *File) AddComment(sheet, cell, format string) error {
|
|||
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(commentID) + ".vml"
|
||||
sheetRelationshipsComments := "../comments" + strconv.Itoa(commentID) + ".xml"
|
||||
sheetRelationshipsDrawingVML := "../drawings/vmlDrawing" + strconv.Itoa(commentID) + ".vml"
|
||||
if xlsx.LegacyDrawing != nil {
|
||||
if ws.LegacyDrawing != nil {
|
||||
// The worksheet already has a comments relationships, use the relationships drawing ../drawings/vmlDrawing%d.vml.
|
||||
sheetRelationshipsDrawingVML = f.getSheetRelationshipsTargetByID(sheet, xlsx.LegacyDrawing.RID)
|
||||
sheetRelationshipsDrawingVML = f.getSheetRelationshipsTargetByID(sheet, ws.LegacyDrawing.RID)
|
||||
commentID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingVML, "../drawings/vmlDrawing"), ".vml"))
|
||||
drawingVML = strings.Replace(sheetRelationshipsDrawingVML, "..", "xl", -1)
|
||||
} else {
|
||||
|
|
|
@ -17,7 +17,7 @@ var trueExpectedDateList = []dateTest{
|
|||
{0.0000000000000000, time.Date(1899, time.December, 30, 0, 0, 0, 0, time.UTC)},
|
||||
{25569.000000000000, time.Unix(0, 0).UTC()},
|
||||
|
||||
// Expected values extracted from real xlsx file
|
||||
// Expected values extracted from real spreadsheet
|
||||
{1.0000000000000000, time.Date(1900, time.January, 1, 0, 0, 0, 0, time.UTC)},
|
||||
{1.0000115740740740, time.Date(1900, time.January, 1, 0, 0, 1, 0, time.UTC)},
|
||||
{1.0006944444444446, time.Date(1900, time.January, 1, 0, 1, 0, 0, time.UTC)},
|
||||
|
|
10
drawing.go
10
drawing.go
|
@ -24,11 +24,11 @@ import (
|
|||
|
||||
// prepareDrawing provides a function to prepare drawing ID and XML by given
|
||||
// drawingID, worksheet name and default drawingXML.
|
||||
func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawingXML string) (int, string) {
|
||||
func (f *File) prepareDrawing(ws *xlsxWorksheet, drawingID int, sheet, drawingXML string) (int, string) {
|
||||
sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
|
||||
if xlsx.Drawing != nil {
|
||||
if ws.Drawing != nil {
|
||||
// The worksheet already has a picture or chart relationships, use the relationships drawing ../drawings/drawing%d.xml.
|
||||
sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID)
|
||||
sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID)
|
||||
drawingID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingXML, "../drawings/drawing"), ".xml"))
|
||||
drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1)
|
||||
} else {
|
||||
|
@ -42,13 +42,13 @@ func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawing
|
|||
|
||||
// prepareChartSheetDrawing provides a function to prepare drawing ID and XML
|
||||
// by given drawingID, worksheet name and default drawingXML.
|
||||
func (f *File) prepareChartSheetDrawing(xlsx *xlsxChartsheet, drawingID int, sheet string) {
|
||||
func (f *File) prepareChartSheetDrawing(cs *xlsxChartsheet, drawingID int, sheet string) {
|
||||
sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
|
||||
// Only allow one chart in a chartsheet.
|
||||
sheetRels := "xl/chartsheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/chartsheets/") + ".rels"
|
||||
rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
|
||||
f.addSheetNameSpace(sheet, SourceRelationship)
|
||||
xlsx.Drawing = &xlsxDrawing{
|
||||
cs.Drawing = &xlsxDrawing{
|
||||
RID: "rId" + strconv.Itoa(rID),
|
||||
}
|
||||
return
|
||||
|
|
22
excelize.go
22
excelize.go
|
@ -166,7 +166,7 @@ func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error {
|
|||
|
||||
// workSheetReader provides a function to get the pointer to the structure
|
||||
// after deserialization by given worksheet name.
|
||||
func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) {
|
||||
func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
var (
|
||||
|
@ -178,18 +178,18 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) {
|
|||
err = fmt.Errorf("sheet %s is not exist", sheet)
|
||||
return
|
||||
}
|
||||
if xlsx = f.Sheet[name]; f.Sheet[name] == nil {
|
||||
if ws = f.Sheet[name]; f.Sheet[name] == nil {
|
||||
if strings.HasPrefix(name, "xl/chartsheets") {
|
||||
err = fmt.Errorf("sheet %s is chart sheet", sheet)
|
||||
return
|
||||
}
|
||||
xlsx = new(xlsxWorksheet)
|
||||
ws = new(xlsxWorksheet)
|
||||
if _, ok := f.xmlAttr[name]; !ok {
|
||||
d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(name))))
|
||||
f.xmlAttr[name] = append(f.xmlAttr[name], getRootElement(d)...)
|
||||
}
|
||||
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(name)))).
|
||||
Decode(xlsx); err != nil && err != io.EOF {
|
||||
Decode(ws); err != nil && err != io.EOF {
|
||||
err = fmt.Errorf("xml decode error: %s", err)
|
||||
return
|
||||
}
|
||||
|
@ -198,13 +198,13 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) {
|
|||
f.checked = make(map[string]bool)
|
||||
}
|
||||
if ok = f.checked[name]; !ok {
|
||||
checkSheet(xlsx)
|
||||
if err = checkRow(xlsx); err != nil {
|
||||
checkSheet(ws)
|
||||
if err = checkRow(ws); err != nil {
|
||||
return
|
||||
}
|
||||
f.checked[name] = true
|
||||
}
|
||||
f.Sheet[name] = xlsx
|
||||
f.Sheet[name] = ws
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -212,9 +212,9 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) {
|
|||
|
||||
// checkSheet provides a function to fill each row element and make that is
|
||||
// continuous in a worksheet of XML.
|
||||
func checkSheet(xlsx *xlsxWorksheet) {
|
||||
func checkSheet(ws *xlsxWorksheet) {
|
||||
var row int
|
||||
for _, r := range xlsx.SheetData.Row {
|
||||
for _, r := range ws.SheetData.Row {
|
||||
if r.R != 0 && r.R > row {
|
||||
row = r.R
|
||||
continue
|
||||
|
@ -223,7 +223,7 @@ func checkSheet(xlsx *xlsxWorksheet) {
|
|||
}
|
||||
sheetData := xlsxSheetData{Row: make([]xlsxRow, row)}
|
||||
row = 0
|
||||
for _, r := range xlsx.SheetData.Row {
|
||||
for _, r := range ws.SheetData.Row {
|
||||
if r.R != 0 {
|
||||
sheetData.Row[r.R-1] = r
|
||||
row = r.R
|
||||
|
@ -236,7 +236,7 @@ func checkSheet(xlsx *xlsxWorksheet) {
|
|||
for i := 1; i <= row; i++ {
|
||||
sheetData.Row[i-1].R = i
|
||||
}
|
||||
xlsx.SheetData = sheetData
|
||||
ws.SheetData = sheetData
|
||||
}
|
||||
|
||||
// addRels provides a function to add relationships by given XML path,
|
||||
|
|
|
@ -21,14 +21,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCurrency(t *testing.T) {
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
assert.NoError(t, err)
|
||||
// f.NewSheet("Sheet3")
|
||||
go f.SetCellValue("Sheet1", "A1", "value")
|
||||
go f.SetCellValue("Sheet2", "A1", "value")
|
||||
}
|
||||
|
||||
func TestOpenFile(t *testing.T) {
|
||||
// Test update the spreadsheet file.
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
|
|
6
file.go
6
file.go
|
@ -23,7 +23,7 @@ import (
|
|||
// NewFile provides a function to create new file by default template. For
|
||||
// example:
|
||||
//
|
||||
// xlsx := NewFile()
|
||||
// f := NewFile()
|
||||
//
|
||||
func NewFile() *File {
|
||||
file := make(map[string][]byte)
|
||||
|
@ -54,7 +54,7 @@ func NewFile() *File {
|
|||
return f
|
||||
}
|
||||
|
||||
// Save provides a function to override the xlsx file with origin path.
|
||||
// Save provides a function to override the spreadsheet with origin path.
|
||||
func (f *File) Save() error {
|
||||
if f.Path == "" {
|
||||
return fmt.Errorf("no path defined for file, consider File.WriteTo or File.Write")
|
||||
|
@ -62,7 +62,7 @@ func (f *File) Save() error {
|
|||
return f.SaveAs(f.Path)
|
||||
}
|
||||
|
||||
// SaveAs provides a function to create or update to an xlsx file at the
|
||||
// SaveAs provides a function to create or update to an spreadsheet at the
|
||||
// provided path.
|
||||
func (f *File) SaveAs(name string, opt ...Options) error {
|
||||
if len(name) > MaxFileNameLength {
|
||||
|
|
|
@ -24,7 +24,7 @@ func BenchmarkWrite(b *testing.B) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Save xlsx file by the given path.
|
||||
// Save spreadsheet by the given path.
|
||||
err := f.SaveAs("./test.xlsx")
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
|
|
38
merge.go
38
merge.go
|
@ -47,14 +47,14 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
|
|||
hcell, _ = CoordinatesToCellName(rect1[0], rect1[1])
|
||||
vcell, _ = CoordinatesToCellName(rect1[2], rect1[3])
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ref := hcell + ":" + vcell
|
||||
if xlsx.MergeCells != nil {
|
||||
for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
|
||||
cellData := xlsx.MergeCells.Cells[i]
|
||||
if ws.MergeCells != nil {
|
||||
for i := 0; i < len(ws.MergeCells.Cells); i++ {
|
||||
cellData := ws.MergeCells.Cells[i]
|
||||
if cellData == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
|
|||
|
||||
// Delete the merged cells of the overlapping area.
|
||||
if isOverlap(rect1, rect2) {
|
||||
xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells[:i], xlsx.MergeCells.Cells[i+1:]...)
|
||||
ws.MergeCells.Cells = append(ws.MergeCells.Cells[:i], ws.MergeCells.Cells[i+1:]...)
|
||||
i--
|
||||
|
||||
if rect1[0] > rect2[0] {
|
||||
|
@ -93,11 +93,11 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
|
|||
ref = hcell + ":" + vcell
|
||||
}
|
||||
}
|
||||
xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells, &xlsxMergeCell{Ref: ref})
|
||||
ws.MergeCells.Cells = append(ws.MergeCells.Cells, &xlsxMergeCell{Ref: ref})
|
||||
} else {
|
||||
xlsx.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ref}}}
|
||||
ws.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ref}}}
|
||||
}
|
||||
xlsx.MergeCells.Count = len(xlsx.MergeCells.Cells)
|
||||
ws.MergeCells.Count = len(ws.MergeCells.Cells)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
|
|||
//
|
||||
// Attention: overlapped areas will also be unmerged.
|
||||
func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -121,12 +121,12 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
|
|||
_ = sortCoordinates(rect1)
|
||||
|
||||
// return nil since no MergeCells in the sheet
|
||||
if xlsx.MergeCells == nil {
|
||||
if ws.MergeCells == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _, cellData := range xlsx.MergeCells.Cells {
|
||||
for _, cellData := range ws.MergeCells.Cells {
|
||||
if cellData == nil {
|
||||
continue
|
||||
}
|
||||
|
@ -143,11 +143,11 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
|
|||
if isOverlap(rect1, rect2) {
|
||||
continue
|
||||
}
|
||||
xlsx.MergeCells.Cells[i] = cellData
|
||||
ws.MergeCells.Cells[i] = cellData
|
||||
i++
|
||||
}
|
||||
xlsx.MergeCells.Cells = xlsx.MergeCells.Cells[:i]
|
||||
xlsx.MergeCells.Count = len(xlsx.MergeCells.Cells)
|
||||
ws.MergeCells.Cells = ws.MergeCells.Cells[:i]
|
||||
ws.MergeCells.Count = len(ws.MergeCells.Cells)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -155,15 +155,15 @@ func (f *File) UnmergeCell(sheet string, hcell, vcell string) error {
|
|||
// currently.
|
||||
func (f *File) GetMergeCells(sheet string) ([]MergeCell, error) {
|
||||
var mergeCells []MergeCell
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return mergeCells, err
|
||||
}
|
||||
if xlsx.MergeCells != nil {
|
||||
mergeCells = make([]MergeCell, 0, len(xlsx.MergeCells.Cells))
|
||||
if ws.MergeCells != nil {
|
||||
mergeCells = make([]MergeCell, 0, len(ws.MergeCells.Cells))
|
||||
|
||||
for i := range xlsx.MergeCells.Cells {
|
||||
ref := xlsx.MergeCells.Cells[i].Ref
|
||||
for i := range ws.MergeCells.Cells {
|
||||
ref := ws.MergeCells.Cells[i].Ref
|
||||
axis := strings.Split(ref, ":")[0]
|
||||
val, _ := f.GetCellValue(sheet, axis)
|
||||
mergeCells = append(mergeCells, []string{ref, val})
|
||||
|
|
10
picture.go
10
picture.go
|
@ -145,14 +145,14 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
|
|||
return err
|
||||
}
|
||||
// Read sheet data.
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder.
|
||||
drawingID := f.countDrawings() + 1
|
||||
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
|
||||
drawingID, drawingXML = f.prepareDrawing(xlsx, drawingID, sheet, drawingXML)
|
||||
drawingID, drawingXML = f.prepareDrawing(ws, drawingID, sheet, drawingXML)
|
||||
drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels"
|
||||
mediaStr := ".." + strings.TrimPrefix(f.addMedia(file, ext), "xl")
|
||||
drawingRID := f.addRels(drawingRels, SourceRelationshipImage, mediaStr, hyperlinkType)
|
||||
|
@ -459,14 +459,14 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
|
|||
}
|
||||
col--
|
||||
row--
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if xlsx.Drawing == nil {
|
||||
if ws.Drawing == nil {
|
||||
return "", nil, err
|
||||
}
|
||||
target := f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID)
|
||||
target := f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID)
|
||||
drawingXML := strings.Replace(target, "..", "xl", -1)
|
||||
_, ok := f.XLSX[drawingXML]
|
||||
if !ok {
|
||||
|
|
123
rows.go
123
rows.go
|
@ -228,25 +228,25 @@ func (f *File) SetRowHeight(sheet string, row int, height float64) error {
|
|||
if height > MaxRowHeight {
|
||||
return errors.New("the height of the row must be smaller than or equal to 409 points")
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prepareSheetXML(xlsx, 0, row)
|
||||
prepareSheetXML(ws, 0, row)
|
||||
|
||||
rowIdx := row - 1
|
||||
xlsx.SheetData.Row[rowIdx].Ht = height
|
||||
xlsx.SheetData.Row[rowIdx].CustomHeight = true
|
||||
ws.SheetData.Row[rowIdx].Ht = height
|
||||
ws.SheetData.Row[rowIdx].CustomHeight = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// getRowHeight provides a function to get row height in pixels by given sheet
|
||||
// name and row index.
|
||||
func (f *File) getRowHeight(sheet string, row int) int {
|
||||
xlsx, _ := f.workSheetReader(sheet)
|
||||
for i := range xlsx.SheetData.Row {
|
||||
v := &xlsx.SheetData.Row[i]
|
||||
ws, _ := f.workSheetReader(sheet)
|
||||
for i := range ws.SheetData.Row {
|
||||
v := &ws.SheetData.Row[i]
|
||||
if v.R == row+1 && v.Ht != 0 {
|
||||
return int(convertRowHeightToPixels(v.Ht))
|
||||
}
|
||||
|
@ -322,28 +322,28 @@ func (f *File) sharedStringsReader() *xlsxSST {
|
|||
}
|
||||
|
||||
// getValueFrom return a value from a column/row cell, this function is
|
||||
// inteded to be used with for range on rows an argument with the xlsx opened
|
||||
// file.
|
||||
func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
|
||||
// inteded to be used with for range on rows an argument with the spreadsheet
|
||||
// opened file.
|
||||
func (c *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
switch xlsx.T {
|
||||
switch c.T {
|
||||
case "s":
|
||||
if xlsx.V != "" {
|
||||
if c.V != "" {
|
||||
xlsxSI := 0
|
||||
xlsxSI, _ = strconv.Atoi(xlsx.V)
|
||||
xlsxSI, _ = strconv.Atoi(c.V)
|
||||
if len(d.SI) > xlsxSI {
|
||||
return f.formattedValue(xlsx.S, d.SI[xlsxSI].String()), nil
|
||||
return f.formattedValue(c.S, d.SI[xlsxSI].String()), nil
|
||||
}
|
||||
}
|
||||
return f.formattedValue(xlsx.S, xlsx.V), nil
|
||||
return f.formattedValue(c.S, c.V), nil
|
||||
case "str":
|
||||
return f.formattedValue(xlsx.S, xlsx.V), nil
|
||||
return f.formattedValue(c.S, c.V), nil
|
||||
case "inlineStr":
|
||||
if xlsx.IS != nil {
|
||||
return f.formattedValue(xlsx.S, xlsx.IS.String()), nil
|
||||
if c.IS != nil {
|
||||
return f.formattedValue(c.S, c.IS.String()), nil
|
||||
}
|
||||
return f.formattedValue(xlsx.S, xlsx.V), nil
|
||||
return f.formattedValue(c.S, c.V), nil
|
||||
default:
|
||||
// correct numeric values as legacy Excel app
|
||||
// https://en.wikipedia.org/wiki/Numeric_precision_in_Microsoft_Excel
|
||||
|
@ -351,20 +351,19 @@ func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
|
|||
// Although this number has a decimal representation that is an infinite string of ones,
|
||||
// Excel displays only the leading 15 figures. In the second line, the number one is added to the fraction, and again Excel displays only 15 figures.
|
||||
const precision = 1000000000000000
|
||||
if len(xlsx.V) > 16 {
|
||||
num, err := strconv.ParseFloat(xlsx.V, 64)
|
||||
if len(c.V) > 16 {
|
||||
num, err := strconv.ParseFloat(c.V, 64)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
num = math.Round(num*precision) / precision
|
||||
val := fmt.Sprintf("%g", num)
|
||||
if val != xlsx.V {
|
||||
return f.formattedValue(xlsx.S, val), nil
|
||||
if val != c.V {
|
||||
return f.formattedValue(c.S, val), nil
|
||||
}
|
||||
}
|
||||
|
||||
return f.formattedValue(xlsx.S, xlsx.V), nil
|
||||
return f.formattedValue(c.S, c.V), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,12 +377,12 @@ func (f *File) SetRowVisible(sheet string, row int, visible bool) error {
|
|||
return newInvalidRowNumberError(row)
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prepareSheetXML(xlsx, 0, row)
|
||||
xlsx.SheetData.Row[row-1].Hidden = !visible
|
||||
prepareSheetXML(ws, 0, row)
|
||||
ws.SheetData.Row[row-1].Hidden = !visible
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -398,14 +397,14 @@ func (f *File) GetRowVisible(sheet string, row int) (bool, error) {
|
|||
return false, newInvalidRowNumberError(row)
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if row > len(xlsx.SheetData.Row) {
|
||||
if row > len(ws.SheetData.Row) {
|
||||
return false, nil
|
||||
}
|
||||
return !xlsx.SheetData.Row[row-1].Hidden, nil
|
||||
return !ws.SheetData.Row[row-1].Hidden, nil
|
||||
}
|
||||
|
||||
// SetRowOutlineLevel provides a function to set outline level number of a
|
||||
|
@ -421,12 +420,12 @@ func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error {
|
|||
if level > 7 || level < 1 {
|
||||
return errors.New("invalid outline level")
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prepareSheetXML(xlsx, 0, row)
|
||||
xlsx.SheetData.Row[row-1].OutlineLevel = level
|
||||
prepareSheetXML(ws, 0, row)
|
||||
ws.SheetData.Row[row-1].OutlineLevel = level
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -440,14 +439,14 @@ func (f *File) GetRowOutlineLevel(sheet string, row int) (uint8, error) {
|
|||
if row < 1 {
|
||||
return 0, newInvalidRowNumberError(row)
|
||||
}
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if row > len(xlsx.SheetData.Row) {
|
||||
if row > len(ws.SheetData.Row) {
|
||||
return 0, nil
|
||||
}
|
||||
return xlsx.SheetData.Row[row-1].OutlineLevel, nil
|
||||
return ws.SheetData.Row[row-1].OutlineLevel, nil
|
||||
}
|
||||
|
||||
// RemoveRow provides a function to remove single row by given worksheet name
|
||||
|
@ -464,22 +463,22 @@ func (f *File) RemoveRow(sheet string, row int) error {
|
|||
return newInvalidRowNumberError(row)
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if row > len(xlsx.SheetData.Row) {
|
||||
if row > len(ws.SheetData.Row) {
|
||||
return f.adjustHelper(sheet, rows, row, -1)
|
||||
}
|
||||
keep := 0
|
||||
for rowIdx := 0; rowIdx < len(xlsx.SheetData.Row); rowIdx++ {
|
||||
v := &xlsx.SheetData.Row[rowIdx]
|
||||
for rowIdx := 0; rowIdx < len(ws.SheetData.Row); rowIdx++ {
|
||||
v := &ws.SheetData.Row[rowIdx]
|
||||
if v.R != row {
|
||||
xlsx.SheetData.Row[keep] = *v
|
||||
ws.SheetData.Row[keep] = *v
|
||||
keep++
|
||||
}
|
||||
}
|
||||
xlsx.SheetData.Row = xlsx.SheetData.Row[:keep]
|
||||
ws.SheetData.Row = ws.SheetData.Row[:keep]
|
||||
return f.adjustHelper(sheet, rows, row, -1)
|
||||
}
|
||||
|
||||
|
@ -526,20 +525,20 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
|||
return newInvalidRowNumberError(row)
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if row > len(xlsx.SheetData.Row) || row2 < 1 || row == row2 {
|
||||
if row > len(ws.SheetData.Row) || row2 < 1 || row == row2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var ok bool
|
||||
var rowCopy xlsxRow
|
||||
|
||||
for i, r := range xlsx.SheetData.Row {
|
||||
for i, r := range ws.SheetData.Row {
|
||||
if r.R == row {
|
||||
rowCopy = xlsx.SheetData.Row[i]
|
||||
rowCopy = ws.SheetData.Row[i]
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
|
@ -553,13 +552,13 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
|||
}
|
||||
|
||||
idx2 := -1
|
||||
for i, r := range xlsx.SheetData.Row {
|
||||
for i, r := range ws.SheetData.Row {
|
||||
if r.R == row2 {
|
||||
idx2 = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if idx2 == -1 && len(xlsx.SheetData.Row) >= row2 {
|
||||
if idx2 == -1 && len(ws.SheetData.Row) >= row2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -567,23 +566,23 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
|||
f.ajustSingleRowDimensions(&rowCopy, row2)
|
||||
|
||||
if idx2 != -1 {
|
||||
xlsx.SheetData.Row[idx2] = rowCopy
|
||||
ws.SheetData.Row[idx2] = rowCopy
|
||||
} else {
|
||||
xlsx.SheetData.Row = append(xlsx.SheetData.Row, rowCopy)
|
||||
ws.SheetData.Row = append(ws.SheetData.Row, rowCopy)
|
||||
}
|
||||
return f.duplicateMergeCells(sheet, xlsx, row, row2)
|
||||
return f.duplicateMergeCells(sheet, ws, row, row2)
|
||||
}
|
||||
|
||||
// duplicateMergeCells merge cells in the destination row if there are single
|
||||
// row merged cells in the copied row.
|
||||
func (f *File) duplicateMergeCells(sheet string, xlsx *xlsxWorksheet, row, row2 int) error {
|
||||
if xlsx.MergeCells == nil {
|
||||
func (f *File) duplicateMergeCells(sheet string, ws *xlsxWorksheet, row, row2 int) error {
|
||||
if ws.MergeCells == nil {
|
||||
return nil
|
||||
}
|
||||
if row > row2 {
|
||||
row++
|
||||
}
|
||||
for _, rng := range xlsx.MergeCells.Cells {
|
||||
for _, rng := range ws.MergeCells.Cells {
|
||||
coordinates, err := f.areaRefToCoordinates(rng.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -592,8 +591,8 @@ func (f *File) duplicateMergeCells(sheet string, xlsx *xlsxWorksheet, row, row2
|
|||
return nil
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
|
||||
areaData := xlsx.MergeCells.Cells[i]
|
||||
for i := 0; i < len(ws.MergeCells.Cells); i++ {
|
||||
areaData := ws.MergeCells.Cells[i]
|
||||
coordinates, _ := f.areaRefToCoordinates(areaData.Ref)
|
||||
x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3]
|
||||
if y1 == y2 && y1 == row {
|
||||
|
@ -632,9 +631,9 @@ func (f *File) duplicateMergeCells(sheet string, xlsx *xlsxWorksheet, row, row2
|
|||
//
|
||||
// Noteice: this method could be very slow for large spreadsheets (more than
|
||||
// 3000 rows one sheet).
|
||||
func checkRow(xlsx *xlsxWorksheet) error {
|
||||
for rowIdx := range xlsx.SheetData.Row {
|
||||
rowData := &xlsx.SheetData.Row[rowIdx]
|
||||
func checkRow(ws *xlsxWorksheet) error {
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
rowData := &ws.SheetData.Row[rowIdx]
|
||||
|
||||
colCount := len(rowData.C)
|
||||
if colCount == 0 {
|
||||
|
@ -665,7 +664,7 @@ func checkRow(xlsx *xlsxWorksheet) error {
|
|||
oldList := rowData.C
|
||||
newlist := make([]xlsxC, 0, lastCol)
|
||||
|
||||
rowData.C = xlsx.SheetData.Row[rowIdx].C[:0]
|
||||
rowData.C = ws.SheetData.Row[rowIdx].C[:0]
|
||||
|
||||
for colIdx := 0; colIdx < lastCol; colIdx++ {
|
||||
cellName, err := CoordinatesToCellName(colIdx+1, rowIdx+1)
|
||||
|
@ -683,7 +682,7 @@ func checkRow(xlsx *xlsxWorksheet) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
xlsx.SheetData.Row[rowIdx].C[colNum-1] = *colData
|
||||
ws.SheetData.Row[rowIdx].C[colNum-1] = *colData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
174
rows_test.go
174
rows_test.go
|
@ -82,11 +82,11 @@ func TestRowsIterator(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRowsError(t *testing.T) {
|
||||
xlsx, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
_, err = xlsx.Rows("SheetN")
|
||||
_, err = f.Rows("SheetN")
|
||||
assert.EqualError(t, err, "sheet SheetN is not exist")
|
||||
}
|
||||
|
||||
|
@ -259,49 +259,49 @@ func TestRemoveRow(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInsertRow(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
sheet1 := xlsx.GetSheetName(0)
|
||||
r, err := xlsx.workSheetReader(sheet1)
|
||||
f := NewFile()
|
||||
sheet1 := f.GetSheetName(0)
|
||||
r, err := f.workSheetReader(sheet1)
|
||||
assert.NoError(t, err)
|
||||
const (
|
||||
colCount = 10
|
||||
rowCount = 10
|
||||
)
|
||||
fillCells(xlsx, sheet1, colCount, rowCount)
|
||||
fillCells(f, sheet1, colCount, rowCount)
|
||||
|
||||
assert.NoError(t, xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
|
||||
assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
|
||||
|
||||
assert.EqualError(t, xlsx.InsertRow(sheet1, -1), "invalid row number -1")
|
||||
assert.EqualError(t, f.InsertRow(sheet1, -1), "invalid row number -1")
|
||||
|
||||
assert.EqualError(t, xlsx.InsertRow(sheet1, 0), "invalid row number 0")
|
||||
assert.EqualError(t, f.InsertRow(sheet1, 0), "invalid row number 0")
|
||||
|
||||
assert.NoError(t, xlsx.InsertRow(sheet1, 1))
|
||||
assert.NoError(t, f.InsertRow(sheet1, 1))
|
||||
if !assert.Len(t, r.SheetData.Row, rowCount+1) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.NoError(t, xlsx.InsertRow(sheet1, 4))
|
||||
assert.NoError(t, f.InsertRow(sheet1, 4))
|
||||
if !assert.Len(t, r.SheetData.Row, rowCount+2) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
|
||||
}
|
||||
|
||||
// Testing internal sructure state after insert operations.
|
||||
// It is important for insert workflow to be constant to avoid side effect with functions related to internal structure.
|
||||
func TestInsertRowInEmptyFile(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
sheet1 := xlsx.GetSheetName(0)
|
||||
r, err := xlsx.workSheetReader(sheet1)
|
||||
f := NewFile()
|
||||
sheet1 := f.GetSheetName(0)
|
||||
r, err := f.workSheetReader(sheet1)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, xlsx.InsertRow(sheet1, 1))
|
||||
assert.NoError(t, f.InsertRow(sheet1, 1))
|
||||
assert.Len(t, r.SheetData.Row, 0)
|
||||
assert.NoError(t, xlsx.InsertRow(sheet1, 2))
|
||||
assert.NoError(t, f.InsertRow(sheet1, 2))
|
||||
assert.Len(t, r.SheetData.Row, 0)
|
||||
assert.NoError(t, xlsx.InsertRow(sheet1, 99))
|
||||
assert.NoError(t, f.InsertRow(sheet1, 99))
|
||||
assert.Len(t, r.SheetData.Row, 0)
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
|
||||
}
|
||||
|
||||
func TestDuplicateRowFromSingleRow(t *testing.T) {
|
||||
|
@ -318,12 +318,12 @@ func TestDuplicateRowFromSingleRow(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("FromSingleRow", func(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, "A1", cells["A1"]))
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, "B1", cells["B1"]))
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetCellStr(sheet, "A1", cells["A1"]))
|
||||
assert.NoError(t, f.SetCellStr(sheet, "B1", cells["B1"]))
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) {
|
||||
assert.NoError(t, f.DuplicateRow(sheet, 1))
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect := map[string]string{
|
||||
|
@ -331,15 +331,15 @@ func TestDuplicateRowFromSingleRow(t *testing.T) {
|
|||
"A2": cells["A1"], "B2": cells["B1"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRow(sheet, 2))
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) {
|
||||
assert.NoError(t, f.DuplicateRow(sheet, 2))
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect = map[string]string{
|
||||
|
@ -348,7 +348,7 @@ func TestDuplicateRowFromSingleRow(t *testing.T) {
|
|||
"A3": cells["A1"], "B3": cells["B1"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -371,16 +371,16 @@ func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("UpdateDuplicatedRows", func(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, "A1", cells["A1"]))
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, "B1", cells["B1"]))
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetCellStr(sheet, "A1", cells["A1"]))
|
||||
assert.NoError(t, f.SetCellStr(sheet, "B1", cells["B1"]))
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
|
||||
assert.NoError(t, f.DuplicateRow(sheet, 1))
|
||||
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, "A2", cells["A2"]))
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, "B2", cells["B2"]))
|
||||
assert.NoError(t, f.SetCellStr(sheet, "A2", cells["A2"]))
|
||||
assert.NoError(t, f.SetCellStr(sheet, "B2", cells["B2"]))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.UpdateDuplicatedRows"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.UpdateDuplicatedRows"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect := map[string]string{
|
||||
|
@ -388,7 +388,7 @@ func TestDuplicateRowUpdateDuplicatedRows(t *testing.T) {
|
|||
"A2": cells["A2"], "B2": cells["B2"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -419,11 +419,11 @@ func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("FirstOfMultipleRows", func(t *testing.T) {
|
||||
xlsx := newFileWithDefaults()
|
||||
f := newFileWithDefaults()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
|
||||
assert.NoError(t, f.DuplicateRow(sheet, 1))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect := map[string]string{
|
||||
|
@ -433,7 +433,7 @@ func TestDuplicateRowFirstOfMultipleRows(t *testing.T) {
|
|||
"A4": cells["A3"], "B4": cells["B3"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -447,24 +447,24 @@ func TestDuplicateRowZeroWithNoRows(t *testing.T) {
|
|||
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
||||
|
||||
t.Run("ZeroWithNoRows", func(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
f := NewFile()
|
||||
|
||||
assert.EqualError(t, xlsx.DuplicateRow(sheet, 0), "invalid row number 0")
|
||||
assert.EqualError(t, f.DuplicateRow(sheet, 0), "invalid row number 0")
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
val, err := xlsx.GetCellValue(sheet, "A1")
|
||||
val, err := f.GetCellValue(sheet, "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", val)
|
||||
val, err = xlsx.GetCellValue(sheet, "B1")
|
||||
val, err = f.GetCellValue(sheet, "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", val)
|
||||
val, err = xlsx.GetCellValue(sheet, "A2")
|
||||
val, err = f.GetCellValue(sheet, "A2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", val)
|
||||
val, err = xlsx.GetCellValue(sheet, "B2")
|
||||
val, err = f.GetCellValue(sheet, "B2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", val)
|
||||
|
||||
|
@ -475,7 +475,7 @@ func TestDuplicateRowZeroWithNoRows(t *testing.T) {
|
|||
}
|
||||
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -489,11 +489,11 @@ func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
|
|||
outFile := filepath.Join("test", "TestDuplicateRow.%s.xlsx")
|
||||
|
||||
t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
f := NewFile()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRow(sheet, 99))
|
||||
assert.NoError(t, f.DuplicateRow(sheet, 99))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect := map[string]string{
|
||||
|
@ -502,7 +502,7 @@ func TestDuplicateRowMiddleRowOfEmptyFile(t *testing.T) {
|
|||
"A100": "",
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -533,11 +533,11 @@ func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
|
||||
xlsx := newFileWithDefaults()
|
||||
f := newFileWithDefaults()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 3))
|
||||
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 3))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect := map[string]string{
|
||||
|
@ -547,7 +547,7 @@ func TestDuplicateRowWithLargeOffsetToMiddleOfData(t *testing.T) {
|
|||
"A4": cells["A3"], "B4": cells["B3"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -578,11 +578,11 @@ func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
|
||||
xlsx := newFileWithDefaults()
|
||||
f := newFileWithDefaults()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 7))
|
||||
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 7))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
expect := map[string]string{
|
||||
|
@ -592,7 +592,7 @@ func TestDuplicateRowWithLargeOffsetToEmptyRows(t *testing.T) {
|
|||
"A7": cells["A1"], "B7": cells["B1"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -623,11 +623,11 @@ func TestDuplicateRowInsertBefore(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("InsertBefore", func(t *testing.T) {
|
||||
xlsx := newFileWithDefaults()
|
||||
f := newFileWithDefaults()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRowTo(sheet, 2, 1))
|
||||
assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
|
@ -638,7 +638,7 @@ func TestDuplicateRowInsertBefore(t *testing.T) {
|
|||
"A4": cells["A3"], "B4": cells["B3"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v, cell) {
|
||||
t.FailNow()
|
||||
|
@ -669,11 +669,11 @@ func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
|
||||
xlsx := newFileWithDefaults()
|
||||
f := newFileWithDefaults()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRowTo(sheet, 3, 1))
|
||||
assert.NoError(t, f.DuplicateRowTo(sheet, 3, 1))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
|
@ -684,7 +684,7 @@ func TestDuplicateRowInsertBeforeWithLargeOffset(t *testing.T) {
|
|||
"A4": cells["A3"], "B4": cells["B3"],
|
||||
}
|
||||
for cell, val := range expect {
|
||||
v, err := xlsx.GetCellValue(sheet, cell)
|
||||
v, err := f.GetCellValue(sheet, cell)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v) {
|
||||
t.FailNow()
|
||||
|
@ -717,12 +717,12 @@ func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
|
||||
xlsx := newFileWithDefaults()
|
||||
f := newFileWithDefaults()
|
||||
|
||||
assert.NoError(t, xlsx.DuplicateRowTo(sheet, 2, 1))
|
||||
assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 8))
|
||||
assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1))
|
||||
assert.NoError(t, f.DuplicateRowTo(sheet, 1, 8))
|
||||
|
||||
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithMergeCells"))) {
|
||||
if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithMergeCells"))) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
|
@ -732,7 +732,7 @@ func TestDuplicateRowInsertBeforeWithMergeCells(t *testing.T) {
|
|||
{"B1:C1", "B2 Value"},
|
||||
}
|
||||
|
||||
mergeCells, err := xlsx.GetMergeCells(sheet)
|
||||
mergeCells, err := f.GetMergeCells(sheet)
|
||||
assert.NoError(t, err)
|
||||
for idx, val := range expect {
|
||||
if !assert.Equal(t, val, mergeCells[idx]) {
|
||||
|
@ -760,21 +760,21 @@ func TestDuplicateRowInvalidRownum(t *testing.T) {
|
|||
for _, row := range invalidIndexes {
|
||||
name := fmt.Sprintf("%d", row)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
f := NewFile()
|
||||
for col, val := range cells {
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, col, val))
|
||||
assert.NoError(t, f.SetCellStr(sheet, col, val))
|
||||
}
|
||||
|
||||
assert.EqualError(t, xlsx.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
|
||||
assert.EqualError(t, f.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
|
||||
|
||||
for col, val := range cells {
|
||||
v, err := xlsx.GetCellValue(sheet, col)
|
||||
v, err := f.GetCellValue(sheet, col)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
|
||||
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, name)))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -782,21 +782,21 @@ func TestDuplicateRowInvalidRownum(t *testing.T) {
|
|||
for _, row2 := range invalidIndexes {
|
||||
name := fmt.Sprintf("[%d,%d]", row1, row2)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
xlsx := NewFile()
|
||||
f := NewFile()
|
||||
for col, val := range cells {
|
||||
assert.NoError(t, xlsx.SetCellStr(sheet, col, val))
|
||||
assert.NoError(t, f.SetCellStr(sheet, col, val))
|
||||
}
|
||||
|
||||
assert.EqualError(t, xlsx.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
|
||||
assert.EqualError(t, f.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
|
||||
|
||||
for col, val := range cells {
|
||||
v, err := xlsx.GetCellValue(sheet, col)
|
||||
v, err := f.GetCellValue(sheet, col)
|
||||
assert.NoError(t, err)
|
||||
if !assert.Equal(t, val, v) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, name)))
|
||||
assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, name)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -809,12 +809,12 @@ func TestDuplicateRowTo(t *testing.T) {
|
|||
|
||||
func TestDuplicateMergeCells(t *testing.T) {
|
||||
f := File{}
|
||||
xlsx := &xlsxWorksheet{MergeCells: &xlsxMergeCells{
|
||||
ws := &xlsxWorksheet{MergeCells: &xlsxMergeCells{
|
||||
Cells: []*xlsxMergeCell{{Ref: "A1:-"}},
|
||||
}}
|
||||
assert.EqualError(t, f.duplicateMergeCells("Sheet1", xlsx, 0, 0), `cannot convert cell "-" to coordinates: invalid cell name "-"`)
|
||||
xlsx.MergeCells.Cells[0].Ref = "A1:B1"
|
||||
assert.EqualError(t, f.duplicateMergeCells("SheetN", xlsx, 1, 2), "sheet SheetN is not exist")
|
||||
assert.EqualError(t, f.duplicateMergeCells("Sheet1", ws, 0, 0), `cannot convert cell "-" to coordinates: invalid cell name "-"`)
|
||||
ws.MergeCells.Cells[0].Ref = "A1:B1"
|
||||
assert.EqualError(t, f.duplicateMergeCells("SheetN", ws, 1, 2), "sheet SheetN is not exist")
|
||||
}
|
||||
|
||||
func TestGetValueFromInlineStr(t *testing.T) {
|
||||
|
|
6
shape.go
6
shape.go
|
@ -261,7 +261,7 @@ func (f *File) AddShape(sheet, cell, format string) error {
|
|||
return err
|
||||
}
|
||||
// Read sheet data.
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -270,9 +270,9 @@ func (f *File) AddShape(sheet, cell, format string) error {
|
|||
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
|
||||
sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
|
||||
|
||||
if xlsx.Drawing != nil {
|
||||
if ws.Drawing != nil {
|
||||
// The worksheet already has a shape or chart relationships, use the relationships drawing ../drawings/drawing%d.xml.
|
||||
sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID)
|
||||
sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID)
|
||||
drawingID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingXML, "../drawings/drawing"), ".xml"))
|
||||
drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1)
|
||||
} else {
|
||||
|
|
76
sheet.go
76
sheet.go
|
@ -202,7 +202,7 @@ func (f *File) setContentTypes(partName, contentType string) {
|
|||
|
||||
// setSheet provides a function to update sheet property by given index.
|
||||
func (f *File) setSheet(index int, name string) {
|
||||
xlsx := xlsxWorksheet{
|
||||
ws := xlsxWorksheet{
|
||||
Dimension: &xlsxDimension{Ref: "A1"},
|
||||
SheetViews: &xlsxSheetViews{
|
||||
SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
|
||||
|
@ -210,7 +210,7 @@ func (f *File) setSheet(index int, name string) {
|
|||
}
|
||||
path := "xl/worksheets/sheet" + strconv.Itoa(index) + ".xml"
|
||||
f.sheetMap[trimSheetName(name)] = path
|
||||
f.Sheet[path] = &xlsx
|
||||
f.Sheet[path] = &ws
|
||||
f.xmlAttr[path] = append(f.xmlAttr[path], NameSpaceSpreadSheet)
|
||||
}
|
||||
|
||||
|
@ -277,24 +277,24 @@ func (f *File) SetActiveSheet(index int) {
|
|||
}
|
||||
}
|
||||
for idx, name := range f.GetSheetList() {
|
||||
xlsx, err := f.workSheetReader(name)
|
||||
ws, err := f.workSheetReader(name)
|
||||
if err != nil {
|
||||
// Chartsheet or dialogsheet
|
||||
return
|
||||
}
|
||||
if xlsx.SheetViews == nil {
|
||||
xlsx.SheetViews = &xlsxSheetViews{
|
||||
if ws.SheetViews == nil {
|
||||
ws.SheetViews = &xlsxSheetViews{
|
||||
SheetView: []xlsxSheetView{{WorkbookViewID: 0}},
|
||||
}
|
||||
}
|
||||
if len(xlsx.SheetViews.SheetView) > 0 {
|
||||
xlsx.SheetViews.SheetView[0].TabSelected = false
|
||||
if len(ws.SheetViews.SheetView) > 0 {
|
||||
ws.SheetViews.SheetView[0].TabSelected = false
|
||||
}
|
||||
if index == idx {
|
||||
if len(xlsx.SheetViews.SheetView) > 0 {
|
||||
xlsx.SheetViews.SheetView[0].TabSelected = true
|
||||
if len(ws.SheetViews.SheetView) > 0 {
|
||||
ws.SheetViews.SheetView[0].TabSelected = true
|
||||
} else {
|
||||
xlsx.SheetViews.SheetView = append(xlsx.SheetViews.SheetView, xlsxSheetView{
|
||||
ws.SheetViews.SheetView = append(ws.SheetViews.SheetView, xlsxSheetView{
|
||||
TabSelected: true,
|
||||
})
|
||||
}
|
||||
|
@ -746,7 +746,7 @@ func parseFormatPanesSet(formatSet string) (*formatPanes, error) {
|
|||
//
|
||||
func (f *File) SetPanes(sheet, panes string) error {
|
||||
fs, _ := parseFormatPanesSet(panes)
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -759,10 +759,10 @@ func (f *File) SetPanes(sheet, panes string) error {
|
|||
if fs.Freeze {
|
||||
p.State = "frozen"
|
||||
}
|
||||
xlsx.SheetViews.SheetView[len(xlsx.SheetViews.SheetView)-1].Pane = p
|
||||
ws.SheetViews.SheetView[len(ws.SheetViews.SheetView)-1].Pane = p
|
||||
if !(fs.Freeze) && !(fs.Split) {
|
||||
if len(xlsx.SheetViews.SheetView) > 0 {
|
||||
xlsx.SheetViews.SheetView[len(xlsx.SheetViews.SheetView)-1].Pane = nil
|
||||
if len(ws.SheetViews.SheetView) > 0 {
|
||||
ws.SheetViews.SheetView[len(ws.SheetViews.SheetView)-1].Pane = nil
|
||||
}
|
||||
}
|
||||
s := []*xlsxSelection{}
|
||||
|
@ -773,7 +773,7 @@ func (f *File) SetPanes(sheet, panes string) error {
|
|||
SQRef: p.SQRef,
|
||||
})
|
||||
}
|
||||
xlsx.SheetViews.SheetView[len(xlsx.SheetViews.SheetView)-1].Selection = s
|
||||
ws.SheetViews.SheetView[len(ws.SheetViews.SheetView)-1].Selection = s
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1020,12 +1020,12 @@ func attrValToInt(name string, attrs []xml.Attr) (val int, err error) {
|
|||
// - No footer on the first page
|
||||
//
|
||||
func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if settings == nil {
|
||||
xlsx.HeaderFooter = nil
|
||||
ws.HeaderFooter = nil
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1037,7 @@ func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error
|
|||
return fmt.Errorf("field %s must be less than 255 characters", v.Type().Field(i).Name)
|
||||
}
|
||||
}
|
||||
xlsx.HeaderFooter = &xlsxHeaderFooter{
|
||||
ws.HeaderFooter = &xlsxHeaderFooter{
|
||||
AlignWithMargins: settings.AlignWithMargins,
|
||||
DifferentFirst: settings.DifferentFirst,
|
||||
DifferentOddEven: settings.DifferentOddEven,
|
||||
|
@ -1062,7 +1062,7 @@ func (f *File) SetHeaderFooter(sheet string, settings *FormatHeaderFooter) error
|
|||
// })
|
||||
//
|
||||
func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1073,7 +1073,7 @@ func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error
|
|||
SelectLockedCells: true,
|
||||
}
|
||||
}
|
||||
xlsx.SheetProtection = &xlsxSheetProtection{
|
||||
ws.SheetProtection = &xlsxSheetProtection{
|
||||
AutoFilter: settings.AutoFilter,
|
||||
DeleteColumns: settings.DeleteColumns,
|
||||
DeleteRows: settings.DeleteRows,
|
||||
|
@ -1092,18 +1092,18 @@ func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error
|
|||
Sort: settings.Sort,
|
||||
}
|
||||
if settings.Password != "" {
|
||||
xlsx.SheetProtection.Password = genSheetPasswd(settings.Password)
|
||||
ws.SheetProtection.Password = genSheetPasswd(settings.Password)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// UnprotectSheet provides a function to unprotect an Excel worksheet.
|
||||
func (f *File) UnprotectSheet(sheet string) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
xlsx.SheetProtection = nil
|
||||
ws.SheetProtection = nil
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1494,19 +1494,19 @@ func (f *File) GroupSheets(sheets []string) error {
|
|||
return errors.New("group worksheet must contain an active worksheet")
|
||||
}
|
||||
// check worksheet exists
|
||||
ws := []*xlsxWorksheet{}
|
||||
wss := []*xlsxWorksheet{}
|
||||
for _, sheet := range sheets {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
worksheet, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws = append(ws, xlsx)
|
||||
wss = append(wss, worksheet)
|
||||
}
|
||||
for _, s := range ws {
|
||||
sheetViews := s.SheetViews.SheetView
|
||||
for _, ws := range wss {
|
||||
sheetViews := ws.SheetViews.SheetView
|
||||
if len(sheetViews) > 0 {
|
||||
for idx := range sheetViews {
|
||||
s.SheetViews.SheetView[idx].TabSelected = true
|
||||
ws.SheetViews.SheetView[idx].TabSelected = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -1664,25 +1664,25 @@ func (f *File) relsReader(path string) *xlsxRelationships {
|
|||
// fillSheetData ensures there are enough rows, and columns in the chosen
|
||||
// row to accept data. Missing rows are backfilled and given their row number
|
||||
// Uses the last populated row as a hint for the size of the next row to add
|
||||
func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) {
|
||||
rowCount := len(xlsx.SheetData.Row)
|
||||
func prepareSheetXML(ws *xlsxWorksheet, col int, row int) {
|
||||
rowCount := len(ws.SheetData.Row)
|
||||
sizeHint := 0
|
||||
var ht float64
|
||||
var customHeight bool
|
||||
if xlsx.SheetFormatPr != nil {
|
||||
ht = xlsx.SheetFormatPr.DefaultRowHeight
|
||||
if ws.SheetFormatPr != nil {
|
||||
ht = ws.SheetFormatPr.DefaultRowHeight
|
||||
customHeight = true
|
||||
}
|
||||
if rowCount > 0 {
|
||||
sizeHint = len(xlsx.SheetData.Row[rowCount-1].C)
|
||||
sizeHint = len(ws.SheetData.Row[rowCount-1].C)
|
||||
}
|
||||
if rowCount < row {
|
||||
// append missing rows
|
||||
for rowIdx := rowCount; rowIdx < row; rowIdx++ {
|
||||
xlsx.SheetData.Row = append(xlsx.SheetData.Row, xlsxRow{R: rowIdx + 1, CustomHeight: customHeight, Ht: ht, C: make([]xlsxC, 0, sizeHint)})
|
||||
ws.SheetData.Row = append(ws.SheetData.Row, xlsxRow{R: rowIdx + 1, CustomHeight: customHeight, Ht: ht, C: make([]xlsxC, 0, sizeHint)})
|
||||
}
|
||||
}
|
||||
rowData := &xlsx.SheetData.Row[row-1]
|
||||
rowData := &ws.SheetData.Row[row-1]
|
||||
fillColumns(rowData, col, row)
|
||||
}
|
||||
|
||||
|
@ -1696,9 +1696,9 @@ func fillColumns(rowData *xlsxRow, col, row int) {
|
|||
}
|
||||
}
|
||||
|
||||
func makeContiguousColumns(xlsx *xlsxWorksheet, fromRow, toRow, colCount int) {
|
||||
func makeContiguousColumns(ws *xlsxWorksheet, fromRow, toRow, colCount int) {
|
||||
for ; fromRow < toRow; fromRow++ {
|
||||
rowData := &xlsx.SheetData.Row[fromRow-1]
|
||||
rowData := &ws.SheetData.Row[fromRow-1]
|
||||
fillColumns(rowData, colCount, fromRow)
|
||||
}
|
||||
}
|
||||
|
|
12
sheetview.go
12
sheetview.go
|
@ -140,21 +140,21 @@ func (o *ZoomScale) getSheetViewOption(view *xlsxSheetView) {
|
|||
}
|
||||
|
||||
// getSheetView returns the SheetView object
|
||||
func (f *File) getSheetView(sheetName string, viewIndex int) (*xlsxSheetView, error) {
|
||||
xlsx, err := f.workSheetReader(sheetName)
|
||||
func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error) {
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if viewIndex < 0 {
|
||||
if viewIndex < -len(xlsx.SheetViews.SheetView) {
|
||||
if viewIndex < -len(ws.SheetViews.SheetView) {
|
||||
return nil, fmt.Errorf("view index %d out of range", viewIndex)
|
||||
}
|
||||
viewIndex = len(xlsx.SheetViews.SheetView) + viewIndex
|
||||
} else if viewIndex >= len(xlsx.SheetViews.SheetView) {
|
||||
viewIndex = len(ws.SheetViews.SheetView) + viewIndex
|
||||
} else if viewIndex >= len(ws.SheetViews.SheetView) {
|
||||
return nil, fmt.Errorf("view index %d out of range", viewIndex)
|
||||
}
|
||||
|
||||
return &(xlsx.SheetViews.SheetView[viewIndex]), err
|
||||
return &(ws.SheetViews.SheetView[viewIndex]), err
|
||||
}
|
||||
|
||||
// SetSheetViewOptions sets sheet view options. The viewIndex may be negative
|
||||
|
|
|
@ -211,7 +211,7 @@ func TestAddSparkline(t *testing.T) {
|
|||
Negative: true,
|
||||
}))
|
||||
|
||||
// Save xlsx file by the given path.
|
||||
// Save spreadsheet by the given path.
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddSparkline.xlsx")))
|
||||
|
||||
// Test error exceptions
|
||||
|
|
|
@ -69,7 +69,7 @@ func TestStreamWriter(t *testing.T) {
|
|||
}
|
||||
|
||||
assert.NoError(t, streamWriter.Flush())
|
||||
// Save xlsx file by the given path.
|
||||
// Save spreadsheet by the given path.
|
||||
assert.NoError(t, file.SaveAs(filepath.Join("test", "TestStreamWriter.xlsx")))
|
||||
|
||||
// Test close temporary file error.
|
||||
|
|
22
styles.go
22
styles.go
|
@ -27,8 +27,8 @@ import (
|
|||
)
|
||||
|
||||
// Excel styles can reference number formats that are built-in, all of which
|
||||
// have an id less than 164. This is a possibly incomplete list comprised of
|
||||
// as many of them as I could find.
|
||||
// have an id less than 164. Note that this number format code list is under
|
||||
// English localization.
|
||||
var builtInNumFmt = map[int]string{
|
||||
0: "general",
|
||||
1: "0",
|
||||
|
@ -2580,15 +2580,15 @@ func setCellXfs(style *xlsxStyleSheet, fontID, numFmtID, fillID, borderID int, a
|
|||
// GetCellStyle provides a function to get cell style index by given worksheet
|
||||
// name and cell coordinates.
|
||||
func (f *File) GetCellStyle(sheet, axis string) (int, error) {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f.prepareCellStyle(xlsx, col, cellData.S), err
|
||||
return f.prepareCellStyle(ws, col, cellData.S), err
|
||||
}
|
||||
|
||||
// SetCellStyle provides a function to add style attribute for cells by given
|
||||
|
@ -2682,16 +2682,16 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
|
|||
vcolIdx := vcol - 1
|
||||
vrowIdx := vrow - 1
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prepareSheetXML(xlsx, vcol, vrow)
|
||||
makeContiguousColumns(xlsx, hrow, vrow, vcol)
|
||||
prepareSheetXML(ws, vcol, vrow)
|
||||
makeContiguousColumns(ws, hrow, vrow, vcol)
|
||||
|
||||
for r := hrowIdx; r <= vrowIdx; r++ {
|
||||
for k := hcolIdx; k <= vcolIdx; k++ {
|
||||
xlsx.SheetData.Row[r].C[k].S = styleID
|
||||
ws.SheetData.Row[r].C[k].S = styleID
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
@ -2926,7 +2926,7 @@ func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
|
|||
"expression": drawConfFmtExp,
|
||||
}
|
||||
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2948,7 +2948,7 @@ func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
|
|||
}
|
||||
}
|
||||
|
||||
xlsx.ConditionalFormatting = append(xlsx.ConditionalFormatting, &xlsxConditionalFormatting{
|
||||
ws.ConditionalFormatting = append(ws.ConditionalFormatting, &xlsxConditionalFormatting{
|
||||
SQRef: area,
|
||||
CfRule: cfRule,
|
||||
})
|
||||
|
|
|
@ -156,18 +156,18 @@ func TestSetConditionalFormat(t *testing.T) {
|
|||
}}
|
||||
|
||||
for _, testCase := range cases {
|
||||
xl := NewFile()
|
||||
f := NewFile()
|
||||
const sheet = "Sheet1"
|
||||
const cellRange = "A1:A1"
|
||||
|
||||
err := xl.SetConditionalFormat(sheet, cellRange, testCase.format)
|
||||
err := f.SetConditionalFormat(sheet, cellRange, testCase.format)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
xlsx, err := xl.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
assert.NoError(t, err)
|
||||
cf := xlsx.ConditionalFormatting
|
||||
cf := ws.ConditionalFormatting
|
||||
assert.Len(t, cf, 1, testCase.label)
|
||||
assert.Len(t, cf[0].CfRule, 1, testCase.label)
|
||||
assert.Equal(t, cellRange, cf[0].SQRef, testCase.label)
|
||||
|
@ -185,7 +185,7 @@ func TestUnsetConditionalFormat(t *testing.T) {
|
|||
assert.NoError(t, f.UnsetConditionalFormat("Sheet1", "A1:A10"))
|
||||
// Test unset conditional format on not exists worksheet.
|
||||
assert.EqualError(t, f.UnsetConditionalFormat("SheetN", "A1:A10"), "sheet SheetN is not exist")
|
||||
// Save xlsx file by the given path.
|
||||
// Save spreadsheet by the given path.
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestUnsetConditionalFormat.xlsx")))
|
||||
}
|
||||
|
||||
|
|
12
table.go
12
table.go
|
@ -323,18 +323,18 @@ func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
|
|||
// autoFilter provides a function to extract the tokens from the filter
|
||||
// expression. The tokens are mainly non-whitespace groups.
|
||||
func (f *File) autoFilter(sheet, ref string, refRange, col int, formatSet *formatAutoFilter) error {
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
ws, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if xlsx.SheetPr != nil {
|
||||
xlsx.SheetPr.FilterMode = true
|
||||
if ws.SheetPr != nil {
|
||||
ws.SheetPr.FilterMode = true
|
||||
}
|
||||
xlsx.SheetPr = &xlsxSheetPr{FilterMode: true}
|
||||
ws.SheetPr = &xlsxSheetPr{FilterMode: true}
|
||||
filter := &xlsxAutoFilter{
|
||||
Ref: ref,
|
||||
}
|
||||
xlsx.AutoFilter = filter
|
||||
ws.AutoFilter = filter
|
||||
if formatSet.Column == "" || formatSet.Expression == "" {
|
||||
return nil
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ func (f *File) autoFilter(sheet, ref string, refRange, col int, formatSet *forma
|
|||
return err
|
||||
}
|
||||
f.writeAutoFilter(filter, expressions, tokens)
|
||||
xlsx.AutoFilter = filter
|
||||
ws.AutoFilter = filter
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue