Support concurrency add picture

v2
xuri 4 years ago
parent 544ef18a8c
commit b7fece5173
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7

@ -56,6 +56,8 @@ func (f *File) deleteCalcChain(index int, axis string) {
f.CalcChain = nil
f.Pkg.Delete("xl/calcChain.xml")
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
for k, v := range content.Overrides {
if v.PartName == "/xl/calcChain.xml" {
content.Overrides = append(content.Overrides[:k], content.Overrides[k+1:]...)

@ -10,6 +10,8 @@ import (
"testing"
"time"
_ "image/jpeg"
"github.com/stretchr/testify/assert"
)
@ -25,6 +27,9 @@ func TestConcurrency(t *testing.T) {
assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("B%d", val), strconv.Itoa(val)))
_, err := f.GetCellValue("Sheet1", fmt.Sprintf("A%d", val))
assert.NoError(t, err)
// 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"}`))
// Concurrency get cell picture
name, raw, err := f.GetPicture("Sheet1", "A1")
assert.Equal(t, "", name)

@ -76,6 +76,8 @@ func (f *File) GetComments() (comments map[string][]Comment) {
func (f *File) getSheetComments(sheetFile string) string {
var rels = "xl/worksheets/_rels/" + sheetFile + ".rels"
if sheetRels := f.relsReader(rels); sheetRels != nil {
sheetRels.Lock()
defer sheetRels.Unlock()
for _, v := range sheetRels.Relationships {
if v.Type == SourceRelationshipComments {
return v.Target

@ -1173,8 +1173,13 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
}
f.Drawings.Store(path, &content)
}
wsDr, _ := f.Drawings.Load(path)
return wsDr.(*xlsxWsDr), len(wsDr.(*xlsxWsDr).OneCellAnchor) + len(wsDr.(*xlsxWsDr).TwoCellAnchor) + 2
var wsDr *xlsxWsDr
if drawing, ok := f.Drawings.Load(path); ok && drawing != nil {
wsDr = drawing.(*xlsxWsDr)
}
wsDr.Lock()
defer wsDr.Unlock()
return wsDr, len(wsDr.OneCellAnchor) + len(wsDr.TwoCellAnchor) + 2
}
// addDrawingChart provides a function to add chart graphic frame by given

@ -43,7 +43,7 @@ type File struct {
Path string
SharedStrings *xlsxSST
sharedStringsMap map[string]int
Sheet sync.Map // map[string]*xlsxWorksheet
Sheet sync.Map
SheetCount int
Styles *xlsxStyleSheet
Theme *xlsxTheme
@ -257,6 +257,8 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int {
if rels == nil {
rels = &xlsxRelationships{}
}
rels.Lock()
defer rels.Unlock()
var rID int
for idx, rel := range rels.Relationships {
ID, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId"))
@ -357,6 +359,8 @@ func (f *File) AddVBAProject(bin string) error {
}
f.setContentTypePartVBAProjectExtensions()
wb := f.relsReader(f.getWorkbookRelsPath())
wb.Lock()
defer wb.Unlock()
var rID int
var ok bool
for _, rel := range wb.Relationships {
@ -387,6 +391,8 @@ func (f *File) AddVBAProject(bin string) error {
func (f *File) setContentTypePartVBAProjectExtensions() {
var ok bool
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
for _, v := range content.Defaults {
if v.Extension == "bin" {
ok = true

@ -184,6 +184,8 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
if sheetRels == nil {
sheetRels = &xlsxRelationships{}
}
sheetRels.Lock()
defer sheetRels.Unlock()
for k, v := range sheetRels.Relationships {
if v.ID == rID {
sheetRels.Relationships = append(sheetRels.Relationships[:k], sheetRels.Relationships[k+1:]...)
@ -297,6 +299,8 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
FLocksWithSheet: formatSet.FLocksWithSheet,
FPrintsWithSheet: formatSet.FPrintsWithSheet,
}
content.Lock()
defer content.Unlock()
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
f.Drawings.Store(drawingXML, content)
return err
@ -344,6 +348,8 @@ func (f *File) addMedia(file []byte, ext string) string {
func (f *File) setContentTypePartImageExtensions() {
var imageTypes = map[string]bool{"jpeg": false, "png": false, "gif": false, "tiff": false}
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
for _, v := range content.Defaults {
_, ok := imageTypes[v.Extension]
if ok {
@ -365,6 +371,8 @@ func (f *File) setContentTypePartImageExtensions() {
func (f *File) setContentTypePartVMLExtensions() {
vml := false
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
for _, v := range content.Defaults {
if v.Extension == "vml" {
vml = true
@ -410,6 +418,8 @@ func (f *File) addContentTypePart(index int, contentType string) {
s()
}
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
for _, v := range content.Overrides {
if v.PartName == partNames[contentType] {
return
@ -434,6 +444,8 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
if sheetRels == nil {
sheetRels = &xlsxRelationships{}
}
sheetRels.Lock()
defer sheetRels.Unlock()
for _, v := range sheetRels.Relationships {
if v.ID == rID {
return v.Target
@ -560,6 +572,8 @@ func (f *File) getPictureFromWsDr(row, col int, drawingRelationships string, wsD
anchor *xdrCellAnchor
drawRel *xlsxRelationship
)
wsDr.Lock()
defer wsDr.Unlock()
for _, anchor = range wsDr.TwoCellAnchor {
if anchor.From != nil && anchor.Pic != nil {
if anchor.From.Col == col && anchor.From.Row == row {
@ -584,6 +598,8 @@ func (f *File) getPictureFromWsDr(row, col int, drawingRelationships string, wsD
// relationship ID.
func (f *File) getDrawingRelationships(rels, rID string) *xlsxRelationship {
if drawingRels := f.relsReader(rels); drawingRels != nil {
drawingRels.Lock()
defer drawingRels.Unlock()
for _, v := range drawingRels.Relationships {
if v.ID == rID {
return &v

@ -272,6 +272,8 @@ func (f *File) SetRowHeight(sheet string, row int, height float64) error {
// name and row number.
func (f *File) getRowHeight(sheet string, row int) int {
ws, _ := f.workSheetReader(sheet)
ws.Lock()
defer ws.Unlock()
for i := range ws.SheetData.Row {
v := &ws.SheetData.Row[i]
if v.R == row && v.Ht != 0 {

@ -93,6 +93,8 @@ func (f *File) contentTypesWriter() {
// the spreadsheet.
func (f *File) getWorkbookPath() (path string) {
if rels := f.relsReader("_rels/.rels"); rels != nil {
rels.Lock()
defer rels.Unlock()
for _, rel := range rels.Relationships {
if rel.Type == SourceRelationshipOfficeDocument {
path = strings.TrimPrefix(rel.Target, "/")
@ -198,6 +200,8 @@ func trimCell(column []xlsxC) []xlsxC {
// type of the spreadsheet.
func (f *File) setContentTypes(partName, contentType string) {
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
content.Overrides = append(content.Overrides, xlsxOverride{
PartName: partName,
ContentType: contentType,
@ -540,6 +544,8 @@ func (f *File) DeleteSheet(name string) {
// relationships by given relationships ID in the file workbook.xml.rels.
func (f *File) deleteSheetFromWorkbookRels(rID string) string {
content := f.relsReader(f.getWorkbookRelsPath())
content.Lock()
defer content.Unlock()
for k, v := range content.Relationships {
if v.ID == rID {
content.Relationships = append(content.Relationships[:k], content.Relationships[k+1:]...)
@ -556,6 +562,8 @@ func (f *File) deleteSheetFromContentTypes(target string) {
target = "/xl/" + target
}
content := f.contentTypesReader()
content.Lock()
defer content.Unlock()
for k, v := range content.Overrides {
if v.PartName == target {
content.Overrides = append(content.Overrides[:k], content.Overrides[k+1:]...)

@ -11,12 +11,16 @@
package excelize
import "encoding/xml"
import (
"encoding/xml"
"sync"
)
// xlsxTypes directly maps the types element of content types for relationship
// parts, it takes a Multipurpose Internet Mail Extension (MIME) media type as a
// value.
type xlsxTypes struct {
sync.Mutex
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/content-types Types"`
Overrides []xlsxOverride `xml:"Override"`
Defaults []xlsxDefault `xml:"Default"`

@ -11,7 +11,10 @@
package excelize
import "encoding/xml"
import (
"encoding/xml"
"sync"
)
// Source relationship and namespace list, associated prefixes and schema in which it was
// introduced.
@ -303,6 +306,7 @@ type xlsxPoint2D struct {
// xlsxWsDr directly maps the root element for a part of this content type shall
// wsDr.
type xlsxWsDr struct {
sync.Mutex
XMLName xml.Name `xml:"xdr:wsDr"`
AbsoluteAnchor []*xdrCellAnchor `xml:"xdr:absoluteAnchor"`
OneCellAnchor []*xdrCellAnchor `xml:"xdr:oneCellAnchor"`

@ -11,10 +11,14 @@
package excelize
import "encoding/xml"
import (
"encoding/xml"
"sync"
)
// xlsxRelationships describe references from parts to other internal resources in the package or to external resources.
type xlsxRelationships struct {
sync.Mutex
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/relationships Relationships"`
Relationships []xlsxRelationship `xml:"Relationship"`
}

Loading…
Cancel
Save