forked from p30928647/excelize
resolve the issue corrupted xlsx after deleting formula of cell, reference #346
This commit is contained in:
parent
e780e41e02
commit
0072bb7310
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
|
||||
// this source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
//
|
||||
// Package excelize providing a set of functions that allow you to write to
|
||||
// and read from XLSX files. Support reads and writes XLSX file generated by
|
||||
// Microsoft Excel™ 2007 and later. Support save file without losing original
|
||||
// charts of XLSX. This library needs Go version 1.8 or later.
|
||||
|
||||
package excelize
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// calcChainReader provides a function to get the pointer to the structure
|
||||
// after deserialization of xl/calcChain.xml.
|
||||
func (f *File) calcChainReader() *xlsxCalcChain {
|
||||
if f.CalcChain == nil {
|
||||
var c xlsxCalcChain
|
||||
_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML("xl/calcChain.xml")), &c)
|
||||
f.CalcChain = &c
|
||||
}
|
||||
return f.CalcChain
|
||||
}
|
||||
|
||||
// calcChainWriter provides a function to save xl/calcChain.xml after
|
||||
// serialize structure.
|
||||
func (f *File) calcChainWriter() {
|
||||
if f.CalcChain != nil {
|
||||
output, _ := xml.Marshal(f.CalcChain)
|
||||
f.saveFileList("xl/calcChain.xml", output)
|
||||
}
|
||||
}
|
||||
|
||||
// deleteCalcChain provides a function to remove cell reference on the
|
||||
// calculation chain.
|
||||
func (f *File) deleteCalcChain(axis string) {
|
||||
calc := f.calcChainReader()
|
||||
if calc != nil {
|
||||
for i, c := range calc.C {
|
||||
if c.R == axis {
|
||||
calc.C = append(calc.C[:i], calc.C[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(calc.C) == 0 {
|
||||
f.CalcChain = nil
|
||||
delete(f.XLSX, "xl/calcChain.xml")
|
||||
content := f.contentTypesReader()
|
||||
for k, v := range content.Overrides {
|
||||
if v.PartName == "/xl/calcChain.xml" {
|
||||
content.Overrides = append(content.Overrides[:k], content.Overrides[k+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
cell.go
5
cell.go
|
@ -305,6 +305,11 @@ func (f *File) SetCellFormula(sheet, axis, formula string) {
|
|||
completeRow(xlsx, rows, cell)
|
||||
completeCol(xlsx, rows, cell)
|
||||
|
||||
if formula == "" {
|
||||
xlsx.SheetData.Row[xAxis].C[yAxis].F = nil
|
||||
f.deleteCalcChain(axis)
|
||||
return
|
||||
}
|
||||
if xlsx.SheetData.Row[xAxis].C[yAxis].F != nil {
|
||||
xlsx.SheetData.Row[xAxis].C[yAxis].F.Content = formula
|
||||
} else {
|
||||
|
|
4
col.go
4
col.go
|
@ -322,6 +322,10 @@ func (f *File) InsertCol(sheet, column string) {
|
|||
//
|
||||
// xlsx.RemoveCol("Sheet1", "C")
|
||||
//
|
||||
// Use this method with caution, which will affect changes in references such
|
||||
// as formulas, charts, and so on. If there is any referenced value of the
|
||||
// worksheet, it will cause a file error when you open it. The excelize only
|
||||
// partially updates these references currently.
|
||||
func (f *File) RemoveCol(sheet, column string) {
|
||||
xlsx := f.workSheetReader(sheet)
|
||||
for r := range xlsx.SheetData.Row {
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
type File struct {
|
||||
checked map[string]bool
|
||||
sheetMap map[string]string
|
||||
CalcChain *xlsxCalcChain
|
||||
ContentTypes *xlsxTypes
|
||||
Path string
|
||||
SharedStrings *xlsxSST
|
||||
|
@ -201,7 +202,8 @@ func (f *File) UpdateLinkedValue() {
|
|||
// row: Index number of the row we're inserting/deleting before
|
||||
// offset: Number of rows/column to insert/delete negative values indicate deletion
|
||||
//
|
||||
// TODO: adjustPageBreaks, adjustComments, adjustDataValidations, adjustProtectedCells
|
||||
// TODO: adjustCalcChain, adjustPageBreaks, adjustComments,
|
||||
// adjustDataValidations, adjustProtectedCells
|
||||
//
|
||||
func (f *File) adjustHelper(sheet string, column, row, offset int) {
|
||||
xlsx := f.workSheetReader(sheet)
|
||||
|
|
|
@ -342,8 +342,18 @@ func TestSetCellFormula(t *testing.T) {
|
|||
xlsx.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
|
||||
// Test set cell formula with illegal rows number.
|
||||
xlsx.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)")
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellFormula1.xlsx")))
|
||||
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellFormula.xlsx")))
|
||||
xlsx, err = OpenFile(filepath.Join("test", "CalcChain.xlsx"))
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
// Test remove cell formula.
|
||||
xlsx.SetCellFormula("Sheet1", "A1", "")
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellFormula2.xlsx")))
|
||||
// Test remove all cell formula.
|
||||
xlsx.SetCellFormula("Sheet1", "B1", "")
|
||||
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellFormula3.xlsx")))
|
||||
}
|
||||
|
||||
func TestSetSheetBackground(t *testing.T) {
|
||||
|
|
1
file.go
1
file.go
|
@ -92,6 +92,7 @@ func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
|
|||
f.workbookRelsWriter()
|
||||
f.worksheetWriter()
|
||||
f.styleSheetWriter()
|
||||
f.calcChainWriter()
|
||||
for path, content := range f.XLSX {
|
||||
fi, err := zw.Create(path)
|
||||
if err != nil {
|
||||
|
|
14
rows.go
14
rows.go
|
@ -343,6 +343,10 @@ func (f *File) GetRowOutlineLevel(sheet string, rowIndex int) uint8 {
|
|||
//
|
||||
// xlsx.RemoveRow("Sheet1", 2)
|
||||
//
|
||||
// Use this method with caution, which will affect changes in references such
|
||||
// as formulas, charts, and so on. If there is any referenced value of the
|
||||
// worksheet, it will cause a file error when you open it. The excelize only
|
||||
// partially updates these references currently.
|
||||
func (f *File) RemoveRow(sheet string, row int) {
|
||||
if row < 0 {
|
||||
return
|
||||
|
@ -375,15 +379,23 @@ func (f *File) InsertRow(sheet string, row int) {
|
|||
//
|
||||
// xlsx.DuplicateRow("Sheet1", 2)
|
||||
//
|
||||
// Use this method with caution, which will affect changes in references such
|
||||
// as formulas, charts, and so on. If there is any referenced value of the
|
||||
// worksheet, it will cause a file error when you open it. The excelize only
|
||||
// partially updates these references currently.
|
||||
func (f *File) DuplicateRow(sheet string, row int) {
|
||||
f.DuplicateRowTo(sheet, row, row+1)
|
||||
}
|
||||
|
||||
// DuplicateRowTo inserts a copy of specified row at specified row position
|
||||
// movig down exists rows aftet target position
|
||||
// moving down exists rows after target position
|
||||
//
|
||||
// xlsx.DuplicateRowTo("Sheet1", 2, 7)
|
||||
//
|
||||
// Use this method with caution, which will affect changes in references such
|
||||
// as formulas, charts, and so on. If there is any referenced value of the
|
||||
// worksheet, it will cause a file error when you open it. The excelize only
|
||||
// partially updates these references currently.
|
||||
func (f *File) DuplicateRowTo(sheet string, row, row2 int) {
|
||||
if row <= 0 || row2 <= 0 || row == row2 {
|
||||
return
|
||||
|
|
2
sheet.go
2
sheet.go
|
@ -900,7 +900,7 @@ func (p *PageLayoutPaperSize) getPageLayout(ps *xlsxPageSetUp) {
|
|||
// 40 | German standard fanfold (8.5 in. by 12 in.)
|
||||
// 41 | German legal fanfold (8.5 in. by 13 in.)
|
||||
// 42 | ISO B4 (250 mm by 353 mm)
|
||||
// 43 | Japanese double postcard (200 mm by 148 mm)
|
||||
// 43 | Japanese postcard (100 mm by 148 mm)
|
||||
// 44 | Standard paper (9 in. by 11 in.)
|
||||
// 45 | Standard paper (10 in. by 11 in.)
|
||||
// 46 | Standard paper (15 in. by 11 in.)
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of
|
||||
// this source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
//
|
||||
// Package excelize providing a set of functions that allow you to write to
|
||||
// and read from XLSX files. Support reads and writes XLSX file generated by
|
||||
// Microsoft Excel™ 2007 and later. Support save file without losing original
|
||||
// charts of XLSX. This library needs Go version 1.8 or later.
|
||||
|
||||
package excelize
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// xlsxCalcChain directly maps the calcChain element. This element represents the root of the calculation chain.
|
||||
type xlsxCalcChain struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main calcChain"`
|
||||
C []xlsxCalcChainC `xml:"c"`
|
||||
}
|
||||
|
||||
// xlsxCalcChainC directly maps the c element.
|
||||
type xlsxCalcChainC struct {
|
||||
R string `xml:"r,attr"`
|
||||
I int `xml:"i,attr"`
|
||||
L bool `xml:"l,attr,omitempty"`
|
||||
S bool `xml:"s,attr,omitempty"`
|
||||
T bool `xml:"t,attr,omitempty"`
|
||||
A bool `xml:"a,attr,omitempty"`
|
||||
}
|
Loading…
Reference in New Issue