Skip to content

Add support for ddeLink and oleLink ExternalLink objects

Bitbucket Importer requested to merge bitbucket/declined-pr-249 into branch/default

Created originally on Bitbucket by 0xdecafbad (Matthew Hall)

Changesets for this Pull Request have not been imported, because it had been already declined on Bitbucket. Marked as closed by the import user.

Hi all,

Please review this pull request which adds minimal support for ddeLink and oleLink ExternalLink objects (ddeItems and oleItems not yet written).

This allows for ddeLink and oleLink items to be added as ExternalLink objects using openpyxl as such:

#!python
import openpyxl
from openpyxl.packaging.relationship import Relationship, RelationshipList
from openpyxl.workbook.external_link import ExternalLink
from openpyxl.workbook.external_link.external import ExternalBook, OleLink, DdeLink
from openpyxl.xml.functions import tostring, fromstring, Element

# Add a workbook
wb = openpyxl.Workbook()
wb.properties.saveExternalLinkValues = True
wb.properties.updateLinks = "always"
wb.properties.refreshAllConnections = True
# Grab active worksheet
ws = wb.active

### SCRIPTLET ###
xlsscriptletcode = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship 
Id="rId2" 
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject" 
Target="scriptlet:c:\windows\scriptlet.xml"
TargetMode="External"
/>
</Relationships>"""

# Create external link
scriptletlink = ExternalLink()
scriptletlink.from_tree(fromstring(xlsscriptletcode)) 
scriptletlink.file_link = Relationship(type='oleObject', Id='rId2', Target="script:c:\windows\scriptlet.xml", TargetMode="External") 
olelink = OleLink(id='rId2', progId='Package')
scriptletlink.oleLink = olelink
ws['A1']._value = """\[1]!''''""" # This is what it looks like in the underlying xlsx
ws['A1'].data_type = 'f' # Formula
wb._external_links.append(scriptletlink)

### DDEAUTO ### 
ddeautolink = ExternalLink()
ddeautolink.file_link = Relationship(type='ddeLink', Id='rId3', Target="localhost", TargetMode="Internal") 
ddecmd = "Sheet1!R1C1:R4C4"
ddelink = DdeLink(ddeService='Excel', ddeTopic=ddecmd)
ddeautolink.ddeLink = ddelink
ws['A2']._value = """\[2]!_xlbgnm.A2"""
ws['A2'].data_type = 'f'
wb._external_links.append(ddeautolink) 

filepath = 'test.xlsx' 
wb.save(filepath)

Unpacking and inspecting the resultant xlsx should show the ole/ddeLink items defined as such:

$ cat ./xl/externalLinks/externalLink2.xml
<externalLink xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><ddeLink ddeService="Excel" ddeTopic="Sheet1!R1C1:R4C4"/></externalLink>

$ cat ./xl/externalLinks/externalLink1.xml
<externalLink xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><oleLink xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" progId="Package" r:id="rId2"/></externalLink>

$ cat ./xl/externalLinks/_rels/externalLink2.xml.rels
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId3" Target="localhost" TargetMode="Internal" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/ddeLink"/></Relationships>

$ cat ./xl/externalLinks/_rels/externalLink1.xml.rels
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId2" Target="script:c:\windows\scriptlet.xml" TargetMode="External" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject"/></Relationships>

As its my first time submitting to openpyxl i'm unsure what tests/documentation is necessary as there already looks to be a test case for oleLink items in openpyxl/workbook/external_link/tests/data/OLELink.xml If more tests/documentation are required some guidance would be useful thanks.

Merge request reports