calcchain.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
  2. // this source code is governed by a BSD-style license that can be found in
  3. // the LICENSE file.
  4. //
  5. // Package excelize providing a set of functions that allow you to write to and
  6. // read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
  7. // writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
  8. // Supports complex components by high compatibility, and provided streaming
  9. // API for generating or reading data from a worksheet with huge amounts of
  10. // data. This library needs Go version 1.16 or later.
  11. package excelize
  12. import (
  13. "bytes"
  14. "encoding/xml"
  15. "io"
  16. )
  17. // calcChainReader provides a function to get the pointer to the structure
  18. // after deserialization of xl/calcChain.xml.
  19. func (f *File) calcChainReader() (*xlsxCalcChain, error) {
  20. if f.CalcChain == nil {
  21. f.CalcChain = new(xlsxCalcChain)
  22. if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathCalcChain)))).
  23. Decode(f.CalcChain); err != nil && err != io.EOF {
  24. return f.CalcChain, err
  25. }
  26. }
  27. return f.CalcChain, nil
  28. }
  29. // calcChainWriter provides a function to save xl/calcChain.xml after
  30. // serialize structure.
  31. func (f *File) calcChainWriter() {
  32. if f.CalcChain != nil && f.CalcChain.C != nil {
  33. output, _ := xml.Marshal(f.CalcChain)
  34. f.saveFileList(defaultXMLPathCalcChain, output)
  35. }
  36. }
  37. // deleteCalcChain provides a function to remove cell reference on the
  38. // calculation chain.
  39. func (f *File) deleteCalcChain(index int, cell string) error {
  40. calc, err := f.calcChainReader()
  41. if err != nil {
  42. return err
  43. }
  44. if calc != nil {
  45. calc.C = xlsxCalcChainCollection(calc.C).Filter(func(c xlsxCalcChainC) bool {
  46. return !((c.I == index && c.R == cell) || (c.I == index && cell == "") || (c.I == 0 && c.R == cell))
  47. })
  48. }
  49. if len(calc.C) == 0 {
  50. f.CalcChain = nil
  51. f.Pkg.Delete(defaultXMLPathCalcChain)
  52. content, err := f.contentTypesReader()
  53. if err != nil {
  54. return err
  55. }
  56. content.Lock()
  57. defer content.Unlock()
  58. for k, v := range content.Overrides {
  59. if v.PartName == "/xl/calcChain.xml" {
  60. content.Overrides = append(content.Overrides[:k], content.Overrides[k+1:]...)
  61. }
  62. }
  63. }
  64. return err
  65. }
  66. type xlsxCalcChainCollection []xlsxCalcChainC
  67. // Filter provides a function to filter calculation chain.
  68. func (c xlsxCalcChainCollection) Filter(fn func(v xlsxCalcChainC) bool) []xlsxCalcChainC {
  69. var results []xlsxCalcChainC
  70. for _, v := range c {
  71. if fn(v) {
  72. results = append(results, v)
  73. }
  74. }
  75. return results
  76. }