@@ -157,20 +157,18 @@ func (f *File) AddPivotTable(opts *PivotTableOptions) error {
157
157
sheetRelationshipsPivotTableXML := "../pivotTables/pivotTable" + strconv .Itoa (pivotTableID ) + ".xml"
158
158
pivotTableXML := strings .ReplaceAll (sheetRelationshipsPivotTableXML , ".." , "xl" )
159
159
pivotCacheXML := "xl/pivotCache/pivotCacheDefinition" + strconv .Itoa (pivotCacheID ) + ".xml"
160
- err = f .addPivotCache (pivotCacheXML , opts )
161
- if err != nil {
160
+ if err = f .addPivotCache (pivotCacheXML , opts ); err != nil {
162
161
return err
163
162
}
164
163
165
164
// workbook pivot cache
166
- workBookPivotCacheRID := f .addRels (f .getWorkbookRelsPath (), SourceRelationshipPivotCache , fmt . Sprintf ( "/ xl/pivotCache/pivotCacheDefinition%d.xml" , pivotCacheID ), "" )
165
+ workBookPivotCacheRID := f .addRels (f .getWorkbookRelsPath (), SourceRelationshipPivotCache , strings . TrimPrefix ( pivotCacheXML , " xl/" ), "" )
167
166
cacheID := f .addWorkbookPivotCache (workBookPivotCacheRID )
168
167
169
168
pivotCacheRels := "xl/pivotTables/_rels/pivotTable" + strconv .Itoa (pivotTableID ) + ".xml.rels"
170
169
// rId not used
171
170
_ = f .addRels (pivotCacheRels , SourceRelationshipPivotCache , fmt .Sprintf ("../pivotCache/pivotCacheDefinition%d.xml" , pivotCacheID ), "" )
172
- err = f .addPivotTable (cacheID , pivotTableID , pivotTableXML , opts )
173
- if err != nil {
171
+ if err = f .addPivotTable (cacheID , pivotTableID , pivotTableXML , opts ); err != nil {
174
172
return err
175
173
}
176
174
pivotTableSheetRels := "xl/worksheets/_rels/" + strings .TrimPrefix (pivotTableSheetPath , "xl/worksheets/" ) + ".rels"
@@ -195,11 +193,14 @@ func (f *File) parseFormatPivotTableSet(opts *PivotTableOptions) (*xlsxWorksheet
195
193
return nil , "" , ErrNameLength
196
194
}
197
195
opts .pivotTableSheetName = pivotTableSheetName
198
- dataRange := f .getDefinedNameRefTo ( opts .DataRange , pivotTableSheetName )
199
- if dataRange == "" {
200
- dataRange = opts . DataRange
196
+ _ , dataRangeRef , err := f .getPivotTableDataRange ( pivotTableSheetName , opts .DataRange , opts . DataRange )
197
+ if err != nil {
198
+ return nil , "" , err
201
199
}
202
- dataSheetName , _ , err := f .adjustRange (dataRange )
200
+ if dataRangeRef == "" {
201
+ dataRangeRef = opts .DataRange
202
+ }
203
+ dataSheetName , _ , err := f .adjustRange (dataRangeRef )
203
204
if err != nil {
204
205
return nil , "" , newPivotTableDataRangeError (err .Error ())
205
206
}
@@ -248,11 +249,17 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
248
249
// fields.
249
250
func (f * File ) getTableFieldsOrder (sheetName , dataRange string ) ([]string , error ) {
250
251
var order []string
251
- ref := f .getDefinedNameRefTo (dataRange , sheetName )
252
- if ref == "" {
253
- ref = dataRange
252
+ if dataRange == "" {
253
+ return order , newPivotTableDataRangeError (ErrParameterRequired .Error ())
254
254
}
255
- dataSheet , coordinates , err := f .adjustRange (ref )
255
+ _ , dataRangeRef , err := f .getPivotTableDataRange (sheetName , dataRange , dataRange )
256
+ if err != nil {
257
+ return order , err
258
+ }
259
+ if dataRangeRef == "" {
260
+ dataRangeRef = dataRange
261
+ }
262
+ dataSheet , coordinates , err := f .adjustRange (dataRangeRef )
256
263
if err != nil {
257
264
return order , newPivotTableDataRangeError (err .Error ())
258
265
}
@@ -271,17 +278,20 @@ func (f *File) getTableFieldsOrder(sheetName, dataRange string) ([]string, error
271
278
func (f * File ) addPivotCache (pivotCacheXML string , opts * PivotTableOptions ) error {
272
279
// validate data range
273
280
definedNameRef := true
274
- dataRange := f .getDefinedNameRefTo (opts .DataRange , opts .pivotTableSheetName )
275
- if dataRange == "" {
281
+ _ , dataRangeRef , err := f .getPivotTableDataRange (opts .pivotTableSheetName , opts .DataRange , opts .DataRange )
282
+ if err != nil {
283
+ return err
284
+ }
285
+ if dataRangeRef == "" {
276
286
definedNameRef = false
277
- dataRange = opts .DataRange
287
+ dataRangeRef = opts .DataRange
278
288
}
279
- dataSheet , coordinates , err := f .adjustRange (dataRange )
289
+ dataSheet , coordinates , err := f .adjustRange (dataRangeRef )
280
290
if err != nil {
281
291
return newPivotTableDataRangeError (err .Error ())
282
292
}
283
293
// data range has been checked
284
- order , _ := f .getTableFieldsOrder (opts .pivotTableSheetName , opts . DataRange )
294
+ order , _ := f .getTableFieldsOrder (opts .pivotTableSheetName , dataRangeRef )
285
295
hCell , _ := CoordinatesToCellName (coordinates [0 ], coordinates [1 ])
286
296
vCell , _ := CoordinatesToCellName (coordinates [2 ], coordinates [3 ])
287
297
pc := xlsxPivotCacheDefinition {
@@ -751,6 +761,32 @@ func (f *File) GetPivotTables(sheet string) ([]PivotTableOptions, error) {
751
761
return pivotTables , nil
752
762
}
753
763
764
+ // getPivotTableDataRange returns pivot table data range name and reference from
765
+ // cell reference, table name or defined name.
766
+ func (f * File ) getPivotTableDataRange (sheet , ref , name string ) (string , string , error ) {
767
+ dataRange := fmt .Sprintf ("%s!%s" , sheet , ref )
768
+ dataRangeRef , isTable := dataRange , false
769
+ if name != "" {
770
+ dataRange = name
771
+ for _ , sheetName := range f .GetSheetList () {
772
+ tables , err := f .GetTables (sheetName )
773
+ e := ErrSheetNotExist {sheetName }
774
+ if err != nil && err .Error () != newNotWorksheetError (sheetName ).Error () && err .Error () != e .Error () {
775
+ return dataRange , dataRangeRef , err
776
+ }
777
+ for _ , table := range tables {
778
+ if table .Name == name {
779
+ dataRangeRef , isTable = fmt .Sprintf ("%s!%s" , sheetName , table .Range ), true
780
+ }
781
+ }
782
+ }
783
+ if ! isTable {
784
+ dataRangeRef = f .getDefinedNameRefTo (name , sheet )
785
+ }
786
+ }
787
+ return dataRange , dataRangeRef , nil
788
+ }
789
+
754
790
// getPivotTable provides a function to get a pivot table definition by given
755
791
// worksheet name, pivot table XML path and pivot cache relationship XML path.
756
792
func (f * File ) getPivotTable (sheet , pivotTableXML , pivotCacheRels string ) (PivotTableOptions , error ) {
@@ -774,7 +810,10 @@ func (f *File) getPivotTable(sheet, pivotTableXML, pivotCacheRels string) (Pivot
774
810
if err != nil {
775
811
return opts , err
776
812
}
777
- dataRange := fmt .Sprintf ("%s!%s" , pc .CacheSource .WorksheetSource .Sheet , pc .CacheSource .WorksheetSource .Ref )
813
+ dataRange , dataRangeRef , err := f .getPivotTableDataRange (sheet , pc .CacheSource .WorksheetSource .Ref , pc .CacheSource .WorksheetSource .Name )
814
+ if err != nil {
815
+ return opts , err
816
+ }
778
817
opts = PivotTableOptions {
779
818
pivotTableXML : pivotTableXML ,
780
819
pivotCacheXML : pivotCacheXML ,
@@ -799,7 +838,7 @@ func (f *File) getPivotTable(sheet, pivotTableXML, pivotCacheRels string) (Pivot
799
838
opts .ShowLastColumn = si .ShowLastColumn
800
839
opts .PivotTableStyleName = si .Name
801
840
}
802
- order , _ := f .getTableFieldsOrder (pt .Name , dataRange )
841
+ order , err := f .getTableFieldsOrder (pt .Name , dataRangeRef )
803
842
f .extractPivotTableFields (order , pt , & opts )
804
843
return opts , err
805
844
}
@@ -906,3 +945,71 @@ func (f *File) genPivotCacheDefinitionID() int {
906
945
})
907
946
return ID + 1
908
947
}
948
+
949
+ // deleteWorkbookPivotCache remove workbook pivot cache and pivot cache
950
+ // relationships.
951
+ func (f * File ) deleteWorkbookPivotCache (opt PivotTableOptions ) error {
952
+ rID , err := f .deleteWorkbookRels (SourceRelationshipPivotCache , strings .TrimPrefix (strings .TrimPrefix (opt .pivotCacheXML , "/" ), "xl/" ))
953
+ if err != nil {
954
+ return err
955
+ }
956
+ wb , err := f .workbookReader ()
957
+ if err != nil {
958
+ return err
959
+ }
960
+ if wb .PivotCaches != nil {
961
+ for i , pivotCache := range wb .PivotCaches .PivotCache {
962
+ if pivotCache .RID == rID {
963
+ wb .PivotCaches .PivotCache = append (wb .PivotCaches .PivotCache [:i ], wb .PivotCaches .PivotCache [i + 1 :]... )
964
+ }
965
+ }
966
+ if len (wb .PivotCaches .PivotCache ) == 0 {
967
+ wb .PivotCaches = nil
968
+ }
969
+ }
970
+ return err
971
+ }
972
+
973
+ // DeletePivotTable delete a pivot table by giving the worksheet name and pivot
974
+ // table name. Note that this function does not clean cell values in the pivot
975
+ // table range.
976
+ func (f * File ) DeletePivotTable (sheet , name string ) error {
977
+ sheetXML , ok := f .getSheetXMLPath (sheet )
978
+ if ! ok {
979
+ return ErrSheetNotExist {sheet }
980
+ }
981
+ rels := "xl/worksheets/_rels/" + strings .TrimPrefix (sheetXML , "xl/worksheets/" ) + ".rels"
982
+ sheetRels , err := f .relsReader (rels )
983
+ if err != nil {
984
+ return err
985
+ }
986
+ if sheetRels == nil {
987
+ sheetRels = & xlsxRelationships {}
988
+ }
989
+ opts , err := f .GetPivotTables (sheet )
990
+ if err != nil {
991
+ return err
992
+ }
993
+ pivotTableCaches := map [string ]int {}
994
+ for _ , sheetName := range f .GetSheetList () {
995
+ sheetPivotTables , _ := f .GetPivotTables (sheetName )
996
+ for _ , sheetPivotTable := range sheetPivotTables {
997
+ pivotTableCaches [sheetPivotTable .pivotCacheXML ]++
998
+ }
999
+ }
1000
+ for _ , v := range sheetRels .Relationships {
1001
+ for _ , opt := range opts {
1002
+ if v .Type == SourceRelationshipPivotTable {
1003
+ pivotTableXML := strings .ReplaceAll (v .Target , ".." , "xl" )
1004
+ if opt .Name == name && opt .pivotTableXML == pivotTableXML {
1005
+ if pivotTableCaches [opt .pivotCacheXML ] == 1 {
1006
+ err = f .deleteWorkbookPivotCache (opt )
1007
+ }
1008
+ f .deleteSheetRelationships (sheet , v .ID )
1009
+ return err
1010
+ }
1011
+ }
1012
+ }
1013
+ }
1014
+ return newNoExistTableError (name )
1015
+ }
0 commit comments