# Copyright (c) 2010-2024 openpyxl
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.descriptors import (
Typed,
String,
Bool,
Integer,
NoneSet,
Sequence,
)
from openpyxl.descriptors.excel import Relation
from openpyxl.descriptors.nested import NestedText
from openpyxl.descriptors.sequence import NestedSequence, ValueSequence
from openpyxl.packaging.relationship import (
Relationship,
get_rels_path,
get_dependents
)
from openpyxl.xml.constants import SHEET_MAIN_NS
from openpyxl.xml.functions import fromstring
"""Manage links to external Workbooks"""
[docs]
class ExternalCell(Serialisable):
r = String()
t = NoneSet(values=(['b', 'd', 'n', 'e', 's', 'str', 'inlineStr']))
vm = Integer(allow_none=True)
v = NestedText(allow_none=True, expected_type=str)
def __init__(self,
r=None,
t=None,
vm=None,
v=None,
):
self.r = r
self.t = t
self.vm = vm
self.v = v
[docs]
class ExternalRow(Serialisable):
r = Integer()
cell = Sequence(expected_type=ExternalCell)
__elements__ = ('cell',)
def __init__(self,
r=(),
cell=None,
):
self.r = r
self.cell = cell
[docs]
class ExternalSheetData(Serialisable):
sheetId = Integer()
refreshError = Bool(allow_none=True)
row = Sequence(expected_type=ExternalRow)
__elements__ = ('row',)
def __init__(self,
sheetId=None,
refreshError=None,
row=(),
):
self.sheetId = sheetId
self.refreshError = refreshError
self.row = row
[docs]
class ExternalSheetDataSet(Serialisable):
sheetData = Sequence(expected_type=ExternalSheetData, )
__elements__ = ('sheetData',)
def __init__(self,
sheetData=None,
):
self.sheetData = sheetData
[docs]
class ExternalSheetNames(Serialisable):
sheetName = ValueSequence(expected_type=str)
__elements__ = ('sheetName',)
def __init__(self,
sheetName=(),
):
self.sheetName = sheetName
[docs]
class ExternalDefinedName(Serialisable):
tagname = "definedName"
name = String()
refersTo = String(allow_none=True)
sheetId = Integer(allow_none=True)
def __init__(self,
name=None,
refersTo=None,
sheetId=None,
):
self.name = name
self.refersTo = refersTo
self.sheetId = sheetId
[docs]
class ExternalBook(Serialisable):
tagname = "externalBook"
sheetNames = Typed(expected_type=ExternalSheetNames, allow_none=True)
definedNames = NestedSequence(expected_type=ExternalDefinedName)
sheetDataSet = Typed(expected_type=ExternalSheetDataSet, allow_none=True)
id = Relation()
__elements__ = ('sheetNames', 'definedNames', 'sheetDataSet')
def __init__(self,
sheetNames=None,
definedNames=(),
sheetDataSet=None,
id=None,
):
self.sheetNames = sheetNames
self.definedNames = definedNames
self.sheetDataSet = sheetDataSet
self.id = id
[docs]
class ExternalLink(Serialisable):
tagname = "externalLink"
_id = None
_path = "/xl/externalLinks/externalLink{0}.xml"
_rel_type = "externalLink"
mime_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml"
externalBook = Typed(expected_type=ExternalBook, allow_none=True)
file_link = Typed(expected_type=Relationship, allow_none=True) # link to external file
__elements__ = ('externalBook', )
def __init__(self,
externalBook=None,
ddeLink=None,
oleLink=None,
extLst=None,
):
self.externalBook = externalBook
# ignore other items for the moment.
[docs]
def to_tree(self):
node = super().to_tree()
node.set("xmlns", SHEET_MAIN_NS)
return node
@property
def path(self):
return self._path.format(self._id)
[docs]
def read_external_link(archive, book_path):
src = archive.read(book_path)
node = fromstring(src)
book = ExternalLink.from_tree(node)
link_path = get_rels_path(book_path)
deps = get_dependents(archive, link_path)
book.file_link = deps[0]
return book