From b1f632d4084130628f10906ff6a7bb55022e4c08 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 30 Apr 2019 18:39:27 +0800 Subject: Resolve #393, upgrade Go module to v2 --- excelize.go | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 41fba37..6fb98c4 100644 --- a/excelize.go +++ b/excelize.go @@ -19,7 +19,6 @@ import ( "io/ioutil" "os" "strconv" - "strings" ) // File define a populated XLSX file struct. @@ -215,49 +214,3 @@ func (f *File) UpdateLinkedValue() error { } return nil } - -// GetMergeCells provides a function to get all merged cells from a worksheet -// currently. -func (f *File) GetMergeCells(sheet string) ([]MergeCell, error) { - var mergeCells []MergeCell - xlsx, err := f.workSheetReader(sheet) - if err != nil { - return mergeCells, err - } - if xlsx.MergeCells != nil { - mergeCells = make([]MergeCell, 0, len(xlsx.MergeCells.Cells)) - - for i := range xlsx.MergeCells.Cells { - ref := xlsx.MergeCells.Cells[i].Ref - axis := strings.Split(ref, ":")[0] - val, _ := f.GetCellValue(sheet, axis) - mergeCells = append(mergeCells, []string{ref, val}) - } - } - - return mergeCells, err -} - -// MergeCell define a merged cell data. -// It consists of the following structure. -// example: []string{"D4:E10", "cell value"} -type MergeCell []string - -// GetCellValue returns merged cell value. -func (m *MergeCell) GetCellValue() string { - return (*m)[1] -} - -// GetStartAxis returns the merge start axis. -// example: "C2" -func (m *MergeCell) GetStartAxis() string { - axis := strings.Split((*m)[0], ":") - return axis[0] -} - -// GetEndAxis returns the merge end axis. -// example: "D4" -func (m *MergeCell) GetEndAxis() string { - axis := strings.Split((*m)[0], ":") - return axis[1] -} -- cgit v1.2.1 From 54def7eaad9ee0469ca495b3661798919239384a Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 27 Jun 2019 21:58:14 +0800 Subject: Add TIF, TIFF format images and more detailed error information when open the encrypted file --- excelize.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 6fb98c4..f636a84 100644 --- a/excelize.go +++ b/excelize.go @@ -14,6 +14,7 @@ import ( "archive/zip" "bytes" "encoding/xml" + "errors" "fmt" "io" "io/ioutil" @@ -69,6 +70,17 @@ func OpenReader(r io.Reader) (*File, error) { zr, err := zip.NewReader(bytes.NewReader(b), int64(len(b))) if err != nil { + identifier := []byte{ + // checking protect workbook by [MS-OFFCRYPTO] - v20181211 3.1 FeatureIdentifier + 0x3c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, + 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, + 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x44, 0x00, 0x61, 0x00, + 0x74, 0x00, 0x61, 0x00, 0x53, 0x00, 0x70, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + } + if bytes.Contains(b, identifier) { + return nil, errors.New("not support encrypted file currently") + } return nil, err } -- cgit v1.2.1 From 35e485756f1d3f5eb1e5f78a5cee06b5ed902645 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 21 Jul 2019 12:56:36 +0800 Subject: Resolve #217, new function add VBA project supported. --- excelize.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index f636a84..c7eff10 100644 --- a/excelize.go +++ b/excelize.go @@ -19,7 +19,9 @@ import ( "io" "io/ioutil" "os" + "path" "strconv" + "strings" ) // File define a populated XLSX file struct. @@ -226,3 +228,78 @@ func (f *File) UpdateLinkedValue() error { } return nil } + +// AddVBAProject provides the method to add vbaProject.bin file which contains +// functions and/or macros. The file extension should be .xlsm. For example: +// +// err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1")) +// if err != nil { +// fmt.Println(err) +// } +// err = f.AddVBAProject("vbaProject.bin") +// if err != nil { +// fmt.Println(err) +// } +// err = f.SaveAs("macros.xlsm") +// if err != nil { +// fmt.Println(err) +// } +// +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 + } + if path.Ext(bin) != ".bin" { + return errors.New("unsupported VBA project extension") + } + f.setContentTypePartVBAProjectExtensions() + wb := f.workbookRelsReader() + var rID int + var ok bool + for _, rel := range wb.Relationships { + if rel.Target == "vbaProject.bin" && rel.Type == SourceRelationshipVBAProject { + ok = true + continue + } + t, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId")) + if t > rID { + rID = t + } + } + rID++ + if !ok { + wb.Relationships = append(wb.Relationships, xlsxWorkbookRelation{ + ID: "rId" + strconv.Itoa(rID), + Target: "vbaProject.bin", + Type: SourceRelationshipVBAProject, + }) + } + file, _ := ioutil.ReadFile(bin) + f.XLSX["xl/vbaProject.bin"] = file + return err +} + +// setContentTypePartVBAProjectExtensions provides a function to set the +// content type for relationship parts and the main document part. +func (f *File) setContentTypePartVBAProjectExtensions() { + var ok bool + content := f.contentTypesReader() + for _, v := range content.Defaults { + if v.Extension == "bin" { + ok = true + } + } + for idx, o := range content.Overrides { + if o.PartName == "/xl/workbook.xml" { + content.Overrides[idx].ContentType = "application/vnd.ms-excel.sheet.macroEnabled.main+xml" + } + } + if !ok { + content.Defaults = append(content.Defaults, xlsxDefault{ + Extension: "bin", + ContentType: "application/vnd.ms-office.vbaProject", + }) + } +} -- cgit v1.2.1 From cbe919fdf6c00733513494680b89171b8b1b41a1 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 4 Aug 2019 20:24:59 +0800 Subject: New feature: sparkline supported --- excelize.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index c7eff10..6d014a0 100644 --- a/excelize.go +++ b/excelize.go @@ -181,11 +181,21 @@ func checkSheet(xlsx *xlsxWorksheet) { // Office Excel 2007. func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte { var oldXmlns = []byte(``) - var newXmlns = []byte(``) + var newXmlns = []byte(``) workbookMarshal = bytes.Replace(workbookMarshal, oldXmlns, newXmlns, -1) return workbookMarshal } +// replaceStyleRelationshipsNameSpaceBytes provides a function to replace +// xl/styles.xml XML tags to self-closing for compatible Microsoft Office +// Excel 2007. +func replaceStyleRelationshipsNameSpaceBytes(contentMarshal []byte) []byte { + var oldXmlns = []byte(``) + var newXmlns = []byte(``) + contentMarshal = bytes.Replace(contentMarshal, oldXmlns, newXmlns, -1) + return contentMarshal +} + // UpdateLinkedValue fix linked values within a spreadsheet are not updating in // Office Excel 2007 and 2010. This function will be remove value tag when met a // cell have a linked value. Reference -- cgit v1.2.1 From 9c70d0ac868f66badf2663cc7b4b3c46d5411131 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 11 Aug 2019 00:36:14 +0800 Subject: Documentation updated, Go 1.10+ required --- excelize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 6d014a0..b734e57 100644 --- a/excelize.go +++ b/excelize.go @@ -5,7 +5,7 @@ // Package excelize providing a set of functions that allow you to write to // and read from XLSX files. Support reads and writes XLSX file generated by // Microsoft Excel™ 2007 and later. Support save file without losing original -// charts of XLSX. This library needs Go version 1.8 or later. +// charts of XLSX. This library needs Go version 1.10 or later. // // See https://xuri.me/excelize for more information about this package. package excelize -- cgit v1.2.1 From 8922f659788187afa6d0a5d3248e999c2c1bb846 Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 16 Sep 2019 01:17:35 +0800 Subject: Combine functions: workBookRelsWriter, drawingRelsWriter into relsWriter; drawingRelsReader, workbookRelsReader, workSheetRelsReader into relsReader; addDrawingRelationships, addSheetRelationships into addRels --- excelize.go | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index b734e57..4d46b94 100644 --- a/excelize.go +++ b/excelize.go @@ -31,7 +31,6 @@ type File struct { CalcChain *xlsxCalcChain Comments map[string]*xlsxComments ContentTypes *xlsxTypes - DrawingRels map[string]*xlsxWorkbookRels Drawings map[string]*xlsxWsDr Path string SharedStrings *xlsxSST @@ -42,8 +41,7 @@ type File struct { DecodeVMLDrawing map[string]*decodeVmlDrawing VMLDrawing map[string]*vmlDrawing WorkBook *xlsxWorkbook - WorkBookRels *xlsxWorkbookRels - WorkSheetRels map[string]*xlsxWorkbookRels + Relationships map[string]*xlsxRelationships XLSX map[string][]byte } @@ -93,13 +91,12 @@ func OpenReader(r io.Reader) (*File, error) { f := &File{ checked: make(map[string]bool), Comments: make(map[string]*xlsxComments), - DrawingRels: make(map[string]*xlsxWorkbookRels), Drawings: make(map[string]*xlsxWsDr), Sheet: make(map[string]*xlsxWorksheet), SheetCount: sheetCount, DecodeVMLDrawing: make(map[string]*decodeVmlDrawing), VMLDrawing: make(map[string]*vmlDrawing), - WorkSheetRels: make(map[string]*xlsxWorkbookRels), + Relationships: make(map[string]*xlsxRelationships), XLSX: file, } f.CalcChain = f.calcChainReader() @@ -176,6 +173,28 @@ func checkSheet(xlsx *xlsxWorksheet) { xlsx.SheetData = sheetData } +// addRels provides a function to add relationships by given XML path, +// relationship type, target and target mode. +func (f *File) addRels(relPath, relType, target, targetMode string) int { + rels := f.relsReader(relPath) + rID := 0 + if rels == nil { + rels = &xlsxRelationships{} + } + rID = len(rels.Relationships) + 1 + var ID bytes.Buffer + ID.WriteString("rId") + ID.WriteString(strconv.Itoa(rID)) + rels.Relationships = append(rels.Relationships, xlsxRelationship{ + ID: ID.String(), + Type: relType, + Target: target, + TargetMode: targetMode, + }) + f.Relationships[relPath] = rels + return rID +} + // replaceWorkSheetsRelationshipsNameSpaceBytes provides a function to replace // xl/worksheets/sheet%d.xml XML tags to self-closing for compatible Microsoft // Office Excel 2007. @@ -265,7 +284,7 @@ func (f *File) AddVBAProject(bin string) error { return errors.New("unsupported VBA project extension") } f.setContentTypePartVBAProjectExtensions() - wb := f.workbookRelsReader() + wb := f.relsReader("xl/_rels/workbook.xml.rels") var rID int var ok bool for _, rel := range wb.Relationships { @@ -280,7 +299,7 @@ func (f *File) AddVBAProject(bin string) error { } rID++ if !ok { - wb.Relationships = append(wb.Relationships, xlsxWorkbookRelation{ + wb.Relationships = append(wb.Relationships, xlsxRelationship{ ID: "rId" + strconv.Itoa(rID), Target: "vbaProject.bin", Type: SourceRelationshipVBAProject, -- cgit v1.2.1 From bf9a8355494eac18812f3caf6d469962824f627f Mon Sep 17 00:00:00 2001 From: Harris Date: Mon, 28 Oct 2019 10:34:21 -0500 Subject: Reduce allocations when writing Fix #494 If a row is full, don't bother allocating a new one, just return it. Use the last populated row as a hint for the size of new rows. Simplify checkSheet to remove row map --- excelize.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 4d46b94..ba6445f 100644 --- a/excelize.go +++ b/excelize.go @@ -155,20 +155,12 @@ func checkSheet(xlsx *xlsxWorksheet) { row = lastRow } } - sheetData := xlsxSheetData{} - existsRows := map[int]int{} - for k := range xlsx.SheetData.Row { - existsRows[xlsx.SheetData.Row[k].R] = k + sheetData := xlsxSheetData{Row: make([]xlsxRow, row)} + for _, r := range xlsx.SheetData.Row { + sheetData.Row[r.R-1] = r } - for i := 0; i < row; i++ { - _, ok := existsRows[i+1] - if ok { - sheetData.Row = append(sheetData.Row, xlsx.SheetData.Row[existsRows[i+1]]) - } else { - sheetData.Row = append(sheetData.Row, xlsxRow{ - R: i + 1, - }) - } + for i := 1; i <= row; i++ { + sheetData.Row[i-1].R = i } xlsx.SheetData = sheetData } -- cgit v1.2.1 From 8d6e431dcd8d96dc51f74308e49b5d4a5b2b9d2e Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 28 Nov 2019 21:53:50 +0800 Subject: Resolve #521, fix missing elements when parsing --- excelize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index ba6445f..c59ec8c 100644 --- a/excelize.go +++ b/excelize.go @@ -192,7 +192,7 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int { // Office Excel 2007. func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte { var oldXmlns = []byte(``) - var newXmlns = []byte(``) + var newXmlns = []byte(``) workbookMarshal = bytes.Replace(workbookMarshal, oldXmlns, newXmlns, -1) return workbookMarshal } -- cgit v1.2.1 From 402ad2f62b04d44f1ab866b32b9e7314a713e5f0 Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 30 Nov 2019 00:06:36 +0800 Subject: Update XML namespace --- excelize.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index c59ec8c..cbe7231 100644 --- a/excelize.go +++ b/excelize.go @@ -192,7 +192,7 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int { // Office Excel 2007. func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte { var oldXmlns = []byte(``) - var newXmlns = []byte(``) + var newXmlns = []byte(``) - var newXmlns = []byte(``) + var newXmlns = []byte(` Date: Thu, 19 Dec 2019 19:30:48 +0300 Subject: =?UTF-8?q?Fix=20#539=20Fixed=20error=20opening=20excel=20file=20c?= =?UTF-8?q?reated=20in=20encoding=20d=E2=80=A6=20(#540)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed issue #539 Fixed error opening excel file created in encoding different from UTF-8, added logging of possible errors when decoding XML if the function does not provide exit with an error * Added test for CharsetReader * Fixed #discussion_r359397878 Discussion: https://github.com/360EntSecGroup-Skylar/excelize/pull/540#discussion_r359397878 * Fixed go fmt * go mod tidy and removed unused imports * The code has been refactored --- excelize.go | 81 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 24 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 4d46b94..fe227b9 100644 --- a/excelize.go +++ b/excelize.go @@ -22,6 +22,8 @@ import ( "path" "strconv" "strings" + + "golang.org/x/net/html/charset" ) // File define a populated XLSX file struct. @@ -43,8 +45,11 @@ type File struct { WorkBook *xlsxWorkbook Relationships map[string]*xlsxRelationships XLSX map[string][]byte + CharsetReader charsetTranscoderFn } +type charsetTranscoderFn func(charset string, input io.Reader) (rdr io.Reader, err error) + // OpenFile take the name of an XLSX file and returns a populated XLSX file // struct for it. func OpenFile(filename string) (*File, error) { @@ -61,6 +66,21 @@ func OpenFile(filename string) (*File, error) { return f, nil } +// object builder +func newFile() *File { + return &File{ + checked: make(map[string]bool), + sheetMap: make(map[string]string), + Comments: make(map[string]*xlsxComments), + Drawings: make(map[string]*xlsxWsDr), + Sheet: make(map[string]*xlsxWorksheet), + DecodeVMLDrawing: make(map[string]*decodeVmlDrawing), + VMLDrawing: make(map[string]*vmlDrawing), + Relationships: make(map[string]*xlsxRelationships), + CharsetReader: charset.NewReaderLabel, + } +} + // OpenReader take an io.Reader and return a populated XLSX file. func OpenReader(r io.Reader) (*File, error) { b, err := ioutil.ReadAll(r) @@ -88,17 +108,8 @@ func OpenReader(r io.Reader) (*File, error) { if err != nil { return nil, err } - f := &File{ - checked: make(map[string]bool), - Comments: make(map[string]*xlsxComments), - Drawings: make(map[string]*xlsxWsDr), - Sheet: make(map[string]*xlsxWorksheet), - SheetCount: sheetCount, - DecodeVMLDrawing: make(map[string]*decodeVmlDrawing), - VMLDrawing: make(map[string]*vmlDrawing), - Relationships: make(map[string]*xlsxRelationships), - XLSX: file, - } + f := newFile() + f.SheetCount, f.XLSX = sheetCount, file f.CalcChain = f.calcChainReader() f.sheetMap = f.getSheetMap() f.Styles = f.stylesReader() @@ -106,6 +117,16 @@ func OpenReader(r io.Reader) (*File, error) { return f, nil } +// CharsetTranscoder Set user defined codepage transcoder function for open XLSX from non UTF-8 encoding +func (f *File) CharsetTranscoder(fn charsetTranscoderFn) *File { f.CharsetReader = fn; return f } + +// Creates new XML decoder with charset reader +func (f *File) xmlNewDecoder(rdr io.Reader) (ret *xml.Decoder) { + ret = xml.NewDecoder(rdr) + ret.CharsetReader = f.CharsetReader + return +} + // setDefaultTimeStyle provides a function to set default numbers format for // time.Time type cell value by given worksheet name, cell coordinates and // number format code. @@ -123,26 +144,38 @@ 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) (*xlsxWorksheet, error) { - name, ok := f.sheetMap[trimSheetName(sheet)] - if !ok { - return nil, fmt.Errorf("sheet %s is not exist", sheet) +func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) { + var ( + name string + ok bool + ) + + if name, ok = f.sheetMap[trimSheetName(sheet)]; !ok { + err = fmt.Errorf("sheet %s is not exist", sheet) + return } - if f.Sheet[name] == nil { - var xlsx xlsxWorksheet - _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(name)), &xlsx) + if xlsx = f.Sheet[name]; f.Sheet[name] == nil { + xlsx = new(xlsxWorksheet) + if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(name)))). + Decode(xlsx); err != nil && err != io.EOF { + err = fmt.Errorf("xml decode error: %s", err) + return + } + err = nil if f.checked == nil { f.checked = make(map[string]bool) } - ok := f.checked[name] - if !ok { - checkSheet(&xlsx) - checkRow(&xlsx) + if ok = f.checked[name]; !ok { + checkSheet(xlsx) + if err = checkRow(xlsx); err != nil { + return + } f.checked[name] = true } - f.Sheet[name] = &xlsx + f.Sheet[name] = xlsx } - return f.Sheet[name], nil + + return } // checkSheet provides a function to fill each row element and make that is -- cgit v1.2.1 From 7358dca436f6ca5948a3f2865b14e828863d86a9 Mon Sep 17 00:00:00 2001 From: match-meng <54879059+match-meng@users.noreply.github.com> Date: Fri, 20 Dec 2019 22:22:56 +0800 Subject: Update comments for the xmlNewDecoder (#542) --- excelize.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 8e386a8..a2e20ff 100644 --- a/excelize.go +++ b/excelize.go @@ -66,7 +66,7 @@ func OpenFile(filename string) (*File, error) { return f, nil } -// object builder +// newFile is object builder func newFile() *File { return &File{ checked: make(map[string]bool), @@ -117,10 +117,11 @@ func OpenReader(r io.Reader) (*File, error) { return f, nil } -// CharsetTranscoder Set user defined codepage transcoder function for open XLSX from non UTF-8 encoding +// CharsetTranscoder Set user defined codepage transcoder function for open +// XLSX from non UTF-8 encoding. func (f *File) CharsetTranscoder(fn charsetTranscoderFn) *File { f.CharsetReader = fn; return f } -// Creates new XML decoder with charset reader +// Creates new XML decoder with charset reader. func (f *File) xmlNewDecoder(rdr io.Reader) (ret *xml.Decoder) { ret = xml.NewDecoder(rdr) ret.CharsetReader = f.CharsetReader -- cgit v1.2.1 From 4e4a5b9b3e052d1694442515492792fb1aa74c5a Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 23 Dec 2019 00:07:40 +0800 Subject: Improve compatibility, fix workbook's rels ID calc error --- excelize.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index a2e20ff..135028c 100644 --- a/excelize.go +++ b/excelize.go @@ -203,11 +203,17 @@ func checkSheet(xlsx *xlsxWorksheet) { // relationship type, target and target mode. func (f *File) addRels(relPath, relType, target, targetMode string) int { rels := f.relsReader(relPath) - rID := 0 if rels == nil { rels = &xlsxRelationships{} } - rID = len(rels.Relationships) + 1 + var rID int + for _, rel := range rels.Relationships { + ID, _ := strconv.Atoi(strings.TrimPrefix(rel.ID, "rId")) + if ID > rID { + rID = ID + } + } + rID++ var ID bytes.Buffer ID.WriteString("rId") ID.WriteString(strconv.Itoa(rID)) -- cgit v1.2.1 From 1666d04559d9f5b579ab7c850ccc95863c31bd25 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 24 Dec 2019 01:09:28 +0800 Subject: optimization: checking error in unit tests --- excelize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 135028c..94f401c 100644 --- a/excelize.go +++ b/excelize.go @@ -138,7 +138,7 @@ func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error { } if s == 0 { style, _ := f.NewStyle(`{"number_format": ` + strconv.Itoa(format) + `}`) - f.SetCellStyle(sheet, axis, axis, style) + _ = f.SetCellStyle(sheet, axis, axis, style) } return err } -- cgit v1.2.1 From 09485b3f9f0aefc58d51462aed65c2416205c591 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 29 Dec 2019 16:02:31 +0800 Subject: Improve code coverage unit tests --- excelize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 94f401c..8fbd315 100644 --- a/excelize.go +++ b/excelize.go @@ -1,4 +1,4 @@ -// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of +// Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of // this source code is governed by a BSD-style license that can be found in // the LICENSE file. -- cgit v1.2.1 From 5f5ec76740704a8362e5a120b4a3582b409a5fdd Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 31 Dec 2019 01:01:16 +0800 Subject: Fix #551, handle empty rows in streaming reading --- excelize.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 8fbd315..9832c6a 100644 --- a/excelize.go +++ b/excelize.go @@ -293,17 +293,14 @@ func (f *File) UpdateLinkedValue() error { // AddVBAProject provides the method to add vbaProject.bin file which contains // functions and/or macros. The file extension should be .xlsm. For example: // -// err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1")) -// if err != nil { -// fmt.Println(err) +// if err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1")); err != nil { +// println(err.Error()) // } -// err = f.AddVBAProject("vbaProject.bin") -// if err != nil { -// fmt.Println(err) +// if err := f.AddVBAProject("vbaProject.bin"); err != nil { +// println(err.Error()) // } -// err = f.SaveAs("macros.xlsm") -// if err != nil { -// fmt.Println(err) +// if err := f.SaveAs("macros.xlsm"); err != nil { +// println(err.Error()) // } // func (f *File) AddVBAProject(bin string) error { -- cgit v1.2.1 From ad883caa0f77dfc016ae99bd5fbb606953eb99a0 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 19 Feb 2020 00:08:10 +0800 Subject: Resolve #580, revert commit https://github.com/360EntSecGroup-Skylar/excelize/commit/5ca7231ed408ac264f509ff52b5d28ff4fbda757 --- excelize.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 9832c6a..e12e769 100644 --- a/excelize.go +++ b/excelize.go @@ -294,13 +294,13 @@ func (f *File) UpdateLinkedValue() error { // functions and/or macros. The file extension should be .xlsm. For example: // // if err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1")); err != nil { -// println(err.Error()) +// fmt.Println(err) // } // if err := f.AddVBAProject("vbaProject.bin"); err != nil { -// println(err.Error()) +// fmt.Println(err) // } // if err := f.SaveAs("macros.xlsm"); err != nil { -// println(err.Error()) +// fmt.Println(err) // } // func (f *File) AddVBAProject(bin string) error { -- cgit v1.2.1 From 2ccb8f62edd5d1ce039e663591964b9066fd2f4e Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 9 Mar 2020 00:08:47 +0800 Subject: Remove calculated properties to make recalculate formulas in some spreadsheet applications, such as Kingsoft WPS --- excelize.go | 3 +++ 1 file changed, 3 insertions(+) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index e12e769..0962122 100644 --- a/excelize.go +++ b/excelize.go @@ -273,6 +273,9 @@ func replaceStyleRelationshipsNameSpaceBytes(contentMarshal []byte) []byte { // // func (f *File) UpdateLinkedValue() error { + wb := f.workbookReader() + // recalculate formulas + wb.CalcPr = nil for _, name := range f.GetSheetMap() { xlsx, err := f.workSheetReader(name) if err != nil { -- cgit v1.2.1 From 9e2318cefa4ebaa7bf6b1dbc95b30ad7a32366b1 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 10 Mar 2020 00:04:23 +0800 Subject: Resolve #470, export Style structs to allow create the style for cells by given JSON or structure --- excelize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 0962122..795120d 100644 --- a/excelize.go +++ b/excelize.go @@ -137,7 +137,7 @@ func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error { return err } if s == 0 { - style, _ := f.NewStyle(`{"number_format": ` + strconv.Itoa(format) + `}`) + style, _ := f.NewStyle(&Style{NumFmt: format}) _ = f.SetCellStyle(sheet, axis, axis, style) } return err -- cgit v1.2.1 From 6afc468a025984aa1b265b0228f032c5ed881a3b Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 28 Mar 2020 23:47:26 +0800 Subject: Resolve #451, support create chart sheet --- excelize.go | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 795120d..3dd4311 100644 --- a/excelize.go +++ b/excelize.go @@ -228,21 +228,10 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int { } // replaceWorkSheetsRelationshipsNameSpaceBytes provides a function to replace -// xl/worksheets/sheet%d.xml XML tags to self-closing for compatible Microsoft -// Office Excel 2007. -func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte { - var oldXmlns = []byte(``) - var newXmlns = []byte(``) - var newXmlns = []byte(``) + var newXmlns = []byte(templateNamespaceIDMap) contentMarshal = bytes.Replace(contentMarshal, oldXmlns, newXmlns, -1) return contentMarshal } @@ -354,13 +343,13 @@ func (f *File) setContentTypePartVBAProjectExtensions() { } for idx, o := range content.Overrides { if o.PartName == "/xl/workbook.xml" { - content.Overrides[idx].ContentType = "application/vnd.ms-excel.sheet.macroEnabled.main+xml" + content.Overrides[idx].ContentType = ContentTypeMacro } } if !ok { content.Defaults = append(content.Defaults, xlsxDefault{ Extension: "bin", - ContentType: "application/vnd.ms-office.vbaProject", + ContentType: ContentTypeVBA, }) } } -- cgit v1.2.1 From 3f89c6e9799c9c82af1305f080416c53d19e64c1 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 29 Mar 2020 18:44:24 +0800 Subject: remove ineffectual variable assignments and simplify code --- excelize.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 3dd4311..520cbb7 100644 --- a/excelize.go +++ b/excelize.go @@ -156,6 +156,10 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) { return } if xlsx = f.Sheet[name]; f.Sheet[name] == nil { + if strings.HasPrefix(name, "xl/chartsheets") { + err = fmt.Errorf("sheet %s is chart sheet", sheet) + return + } xlsx = new(xlsxWorksheet) if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(name)))). Decode(xlsx); err != nil && err != io.EOF { @@ -227,9 +231,9 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int { return rID } -// replaceWorkSheetsRelationshipsNameSpaceBytes provides a function to replace +// replaceRelationshipsNameSpaceBytes provides a function to replace // XML tags to self-closing for compatible Microsoft Office Excel 2007. -func replaceWorkSheetsRelationshipsNameSpaceBytes(contentMarshal []byte) []byte { +func replaceRelationshipsNameSpaceBytes(contentMarshal []byte) []byte { var oldXmlns = []byte(` xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`) var newXmlns = []byte(templateNamespaceIDMap) contentMarshal = bytes.Replace(contentMarshal, oldXmlns, newXmlns, -1) -- cgit v1.2.1 From 0f2a9053246c3ae45e6c7ba911a1fb135664abdf Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 2 Apr 2020 00:41:14 +0800 Subject: Performance improvements --- excelize.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 520cbb7..ae011d9 100644 --- a/excelize.go +++ b/excelize.go @@ -234,10 +234,9 @@ func (f *File) addRels(relPath, relType, target, targetMode string) int { // replaceRelationshipsNameSpaceBytes provides a function to replace // XML tags to self-closing for compatible Microsoft Office Excel 2007. func replaceRelationshipsNameSpaceBytes(contentMarshal []byte) []byte { - var oldXmlns = []byte(` xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`) + var oldXmlns = stringToBytes(` xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`) var newXmlns = []byte(templateNamespaceIDMap) - contentMarshal = bytes.Replace(contentMarshal, oldXmlns, newXmlns, -1) - return contentMarshal + return bytesReplace(contentMarshal, oldXmlns, newXmlns, -1) } // UpdateLinkedValue fix linked values within a spreadsheet are not updating in -- cgit v1.2.1 From 1fe660df648422a53eef0c735657cb2f5237ef7b Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 23 Apr 2020 02:01:14 +0800 Subject: - Resolve #485 use sheet index instead of ID - added 3 internal function: getSheetID, getActiveSheetID, getSheetNameByID --- excelize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index ae011d9..73bc1b5 100644 --- a/excelize.go +++ b/excelize.go @@ -268,7 +268,7 @@ func (f *File) UpdateLinkedValue() error { wb := f.workbookReader() // recalculate formulas wb.CalcPr = nil - for _, name := range f.GetSheetMap() { + for _, name := range f.GetSheetList() { xlsx, err := f.workSheetReader(name) if err != nil { return err -- cgit v1.2.1 From 48fc4c08a2a80f7826d20bf3fd5a018f8e6f3185 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 3 May 2020 18:44:43 +0800 Subject: init formula calculation engine, ref #65 and #599 --- excelize.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 73bc1b5..04e2e85 100644 --- a/excelize.go +++ b/excelize.go @@ -3,9 +3,11 @@ // the LICENSE file. // Package excelize providing a set of functions that allow you to write to -// and read from XLSX files. Support reads and writes XLSX file generated by -// Microsoft Excel™ 2007 and later. Support save file without losing original -// charts of XLSX. This library needs Go version 1.10 or later. +// and read from XLSX / XLSM / XLTM files. Supports reading and writing +// spreadsheet documents generated by Microsoft Exce™ 2007 and later. Supports +// complex components by high compatibility, and provided streaming API for +// generating or reading data from a worksheet with huge amounts of data. This +// library needs Go version 1.10 or later. // // See https://xuri.me/excelize for more information about this package. package excelize -- cgit v1.2.1 From 2efc7107ff30dc7f1e1a798082616ee488f99489 Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 21 May 2020 22:57:58 +0800 Subject: - transform the range to the matrix on the first arg of the formula - typo fix - reset cell with and height when insert picture into merged cell with autofit --- excelize.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'excelize.go') diff --git a/excelize.go b/excelize.go index 04e2e85..3fd25aa 100644 --- a/excelize.go +++ b/excelize.go @@ -28,7 +28,7 @@ import ( "golang.org/x/net/html/charset" ) -// File define a populated XLSX file struct. +// File define a populated spreadsheet file struct. type File struct { checked map[string]bool sheetMap map[string]string @@ -52,8 +52,8 @@ type File struct { type charsetTranscoderFn func(charset string, input io.Reader) (rdr io.Reader, err error) -// OpenFile take the name of an XLSX file and returns a populated XLSX file -// struct for it. +// OpenFile take the name of an spreadsheet file and returns a populated +// spreadsheet file struct for it. func OpenFile(filename string) (*File, error) { file, err := os.Open(filename) if err != nil { @@ -83,7 +83,8 @@ func newFile() *File { } } -// OpenReader take an io.Reader and return a populated XLSX file. +// OpenReader read data stream from io.Reader and return a populated +// spreadsheet file. func OpenReader(r io.Reader) (*File, error) { b, err := ioutil.ReadAll(r) if err != nil { -- cgit v1.2.1