Fix #724, standardize variable naming and update unit tests

This commit is contained in:
xuri 2020-11-10 23:48:09 +08:00
parent 5dd0b4aec2
commit 2514bb16c6
27 changed files with 439 additions and 437 deletions

View File

@ -13,6 +13,7 @@ go:
os:
- linux
- osx
- windows
env:
jobs:

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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
View File

@ -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

View File

@ -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)

View File

@ -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
View File

@ -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 {

View File

@ -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 {

View File

@ -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)},

View File

@ -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

View File

@ -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,

View File

@ -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"))

View File

@ -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 {

View File

@ -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)

View File

@ -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})

View File

@ -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
View File

@ -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
}
}
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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,
})

View File

@ -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")))
}

View File

@ -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
}