Resolve #235, performance optimization for add comments (#347)

formula
BluesJhao 6 years ago committed by xuri
parent c223815cfe
commit 1427027e38

@ -122,31 +122,34 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, cell)) row, _ := strconv.Atoi(strings.Map(intOnlyMapF, cell))
xAxis := row - 1 xAxis := row - 1
yAxis := TitleToNumber(col) yAxis := TitleToNumber(col)
vml := vmlDrawing{ vml := f.VMLDrawing[drawingVML]
XMLNSv: "urn:schemas-microsoft-com:vml", if vml == nil {
XMLNSo: "urn:schemas-microsoft-com:office:office", vml = &vmlDrawing{
XMLNSx: "urn:schemas-microsoft-com:office:excel", XMLNSv: "urn:schemas-microsoft-com:vml",
XMLNSmv: "http://macVmlSchemaUri", XMLNSo: "urn:schemas-microsoft-com:office:office",
Shapelayout: &xlsxShapelayout{ XMLNSx: "urn:schemas-microsoft-com:office:excel",
Ext: "edit", XMLNSmv: "http://macVmlSchemaUri",
IDmap: &xlsxIDmap{ Shapelayout: &xlsxShapelayout{
Ext: "edit", Ext: "edit",
Data: commentID, IDmap: &xlsxIDmap{
}, Ext: "edit",
}, Data: commentID,
Shapetype: &xlsxShapetype{ },
ID: "_x0000_t202",
Coordsize: "21600,21600",
Spt: 202,
Path: "m0,0l0,21600,21600,21600,21600,0xe",
Stroke: &xlsxStroke{
Joinstyle: "miter",
}, },
VPath: &vPath{ Shapetype: &xlsxShapetype{
Gradientshapeok: "t", ID: "_x0000_t202",
Connecttype: "miter", Coordsize: "21600,21600",
Spt: 202,
Path: "m0,0l0,21600,21600,21600,21600,0xe",
Stroke: &xlsxStroke{
Joinstyle: "miter",
},
VPath: &vPath{
Gradientshapeok: "t",
Connecttype: "miter",
},
}, },
}, }
} }
sp := encodeShape{ sp := encodeShape{
Fill: &vFill{ Fill: &vFill{
@ -191,10 +194,8 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
Strokecolor: "#edeaa1", Strokecolor: "#edeaa1",
Val: string(s[13 : len(s)-14]), Val: string(s[13 : len(s)-14]),
} }
c, ok := f.XLSX[drawingVML] d := f.decodeVMLDrawingReader(drawingVML)
if ok { if d != nil {
d := decodeVmlDrawing{}
_ = xml.Unmarshal(namespaceStrictToTransitional(c), &d)
for _, v := range d.Shape { for _, v := range d.Shape {
s := xlsxShape{ s := xlsxShape{
ID: "_x0000_s1025", ID: "_x0000_s1025",
@ -208,8 +209,7 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
} }
} }
vml.Shape = append(vml.Shape, shape) vml.Shape = append(vml.Shape, shape)
v, _ := xml.Marshal(vml) f.VMLDrawing[drawingVML] = vml
f.XLSX[drawingVML] = v
} }
// addComment provides a function to create chart as xl/comments%d.xml by // addComment provides a function to create chart as xl/comments%d.xml by
@ -223,12 +223,15 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
if len(t) > 32512 { if len(t) > 32512 {
t = t[0:32512] t = t[0:32512]
} }
comments := xlsxComments{ comments := f.commentsReader(commentsXML)
Authors: []xlsxAuthor{ if comments == nil {
{ comments = &xlsxComments{
Author: formatSet.Author, Authors: []xlsxAuthor{
{
Author: formatSet.Author,
},
}, },
}, }
} }
cmt := xlsxComment{ cmt := xlsxComment{
Ref: cell, Ref: cell,
@ -261,15 +264,8 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
}, },
}, },
} }
c, ok := f.XLSX[commentsXML]
if ok {
d := xlsxComments{}
_ = xml.Unmarshal(namespaceStrictToTransitional(c), &d)
comments.CommentList.Comment = append(comments.CommentList.Comment, d.CommentList.Comment...)
}
comments.CommentList.Comment = append(comments.CommentList.Comment, cmt) comments.CommentList.Comment = append(comments.CommentList.Comment, cmt)
v, _ := xml.Marshal(comments) f.Comments[commentsXML] = comments
f.saveFileList(commentsXML, v)
} }
// countComments provides a function to get comments files count storage in // countComments provides a function to get comments files count storage in
@ -283,3 +279,53 @@ func (f *File) countComments() int {
} }
return count return count
} }
// decodeVMLDrawingReader provides a function to get the pointer to the
// structure after deserialization of xl/drawings/vmlDrawing%d.xml.
func (f *File) decodeVMLDrawingReader(path string) *decodeVmlDrawing {
if f.DecodeVMLDrawing[path] == nil {
c, ok := f.XLSX[path]
if ok {
d := decodeVmlDrawing{}
_ = xml.Unmarshal(namespaceStrictToTransitional(c), &d)
f.DecodeVMLDrawing[path] = &d
}
}
return f.DecodeVMLDrawing[path]
}
// vmlDrawingWriter provides a function to save xl/drawings/vmlDrawing%d.xml.
// after serialize structure.
func (f *File) vmlDrawingWriter() {
for path, vml := range f.VMLDrawing {
if vml != nil {
v, _ := xml.Marshal(vml)
f.XLSX[path] = v
}
}
}
// commentsReader provides a function to get the pointer to the structure
// after deserialization of xl/comments%d.xml.
func (f *File) commentsReader(path string) *xlsxComments {
if f.Comments[path] == nil {
content, ok := f.XLSX[path]
if ok {
c := xlsxComments{}
_ = xml.Unmarshal(namespaceStrictToTransitional(content), &c)
f.Comments[path] = &c
}
}
return f.Comments[path]
}
// commentsWriter provides a function to save xl/comments%d.xml after
// serialize structure.
func (f *File) commentsWriter() {
for path, c := range f.Comments {
if c != nil {
v, _ := xml.Marshal(c)
f.saveFileList(path, v)
}
}
}

