forked from p30928647/excelize
Make the functions `SetSheetRow`, `New Style` and `SetCellStyle` concurrency safety
This commit is contained in:
parent
b7fece5173
commit
90d200a10b
20
cell.go
20
cell.go
|
@ -139,7 +139,9 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
ws.Unlock()
|
||||
|
||||
var isNum bool
|
||||
cellData.T, cellData.V, isNum, err = setCellTime(value)
|
||||
|
@ -155,6 +157,8 @@ func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// setCellTime prepares cell type and Excel time by given Go time.Time type
|
||||
// timestamp.
|
||||
func setCellTime(value time.Time) (t string, b string, isNum bool, err error) {
|
||||
var excelTime float64
|
||||
excelTime, err = timeToExcelTime(value)
|
||||
|
@ -170,6 +174,8 @@ func setCellTime(value time.Time) (t string, b string, isNum bool, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// setCellDuration prepares cell type and value by given Go time.Duration type
|
||||
// time duration.
|
||||
func setCellDuration(value time.Duration) (t string, v string) {
|
||||
v = strconv.FormatFloat(value.Seconds()/86400.0, 'f', -1, 32)
|
||||
return
|
||||
|
@ -193,6 +199,8 @@ func (f *File) SetCellInt(sheet, axis string, value int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// setCellInt prepares cell type and string type cell value by a given
|
||||
// integer.
|
||||
func setCellInt(value int) (t string, v string) {
|
||||
v = strconv.Itoa(value)
|
||||
return
|
||||
|
@ -209,11 +217,15 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellBool(value)
|
||||
return err
|
||||
}
|
||||
|
||||
// setCellBool prepares cell type and string type cell value by a given
|
||||
// boolean value.
|
||||
func setCellBool(value bool) (t string, v string) {
|
||||
t = "b"
|
||||
if value {
|
||||
|
@ -242,11 +254,15 @@ func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellFloat(value, prec, bitSize)
|
||||
return err
|
||||
}
|
||||
|
||||
// setCellFloat prepares cell type and string type cell value by a given
|
||||
// float value.
|
||||
func setCellFloat(value float64, prec, bitSize int) (t string, v string) {
|
||||
v = strconv.FormatFloat(value, 'f', prec, bitSize)
|
||||
return
|
||||
|
@ -334,11 +350,15 @@ func (f *File) SetCellDefault(sheet, axis, value string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
cellData.S = f.prepareCellStyle(ws, col, cellData.S)
|
||||
cellData.T, cellData.V = setCellDefault(value)
|
||||
return err
|
||||
}
|
||||
|
||||
// setCellDefault prepares cell type and string type cell value by a given
|
||||
// string.
|
||||
func setCellDefault(value string) (t string, v string) {
|
||||
v = value
|
||||
return
|
||||
|
|
13
cell_test.go
13
cell_test.go
|
@ -25,8 +25,20 @@ func TestConcurrency(t *testing.T) {
|
|||
// Concurrency set cell value
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("A%d", val), val))
|
||||
assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("B%d", val), strconv.Itoa(val)))
|
||||
// Concurrency get cell value
|
||||
_, err := f.GetCellValue("Sheet1", fmt.Sprintf("A%d", val))
|
||||
assert.NoError(t, err)
|
||||
// Concurrency set rows
|
||||
assert.NoError(t, f.SetSheetRow("Sheet1", "B6", &[]interface{}{" Hello",
|
||||
[]byte("World"), 42, int8(1<<8/2 - 1), int16(1<<16/2 - 1), int32(1<<32/2 - 1),
|
||||
int64(1<<32/2 - 1), float32(42.65418), float64(-42.65418), float32(42), float64(42),
|
||||
uint(1<<32 - 1), uint8(1<<8 - 1), uint16(1<<16 - 1), uint32(1<<32 - 1),
|
||||
uint64(1<<32 - 1), true, complex64(5 + 10i)}))
|
||||
// Concurrency create style
|
||||
style, err := f.NewStyle(`{"font":{"color":"#1265BE","underline":"single"}}`)
|
||||
assert.NoError(t, err)
|
||||
// Concurrency set cell style
|
||||
assert.NoError(t, f.SetCellStyle("Sheet1", "A3", "A3", style))
|
||||
// Concurrency add picture
|
||||
assert.NoError(t, f.AddPicture("Sheet1", "F21", filepath.Join("test", "images", "excel.jpg"),
|
||||
`{"x_offset": 10, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "positioning": "oneCell"}`))
|
||||
|
@ -59,6 +71,7 @@ func TestConcurrency(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, "1", val)
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestConcurrency.xlsx")))
|
||||
}
|
||||
|
||||
func TestCheckCellInArea(t *testing.T) {
|
||||
|
|
2
sheet.go
2
sheet.go
|
@ -1777,6 +1777,8 @@ func fillColumns(rowData *xlsxRow, col, row int) {
|
|||
|
||||
// makeContiguousColumns make columns in specific rows as contiguous.
|
||||
func makeContiguousColumns(ws *xlsxWorksheet, fromRow, toRow, colCount int) {
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
for ; fromRow < toRow; fromRow++ {
|
||||
rowData := &ws.SheetData.Row[fromRow-1]
|
||||
fillColumns(rowData, colCount, fromRow)
|
||||
|
|
|
@ -1990,6 +1990,8 @@ func (f *File) NewStyle(style interface{}) (int, error) {
|
|||
fs.DecimalPlaces = 2
|
||||
}
|
||||
s := f.stylesReader()
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
// check given style already exist.
|
||||
if cellXfsID = f.getStyleID(s, fs); cellXfsID != -1 {
|
||||
return cellXfsID, err
|
||||
|
@ -2693,7 +2695,8 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
|
|||
}
|
||||
prepareSheetXML(ws, vcol, vrow)
|
||||
makeContiguousColumns(ws, hrow, vrow, vcol)
|
||||
|
||||
ws.Lock()
|
||||
defer ws.Unlock()
|
||||
for r := hrowIdx; r <= vrowIdx; r++ {
|
||||
for k := hcolIdx; k <= vcolIdx; k++ {
|
||||
ws.SheetData.Row[r].C[k].S = styleID
|
||||
|
|
|
@ -11,10 +11,14 @@
|
|||
|
||||
package excelize
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// xlsxStyleSheet is the root element of the Styles part.
|
||||
type xlsxStyleSheet struct {
|
||||
sync.Mutex
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main styleSheet"`
|
||||
NumFmts *xlsxNumFmts `xml:"numFmts,omitempty"`
|
||||
Fonts *xlsxFonts `xml:"fonts,omitempty"`
|
||||
|
|
Loading…
Reference in New Issue