已验证 提交 156bf6d1 编写于 作者: xurime's avatar xurime

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
上级 3ee3c38f
...@@ -200,12 +200,12 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error { ...@@ -200,12 +200,12 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return err return err
} }
ws.Lock() ws.Lock()
cellData.S = f.prepareCellStyle(ws, col, cellData.S) cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
ws.Unlock() ws.Unlock()
var isNum bool var isNum bool
...@@ -214,10 +214,7 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error { ...@@ -214,10 +214,7 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
return err return err
} }
if isNum { if isNum {
err = f.setDefaultTimeStyle(sheet, axis, 22) _ = f.setDefaultTimeStyle(sheet, axis, 22)
if err != nil {
return err
}
} }
return err return err
} }
...@@ -254,13 +251,13 @@ func (f *File) SetCellInt(sheet, axis string, value int) error { ...@@ -254,13 +251,13 @@ func (f *File) SetCellInt(sheet, axis string, value int) error {
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return err return err
} }
ws.Lock() ws.Lock()
defer ws.Unlock() 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) cellData.T, cellData.V = setCellInt(value)
return err return err
} }
...@@ -279,13 +276,13 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error { ...@@ -279,13 +276,13 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error {
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return err return err
} }
ws.Lock() ws.Lock()
defer ws.Unlock() 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) cellData.T, cellData.V = setCellBool(value)
return err return err
} }
...@@ -316,13 +313,13 @@ func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int ...@@ -316,13 +313,13 @@ func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return err return err
} }
ws.Lock() ws.Lock()
defer ws.Unlock() 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) cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
return err return err
} }
...@@ -341,13 +338,13 @@ func (f *File) SetCellStr(sheet, axis, value string) error { ...@@ -341,13 +338,13 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return err return err
} }
ws.Lock() ws.Lock()
defer ws.Unlock() 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) cellData.T, cellData.V, err = f.setCellString(value)
return err return err
} }
...@@ -439,13 +436,13 @@ func (f *File) SetCellDefault(sheet, axis, value string) error { ...@@ -439,13 +436,13 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return err return err
} }
ws.Lock() ws.Lock()
defer ws.Unlock() 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) cellData.T, cellData.V = setCellDefault(value)
return err return err
} }
...@@ -937,14 +934,14 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error { ...@@ -937,14 +934,14 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
if err != nil { if err != nil {
return err return err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, cell) cellData, col, row, err := f.prepareCell(ws, sheet, cell)
if err != nil { if err != nil {
return err return err
} }
if err := f.sharedStringsLoader(); err != nil { if err := f.sharedStringsLoader(); err != nil {
return err return err
} }
cellData.S = f.prepareCellStyle(ws, col, cellData.S) cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
si := xlsxSI{} si := xlsxSI{}
sst := f.sharedStringsReader() sst := f.sharedStringsReader()
textRuns := []xlsxR{} textRuns := []xlsxR{}
...@@ -1133,13 +1130,18 @@ func isTimeNumFmt(format string) bool { ...@@ -1133,13 +1130,18 @@ func isTimeNumFmt(format string) bool {
// prepareCellStyle provides a function to prepare style index of cell in // prepareCellStyle provides a function to prepare style index of cell in
// worksheet by given column index and style index. // 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 { if ws.Cols != nil && style == 0 {
for _, c := range ws.Cols.Col { for _, c := range ws.Cols.Col {
if c.Min <= col && col <= c.Max { if c.Min <= col && col <= c.Max && c.Style != 0 {
style = c.Style return c.Style
}
} }
} }
for rowIdx := range ws.SheetData.Row {
if styleID := ws.SheetData.Row[rowIdx].S; style == 0 && styleID != 0 {
return styleID
}
} }
return style return style
} }
...@@ -1150,6 +1152,11 @@ func (f *File) mergeCellsParser(ws *xlsxWorksheet, axis string) (string, error) ...@@ -1150,6 +1152,11 @@ func (f *File) mergeCellsParser(ws *xlsxWorksheet, axis string) (string, error)
axis = strings.ToUpper(axis) axis = strings.ToUpper(axis)
if ws.MergeCells != nil { if ws.MergeCells != nil {
for i := 0; i < len(ws.MergeCells.Cells); i++ { 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) ok, err := f.checkCellInArea(axis, ws.MergeCells.Cells[i].Ref)
if err != nil { if err != nil {
return axis, err return axis, err
...@@ -1170,8 +1177,7 @@ func (f *File) checkCellInArea(cell, area string) (bool, error) { ...@@ -1170,8 +1177,7 @@ func (f *File) checkCellInArea(cell, area string) (bool, error) {
return false, err return false, err
} }
rng := strings.Split(area, ":") if rng := strings.Split(area, ":"); len(rng) != 2 {
if len(rng) != 2 {
return false, err return false, err
} }
coordinates, err := areaRefToCoordinates(area) coordinates, err := areaRefToCoordinates(area)
......
...@@ -592,9 +592,8 @@ func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, heigh ...@@ -592,9 +592,8 @@ func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, heigh
row++ row++
} }
// Initialise end cell to the same as the start cell. // Initialized end cell to the same as the start cell.
colEnd := col colEnd, rowEnd := col, row
rowEnd := row
width += x1 width += x1
height += y1 height += y1
...@@ -632,7 +631,7 @@ func (f *File) getColWidth(sheet string, col int) int { ...@@ -632,7 +631,7 @@ func (f *File) getColWidth(sheet string, col int) int {
return int(convertColWidthToPixels(width)) 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) return int(defaultColWidthPixels)
} }
...@@ -658,7 +657,7 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) { ...@@ -658,7 +657,7 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) {
return width, err return width, err
} }
} }
// Optimisation for when the column widths haven't changed. // Optimization for when the column widths haven't changed.
return defaultColWidth, err return defaultColWidth, err
} }
...@@ -707,7 +706,7 @@ func (f *File) RemoveCol(sheet, col string) error { ...@@ -707,7 +706,7 @@ func (f *File) RemoveCol(sheet, col string) error {
return f.adjustHelper(sheet, columns, num, -1) 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 // 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. // 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. // If the column is hidden it has a value of zero.
......
...@@ -289,18 +289,24 @@ func TestOutlineLevel(t *testing.T) { ...@@ -289,18 +289,24 @@ func TestOutlineLevel(t *testing.T) {
func TestSetColStyle(t *testing.T) { func TestSetColStyle(t *testing.T) {
f := NewFile() f := NewFile()
assert.NoError(t, f.SetCellValue("Sheet1", "B2", "Hello")) 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) assert.NoError(t, err)
// Test set column style on not exists worksheet. // 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. // Test set column style with illegal cell coordinates.
assert.EqualError(t, f.SetColStyle("Sheet1", "*", style), newInvalidColumnNameError("*").Error()) assert.EqualError(t, f.SetColStyle("Sheet1", "*", styleID), newInvalidColumnNameError("*").Error())
assert.EqualError(t, f.SetColStyle("Sheet1", "A:*", style), 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. // Test set column style with already exists column with style.
assert.NoError(t, f.SetColStyle("Sheet1", "B", style)) assert.NoError(t, f.SetColStyle("Sheet1", "B", styleID))
assert.NoError(t, f.SetColStyle("Sheet1", "D:C", style)) 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"))) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetColStyle.xlsx")))
} }
......
...@@ -147,6 +147,7 @@ func TestOpenFile(t *testing.T) { ...@@ -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()))
assert.NoError(t, f.SetCellValue("Sheet2", "G4", time.Now().UTC())) 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 // 02:46:40
assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13))) assert.NoError(t, f.SetCellValue("Sheet2", "G5", time.Duration(1e13)))
// Test completion column. // Test completion column.
......
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
package excelize package excelize
import "strings" import (
"strings"
)
// Rect gets merged cell rectangle coordinates sequence. // Rect gets merged cell rectangle coordinates sequence.
func (mc *xlsxMergeCell) Rect() ([]int, error) { func (mc *xlsxMergeCell) Rect() ([]int, error) {
...@@ -68,7 +70,8 @@ func (f *File) MergeCell(sheet, hCell, vCell string) 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 = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ref, rect: rect}}}
} }
ws.MergeCells.Count = len(ws.MergeCells.Cells) 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. // UnmergeCell provides a function to unmerge a given coordinate area.
......
...@@ -921,6 +921,9 @@ func TestSetRowStyle(t *testing.T) { ...@@ -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("Sheet1", 1, 1, -1), newInvalidStyleID(-1).Error())
assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, styleID), "sheet SheetN is not exist") assert.EqualError(t, f.SetRowStyle("SheetN", 1, 1, styleID), "sheet SheetN is not exist")
assert.NoError(t, f.SetRowStyle("Sheet1", 10, 1, styleID)) 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"))) assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRowStyle.xlsx")))
} }
......
...@@ -2613,11 +2613,11 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) { ...@@ -2613,11 +2613,11 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
cellData, col, _, err := f.prepareCell(ws, sheet, axis) cellData, col, row, err := f.prepareCell(ws, sheet, axis)
if err != nil { if err != nil {
return 0, err 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 // SetCellStyle provides a function to add style attribute for cells by given
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册