summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRi Xu <xuri.me@gmail.com>2016-09-05 16:37:15 +0800
committerRi Xu <xuri.me@gmail.com>2016-09-05 16:37:15 +0800
commit50863294f9d6f2ecc399d06f1b3c2312c4bdce10 (patch)
tree0cc7513dd3c56eef889432f27da1186288a2ed98
parent956a4627d1f2b78172eaaf6078209d4cf8e64ce2 (diff)
Fix issue #2 change project to object-oriented style and update readme file.
-rw-r--r--README.md38
-rw-r--r--cell.go6
-rw-r--r--excelize.go35
-rw-r--r--excelize_test.go66
-rw-r--r--file.go60
-rw-r--r--lib.go9
-rw-r--r--sheet.go57
7 files changed, 142 insertions, 129 deletions
diff --git a/README.md b/README.md
index 357c92d..1cfe4e5 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
## Introduction
-Excelize is a library written in pure Golang and providing a set of functions that allow you to write to and read from XLSX files. Support reads and writes XLSX file generated by Office Excel 2007 and later. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/Luxurioust/excelize).
+Excelize is a library written in pure Golang and providing a set of functions that allow you to write to and read from XLSX files. Support reads and writes XLSX file generated by Office Excel 2007 and later. Support save file without losing original charts of XLSX. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/Luxurioust/excelize).
## Basic Usage
@@ -35,11 +35,11 @@ import (
func main() {
xlsx := excelize.CreateFile()
- xlsx = excelize.NewSheet(xlsx, 2, "Sheet2")
- xlsx = excelize.NewSheet(xlsx, 3, "Sheet3")
- xlsx = excelize.SetCellInt(xlsx, "Sheet2", "A23", 10)
- xlsx = excelize.SetCellStr(xlsx, "Sheet3", "B20", "Hello")
- err := excelize.Save(xlsx, "/home/Workbook.xlsx")
+ xlsx.NewSheet(2, "Sheet2")
+ xlsx.NewSheet(3, "Sheet3")
+ xlsx.SetCellInt("Sheet2", "A23", 10)
+ xlsx.SetCellStr("Sheet3", "B20", "Hello")
+ err := xlsx.WriteTo("/home/Workbook.xlsx")
if err != nil {
fmt.Println(err)
}
@@ -59,20 +59,17 @@ import (
)
func main() {
- xlsx, err := excelize.OpenFile("/home/Workbook.xlsx")
+ xlsx := excelize.OpenFile("/home/Workbook.xlsx")
+ xlsx.SetCellInt("Sheet2", "B2", 100)
+ xlsx.SetCellStr("Sheet2", "C11", "Hello")
+ xlsx.NewSheet(3, "TestSheet")
+ xlsx.SetCellInt("Sheet3", "A23", 10)
+ xlsx.SetCellStr("Sheet3", "b230", "World")
+ xlsx.SetActiveSheet(2)
+ err := xlsx.Save()
if err != nil {
fmt.Println(err)
}
- xlsx = excelize.SetCellInt(xlsx, "Sheet2", "B2", 100)
- xlsx = excelize.SetCellStr(xlsx, "Sheet2", "C11", "Hello")
- xlsx = excelize.NewSheet(xlsx, 3, "TestSheet")
- xlsx = excelize.SetCellInt(xlsx, "Sheet3", "A23", 10)
- xlsx = excelize.SetCellStr(xlsx, "Sheet3", "b230", "World")
- xlsx = excelize.SetActiveSheet(xlsx, 2)
- err = excelize.Save(xlsx, "/home/Workbook.xlsx")
- if err != nil {
- fmt.Println(err)
- }
}
```
@@ -87,11 +84,8 @@ import (
)
func main() {
- xlsx, err := excelize.OpenFile("/home/Workbook.xlsx")
- if err != nil {
- fmt.Println(err)
- }
- cell := excelize.GetCellValue(file, "Sheet2", "D11")
+ xlsx := excelize.OpenFile("/home/Workbook.xlsx")
+ cell := xlsx.GetCellValue("Sheet2", "D11")
fmt.Println(cell)
}
```
diff --git a/cell.go b/cell.go
index ecfc5ca..4e84260 100644
--- a/cell.go
+++ b/cell.go
@@ -7,13 +7,13 @@ import (
)
// GetCellValue provide function get value from cell by given sheet index and axis in XLSX file
-func GetCellValue(file map[string]string, sheet string, axis string) string {
+func (f *File) GetCellValue(sheet string, axis string) string {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
row := getRowIndex(axis)
xAxis := row - 1
name := `xl/worksheets/` + strings.ToLower(sheet) + `.xml`
- xml.Unmarshal([]byte(readXML(file, name)), &xlsx)
+ xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
rows := len(xlsx.SheetData.Row)
if rows <= xAxis {
return ``
@@ -26,7 +26,7 @@ func GetCellValue(file map[string]string, sheet string, axis string) string {
shardStrings := xlsxSST{}
xlsxSI := 0
xlsxSI, _ = strconv.Atoi(v.V)
- xml.Unmarshal([]byte(readXML(file, `xl/sharedStrings.xml`)), &shardStrings)
+ xml.Unmarshal([]byte(f.readXML(`xl/sharedStrings.xml`)), &shardStrings)
return shardStrings.SI[xlsxSI].T
case "str":
return v.V
diff --git a/excelize.go b/excelize.go
index 2dd62d3..d37860f 100644
--- a/excelize.go
+++ b/excelize.go
@@ -9,26 +9,27 @@ import (
"strings"
)
-// FileList define a populated xlsx.File struct.
-type FileList struct {
- Key string
- Value string
+// File define a populated xlsx.File struct.
+type File struct {
+ XLSX map[string]string
+ Path string
}
// OpenFile take the name of an XLSX file and returns a populated
// xlsx.File struct for it.
-func OpenFile(filename string) (file map[string]string, err error) {
+func OpenFile(filename string) *File {
var f *zip.ReadCloser
- f, err = zip.OpenReader(filename)
- if err != nil {
- return nil, err
+ file := make(map[string]string)
+ f, _ = zip.OpenReader(filename)
+ file, _ = ReadZip(f)
+ return &File{
+ XLSX: file,
+ Path: filename,
}
- file, err = ReadZip(f)
- return
}
// SetCellInt provide function to set int type value of a cell
-func SetCellInt(file map[string]string, sheet string, axis string, value int) map[string]string {
+func (f *File) SetCellInt(sheet string, axis string, value int) {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
col := getColIndex(axis)
@@ -37,7 +38,7 @@ func SetCellInt(file map[string]string, sheet string, axis string, value int) ma
yAxis := titleToNumber(col)
name := `xl/worksheets/` + strings.ToLower(sheet) + `.xml`
- xml.Unmarshal([]byte(readXML(file, name)), &xlsx)
+ xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
rows := xAxis + 1
cell := yAxis + 1
@@ -53,12 +54,11 @@ func SetCellInt(file map[string]string, sheet string, axis string, value int) ma
if err != nil {
fmt.Println(err)
}
- saveFileList(file, name, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
- return file
+ f.saveFileList(name, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
}
// SetCellStr provide function to set string type value of a cell
-func SetCellStr(file map[string]string, sheet string, axis string, value string) map[string]string {
+func (f *File) SetCellStr(sheet string, axis string, value string) {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
col := getColIndex(axis)
@@ -67,7 +67,7 @@ func SetCellStr(file map[string]string, sheet string, axis string, value string)
yAxis := titleToNumber(col)
name := `xl/worksheets/` + strings.ToLower(sheet) + `.xml`
- xml.Unmarshal([]byte(readXML(file, name)), &xlsx)
+ xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
rows := xAxis + 1
cell := yAxis + 1
@@ -83,8 +83,7 @@ func SetCellStr(file map[string]string, sheet string, axis string, value string)
if err != nil {
fmt.Println(err)
}
- saveFileList(file, name, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
- return file
+ f.saveFileList(name, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
}
// Completion column element tags of XML in a sheet
diff --git a/excelize_test.go b/excelize_test.go
index 3751775..d206e2d 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -7,57 +7,51 @@ import (
func TestExcelize(t *testing.T) {
// Test update a XLSX file
- file, err := OpenFile("./test/Workbook1.xlsx")
- if err != nil {
- t.Log(err)
+ file := OpenFile("./test/Workbook1.xlsx")
+ file.SetCellInt("SHEET2", "B2", 100)
+ file.SetCellStr("SHEET2", "C11", "Knowns")
+ file.NewSheet(3, "TestSheet")
+ file.SetCellInt("Sheet3", "A23", 10)
+ file.SetCellStr("SHEET3", "b230", "10")
+ file.SetCellStr("SHEET10", "b230", "10")
+ file.SetActiveSheet(2)
+ for i := 1; i <= 300; i++ {
+ file.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
}
- file = SetCellInt(file, "SHEET2", "B2", 100)
- file = SetCellStr(file, "SHEET2", "C11", "Knowns")
- file = NewSheet(file, 3, "TestSheet")
- file = SetCellInt(file, "Sheet3", "A23", 10)
- file = SetCellStr(file, "SHEET3", "b230", "10")
- file = SetActiveSheet(file, 2)
+ err := file.Save()
if err != nil {
t.Log(err)
}
- for i := 1; i <= 300; i++ {
- file = SetCellStr(file, "SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
- }
- err = Save(file, "./test/Workbook_2.xlsx")
+ // Test write file to given path
+ err = file.WriteTo("./test/Workbook_2.xlsx")
if err != nil {
t.Log(err)
}
-
- // Test save to not exist directory
- err = Save(file, "")
+ // Test write file to not exist directory
+ err = file.WriteTo("")
if err != nil {
t.Log(err)
}
// Test create a XLSX file
file2 := CreateFile()
- file2 = NewSheet(file2, 2, "TestSheet2")
- file2 = NewSheet(file2, 3, "TestSheet3")
- file2 = SetCellInt(file2, "Sheet2", "A23", 10)
- file2 = SetCellStr(file2, "SHEET1", "B20", "10")
- file2 = SetActiveSheet(file2, 0)
- err = Save(file2, "./test/Workbook_3.xlsx")
+ file2.NewSheet(2, "XLSXSheet2")
+ file2.NewSheet(3, "XLSXSheet3")
+ file2.SetCellInt("Sheet2", "A23", 56)
+ file2.SetCellStr("SHEET1", "B20", "42")
+ file2.SetActiveSheet(0)
+ err = file2.WriteTo("./test/Workbook_3.xlsx")
if err != nil {
t.Log(err)
}
- // Test read cell value
- file, err = OpenFile("./test/Workbook1.xlsx")
- if err != nil {
- t.Log(err)
- }
- // Test given illegal rows number
- GetCellValue(file, "Sheet2", "a-1")
- // Test given lowercase column number
- GetCellValue(file, "Sheet2", "a5")
- GetCellValue(file, "Sheet2", "C11")
- GetCellValue(file, "Sheet2", "D11")
- GetCellValue(file, "Sheet2", "D12")
- // Test given axis large than exists row
- GetCellValue(file, "Sheet2", "E13")
+ // Test read cell value with given illegal rows number
+ file.GetCellValue("Sheet2", "a-1")
+ // Test read cell value with given lowercase column number
+ file.GetCellValue("Sheet2", "a5")
+ file.GetCellValue("Sheet2", "C11")
+ file.GetCellValue("Sheet2", "D11")
+ file.GetCellValue("Sheet2", "D12")
+ // Test read cell value with given axis large than exists row
+ file.GetCellValue("Sheet2", "E13")
}
diff --git a/file.go b/file.go
index a25d66d..e3af5ca 100644
--- a/file.go
+++ b/file.go
@@ -9,25 +9,53 @@ import (
// CreateFile provide function to create new file by default template
// For example:
// xlsx := CreateFile()
-func CreateFile() map[string]string {
+func CreateFile() *File {
file := make(map[string]string)
- file = saveFileList(file, `_rels/.rels`, templateRels)
- file = saveFileList(file, `docProps/app.xml`, templateDocpropsApp)
- file = saveFileList(file, `docProps/core.xml`, templateDocpropsCore)
- file = saveFileList(file, `xl/_rels/workbook.xml.rels`, templateWorkbookRels)
- file = saveFileList(file, `xl/theme/theme1.xml`, templateTheme)
- file = saveFileList(file, `xl/worksheets/sheet1.xml`, templateSheet)
- file = saveFileList(file, `xl/styles.xml`, templateStyles)
- file = saveFileList(file, `xl/workbook.xml`, templateWorkbook)
- file = saveFileList(file, `[Content_Types].xml`, templateContentTypes)
- return file
+ file[`_rels/.rels`] = templateRels
+ file[`docProps/app.xml`] = templateDocpropsApp
+ file[`docProps/core.xml`] = templateDocpropsCore
+ file[`xl/_rels/workbook.xml.rels`] = templateWorkbookRels
+ file[`xl/theme/theme1.xml`] = templateTheme
+ file[`xl/worksheets/sheet1.xml`] = templateSheet
+ file[`xl/styles.xml`] = templateStyles
+ file[`xl/workbook.xml`] = templateWorkbook
+ file[`[Content_Types].xml`] = templateContentTypes
+ return &File{
+ XLSX: file,
+ }
+}
+
+// Save provide function override the xlsx file with origin path.
+func (f *File) Save() error {
+ buf := new(bytes.Buffer)
+ w := zip.NewWriter(buf)
+ for path, content := range f.XLSX {
+ f, err := w.Create(path)
+ if err != nil {
+ return err
+ }
+ _, err = f.Write([]byte(content))
+ if err != nil {
+ return err
+ }
+ }
+ err := w.Close()
+ if err != nil {
+ return err
+ }
+ file, err := os.OpenFile(f.Path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
+ if err != nil {
+ return err
+ }
+ buf.WriteTo(file)
+ return err
}
-// Save after create or update to an xlsx file at the provided path.
-func Save(files map[string]string, name string) error {
+// WriteTo provide function create or update to an xlsx file at the provided path.
+func (f *File) WriteTo(name string) error {
buf := new(bytes.Buffer)
w := zip.NewWriter(buf)
- for path, content := range files {
+ for path, content := range f.XLSX {
f, err := w.Create(path)
if err != nil {
return err
@@ -41,10 +69,10 @@ func Save(files map[string]string, name string) error {
if err != nil {
return err
}
- f, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
+ file, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
if err != nil {
return err
}
- buf.WriteTo(f)
+ buf.WriteTo(file)
return err
}
diff --git a/lib.go b/lib.go
index 7147424..915bca1 100644
--- a/lib.go
+++ b/lib.go
@@ -30,17 +30,16 @@ func ReadZipReader(r *zip.Reader) (map[string]string, error) {
}
// Read XML content as string and replace drawing property in XML namespace of sheet
-func readXML(files map[string]string, name string) string {
- if content, ok := files[name]; ok {
+func (f *File) readXML(name string) string {
+ if content, ok := f.XLSX[name]; ok {
return strings.Replace(content, "<drawing r:id=", "<drawing rid=", -1)
}
return ``
}
// Update given file content in file list of XLSX
-func saveFileList(files map[string]string, name string, content string) map[string]string {
- files[name] = XMLHeader + content
- return files
+func (f *File) saveFileList(name string, content string) {
+ f.XLSX[name] = XMLHeader + content
}
// Read file content as string in a archive file
diff --git a/sheet.go b/sheet.go
index 5ff2120..0728567 100644
--- a/sheet.go
+++ b/sheet.go
@@ -11,24 +11,23 @@ import (
// NewSheet provice function to greate a new sheet by given index, when
// creating a new XLSX file, the default sheet will be create, when you
// create a new file, you need to ensure that the index is continuous.
-func NewSheet(file map[string]string, index int, name string) map[string]string {
+func (f *File) NewSheet(index int, name string) {
// Update docProps/app.xml
- file = setAppXML(file)
+ f.setAppXML()
// Update [Content_Types].xml
- file = setContentTypes(file, index)
+ f.setContentTypes(index)
// Create new sheet /xl/worksheets/sheet%d.xml
- file = setSheet(file, index)
+ f.setSheet(index)
// Update xl/_rels/workbook.xml.rels
- file = addXlsxWorkbookRels(file, index)
+ f.addXlsxWorkbookRels(index)
// Update xl/workbook.xml
- file = setWorkbook(file, index, name)
- return file
+ f.setWorkbook(index, name)
}
// Read and update property of contents type of XLSX
-func setContentTypes(file map[string]string, index int) map[string]string {
+func (f *File) setContentTypes(index int) {
var content xlsxTypes
- xml.Unmarshal([]byte(readXML(file, `[Content_Types].xml`)), &content)
+ xml.Unmarshal([]byte(f.readXML(`[Content_Types].xml`)), &content)
content.Overrides = append(content.Overrides, xlsxOverride{
PartName: `/xl/worksheets/sheet` + strconv.Itoa(index) + `.xml`,
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
@@ -37,11 +36,11 @@ func setContentTypes(file map[string]string, index int) map[string]string {
if err != nil {
fmt.Println(err)
}
- return saveFileList(file, `[Content_Types].xml`, string(output))
+ f.saveFileList(`[Content_Types].xml`, string(output))
}
// Update sheet property by given index
-func setSheet(file map[string]string, index int) map[string]string {
+func (f *File) setSheet(index int) {
var xlsx xlsxWorksheet
xlsx.Dimension.Ref = "A1"
xlsx.SheetViews.SheetView = append(xlsx.SheetViews.SheetView, xlsxSheetView{
@@ -52,15 +51,15 @@ func setSheet(file map[string]string, index int) map[string]string {
fmt.Println(err)
}
path := `xl/worksheets/sheet` + strconv.Itoa(index) + `.xml`
- return saveFileList(file, path, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
+ f.saveFileList(path, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output))))
}
// Update workbook property of XLSX
-func setWorkbook(file map[string]string, index int, name string) map[string]string {
+func (f *File) setWorkbook(index int, name string) {
var content xlsxWorkbook
- xml.Unmarshal([]byte(readXML(file, `xl/workbook.xml`)), &content)
+ xml.Unmarshal([]byte(f.readXML(`xl/workbook.xml`)), &content)
- rels := readXlsxWorkbookRels(file)
+ rels := f.readXlsxWorkbookRels()
rID := len(rels.Relationships)
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
Name: name,
@@ -71,19 +70,19 @@ func setWorkbook(file map[string]string, index int, name string) map[string]stri
if err != nil {
fmt.Println(err)
}
- return saveFileList(file, `xl/workbook.xml`, replaceRelationshipsNameSpace(string(output)))
+ f.saveFileList(`xl/workbook.xml`, replaceRelationshipsNameSpace(string(output)))
}
// Read and unmarshal workbook relationships of XLSX
-func readXlsxWorkbookRels(file map[string]string) xlsxWorkbookRels {
+func (f *File) readXlsxWorkbookRels() xlsxWorkbookRels {
var content xlsxWorkbookRels
- xml.Unmarshal([]byte(readXML(file, `xl/_rels/workbook.xml.rels`)), &content)
+ xml.Unmarshal([]byte(f.readXML(`xl/_rels/workbook.xml.rels`)), &content)
return content
}
// Update workbook relationships property of XLSX
-func addXlsxWorkbookRels(file map[string]string, sheet int) map[string]string {
- content := readXlsxWorkbookRels(file)
+func (f *File) addXlsxWorkbookRels(sheet int) {
+ content := f.readXlsxWorkbookRels()
rID := len(content.Relationships) + 1
ID := bytes.Buffer{}
ID.WriteString("rId")
@@ -101,12 +100,12 @@ func addXlsxWorkbookRels(file map[string]string, sheet int) map[string]string {
if err != nil {
fmt.Println(err)
}
- return saveFileList(file, `xl/_rels/workbook.xml.rels`, string(output))
+ f.saveFileList(`xl/_rels/workbook.xml.rels`, string(output))
}
// Update docProps/app.xml file of XML
-func setAppXML(file map[string]string) map[string]string {
- return saveFileList(file, `docProps/app.xml`, templateDocpropsApp)
+func (f *File) setAppXML() {
+ f.saveFileList(`docProps/app.xml`, templateDocpropsApp)
}
// Some tools that read XLSX files have very strict requirements about
@@ -134,13 +133,13 @@ func replaceRelationshipsID(workbookMarshal string) string {
}
// SetActiveSheet provide function to set default active sheet of XLSX by given index
-func SetActiveSheet(file map[string]string, index int) map[string]string {
+func (f *File) SetActiveSheet(index int) {
var content xlsxWorkbook
if index < 1 {
index = 1
}
index--
- xml.Unmarshal([]byte(readXML(file, `xl/workbook.xml`)), &content)
+ xml.Unmarshal([]byte(f.readXML(`xl/workbook.xml`)), &content)
if len(content.BookViews.WorkBookView) > 0 {
content.BookViews.WorkBookView[0].ActiveTab = index
} else {
@@ -153,7 +152,7 @@ func SetActiveSheet(file map[string]string, index int) map[string]string {
if err != nil {
fmt.Println(err)
}
- file = saveFileList(file, `xl/workbook.xml`, workBookCompatibility(replaceRelationshipsNameSpace(string(output))))
+ f.saveFileList(`xl/workbook.xml`, workBookCompatibility(replaceRelationshipsNameSpace(string(output))))
index++
buffer := bytes.Buffer{}
for i := 0; i < sheets; i++ {
@@ -162,7 +161,7 @@ func SetActiveSheet(file map[string]string, index int) map[string]string {
buffer.WriteString(`xl/worksheets/sheet`)
buffer.WriteString(strconv.Itoa(sheetIndex))
buffer.WriteString(`.xml`)
- xml.Unmarshal([]byte(readXML(file, buffer.String())), &xlsx)
+ xml.Unmarshal([]byte(f.readXML(buffer.String())), &xlsx)
if index == sheetIndex {
if len(xlsx.SheetViews.SheetView) > 0 {
xlsx.SheetViews.SheetView[0].TabSelected = true
@@ -180,10 +179,10 @@ func SetActiveSheet(file map[string]string, index int) map[string]string {
if err != nil {
fmt.Println(err)
}
- file = saveFileList(file, buffer.String(), replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(sheet))))
+ f.saveFileList(buffer.String(), replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(sheet))))
buffer.Reset()
}
- return file
+ return
}
// Replace xl/workbook.xml XML tags to self-closing for compatible Office Excel 2007