forked from p30928647/excelize
Compatible with Go 1.15, fix unit test failed on Windows and fixed #689 potential race condition
This commit is contained in:
parent
cb6f8852bb
commit
c3e92a51d7
|
@ -21,7 +21,7 @@ env:
|
|||
|
||||
script:
|
||||
- env GO111MODULE=on go vet ./...
|
||||
- env GO111MODULE=on go test ./... -v -coverprofile=coverage.txt -covermode=atomic
|
||||
- env GO111MODULE=on go test -v -race ./... -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
|
20
cell.go
20
cell.go
|
@ -18,7 +18,6 @@ import (
|
|||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -33,8 +32,6 @@ const (
|
|||
STCellFormulaTypeShared = "shared"
|
||||
)
|
||||
|
||||
var rwMutex sync.RWMutex
|
||||
|
||||
// GetCellValue provides a function to get formatted value from cell by given
|
||||
// worksheet name and axis in XLSX file. If it is possible to apply a format
|
||||
// to the cell value, it will do so, if not then an error will be returned,
|
||||
|
@ -181,8 +178,6 @@ 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 {
|
||||
rwMutex.Lock()
|
||||
defer rwMutex.Unlock()
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -204,8 +199,6 @@ 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 {
|
||||
rwMutex.Lock()
|
||||
defer rwMutex.Unlock()
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -239,8 +232,6 @@ 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 {
|
||||
rwMutex.Lock()
|
||||
defer rwMutex.Unlock()
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -262,8 +253,6 @@ 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 {
|
||||
rwMutex.Lock()
|
||||
defer rwMutex.Unlock()
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -291,6 +280,8 @@ func (f *File) setCellString(value string) (t string, v string) {
|
|||
// setSharedString provides a function to add string to the share string table.
|
||||
func (f *File) setSharedString(val string) int {
|
||||
sst := f.sharedStringsReader()
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if i, ok := f.sharedStringsMap[val]; ok {
|
||||
return i
|
||||
}
|
||||
|
@ -371,8 +362,6 @@ 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 {
|
||||
rwMutex.Lock()
|
||||
defer rwMutex.Unlock()
|
||||
xlsx, err := f.workSheetReader(sheet)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -697,6 +686,8 @@ 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()
|
||||
var err error
|
||||
cell, err = f.mergeCellsParser(xlsx, cell)
|
||||
if err != nil {
|
||||
|
@ -728,6 +719,9 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
|
|||
return "", err
|
||||
}
|
||||
|
||||
xlsx.Lock()
|
||||
defer xlsx.Unlock()
|
||||
|
||||
lastRowNum := 0
|
||||
if l := len(xlsx.SheetData.Row); l > 0 {
|
||||
lastRowNum = xlsx.SheetData.Row[l-1].R
|
||||
|
|
21
cell_test.go
21
cell_test.go
|
@ -4,12 +4,33 @@ import (
|
|||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConcurrency(t *testing.T) {
|
||||
f := NewFile()
|
||||
wg := new(sync.WaitGroup)
|
||||
for i := 1; i <= 5; i++ {
|
||||
wg.Add(1)
|
||||
go func(val int) {
|
||||
f.SetCellValue("Sheet1", fmt.Sprintf("A%d", val), val)
|
||||
f.SetCellValue("Sheet1", fmt.Sprintf("B%d", val), strconv.Itoa(val))
|
||||
f.GetCellValue("Sheet1", fmt.Sprintf("A%d", val))
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
val, err := f.GetCellValue("Sheet1", "A1")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
assert.Equal(t, "1", val)
|
||||
}
|
||||
|
||||
func TestCheckCellInArea(t *testing.T) {
|
||||
f := NewFile()
|
||||
expectedTrueCellInAreaList := [][2]string{
|
||||
|
|
|
@ -24,12 +24,14 @@ import (
|
|||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/html/charset"
|
||||
)
|
||||
|
||||
// File define a populated spreadsheet file struct.
|
||||
type File struct {
|
||||
sync.RWMutex
|
||||
xmlAttr map[string][]xml.Attr
|
||||
checked map[string]bool
|
||||
sheetMap map[string]string
|
||||
|
@ -153,6 +155,8 @@ 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) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
var (
|
||||
name string
|
||||
ok bool
|
||||
|
@ -323,7 +327,7 @@ func (f *File) AddVBAProject(bin string) error {
|
|||
var err error
|
||||
// Check vbaProject.bin exists first.
|
||||
if _, err = os.Stat(bin); os.IsNotExist(err) {
|
||||
return err
|
||||
return fmt.Errorf("stat %s: no such file or directory", bin)
|
||||
}
|
||||
if path.Ext(bin) != ".bin" {
|
||||
return errors.New("unsupported VBA project extension")
|
||||
|
|
2
lib.go
2
lib.go
|
@ -167,7 +167,7 @@ func ColumnNumberToName(num int) (string, error) {
|
|||
}
|
||||
var col string
|
||||
for num > 0 {
|
||||
col = string((num-1)%26+65) + col
|
||||
col = string(rune((num-1)%26+65)) + col
|
||||
num = (num - 1) / 26
|
||||
}
|
||||
return col, nil
|
||||
|
|
4
rows.go
4
rows.go
|
@ -284,6 +284,8 @@ func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
|
|||
func (f *File) sharedStringsReader() *xlsxSST {
|
||||
var err error
|
||||
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if f.SharedStrings == nil {
|
||||
var sharedStrings xlsxSST
|
||||
ss := f.readXML("xl/sharedStrings.xml")
|
||||
|
@ -318,6 +320,8 @@ func (f *File) sharedStringsReader() *xlsxSST {
|
|||
// 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) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
switch xlsx.T {
|
||||
case "s":
|
||||
if xlsx.V != "" {
|
||||
|
|
|
@ -91,6 +91,7 @@ func TestStreamWriter(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
_, err = streamWriter.rawData.Reader()
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, streamWriter.rawData.tmp.Close())
|
||||
assert.NoError(t, os.Remove(streamWriter.rawData.tmp.Name()))
|
||||
|
||||
// Test unsupport charset
|
||||
|
|
|
@ -11,11 +11,15 @@
|
|||
|
||||
package excelize
|
||||
|
||||
import "encoding/xml"
|
||||
import (
|
||||
"encoding/xml"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// xlsxWorksheet directly maps the worksheet element in the namespace
|
||||
// http://schemas.openxmlformats.org/spreadsheetml/2006/main.
|
||||
type xlsxWorksheet struct {
|
||||
sync.RWMutex
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main worksheet"`
|
||||
SheetPr *xlsxSheetPr `xml:"sheetPr"`
|
||||
Dimension *xlsxDimension `xml:"dimension"`
|
||||
|
|
Loading…
Reference in New Issue