summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--README.md20
-rw-r--r--README_zh.md20
-rw-r--r--cell.go16
-rw-r--r--chart.go11
-rw-r--r--col.go12
-rw-r--r--comment.go32
-rw-r--r--datavalidation.go233
-rw-r--r--datavalidation_test.go57
-rw-r--r--date.go22
-rw-r--r--date_test.go54
-rw-r--r--excelize.go12
-rw-r--r--excelize.pngbin54188 -> 62974 bytes
-rw-r--r--excelize_test.go71
-rw-r--r--file.go31
-rw-r--r--go.mod1
-rw-r--r--hsl.go56
-rw-r--r--lib.go53
-rw-r--r--logo.pngbin4208 -> 7085 bytes
-rw-r--r--picture.go89
-rw-r--r--rows.go11
-rw-r--r--shape.go9
-rw-r--r--sheet.go239
-rw-r--r--sheetpr.go29
-rw-r--r--sheetpr_test.go8
-rw-r--r--sheetview.go19
-rw-r--r--sheetview_test.go18
-rw-r--r--styles.go69
-rw-r--r--table.go17
-rw-r--r--templates.go9
-rw-r--r--[-rwxr-xr-x]test/Book1.xlsxbin23099 -> 23153 bytes
-rw-r--r--test/images/excel.gifbin4952 -> 7221 bytes
-rw-r--r--test/images/excel.jpgbin3960 -> 5376 bytes
-rw-r--r--test/images/excel.pngbin8991 -> 13233 bytes
-rw-r--r--vmlDrawing.go9
-rw-r--r--xmlChart.go13
-rw-r--r--xmlComments.go17
-rw-r--r--xmlContentTypes.go9
-rw-r--r--xmlDecodeDrawing.go9
-rw-r--r--xmlDrawing.go50
-rw-r--r--xmlSharedStrings.go9
-rw-r--r--xmlStyles.go9
-rw-r--r--xmlTable.go9
-rw-r--r--xmlTheme.go9
-rw-r--r--xmlWorkbook.go11
-rw-r--r--xmlWorksheet.go108
46 files changed, 1206 insertions, 275 deletions
diff --git a/.travis.yml b/.travis.yml
index 26ca7b2..c2f0f90 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,7 @@ go:
- 1.8.x
- 1.9.x
- 1.10.x
+ - 1.11.x
os:
- linux
diff --git a/README.md b/README.md
index 61ac2d6..e0fbc27 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,15 @@
-![Excelize](./excelize.png "Excelize")
+<p align="center"><img width="650" src="./excelize.png" alt="Excelize logo"></p>
-# Excelize
+<p align="center">
+ <a href="https://travis-ci.org/360EntSecGroup-Skylar/excelize"><img src="https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master" alt="Build Status"></a>
+ <a href="https://codecov.io/gh/360EntSecGroup-Skylar/excelize"><img src="https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
+ <a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
+ <a href="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize"><img src="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize?status.svg" alt="GoDoc"></a>
+ <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
+ <a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
+</p>
-[![Build Status](https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master)](https://travis-ci.org/360EntSecGroup-Skylar/excelize)
-[![Code Coverage](https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg)](https://codecov.io/gh/360EntSecGroup-Skylar/excelize)
-[![Go Report Card](https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize)](https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize)
-[![GoDoc](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize?status.svg)](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize)
-[![Licenses](https://img.shields.io/badge/license-bsd-orange.svg)](https://opensource.org/licenses/BSD-3-Clause)
-[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/xuri)
+# Excelize
## Introduction
@@ -88,7 +90,7 @@ func main() {
With Excelize chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your worksheet at all.
-![Excelize](./test/images/chart.png "Excelize")
+<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p>
```go
package main
diff --git a/README_zh.md b/README_zh.md
index 49680d1..6be0f92 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -1,13 +1,15 @@
-![Excelize](./excelize.png "Excelize")
+<p align="center"><img width="650" src="./excelize.png" alt="Excelize logo"></p>
-# Excelize
+<p align="center">
+ <a href="https://travis-ci.org/360EntSecGroup-Skylar/excelize"><img src="https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master" alt="Build Status"></a>
+ <a href="https://codecov.io/gh/360EntSecGroup-Skylar/excelize"><img src="https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
+ <a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
+ <a href="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize"><img src="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize?status.svg" alt="GoDoc"></a>
+ <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
+ <a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
+</p>
-[![Build Status](https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master)](https://travis-ci.org/360EntSecGroup-Skylar/excelize)
-[![Code Coverage](https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg)](https://codecov.io/gh/360EntSecGroup-Skylar/excelize)
-[![Go Report Card](https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize)](https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize)
-[![GoDoc](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize?status.svg)](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize)
-[![Licenses](https://img.shields.io/badge/license-bsd-orange.svg)](https://opensource.org/licenses/BSD-3-Clause)
-[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/xuri)
+# Excelize
## 简介
@@ -88,7 +90,7 @@ func main() {
使用 Excelize 生成图表十分简单,仅需几行代码。您可以根据工作表中的已有数据构建图表,或向工作表中添加数据并创建图表。
-![Excelize](./test/images/chart.png "Excelize")
+<p align="center"><img width="650" src="./test/images/chart.png" alt="Excelize"></p>
```go
package main
diff --git a/cell.go b/cell.go
index 5ec5976..aa4067f 100644
--- a/cell.go
+++ b/cell.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -235,12 +244,13 @@ func (f *File) GetCellFormula(sheet, axis string) string {
if xlsx.SheetData.Row[k].R == row {
for i := range xlsx.SheetData.Row[k].C {
if axis == xlsx.SheetData.Row[k].C[i].R {
+ if xlsx.SheetData.Row[k].C[i].F == nil {
+ continue
+ }
if xlsx.SheetData.Row[k].C[i].F.T == STCellFormulaTypeShared {
return getSharedForumula(xlsx, xlsx.SheetData.Row[k].C[i].F.Si)
}
- if xlsx.SheetData.Row[k].C[i].F != nil {
- return xlsx.SheetData.Row[k].C[i].F.Content
- }
+ return xlsx.SheetData.Row[k].C[i].F.Content
}
}
}
diff --git a/chart.go b/chart.go
index 8e1d7e9..edfcab7 100644
--- a/chart.go
+++ b/chart.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -1088,7 +1097,7 @@ func (f *File) drawingParser(drawingXML string, content *xlsxWsDr) int {
_, ok := f.XLSX[drawingXML]
if ok { // Append Model
decodeWsDr := decodeWsDr{}
- _ = xml.Unmarshal([]byte(f.readXML(drawingXML)), &decodeWsDr)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(drawingXML)), &decodeWsDr)
content.R = decodeWsDr.R
cNvPrID = len(decodeWsDr.OneCellAnchor) + len(decodeWsDr.TwoCellAnchor) + 1
for _, v := range decodeWsDr.OneCellAnchor {
diff --git a/col.go b/col.go
index e3870ee..05405bd 100644
--- a/col.go
+++ b/col.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -328,7 +337,8 @@ func (f *File) RemoveCol(sheet, column string) {
f.adjustHelper(sheet, col, -1, -1)
}
-// Completion column element tags of XML in a sheet.
+// completeCol provieds function to completion column element tags of XML in a
+// sheet.
func completeCol(xlsx *xlsxWorksheet, row, cell int) {
buffer := bytes.Buffer{}
for r := range xlsx.SheetData.Row {
diff --git a/comment.go b/comment.go
index 8bf4fd3..9031aad 100644
--- a/comment.go
+++ b/comment.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -21,8 +30,8 @@ func parseFormatCommentsSet(formatSet string) (*formatComment, error) {
// GetComments retrieves all comments and returns a map of worksheet name to
// the worksheet comments.
-func (f *File) GetComments() (comments map[string]*xlsxComments) {
- comments = map[string]*xlsxComments{}
+func (f *File) GetComments() (comments map[string][]Comment) {
+ comments = map[string][]Comment{}
for n := range f.sheetMap {
commentID := f.GetSheetIndex(n)
commentsXML := "xl/comments" + strconv.Itoa(commentID) + ".xml"
@@ -30,7 +39,20 @@ func (f *File) GetComments() (comments map[string]*xlsxComments) {
if ok {
d := xlsxComments{}
xml.Unmarshal([]byte(c), &d)
- comments[n] = &d
+ sheetComments := []Comment{}
+ for _, comment := range d.CommentList.Comment {
+ sheetComment := Comment{}
+ if comment.AuthorID < len(d.Authors) {
+ sheetComment.Author = d.Authors[comment.AuthorID].Author
+ }
+ sheetComment.Ref = comment.Ref
+ sheetComment.AuthorID = comment.AuthorID
+ for _, text := range comment.Text.R {
+ sheetComment.Text += text.T
+ }
+ sheetComments = append(sheetComments, sheetComment)
+ }
+ comments[n] = sheetComments
}
}
return
@@ -160,7 +182,7 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
c, ok := f.XLSX[drawingVML]
if ok {
d := decodeVmlDrawing{}
- _ = xml.Unmarshal([]byte(c), &d)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(c), &d)
for _, v := range d.Shape {
s := xlsxShape{
ID: "_x0000_s1025",
@@ -230,7 +252,7 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
c, ok := f.XLSX[commentsXML]
if ok {
d := xlsxComments{}
- _ = xml.Unmarshal([]byte(c), &d)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(c), &d)
comments.CommentList.Comment = append(comments.CommentList.Comment, d.CommentList.Comment...)
}
comments.CommentList.Comment = append(comments.CommentList.Comment, cmt)
diff --git a/datavalidation.go b/datavalidation.go
new file mode 100644
index 0000000..5ebd61f
--- /dev/null
+++ b/datavalidation.go
@@ -0,0 +1,233 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
+package excelize
+
+import (
+ "fmt"
+ "strings"
+)
+
+// DataValidationType defined the type of data validation.
+type DataValidationType int
+
+// Data validation types.
+const (
+ _DataValidationType = iota
+ typeNone // inline use
+ DataValidationTypeCustom
+ DataValidationTypeDate
+ DataValidationTypeDecimal
+ typeList // inline use
+ DataValidationTypeTextLeng
+ DataValidationTypeTime
+ // DataValidationTypeWhole Integer
+ DataValidationTypeWhole
+)
+
+const (
+ // dataValidationFormulaStrLen 255 characters+ 2 quotes
+ dataValidationFormulaStrLen = 257
+ // dataValidationFormulaStrLenErr
+ dataValidationFormulaStrLenErr = "data validation must be 0-255 characters"
+)
+
+// DataValidationErrorStyle defined the style of data validation error alert.
+type DataValidationErrorStyle int
+
+// Data validation error styles.
+const (
+ _ DataValidationErrorStyle = iota
+ DataValidationErrorStyleStop
+ DataValidationErrorStyleWarning
+ DataValidationErrorStyleInformation
+)
+
+// Data validation error styles.
+const (
+ styleStop = "stop"
+ styleWarning = "warning"
+ styleInformation = "information"
+)
+
+// DataValidationOperator operator enum.
+type DataValidationOperator int
+
+// Data validation operators.
+const (
+ _DataValidationOperator = iota
+ DataValidationOperatorBetween
+ DataValidationOperatorEqual
+ DataValidationOperatorGreaterThan
+ DataValidationOperatorGreaterThanOrEqual
+ DataValidationOperatorLessThan
+ DataValidationOperatorLessThanOrEqual
+ DataValidationOperatorNotBetween
+ DataValidationOperatorNotEqual
+)
+
+// NewDataValidation return data validation struct.
+func NewDataValidation(allowBlank bool) *DataValidation {
+ return &DataValidation{
+ AllowBlank: allowBlank,
+ ShowErrorMessage: false,
+ ShowInputMessage: false,
+ }
+}
+
+// SetError set error notice.
+func (dd *DataValidation) SetError(style DataValidationErrorStyle, title, msg string) {
+ dd.Error = &msg
+ dd.ErrorTitle = &title
+ strStyle := styleStop
+ switch style {
+ case DataValidationErrorStyleStop:
+ strStyle = styleStop
+ case DataValidationErrorStyleWarning:
+ strStyle = styleWarning
+ case DataValidationErrorStyleInformation:
+ strStyle = styleInformation
+
+ }
+ dd.ShowErrorMessage = true
+ dd.ErrorStyle = &strStyle
+}
+
+// SetInput set prompt notice.
+func (dd *DataValidation) SetInput(title, msg string) {
+ dd.ShowInputMessage = true
+ dd.PromptTitle = &title
+ dd.Prompt = &msg
+}
+
+// SetDropList data validation list.
+func (dd *DataValidation) SetDropList(keys []string) error {
+ dd.Formula1 = "\"" + strings.Join(keys, ",") + "\""
+ dd.Type = convDataValidationType(typeList)
+ return nil
+}
+
+// SetRange provides function to set data validation range in drop list.
+func (dd *DataValidation) SetRange(f1, f2 int, t DataValidationType, o DataValidationOperator) error {
+ formula1 := fmt.Sprintf("%d", f1)
+ formula2 := fmt.Sprintf("%d", f2)
+ if dataValidationFormulaStrLen < len(dd.Formula1) || dataValidationFormulaStrLen < len(dd.Formula2) {
+ return fmt.Errorf(dataValidationFormulaStrLenErr)
+ }
+
+ dd.Formula1 = formula1
+ dd.Formula2 = formula2
+ dd.Type = convDataValidationType(t)
+ dd.Operator = convDataValidationOperatior(o)
+ return nil
+}
+
+// SetSqrefDropList provides set data validation on a range with source
+// reference range of the worksheet by given data validation object and
+// worksheet name. The data validation object can be created by
+// NewDataValidation function. For example, set data validation on
+// Sheet1!A7:B8 with validation criteria source Sheet1!E1:E3 settings, create
+// in-cell dropdown by allowing list source:
+//
+// dvRange := excelize.NewDataValidation(true)
+// dvRange.Sqref = "A7:B8"
+// dvRange.SetSqrefDropList("E1:E3", true)
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+func (dd *DataValidation) SetSqrefDropList(sqref string, isCurrentSheet bool) error {
+ if isCurrentSheet {
+ dd.Formula1 = sqref
+ dd.Type = convDataValidationType(typeList)
+ return nil
+ }
+ return fmt.Errorf("cross-sheet sqref cell are not supported")
+}
+
+// SetSqref provides function to set data validation range in drop list.
+func (dd *DataValidation) SetSqref(sqref string) {
+ if dd.Sqref == "" {
+ dd.Sqref = sqref
+ } else {
+ dd.Sqref = fmt.Sprintf("%s %s", dd.Sqref, sqref)
+ }
+}
+
+// convDataValidationType get excel data validation type.
+func convDataValidationType(t DataValidationType) string {
+ typeMap := map[DataValidationType]string{
+ typeNone: "none",
+ DataValidationTypeCustom: "custom",
+ DataValidationTypeDate: "date",
+ DataValidationTypeDecimal: "decimal",
+ typeList: "list",
+ DataValidationTypeTextLeng: "textLength",
+ DataValidationTypeTime: "time",
+ DataValidationTypeWhole: "whole",
+ }
+
+ return typeMap[t]
+
+}
+
+// convDataValidationOperatior get excel data validation operator.
+func convDataValidationOperatior(o DataValidationOperator) string {
+ typeMap := map[DataValidationOperator]string{
+ DataValidationOperatorBetween: "between",
+ DataValidationOperatorEqual: "equal",
+ DataValidationOperatorGreaterThan: "greaterThan",
+ DataValidationOperatorGreaterThanOrEqual: "greaterThanOrEqual",
+ DataValidationOperatorLessThan: "lessThan",
+ DataValidationOperatorLessThanOrEqual: "lessThanOrEqual",
+ DataValidationOperatorNotBetween: "notBetween",
+ DataValidationOperatorNotEqual: "notEqual",
+ }
+
+ return typeMap[o]
+
+}
+
+// AddDataValidation provides set data validation on a range of the worksheet
+// by given data validation object and worksheet name. The data validation
+// object can be created by NewDataValidation function.
+//
+// Example 1, set data validation on Sheet1!A1:B2 with validation criteria
+// settings, show error alert after invalid data is entered with "Stop" style
+// and custom title "error body":
+//
+// dvRange := excelize.NewDataValidation(true)
+// dvRange.Sqref = "A1:B2"
+// dvRange.SetRange(10, 20, excelize.DataValidationTypeWhole, excelize.DataValidationOperatorBetween)
+// dvRange.SetError(excelize.DataValidationErrorStyleStop, "error title", "error body")
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+// Example 2, set data validation on Sheet1!A3:B4 with validation criteria
+// settings, and show input message when cell is selected:
+//
+// dvRange = excelize.NewDataValidation(true)
+// dvRange.Sqref = "A3:B4"
+// dvRange.SetRange(10, 20, excelize.DataValidationTypeWhole, excelize.DataValidationOperatorGreaterThan)
+// dvRange.SetInput("input title", "input body")
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+// Example 3, set data validation on Sheet1!A5:B6 with validation criteria
+// settings, create in-cell dropdown by allowing list source:
+//
+// dvRange = excelize.NewDataValidation(true)
+// dvRange.Sqref = "A5:B6"
+// dvRange.SetDropList([]string{"1", "2", "3"})
+// xlsx.AddDataValidation("Sheet1", dvRange)
+//
+func (f *File) AddDataValidation(sheet string, dv *DataValidation) {
+ xlsx := f.workSheetReader(sheet)
+ if nil == xlsx.DataValidations {
+ xlsx.DataValidations = new(xlsxDataValidations)
+ }
+ xlsx.DataValidations.DataValidation = append(xlsx.DataValidations.DataValidation, dv)
+ xlsx.DataValidations.Count = len(xlsx.DataValidations.DataValidation)
+}
diff --git a/datavalidation_test.go b/datavalidation_test.go
new file mode 100644
index 0000000..39dd229
--- /dev/null
+++ b/datavalidation_test.go
@@ -0,0 +1,57 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
+package excelize
+
+import "testing"
+
+func TestDataValidation(t *testing.T) {
+ xlsx := NewFile()
+
+ dvRange := NewDataValidation(true)
+ dvRange.Sqref = "A1:B2"
+ dvRange.SetRange(10, 20, DataValidationTypeWhole, DataValidationOperatorBetween)
+ dvRange.SetError(DataValidationErrorStyleStop, "error title", "error body")
+ dvRange.SetError(DataValidationErrorStyleWarning, "error title", "error body")
+ dvRange.SetError(DataValidationErrorStyleInformation, "error title", "error body")
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ dvRange = NewDataValidation(true)
+ dvRange.Sqref = "A3:B4"
+ dvRange.SetRange(10, 20, DataValidationTypeWhole, DataValidationOperatorGreaterThan)
+ dvRange.SetInput("input title", "input body")
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ dvRange = NewDataValidation(true)
+ dvRange.Sqref = "A5:B6"
+ dvRange.SetDropList([]string{"1", "2", "3"})
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ xlsx.SetCellStr("Sheet1", "E1", "E1")
+ xlsx.SetCellStr("Sheet1", "E2", "E2")
+ xlsx.SetCellStr("Sheet1", "E3", "E3")
+ dvRange = NewDataValidation(true)
+ dvRange.SetSqref("A7:B8")
+ dvRange.SetSqref("A7:B8")
+ dvRange.SetSqrefDropList("$E$1:$E$3", true)
+ err := dvRange.SetSqrefDropList("$E$1:$E$3", false)
+ t.Log(err)
+ xlsx.AddDataValidation("Sheet1", dvRange)
+
+ dvRange = NewDataValidation(true)
+ dvRange.SetDropList(make([]string, 258))
+ err = dvRange.SetRange(10, 20, DataValidationTypeWhole, DataValidationOperatorGreaterThan)
+ t.Log(err)
+
+ // Test write file to given path.
+ err = xlsx.SaveAs("./test/Book_data_validation.xlsx")
+ if err != nil {
+ t.Error(err)
+ }
+}
diff --git a/date.go b/date.go
index 7233661..a0b8ceb 100644
--- a/date.go
+++ b/date.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -81,12 +90,13 @@ func julianDateToGregorianTime(part1, part2 float64) time.Time {
return time.Date(year, time.Month(month), day, hours, minutes, seconds, nanoseconds, time.UTC)
}
-// By this point generations of programmers have repeated the algorithm sent
-// to the editor of "Communications of the ACM" in 1968 (published in CACM,
-// volume 11, number 10, October 1968, p.657). None of those programmers seems
-// to have found it necessary to explain the constants or variable names set
-// out by Henry F. Fliegel and Thomas C. Van Flandern. Maybe one day I'll buy
-// that jounal and expand an explanation here - that day is not today.
+// doTheFliegelAndVanFlandernAlgorithm; By this point generations of
+// programmers have repeated the algorithm sent to the editor of
+// "Communications of the ACM" in 1968 (published in CACM, volume 11, number
+// 10, October 1968, p.657). None of those programmers seems to have found it
+// necessary to explain the constants or variable names set out by Henry F.
+// Fliegel and Thomas C. Van Flandern. Maybe one day I'll buy that jounal and
+// expand an explanation here - that day is not today.
func doTheFliegelAndVanFlandernAlgorithm(jd int) (day, month, year int) {
l := jd + 68569
n := (4 * l) / 146097
diff --git a/date_test.go b/date_test.go
index bf071e0..06421b8 100644
--- a/date_test.go
+++ b/date_test.go
@@ -1,42 +1,42 @@
package excelize
import (
- "testing"
- "time"
+ "testing"
+ "time"
)
type dateTest struct {
- ExcelValue float64
- GoValue time.Time
+ ExcelValue float64
+ GoValue time.Time
}
func TestTimeToExcelTime(t *testing.T) {
- trueExpectedInputList := []dateTest {
- {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
- {25569.0, time.Unix(0, 0)},
- {43269.0, time.Date(2018, 6, 18, 0, 0, 0, 0, time.UTC)},
- {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
- }
+ trueExpectedInputList := []dateTest{
+ {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
+ {25569.0, time.Unix(0, 0)},
+ {43269.0, time.Date(2018, 6, 18, 0, 0, 0, 0, time.UTC)},
+ {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
+ }
- for _, test := range trueExpectedInputList {
- if test.ExcelValue != timeToExcelTime(test.GoValue) {
- t.Fatalf("Expected %v from %v = true, got %v\n", test.ExcelValue, test.GoValue, timeToExcelTime(test.GoValue))
- }
- }
+ for _, test := range trueExpectedInputList {
+ if test.ExcelValue != timeToExcelTime(test.GoValue) {
+ t.Fatalf("Expected %v from %v = true, got %v\n", test.ExcelValue, test.GoValue, timeToExcelTime(test.GoValue))
+ }
+ }
}
func TestTimeFromExcelTime(t *testing.T) {
- trueExpectedInputList := []dateTest {
- {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
- {60.0, time.Date(1900, 2, 28, 0, 0, 0, 0, time.UTC)},
- {61.0, time.Date(1900, 3, 1, 0, 0, 0, 0, time.UTC)},
- {41275.0, time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)},
- {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
- }
+ trueExpectedInputList := []dateTest{
+ {0.0, time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)},
+ {60.0, time.Date(1900, 2, 28, 0, 0, 0, 0, time.UTC)},
+ {61.0, time.Date(1900, 3, 1, 0, 0, 0, 0, time.UTC)},
+ {41275.0, time.Date(2013, 1, 1, 0, 0, 0, 0, time.UTC)},
+ {401769.0, time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)},
+ }
- for _, test := range trueExpectedInputList {
- if test.GoValue != timeFromExcelTime(test.ExcelValue, false) {
- t.Fatalf("Expected %v from %v = true, got %v\n", test.GoValue, test.ExcelValue, timeFromExcelTime(test.ExcelValue, false))
- }
- }
+ for _, test := range trueExpectedInputList {
+ if test.GoValue != timeFromExcelTime(test.ExcelValue, false) {
+ t.Fatalf("Expected %v from %v = true, got %v\n", test.GoValue, test.ExcelValue, timeFromExcelTime(test.ExcelValue, false))
+ }
+ }
}
diff --git a/excelize.go b/excelize.go
index 013f357..4b4aa32 100644
--- a/excelize.go
+++ b/excelize.go
@@ -1,3 +1,13 @@
+// Copyright 2016 - 2018 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.
+
+// 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.
+//
+// See https://xuri.me/excelize for more information about this package.
package excelize
import (
@@ -90,7 +100,7 @@ func (f *File) workSheetReader(sheet string) *xlsxWorksheet {
}
if f.Sheet[name] == nil {
var xlsx xlsxWorksheet
- _ = xml.Unmarshal(f.readXML(name), &xlsx)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(name)), &xlsx)
if f.checked == nil {
f.checked = make(map[string]bool)
}
diff --git a/excelize.png b/excelize.png
index 9f220b5..5d0766b 100644
--- a/excelize.png
+++ b/excelize.png
Binary files differ
diff --git a/excelize_test.go b/excelize_test.go
index f55ac01..6eb3692 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -21,9 +21,9 @@ func TestOpenFile(t *testing.T) {
t.Error(err)
}
// Test get all the rows in a not exists worksheet.
- rows := xlsx.GetRows("Sheet4")
+ xlsx.GetRows("Sheet4")
// Test get all the rows in a worksheet.
- rows = xlsx.GetRows("Sheet2")
+ rows := xlsx.GetRows("Sheet2")
for _, row := range rows {
for _, cell := range row {
t.Log(cell, "\t")
@@ -128,7 +128,7 @@ func TestOpenFile(t *testing.T) {
}
err = xlsx.Save()
if err != nil {
- t.Log(err)
+ t.Error(err)
}
// Test write file to not exist directory.
err = xlsx.SaveAs("")
@@ -162,6 +162,24 @@ func TestAddPicture(t *testing.T) {
if err != nil {
t.Log(err)
}
+ err = xlsx.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", "jpg", make([]byte, 1))
+ if err != nil {
+ t.Log(err)
+ }
+ // Test add picture to worksheet with invalid file data.
+ err = xlsx.AddPictureFromBytes("Sheet1", "G21", "", "Excel Logo", ".jpg", make([]byte, 1))
+ if err != nil {
+ t.Log(err)
+ }
+ file, err := ioutil.ReadFile("./test/images/excel.jpg")
+ if err != nil {
+ t.Error(err)
+ }
+ // Test add picture to worksheet from bytes.
+ err = xlsx.AddPictureFromBytes("Sheet1", "Q1", "", "Excel Logo", ".jpg", file)
+ if err != nil {
+ t.Log(err)
+ }
// Test write file to given path.
err = xlsx.SaveAs("./test/Book2.xlsx")
if err != nil {
@@ -211,9 +229,14 @@ func TestNewFile(t *testing.T) {
if err != nil {
t.Error(err)
}
- // Test add picture to worksheet with invalid formatset
+ // Test add picture to worksheet without formatset.
err = xlsx.AddPicture("Sheet1", "C2", "./test/images/excel.png", "")
if err != nil {
+ t.Error(err)
+ }
+ // Test add picture to worksheet with invalid formatset.
+ err = xlsx.AddPicture("Sheet1", "C2", "./test/images/excel.png", `{`)
+ if err != nil {
t.Log(err)
}
err = xlsx.SaveAs("./test/Book3.xlsx")
@@ -548,7 +571,7 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
xlsx.SetCellValue("Sheet1", "A1", 42920.5)
xlsx.SetCellValue("Sheet1", "A2", 42920.5)
- style, err = xlsx.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
+ _, err = xlsx.NewStyle(`{"number_format": 26, "lang": "zh-tw"}`)
if err != nil {
t.Log(err)
}
@@ -1225,6 +1248,44 @@ func TestHSL(t *testing.T) {
t.Log(RGBToHSL(250, 50, 100))
}
+func TestSearchSheet(t *testing.T) {
+ xlsx, err := OpenFile("./test/SharedStrings.xlsx")
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ // Test search in a not exists worksheet.
+ t.Log(xlsx.SearchSheet("Sheet4", ""))
+ // Test search a not exists value.
+ t.Log(xlsx.SearchSheet("Sheet1", "X"))
+ t.Log(xlsx.SearchSheet("Sheet1", "A"))
+}
+
+func TestProtectSheet(t *testing.T) {
+ xlsx := NewFile()
+ xlsx.ProtectSheet("Sheet1", nil)
+ xlsx.ProtectSheet("Sheet1", &FormatSheetProtection{
+ Password: "password",
+ EditScenarios: false,
+ })
+ err := xlsx.SaveAs("./test/Book_protect_sheet.xlsx")
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestUnprotectSheet(t *testing.T) {
+ xlsx, err := OpenFile("./test/Book1.xlsx")
+ if err != nil {
+ t.Error(err)
+ }
+ xlsx.UnprotectSheet("Sheet1")
+ err = xlsx.Save()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
func trimSliceSpace(s []string) []string {
for {
if len(s) > 0 && s[len(s)-1] == "" {
diff --git a/file.go b/file.go
index a45fc28..1f69005 100644
--- a/file.go
+++ b/file.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -43,7 +52,7 @@ func NewFile() *File {
// Save provides a function to override the xlsx file with origin path.
func (f *File) Save() error {
if f.Path == "" {
- return fmt.Errorf("No path defined for file, consider File.WriteTo or File.Write")
+ return fmt.Errorf("no path defined for file, consider File.WriteTo or File.Write")
}
return f.SaveAs(f.Path)
}
@@ -67,6 +76,15 @@ func (f *File) Write(w io.Writer) error {
// WriteTo implements io.WriterTo to write the file.
func (f *File) WriteTo(w io.Writer) (int64, error) {
+ buf, err := f.WriteToBuffer()
+ if err != nil {
+ return 0, err
+ }
+ return buf.WriteTo(w)
+}
+
+// WriteToBuffer provides a function to get bytes.Buffer from the saved file.
+func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
buf := new(bytes.Buffer)
zw := zip.NewWriter(buf)
f.contentTypesWriter()
@@ -77,17 +95,12 @@ func (f *File) WriteTo(w io.Writer) (int64, error) {
for path, content := range f.XLSX {
fi, err := zw.Create(path)
if err != nil {
- return 0, err
+ return buf, err
}
_, err = fi.Write(content)
if err != nil {
- return 0, err
+ return buf, err
}
}
- err := zw.Close()
- if err != nil {
- return 0, err
- }
-
- return buf.WriteTo(w)
+ return buf, zw.Close()
}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..0536371
--- /dev/null
+++ b/go.mod
@@ -0,0 +1 @@
+module github.com/360EntSecGroup-Skylar/excelize
diff --git a/hsl.go b/hsl.go
index bd868b1..c30c165 100644
--- a/hsl.go
+++ b/hsl.go
@@ -1,32 +1,30 @@
-/*
-Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+// Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package excelize
diff --git a/lib.go b/lib.go
index 8013efa..cf43dc9 100644
--- a/lib.go
+++ b/lib.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -6,6 +15,8 @@ import (
"io"
"log"
"math"
+ "strconv"
+ "strings"
"unicode"
)
@@ -174,3 +185,45 @@ func parseFormatSet(formatSet string) []byte {
}
return []byte("{}")
}
+
+// namespaceStrictToTransitional provides a method to convert Strict and
+// Transitional namespaces.
+func namespaceStrictToTransitional(content []byte) []byte {
+ var namespaceTranslationDic = map[string]string{
+ StrictSourceRelationship: SourceRelationship,
+ StrictSourceRelationshipChart: SourceRelationshipChart,
+ StrictSourceRelationshipComments: SourceRelationshipComments,
+ StrictSourceRelationshipImage: SourceRelationshipImage,
+ StrictNameSpaceSpreadSheet: NameSpaceSpreadSheet,
+ }
+ for s, n := range namespaceTranslationDic {
+ content = bytes.Replace(content, []byte(s), []byte(n), -1)
+ }
+ return content
+}
+
+// genSheetPasswd provides a method to generate password for worksheet
+// protection by given plaintext. When an Excel sheet is being protected with
+// a password, a 16-bit (two byte) long hash is generated. To verify a
+// password, it is compared to the hash. Obviously, if the input data volume
+// is great, numerous passwords will match the same hash. Here is the
+// algorithm to create the hash value:
+//
+// take the ASCII values of all characters shift left the first character 1 bit, the second 2 bits and so on (use only the lower 15 bits and rotate all higher bits, the highest bit of the 16-bit value is always 0 [signed short])
+// XOR all these values
+// XOR the count of characters
+// XOR the constant 0xCE4B
+func genSheetPasswd(plaintext string) string {
+ var password int64 = 0x0000
+ var charPos uint = 1
+ for _, v := range plaintext {
+ value := int64(v) << charPos
+ charPos++
+ rotatedBits := value >> 15 // rotated bits beyond bit 15
+ value &= 0x7fff // first 15 bits
+ password ^= (value | rotatedBits)
+ }
+ password ^= int64(len(plaintext))
+ password ^= 0xCE4B
+ return strings.ToUpper(strconv.FormatInt(password, 16))
+}
diff --git a/logo.png b/logo.png
index 4853698..32235b8 100644
--- a/logo.png
+++ b/logo.png
Binary files differ
diff --git a/picture.go b/picture.go
index 97e72a6..9efd875 100644
--- a/picture.go
+++ b/picture.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -78,27 +87,66 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
// positioning is move and size with cells.
func (f *File) AddPicture(sheet, cell, picture, format string) error {
var err error
- var drawingHyperlinkRID int
- var hyperlinkType string
// Check picture exists first.
if _, err = os.Stat(picture); os.IsNotExist(err) {
return err
}
ext, ok := supportImageTypes[path.Ext(picture)]
if !ok {
- return errors.New("Unsupported image extension")
+ return errors.New("unsupported image extension")
}
- readFile, err := os.Open(picture)
- if err!=nil{
- return err
+ file, _ := ioutil.ReadFile(picture)
+ _, name := filepath.Split(picture)
+ return f.AddPictureFromBytes(sheet, cell, format, name, ext, file)
+}
+
+// AddPictureFromBytes provides the method to add picture in a sheet by given
+// picture format set (such as offset, scale, aspect ratio setting and print
+// settings), file base name, extension name and file bytes. For example:
+//
+// package main
+//
+// import (
+// "fmt"
+// _ "image/jpeg"
+// "io/ioutil"
+//
+// "github.com/360EntSecGroup-Skylar/excelize"
+// )
+//
+// func main() {
+// xlsx := excelize.NewFile()
+//
+// file, err := ioutil.ReadFile("./image1.jpg")
+// if err != nil {
+// fmt.Println(err)
+// }
+// err = xlsx.AddPictureFromBytes("Sheet1", "A2", "", "Excel Logo", ".jpg", file)
+// if err != nil {
+// fmt.Println(err)
+// }
+// err = xlsx.SaveAs("./Book1.xlsx")
+// if err != nil {
+// fmt.Println(err)
+// }
+// }
+//
+func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string, file []byte) error {
+ var err error
+ var drawingHyperlinkRID int
+ var hyperlinkType string
+ ext, ok := supportImageTypes[extension]
+ if !ok {
+ return errors.New("unsupported image extension")
}
- defer readFile.Close()
- image, _, _ := image.DecodeConfig(readFile)
- _, file := filepath.Split(picture)
formatSet, err := parseFormatPictureSet(format)
if err != nil {
return err
}
+ image, _, err := image.DecodeConfig(bytes.NewReader(file))
+ if err != nil {
+ return err
+ }
// Read sheet data.
xlsx := f.workSheetReader(sheet)
// Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder.
@@ -114,8 +162,8 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
}
drawingHyperlinkRID = f.addDrawingRelationships(drawingID, SourceRelationshipHyperLink, formatSet.Hyperlink, hyperlinkType)
}
- f.addDrawingPicture(sheet, drawingXML, cell, file, image.Width, image.Height, drawingRID, drawingHyperlinkRID, formatSet)
- f.addMedia(picture, ext)
+ f.addDrawingPicture(sheet, drawingXML, cell, name, image.Width, image.Height, drawingRID, drawingHyperlinkRID, formatSet)
+ f.addMedia(file, ext)
f.addContentTypePart(drawingID, "drawings")
return err
}
@@ -137,7 +185,7 @@ func (f *File) addSheetRelationships(sheet, relType, target, targetMode string)
_, ok = f.XLSX[rels]
if ok {
ID.Reset()
- _ = xml.Unmarshal([]byte(f.readXML(rels)), &sheetRels)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels)
rID = len(sheetRels.Relationships) + 1
ID.WriteString("rId")
ID.WriteString(strconv.Itoa(rID))
@@ -163,7 +211,7 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
}
var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
var sheetRels xlsxWorkbookRels
- _ = xml.Unmarshal([]byte(f.readXML(rels)), &sheetRels)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels)
for k, v := range sheetRels.Relationships {
if v.ID == rID {
sheetRels.Relationships = append(sheetRels.Relationships[:k], sheetRels.Relationships[k+1:]...)
@@ -280,7 +328,7 @@ func (f *File) addDrawingRelationships(index int, relType, target, targetMode st
_, ok := f.XLSX[rels]
if ok {
ID.Reset()
- _ = xml.Unmarshal([]byte(f.readXML(rels)), &drawingRels)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &drawingRels)
rID = len(drawingRels.Relationships) + 1
ID.WriteString("rId")
ID.WriteString(strconv.Itoa(rID))
@@ -309,12 +357,11 @@ func (f *File) countMedia() int {
}
// addMedia provides a function to add picture into folder xl/media/image by
-// given file name and extension name.
-func (f *File) addMedia(file, ext string) {
+// given file and extension name.
+func (f *File) addMedia(file []byte, ext string) {
count := f.countMedia()
- dat, _ := ioutil.ReadFile(file)
media := "xl/media/image" + strconv.Itoa(count+1) + ext
- f.XLSX[media] = dat
+ f.XLSX[media] = file
}
// setContentTypePartImageExtensions provides a function to set the content
@@ -401,7 +448,7 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
}
var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
var sheetRels xlsxWorkbookRels
- _ = xml.Unmarshal([]byte(f.readXML(rels)), &sheetRels)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels)
for _, v := range sheetRels.Relationships {
if v.ID == rID {
return v.Target
@@ -441,7 +488,7 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte) {
return "", nil
}
decodeWsDr := decodeWsDr{}
- _ = xml.Unmarshal([]byte(f.readXML(drawingXML)), &decodeWsDr)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(drawingXML)), &decodeWsDr)
cell = strings.ToUpper(cell)
fromCol := string(strings.Map(letterOnlyMapF, cell))
@@ -476,7 +523,7 @@ func (f *File) getDrawingRelationships(rels, rID string) *xlsxWorkbookRelation {
return nil
}
var drawingRels xlsxWorkbookRels
- _ = xml.Unmarshal([]byte(f.readXML(rels)), &drawingRels)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &drawingRels)
for _, v := range drawingRels.Relationships {
if v.ID == rID {
return &v
diff --git a/rows.go b/rows.go
index 521a945..b633633 100644
--- a/rows.go
+++ b/rows.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -240,7 +249,7 @@ func (f *File) sharedStringsReader() *xlsxSST {
if len(ss) == 0 {
ss = f.readXML("xl/SharedStrings.xml")
}
- _ = xml.Unmarshal([]byte(ss), &sharedStrings)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(ss), &sharedStrings)
f.SharedStrings = &sharedStrings
}
return f.SharedStrings
diff --git a/shape.go b/shape.go
index 8fbfbcd..ad87712 100644
--- a/shape.go
+++ b/shape.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
diff --git a/sheet.go b/sheet.go
index 011ecb8..f546561 100644
--- a/sheet.go
+++ b/sheet.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -5,6 +14,8 @@ import (
"encoding/json"
"encoding/xml"
"errors"
+ "fmt"
+ "io/ioutil"
"os"
"path"
"strconv"
@@ -14,26 +25,35 @@ import (
"github.com/mohae/deepcopy"
)
-// NewSheet provides a function to create a new sheet by given worksheet name,
-// when creating a new XLSX file, the default sheet will be create, when you
-// create a new file.
+// NewSheet provides function to create a new sheet by given worksheet name.
+// When creating a new XLSX file, the default sheet will be created. Returns
+// the number of sheets in the workbook (file) after appending the new sheet.
func (f *File) NewSheet(name string) int {
// Check if the worksheet already exists
if f.GetSheetIndex(name) != 0 {
return f.SheetCount
}
+ f.DeleteSheet(name)
f.SheetCount++
+ wb := f.workbookReader()
+ sheetID := 0
+ for _, v := range wb.Sheets.Sheet {
+ if v.SheetID > sheetID {
+ sheetID = v.SheetID
+ }
+ }
+ sheetID++
// Update docProps/app.xml
f.setAppXML()
// Update [Content_Types].xml
- f.setContentTypes(f.SheetCount)
+ f.setContentTypes(sheetID)
// Create new sheet /xl/worksheets/sheet%d.xml
- f.setSheet(f.SheetCount, name)
+ f.setSheet(sheetID, name)
// Update xl/_rels/workbook.xml.rels
- rID := f.addXlsxWorkbookRels(f.SheetCount)
+ rID := f.addXlsxWorkbookRels(sheetID)
// Update xl/workbook.xml
- f.setWorkbook(name, rID)
- return f.SheetCount
+ f.setWorkbook(name, sheetID, rID)
+ return sheetID
}
// contentTypesReader provides a function to get the pointer to the
@@ -41,7 +61,7 @@ func (f *File) NewSheet(name string) int {
func (f *File) contentTypesReader() *xlsxTypes {
if f.ContentTypes == nil {
var content xlsxTypes
- _ = xml.Unmarshal([]byte(f.readXML("[Content_Types].xml")), &content)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML("[Content_Types].xml")), &content)
f.ContentTypes = &content
}
return f.ContentTypes
@@ -61,7 +81,7 @@ func (f *File) contentTypesWriter() {
func (f *File) workbookReader() *xlsxWorkbook {
if f.WorkBook == nil {
var content xlsxWorkbook
- _ = xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML("xl/workbook.xml")), &content)
f.WorkBook = &content
}
return f.WorkBook
@@ -107,7 +127,8 @@ func trimCell(column []xlsxC) []xlsxC {
return col[0:i]
}
-// Read and update property of contents type of XLSX.
+// setContentTypes provides a function to read and update property of contents
+// type of XLSX.
func (f *File) setContentTypes(index int) {
content := f.contentTypesReader()
content.Overrides = append(content.Overrides, xlsxOverride{
@@ -116,7 +137,7 @@ func (f *File) setContentTypes(index int) {
})
}
-// Update sheet property by given index.
+// setSheet provides a function to update sheet property by given index.
func (f *File) setSheet(index int, name string) {
var xlsx xlsxWorksheet
xlsx.Dimension.Ref = "A1"
@@ -130,19 +151,11 @@ func (f *File) setSheet(index int, name string) {
// setWorkbook update workbook property of XLSX. Maximum 31 characters are
// allowed in sheet title.
-func (f *File) setWorkbook(name string, rid int) {
+func (f *File) setWorkbook(name string, sheetID, rid int) {
content := f.workbookReader()
- rID := 0
- for _, v := range content.Sheets.Sheet {
- t, _ := strconv.Atoi(v.SheetID)
- if t > rID {
- rID = t
- }
- }
- rID++
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
Name: trimSheetName(name),
- SheetID: strconv.Itoa(rID),
+ SheetID: sheetID,
ID: "rId" + strconv.Itoa(rid),
})
}
@@ -152,7 +165,7 @@ func (f *File) setWorkbook(name string, rid int) {
func (f *File) workbookRelsReader() *xlsxWorkbookRels {
if f.WorkBookRels == nil {
var content xlsxWorkbookRels
- _ = xml.Unmarshal([]byte(f.readXML("xl/_rels/workbook.xml.rels")), &content)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML("xl/_rels/workbook.xml.rels")), &content)
f.WorkBookRels = &content
}
return f.WorkBookRels
@@ -198,39 +211,44 @@ func (f *File) setAppXML() {
f.saveFileList("docProps/app.xml", []byte(templateDocpropsApp))
}
-// Some tools that read XLSX files have very strict requirements about the
-// structure of the input XML. In particular both Numbers on the Mac and SAS
-// dislike inline XML namespace declarations, or namespace prefixes that don't
-// match the ones that Excel itself uses. This is a problem because the Go XML
-// library doesn't multiple namespace declarations in a single element of a
-// document. This function is a horrible hack to fix that after the XML
-// marshalling is completed.
+// replaceRelationshipsNameSpaceBytes; Some tools that read XLSX files have
+// very strict requirements about the structure of the input XML. In
+// particular both Numbers on the Mac and SAS dislike inline XML namespace
+// declarations, or namespace prefixes that don't match the ones that Excel
+// itself uses. This is a problem because the Go XML library doesn't multiple
+// namespace declarations in a single element of a document. This function is
+// a horrible hack to fix that after the XML marshalling is completed.
func replaceRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte {
oldXmlns := []byte(`<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
newXmlns := []byte(`<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">`)
return bytes.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
}
-// SetActiveSheet provides a function to set default active worksheet of XLSX by
-// given index. Note that active index is different with the index that got by
-// function GetSheetMap, and it should be greater than 0 and less than total
+// SetActiveSheet provides function to set default active worksheet of XLSX by
+// given index. Note that active index is different from the index returned by
+// function GetSheetMap(). It should be greater than 0 and less than total
// worksheet numbers.
func (f *File) SetActiveSheet(index int) {
if index < 1 {
index = 1
}
- index--
- content := f.workbookReader()
- if len(content.BookViews.WorkBookView) > 0 {
- content.BookViews.WorkBookView[0].ActiveTab = index
- } else {
- content.BookViews.WorkBookView = append(content.BookViews.WorkBookView, xlsxWorkBookView{
- ActiveTab: index,
- })
+ wb := f.workbookReader()
+ for activeTab, sheet := range wb.Sheets.Sheet {
+ if sheet.SheetID == index {
+ if len(wb.BookViews.WorkBookView) > 0 {
+ wb.BookViews.WorkBookView[0].ActiveTab = activeTab
+ } else {
+ wb.BookViews.WorkBookView = append(wb.BookViews.WorkBookView, xlsxWorkBookView{
+ ActiveTab: activeTab,
+ })
+ }
+ }
}
- index++
for idx, name := range f.GetSheetMap() {
xlsx := f.workSheetReader(name)
+ if len(xlsx.SheetViews.SheetView) > 0 {
+ xlsx.SheetViews.SheetView[0].TabSelected = false
+ }
if index == idx {
if len(xlsx.SheetViews.SheetView) > 0 {
xlsx.SheetViews.SheetView[0].TabSelected = true
@@ -239,32 +257,20 @@ func (f *File) SetActiveSheet(index int) {
TabSelected: true,
})
}
- } else {
- if len(xlsx.SheetViews.SheetView) > 0 {
- xlsx.SheetViews.SheetView[0].TabSelected = false
- }
}
}
}
-// GetActiveSheetIndex provides a function to get active sheet of XLSX. If not
-// found the active sheet will be return integer 0.
+// GetActiveSheetIndex provides a function to get active sheet index of the
+// XLSX. If not found the active sheet will be return integer 0.
func (f *File) GetActiveSheetIndex() int {
- buffer := bytes.Buffer{}
- content := f.workbookReader()
- for _, v := range content.Sheets.Sheet {
- xlsx := xlsxWorksheet{}
- buffer.WriteString("xl/worksheets/sheet")
- buffer.WriteString(strings.TrimPrefix(v.ID, "rId"))
- buffer.WriteString(".xml")
- _ = xml.Unmarshal([]byte(f.readXML(buffer.String())), &xlsx)
+ for idx, name := range f.GetSheetMap() {
+ xlsx := f.workSheetReader(name)
for _, sheetView := range xlsx.SheetViews.SheetView {
if sheetView.TabSelected {
- ID, _ := strconv.Atoi(strings.TrimPrefix(v.ID, "rId"))
- return ID
+ return idx
}
}
- buffer.Reset()
}
return 0
}
@@ -342,8 +348,9 @@ func (f *File) GetSheetMap() map[int]string {
sheetMap := map[int]string{}
for _, v := range content.Sheets.Sheet {
for _, rel := range rels.Relationships {
- if rel.ID == v.ID {
- rID, _ := strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(rel.Target, "worksheets/sheet"), ".xml"))
+ relStr := strings.SplitN(rel.Target, "worksheets/sheet", 2)
+ if rel.ID == v.ID && len(relStr) == 2 {
+ rID, _ := strconv.Atoi(strings.TrimSuffix(relStr[1], ".xml"))
sheetMap[rID] = v.Name
}
}
@@ -362,7 +369,7 @@ func (f *File) getSheetMap() map[string]string {
}
// SetSheetBackground provides a function to set background picture by given
-// worksheet name.
+// worksheet name and file path.
func (f *File) SetSheetBackground(sheet, picture string) error {
var err error
// Check picture exists first.
@@ -371,12 +378,13 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
}
ext, ok := supportImageTypes[path.Ext(picture)]
if !ok {
- return errors.New("Unsupported image extension")
+ return errors.New("unsupported image extension")
}
pictureID := f.countMedia() + 1
rID := f.addSheetRelationships(sheet, SourceRelationshipImage, "../media/image"+strconv.Itoa(pictureID)+ext, "")
f.addSheetPicture(sheet, rID)
- f.addMedia(picture, ext)
+ file, _ := ioutil.ReadFile(picture)
+ f.addMedia(file, ext)
f.setContentTypePartImageExtensions()
return err
}
@@ -391,8 +399,8 @@ func (f *File) DeleteSheet(name string) {
for k, v := range content.Sheets.Sheet {
if v.Name == trimSheetName(name) && len(content.Sheets.Sheet) > 1 {
content.Sheets.Sheet = append(content.Sheets.Sheet[:k], content.Sheets.Sheet[k+1:]...)
- sheet := "xl/worksheets/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml"
- rels := "xl/worksheets/_rels/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml.rels"
+ sheet := "xl/worksheets/sheet" + strconv.Itoa(v.SheetID) + ".xml"
+ rels := "xl/worksheets/_rels/sheet" + strconv.Itoa(v.SheetID) + ".xml.rels"
target := f.deleteSheetFromWorkbookRels(v.ID)
f.deleteSheetFromContentTypes(target)
delete(f.sheetMap, name)
@@ -441,7 +449,7 @@ func (f *File) deleteSheetFromContentTypes(target string) {
//
func (f *File) CopySheet(from, to int) error {
if from < 1 || to < 1 || from == to || f.GetSheetName(from) == "" || f.GetSheetName(to) == "" {
- return errors.New("Invalid worksheet index")
+ return errors.New("invalid worksheet index")
}
f.copySheet(from, to)
return nil
@@ -649,6 +657,103 @@ func (f *File) GetSheetVisible(name string) bool {
return visible
}
+// SearchSheet provides a function to get coordinates by given worksheet name
+// and cell value. This function only supports exact match of strings and
+// numbers, doesn't support the calculated result, formatted numbers and
+// conditional lookup currently. If it is a merged cell, it will return the
+// coordinates of the upper left corner of the merged area. For example,
+// search the coordinates of the value of "100" on Sheet1:
+//
+// xlsx.SearchSheet("Sheet1", "100")
+//
+func (f *File) SearchSheet(sheet, value string) []string {
+ xlsx := f.workSheetReader(sheet)
+ result := []string{}
+ name, ok := f.sheetMap[trimSheetName(sheet)]
+ if !ok {
+ return result
+ }
+ if xlsx != nil {
+ output, _ := xml.Marshal(f.Sheet[name])
+ f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
+ }
+ xml.NewDecoder(bytes.NewReader(f.readXML(name)))
+ d := f.sharedStringsReader()
+ var inElement string
+ var r xlsxRow
+ decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
+ for {
+ token, _ := decoder.Token()
+ if token == nil {
+ break
+ }
+ switch startElement := token.(type) {
+ case xml.StartElement:
+ inElement = startElement.Name.Local
+ if inElement == "row" {
+ r = xlsxRow{}
+ _ = decoder.DecodeElement(&r, &startElement)
+ for _, colCell := range r.C {
+ val, _ := colCell.getValueFrom(f, d)
+ if val != value {
+ continue
+ }
+ result = append(result, fmt.Sprintf("%s%d", strings.Map(letterOnlyMapF, colCell.R), r.R))
+ }
+ }
+ default:
+ }
+ }
+ return result
+}
+
+// ProtectSheet provides a function to prevent other users from accidentally
+// or deliberately changing, moving, or deleting data in a worksheet. For
+// example, protect Sheet1 with protection settings:
+//
+// xlsx.ProtectSheet("Sheet1", &excelize.FormatSheetProtection{
+// Password: "password",
+// EditScenarios: false,
+// })
+//
+func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) {
+ xlsx := f.workSheetReader(sheet)
+ if settings == nil {
+ settings = &FormatSheetProtection{
+ EditObjects: true,
+ EditScenarios: true,
+ SelectLockedCells: true,
+ }
+ }
+ xlsx.SheetProtection = &xlsxSheetProtection{
+ AutoFilter: settings.AutoFilter,
+ DeleteColumns: settings.DeleteColumns,
+ DeleteRows: settings.DeleteRows,
+ FormatCells: settings.FormatCells,
+ FormatColumns: settings.FormatColumns,
+ FormatRows: settings.FormatRows,
+ InsertColumns: settings.InsertColumns,
+ InsertHyperlinks: settings.InsertHyperlinks,
+ InsertRows: settings.InsertRows,
+ Objects: settings.EditObjects,
+ PivotTables: settings.PivotTables,
+ Scenarios: settings.EditScenarios,
+ SelectLockedCells: settings.SelectLockedCells,
+ SelectUnlockedCells: settings.SelectUnlockedCells,
+ Sheet: true,
+ Sort: settings.Sort,
+ }
+ if settings.Password != "" {
+ xlsx.SheetProtection.Password = genSheetPasswd(settings.Password)
+ }
+}
+
+// UnprotectSheet provides a function to unprotect an Excel worksheet.
+func (f *File) UnprotectSheet(sheet string) {
+ xlsx := f.workSheetReader(sheet)
+ xlsx.SheetProtection = nil
+}
+
// trimSheetName provides a function to trim invaild characters by given worksheet
// name.
func trimSheetName(name string) string {
diff --git a/sheetpr.go b/sheetpr.go
index 1601ab1..57eebd4 100644
--- a/sheetpr.go
+++ b/sheetpr.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
// SheetPrOption is an option of a view of a worksheet. See SetSheetPrOptions().
@@ -22,8 +31,26 @@ type (
FitToPage bool
// AutoPageBreaks is a SheetPrOption
AutoPageBreaks bool
+ // OutlineSummaryBelow is an outlinePr, within SheetPr option
+ OutlineSummaryBelow bool
)
+func (o OutlineSummaryBelow) setSheetPrOption(pr *xlsxSheetPr) {
+ if pr.OutlinePr == nil {
+ pr.OutlinePr = new(xlsxOutlinePr)
+ }
+ pr.OutlinePr.SummaryBelow = bool(o)
+}
+
+func (o *OutlineSummaryBelow) getSheetPrOption(pr *xlsxSheetPr) {
+ // Excel default: true
+ if pr == nil || pr.OutlinePr == nil {
+ *o = true
+ return
+ }
+ *o = OutlineSummaryBelow(defaultTrue(&pr.OutlinePr.SummaryBelow))
+}
+
func (o CodeName) setSheetPrOption(pr *xlsxSheetPr) {
pr.CodeName = string(o)
}
@@ -106,6 +133,7 @@ func (o *AutoPageBreaks) getSheetPrOption(pr *xlsxSheetPr) {
// Published(bool)
// FitToPage(bool)
// AutoPageBreaks(bool)
+// OutlineSummaryBelow(bool)
func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
sheet := f.workSheetReader(name)
pr := sheet.SheetPr
@@ -128,6 +156,7 @@ func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
// Published(bool)
// FitToPage(bool)
// AutoPageBreaks(bool)
+// OutlineSummaryBelow(bool)
func (f *File) GetSheetPrOptions(name string, opts ...SheetPrOptionPtr) error {
sheet := f.workSheetReader(name)
pr := sheet.SheetPr
diff --git a/sheetpr_test.go b/sheetpr_test.go
index e7e7482..d9f5059 100644
--- a/sheetpr_test.go
+++ b/sheetpr_test.go
@@ -15,6 +15,7 @@ var _ = []excelize.SheetPrOption{
excelize.Published(false),
excelize.FitToPage(true),
excelize.AutoPageBreaks(true),
+ excelize.OutlineSummaryBelow(true),
}
var _ = []excelize.SheetPrOptionPtr{
@@ -23,6 +24,7 @@ var _ = []excelize.SheetPrOptionPtr{
(*excelize.Published)(nil),
(*excelize.FitToPage)(nil),
(*excelize.AutoPageBreaks)(nil),
+ (*excelize.OutlineSummaryBelow)(nil),
}
func ExampleFile_SetSheetPrOptions() {
@@ -35,6 +37,7 @@ func ExampleFile_SetSheetPrOptions() {
excelize.Published(false),
excelize.FitToPage(true),
excelize.AutoPageBreaks(true),
+ excelize.OutlineSummaryBelow(false),
); err != nil {
panic(err)
}
@@ -51,6 +54,7 @@ func ExampleFile_GetSheetPrOptions() {
published excelize.Published
fitToPage excelize.FitToPage
autoPageBreaks excelize.AutoPageBreaks
+ outlineSummaryBelow excelize.OutlineSummaryBelow
)
if err := xl.GetSheetPrOptions(sheet,
@@ -59,6 +63,7 @@ func ExampleFile_GetSheetPrOptions() {
&published,
&fitToPage,
&autoPageBreaks,
+ &outlineSummaryBelow,
); err != nil {
panic(err)
}
@@ -68,6 +73,7 @@ func ExampleFile_GetSheetPrOptions() {
fmt.Println("- published:", published)
fmt.Println("- fitToPage:", fitToPage)
fmt.Println("- autoPageBreaks:", autoPageBreaks)
+ fmt.Println("- outlineSummaryBelow:", outlineSummaryBelow)
// Output:
// Defaults:
// - codeName: ""
@@ -75,6 +81,7 @@ func ExampleFile_GetSheetPrOptions() {
// - published: true
// - fitToPage: false
// - autoPageBreaks: false
+ // - outlineSummaryBelow: true
}
func TestSheetPrOptions(t *testing.T) {
@@ -88,6 +95,7 @@ func TestSheetPrOptions(t *testing.T) {
{new(excelize.Published), excelize.Published(false)},
{new(excelize.FitToPage), excelize.FitToPage(true)},
{new(excelize.AutoPageBreaks), excelize.AutoPageBreaks(true)},
+ {new(excelize.OutlineSummaryBelow), excelize.OutlineSummaryBelow(false)},
} {
opt := test.nonDefault
t.Logf("option %T", opt)
diff --git a/sheetview.go b/sheetview.go
index 679e915..37a0c39 100644
--- a/sheetview.go
+++ b/sheetview.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "fmt"
@@ -26,6 +35,8 @@ type (
ShowRowColHeaders bool
// ZoomScale is a SheetViewOption.
ZoomScale float64
+ // TopLeftCell is a SheetViewOption.
+ TopLeftCell string
/* TODO
// ShowWhiteSpace is a SheetViewOption.
ShowWhiteSpace bool
@@ -38,6 +49,14 @@ type (
// Defaults for each option are described in XML schema for CT_SheetView
+func (o TopLeftCell) setSheetViewOption(view *xlsxSheetView) {
+ view.TopLeftCell = string(o)
+}
+
+func (o *TopLeftCell) getSheetViewOption(view *xlsxSheetView) {
+ *o = TopLeftCell(string(view.TopLeftCell))
+}
+
func (o DefaultGridColor) setSheetViewOption(view *xlsxSheetView) {
view.DefaultGridColor = boolPtr(bool(o))
}
diff --git a/sheetview_test.go b/sheetview_test.go
index c580906..ee81d5b 100644
--- a/sheetview_test.go
+++ b/sheetview_test.go
@@ -13,12 +13,14 @@ var _ = []excelize.SheetViewOption{
excelize.ShowFormulas(false),
excelize.ShowGridLines(true),
excelize.ShowRowColHeaders(true),
+ excelize.TopLeftCell("B2"),
// SheetViewOptionPtr are also SheetViewOption
new(excelize.DefaultGridColor),
new(excelize.RightToLeft),
new(excelize.ShowFormulas),
new(excelize.ShowGridLines),
new(excelize.ShowRowColHeaders),
+ new(excelize.TopLeftCell),
}
var _ = []excelize.SheetViewOptionPtr{
@@ -27,6 +29,7 @@ var _ = []excelize.SheetViewOptionPtr{
(*excelize.ShowFormulas)(nil),
(*excelize.ShowGridLines)(nil),
(*excelize.ShowRowColHeaders)(nil),
+ (*excelize.TopLeftCell)(nil),
}
func ExampleFile_SetSheetViewOptions() {
@@ -40,6 +43,7 @@ func ExampleFile_SetSheetViewOptions() {
excelize.ShowGridLines(true),
excelize.ShowRowColHeaders(true),
excelize.ZoomScale(80),
+ excelize.TopLeftCell("C3"),
); err != nil {
panic(err)
}
@@ -91,6 +95,7 @@ func ExampleFile_GetSheetViewOptions() {
showGridLines excelize.ShowGridLines
showRowColHeaders excelize.ShowRowColHeaders
zoomScale excelize.ZoomScale
+ topLeftCell excelize.TopLeftCell
)
if err := xl.GetSheetViewOptions(sheet, 0,
@@ -100,6 +105,7 @@ func ExampleFile_GetSheetViewOptions() {
&showGridLines,
&showRowColHeaders,
&zoomScale,
+ &topLeftCell,
); err != nil {
panic(err)
}
@@ -111,6 +117,15 @@ func ExampleFile_GetSheetViewOptions() {
fmt.Println("- showGridLines:", showGridLines)
fmt.Println("- showRowColHeaders:", showRowColHeaders)
fmt.Println("- zoomScale:", zoomScale)
+ fmt.Println("- topLeftCell:", `"`+topLeftCell+`"`)
+
+ if err := xl.SetSheetViewOptions(sheet, 0, excelize.TopLeftCell("B2")); err != nil {
+ panic(err)
+ }
+
+ if err := xl.GetSheetViewOptions(sheet, 0, &topLeftCell); err != nil {
+ panic(err)
+ }
if err := xl.SetSheetViewOptions(sheet, 0, excelize.ShowGridLines(false)); err != nil {
panic(err)
@@ -122,6 +137,7 @@ func ExampleFile_GetSheetViewOptions() {
fmt.Println("After change:")
fmt.Println("- showGridLines:", showGridLines)
+ fmt.Println("- topLeftCell:", topLeftCell)
// Output:
// Default:
@@ -131,8 +147,10 @@ func ExampleFile_GetSheetViewOptions() {
// - showGridLines: true
// - showRowColHeaders: true
// - zoomScale: 0
+ // - topLeftCell: ""
// After change:
// - showGridLines: false
+ // - topLeftCell: B2
}
func TestSheetViewOptionsErrors(t *testing.T) {
diff --git a/styles.go b/styles.go
index a288b37..f923787 100644
--- a/styles.go
+++ b/styles.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -798,35 +807,35 @@ var validType = map[string]string{
// criteriaType defined the list of valid criteria types.
var criteriaType = map[string]string{
- "between": "between",
- "not between": "notBetween",
- "equal to": "equal",
- "=": "equal",
- "==": "equal",
- "not equal to": "notEqual",
- "!=": "notEqual",
- "<>": "notEqual",
- "greater than": "greaterThan",
- ">": "greaterThan",
- "less than": "lessThan",
- "<": "lessThan",
+ "between": "between",
+ "not between": "notBetween",
+ "equal to": "equal",
+ "=": "equal",
+ "==": "equal",
+ "not equal to": "notEqual",
+ "!=": "notEqual",
+ "<>": "notEqual",
+ "greater than": "greaterThan",
+ ">": "greaterThan",
+ "less than": "lessThan",
+ "<": "lessThan",
"greater than or equal to": "greaterThanOrEqual",
- ">=": "greaterThanOrEqual",
- "less than or equal to": "lessThanOrEqual",
- "<=": "lessThanOrEqual",
- "containing": "containsText",
- "not containing": "notContains",
- "begins with": "beginsWith",
- "ends with": "endsWith",
- "yesterday": "yesterday",
- "today": "today",
- "last 7 days": "last7Days",
- "last week": "lastWeek",
- "this week": "thisWeek",
- "continue week": "continueWeek",
- "last month": "lastMonth",
- "this month": "thisMonth",
- "continue month": "continueMonth",
+ ">=": "greaterThanOrEqual",
+ "less than or equal to": "lessThanOrEqual",
+ "<=": "lessThanOrEqual",
+ "containing": "containsText",
+ "not containing": "notContains",
+ "begins with": "beginsWith",
+ "ends with": "endsWith",
+ "yesterday": "yesterday",
+ "today": "today",
+ "last 7 days": "last7Days",
+ "last week": "lastWeek",
+ "this week": "thisWeek",
+ "continue week": "continueWeek",
+ "last month": "lastMonth",
+ "this month": "thisMonth",
+ "continue month": "continueMonth",
}
// formatToString provides a function to return original string by given
@@ -990,7 +999,7 @@ func is12HourTime(format string) bool {
func (f *File) stylesReader() *xlsxStyleSheet {
if f.Styles == nil {
var styleSheet xlsxStyleSheet
- _ = xml.Unmarshal([]byte(f.readXML("xl/styles.xml")), &styleSheet)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML("xl/styles.xml")), &styleSheet)
f.Styles = &styleSheet
}
return f.Styles
@@ -2748,7 +2757,7 @@ func getPaletteColor(color string) string {
// structure after deserialization.
func (f *File) themeReader() *xlsxTheme {
var theme xlsxTheme
- _ = xml.Unmarshal([]byte(f.readXML("xl/theme/theme1.xml")), &theme)
+ _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML("xl/theme/theme1.xml")), &theme)
return &theme
}
diff --git a/table.go b/table.go
index 643b156..02c89fa 100644
--- a/table.go
+++ b/table.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import (
@@ -282,7 +291,7 @@ func (f *File) autoFilter(sheet, ref string, refRange, hxAxis int, formatSet *fo
col := TitleToNumber(formatSet.Column)
offset := col - hxAxis
if offset < 0 || offset > refRange {
- return fmt.Errorf("Incorrect index of column '%s'", formatSet.Column)
+ return fmt.Errorf("incorrect index of column '%s'", formatSet.Column)
}
filter.FilterColumn = &xlsxFilterColumn{
ColID: offset,
@@ -290,7 +299,7 @@ func (f *File) autoFilter(sheet, ref string, refRange, hxAxis int, formatSet *fo
re := regexp.MustCompile(`"(?:[^"]|"")*"|\S+`)
token := re.FindAllString(formatSet.Expression, -1)
if len(token) != 3 && len(token) != 7 {
- return fmt.Errorf("Incorrect number of tokens in criteria '%s'", formatSet.Expression)
+ return fmt.Errorf("incorrect number of tokens in criteria '%s'", formatSet.Expression)
}
expressions, tokens, err := f.parseFilterExpression(formatSet.Expression, token)
if err != nil {
@@ -415,7 +424,7 @@ func (f *File) parseFilterTokens(expression string, tokens []string) ([]int, str
operator, ok := operators[strings.ToLower(tokens[1])]
if !ok {
// Convert the operator from a number to a descriptive string.
- return []int{}, "", fmt.Errorf("Unknown operator: %s", tokens[1])
+ return []int{}, "", fmt.Errorf("unknown operator: %s", tokens[1])
}
token := tokens[2]
// Special handling for Blanks/NonBlanks.
@@ -423,7 +432,7 @@ func (f *File) parseFilterTokens(expression string, tokens []string) ([]int, str
if re {
// Only allow Equals or NotEqual in this context.
if operator != 2 && operator != 5 {
- return []int{operator}, token, fmt.Errorf("The operator '%s' in expression '%s' is not valid in relation to Blanks/NonBlanks'", tokens[1], expression)
+ return []int{operator}, token, fmt.Errorf("the operator '%s' in expression '%s' is not valid in relation to Blanks/NonBlanks'", tokens[1], expression)
}
token = strings.ToLower(token)
// The operator should always be 2 (=) to flag a "simple" equality in
diff --git a/templates.go b/templates.go
index ef6058c..1d0655d 100644
--- a/templates.go
+++ b/templates.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+//
// This file contains default templates for XML files we don't yet populated
// based on content.
diff --git a/test/Book1.xlsx b/test/Book1.xlsx
index 84c43d1..2ef1121 100755..100644
--- a/test/Book1.xlsx
+++ b/test/Book1.xlsx
Binary files differ
diff --git a/test/images/excel.gif b/test/images/excel.gif
index bf7499a..4baa4b5 100644
--- a/test/images/excel.gif
+++ b/test/images/excel.gif
Binary files differ
diff --git a/test/images/excel.jpg b/test/images/excel.jpg
index 49edfef..ed1ee1d 100644
--- a/test/images/excel.jpg
+++ b/test/images/excel.jpg
Binary files differ
diff --git a/test/images/excel.png b/test/images/excel.png
index 52c36db..3e4760b 100644
--- a/test/images/excel.png
+++ b/test/images/excel.png
Binary files differ
diff --git a/vmlDrawing.go b/vmlDrawing.go
index 307186a..c17dde7 100644
--- a/vmlDrawing.go
+++ b/vmlDrawing.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlChart.go b/xmlChart.go
index a263334..3271cbb 100644
--- a/xmlChart.go
+++ b/xmlChart.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
@@ -244,7 +253,7 @@ type aLn struct {
Algn string `xml:"algn,attr,omitempty"`
Cap string `xml:"cap,attr,omitempty"`
Cmpd string `xml:"cmpd,attr,omitempty"`
- W int `xml:"w,attr,omitempty" `
+ W int `xml:"w,attr,omitempty"`
NoFill string `xml:"a:noFill,omitempty"`
Round string `xml:"a:round,omitempty"`
SolidFill *aSolidFill `xml:"a:solidFill"`
@@ -582,7 +591,7 @@ type formatChartSeries struct {
} `json:"line"`
Marker struct {
Type string `json:"type"`
- Size int `json:"size,"`
+ Size int `json:"size"`
Width float64 `json:"width"`
Border struct {
Color string `json:"color"`
diff --git a/xmlComments.go b/xmlComments.go
index fadc9b3..9075c88 100644
--- a/xmlComments.go
+++ b/xmlComments.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
@@ -53,3 +62,11 @@ type formatComment struct {
Author string `json:"author"`
Text string `json:"text"`
}
+
+// Comment directly maps the comment information.
+type Comment struct {
+ Author string `json:"author"`
+ AuthorID int `json:"author_id"`
+ Ref string `json:"ref"`
+ Text string `json:"text"`
+}
diff --git a/xmlContentTypes.go b/xmlContentTypes.go
index 121c684..8d09d51 100644
--- a/xmlContentTypes.go
+++ b/xmlContentTypes.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlDecodeDrawing.go b/xmlDecodeDrawing.go
index fff6b9d..d21c3f0 100644
--- a/xmlDecodeDrawing.go
+++ b/xmlDecodeDrawing.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlDrawing.go b/xmlDrawing.go
index beb6bc9..7356cb5 100644
--- a/xmlDrawing.go
+++ b/xmlDrawing.go
@@ -1,27 +1,41 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
// Source relationship and namespace.
const (
- SourceRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
- SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
- SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
- SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
- SourceRelationshipTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
- SourceRelationshipDrawingML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
- SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
- SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
- SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
- SourceRelationshipChart201506 = "http://schemas.microsoft.com/office/drawing/2015/06/chart"
- SourceRelationshipChart20070802 = "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"
- SourceRelationshipChart2014 = "http://schemas.microsoft.com/office/drawing/2014/chart"
- SourceRelationshipCompatibility = "http://schemas.openxmlformats.org/markup-compatibility/2006"
- NameSpaceDrawingML = "http://schemas.openxmlformats.org/drawingml/2006/main"
- NameSpaceDrawingMLChart = "http://schemas.openxmlformats.org/drawingml/2006/chart"
- NameSpaceDrawingMLSpreadSheet = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
- NameSpaceSpreadSheet = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
- NameSpaceXML = "http://www.w3.org/XML/1998/namespace"
+ SourceRelationship = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
+ SourceRelationshipChart = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"
+ SourceRelationshipComments = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
+ SourceRelationshipImage = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
+ SourceRelationshipTable = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"
+ SourceRelationshipDrawingML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
+ SourceRelationshipDrawingVML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"
+ SourceRelationshipHyperLink = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
+ SourceRelationshipWorkSheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
+ SourceRelationshipChart201506 = "http://schemas.microsoft.com/office/drawing/2015/06/chart"
+ SourceRelationshipChart20070802 = "http://schemas.microsoft.com/office/drawing/2007/8/2/chart"
+ SourceRelationshipChart2014 = "http://schemas.microsoft.com/office/drawing/2014/chart"
+ SourceRelationshipCompatibility = "http://schemas.openxmlformats.org/markup-compatibility/2006"
+ NameSpaceDrawingML = "http://schemas.openxmlformats.org/drawingml/2006/main"
+ NameSpaceDrawingMLChart = "http://schemas.openxmlformats.org/drawingml/2006/chart"
+ NameSpaceDrawingMLSpreadSheet = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
+ NameSpaceSpreadSheet = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
+ NameSpaceXML = "http://www.w3.org/XML/1998/namespace"
+ StrictSourceRelationship = "http://purl.oclc.org/ooxml/officeDocument/relationships"
+ StrictSourceRelationshipChart = "http://purl.oclc.org/ooxml/officeDocument/relationships/chart"
+ StrictSourceRelationshipComments = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments"
+ StrictSourceRelationshipImage = "http://purl.oclc.org/ooxml/officeDocument/relationships/image"
+ StrictNameSpaceSpreadSheet = "http://purl.oclc.org/ooxml/spreadsheetml/main"
)
var supportImageTypes = map[string]string{".gif": ".gif", ".jpg": ".jpeg", ".jpeg": ".jpeg", ".png": ".png"}
diff --git a/xmlSharedStrings.go b/xmlSharedStrings.go
index c8b54a0..782ed61 100644
--- a/xmlSharedStrings.go
+++ b/xmlSharedStrings.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlStyles.go b/xmlStyles.go
index 05ff22b..7ba4379 100644
--- a/xmlStyles.go
+++ b/xmlStyles.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlTable.go b/xmlTable.go
index b238350..7e155e6 100644
--- a/xmlTable.go
+++ b/xmlTable.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlTheme.go b/xmlTheme.go
index d2ab343..b4140b6 100644
--- a/xmlTheme.go
+++ b/xmlTheme.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
diff --git a/xmlWorkbook.go b/xmlWorkbook.go
index 816d5a4..6572033 100644
--- a/xmlWorkbook.go
+++ b/xmlWorkbook.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
@@ -142,7 +151,7 @@ type xlsxSheets struct {
// not checked it for completeness - it does as much as I need.
type xlsxSheet struct {
Name string `xml:"name,attr,omitempty"`
- SheetID string `xml:"sheetId,attr,omitempty"`
+ SheetID int `xml:"sheetId,attr,omitempty"`
ID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
State string `xml:"state,attr,omitempty"`
}
diff --git a/xmlWorksheet.go b/xmlWorksheet.go
index 87d66a1..d35b40e 100644
--- a/xmlWorksheet.go
+++ b/xmlWorksheet.go
@@ -1,3 +1,12 @@
+// Copyright 2016 - 2018 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.
+//
+// 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.
+
package excelize
import "encoding/xml"
@@ -18,7 +27,7 @@ type xlsxWorksheet struct {
MergeCells *xlsxMergeCells `xml:"mergeCells"`
PhoneticPr *xlsxPhoneticPr `xml:"phoneticPr"`
ConditionalFormatting []*xlsxConditionalFormatting `xml:"conditionalFormatting"`
- DataValidations *xlsxDataValidations `xml:"dataValidations"`
+ DataValidations *xlsxDataValidations `xml:"dataValidations,omitempty"`
Hyperlinks *xlsxHyperlinks `xml:"hyperlinks"`
PrintOptions *xlsxPrintOptions `xml:"printOptions"`
PageMargins *xlsxPageMargins `xml:"pageMargins"`
@@ -202,6 +211,13 @@ type xlsxSheetPr struct {
TransitionEntry bool `xml:"transitionEntry,attr,omitempty"`
TabColor *xlsxTabColor `xml:"tabColor,omitempty"`
PageSetUpPr *xlsxPageSetUpPr `xml:"pageSetUpPr,omitempty"`
+ OutlinePr *xlsxOutlinePr `xml:"outlinePr,omitempty"`
+}
+
+// xlsxOutlinePr maps to the outlinePr element
+// SummaryBelow allows you to adjust the direction of grouper controls
+type xlsxOutlinePr struct {
+ SummaryBelow bool `xml:"summaryBelow,attr"`
}
// xlsxPageSetUpPr directly maps the pageSetupPr element in the namespace
@@ -294,11 +310,30 @@ type xlsxMergeCells struct {
// xlsxDataValidations expresses all data validation information for cells in a
// sheet which have data validation features applied.
type xlsxDataValidations struct {
- Count int `xml:"count,attr,omitempty"`
- DisablePrompts bool `xml:"disablePrompts,attr,omitempty"`
- XWindow int `xml:"xWindow,attr,omitempty"`
- YWindow int `xml:"yWindow,attr,omitempty"`
- DataValidation string `xml:",innerxml"`
+ Count int `xml:"count,attr,omitempty"`
+ DisablePrompts bool `xml:"disablePrompts,attr,omitempty"`
+ XWindow int `xml:"xWindow,attr,omitempty"`
+ YWindow int `xml:"yWindow,attr,omitempty"`
+ DataValidation []*DataValidation `xml:"dataValidation"`
+}
+
+// DataValidation directly maps the a single item of data validation defined
+// on a range of the worksheet.
+type DataValidation struct {
+ AllowBlank bool `xml:"allowBlank,attr"`
+ Error *string `xml:"error,attr"`
+ ErrorStyle *string `xml:"errorStyle,attr"`
+ ErrorTitle *string `xml:"errorTitle,attr"`
+ Operator string `xml:"operator,attr"`
+ Prompt *string `xml:"prompt,attr"`
+ PromptTitle *string `xml:"promptTitle"`
+ ShowDropDown bool `xml:"showDropDown,attr"`
+ ShowErrorMessage bool `xml:"showErrorMessage,attr"`
+ ShowInputMessage bool `xml:"showInputMessage,attr"`
+ Sqref string `xml:"sqref,attr"`
+ Type string `xml:"type,attr"`
+ Formula1 string `xml:"formula1"`
+ Formula2 string `xml:"formula2"`
}
// xlsxC directly maps the c element in the namespace
@@ -349,26 +384,27 @@ type xlsxF struct {
// xlsxSheetProtection collection expresses the sheet protection options to
// enforce when the sheet is protected.
type xlsxSheetProtection struct {
- AlgorithmName string `xml:"algorithmName,attr,omitempty"`
- AutoFilter int `xml:"autoFilter,attr,omitempty"`
- DeleteColumns int `xml:"deleteColumns,attr,omitempty"`
- DeleteRows int `xml:"deleteRows,attr,omitempty"`
- FormatCells int `xml:"formatCells,attr,omitempty"`
- FormatColumns int `xml:"formatColumns,attr,omitempty"`
- FormatRows int `xml:"formatRows,attr,omitempty"`
- HashValue string `xml:"hashValue,attr,omitempty"`
- InsertColumns int `xml:"insertColumns,attr,omitempty"`
- InsertHyperlinks int `xml:"insertHyperlinks,attr,omitempty"`
- InsertRows int `xml:"insertRows,attr,omitempty"`
- Objects int `xml:"objects,attr,omitempty"`
- PivotTables int `xml:"pivotTables,attr,omitempty"`
- SaltValue string `xml:"saltValue,attr,omitempty"`
- Scenarios int `xml:"scenarios,attr,omitempty"`
- SelectLockedCells int `xml:"selectLockedCells,attr,omitempty"`
- SelectUnlockedCell int `xml:"selectUnlockedCell,attr,omitempty"`
- Sheet int `xml:"sheet,attr,omitempty"`
- Sort int `xml:"sort,attr,omitempty"`
- SpinCount int `xml:"spinCount,attr,omitempty"`
+ AlgorithmName string `xml:"algorithmName,attr,omitempty"`
+ AutoFilter bool `xml:"autoFilter,attr,omitempty"`
+ DeleteColumns bool `xml:"deleteColumns,attr,omitempty"`
+ DeleteRows bool `xml:"deleteRows,attr,omitempty"`
+ FormatCells bool `xml:"formatCells,attr,omitempty"`
+ FormatColumns bool `xml:"formatColumns,attr,omitempty"`
+ FormatRows bool `xml:"formatRows,attr,omitempty"`
+ HashValue string `xml:"hashValue,attr,omitempty"`
+ InsertColumns bool `xml:"insertColumns,attr,omitempty"`
+ InsertHyperlinks bool `xml:"insertHyperlinks,attr,omitempty"`
+ InsertRows bool `xml:"insertRows,attr,omitempty"`
+ Objects bool `xml:"objects,attr,omitempty"`
+ Password string `xml:"password,attr,omitempty"`
+ PivotTables bool `xml:"pivotTables,attr,omitempty"`
+ SaltValue string `xml:"saltValue,attr,omitempty"`
+ Scenarios bool `xml:"scenarios,attr,omitempty"`
+ SelectLockedCells bool `xml:"selectLockedCells,attr,omitempty"`
+ SelectUnlockedCells bool `xml:"selectUnlockedCells,attr,omitempty"`
+ Sheet bool `xml:"sheet,attr,omitempty"`
+ Sort bool `xml:"sort,attr,omitempty"`
+ SpinCount int `xml:"spinCount,attr,omitempty"`
}
// xlsxPhoneticPr (Phonetic Properties) represents a collection of phonetic
@@ -571,3 +607,23 @@ type formatConditional struct {
MultiRange string `json:"multi_range,omitempty"`
BarColor string `json:"bar_color,omitempty"`
}
+
+// FormatSheetProtection directly maps the settings of worksheet protection.
+type FormatSheetProtection struct {
+ AutoFilter bool
+ DeleteColumns bool
+ DeleteRows bool
+ EditObjects bool
+ EditScenarios bool
+ FormatCells bool
+ FormatColumns bool
+ FormatRows bool
+ InsertColumns bool
+ InsertHyperlinks bool
+ InsertRows bool
+ Password string
+ PivotTables bool
+ SelectLockedCells bool
+ SelectUnlockedCells bool
+ Sort bool
+}