Skip to content

Commit 4a9b39a

Browse files
committed
- Add hyperlink and set formula support for cell support;
- Character limits for cells added; - Update go test and fix typo
1 parent 52796f6 commit 4a9b39a

8 files changed

+196
-91
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func main() {
106106
}
107107
```
108108

109-
### Add pictures to XLSX files
109+
### Add picture to XLSX files
110110

111111
```go
112112
package main
@@ -125,6 +125,11 @@ func main() {
125125
fmt.Println(err)
126126
os.Exit(1)
127127
}
128+
err = xlsx.WriteTo("/tmp/Workbook.xlsx")
129+
if err != nil {
130+
fmt.Println(err)
131+
os.Exit(1)
132+
}
128133
}
129134
```
130135

cell.go

+59-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import (
66
"strings"
77
)
88

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

53-
// GetCellFormula provide function get formula from cell by given sheet index
54-
// and axis in XLSX file.
54+
// GetCellFormula provides function to get formula from cell by given sheet
55+
// index and axis in XLSX file.
5556
func (f *File) GetCellFormula(sheet string, axis string) string {
5657
axis = strings.ToUpper(axis)
5758
var xlsx xlsxWorksheet
@@ -84,3 +85,57 @@ func (f *File) GetCellFormula(sheet string, axis string) string {
8485
}
8586
return ""
8687
}
88+
89+
// SetCellHyperLink provides function to set cell hyperlink by given sheet index
90+
// and link URL address. Only support external link currently.
91+
func (f *File) SetCellHyperLink(sheet, axis, link string) {
92+
axis = strings.ToUpper(axis)
93+
var xlsx xlsxWorksheet
94+
name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
95+
xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
96+
rID := f.addSheetRelationships(sheet, SourceRelationshipHyperLink, link, "External")
97+
hyperlink := xlsxHyperlink{
98+
Ref: axis,
99+
RID: "rId" + strconv.Itoa(rID),
100+
}
101+
if xlsx.Hyperlinks != nil {
102+
xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink, hyperlink)
103+
} else {
104+
hyperlinks := xlsxHyperlinks{}
105+
hyperlinks.Hyperlink = append(hyperlinks.Hyperlink, hyperlink)
106+
xlsx.Hyperlinks = &hyperlinks
107+
}
108+
output, _ := xml.Marshal(xlsx)
109+
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
110+
}
111+
112+
// SetCellFormula provides function to set cell formula by given string and
113+
// sheet index.
114+
func (f *File) SetCellFormula(sheet, axis, formula string) {
115+
axis = strings.ToUpper(axis)
116+
var xlsx xlsxWorksheet
117+
col := string(strings.Map(letterOnlyMapF, axis))
118+
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis))
119+
xAxis := row - 1
120+
yAxis := titleToNumber(col)
121+
122+
name := "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
123+
xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
124+
125+
rows := xAxis + 1
126+
cell := yAxis + 1
127+
128+
xlsx = completeRow(xlsx, rows, cell)
129+
xlsx = completeCol(xlsx, rows, cell)
130+
131+
if xlsx.SheetData.Row[xAxis].C[yAxis].F != nil {
132+
xlsx.SheetData.Row[xAxis].C[yAxis].F.Content = formula
133+
} else {
134+
f := xlsxF{
135+
Content: formula,
136+
}
137+
xlsx.SheetData.Row[xAxis].C[yAxis].F = &f
138+
}
139+
output, _ := xml.Marshal(xlsx)
140+
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
141+
}

excelize.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ func (f *File) SetCellInt(sheet string, axis string, value int) {
8585
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
8686
}
8787

88-
// SetCellStr provides function to set string type value of a cell.
88+
// SetCellStr provides function to set string type value of a cell. Total number
89+
// of characters that a cell can contain 32767 characters.
8990
func (f *File) SetCellStr(sheet string, axis string, value string) {
9091
axis = strings.ToUpper(axis)
92+
if len(value) > 32767 {
93+
value = value[0:32767]
94+
}
9195
var xlsx xlsxWorksheet
9296
col := string(strings.Map(letterOnlyMapF, axis))
9397
row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis))

excelize_test.go

+110-71
Original file line numberDiff line numberDiff line change
@@ -7,122 +7,133 @@ import (
77

88
func TestOpenFile(t *testing.T) {
99
// Test update a XLSX file.
10-
f1, err := OpenFile("./test/Workbook1.xlsx")
10+
xlsx, err := OpenFile("./test/Workbook1.xlsx")
1111
if err != nil {
1212
t.Log(err)
1313
}
1414
// Test get all the rows in a not exists sheet.
15-
rows := f1.GetRows("Sheet4")
15+
rows := xlsx.GetRows("Sheet4")
1616
// Test get all the rows in a sheet.
17-
rows = f1.GetRows("Sheet2")
17+
rows = xlsx.GetRows("Sheet2")
1818
for _, row := range rows {
1919
for _, cell := range row {
2020
t.Log(cell, "\t")
2121
}
2222
t.Log("\r\n")
2323
}
24-
f1.UpdateLinkedValue()
25-
f1.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
26-
f1.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
27-
f1.SetCellInt("SHEET2", "A1", 100)
28-
f1.SetCellStr("SHEET2", "C11", "Knowns")
29-
f1.NewSheet(3, ":\\/?*[]Maximum 31 characters allowed in sheet title.")
24+
xlsx.UpdateLinkedValue()
25+
xlsx.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(100.1588), 'f', -1, 32))
26+
xlsx.SetCellDefault("SHEET2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
27+
xlsx.SetCellInt("SHEET2", "A1", 100)
28+
xlsx.SetCellStr("SHEET2", "C11", "Knowns")
29+
// Test max characters in a cell.
30+
var s = "c"
31+
for i := 0; i < 32768; i++ {
32+
s += "c"
33+
}
34+
xlsx.SetCellStr("SHEET2", "D11", s)
35+
xlsx.NewSheet(3, ":\\/?*[]Maximum 31 characters allowed in sheet title.")
3036
// Test set sheet name with illegal name.
31-
f1.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
32-
f1.SetCellInt("Sheet3", "A23", 10)
33-
f1.SetCellStr("SHEET3", "b230", "10")
34-
f1.SetCellStr("SHEET10", "b230", "10")
35-
f1.SetActiveSheet(2)
36-
f1.GetCellFormula("Sheet1", "B19") // Test get cell formula with given rows number.
37-
f1.GetCellFormula("Sheet2", "B20") // Test get cell formula with illegal sheet index.
38-
f1.GetCellFormula("Sheet1", "B20") // Test get cell formula with illegal rows number.
37+
xlsx.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
38+
xlsx.SetCellInt("Sheet3", "A23", 10)
39+
xlsx.SetCellStr("SHEET3", "b230", "10")
40+
xlsx.SetCellStr("SHEET10", "b230", "10")
41+
xlsx.SetActiveSheet(2)
42+
xlsx.GetCellFormula("Sheet1", "B19") // Test get cell formula with given rows number.
43+
xlsx.GetCellFormula("Sheet2", "B20") // Test get cell formula with illegal sheet index.
44+
xlsx.GetCellFormula("Sheet1", "B20") // Test get cell formula with illegal rows number.
3945
// Test read cell value with given illegal rows number.
40-
f1.GetCellValue("Sheet2", "a-1")
46+
xlsx.GetCellValue("Sheet2", "a-1")
4147
// Test read cell value with given lowercase column number.
42-
f1.GetCellValue("Sheet2", "a5")
43-
f1.GetCellValue("Sheet2", "C11")
44-
f1.GetCellValue("Sheet2", "D11")
45-
f1.GetCellValue("Sheet2", "D12")
48+
xlsx.GetCellValue("Sheet2", "a5")
49+
xlsx.GetCellValue("Sheet2", "C11")
50+
xlsx.GetCellValue("Sheet2", "D11")
51+
xlsx.GetCellValue("Sheet2", "D12")
4652
// Test SetCellValue function.
47-
f1.SetCellValue("Sheet2", "F1", "Hello")
48-
f1.SetCellValue("Sheet2", "G1", []byte("World"))
49-
f1.SetCellValue("Sheet2", "F2", 42)
50-
f1.SetCellValue("Sheet2", "F2", int8(42))
51-
f1.SetCellValue("Sheet2", "F2", int16(42))
52-
f1.SetCellValue("Sheet2", "F2", int32(42))
53-
f1.SetCellValue("Sheet2", "F2", int64(42))
54-
f1.SetCellValue("Sheet2", "F2", float32(42.65418))
55-
f1.SetCellValue("Sheet2", "F2", float64(-42.65418))
56-
f1.SetCellValue("Sheet2", "F2", float32(42))
57-
f1.SetCellValue("Sheet2", "F2", float64(42))
58-
f1.SetCellValue("Sheet2", "G2", nil)
53+
xlsx.SetCellValue("Sheet2", "F1", "Hello")
54+
xlsx.SetCellValue("Sheet2", "G1", []byte("World"))
55+
xlsx.SetCellValue("Sheet2", "F2", 42)
56+
xlsx.SetCellValue("Sheet2", "F2", int8(42))
57+
xlsx.SetCellValue("Sheet2", "F2", int16(42))
58+
xlsx.SetCellValue("Sheet2", "F2", int32(42))
59+
xlsx.SetCellValue("Sheet2", "F2", int64(42))
60+
xlsx.SetCellValue("Sheet2", "F2", float32(42.65418))
61+
xlsx.SetCellValue("Sheet2", "F2", float64(-42.65418))
62+
xlsx.SetCellValue("Sheet2", "F2", float32(42))
63+
xlsx.SetCellValue("Sheet2", "F2", float64(42))
64+
xlsx.SetCellValue("Sheet2", "G2", nil)
5965
// Test completion column.
60-
f1.SetCellValue("Sheet2", "M2", nil)
66+
xlsx.SetCellValue("Sheet2", "M2", nil)
6167
// Test read cell value with given axis large than exists row.
62-
f1.GetCellValue("Sheet2", "E231")
68+
xlsx.GetCellValue("Sheet2", "E231")
6369
// Test get active sheet of XLSX and get sheet name of XLSX by given sheet index.
64-
f1.GetSheetName(f1.GetActiveSheetIndex())
70+
xlsx.GetSheetName(xlsx.GetActiveSheetIndex())
6571
// Test get sheet name of XLSX by given invalid sheet index.
66-
f1.GetSheetName(4)
72+
xlsx.GetSheetName(4)
6773
// Test get sheet map of XLSX.
68-
f1.GetSheetMap()
69-
74+
xlsx.GetSheetMap()
7075
for i := 1; i <= 300; i++ {
71-
f1.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
76+
xlsx.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i))
77+
}
78+
err = xlsx.Save()
79+
if err != nil {
80+
t.Log(err)
81+
}
82+
// Test write file to not exist directory.
83+
err = xlsx.WriteTo("")
84+
if err != nil {
85+
t.Log(err)
7286
}
73-
err = f1.Save()
87+
}
88+
89+
func TestAddPicture(t *testing.T) {
90+
xlsx, err := OpenFile("./test/Workbook1.xlsx")
7491
if err != nil {
7592
t.Log(err)
7693
}
7794
// Test add picture to sheet.
78-
err = f1.AddPicture("Sheet2", "I1", "L10", "./test/images/excel.jpg")
95+
err = xlsx.AddPicture("Sheet2", "I1", "L10", "./test/images/excel.jpg")
7996
if err != nil {
8097
t.Log(err)
8198
}
82-
err = f1.AddPicture("Sheet1", "F21", "G25", "./test/images/excel.png")
99+
err = xlsx.AddPicture("Sheet1", "F21", "G25", "./test/images/excel.png")
83100
if err != nil {
84101
t.Log(err)
85102
}
86-
err = f1.AddPicture("Sheet2", "L1", "O10", "./test/images/excel.bmp")
103+
err = xlsx.AddPicture("Sheet2", "L1", "O10", "./test/images/excel.bmp")
87104
if err != nil {
88105
t.Log(err)
89106
}
90-
err = f1.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.ico")
107+
err = xlsx.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.ico")
91108
if err != nil {
92109
t.Log(err)
93110
}
94111
// Test add picture to sheet with unsupport file type.
95-
err = f1.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.icon")
112+
err = xlsx.AddPicture("Sheet1", "G21", "H25", "./test/images/excel.icon")
96113
if err != nil {
97114
t.Log(err)
98115
}
99116
// Test add picture to sheet with invalid file path.
100-
err = f1.AddPicture("Sheet1", "G21", "H25", "./test/Workbook1.xlsx")
117+
err = xlsx.AddPicture("Sheet1", "G21", "H25", "./test/Workbook1.xlsx")
101118
if err != nil {
102119
t.Log(err)
103120
}
104-
105121
// Test write file to given path.
106-
err = f1.WriteTo("./test/Workbook_2.xlsx")
107-
if err != nil {
108-
t.Log(err)
109-
}
110-
// Test write file to not exist directory.
111-
err = f1.WriteTo("")
122+
err = xlsx.WriteTo("./test/Workbook_2.xlsx")
112123
if err != nil {
113124
t.Log(err)
114125
}
115126
}
116127

117128
func TestBrokenFile(t *testing.T) {
118129
// Test write file with broken file struct.
119-
f2 := File{}
120-
err := f2.Save()
130+
xlsx := File{}
131+
err := xlsx.Save()
121132
if err != nil {
122133
t.Log(err)
123134
}
124135
// Test write file with broken file struct with given path.
125-
err = f2.WriteTo("./test/Workbook_3.xlsx")
136+
err = xlsx.WriteTo("./test/Workbook_3.xlsx")
126137
if err != nil {
127138
t.Log(err)
128139
}
@@ -143,35 +154,63 @@ func TestBrokenFile(t *testing.T) {
143154

144155
func TestCreateFile(t *testing.T) {
145156
// Test create a XLSX file.
146-
f4 := CreateFile()
147-
f4.NewSheet(2, "XLSXSheet2")
148-
f4.NewSheet(3, "XLSXSheet3")
149-
f4.SetCellInt("Sheet2", "A23", 56)
150-
f4.SetCellStr("SHEET1", "B20", "42")
151-
f4.SetActiveSheet(0)
157+
xlsx := CreateFile()
158+
xlsx.NewSheet(2, "XLSXSheet2")
159+
xlsx.NewSheet(3, "XLSXSheet3")
160+
xlsx.SetCellInt("Sheet2", "A23", 56)
161+
xlsx.SetCellStr("SHEET1", "B20", "42")
162+
xlsx.SetActiveSheet(0)
152163
// Test add picture to sheet.
153-
err := f4.AddPicture("Sheet1", "H2", "K12", "./test/images/excel.gif")
164+
err := xlsx.AddPicture("Sheet1", "H2", "K12", "./test/images/excel.gif")
154165
if err != nil {
155166
t.Log(err)
156167
}
157-
err = f4.AddPicture("Sheet1", "C2", "F12", "./test/images/excel.tif")
168+
err = xlsx.AddPicture("Sheet1", "C2", "F12", "./test/images/excel.tif")
158169
if err != nil {
159170
t.Log(err)
160171
}
161-
err = f4.WriteTo("./test/Workbook_3.xlsx")
172+
err = xlsx.WriteTo("./test/Workbook_3.xlsx")
162173
if err != nil {
163174
t.Log(err)
164175
}
165176
}
166177

167178
func TestSetColWidth(t *testing.T) {
168-
f5, err := OpenFile("./test/Workbook1.xlsx")
179+
xlsx, err := OpenFile("./test/Workbook1.xlsx")
180+
if err != nil {
181+
t.Log(err)
182+
}
183+
xlsx.SetColWidth("sheet1", "B", "A", 12)
184+
xlsx.SetColWidth("sheet1", "A", "B", 12)
185+
err = xlsx.Save()
186+
if err != nil {
187+
t.Log(err)
188+
}
189+
}
190+
191+
func TestSetCellHyperLink(t *testing.T) {
192+
xlsx, err := OpenFile("./test/Workbook1.xlsx")
193+
if err != nil {
194+
t.Log(err)
195+
}
196+
// Test set cell hyperlink in a work sheet already have hyperlinks.
197+
xlsx.SetCellHyperLink("sheet1", "B19", "https://github.com/Luxurioust/excelize")
198+
// Test add first hyperlink in a work sheet.
199+
xlsx.SetCellHyperLink("sheet2", "C1", "https://github.com/Luxurioust/excelize")
200+
err = xlsx.Save()
201+
if err != nil {
202+
t.Log(err)
203+
}
204+
}
205+
206+
func TestSetCellFormula(t *testing.T) {
207+
xlsx, err := OpenFile("./test/Workbook1.xlsx")
169208
if err != nil {
170209
t.Log(err)
171210
}
172-
f5.SetColWidth("sheet1", "B", "A", 12)
173-
f5.SetColWidth("sheet1", "A", "B", 12)
174-
err = f5.Save()
211+
xlsx.SetCellFormula("sheet1", "B19", "SUM(Sheet2!D2,Sheet2!D11)")
212+
xlsx.SetCellFormula("sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
213+
err = xlsx.Save()
175214
if err != nil {
176215
t.Log(err)
177216
}

0 commit comments

Comments
 (0)