diff --git a/README.md b/README.md index 5457f89c..41811777 100644 --- a/README.md +++ b/README.md @@ -110,13 +110,18 @@ func main() { } // Insert a picture. err = xlsx.AddPicture("Sheet1", "A2", "/tmp/image1.gif", 0, 0, 1, 1) + if err != nil { + fmt.Println(err) + } // Insert a picture to sheet with scaling. err = xlsx.AddPicture("Sheet1", "D2", "/tmp/image2.jpg", 0, 0, 0.5, 0.5) + if err != nil { + fmt.Println(err) + } // Insert a picture offset in the cell. err = xlsx.AddPicture("Sheet1", "H2", "/tmp/image3.png", 15, 10, 1, 1) if err != nil { fmt.Println(err) - os.Exit(1) } // Save the xlsx file with the origin path. err = xlsx.Save() diff --git a/cell.go b/cell.go index e9933aa8..3e112988 100644 --- a/cell.go +++ b/cell.go @@ -106,6 +106,14 @@ func (f *File) SetCellFormula(sheet, axis, formula string) { var xlsx xlsxWorksheet name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + if f.checked == nil { + f.checked = make(map[string]bool) + } + ok := f.checked[name] + if !ok { + xlsx = checkRow(xlsx) + f.checked[name] = true + } if xlsx.MergeCells != nil { for i := 0; i < len(xlsx.MergeCells.Cells); i++ { if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) { @@ -143,6 +151,14 @@ func (f *File) SetCellHyperLink(sheet, axis, link string) { var xlsx xlsxWorksheet name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + if f.checked == nil { + f.checked = make(map[string]bool) + } + ok := f.checked[name] + if !ok { + xlsx = checkRow(xlsx) + f.checked[name] = true + } if xlsx.MergeCells != nil { for i := 0; i < len(xlsx.MergeCells.Cells); i++ { if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) { @@ -205,6 +221,14 @@ func (f *File) MergeCell(sheet, hcell, vcell string) { var xlsx xlsxWorksheet name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + if f.checked == nil { + f.checked = make(map[string]bool) + } + ok := f.checked[name] + if !ok { + xlsx = checkRow(xlsx) + f.checked[name] = true + } if xlsx.MergeCells != nil { mergeCell := xlsxMergeCell{} // Correct the coordinate area, such correct C1:B3 to B1:C3. diff --git a/excelize.go b/excelize.go index ed36589a..bc37c0a4 100644 --- a/excelize.go +++ b/excelize.go @@ -10,6 +10,7 @@ import ( // File define a populated XLSX file struct. type File struct { + checked map[string]bool XLSX map[string]string Path string SheetCount int @@ -21,6 +22,7 @@ func OpenFile(filename string) (*File, error) { var f *zip.ReadCloser var err error file := make(map[string]string) + c := make(map[string]bool) sheetCount := 0 f, err = zip.OpenReader(filename) if err != nil { @@ -28,6 +30,7 @@ func OpenFile(filename string) (*File, error) { } file, sheetCount, _ = ReadZip(f) return &File{ + checked: c, XLSX: file, Path: filename, SheetCount: sheetCount, @@ -66,6 +69,15 @@ func (f *File) SetCellInt(sheet string, axis string, value int) { var xlsx xlsxWorksheet name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + if f.checked == nil { + f.checked = make(map[string]bool) + } + ok := f.checked[name] + if !ok { + xlsx = checkRow(xlsx) + f.checked[name] = true + } + if xlsx.MergeCells != nil { for i := 0; i < len(xlsx.MergeCells.Cells); i++ { if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) { @@ -98,6 +110,14 @@ func (f *File) SetCellStr(sheet string, axis string, value string) { var xlsx xlsxWorksheet name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + if f.checked == nil { + f.checked = make(map[string]bool) + } + ok := f.checked[name] + if !ok { + xlsx = checkRow(xlsx) + f.checked[name] = true + } if xlsx.MergeCells != nil { for i := 0; i < len(xlsx.MergeCells.Cells); i++ { if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) { @@ -133,6 +153,14 @@ func (f *File) SetCellDefault(sheet string, axis string, value string) { var xlsx xlsxWorksheet name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + if f.checked == nil { + f.checked = make(map[string]bool) + } + ok := f.checked[name] + if !ok { + xlsx = checkRow(xlsx) + f.checked[name] = true + } if xlsx.MergeCells != nil { for i := 0; i < len(xlsx.MergeCells.Cells); i++ { if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) { diff --git a/excelize_test.go b/excelize_test.go index b7f664e9..005edd4d 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -236,7 +236,7 @@ func TestSetSheetBackground(t *testing.T) { } } -func TestSMergeCell(t *testing.T) { +func TestMergeCell(t *testing.T) { xlsx, err := OpenFile("./test/Workbook1.xlsx") if err != nil { t.Log(err) diff --git a/lib.go b/lib.go index 77c6e238..c3767e3f 100644 --- a/lib.go +++ b/lib.go @@ -3,7 +3,6 @@ package excelize import ( "archive/zip" "bytes" - "encoding/xml" "io" "log" "math" @@ -26,11 +25,6 @@ func ReadZipReader(r *zip.Reader) (map[string]string, int, error) { fileList[v.Name] = readFile(v) if len(v.Name) > 18 { if v.Name[0:19] == "xl/worksheets/sheet" { - var xlsx xlsxWorksheet - xml.Unmarshal([]byte(fileList[v.Name]), &xlsx) - xlsx = checkRow(xlsx) - output, _ := xml.Marshal(xlsx) - fileList[v.Name] = replaceWorkSheetsRelationshipsNameSpace(string(output)) worksheets++ } } diff --git a/picture.go b/picture.go index 712dddfe..bc5edc11 100644 --- a/picture.go +++ b/picture.go @@ -33,13 +33,18 @@ import ( // xlsx := excelize.CreateFile() // // Insert a picture. // err := xlsx.AddPicture("Sheet1", "A2", "/tmp/image1.jpg", 0, 0, 1, 1) +// if err != nil { +// fmt.Println(err) +// } // // Insert a picture to sheet with scaling. // err = xlsx.AddPicture("Sheet1", "D2", "/tmp/image1.png", 0, 0, 0.5, 0.5) +// if err != nil { +// fmt.Println(err) +// } // // Insert a picture offset in the cell. // err = xlsx.AddPicture("Sheet1", "H2", "/tmp/image3.gif", 15, 10, 1, 1) // if err != nil { // fmt.Println(err) -// os.Exit(1) // } // err = xlsx.WriteTo("/tmp/Workbook.xlsx") // if err != nil { diff --git a/rows.go b/rows.go index 89365a23..58b52a36 100644 --- a/rows.go +++ b/rows.go @@ -17,23 +17,37 @@ import ( // } // func (f *File) GetRows(sheet string) [][]string { - xlsx := xlsxWorksheet{} - r := [][]string{} + rows := [][]string{} name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml" - err := xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + decoder := xml.NewDecoder(strings.NewReader(f.readXML(name))) + d, err := readXMLSST(f) if err != nil { - return r + return rows } - rows := xlsx.SheetData.Row - for _, row := range rows { - c := []string{} - for _, colCell := range row.C { - val, _ := colCell.getValueFrom(f) - c = append(c, val) + var inElement string + var row []string + for { + token, _ := decoder.Token() + if token == nil { + break + } + switch startElement := token.(type) { + case xml.StartElement: + inElement = startElement.Name.Local + if inElement == "row" { + var r xlsxRow + decoder.DecodeElement(&r, &startElement) + for _, colCell := range r.C { + val, _ := colCell.getValueFrom(f, d) + row = append(row, val) + } + rows = append(rows, row) + row = row[:0] + } + default: } - r = append(r, c) } - return r + return rows } // SetRowHeight provides a function to set the height of a single row. @@ -65,23 +79,19 @@ func (f *File) SetRowHeight(sheet string, rowIndex int, height float64) { } // readXMLSST read xmlSST simple function. -func readXMLSST(f *File) (xlsxSST, error) { +func readXMLSST(f *File) (*xlsxSST, error) { shardStrings := xlsxSST{} err := xml.Unmarshal([]byte(f.readXML("xl/sharedStrings.xml")), &shardStrings) - return shardStrings, err + return &shardStrings, err } // getValueFrom return a value from a column/row cell, this function is inteded // to be used with for range on rows an argument with the xlsx opened file. -func (xlsx *xlsxC) getValueFrom(f *File) (string, error) { +func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) { switch xlsx.T { case "s": xlsxSI := 0 xlsxSI, _ = strconv.Atoi(xlsx.V) - d, err := readXMLSST(f) - if err != nil { - return "", err - } if len(d.SI[xlsxSI].R) > 0 { value := "" for _, v := range d.SI[xlsxSI].R {