From df8f85d6abdebba567766484705134f30bf5f847 Mon Sep 17 00:00:00 2001 From: Ri Xu Date: Tue, 6 Sep 2016 21:20:24 +0800 Subject: [PATCH] Open file error return added and UpdateLinkedValue function added to fix linked values within a spreadsheet are not updating. --- README.md | 19 +++++++++---- excelize.go | 65 ++++++++++++++++++++++++++++++++++++++------ excelize_test.go | 32 ++++++++++++++-------- lib.go | 12 ++++++-- test/Workbook1.xlsx | Bin 18204 -> 18281 bytes 5 files changed, 101 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1cfe4e5..431aea6 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,15 @@ import ( ) func main() { - xlsx := excelize.CreateFile() + xlsx, err := excelize.CreateFile() + if err != nil { + fmt.Println(err) + } xlsx.NewSheet(2, "Sheet2") xlsx.NewSheet(3, "Sheet3") xlsx.SetCellInt("Sheet2", "A23", 10) xlsx.SetCellStr("Sheet3", "B20", "Hello") - err := xlsx.WriteTo("/home/Workbook.xlsx") + err = xlsx.WriteTo("/home/Workbook.xlsx") if err != nil { fmt.Println(err) } @@ -59,14 +62,17 @@ import ( ) func main() { - xlsx := excelize.OpenFile("/home/Workbook.xlsx") + xlsx, err := excelize.OpenFile("/home/Workbook.xlsx") + if err != nil { + fmt.Println(err) + } 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() + err = xlsx.Save() if err != nil { fmt.Println(err) } @@ -84,7 +90,10 @@ import ( ) func main() { - xlsx := excelize.OpenFile("/home/Workbook.xlsx") + xlsx, err := excelize.OpenFile("/home/Workbook.xlsx") + if err != nil { + fmt.Println(err) + } cell := xlsx.GetCellValue("Sheet2", "D11") fmt.Println(cell) } diff --git a/excelize.go b/excelize.go index d37860f..15710db 100644 --- a/excelize.go +++ b/excelize.go @@ -11,21 +11,28 @@ import ( // File define a populated xlsx.File struct. type File struct { - XLSX map[string]string - Path string + XLSX map[string]string + Path string + SheetCount int } // OpenFile take the name of an XLSX file and returns a populated // xlsx.File struct for it. -func OpenFile(filename string) *File { +func OpenFile(filename string) (*File, error) { var f *zip.ReadCloser + var err error file := make(map[string]string) - f, _ = zip.OpenReader(filename) - file, _ = ReadZip(f) - return &File{ - XLSX: file, - Path: filename, + sheetCount := 0 + f, err = zip.OpenReader(filename) + if err != nil { + return &File{}, err } + file, sheetCount, err = ReadZip(f) + return &File{ + XLSX: file, + Path: filename, + SheetCount: sheetCount, + }, nil } // SetCellInt provide function to set int type value of a cell @@ -176,6 +183,7 @@ func replaceWorkSheetsRelationshipsNameSpace(workbookMarshal string) string { // // // +// Noteice: this method could be very slow for large spreadsheets (more than 3000 rows one sheet). func checkRow(xlsx xlsxWorksheet) xlsxWorksheet { buffer := bytes.Buffer{} for k, v := range xlsx.SheetData.Row { @@ -207,3 +215,44 @@ func checkRow(xlsx xlsxWorksheet) xlsxWorksheet { } return xlsx } + +// UpdateLinkedValue fix linked values within a spreadsheet are not updating. +// This function will be remove value tag when met a cell have a linked value. +// Reference https://social.technet.microsoft.com/Forums/office/en-US/e16bae1f-6a2c-4325-8013-e989a3479066/excel-2010-linked-cells-not-updating?forum=excel +// +// Notice: after open XLSX file Excel will be update linked value and generate +// new value and will prompt save file or not. +// +// For example: +// +// +// +// SUM(Sheet2!D2,Sheet2!D11) +// 100 +// +// +// +// to +// +// +// +// SUM(Sheet2!D2,Sheet2!D11) +// +// +func (f *File) UpdateLinkedValue() { + for i := 1; i <= f.SheetCount; i++ { + var xlsx xlsxWorksheet + name := `xl/worksheets/sheet` + strconv.Itoa(i) + `.xml` + xml.Unmarshal([]byte(f.readXML(name)), &xlsx) + for indexR, row := range xlsx.SheetData.Row { + for indexC, col := range row.C { + if col.F != nil && col.V != `` { + xlsx.SheetData.Row[indexR].C[indexC].V = `` + xlsx.SheetData.Row[indexR].C[indexC].T = `` + } + } + } + output, _ := xml.Marshal(xlsx) + f.saveFileList(name, replaceRelationshipsID(replaceWorkSheetsRelationshipsNameSpace(string(output)))) + } +} diff --git a/excelize_test.go b/excelize_test.go index d206e2d..7af1991 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -7,7 +7,11 @@ import ( func TestExcelize(t *testing.T) { // Test update a XLSX file - file := OpenFile("./test/Workbook1.xlsx") + file, err := OpenFile("./test/Workbook1.xlsx") + if err != nil { + t.Log(err) + } + file.UpdateLinkedValue() file.SetCellInt("SHEET2", "B2", 100) file.SetCellStr("SHEET2", "C11", "Knowns") file.NewSheet(3, "TestSheet") @@ -15,10 +19,20 @@ func TestExcelize(t *testing.T) { file.SetCellStr("SHEET3", "b230", "10") file.SetCellStr("SHEET10", "b230", "10") file.SetActiveSheet(2) + // 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") + for i := 1; i <= 300; i++ { file.SetCellStr("SHEET3", "c"+strconv.Itoa(i), strconv.Itoa(i)) } - err := file.Save() + err = file.Save() if err != nil { t.Log(err) } @@ -45,13 +59,9 @@ func TestExcelize(t *testing.T) { t.Log(err) } - // 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") + // Test open a XLSX file with given illegal path + _, err = OpenFile("./test/Workbook.xlsx") + if err != nil { + t.Log(err) + } } diff --git a/lib.go b/lib.go index 915bca1..0fe6870 100644 --- a/lib.go +++ b/lib.go @@ -14,19 +14,25 @@ import ( // ReadZip takes a pointer to a zip.ReadCloser and returns a // xlsx.File struct populated with its contents. In most cases // ReadZip is not used directly, but is called internally by OpenFile. -func ReadZip(f *zip.ReadCloser) (map[string]string, error) { +func ReadZip(f *zip.ReadCloser) (map[string]string, int, error) { defer f.Close() return ReadZipReader(&f.Reader) } // ReadZipReader can be used to read an XLSX in memory without // touching the filesystem. -func ReadZipReader(r *zip.Reader) (map[string]string, error) { +func ReadZipReader(r *zip.Reader) (map[string]string, int, error) { fileList := make(map[string]string) + worksheets := 0 for _, v := range r.File { fileList[v.Name] = readFile(v) + if len(v.Name) > 18 { + if v.Name[0:19] == "xl/worksheets/sheet" { + worksheets++ + } + } } - return fileList, nil + return fileList, worksheets, nil } // Read XML content as string and replace drawing property in XML namespace of sheet diff --git a/test/Workbook1.xlsx b/test/Workbook1.xlsx index 05b51c27d7823ff3abce08a1df4c479b1af2727a..81565d649d5246946fbf9c5181ec23293476adc9 100644 GIT binary patch delta 1022 zcmbQ!$M~|3al;ixX6XfLo3AsPLKyta9?T$-$x&=_V3}$*U$D&N)9k8XfzRx-q`@jC zD64}7b}7$g2Q#9yk8prx6iqb20=_1yjC`yM)jS)gpSXLUk%1wTd2)lPeEnqa{M!aR z4ey!1$(zhIOXy8{e^p{z_d3UoGF&{~yXU3O+}7%`Ok30Q^Lua0^-O!eBuy6i`BC+0 z`1xxacrDg%)UPm_S;V&YP}KL_gYxh4_4O=2JAT`0a>Myx`GcRKGxIO5tzj3CIQo6x zgIEq{wU%(%h?nXX4*u%AR@%%f*NN8E7bv_oJRvpFZ@GQz)LqZ3ou1u0d|=r{u4gN* ziT&EpZed^)@O9tiX8TKPs`$@&ZI9v?=X&eV;Uz6wraZ-X^(NQbiziQAxNiRB_d&8Z z11r0?M_GQk(ZczVuXW$sO0~2mkJPyAR|I~ed6o*lR77|IN3rP zc0H(nBGDeNxbD%zCZAxxdyAc)c>cSb&RwSs+btT;f3ke|)?(iNzR*jD zd1txDw)btiw0FhAiP^&c9)9D0v5h-rsblZu6R+;d>{&E7z;yDLJEvpVBA@YXKQr-n zPnTrM9=*(IK^L{6)-RqJxPZSeXZ9z#W|K%gvyk~#7Jn1{(n_vPIo-bd{Amt9`?HtV zyK8#xd$Oo=K0?duTx*;@Bw+Jf(11N>sT1!tpYa@wG zKc8&|SbwFhDQ^8&ZLP8B-E3j!0&#l1qd9KPcO7jpC8Z|6R_5Cr;4}%6V}K5v06tEit8G{!4SU$CQ+we9pB%8Z}QbFi0?{FhGF9{6b~4rWAYAK?JYD4J-31$<3Z8Tl9(6d4#U6&g=sWMH_@G`Yc4zJ8K#{%r%E zw)f26PuQIzIkVu1aGAHZ@2$HYs(9lhNg9h*|_F>Vcfhga&P_iJHfY}F;1K+kd*i3 zfX%hgsb?D)KlQlve7Y3Kb>PvmeW#M^oiS{oKbd9I`s$m9M;}r*F$dB0xLthC$fhUu@@PT{Mciu}0#&~E<*QRm;>wo-1| z#+T|>W!x9aJ^k2i-Lt4g%Nv@QE#G|<+pB-YX#fA?JmIRYrO)hcpa1zzt*}nzs?)LP zPygpUb)0l6F5*qX^PlQ(_b+_SJ}r7;=A}j3+D+4xg(oJZO@Hop?SR5J4%@o+E4yb* zJ)Xz)Yf-4ssgr3^>aQn<=^6%GR5qVzUs)l)m^1AJ=xJ#YOM>-kU9X%?ttO|