@ -23,19 +23,22 @@ import (
// File define a populated XLSX file struct. // File define a populated XLSX file struct.
type File struct { type File struct {
checked map[string]bool checked map[string]bool
sheetMap map[string]string sheetMap map[string]string
CalcChain *xlsxCalcChain CalcChain *xlsxCalcChain
ContentTypes *xlsxTypes Comments map[string]*xlsxComments
Path string ContentTypes *xlsxTypes
SharedStrings *xlsxSST Path string
Sheet map[string]*xlsxWorksheet SharedStrings *xlsxSST
SheetCount int Sheet map[string]*xlsxWorksheet
Styles *xlsxStyleSheet SheetCount int
Theme *xlsxTheme Styles *xlsxStyleSheet
WorkBook *xlsxWorkbook Theme *xlsxTheme
WorkBookRels *xlsxWorkbookRels DecodeVMLDrawing map[string]*decodeVmlDrawing
XLSX map[string][]byte VMLDrawing map[string]*vmlDrawing
WorkBook *xlsxWorkbook
WorkBookRels *xlsxWorkbookRels
XLSX map[string][]byte
} }
// OpenFile take the name of an XLSX file and returns a populated XLSX file // OpenFile take the name of an XLSX file and returns a populated XLSX file
@ -71,11 +74,15 @@ func OpenReader(r io.Reader) (*File, error) {
return nil, err return nil, err
} }
f := &File{ f := &File{
checked: make(map[string]bool), checked: make(map[string]bool),
Sheet: make(map[string]*xlsxWorksheet), Comments: make(map[string]*xlsxComments),
SheetCount: sheetCount, Sheet: make(map[string]*xlsxWorksheet),
XLSX: file, SheetCount: sheetCount,
DecodeVMLDrawing: make(map[string]*decodeVmlDrawing),
VMLDrawing: make(map[string]*vmlDrawing),
XLSX: file,
} }
f.CalcChain = f.calcChainReader()
f.sheetMap = f.getSheetMap() f.sheetMap = f.getSheetMap()
f.Styles = f.stylesReader() f.Styles = f.stylesReader()
f.Theme = f.themeReader() f.Theme = f.themeReader()

@ -39,8 +39,12 @@ func NewFile() *File {
SheetCount: 1, SheetCount: 1,
XLSX: file, XLSX: file,
} }
f.CalcChain = f.calcChainReader()
f.Comments = make(map[string]*xlsxComments)
f.ContentTypes = f.contentTypesReader() f.ContentTypes = f.contentTypesReader()
f.Styles = f.stylesReader() f.Styles = f.stylesReader()
f.DecodeVMLDrawing = make(map[string]*decodeVmlDrawing)
f.VMLDrawing = make(map[string]*vmlDrawing)
f.WorkBook = f.workbookReader() f.WorkBook = f.workbookReader()
f.WorkBookRels = f.workbookRelsReader() f.WorkBookRels = f.workbookRelsReader()
f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1") f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1")
@ -87,12 +91,15 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
func (f *File) WriteToBuffer() (*bytes.Buffer, error) { func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
zw := zip.NewWriter(buf) zw := zip.NewWriter(buf)
f.calcChainWriter()
f.commentsWriter()
f.contentTypesWriter() f.contentTypesWriter()
f.vmlDrawingWriter()
f.workbookWriter() f.workbookWriter()
f.workbookRelsWriter() f.workbookRelsWriter()
f.worksheetWriter() f.worksheetWriter()
f.styleSheetWriter() f.styleSheetWriter()
f.calcChainWriter()
for path, content := range f.XLSX { for path, content := range f.XLSX {
fi, err := zw.Create(path) fi, err := zw.Create(path)
if err != nil { if err != nil {

Loading…
Cancel
Save