This closes #1129, make cell support inheritance columns/rows style
Correct cells style in merge range Fix incorrect style ID returned on getting cell style in some cases Unit test updated and simplified code
This commit is contained in:
parent
3ee3c38f9c
commit
156bf6d16e
52
cell.go
52
cell.go
|
@ -200,12 +200,12 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
ws.Unlock()
|
||||
|
||||
var isNum bool
|
||||
|
@ -214,10 +214,7 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
|||
return err
|
||||
}
|
||||
if isNum {
|
||||
err = f.setDefaultTimeStyle(sheet, axis, 22)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = f.setDefaultTimeStyle(sheet, axis, 22)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -254,13 +251,13 @@ func (f *File) SetCellInt(sheet, axis string, value int) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
cellData.T, cellData.V = setCellInt(value)
|
||||
return err
|
||||
}
|
||||
|
@ -279,13 +276,13 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
cellData.T, cellData.V = setCellBool(value)
|
||||
return err
|
||||
}
|
||||
|
@ -316,13 +313,13 @@ func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
|
||||
return err
|
||||
}
|
||||
|
@ -341,13 +338,13 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
cellData.T, cellData.V, err = f.setCellString(value)
|
||||
return err
|
||||
}
|
||||
|
@ -439,13 +436,13 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
cellData.T, cellData.V = setCellDefault(value)
|
||||
return err
|
||||
}
|
||||
|
@ -937,14 +934,14 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, cell)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, cell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.sharedStringsLoader(); err != nil {
|
||||
return err
|
||||
}
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
|
||||
si := xlsxSI{}
|
||||
sst := f.sharedStringsReader()
|
||||
textRuns := []xlsxR{}
|
||||
|
@ -1133,14 +1130,19 @@ func isTimeNumFmt(format string) bool {
|
|||
|
||||
// prepareCellStyle provides a function to prepare style index of cell in
|
||||
// worksheet by given column index and style index.
|
||||
func (f *File) prepareCellStyle(ws *xlsxWorksheet, col, style int) int {
|
||||
func (f *File) prepareCellStyle(ws *xlsxWorksheet, col, row, 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
|
||||
if c.Min <= col && col <= c.Max && c.Style != 0 {
|
||||
return c.Style
|
||||
}
|
||||
}
|
||||
}
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
if styleID := ws.SheetData.Row[rowIdx].S; style == 0 && styleID != 0 {
|
||||
return styleID
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
|
@ -1150,6 +1152,11 @@ func (f *File) mergeCellsParser(ws *xlsxWorksheet, axis string) (string, error)
|
|||
axis = strings.ToUpper(axis)
|
||||
if ws.MergeCells != nil {
|
||||
for i := 0; i < len(ws.MergeCells.Cells); i++ {
|
||||
if ws.MergeCells.Cells[i] == nil {
|
||||
ws.MergeCells.Cells = append(ws.MergeCells.Cells[:i], ws.MergeCells.Cells[i+1:]...)
|
||||
i--
|
||||
continue
|
||||
}
|
||||
ok, err := f.checkCellInArea(axis, ws.MergeCells.Cells[i].Ref)
|
||||
if err != nil {
|
||||
return axis, err
|
||||
|
@ -1170,8 +1177,7 @@ func (f *File) checkCellInArea(cell, area string) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
rng := strings.Split(area, ":")
|
||||
if len(rng) != 2 {
|
||||
if rng := strings.Split(area, ":"); len(rng) != 2 {
|
||||
return false, err
|
||||
}
|
||||
coordinates, err := areaRefToCoordinates(area)
|
||||
|
|
11
col.go
11
col.go
|
@ -592,9 +592,8 @@ func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, heigh
|
|||
row++
|
||||
}
|
||||
|
||||
// Initialise end cell to the same as the start cell.
|
||||
colEnd := col
|
||||
rowEnd := row
|
||||
// Initialized end cell to the same as the start cell.
|
||||
colEnd, rowEnd := col, row
|
||||
|
||||
width += x1
|
||||
height += y1
|
||||
|
@ -632,7 +631,7 @@ func (f *File) getColWidth(sheet string, col int) int {
|
|||
return int(convertColWidthToPixels(width))
|
||||
}
|
||||
}
|
||||
// Optimisation for when the column widths haven't changed.
|
||||
// Optimization for when the column widths haven't changed.
|
||||
return int(defaultColWidthPixels)
|
||||
}
|
||||
|
||||
|
@ -658,7 +657,7 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) {
|
|||
return width, err
|
||||
}
|
||||
}
|
||||
// Optimisation for when the column widths haven't changed.
|
||||
// Optimization for when the column widths haven't changed.
|
||||
return defaultColWidth, err
|
||||
}
|
||||
|
||||
|
@ -707,7 +706,7 @@ func (f *File) RemoveCol(sheet, col string) error {
|
|||
return f.adjustHelper(sheet, columns, num, -1)
|
||||
}
|
||||
|
||||
// convertColWidthToPixels provieds function to convert the width of a cell
|
||||
// convertColWidthToPixels provides function to convert the width of a cell
|
||||
// from user's units to pixels. Excel rounds the column width to the nearest
|
||||
// pixel. If the width hasn't been set by the user we use the default value.
|
||||
// If the column is hidden it has a value of zero.
|
||||
|
|
20
col_test.go
20
col_test.go
|
@ -289,18 +289,24 @@ func TestOutlineLevel(t *testing.T) {
|
|||
func TestSetColStyle(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", "B2", "Hello"))
|
||||
style, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#94d3a2"],"pattern":1}}`)
|
||||
styleID, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#94d3a2"],"pattern":1}}`)
|
||||
assert.NoError(t, err)
|
||||
// Test set column style on not exists worksheet.
|
||||
assert.EqualError(t, f.SetColStyle("SheetN", "E", style), "sheet SheetN is not exist")
|
||||
assert.EqualError(t, f.SetColStyle("SheetN", "E", styleID), "sheet SheetN is not exist")
|
||||
// Test set column style with illegal cell coordinates.
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "*", style), newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "A:*", style), newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "*", styleID), newInvalidColumnNameError("*").Error())
|
||||
assert.EqualError(t, f.SetColStyle("Sheet1", "A:*", styleID), newInvalidColumnNameError("*").Error())
|
||||
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "B", style))
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "B", styleID))
|
||||
// Test set column style with already exists column with style.
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "B", style))
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "D:C", style))
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "B", styleID))
|
||||
assert.NoError(t, f.SetColStyle("Sheet1", "D:C", styleID))
|
||||
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||
assert.True(t, ok)
|
||||
ws.(*xlsxWorksheet).SheetData.Row[1].C[2].S = 0
|
||||
cellStyleID, err := f.GetCellStyle("Sheet1", "C2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, styleID, cellStyleID)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetColStyle.xlsx")))
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ func TestOpenFile(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now()))
|
||||
|
||||
assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now().UTC()))
|
||||
assert.EqualError(t, f.SetCellValue("SheetN", "A1", time.Now()), "sheet SheetN is not exist")
|
||||
// 02:46:40
|
||||
assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13)))
|
||||
// Test completion column.
|
||||
|
|
7
merge.go
7
merge.go
|
@ -11,7 +11,9 @@
|
|||
|
||||
package excelize
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Rect gets merged cell rectangle coordinates sequence.
|
||||
func (mc *xlsxMergeCell) Rect() ([]int, error) {
|
||||
|
@ -68,7 +70,8 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error {
|
|||
ws.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ref, rect: rect}}}
|
||||
}
|
||||
ws.MergeCells.Count = len(ws.MergeCells.Cells)
|
||||
return err
|
||||
styleID, _ := f.GetCellStyle(sheet, hCell)
|
||||
return f.SetCellStyle(sheet, hCell, vCell, styleID)
|
||||
}
|
||||
|
||||
// UnmergeCell provides a function to unmerge a given coordinate area.
|
||||
|
|
|
@ -921,6 +921,9 @@ func TestSetRowStyle(t *testing.T) {
|
|||
assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, -1), newInvalidStyleID(-1).Error())
|
||||
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, styleID), "sheet SheetN is not exist")
|
||||
assert.NoError(t, f.SetRowStyle("Sheet1", 10, 1, styleID))
|
||||
cellStyleID, err := f.GetCellStyle("Sheet1", "B2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, styleID, cellStyleID)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRowStyle.xlsx")))
|
||||
}
|
||||
|
||||
|
|
|
@ -2613,11 +2613,11 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
|
|||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cellData, col, _, err := f.prepareCell(ws, sheet, axis)
|
||||
cellData, col, row, err := f.prepareCell(ws, sheet, axis)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f.prepareCellStyle(ws, col, cellData.S), err
|
||||
return f.prepareCellStyle(ws, col, row, cellData.S), err
|
||||
}
|
||||
|
||||
// SetCellStyle provides a function to add style attribute for cells by given
|
||||
|
|
Loading…
Reference in New Issue