From 821632cf89422b9955160a3af7f28f05a12f70f8 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 12 Jun 2019 08:10:33 +0800 Subject: Fix #424, refactor merged cells adjuster --- cell.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index bd4d93b..6743e2a 100644 --- a/cell.go +++ b/cell.go @@ -401,31 +401,27 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error { // If you create a merged cell that overlaps with another existing merged cell, // those merged cells that already exist will be removed. func (f *File) MergeCell(sheet, hcell, vcell string) error { - hcol, hrow, err := CellNameToCoordinates(hcell) + coordinates, err := f.areaRefToCoordinates(hcell + ":" + vcell) if err != nil { return err } + x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3] - vcol, vrow, err := CellNameToCoordinates(vcell) - if err != nil { - return err - } - - if hcol == vcol && hrow == vrow { + if x1 == x2 && y1 == y2 { return err } // Correct the coordinate area, such correct C1:B3 to B1:C3. - if vcol < hcol { - hcol, vcol = vcol, hcol + if x2 < x1 { + x1, x2 = x2, x1 } - if vrow < hrow { - hrow, vrow = vrow, hrow + if y2 < y1 { + y1, y2 = y2, y1 } - hcell, _ = CoordinatesToCellName(hcol, hrow) - vcell, _ = CoordinatesToCellName(vcol, vrow) + hcell, _ = CoordinatesToCellName(x1, y1) + vcell, _ = CoordinatesToCellName(x2, y2) xlsx, err := f.workSheetReader(sheet) if err != nil { -- 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 --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index 6743e2a..f61e268 100644 --- a/cell.go +++ b/cell.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. package excelize -- cgit v1.2.1 From ac395a60ed2ac643403678991ff4745231ff48c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Mengu=C3=A9?= Date: Tue, 13 Aug 2019 15:39:12 +0200 Subject: SetCellValue: use fmt.Sprint(v) instead of fmt.Sprintf("%v", v) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because that does the same thing, but without having to parse a format string. Signed-off-by: Olivier Mengué --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index f61e268..9d478a5 100644 --- a/cell.go +++ b/cell.go @@ -94,7 +94,7 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) error { case nil: err = f.SetCellStr(sheet, axis, "") default: - err = f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value)) + err = f.SetCellStr(sheet, axis, fmt.Sprint(value)) } return err } -- cgit v1.2.1 From 64809db2c9ee30779e4839e9d60a315479092ce6 Mon Sep 17 00:00:00 2001 From: mqy Date: Mon, 19 Aug 2019 15:53:56 +0800 Subject: add missing error check in SetSheetRow() --- cell.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index 9d478a5..e897379 100644 --- a/cell.go +++ b/cell.go @@ -471,12 +471,14 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error { for i := 0; i < v.Len(); i++ { cell, err := CoordinatesToCellName(col+i, row) - // Error should never happens here. But keep ckecking to early detect regresions - // if it will be introduced in furure + // Error should never happens here. But keep checking to early detect regresions + // if it will be introduced in future. if err != nil { return err } - f.SetCellValue(sheet, cell, v.Index(i).Interface()) + if err := f.SetCellValue(sheet, cell, v.Index(i).Interface()); err != nil { + return err + } } return err } -- 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 --- cell.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index e897379..1da46aa 100644 --- a/cell.go +++ b/cell.go @@ -378,7 +378,9 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error { linkData = xlsxHyperlink{ Ref: axis, } - rID := f.addSheetRelationships(sheet, SourceRelationshipHyperLink, link, linkType) + sheetPath, _ := f.sheetMap[trimSheetName(sheet)] + sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels" + rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType) linkData.RID = "rId" + strconv.Itoa(rID) case "Location": linkData = xlsxHyperlink{ -- cgit v1.2.1 From 3280e1b68664e12143cbd2b3a408f9f494a72897 Mon Sep 17 00:00:00 2001 From: Christian Fiedler Date: Sun, 22 Sep 2019 14:52:01 +0200 Subject: Allow access to more formula attributes in SetCellFormula (#484) * Allow access to more formula attributes in SetCellFormula Make SetCellFormula variadic to not break API. The new arguments are option arguments in which the type of the formula and the ref attribute may be set. These need to be set for an array formula to work. * Add TestWriteArrayFormula to test optional parameters of SetCellFormula TestWriteArrayFormula writes a document to the test directory that contains array formulas that are used to calculate standard deviations. The file also contains values calculated by the Go testcase, so the results can be verified. It should be tested, if the array formula works (i.e. shows a number, not an error) and that the values calculated by the formula and those calculated by Go are the same. --- cell.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index 1da46aa..f9868de 100644 --- a/cell.go +++ b/cell.go @@ -273,9 +273,15 @@ func (f *File) GetCellFormula(sheet, axis string) (string, error) { }) } +// FormulaOpts can be passed to SetCellFormula to use other formula types. +type FormulaOpts struct { + Type *string // Formula type + Ref *string // Shared formula ref +} + // SetCellFormula provides a function to set cell formula by given string and // worksheet name. -func (f *File) SetCellFormula(sheet, axis, formula string) error { +func (f *File) SetCellFormula(sheet, axis, formula string, opts ...FormulaOpts) error { xlsx, err := f.workSheetReader(sheet) if err != nil { return err @@ -295,6 +301,17 @@ func (f *File) SetCellFormula(sheet, axis, formula string) error { } else { cellData.F = &xlsxF{Content: formula} } + + for _, o := range opts { + if o.Type != nil { + cellData.F.T = *o.Type + } + + if o.Ref != nil { + cellData.F.Ref = *o.Ref + } + } + return err } -- cgit v1.2.1 From 810139f5fc46b1002c0998379b18af3d2feffbb7 Mon Sep 17 00:00:00 2001 From: heiy <287789299@qq.com> Date: Thu, 10 Oct 2019 20:04:33 +0800 Subject: solve ending space missing --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index f9868de..ab42b72 100644 --- a/cell.go +++ b/cell.go @@ -229,7 +229,7 @@ func (f *File) SetCellStr(sheet, axis, value string) error { value = value[0:32767] } // Leading space(s) character detection. - if len(value) > 0 && value[0] == 32 { + if len(value) > 0 && (value[0] == 32 || value[len(value)-1] == 32) { cellData.XMLSpace = xml.Attr{ Name: xml.Name{Space: NameSpaceXML, Local: "space"}, Value: "preserve", -- cgit v1.2.1 From 2e791fa433def282ee2e7a5049a46fc4a76796cf Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 16 Oct 2019 01:03:29 +0800 Subject: Optimize code of Getting/Setting Page Margins --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index ab42b72..a25f2e4 100644 --- a/cell.go +++ b/cell.go @@ -228,7 +228,7 @@ func (f *File) SetCellStr(sheet, axis, value string) error { if len(value) > 32767 { value = value[0:32767] } - // Leading space(s) character detection. + // Leading and ending space(s) character detection. if len(value) > 0 && (value[0] == 32 || value[len(value)-1] == 32) { cellData.XMLSpace = xml.Attr{ Name: xml.Name{Space: NameSpaceXML, Local: "space"}, -- cgit v1.2.1 From da0d2ffbb6ebdfb7b1e5cf501a1986421311017b Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 14 Dec 2019 19:57:37 +0800 Subject: Fix #533, add support overlapped mergecells --- cell.go | 86 ++++++++++++++++++----------------------------------------------- 1 file changed, 24 insertions(+), 62 deletions(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index a25f2e4..ad4bcdb 100644 --- a/cell.go +++ b/cell.go @@ -412,63 +412,6 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error { return nil } -// MergeCell provides a function to merge cells by given coordinate area and -// sheet name. For example create a merged cell of D3:E9 on Sheet1: -// -// err := f.MergeCell("Sheet1", "D3", "E9") -// -// If you create a merged cell that overlaps with another existing merged cell, -// those merged cells that already exist will be removed. -func (f *File) MergeCell(sheet, hcell, vcell string) error { - coordinates, err := f.areaRefToCoordinates(hcell + ":" + vcell) - if err != nil { - return err - } - x1, y1, x2, y2 := coordinates[0], coordinates[1], coordinates[2], coordinates[3] - - if x1 == x2 && y1 == y2 { - return err - } - - // Correct the coordinate area, such correct C1:B3 to B1:C3. - if x2 < x1 { - x1, x2 = x2, x1 - } - - if y2 < y1 { - y1, y2 = y2, y1 - } - - hcell, _ = CoordinatesToCellName(x1, y1) - vcell, _ = CoordinatesToCellName(x2, y2) - - xlsx, err := f.workSheetReader(sheet) - if err != nil { - return err - } - if xlsx.MergeCells != nil { - ref := hcell + ":" + vcell - // Delete the merged cells of the overlapping area. - for _, cellData := range xlsx.MergeCells.Cells { - cc := strings.Split(cellData.Ref, ":") - if len(cc) != 2 { - return fmt.Errorf("invalid area %q", cellData.Ref) - } - c1, _ := checkCellInArea(hcell, cellData.Ref) - c2, _ := checkCellInArea(vcell, cellData.Ref) - c3, _ := checkCellInArea(cc[0], ref) - c4, _ := checkCellInArea(cc[1], ref) - if !(!c1 && !c2 && !c3 && !c4) { - return nil - } - } - xlsx.MergeCells.Cells = append(xlsx.MergeCells.Cells, &xlsxMergeCell{Ref: ref}) - } else { - xlsx.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: hcell + ":" + vcell}}} - } - return err -} - // SetSheetRow writes an array to row by given worksheet name, starting // coordinate and a pointer to array type 'slice'. For example, writes an // array to row 6 start with the cell B6 on Sheet1: @@ -601,7 +544,7 @@ func (f *File) mergeCellsParser(xlsx *xlsxWorksheet, axis string) (string, error axis = strings.ToUpper(axis) if xlsx.MergeCells != nil { for i := 0; i < len(xlsx.MergeCells.Cells); i++ { - ok, err := checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) + ok, err := f.checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) if err != nil { return axis, err } @@ -615,7 +558,7 @@ func (f *File) mergeCellsParser(xlsx *xlsxWorksheet, axis string) (string, error // checkCellInArea provides a function to determine if a given coordinate is // within an area. -func checkCellInArea(cell, area string) (bool, error) { +func (f *File) checkCellInArea(cell, area string) (bool, error) { col, row, err := CellNameToCoordinates(cell) if err != nil { return false, err @@ -625,11 +568,30 @@ func checkCellInArea(cell, area string) (bool, error) { if len(rng) != 2 { return false, err } + coordinates, err := f.areaRefToCoordinates(area) + if err != nil { + return false, err + } + + return cellInRef([]int{col, row}, coordinates), err +} - firstCol, firstRow, _ := CellNameToCoordinates(rng[0]) - lastCol, lastRow, _ := CellNameToCoordinates(rng[1]) +// cellInRef provides a function to determine if a given range is within an +// range. +func cellInRef(cell, ref []int) bool { + return cell[0] >= ref[0] && cell[0] <= ref[2] && cell[1] >= ref[1] && cell[1] <= ref[3] +} - return col >= firstCol && col <= lastCol && row >= firstRow && row <= lastRow, err +// isOverlap find if the given two rectangles overlap or not. +func isOverlap(rect1, rect2 []int) bool { + return cellInRef([]int{rect1[0], rect1[1]}, rect2) || + cellInRef([]int{rect1[2], rect1[1]}, rect2) || + cellInRef([]int{rect1[0], rect1[3]}, rect2) || + cellInRef([]int{rect1[2], rect1[3]}, rect2) || + cellInRef([]int{rect2[0], rect2[1]}, rect1) || + cellInRef([]int{rect2[2], rect2[1]}, rect1) || + cellInRef([]int{rect2[0], rect2[3]}, rect1) || + cellInRef([]int{rect2[2], rect2[3]}, rect1) } // getSharedForumula find a cell contains the same formula as another cell, -- 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 --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index ad4bcdb..e59a659 100644 --- a/cell.go +++ b/cell.go @@ -395,7 +395,7 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error { linkData = xlsxHyperlink{ Ref: axis, } - sheetPath, _ := f.sheetMap[trimSheetName(sheet)] + sheetPath := f.sheetMap[trimSheetName(sheet)] sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels" rID := f.addRels(sheetRels, SourceRelationshipHyperLink, link, linkType) linkData.RID = "rId" + strconv.Itoa(rID) -- cgit v1.2.1 From 5f3a4bc39f9cf2987104ffe57242a0526cdd9158 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 25 Dec 2019 00:00:50 +0800 Subject: Fix #538, added setting a major unit and tick label skip support for the chart --- cell.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index e59a659..da091ee 100644 --- a/cell.go +++ b/cell.go @@ -44,7 +44,8 @@ func (f *File) GetCellValue(sheet, axis string) (string, error) { }) } -// SetCellValue provides a function to set value of a cell. The following +// SetCellValue provides a function to set value of a cell. The specified +// coordinates should not be in the first row of the table. The following // shows the supported data types: // // int -- cgit v1.2.1 From 5c87effc7e6c97fff36a56dea1afac8a2f06fb37 Mon Sep 17 00:00:00 2001 From: Cameron Howey Date: Sat, 28 Dec 2019 20:45:10 -0800 Subject: Stream to Excel table (#530) * Support all datatypes for StreamWriter * Support setting styles with StreamWriter **NOTE:** This is a breaking change. Values are now explicitly passed as a []interface{} for simplicity. We also let styles to be set at the same time. * Create function to write stream into a table * Write rows directly to buffer Avoiding the xml.Encoder makes the streamer faster and use less memory. Using the included benchmark, the results went from: > BenchmarkStreamWriter-4 514 2576155 ns/op 454918 B/op 6592 allocs/op down to: > BenchmarkStreamWriter-4 1614 777480 ns/op 147608 B/op 5570 allocs/op * Use AddTable instead of SetTable This requires reading the cells after they have been written, which requires additional structure for the temp file. As a bonus, we now efficiently allocate only one buffer when reading the file back into memory, using the same approach as ioutil.ReadFile. * Use an exported Cell type to handle inline styles for StreamWriter --- cell.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 28 deletions(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index da091ee..1aeddc1 100644 --- a/cell.go +++ b/cell.go @@ -83,7 +83,8 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) error { case []byte: err = f.SetCellStr(sheet, axis, string(v)) case time.Duration: - err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(v.Seconds()/86400.0, 'f', -1, 32)) + _, d := setCellDuration(v) + err = f.SetCellDefault(sheet, axis, d) if err != nil { return err } @@ -131,28 +132,50 @@ func (f *File) setCellIntFunc(sheet, axis string, value interface{}) error { // setCellTimeFunc provides a method to process time type of value for // SetCellValue. func (f *File) setCellTimeFunc(sheet, axis string, value time.Time) error { - excelTime, err := timeToExcelTime(value) + xlsx, err := f.workSheetReader(sheet) if err != nil { return err } - if excelTime > 0 { - err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(excelTime, 'f', -1, 64)) - if err != nil { - return err - } + cellData, col, _, err := f.prepareCell(xlsx, sheet, axis) + if err != nil { + return err + } + cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) + + var isNum bool + cellData.T, cellData.V, isNum, err = setCellTime(value) + if err != nil { + return err + } + if isNum { err = f.setDefaultTimeStyle(sheet, axis, 22) if err != nil { return err } - } else { - err = f.SetCellStr(sheet, axis, value.Format(time.RFC3339Nano)) - if err != nil { - return err - } } return err } +func setCellTime(value time.Time) (t string, b string, isNum bool, err error) { + var excelTime float64 + excelTime, err = timeToExcelTime(value) + if err != nil { + return + } + isNum = excelTime > 0 + if isNum { + t, b = setCellDefault(strconv.FormatFloat(excelTime, 'f', -1, 64)) + } else { + t, b = setCellDefault(value.Format(time.RFC3339Nano)) + } + return +} + +func setCellDuration(value time.Duration) (t string, v string) { + v = strconv.FormatFloat(value.Seconds()/86400.0, 'f', -1, 32) + return +} + // 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 { @@ -165,11 +188,15 @@ func (f *File) SetCellInt(sheet, axis string, value int) error { return err } cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) - cellData.T = "" - cellData.V = strconv.Itoa(value) + cellData.T, cellData.V = setCellInt(value) return err } +func setCellInt(value int) (t string, v string) { + v = strconv.Itoa(value) + return +} + // 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 { @@ -182,13 +209,18 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error { return err } cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) - cellData.T = "b" + cellData.T, cellData.V = setCellBool(value) + return err +} + +func setCellBool(value bool) (t string, v string) { + t = "b" if value { - cellData.V = "1" + v = "1" } else { - cellData.V = "0" + v = "0" } - return err + return } // SetCellFloat sets a floating point value into a cell. The prec parameter @@ -210,11 +242,15 @@ func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int return err } cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) - cellData.T = "" - cellData.V = strconv.FormatFloat(value, 'f', prec, bitSize) + cellData.T, cellData.V = setCellFloat(value, prec, bitSize) return err } +func setCellFloat(value float64, prec, bitSize int) (t string, v string) { + v = strconv.FormatFloat(value, 'f', prec, bitSize) + return +} + // 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 { @@ -226,21 +262,25 @@ func (f *File) SetCellStr(sheet, axis, value string) error { if err != nil { return err } + cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) + cellData.T, cellData.V, cellData.XMLSpace = setCellStr(value) + return err +} + +func setCellStr(value string) (t string, v string, ns xml.Attr) { if len(value) > 32767 { value = value[0:32767] } // Leading and ending space(s) character detection. if len(value) > 0 && (value[0] == 32 || value[len(value)-1] == 32) { - cellData.XMLSpace = xml.Attr{ + ns = xml.Attr{ Name: xml.Name{Space: NameSpaceXML, Local: "space"}, Value: "preserve", } } - - cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) - cellData.T = "str" - cellData.V = value - return err + t = "str" + v = value + return } // SetCellDefault provides a function to set string type value of a cell as @@ -255,11 +295,15 @@ func (f *File) SetCellDefault(sheet, axis, value string) error { return err } cellData.S = f.prepareCellStyle(xlsx, col, cellData.S) - cellData.T = "" - cellData.V = value + cellData.T, cellData.V = setCellDefault(value) return err } +func setCellDefault(value string) (t string, v string) { + v = value + return +} + // GetCellFormula provides a function to get formula from cell by given // worksheet name and axis in XLSX file. func (f *File) GetCellFormula(sheet, axis string) (string, error) { -- 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 --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index 1aeddc1..a659680 100644 --- a/cell.go +++ b/cell.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 66d0272f6af59b5f0c97a304379a795420a43e8b Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 6 Apr 2020 00:23:27 +0800 Subject: Resolve #172, init rich text support --- cell.go | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) (limited to 'cell.go') diff --git a/cell.go b/cell.go index a659680..95cfbbf 100644 --- a/cell.go +++ b/cell.go @@ -457,6 +457,172 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error { return nil } +// SetCellRichText provides a function to set cell with rich text by given +// worksheet. For example: +// +// package main +// +// import ( +// "fmt" +// +// "github.com/360EntSecGroup-Skylar/excelize" +// ) +// +// func main() { +// f := excelize.NewFile() +// if err := f.SetRowHeight("Sheet1", 1, 35); err != nil { +// fmt.Println(err) +// return +// } +// if err := f.SetColWidth("Sheet1", "A", "A", 44); err != nil { +// fmt.Println(err) +// return +// } +// if err := f.SetCellRichText("Sheet1", "A1", []excelize.RichTextRun{ +// { +// Text: "blod", +// Font: &excelize.Font{ +// Bold: true, +// Color: "2354e8", +// Family: "Times New Roman", +// }, +// }, +// { +// Text: " and ", +// Font: &excelize.Font{ +// Family: "Times New Roman", +// }, +// }, +// { +// Text: " italic", +// Font: &excelize.Font{ +// Bold: true, +// Color: "e83723", +// Italic: true, +// Family: "Times New Roman", +// }, +// }, +// { +// Text: "text with color and font-family,", +// Font: &excelize.Font{ +// Bold: true, +// Color: "2354e8", +// Family: "Times New Roman", +// }, +// }, +// { +// Text: "\r\nlarge text with ", +// Font: &excelize.Font{ +// Size: 14, +// Color: "ad23e8", +// }, +// }, +// { +// Text: "strike", +// Font: &excelize.Font{ +// Color: "e89923", +// Strike: true, +// }, +// }, +// { +// Text: " and ", +// Font: &excelize.Font{ +// Size: 14, +// Color: "ad23e8", +// }, +// }, +// { +// Text: "underline.", +// Font: &excelize.Font{ +// Color: "23e833", +// Underline: "single", +// }, +// }, +// }); err != nil { +// fmt.Println(err) +// return +// } +// style, err := f.NewStyle(&excelize.Style{ +// Alignment: &excelize.Alignment{ +// WrapText: true, +// }, +// }) +// if err != nil { +// fmt.Println(err) +// return +// } +// if err := f.SetCellStyle("Sheet1", "A1", "A1", style); err != nil { +// fmt.Println(err) +// return +// } +// if err := f.SaveAs("Book1.xlsx"); err != nil { +// fmt.Println(err) +// } +// } +// +func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error { + ws, err := f.workSheetReader(sheet) + if err != nil { + return err + } + cellData, col, _, err := f.prepareCell(ws, sheet, cell) + if err != nil { + return err + } + cellData.S = f.prepareCellStyle(ws, col, cellData.S) + si := xlsxSI{} + sst := f.sharedStringsReader() + textRuns := []xlsxR{} + for _, textRun := range runs { + run := xlsxR{T: &xlsxT{Val: textRun.Text}} + if strings.ContainsAny(textRun.Text, "\r\n ") { + run.T.Space = "preserve" + } + fnt := textRun.Font + if fnt != nil { + rpr := xlsxRPr{} + if fnt.Bold { + rpr.B = " " + } + if fnt.Italic { + rpr.I = " " + } + if fnt.Strike { + rpr.Strike = " " + } + if fnt.Underline != "" { + rpr.U = &attrValString{Val: &fnt.Underline} + } + if fnt.Family != "" { + rpr.RFont = &attrValString{Val: &fnt.Family} + } + if fnt.Size > 0.0 { + rpr.Sz = &attrValFloat{Val: &fnt.Size} + } + if fnt.Color != "" { + rpr.Color = &xlsxColor{RGB: getPaletteColor(fnt.Color)} + } + run.RPr = &rpr + } + textRuns = append(textRuns, run) + } + si.R = textRuns + sst.SI = append(sst.SI, si) + sst.Count++ + sst.UniqueCount++ + cellData.T, cellData.V = "s", strconv.Itoa(len(sst.SI)-1) + f.addContentTypePart(0, "sharedStrings") + rels := f.relsReader("xl/_rels/workbook.xml.rels") + for _, rel := range rels.Relationships { + if rel.Target == "sharedStrings.xml" { + return err + } + } + // Update xl/_rels/workbook.xml.rels + f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipSharedStrings, "sharedStrings.xml", "") + return err +} + // SetSheetRow writes an array to row by given worksheet name, starting // coordinate and a pointer to array type 'slice'. For example, writes an // array to row 6 start with the cell B6 on Sheet1: -- cgit v1.2.1 From e36650f4ffd3e305d2c3834620f97ec382cf6faf Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 9 Apr 2020 01:00:14 +0800 Subject: Resolve #598, filter support for AddPivotTable --- cell.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index 95cfbbf..8e7ede1 100644 --- a/cell.go +++ b/cell.go @@ -458,7 +458,8 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error { } // SetCellRichText provides a function to set cell with rich text by given -// worksheet. For example: +// worksheet. For example, set rich text on the A1 cell of the worksheet named +// Sheet1: // // package main // -- 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 --- cell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index 8e7ede1..a69f4d9 100644 --- a/cell.go +++ b/cell.go @@ -337,7 +337,7 @@ func (f *File) SetCellFormula(sheet, axis, formula string, opts ...FormulaOpts) } if formula == "" { cellData.F = nil - f.deleteCalcChain(f.GetSheetIndex(sheet), axis) + f.deleteCalcChain(f.getSheetID(sheet), axis) return err } -- cgit v1.2.1 From 882abb80988b7c50286dd2e6c6589fab10662db6 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 10 May 2020 16:56:08 +0800 Subject: - formula engine: reduce cyclomatic complexity - styles: allow empty and default cell formats, #628 --- cell.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cell.go') diff --git a/cell.go b/cell.go index a69f4d9..63db194 100644 --- a/cell.go +++ b/cell.go @@ -730,9 +730,9 @@ func (f *File) formattedValue(s int, v string) string { return v } styleSheet := f.stylesReader() - ok := builtInNumFmtFunc[styleSheet.CellXfs.Xf[s].NumFmtID] + ok := builtInNumFmtFunc[*styleSheet.CellXfs.Xf[s].NumFmtID] if ok != nil { - return ok(styleSheet.CellXfs.Xf[s].NumFmtID, v) + return ok(*styleSheet.CellXfs.Xf[s].NumFmtID, v) } return v } -- cgit v1.2.1