about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/xlsxwriter/packager.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/xlsxwriter/packager.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/xlsxwriter/packager.py')
-rw-r--r--.venv/lib/python3.12/site-packages/xlsxwriter/packager.py880
1 files changed, 880 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/xlsxwriter/packager.py b/.venv/lib/python3.12/site-packages/xlsxwriter/packager.py
new file mode 100644
index 00000000..17587f0a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/xlsxwriter/packager.py
@@ -0,0 +1,880 @@
+###############################################################################
+#
+# Packager - A class for writing the Excel XLSX Worksheet file.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org
+#
+
+# Standard packages.
+import os
+import stat
+import tempfile
+from io import BytesIO, StringIO
+from shutil import copy
+
+# Package imports.
+from .app import App
+from .comments import Comments
+from .contenttypes import ContentTypes
+from .core import Core
+from .custom import Custom
+from .exceptions import EmptyChartSeries
+from .feature_property_bag import FeaturePropertyBag
+from .metadata import Metadata
+from .relationships import Relationships
+from .rich_value import RichValue
+from .rich_value_rel import RichValueRel
+from .rich_value_structure import RichValueStructure
+from .rich_value_types import RichValueTypes
+from .sharedstrings import SharedStrings
+from .styles import Styles
+from .table import Table
+from .theme import Theme
+from .vml import Vml
+
+
+class Packager:
+    """
+    A class for writing the Excel XLSX Packager file.
+
+    This module is used in conjunction with XlsxWriter to create an
+    Excel XLSX container file.
+
+    From Wikipedia: The Open Packaging Conventions (OPC) is a
+    container-file technology initially created by Microsoft to store
+    a combination of XML and non-XML files that together form a single
+    entity such as an Open XML Paper Specification (OpenXPS)
+    document. http://en.wikipedia.org/wiki/Open_Packaging_Conventions.
+
+    At its simplest an Excel XLSX file contains the following elements::
+
+         ____ [Content_Types].xml
+        |
+        |____ docProps
+        | |____ app.xml
+        | |____ core.xml
+        |
+        |____ xl
+        | |____ workbook.xml
+        | |____ worksheets
+        | | |____ sheet1.xml
+        | |
+        | |____ styles.xml
+        | |
+        | |____ theme
+        | | |____ theme1.xml
+        | |
+        | |_____rels
+        |   |____ workbook.xml.rels
+        |
+        |_____rels
+          |____ .rels
+
+    The Packager class coordinates the classes that represent the
+    elements of the package and writes them into the XLSX file.
+
+    """
+
+    ###########################################################################
+    #
+    # Public API.
+    #
+    ###########################################################################
+
+    def __init__(self):
+        """
+        Constructor.
+
+        """
+
+        super().__init__()
+
+        self.tmpdir = ""
+        self.in_memory = False
+        self.workbook = None
+        self.worksheet_count = 0
+        self.chartsheet_count = 0
+        self.chart_count = 0
+        self.drawing_count = 0
+        self.table_count = 0
+        self.num_vml_files = 0
+        self.num_comment_files = 0
+        self.named_ranges = []
+        self.filenames = []
+
+    ###########################################################################
+    #
+    # Private API.
+    #
+    ###########################################################################
+
+    def _set_tmpdir(self, tmpdir):
+        # Set an optional user defined temp directory.
+        self.tmpdir = tmpdir
+
+    def _set_in_memory(self, in_memory):
+        # Set the optional 'in_memory' mode.
+        self.in_memory = in_memory
+
+    def _add_workbook(self, workbook):
+        # Add the Excel::Writer::XLSX::Workbook object to the package.
+        self.workbook = workbook
+        self.chart_count = len(workbook.charts)
+        self.drawing_count = len(workbook.drawings)
+        self.num_vml_files = workbook.num_vml_files
+        self.num_comment_files = workbook.num_comment_files
+        self.named_ranges = workbook.named_ranges
+
+        for worksheet in self.workbook.worksheets():
+            if worksheet.is_chartsheet:
+                self.chartsheet_count += 1
+            else:
+                self.worksheet_count += 1
+
+    def _create_package(self):
+        # Write the xml files that make up the XLSX OPC package.
+        self._write_content_types_file()
+        self._write_root_rels_file()
+        self._write_workbook_rels_file()
+        self._write_worksheet_files()
+        self._write_chartsheet_files()
+        self._write_workbook_file()
+        self._write_chart_files()
+        self._write_drawing_files()
+        self._write_vml_files()
+        self._write_comment_files()
+        self._write_table_files()
+        self._write_shared_strings_file()
+        self._write_styles_file()
+        self._write_custom_file()
+        self._write_theme_file()
+        self._write_worksheet_rels_files()
+        self._write_chartsheet_rels_files()
+        self._write_drawing_rels_files()
+        self._write_rich_value_rels_files()
+        self._add_image_files()
+        self._add_vba_project()
+        self._add_vba_project_signature()
+        self._write_vba_project_rels_file()
+        self._write_core_file()
+        self._write_app_file()
+        self._write_metadata_file()
+        self._write_feature_bag_property()
+        self._write_rich_value_files()
+
+        return self.filenames
+
+    def _filename(self, xml_filename):
+        # Create a temp filename to write the XML data to and store the Excel
+        # filename to use as the name in the Zip container.
+        if self.in_memory:
+            os_filename = StringIO()
+        else:
+            (fd, os_filename) = tempfile.mkstemp(dir=self.tmpdir)
+            os.close(fd)
+
+        self.filenames.append((os_filename, xml_filename, False))
+
+        return os_filename
+
+    def _write_workbook_file(self):
+        # Write the workbook.xml file.
+        workbook = self.workbook
+
+        workbook._set_xml_writer(self._filename("xl/workbook.xml"))
+        workbook._assemble_xml_file()
+
+    def _write_worksheet_files(self):
+        # Write the worksheet files.
+        index = 1
+        for worksheet in self.workbook.worksheets():
+            if worksheet.is_chartsheet:
+                continue
+
+            if worksheet.constant_memory:
+                worksheet._opt_reopen()
+                worksheet._write_single_row()
+
+            worksheet._set_xml_writer(
+                self._filename("xl/worksheets/sheet" + str(index) + ".xml")
+            )
+            worksheet._assemble_xml_file()
+            index += 1
+
+    def _write_chartsheet_files(self):
+        # Write the chartsheet files.
+        index = 1
+        for worksheet in self.workbook.worksheets():
+            if not worksheet.is_chartsheet:
+                continue
+
+            worksheet._set_xml_writer(
+                self._filename("xl/chartsheets/sheet" + str(index) + ".xml")
+            )
+            worksheet._assemble_xml_file()
+            index += 1
+
+    def _write_chart_files(self):
+        # Write the chart files.
+        if not self.workbook.charts:
+            return
+
+        index = 1
+        for chart in self.workbook.charts:
+            # Check that the chart has at least one data series.
+            if not chart.series:
+                raise EmptyChartSeries(
+                    f"Chart{index} must contain at least one "
+                    f"data series. See chart.add_series()."
+                )
+
+            chart._set_xml_writer(
+                self._filename("xl/charts/chart" + str(index) + ".xml")
+            )
+            chart._assemble_xml_file()
+            index += 1
+
+    def _write_drawing_files(self):
+        # Write the drawing files.
+        if not self.drawing_count:
+            return
+
+        index = 1
+        for drawing in self.workbook.drawings:
+            drawing._set_xml_writer(
+                self._filename("xl/drawings/drawing" + str(index) + ".xml")
+            )
+            drawing._assemble_xml_file()
+            index += 1
+
+    def _write_vml_files(self):
+        # Write the comment VML files.
+        index = 1
+        for worksheet in self.workbook.worksheets():
+            if not worksheet.has_vml and not worksheet.has_header_vml:
+                continue
+            if worksheet.has_vml:
+                vml = Vml()
+                vml._set_xml_writer(
+                    self._filename("xl/drawings/vmlDrawing" + str(index) + ".vml")
+                )
+                vml._assemble_xml_file(
+                    worksheet.vml_data_id,
+                    worksheet.vml_shape_id,
+                    worksheet.comments_list,
+                    worksheet.buttons_list,
+                )
+                index += 1
+
+            if worksheet.has_header_vml:
+                vml = Vml()
+
+                vml._set_xml_writer(
+                    self._filename("xl/drawings/vmlDrawing" + str(index) + ".vml")
+                )
+                vml._assemble_xml_file(
+                    worksheet.vml_header_id,
+                    worksheet.vml_header_id * 1024,
+                    None,
+                    None,
+                    worksheet.header_images_list,
+                )
+
+                self._write_vml_drawing_rels_file(worksheet, index)
+                index += 1
+
+    def _write_comment_files(self):
+        # Write the comment files.
+        index = 1
+        for worksheet in self.workbook.worksheets():
+            if not worksheet.has_comments:
+                continue
+
+            comment = Comments()
+            comment._set_xml_writer(self._filename("xl/comments" + str(index) + ".xml"))
+            comment._assemble_xml_file(worksheet.comments_list)
+            index += 1
+
+    def _write_shared_strings_file(self):
+        # Write the sharedStrings.xml file.
+        sst = SharedStrings()
+        sst.string_table = self.workbook.str_table
+
+        if not self.workbook.str_table.count:
+            return
+
+        sst._set_xml_writer(self._filename("xl/sharedStrings.xml"))
+        sst._assemble_xml_file()
+
+    def _write_app_file(self):
+        # Write the app.xml file.
+        properties = self.workbook.doc_properties
+        app = App()
+
+        # Add the Worksheet parts.
+        worksheet_count = 0
+        for worksheet in self.workbook.worksheets():
+            if worksheet.is_chartsheet:
+                continue
+
+            # Don't write/count veryHidden sheets.
+            if worksheet.hidden != 2:
+                app._add_part_name(worksheet.name)
+                worksheet_count += 1
+
+        # Add the Worksheet heading pairs.
+        app._add_heading_pair(["Worksheets", worksheet_count])
+
+        # Add the Chartsheet parts.
+        for worksheet in self.workbook.worksheets():
+            if not worksheet.is_chartsheet:
+                continue
+            app._add_part_name(worksheet.name)
+
+        # Add the Chartsheet heading pairs.
+        app._add_heading_pair(["Charts", self.chartsheet_count])
+
+        # Add the Named Range heading pairs.
+        if self.named_ranges:
+            app._add_heading_pair(["Named Ranges", len(self.named_ranges)])
+
+        # Add the Named Ranges parts.
+        for named_range in self.named_ranges:
+            app._add_part_name(named_range)
+
+        app._set_properties(properties)
+        app.doc_security = self.workbook.read_only
+
+        app._set_xml_writer(self._filename("docProps/app.xml"))
+        app._assemble_xml_file()
+
+    def _write_core_file(self):
+        # Write the core.xml file.
+        properties = self.workbook.doc_properties
+        core = Core()
+
+        core._set_properties(properties)
+        core._set_xml_writer(self._filename("docProps/core.xml"))
+        core._assemble_xml_file()
+
+    def _write_metadata_file(self):
+        # Write the metadata.xml file.
+        if not self.workbook.has_metadata:
+            return
+
+        metadata = Metadata()
+        metadata.has_dynamic_functions = self.workbook.has_dynamic_functions
+        metadata.num_embedded_images = len(self.workbook.embedded_images.images)
+
+        metadata._set_xml_writer(self._filename("xl/metadata.xml"))
+        metadata._assemble_xml_file()
+
+    def _write_feature_bag_property(self):
+        # Write the featurePropertyBag.xml file.
+        feature_property_bags = self.workbook._has_feature_property_bags()
+        if not feature_property_bags:
+            return
+
+        property_bag = FeaturePropertyBag()
+        property_bag.feature_property_bags = feature_property_bags
+
+        property_bag._set_xml_writer(
+            self._filename("xl/featurePropertyBag/featurePropertyBag.xml")
+        )
+        property_bag._assemble_xml_file()
+
+    def _write_rich_value_files(self):
+
+        if not self.workbook.embedded_images.has_images():
+            return
+
+        self._write_rich_value()
+        self._write_rich_value_types()
+        self._write_rich_value_structure()
+        self._write_rich_value_rel()
+
+    def _write_rich_value(self):
+        # Write the rdrichvalue.xml file.
+        filename = self._filename("xl/richData/rdrichvalue.xml")
+        xml_file = RichValue()
+        xml_file.embedded_images = self.workbook.embedded_images.images
+        xml_file._set_xml_writer(filename)
+        xml_file._assemble_xml_file()
+
+    def _write_rich_value_types(self):
+        # Write the rdRichValueTypes.xml file.
+        filename = self._filename("xl/richData/rdRichValueTypes.xml")
+        xml_file = RichValueTypes()
+        xml_file._set_xml_writer(filename)
+        xml_file._assemble_xml_file()
+
+    def _write_rich_value_structure(self):
+        # Write the rdrichvaluestructure.xml file.
+        filename = self._filename("xl/richData/rdrichvaluestructure.xml")
+        xml_file = RichValueStructure()
+        xml_file.has_embedded_descriptions = self.workbook.has_embedded_descriptions
+        xml_file._set_xml_writer(filename)
+        xml_file._assemble_xml_file()
+
+    def _write_rich_value_rel(self):
+        # Write the richValueRel.xml file.
+        filename = self._filename("xl/richData/richValueRel.xml")
+        xml_file = RichValueRel()
+        xml_file.num_embedded_images = len(self.workbook.embedded_images.images)
+        xml_file._set_xml_writer(filename)
+        xml_file._assemble_xml_file()
+
+    def _write_custom_file(self):
+        # Write the custom.xml file.
+        properties = self.workbook.custom_properties
+        custom = Custom()
+
+        if not properties:
+            return
+
+        custom._set_properties(properties)
+        custom._set_xml_writer(self._filename("docProps/custom.xml"))
+        custom._assemble_xml_file()
+
+    def _write_content_types_file(self):
+        # Write the ContentTypes.xml file.
+        content = ContentTypes()
+        content._add_image_types(self.workbook.image_types)
+
+        self._get_table_count()
+
+        worksheet_index = 1
+        chartsheet_index = 1
+        for worksheet in self.workbook.worksheets():
+            if worksheet.is_chartsheet:
+                content._add_chartsheet_name("sheet" + str(chartsheet_index))
+                chartsheet_index += 1
+            else:
+                content._add_worksheet_name("sheet" + str(worksheet_index))
+                worksheet_index += 1
+
+        for i in range(1, self.chart_count + 1):
+            content._add_chart_name("chart" + str(i))
+
+        for i in range(1, self.drawing_count + 1):
+            content._add_drawing_name("drawing" + str(i))
+
+        if self.num_vml_files:
+            content._add_vml_name()
+
+        for i in range(1, self.table_count + 1):
+            content._add_table_name("table" + str(i))
+
+        for i in range(1, self.num_comment_files + 1):
+            content._add_comment_name("comments" + str(i))
+
+        # Add the sharedString rel if there is string data in the workbook.
+        if self.workbook.str_table.count:
+            content._add_shared_strings()
+
+        # Add vbaProject (and optionally vbaProjectSignature) if present.
+        if self.workbook.vba_project:
+            content._add_vba_project()
+            if self.workbook.vba_project_signature:
+                content._add_vba_project_signature()
+
+        # Add the custom properties if present.
+        if self.workbook.custom_properties:
+            content._add_custom_properties()
+
+        # Add the metadata file if present.
+        if self.workbook.has_metadata:
+            content._add_metadata()
+
+        # Add the metadata file if present.
+        if self.workbook._has_feature_property_bags():
+            content._add_feature_bag_property()
+
+        # Add the RichValue file if present.
+        if self.workbook.embedded_images.has_images():
+            content._add_rich_value()
+
+        content._set_xml_writer(self._filename("[Content_Types].xml"))
+        content._assemble_xml_file()
+
+    def _write_styles_file(self):
+        # Write the style xml file.
+        xf_formats = self.workbook.xf_formats
+        palette = self.workbook.palette
+        font_count = self.workbook.font_count
+        num_formats = self.workbook.num_formats
+        border_count = self.workbook.border_count
+        fill_count = self.workbook.fill_count
+        custom_colors = self.workbook.custom_colors
+        dxf_formats = self.workbook.dxf_formats
+        has_comments = self.workbook.has_comments
+
+        styles = Styles()
+        styles._set_style_properties(
+            [
+                xf_formats,
+                palette,
+                font_count,
+                num_formats,
+                border_count,
+                fill_count,
+                custom_colors,
+                dxf_formats,
+                has_comments,
+            ]
+        )
+
+        styles._set_xml_writer(self._filename("xl/styles.xml"))
+        styles._assemble_xml_file()
+
+    def _write_theme_file(self):
+        # Write the theme xml file.
+        theme = Theme()
+
+        theme._set_xml_writer(self._filename("xl/theme/theme1.xml"))
+        theme._assemble_xml_file()
+
+    def _write_table_files(self):
+        # Write the table files.
+        index = 1
+        for worksheet in self.workbook.worksheets():
+            table_props = worksheet.tables
+
+            if not table_props:
+                continue
+
+            for table_props in table_props:
+                table = Table()
+                table._set_xml_writer(
+                    self._filename("xl/tables/table" + str(index) + ".xml")
+                )
+                table._set_properties(table_props)
+                table._assemble_xml_file()
+                index += 1
+
+    def _get_table_count(self):
+        # Count the table files. Required for the [Content_Types] file.
+        for worksheet in self.workbook.worksheets():
+            for _ in worksheet.tables:
+                self.table_count += 1
+
+    def _write_root_rels_file(self):
+        # Write the _rels/.rels xml file.
+        rels = Relationships()
+
+        rels._add_document_relationship("/officeDocument", "xl/workbook.xml")
+
+        rels._add_package_relationship("/metadata/core-properties", "docProps/core.xml")
+
+        rels._add_document_relationship("/extended-properties", "docProps/app.xml")
+
+        if self.workbook.custom_properties:
+            rels._add_document_relationship("/custom-properties", "docProps/custom.xml")
+
+        rels._set_xml_writer(self._filename("_rels/.rels"))
+
+        rels._assemble_xml_file()
+
+    def _write_workbook_rels_file(self):
+        # Write the _rels/.rels xml file.
+        rels = Relationships()
+
+        worksheet_index = 1
+        chartsheet_index = 1
+
+        for worksheet in self.workbook.worksheets():
+            if worksheet.is_chartsheet:
+                rels._add_document_relationship(
+                    "/chartsheet", "chartsheets/sheet" + str(chartsheet_index) + ".xml"
+                )
+                chartsheet_index += 1
+            else:
+                rels._add_document_relationship(
+                    "/worksheet", "worksheets/sheet" + str(worksheet_index) + ".xml"
+                )
+                worksheet_index += 1
+
+        rels._add_document_relationship("/theme", "theme/theme1.xml")
+        rels._add_document_relationship("/styles", "styles.xml")
+
+        # Add the sharedString rel if there is string data in the workbook.
+        if self.workbook.str_table.count:
+            rels._add_document_relationship("/sharedStrings", "sharedStrings.xml")
+
+        # Add vbaProject if present.
+        if self.workbook.vba_project:
+            rels._add_ms_package_relationship("/vbaProject", "vbaProject.bin")
+
+        # Add the metadata file if required.
+        if self.workbook.has_metadata:
+            rels._add_document_relationship("/sheetMetadata", "metadata.xml")
+
+        # Add the RichValue files if present.
+        if self.workbook.embedded_images.has_images():
+            rels._add_rich_value_relationship()
+
+        # Add the checkbox/FeaturePropertyBag file if present.
+        if self.workbook._has_feature_property_bags():
+            rels._add_feature_bag_relationship()
+
+        rels._set_xml_writer(self._filename("xl/_rels/workbook.xml.rels"))
+        rels._assemble_xml_file()
+
+    def _write_worksheet_rels_files(self):
+        # Write data such as hyperlinks or drawings.
+        index = 0
+        for worksheet in self.workbook.worksheets():
+            if worksheet.is_chartsheet:
+                continue
+
+            index += 1
+
+            external_links = (
+                worksheet.external_hyper_links
+                + worksheet.external_drawing_links
+                + worksheet.external_vml_links
+                + worksheet.external_background_links
+                + worksheet.external_table_links
+                + worksheet.external_comment_links
+            )
+
+            if not external_links:
+                continue
+
+            # Create the worksheet .rels dirs.
+            rels = Relationships()
+
+            for link_data in external_links:
+                rels._add_document_relationship(*link_data)
+
+            # Create .rels file such as /xl/worksheets/_rels/sheet1.xml.rels.
+            rels._set_xml_writer(
+                self._filename("xl/worksheets/_rels/sheet" + str(index) + ".xml.rels")
+            )
+            rels._assemble_xml_file()
+
+    def _write_chartsheet_rels_files(self):
+        # Write the chartsheet .rels files for links to drawing files.
+        index = 0
+        for worksheet in self.workbook.worksheets():
+            if not worksheet.is_chartsheet:
+                continue
+
+            index += 1
+
+            external_links = (
+                worksheet.external_drawing_links + worksheet.external_vml_links
+            )
+
+            if not external_links:
+                continue
+
+            # Create the chartsheet .rels xlsx_dir.
+            rels = Relationships()
+
+            for link_data in external_links:
+                rels._add_document_relationship(*link_data)
+
+            # Create .rels file such as /xl/chartsheets/_rels/sheet1.xml.rels.
+            rels._set_xml_writer(
+                self._filename("xl/chartsheets/_rels/sheet" + str(index) + ".xml.rels")
+            )
+            rels._assemble_xml_file()
+
+    def _write_drawing_rels_files(self):
+        # Write the drawing .rels files for worksheets with charts or drawings.
+        index = 0
+        for worksheet in self.workbook.worksheets():
+            if worksheet.drawing:
+                index += 1
+
+            if not worksheet.drawing_links:
+                continue
+
+            # Create the drawing .rels xlsx_dir.
+            rels = Relationships()
+
+            for drawing_data in worksheet.drawing_links:
+                rels._add_document_relationship(*drawing_data)
+
+            # Create .rels file such as /xl/drawings/_rels/sheet1.xml.rels.
+            rels._set_xml_writer(
+                self._filename("xl/drawings/_rels/drawing" + str(index) + ".xml.rels")
+            )
+            rels._assemble_xml_file()
+
+    def _write_vml_drawing_rels_file(self, worksheet, index):
+        # Write the vmlDdrawing .rels files for worksheets with images in
+        # headers or footers.
+
+        # Create the drawing .rels dir.
+        rels = Relationships()
+
+        for drawing_data in worksheet.vml_drawing_links:
+            rels._add_document_relationship(*drawing_data)
+
+        # Create .rels file such as /xl/drawings/_rels/vmlDrawing1.vml.rels.
+        rels._set_xml_writer(
+            self._filename("xl/drawings/_rels/vmlDrawing" + str(index) + ".vml.rels")
+        )
+        rels._assemble_xml_file()
+
+    def _write_vba_project_rels_file(self):
+        # Write the vbaProject.rels xml file if signed macros exist.
+        vba_project_signature = self.workbook.vba_project_signature
+
+        if not vba_project_signature:
+            return
+
+        # Create the vbaProject .rels dir.
+        rels = Relationships()
+
+        rels._add_ms_package_relationship(
+            "/vbaProjectSignature", "vbaProjectSignature.bin"
+        )
+
+        rels._set_xml_writer(self._filename("xl/_rels/vbaProject.bin.rels"))
+        rels._assemble_xml_file()
+
+    def _write_rich_value_rels_files(self):
+        # Write the richValueRel.xml.rels for embedded images.
+        if not self.workbook.embedded_images.has_images():
+            return
+
+        # Create the worksheet .rels dirs.
+        rels = Relationships()
+
+        index = 1
+        for image_data in self.workbook.embedded_images.images:
+            file_type = image_data[1]
+            image_file = f"../media/image{index}.{file_type}"
+            rels._add_document_relationship("/image", image_file)
+            index += 1
+
+        # Create .rels file such as /xl/worksheets/_rels/sheet1.xml.rels.
+        rels._set_xml_writer(self._filename("/xl/richData/_rels/richValueRel.xml.rels"))
+
+        rels._assemble_xml_file()
+
+    def _add_image_files(self):
+        # pylint: disable=consider-using-with
+        # Write the /xl/media/image?.xml files.
+        workbook = self.workbook
+        index = 1
+
+        images = workbook.embedded_images.images + workbook.images
+
+        for image in images:
+            filename = image[0]
+            ext = "." + image[1]
+            image_data = image[2]
+
+            xml_image_name = "xl/media/image" + str(index) + ext
+
+            if not self.in_memory:
+                # In file mode we just write or copy the image file.
+                os_filename = self._filename(xml_image_name)
+
+                if image_data:
+                    # The data is in a byte stream. Write it to the target.
+                    os_file = open(os_filename, mode="wb")
+                    os_file.write(image_data.getvalue())
+                    os_file.close()
+                else:
+                    copy(filename, os_filename)
+
+                    # Allow copies of Windows read-only images to be deleted.
+                    try:
+                        os.chmod(
+                            os_filename, os.stat(os_filename).st_mode | stat.S_IWRITE
+                        )
+                    except OSError:
+                        pass
+            else:
+                # For in-memory mode we read the image into a stream.
+                if image_data:
+                    # The data is already in a byte stream.
+                    os_filename = image_data
+                else:
+                    image_file = open(filename, mode="rb")
+                    image_data = image_file.read()
+                    os_filename = BytesIO(image_data)
+                    image_file.close()
+
+                self.filenames.append((os_filename, xml_image_name, True))
+
+            index += 1
+
+    def _add_vba_project_signature(self):
+        # pylint: disable=consider-using-with
+        # Copy in a vbaProjectSignature.bin file.
+        vba_project_signature = self.workbook.vba_project_signature
+        vba_project_signature_is_stream = self.workbook.vba_project_signature_is_stream
+
+        if not vba_project_signature:
+            return
+
+        xml_vba_signature_name = "xl/vbaProjectSignature.bin"
+
+        if not self.in_memory:
+            # In file mode we just write or copy the VBA project signature file.
+            os_filename = self._filename(xml_vba_signature_name)
+
+            if vba_project_signature_is_stream:
+                # The data is in a byte stream. Write it to the target.
+                os_file = open(os_filename, mode="wb")
+                os_file.write(vba_project_signature.getvalue())
+                os_file.close()
+            else:
+                copy(vba_project_signature, os_filename)
+
+        else:
+            # For in-memory mode we read the vba into a stream.
+            if vba_project_signature_is_stream:
+                # The data is already in a byte stream.
+                os_filename = vba_project_signature
+            else:
+                vba_file = open(vba_project_signature, mode="rb")
+                vba_data = vba_file.read()
+                os_filename = BytesIO(vba_data)
+                vba_file.close()
+
+            self.filenames.append((os_filename, xml_vba_signature_name, True))
+
+    def _add_vba_project(self):
+        # pylint: disable=consider-using-with
+        # Copy in a vbaProject.bin file.
+        vba_project = self.workbook.vba_project
+        vba_project_is_stream = self.workbook.vba_project_is_stream
+
+        if not vba_project:
+            return
+
+        xml_vba_name = "xl/vbaProject.bin"
+
+        if not self.in_memory:
+            # In file mode we just write or copy the VBA file.
+            os_filename = self._filename(xml_vba_name)
+
+            if vba_project_is_stream:
+                # The data is in a byte stream. Write it to the target.
+                os_file = open(os_filename, mode="wb")
+                os_file.write(vba_project.getvalue())
+                os_file.close()
+            else:
+                copy(vba_project, os_filename)
+
+        else:
+            # For in-memory mode we read the vba into a stream.
+            if vba_project_is_stream:
+                # The data is already in a byte stream.
+                os_filename = vba_project
+            else:
+                vba_file = open(vba_project, mode="rb")
+                vba_data = vba_file.read()
+                os_filename = BytesIO(vba_data)
+                vba_file.close()
+
+            self.filenames.append((os_filename, xml_vba_name, True))