external.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. from __future__ import absolute_import
  2. # Copyright (c) 2010-2019 openpyxl
  3. from openpyxl.compat import unicode
  4. from openpyxl.descriptors.serialisable import Serialisable
  5. from openpyxl.descriptors import (
  6. Typed,
  7. String,
  8. Bool,
  9. Integer,
  10. NoneSet,
  11. Sequence,
  12. )
  13. from openpyxl.descriptors.excel import Relation, ExtensionList
  14. from openpyxl.descriptors.nested import NestedText
  15. from openpyxl.descriptors.sequence import NestedSequence, ValueSequence
  16. from openpyxl.packaging.relationship import (
  17. Relationship,
  18. get_rels_path,
  19. get_dependents
  20. )
  21. from openpyxl.xml.constants import SHEET_MAIN_NS
  22. from openpyxl.xml.functions import fromstring
  23. """Manage links to external Workbooks"""
  24. class ExternalCell(Serialisable):
  25. r = String()
  26. t = NoneSet(values=(['b', 'd', 'n', 'e', 's', 'str', 'inlineStr']))
  27. vm = Integer(allow_none=True)
  28. v = NestedText(allow_none=True, expected_type=unicode)
  29. def __init__(self,
  30. r=None,
  31. t=None,
  32. vm=None,
  33. v=None,
  34. ):
  35. self.r = r
  36. self.t = t
  37. self.vm = vm
  38. self.v = v
  39. class ExternalRow(Serialisable):
  40. r = Integer()
  41. cell = Sequence(expected_type=ExternalCell)
  42. __elements__ = ('cell',)
  43. def __init__(self,
  44. r=(),
  45. cell=None,
  46. ):
  47. self.r = r
  48. self.cell = cell
  49. class ExternalSheetData(Serialisable):
  50. sheetId = Integer()
  51. refreshError = Bool(allow_none=True)
  52. row = Sequence(expected_type=ExternalRow)
  53. __elements__ = ('row',)
  54. def __init__(self,
  55. sheetId=None,
  56. refreshError=None,
  57. row=(),
  58. ):
  59. self.sheetId = sheetId
  60. self.refreshError = refreshError
  61. self.row = row
  62. class ExternalSheetDataSet(Serialisable):
  63. sheetData = Sequence(expected_type=ExternalSheetData, )
  64. __elements__ = ('sheetData',)
  65. def __init__(self,
  66. sheetData=None,
  67. ):
  68. self.sheetData = sheetData
  69. class ExternalSheetNames(Serialisable):
  70. sheetName = ValueSequence(expected_type=unicode)
  71. __elements__ = ('sheetName',)
  72. def __init__(self,
  73. sheetName=(),
  74. ):
  75. self.sheetName = sheetName
  76. class ExternalDefinedName(Serialisable):
  77. tagname = "definedName"
  78. name = String()
  79. refersTo = String(allow_none=True)
  80. sheetId = Integer(allow_none=True)
  81. def __init__(self,
  82. name=None,
  83. refersTo=None,
  84. sheetId=None,
  85. ):
  86. self.name = name
  87. self.refersTo = refersTo
  88. self.sheetId = sheetId
  89. class ExternalBook(Serialisable):
  90. tagname = "externalBook"
  91. sheetNames = Typed(expected_type=ExternalSheetNames, allow_none=True)
  92. definedNames = NestedSequence(expected_type=ExternalDefinedName)
  93. sheetDataSet = Typed(expected_type=ExternalSheetDataSet, allow_none=True)
  94. id = Relation()
  95. __elements__ = ('sheetNames', 'definedNames', 'sheetDataSet')
  96. def __init__(self,
  97. sheetNames=None,
  98. definedNames=(),
  99. sheetDataSet=None,
  100. id=None,
  101. ):
  102. self.sheetNames = sheetNames
  103. self.definedNames = definedNames
  104. self.sheetDataSet = sheetDataSet
  105. self.id = id
  106. class ExternalLink(Serialisable):
  107. tagname = "externalLink"
  108. _id = None
  109. _path = "/xl/externalLinks/externalLink{0}.xml"
  110. _rel_type = "externalLink"
  111. mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml"
  112. externalBook = Typed(expected_type=ExternalBook, allow_none=True)
  113. file_link = Typed(expected_type=Relationship, allow_none=True) # link to external file
  114. __elements__ = ('externalBook', )
  115. def __init__(self,
  116. externalBook=None,
  117. ddeLink=None,
  118. oleLink=None,
  119. extLst=None,
  120. ):
  121. self.externalBook = externalBook
  122. # ignore other items for the moment.
  123. def to_tree(self):
  124. node = super(ExternalLink, self).to_tree()
  125. node.set("xmlns", SHEET_MAIN_NS)
  126. return node
  127. @property
  128. def path(self):
  129. return self._path.format(self._id)
  130. def read_external_link(archive, book_path):
  131. src = archive.read(book_path)
  132. node = fromstring(src)
  133. book = ExternalLink.from_tree(node)
  134. link_path = get_rels_path(book_path)
  135. deps = get_dependents(archive, link_path)
  136. book.file_link = deps.Relationship[0]
  137. return book