208 lines
6.9 KiB
Python
208 lines
6.9 KiB
Python
###############################################################################
|
|
#
|
|
# ContentTypes - A class for writing the Excel XLSX ContentTypes file.
|
|
#
|
|
# Copyright 2013-2019, John McNamara, jmcnamara@cpan.org
|
|
#
|
|
|
|
import copy
|
|
from . import xmlwriter
|
|
|
|
# Long namespace strings used in the class.
|
|
app_package = 'application/vnd.openxmlformats-package.'
|
|
app_document = 'application/vnd.openxmlformats-officedocument.'
|
|
|
|
defaults = [
|
|
['rels', app_package + 'relationships+xml'],
|
|
['xml', 'application/xml'],
|
|
]
|
|
|
|
overrides = [
|
|
['/docProps/app.xml', app_document + 'extended-properties+xml'],
|
|
['/docProps/core.xml', app_package + 'core-properties+xml'],
|
|
['/xl/styles.xml', app_document + 'spreadsheetml.styles+xml'],
|
|
['/xl/theme/theme1.xml', app_document + 'theme+xml'],
|
|
['/xl/workbook.xml', app_document + 'spreadsheetml.sheet.main+xml'],
|
|
]
|
|
|
|
|
|
class ContentTypes(xmlwriter.XMLwriter):
|
|
"""
|
|
A class for writing the Excel XLSX ContentTypes file.
|
|
|
|
|
|
"""
|
|
|
|
###########################################################################
|
|
#
|
|
# Public API.
|
|
#
|
|
###########################################################################
|
|
|
|
def __init__(self):
|
|
"""
|
|
Constructor.
|
|
|
|
"""
|
|
|
|
super(ContentTypes, self).__init__()
|
|
|
|
# Copy the defaults in case we need to change them.
|
|
self.defaults = copy.deepcopy(defaults)
|
|
self.overrides = copy.deepcopy(overrides)
|
|
|
|
###########################################################################
|
|
#
|
|
# Private API.
|
|
#
|
|
###########################################################################
|
|
|
|
def _assemble_xml_file(self):
|
|
# Assemble and write the XML file.
|
|
|
|
# Write the XML declaration.
|
|
self._xml_declaration()
|
|
|
|
self._write_types()
|
|
self._write_defaults()
|
|
self._write_overrides()
|
|
|
|
self._xml_end_tag('Types')
|
|
|
|
# Close the file.
|
|
self._xml_close()
|
|
|
|
def _add_default(self, default):
|
|
# Add elements to the ContentTypes defaults.
|
|
self.defaults.append(default)
|
|
|
|
def _add_override(self, override):
|
|
# Add elements to the ContentTypes overrides.
|
|
self.overrides.append(override)
|
|
|
|
def _add_worksheet_name(self, worksheet_name):
|
|
# Add the name of a worksheet to the ContentTypes overrides.
|
|
worksheet_name = "/xl/worksheets/" + worksheet_name + ".xml"
|
|
|
|
self._add_override((worksheet_name,
|
|
app_document + 'spreadsheetml.worksheet+xml'))
|
|
|
|
def _add_chartsheet_name(self, chartsheet_name):
|
|
# Add the name of a chartsheet to the ContentTypes overrides.
|
|
chartsheet_name = "/xl/chartsheets/" + chartsheet_name + ".xml"
|
|
|
|
self._add_override((chartsheet_name,
|
|
app_document + 'spreadsheetml.chartsheet+xml'))
|
|
|
|
def _add_chart_name(self, chart_name):
|
|
# Add the name of a chart to the ContentTypes overrides.
|
|
chart_name = "/xl/charts/" + chart_name + ".xml"
|
|
|
|
self._add_override((chart_name, app_document + 'drawingml.chart+xml'))
|
|
|
|
def _add_drawing_name(self, drawing_name):
|
|
# Add the name of a drawing to the ContentTypes overrides.
|
|
drawing_name = "/xl/drawings/" + drawing_name + ".xml"
|
|
|
|
self._add_override((drawing_name, app_document + 'drawing+xml'))
|
|
|
|
def _add_vml_name(self):
|
|
# Add the name of a VML drawing to the ContentTypes defaults.
|
|
self._add_default(('vml', app_document + 'vmlDrawing'))
|
|
|
|
def _add_comment_name(self, comment_name):
|
|
# Add the name of a comment to the ContentTypes overrides.
|
|
comment_name = "/xl/" + comment_name + ".xml"
|
|
|
|
self._add_override((comment_name,
|
|
app_document + 'spreadsheetml.comments+xml'))
|
|
|
|
def _add_shared_strings(self):
|
|
# Add the sharedStrings link to the ContentTypes overrides.
|
|
self._add_override(('/xl/sharedStrings.xml',
|
|
app_document + 'spreadsheetml.sharedStrings+xml'))
|
|
|
|
def _add_calc_chain(self):
|
|
# Add the calcChain link to the ContentTypes overrides.
|
|
self._add_override(('/xl/calcChain.xml',
|
|
app_document + 'spreadsheetml.calcChain+xml'))
|
|
|
|
def _add_image_types(self, image_types):
|
|
# Add the image default types.
|
|
for image_type in image_types:
|
|
extension = image_type
|
|
|
|
if image_type in ('wmf', 'emf'):
|
|
image_type = 'x-' + image_type
|
|
|
|
self._add_default((extension, 'image/' + image_type))
|
|
|
|
def _add_table_name(self, table_name):
|
|
# Add the name of a table to the ContentTypes overrides.
|
|
table_name = "/xl/tables/" + table_name + ".xml"
|
|
|
|
self._add_override((table_name,
|
|
app_document + 'spreadsheetml.table+xml'))
|
|
|
|
def _add_vba_project(self):
|
|
# Add a vbaProject to the ContentTypes defaults.
|
|
|
|
# Change the workbook.xml content-type from xlsx to xlsm.
|
|
for i, override in enumerate(self.overrides):
|
|
if override[0] == '/xl/workbook.xml':
|
|
self.overrides[i][1] = 'application/vnd.ms-excel.' \
|
|
'sheet.macroEnabled.main+xml'
|
|
|
|
self._add_default(('bin', 'application/vnd.ms-office.vbaProject'))
|
|
|
|
def _add_custom_properties(self):
|
|
# Add the custom properties to the ContentTypes overrides.
|
|
self._add_override(('/docProps/custom.xml',
|
|
app_document + 'custom-properties+xml'))
|
|
|
|
###########################################################################
|
|
#
|
|
# XML methods.
|
|
#
|
|
###########################################################################
|
|
|
|
def _write_defaults(self):
|
|
# Write out all of the <Default> types.
|
|
|
|
for extension, content_type in self.defaults:
|
|
self._xml_empty_tag('Default',
|
|
[('Extension', extension),
|
|
('ContentType', content_type)])
|
|
|
|
def _write_overrides(self):
|
|
# Write out all of the <Override> types.
|
|
for part_name, content_type in self.overrides:
|
|
self._xml_empty_tag('Override',
|
|
[('PartName', part_name),
|
|
('ContentType', content_type)])
|
|
|
|
def _write_types(self):
|
|
# Write the <Types> element.
|
|
xmlns = 'http://schemas.openxmlformats.org/package/2006/content-types'
|
|
|
|
attributes = [('xmlns', xmlns,)]
|
|
self._xml_start_tag('Types', attributes)
|
|
|
|
def _write_default(self, extension, content_type):
|
|
# Write the <Default> element.
|
|
attributes = [
|
|
('Extension', extension),
|
|
('ContentType', content_type),
|
|
]
|
|
|
|
self._xml_empty_tag('Default', attributes)
|
|
|
|
def _write_override(self, part_name, content_type):
|
|
# Write the <Override> element.
|
|
attributes = [
|
|
('PartName', part_name),
|
|
('ContentType', content_type),
|
|
]
|
|
|
|
self._xml_empty_tag('Override', attributes)
|