Support update volatile dependencies on inserting/deleting columns/rows
This commit is contained in:
parent
b41a6cc3cd
commit
7291e787bd
86
adjust.go
86
adjust.go
|
@ -38,7 +38,7 @@ const (
|
||||||
// row: Index number of the row we're inserting/deleting before
|
// row: Index number of the row we're inserting/deleting before
|
||||||
// offset: Number of rows/column to insert/delete negative values indicate deletion
|
// offset: Number of rows/column to insert/delete negative values indicate deletion
|
||||||
//
|
//
|
||||||
// TODO: adjustPageBreaks, adjustComments, adjustDataValidations, adjustProtectedCells
|
// TODO: adjustComments, adjustDataValidations, adjustDrawings, adjustPageBreaks, adjustProtectedCells
|
||||||
func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
|
func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,6 +66,9 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
|
||||||
if err = f.adjustCalcChain(dir, num, offset, sheetID); err != nil {
|
if err = f.adjustCalcChain(dir, num, offset, sheetID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err = f.adjustVolatileDeps(dir, num, offset, sheetID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if ws.MergeCells != nil && len(ws.MergeCells.Cells) == 0 {
|
if ws.MergeCells != nil && len(ws.MergeCells.Cells) == 0 {
|
||||||
ws.MergeCells = nil
|
ws.MergeCells = nil
|
||||||
}
|
}
|
||||||
|
@ -498,7 +501,8 @@ func (f *File) adjustTable(ws *xlsxWorksheet, sheet string, dir adjustDirection,
|
||||||
t.AutoFilter.Ref = t.Ref
|
t.AutoFilter.Ref = t.Ref
|
||||||
}
|
}
|
||||||
_ = f.setTableColumns(sheet, true, x1, y1, x2, &t)
|
_ = f.setTableColumns(sheet, true, x1, y1, x2, &t)
|
||||||
t.TotalsRowCount = 0
|
// Currently doesn't support query table
|
||||||
|
t.TableType, t.TotalsRowCount, t.ConnectionID = "", 0, 0
|
||||||
table, _ := xml.Marshal(t)
|
table, _ := xml.Marshal(t)
|
||||||
f.saveFileList(tableXML, table)
|
f.saveFileList(tableXML, table)
|
||||||
}
|
}
|
||||||
|
@ -578,7 +582,6 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off
|
||||||
if dir == rows {
|
if dir == rows {
|
||||||
if y1 == num && y2 == num && offset < 0 {
|
if y1 == num && y2 == num && offset < 0 {
|
||||||
f.deleteMergeCell(ws, i)
|
f.deleteMergeCell(ws, i)
|
||||||
i--
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +589,6 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off
|
||||||
} else {
|
} else {
|
||||||
if x1 == num && x2 == num && offset < 0 {
|
if x1 == num && x2 == num && offset < 0 {
|
||||||
f.deleteMergeCell(ws, i)
|
f.deleteMergeCell(ws, i)
|
||||||
i--
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,18 +644,15 @@ func (f *File) deleteMergeCell(ws *xlsxWorksheet, idx int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjustCalcChainRef update the cell reference in calculation chain when
|
// adjustCellName returns updated cell name by giving column/row number and
|
||||||
// inserting or deleting rows or columns.
|
// offset on inserting or deleting rows or columns.
|
||||||
func (f *File) adjustCalcChainRef(i, c, r, offset int, dir adjustDirection) {
|
func adjustCellName(cell string, dir adjustDirection, c, r, offset int) (string, error) {
|
||||||
if dir == rows {
|
if dir == rows {
|
||||||
if rn := r + offset; rn > 0 {
|
if rn := r + offset; rn > 0 {
|
||||||
f.CalcChain.C[i].R, _ = CoordinatesToCellName(c, rn)
|
return CoordinatesToCellName(c, rn)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
if nc := c + offset; nc > 0 {
|
|
||||||
f.CalcChain.C[i].R, _ = CoordinatesToCellName(nc, r)
|
|
||||||
}
|
}
|
||||||
|
return CoordinatesToCellName(c+offset, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjustCalcChain provides a function to update the calculation chain when
|
// adjustCalcChain provides a function to update the calculation chain when
|
||||||
|
@ -665,7 +664,8 @@ func (f *File) adjustCalcChain(dir adjustDirection, num, offset, sheetID int) er
|
||||||
// If sheet ID is omitted, it is assumed to be the same as the i value of
|
// If sheet ID is omitted, it is assumed to be the same as the i value of
|
||||||
// the previous cell.
|
// the previous cell.
|
||||||
var prevSheetID int
|
var prevSheetID int
|
||||||
for index, c := range f.CalcChain.C {
|
for i := 0; i < len(f.CalcChain.C); i++ {
|
||||||
|
c := f.CalcChain.C[i]
|
||||||
if c.I == 0 {
|
if c.I == 0 {
|
||||||
c.I = prevSheetID
|
c.I = prevSheetID
|
||||||
}
|
}
|
||||||
|
@ -680,16 +680,72 @@ func (f *File) adjustCalcChain(dir adjustDirection, num, offset, sheetID int) er
|
||||||
if dir == rows && num <= rowNum {
|
if dir == rows && num <= rowNum {
|
||||||
if num == rowNum && offset == -1 {
|
if num == rowNum && offset == -1 {
|
||||||
_ = f.deleteCalcChain(c.I, c.R)
|
_ = f.deleteCalcChain(c.I, c.R)
|
||||||
|
i--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
f.adjustCalcChainRef(index, colNum, rowNum, offset, dir)
|
f.CalcChain.C[i].R, _ = adjustCellName(c.R, dir, colNum, rowNum, offset)
|
||||||
}
|
}
|
||||||
if dir == columns && num <= colNum {
|
if dir == columns && num <= colNum {
|
||||||
if num == colNum && offset == -1 {
|
if num == colNum && offset == -1 {
|
||||||
_ = f.deleteCalcChain(c.I, c.R)
|
_ = f.deleteCalcChain(c.I, c.R)
|
||||||
|
i--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
f.adjustCalcChainRef(index, colNum, rowNum, offset, dir)
|
f.CalcChain.C[i].R, _ = adjustCellName(c.R, dir, colNum, rowNum, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjustVolatileDepsTopic updates the volatile dependencies topic when
|
||||||
|
// inserting or deleting rows or columns.
|
||||||
|
func (vt *xlsxVolTypes) adjustVolatileDepsTopic(cell string, dir adjustDirection, indexes []int) (int, error) {
|
||||||
|
num, offset, i1, i2, i3, i4 := indexes[0], indexes[1], indexes[2], indexes[3], indexes[4], indexes[5]
|
||||||
|
colNum, rowNum, err := CellNameToCoordinates(cell)
|
||||||
|
if err != nil {
|
||||||
|
return i4, err
|
||||||
|
}
|
||||||
|
if dir == rows && num <= rowNum {
|
||||||
|
if num == rowNum && offset == -1 {
|
||||||
|
vt.deleteVolTopicRef(i1, i2, i3, i4)
|
||||||
|
i4--
|
||||||
|
return i4, err
|
||||||
|
}
|
||||||
|
vt.VolType[i1].Main[i2].Tp[i3].Tr[i4].R, _ = adjustCellName(cell, dir, colNum, rowNum, offset)
|
||||||
|
}
|
||||||
|
if dir == columns && num <= colNum {
|
||||||
|
if num == colNum && offset == -1 {
|
||||||
|
vt.deleteVolTopicRef(i1, i2, i3, i4)
|
||||||
|
i4--
|
||||||
|
return i4, err
|
||||||
|
}
|
||||||
|
if name, _ := adjustCellName(cell, dir, colNum, rowNum, offset); name != "" {
|
||||||
|
vt.VolType[i1].Main[i2].Tp[i3].Tr[i4].R, _ = adjustCellName(cell, dir, colNum, rowNum, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i4, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjustVolatileDeps updates the volatile dependencies when inserting or
|
||||||
|
// deleting rows or columns.
|
||||||
|
func (f *File) adjustVolatileDeps(dir adjustDirection, num, offset, sheetID int) error {
|
||||||
|
volTypes, err := f.volatileDepsReader()
|
||||||
|
if err != nil || volTypes == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i1 := 0; i1 < len(volTypes.VolType); i1++ {
|
||||||
|
for i2 := 0; i2 < len(volTypes.VolType[i1].Main); i2++ {
|
||||||
|
for i3 := 0; i3 < len(volTypes.VolType[i1].Main[i2].Tp); i3++ {
|
||||||
|
for i4 := 0; i4 < len(volTypes.VolType[i1].Main[i2].Tp[i3].Tr); i4++ {
|
||||||
|
ref := volTypes.VolType[i1].Main[i2].Tp[i3].Tr[i4]
|
||||||
|
if ref.S != sheetID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i4, err = volTypes.adjustVolatileDepsTopic(ref.R, dir, []int{num, offset, i1, i2, i3, i4}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -927,3 +927,23 @@ func TestAdjustFormula(t *testing.T) {
|
||||||
assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
|
assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAdjustVolatileDeps(t *testing.T) {
|
||||||
|
f := NewFile()
|
||||||
|
f.Pkg.Store(defaultXMLPathVolatileDeps, []byte(fmt.Sprintf(`<volTypes xmlns="%s"><volType><main><tp><tr r="C2" s="2"/><tr r="C2" s="1"/><tr r="D3" s="1"/></tp></main></volType></volTypes>`, NameSpaceSpreadSheet.Value)))
|
||||||
|
assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
|
||||||
|
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||||
|
assert.Equal(t, "D3", f.VolatileDeps.VolType[0].Main[0].Tp[0].Tr[1].R)
|
||||||
|
assert.NoError(t, f.RemoveCol("Sheet1", "D"))
|
||||||
|
assert.NoError(t, f.RemoveRow("Sheet1", 4))
|
||||||
|
assert.Len(t, f.VolatileDeps.VolType[0].Main[0].Tp[0].Tr, 1)
|
||||||
|
|
||||||
|
f = NewFile()
|
||||||
|
f.Pkg.Store(defaultXMLPathVolatileDeps, MacintoshCyrillicCharset)
|
||||||
|
assert.EqualError(t, f.InsertRows("Sheet1", 2, 1), "XML syntax error on line 1: invalid UTF-8")
|
||||||
|
|
||||||
|
f = NewFile()
|
||||||
|
f.Pkg.Store(defaultXMLPathVolatileDeps, []byte(fmt.Sprintf(`<volTypes xmlns="%s"><volType><main><tp><tr r="A" s="1"/></tp></main></volType></volTypes>`, NameSpaceSpreadSheet.Value)))
|
||||||
|
assert.Equal(t, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")), f.InsertCols("Sheet1", "A", 1))
|
||||||
|
f.volatileDepsWriter()
|
||||||
|
}
|
||||||
|
|
36
calcchain.go
36
calcchain.go
|
@ -81,3 +81,39 @@ func (c xlsxCalcChainCollection) Filter(fn func(v xlsxCalcChainC) bool) []xlsxCa
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// volatileDepsReader provides a function to get the pointer to the structure
|
||||||
|
// after deserialization of xl/volatileDependencies.xml.
|
||||||
|
func (f *File) volatileDepsReader() (*xlsxVolTypes, error) {
|
||||||
|
if f.VolatileDeps == nil {
|
||||||
|
volatileDeps, ok := f.Pkg.Load(defaultXMLPathVolatileDeps)
|
||||||
|
if !ok {
|
||||||
|
return f.VolatileDeps, nil
|
||||||
|
}
|
||||||
|
f.VolatileDeps = new(xlsxVolTypes)
|
||||||
|
if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(volatileDeps.([]byte)))).
|
||||||
|
Decode(f.VolatileDeps); err != nil && err != io.EOF {
|
||||||
|
return f.VolatileDeps, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f.VolatileDeps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// volatileDepsWriter provides a function to save xl/volatileDependencies.xml
|
||||||
|
// after serialize structure.
|
||||||
|
func (f *File) volatileDepsWriter() {
|
||||||
|
if f.VolatileDeps != nil {
|
||||||
|
output, _ := xml.Marshal(f.VolatileDeps)
|
||||||
|
f.saveFileList(defaultXMLPathVolatileDeps, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteVolTopicRef provides a function to remove cell reference on the
|
||||||
|
// volatile dependencies topic.
|
||||||
|
func (vt *xlsxVolTypes) deleteVolTopicRef(i1, i2, i3, i4 int) {
|
||||||
|
for i := range vt.VolType[i1].Main[i2].Tp[i3].Tr {
|
||||||
|
if i == i4 {
|
||||||
|
vt.VolType[i1].Main[i2].Tp[i3].Tr = append(vt.VolType[i1].Main[i2].Tp[i3].Tr[:i], vt.VolType[i1].Main[i2].Tp[i3].Tr[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
excelize.go
19
excelize.go
|
@ -29,31 +29,32 @@ import (
|
||||||
// File define a populated spreadsheet file struct.
|
// File define a populated spreadsheet file struct.
|
||||||
type File struct {
|
type File struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
options *Options
|
|
||||||
xmlAttr sync.Map
|
|
||||||
checked sync.Map
|
checked sync.Map
|
||||||
|
options *Options
|
||||||
|
sharedStringItem [][]uint
|
||||||
|
sharedStringsMap map[string]int
|
||||||
|
sharedStringTemp *os.File
|
||||||
sheetMap map[string]string
|
sheetMap map[string]string
|
||||||
streams map[string]*StreamWriter
|
streams map[string]*StreamWriter
|
||||||
tempFiles sync.Map
|
tempFiles sync.Map
|
||||||
sharedStringsMap map[string]int
|
xmlAttr sync.Map
|
||||||
sharedStringItem [][]uint
|
|
||||||
sharedStringTemp *os.File
|
|
||||||
CalcChain *xlsxCalcChain
|
CalcChain *xlsxCalcChain
|
||||||
|
CharsetReader charsetTranscoderFn
|
||||||
Comments map[string]*xlsxComments
|
Comments map[string]*xlsxComments
|
||||||
ContentTypes *xlsxTypes
|
ContentTypes *xlsxTypes
|
||||||
|
DecodeVMLDrawing map[string]*decodeVmlDrawing
|
||||||
Drawings sync.Map
|
Drawings sync.Map
|
||||||
Path string
|
Path string
|
||||||
|
Pkg sync.Map
|
||||||
|
Relationships sync.Map
|
||||||
SharedStrings *xlsxSST
|
SharedStrings *xlsxSST
|
||||||
Sheet sync.Map
|
Sheet sync.Map
|
||||||
SheetCount int
|
SheetCount int
|
||||||
Styles *xlsxStyleSheet
|
Styles *xlsxStyleSheet
|
||||||
Theme *decodeTheme
|
Theme *decodeTheme
|
||||||
DecodeVMLDrawing map[string]*decodeVmlDrawing
|
|
||||||
VMLDrawing map[string]*vmlDrawing
|
VMLDrawing map[string]*vmlDrawing
|
||||||
|
VolatileDeps *xlsxVolTypes
|
||||||
WorkBook *xlsxWorkbook
|
WorkBook *xlsxWorkbook
|
||||||
Relationships sync.Map
|
|
||||||
Pkg sync.Map
|
|
||||||
CharsetReader charsetTranscoderFn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// charsetTranscoderFn set user-defined codepage transcoder function for open
|
// charsetTranscoderFn set user-defined codepage transcoder function for open
|
||||||
|
|
1
file.go
1
file.go
|
@ -176,6 +176,7 @@ func (f *File) writeToZip(zw *zip.Writer) error {
|
||||||
f.commentsWriter()
|
f.commentsWriter()
|
||||||
f.contentTypesWriter()
|
f.contentTypesWriter()
|
||||||
f.drawingsWriter()
|
f.drawingsWriter()
|
||||||
|
f.volatileDepsWriter()
|
||||||
f.vmlDrawingWriter()
|
f.vmlDrawingWriter()
|
||||||
f.workBookWriter()
|
f.workBookWriter()
|
||||||
f.workSheetWriter()
|
f.workSheetWriter()
|
||||||
|
|
2
table.go
2
table.go
|
@ -292,7 +292,7 @@ func (f *File) setTableColumns(sheet string, showHeaderRow bool, x1, y1, x2 int,
|
||||||
}
|
}
|
||||||
header = append(header, name)
|
header = append(header, name)
|
||||||
if column := getTableColumn(name); column != nil {
|
if column := getTableColumn(name); column != nil {
|
||||||
column.ID, column.DataDxfID = idx, 0
|
column.ID, column.DataDxfID, column.QueryTableFieldID = idx, 0, 0
|
||||||
tableColumns = append(tableColumns, column)
|
tableColumns = append(tableColumns, column)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,16 +218,17 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
defaultTempFileSST = "sharedStrings"
|
||||||
|
defaultXMLPathCalcChain = "xl/calcChain.xml"
|
||||||
defaultXMLPathContentTypes = "[Content_Types].xml"
|
defaultXMLPathContentTypes = "[Content_Types].xml"
|
||||||
defaultXMLPathDocPropsApp = "docProps/app.xml"
|
defaultXMLPathDocPropsApp = "docProps/app.xml"
|
||||||
defaultXMLPathDocPropsCore = "docProps/core.xml"
|
defaultXMLPathDocPropsCore = "docProps/core.xml"
|
||||||
defaultXMLPathCalcChain = "xl/calcChain.xml"
|
|
||||||
defaultXMLPathSharedStrings = "xl/sharedStrings.xml"
|
defaultXMLPathSharedStrings = "xl/sharedStrings.xml"
|
||||||
defaultXMLPathStyles = "xl/styles.xml"
|
defaultXMLPathStyles = "xl/styles.xml"
|
||||||
defaultXMLPathTheme = "xl/theme/theme1.xml"
|
defaultXMLPathTheme = "xl/theme/theme1.xml"
|
||||||
|
defaultXMLPathVolatileDeps = "xl/volatileDependencies.xml"
|
||||||
defaultXMLPathWorkbook = "xl/workbook.xml"
|
defaultXMLPathWorkbook = "xl/workbook.xml"
|
||||||
defaultXMLPathWorkbookRels = "xl/_rels/workbook.xml.rels"
|
defaultXMLPathWorkbookRels = "xl/_rels/workbook.xml.rels"
|
||||||
defaultTempFileSST = "sharedStrings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IndexedColorMapping is the table of default mappings from indexed color value
|
// IndexedColorMapping is the table of default mappings from indexed color value
|
||||||
|
|
|
@ -11,10 +11,15 @@
|
||||||
|
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
import "encoding/xml"
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
// xlsxCalcChain directly maps the calcChain element. This element represents the root of the calculation chain.
|
// xlsxCalcChain directly maps the calcChain element. This element represents
|
||||||
|
// the root of the calculation chain.
|
||||||
type xlsxCalcChain struct {
|
type xlsxCalcChain struct {
|
||||||
|
mu sync.Mutex
|
||||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main calcChain"`
|
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main calcChain"`
|
||||||
C []xlsxCalcChainC `xml:"c"`
|
C []xlsxCalcChainC `xml:"c"`
|
||||||
}
|
}
|
||||||
|
@ -82,3 +87,43 @@ type xlsxCalcChainC struct {
|
||||||
T bool `xml:"t,attr,omitempty"`
|
T bool `xml:"t,attr,omitempty"`
|
||||||
A bool `xml:"a,attr,omitempty"`
|
A bool `xml:"a,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xlsxVolTypes maps the volatileDependencies part provides a cache of data that
|
||||||
|
// supports Real Time Data (RTD) and CUBE functions in the workbook.
|
||||||
|
type xlsxVolTypes struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main volTypes"`
|
||||||
|
VolType []xlsxVolType `xml:"volType"`
|
||||||
|
ExtLst *xlsxExtLst `xml:"extLst"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxVolType represents dependency information for a specific type of external
|
||||||
|
// data server.
|
||||||
|
type xlsxVolType struct {
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
Main []xlsxVolMain `xml:"main"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxVolMain represents dependency information for all topics within a
|
||||||
|
// volatile dependency type that share the same first string or function
|
||||||
|
// argument.
|
||||||
|
type xlsxVolMain struct {
|
||||||
|
First string `xml:"first,attr"`
|
||||||
|
Tp []xlsxVolTopic `xml:"tp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxVolTopic represents dependency information for all topics within a
|
||||||
|
// volatile dependency type that share the same first string or argument.
|
||||||
|
type xlsxVolTopic struct {
|
||||||
|
T string `xml:"t,attr,omitempty"`
|
||||||
|
V string `xml:"v"`
|
||||||
|
Stp []string `xml:"stp"`
|
||||||
|
Tr []xlsxVolTopicRef `xml:"tr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxVolTopicRef represents the reference to a cell that depends on this
|
||||||
|
// topic. Each topic can have one or more cells dependencies.
|
||||||
|
type xlsxVolTopicRef struct {
|
||||||
|
R string `xml:"r,attr"`
|
||||||
|
S int `xml:"s,attr"`
|
||||||
|
}
|
||||||
|
|
|
@ -37,12 +37,12 @@ type xlsxTable struct {
|
||||||
DataDxfID int `xml:"dataDxfId,attr,omitempty"`
|
DataDxfID int `xml:"dataDxfId,attr,omitempty"`
|
||||||
TotalsRowDxfID int `xml:"totalsRowDxfId,attr,omitempty"`
|
TotalsRowDxfID int `xml:"totalsRowDxfId,attr,omitempty"`
|
||||||
HeaderRowBorderDxfID int `xml:"headerRowBorderDxfId,attr,omitempty"`
|
HeaderRowBorderDxfID int `xml:"headerRowBorderDxfId,attr,omitempty"`
|
||||||
TableBorderDxfId int `xml:"tableBorderDxfId,attr,omitempty"`
|
TableBorderDxfID int `xml:"tableBorderDxfId,attr,omitempty"`
|
||||||
TotalsRowBorderDxfId int `xml:"totalsRowBorderDxfId,attr,omitempty"`
|
TotalsRowBorderDxfID int `xml:"totalsRowBorderDxfId,attr,omitempty"`
|
||||||
HeaderRowCellStyle string `xml:"headerRowCellStyle,attr,omitempty"`
|
HeaderRowCellStyle string `xml:"headerRowCellStyle,attr,omitempty"`
|
||||||
DataCellStyle string `xml:"dataCellStyle,attr,omitempty"`
|
DataCellStyle string `xml:"dataCellStyle,attr,omitempty"`
|
||||||
TotalsRowCellStyle string `xml:"totalsRowCellStyle,attr,omitempty"`
|
TotalsRowCellStyle string `xml:"totalsRowCellStyle,attr,omitempty"`
|
||||||
ConnectionId int `xml:"connectionId,attr,omitempty"`
|
ConnectionID int `xml:"connectionId,attr,omitempty"`
|
||||||
AutoFilter *xlsxAutoFilter `xml:"autoFilter"`
|
AutoFilter *xlsxAutoFilter `xml:"autoFilter"`
|
||||||
TableColumns *xlsxTableColumns `xml:"tableColumns"`
|
TableColumns *xlsxTableColumns `xml:"tableColumns"`
|
||||||
TableStyleInfo *xlsxTableStyleInfo `xml:"tableStyleInfo"`
|
TableStyleInfo *xlsxTableStyleInfo `xml:"tableStyleInfo"`
|
||||||
|
|
Loading…
Reference in New Issue