Skip to content

Commit

Permalink
- Add hyperlink and set formula support for cell support;
Browse files Browse the repository at this point in the history
- Character limits for cells added;
- Update go test and fix typo
  • Loading branch information
xuri committed Jan 19, 2017
1 parent 52796f6 commit 4a9b39a
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 91 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func main() {
}
```

### Add pictures to XLSX files
### Add picture to XLSX files

```go
package main
Expand All @@ -125,6 +125,11 @@ func main() {
fmt.Println(err)
os.Exit(1)
}
err = xlsx.WriteTo("/tmp/Workbook.xlsx")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
```

Expand Down
63 changes: 59 additions & 4 deletions cell.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"strings"
)

// GetCellValue provide function get value from cell by given sheet index and
// axis in XLSX file. The value of the merged cell is not available currently.
// GetCellValue provides function to get value from cell by given sheet index
// and axis in XLSX file. The value of the merged cell is not available
// currently.
func (f *File) GetCellValue(sheet string, axis string) string {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
Expand Down Expand Up @@ -50,8 +51,8 @@ func (f *File) GetCellValue(sheet string, axis string) string {
return ""
}

// GetCellFormula provide function get formula from cell by given sheet index
// and axis in XLSX file.
// GetCellFormula provides function to get formula from cell by given sheet
// index and axis in XLSX file.
func (f *File) GetCellFormula(sheet string, axis string) string {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
Expand Down Expand Up @@ -84,3 +85,57 @@ func (f *File) GetCellFormula(sheet string, axis string) string {
}
return ""
}

// SetCellHyperLink provides function to set cell hyperlink by given sheet index
// and link URL address. Only support external link currently.
func (f *File) SetCellHyperLink(sheet, axis, link string) {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
rID := f.addSheetRelationships(sheet, SourceRelationshipHyperLink, link, "External")
hyperlink := xlsxHyperlink{
Ref: axis,
RID: "rId" + strconv.Itoa(rID),
}
if xlsx.Hyperlinks != nil {
xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink, hyperlink)
} else {
hyperlinks := xlsxHyperlinks{}
hyperlinks.Hyperlink = append(hyperlinks.Hyperlink, hyperlink)
xlsx.Hyperlinks = &hyperlinks
}
output, _ := xml.Marshal(xlsx)
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
}

// SetCellFormula provides function to set cell formula by given string and
// sheet index.
func (f *File) SetCellFormula(sheet, axis, formula string) {
axis = strings.ToUpper(axis)
var xlsx xlsxWorksheet
col := string(strings.Map(letterOnlyMapF, axis))
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis))
xAxis := row - 1
yAxis := titleToNumber(col)

name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
xml.Unmarshal([]byte(f.readXML(name)), &xlsx)

rows := xAxis + 1
cell := yAxis + 1

xlsx = completeRow(xlsx, rows, cell)
xlsx = completeCol(xlsx, rows, cell)

if xlsx.SheetData.Row[xAxis].C[yAxis].F != nil {
xlsx.SheetData.Row[xAxis].C[yAxis].F.Content = formula
} else {
f := xlsxF{
Content: formula,
}
xlsx.SheetData.Row[xAxis].C[yAxis].F = &f
}
output, _ := xml.Marshal(xlsx)
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
}
6 changes: 5 additions & 1 deletion excelize.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,13 @@ func (f *File) SetCellInt(sheet string, axis string, value int) {
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
}

// SetCellStr provides function to set string type value of a cell.
// SetCellStr provides function to set string type value of a cell. Total number
// of characters that a cell can contain 32767 characters.
func (f *File) SetCellStr(sheet string, axis string, value string) {
axis = strings.ToUpper(axis)
if len(value) > 32767 {
value = value[0:32767]
}
var xlsx xlsxWorksheet
col := string(strings.Map(letterOnlyMapF, axis))
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis))
Expand Down
181 changes: 110 additions & 71 deletions excelize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,122 +7,133 @@ import (

func TestOpenFile(t *testing.T) {
// Test update a XLSX file.
f1, err := OpenFile("./test/Workbook1.xlsx")
xlsx, err := OpenFile("./test/Workbook1.xlsx")
if err != nil {
t.Log(err)
}
// Test get all the rows in a not exists sheet.
rows := f1.GetRows("Sheet4")
rows := xlsx.GetRows("Sheet4")
// Test get all the rows in a sheet.
rows = f1.GetRows("Sheet2")
rows = xlsx.GetRows("Sheet2")
for _, row := range rows {
for _, cell := range row {
t.Log(cell, "\t")
}
t.Log("\r\n")
}
f1.UpdateLinkedValue()
f1.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
f1.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
f1.SetCellInt("SHEET2", "A1", 100)
f1.SetCellStr("SHEET2", "C11", "Knowns")
f1.NewSheet(3, ":\\/?*[]Maximum 31 characters allowed in sheet title.")
xlsx.UpdateLinkedValue()
xlsx.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
xlsx.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
xlsx.SetCellInt("SHEET2", "A1", 100)
xlsx.SetCellStr("SHEET2", "C11", "Knowns")
// Test max characters in a cell.
var s = "c"
for i := 0; i < 32768; i++ {
s += "c"
}
xlsx.SetCellStr("SHEET2", "D11", s)
xlsx.NewSheet(3, ":\\/?*[]Maximum 31 characters allowed in sheet title.")
// Test set sheet name with illegal name.
f1.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
f1.SetCellInt("Sheet3", "A23", 10)
f1.SetCellStr("SHEET3", "b230", "10")
f1.SetCellStr("SHEET10", "b230", "10")
f1.SetActiveSheet(2)
f1.GetCellFormula("Sheet1", "B19") // Test get cell formula with given rows number.
f1.GetCellFormula("Sheet2", "B20") // Test get cell formula with illegal sheet index.
f1.GetCellFormula("Sheet1", "B20") // Test get cell formula with illegal rows number.
xlsx.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
xlsx.SetCellInt("Sheet3", "A23", 10)
xlsx.SetCellStr("SHEET3", "b230", "10")
xlsx.SetCellStr("SHEET10", "b230", "10")
xlsx.SetActiveSheet(2)
xlsx.GetCellFormula("Sheet1", "B19") // Test get cell formula with given rows number.
xlsx.GetCellFormula("Sheet2", "B20") // Test get cell formula with illegal sheet index.
xlsx.GetCellFormula("Sheet1", "B20") // Test get cell formula with illegal rows number.
// Test read cell value with given illegal rows number.
f1.GetCellValue("Sheet2", "a-1")
xlsx.GetCellValue("Sheet2", "a-1")
// Test read cell value with given lowercase column number.
f1.GetCellValue("Sheet2", "a5")
f1.GetCellValue("Sheet2", "C11")
f1.GetCellValue("Sheet2", "D11")
f1.GetCellValue("Sheet2", "D12")
xlsx.GetCellValue("Sheet2", "a5")
xlsx.GetCellValue("Sheet2", "C11")
xlsx.GetCellValue("Sheet2", "D11")
xlsx.GetCellValue("Sheet2", "D12")
// Test SetCellValue function.
f1.SetCellValue("Sheet2", "F1", "Hello")
f1.SetCellValue("Sheet2", "G1", []byte("World"))
f1.SetCellValue("Sheet2", "F2", 42)
f1.SetCellValue("Sheet2", "F2", int8(42))
f1.SetCellValue("Sheet2", "F2", int16(42))
f1.SetCellValue("Sheet2", "F2", int32(42))
f1.SetCellValue("Sheet2", "F2", int64(42))
f1.SetCellValue("Sheet2", "F2", float32(42.65418))
f1.SetCellValue("Sheet2", "F2", float64(-42.65418))
f1.SetCellValue("Sheet2", "F2", float32(42))
f1.SetCellValue("Sheet2", "F2", float64(42))
f1.SetCellValue("Sheet2", "G2", nil)
xlsx.SetCellValue("Sheet2", "F1", "Hello")
xlsx.SetCellValue("Sheet2", "G1", []byte("World"))
xlsx.SetCellValue("Sheet2", "F2", 42)
xlsx.SetCellValue("Sheet2", "F2", int8(42))
xlsx.SetCellValue("Sheet2", "F2", int16(42))
xlsx.SetCellValue("Sheet2", "F2", int32(42))
xlsx.SetCellValue("Sheet2", "F2", int64(42))
xlsx.SetCellValue("Sheet2", "F2", float32(42.65418))
xlsx.SetCellValue("Sheet2", "F2", float64(-42.65418))
xlsx.SetCellValue("Sheet2", "F2", float32(42))
xlsx.SetCellValue("Sheet2", "F2", float64(42))
xlsx.SetCellValue("Sheet2", "G2", nil)
// Test completion column.
f1.SetCellValue("Sheet2", "M2", nil)
xlsx.SetCellValue("Sheet2", "M2", nil)
// Test read cell value with given axis large than exists row.
f1.GetCellValue("Sheet2", "E231")
xlsx.GetCellValue("Sheet2", "E231")
// Test get active sheet of XLSX and get sheet name of XLSX by given sheet index.
f1.GetSheetName(f1.GetActiveSheetIndex())
xlsx.GetSheetName(xlsx.GetActiveSheetIndex())
// Test get sheet name of XLSX by given invalid sheet index.
f1.GetSheetName(4)
xlsx.GetSheetName(4)
// Test get sheet map of XLSX.
f1.GetSheetMap()

xlsx.GetSheetMap()
for i := 1; i <= 300; i++ {
f1.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
xlsx.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
}
err = xlsx.Save()
if err != nil {
t.Log(err)
}
// Test write file to not exist directory.
err = xlsx.WriteTo("")
if err != nil {
t.Log(err)
}
err = f1.Save()
}

func TestAddPicture(t *testing.T) {
xlsx, err := OpenFile("./test/Workbook1.xlsx")
if err != nil {
t.Log(err)
}
// Test add picture to sheet.
err = f1.AddPicture("Sheet2", "I1", "L10", "./test/images/excel.jpg")
err = xlsx.AddPicture("Sheet2", "I1", "L10", "./test/images/excel.jpg")
if err != nil {
t.Log(err)
}
err = f1.AddPicture("Sheet1", "F21", "G25", "./test/images/excel.png")
err = xlsx.AddPicture("Sheet1", "F21", "G25", "./test/images/excel.png")
if err != nil {
t.Log(err)
}
err = f1.AddPicture("Sheet2", "L1", "O10", "./test/images/excel.bmp")
err = xlsx.AddPicture("Sheet2", "L1", "O10", "./test/images/excel.bmp")
if err != nil {
t.Log(err)
}
err = f1.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.ico")
err = xlsx.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.ico")
if err != nil {
t.Log(err)
}
// Test add picture to sheet with unsupport file type.
err = f1.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.icon")
err = xlsx.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.icon")
if err != nil {
t.Log(err)
}
// Test add picture to sheet with invalid file path.
err = f1.AddPicture("Sheet1", "G21", "H25", "./test/Workbook1.xlsx")
err = xlsx.AddPicture("Sheet1", "G21", "H25", "./test/Workbook1.xlsx")
if err != nil {
t.Log(err)
}

// Test write file to given path.
err = f1.WriteTo("./test/Workbook_2.xlsx")
if err != nil {
t.Log(err)
}
// Test write file to not exist directory.
err = f1.WriteTo("")
err = xlsx.WriteTo("./test/Workbook_2.xlsx")
if err != nil {
t.Log(err)
}
}

func TestBrokenFile(t *testing.T) {
// Test write file with broken file struct.
f2 := File{}
err := f2.Save()
xlsx := File{}
err := xlsx.Save()
if err != nil {
t.Log(err)
}
// Test write file with broken file struct with given path.
err = f2.WriteTo("./test/Workbook_3.xlsx")
err = xlsx.WriteTo("./test/Workbook_3.xlsx")
if err != nil {
t.Log(err)
}
Expand All @@ -143,35 +154,63 @@ func TestBrokenFile(t *testing.T) {

func TestCreateFile(t *testing.T) {
// Test create a XLSX file.
f4 := CreateFile()
f4.NewSheet(2, "XLSXSheet2")
f4.NewSheet(3, "XLSXSheet3")
f4.SetCellInt("Sheet2", "A23", 56)
f4.SetCellStr("SHEET1", "B20", "42")
f4.SetActiveSheet(0)
xlsx := CreateFile()
xlsx.NewSheet(2, "XLSXSheet2")
xlsx.NewSheet(3, "XLSXSheet3")
xlsx.SetCellInt("Sheet2", "A23", 56)
xlsx.SetCellStr("SHEET1", "B20", "42")
xlsx.SetActiveSheet(0)
// Test add picture to sheet.
err := f4.AddPicture("Sheet1", "H2", "K12", "./test/images/excel.gif")
err := xlsx.AddPicture("Sheet1", "H2", "K12", "./test/images/excel.gif")
if err != nil {
t.Log(err)
}
err = f4.AddPicture("Sheet1", "C2", "F12", "./test/images/excel.tif")
err = xlsx.AddPicture("Sheet1", "C2", "F12", "./test/images/excel.tif")
if err != nil {
t.Log(err)
}
err = f4.WriteTo("./test/Workbook_3.xlsx")
err = xlsx.WriteTo("./test/Workbook_3.xlsx")
if err != nil {
t.Log(err)
}
}

func TestSetColWidth(t *testing.T) {
f5, err := OpenFile("./test/Workbook1.xlsx")
xlsx, err := OpenFile("./test/Workbook1.xlsx")
if err != nil {
t.Log(err)
}
xlsx.SetColWidth("sheet1", "B", "A", 12)
xlsx.SetColWidth("sheet1", "A", "B", 12)
err = xlsx.Save()
if err != nil {
t.Log(err)
}
}

func TestSetCellHyperLink(t *testing.T) {
xlsx, err := OpenFile("./test/Workbook1.xlsx")
if err != nil {
t.Log(err)
}
// Test set cell hyperlink in a work sheet already have hyperlinks.
xlsx.SetCellHyperLink("sheet1", "B19", "https://github.com/Luxurioust/excelize")
// Test add first hyperlink in a work sheet.
xlsx.SetCellHyperLink("sheet2", "C1", "https://github.com/Luxurioust/excelize")
err = xlsx.Save()
if err != nil {
t.Log(err)
}
}

func TestSetCellFormula(t *testing.T) {
xlsx, err := OpenFile("./test/Workbook1.xlsx")
if err != nil {
t.Log(err)
}
f5.SetColWidth("sheet1", "B", "A", 12)
f5.SetColWidth("sheet1", "A", "B", 12)
err = f5.Save()
xlsx.SetCellFormula("sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")
xlsx.SetCellFormula("sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
err = xlsx.Save()
if err != nil {
t.Log(err)
}
Expand Down
Loading

0 comments on commit 4a9b39a

Please sign in to comment.