From 7b0c6e267e580b5ecbf6a225ae800949f3fc0647 Mon Sep 17 00:00:00 2001 From: John McNamara Date: Sun, 18 Feb 2024 17:56:25 +0000 Subject: [PATCH] worksheet: add support for embedded images --- xlsxwriter/contenttypes.py | 27 ++ xlsxwriter/metadata.py | 139 ++++++-- xlsxwriter/packager.py | 82 ++++- xlsxwriter/relationships.py | 22 ++ xlsxwriter/rich_value.py | 96 ++++++ xlsxwriter/rich_value_rel.py | 81 +++++ xlsxwriter/rich_value_structure.py | 98 ++++++ xlsxwriter/rich_value_types.py | 124 +++++++ .../test/comparison/test_embed_image01.py | 34 ++ .../test/comparison/test_embed_image02.py | 35 ++ .../test/comparison/test_embed_image03.py | 35 ++ .../test/comparison/test_embed_image04.py | 36 +++ .../test/comparison/test_embed_image05.py | 36 +++ .../test/comparison/test_embed_image06.py | 35 ++ .../test/comparison/test_embed_image07.py | 36 +++ .../test/comparison/test_embed_image08.py | 36 +++ .../test/comparison/test_embed_image09.py | 39 +++ .../test/comparison/test_embed_image10.py | 36 +++ .../test/comparison/test_embed_image11.py | 37 +++ .../test/comparison/test_embed_image12.py | 38 +++ .../comparison/xlsx_files/embed_image01.xlsx | Bin 0 -> 8567 bytes .../comparison/xlsx_files/embed_image02.xlsx | Bin 0 -> 8579 bytes .../comparison/xlsx_files/embed_image03.xlsx | Bin 0 -> 8954 bytes .../comparison/xlsx_files/embed_image04.xlsx | Bin 0 -> 9462 bytes .../comparison/xlsx_files/embed_image05.xlsx | Bin 0 -> 8763 bytes .../comparison/xlsx_files/embed_image06.xlsx | Bin 0 -> 10329 bytes .../comparison/xlsx_files/embed_image07.xlsx | Bin 0 -> 10716 bytes .../comparison/xlsx_files/embed_image08.xlsx | Bin 0 -> 8586 bytes .../comparison/xlsx_files/embed_image09.xlsx | Bin 0 -> 8586 bytes .../comparison/xlsx_files/embed_image10.xlsx | Bin 0 -> 9114 bytes .../comparison/xlsx_files/embed_image11.xlsx | Bin 0 -> 8610 bytes .../comparison/xlsx_files/embed_image12.xlsx | Bin 0 -> 8622 bytes xlsxwriter/workbook.py | 305 ++++-------------- xlsxwriter/worksheet.py | 62 +++- 34 files changed, 1185 insertions(+), 284 deletions(-) create mode 100644 xlsxwriter/rich_value.py create mode 100644 xlsxwriter/rich_value_rel.py create mode 100644 xlsxwriter/rich_value_structure.py create mode 100644 xlsxwriter/rich_value_types.py create mode 100644 xlsxwriter/test/comparison/test_embed_image01.py create mode 100644 xlsxwriter/test/comparison/test_embed_image02.py create mode 100644 xlsxwriter/test/comparison/test_embed_image03.py create mode 100644 xlsxwriter/test/comparison/test_embed_image04.py create mode 100644 xlsxwriter/test/comparison/test_embed_image05.py create mode 100644 xlsxwriter/test/comparison/test_embed_image06.py create mode 100644 xlsxwriter/test/comparison/test_embed_image07.py create mode 100644 xlsxwriter/test/comparison/test_embed_image08.py create mode 100644 xlsxwriter/test/comparison/test_embed_image09.py create mode 100644 xlsxwriter/test/comparison/test_embed_image10.py create mode 100644 xlsxwriter/test/comparison/test_embed_image11.py create mode 100644 xlsxwriter/test/comparison/test_embed_image12.py create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image01.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image02.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image03.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image04.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image05.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image06.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image07.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image08.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image09.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image10.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image11.xlsx create mode 100644 xlsxwriter/test/comparison/xlsx_files/embed_image12.xlsx diff --git a/xlsxwriter/contenttypes.py b/xlsxwriter/contenttypes.py index 9b4f67b11..ecad3209e 100644 --- a/xlsxwriter/contenttypes.py +++ b/xlsxwriter/contenttypes.py @@ -179,6 +179,33 @@ def _add_metadata(self): ("/xl/metadata.xml", app_document + "spreadsheetml.sheetMetadata+xml") ) + def _add_rich_value(self): + # Add the richValue files to the ContentTypes overrides. + self._add_override( + ( + "/xl/richData/rdRichValueTypes.xml", + "application/vnd.ms-excel.rdrichvaluetypes+xml", + ) + ) + + self._add_override( + ("/xl/richData/rdrichvalue.xml", "application/vnd.ms-excel.rdrichvalue+xml") + ) + + self._add_override( + ( + "/xl/richData/rdrichvaluestructure.xml", + "application/vnd.ms-excel.rdrichvaluestructure+xml", + ) + ) + + self._add_override( + ( + "/xl/richData/richValueRel.xml", + "application/vnd.ms-excel.richvaluerel+xml", + ) + ) + ########################################################################### # # XML methods. diff --git a/xlsxwriter/metadata.py b/xlsxwriter/metadata.py index 5495a968b..335938ceb 100644 --- a/xlsxwriter/metadata.py +++ b/xlsxwriter/metadata.py @@ -29,6 +29,9 @@ def __init__(self): """ super(Metadata, self).__init__() + self.has_dynamic_functions = False + self.has_embedded_images = False + self.num_embedded_images = 0 ########################################################################### # @@ -39,6 +42,9 @@ def __init__(self): def _assemble_xml_file(self): # Assemble and write the XML file. + if self.num_embedded_images > 0: + self.has_embedded_images = True + # Write the XML declaration. self._xml_declaration() @@ -48,11 +54,17 @@ def _assemble_xml_file(self): # Write the metadataTypes element. self._write_metadata_types() - # Write the futureMetadata element. - self._write_future_metadata() + # Write the futureMetadata elements. + if self.has_dynamic_functions: + self._write_cell_future_metadata() + if self.has_embedded_images: + self._write_value_future_metadata() # Write the cellMetadata element. - self._write_cell_metadata() + if self.has_dynamic_functions: + self._write_cell_metadata() + if self.has_embedded_images: + self._write_value_metadata() self._xml_end_tag("metadata") @@ -68,28 +80,40 @@ def _assemble_xml_file(self): def _write_metadata(self): # Write the element. xmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" - schema = "http://schemas.microsoft.com/office" - xmlns_xda = schema + "/spreadsheetml/2017/dynamicarray" + schema = "http://schemas.microsoft.com/office/spreadsheetml" - attributes = [ - ("xmlns", xmlns), - ("xmlns:xda", xmlns_xda), - ] + attributes = [("xmlns", xmlns)] + + if self.has_embedded_images: + attributes.append(("xmlns:xlrd", schema + "/2017/richdata")) + + if self.has_dynamic_functions: + attributes.append(("xmlns:xda", schema + "/2017/dynamicarray")) self._xml_start_tag("metadata", attributes) def _write_metadata_types(self): # Write the element. - attributes = [("count", 1)] + count = 0 + + if self.has_dynamic_functions: + count += 1 + if self.has_embedded_images: + count += 1 + + attributes = [("count", count)] self._xml_start_tag("metadataTypes", attributes) # Write the metadataType element. - self._write_metadata_type() + if self.has_dynamic_functions: + self._write_cell_metadata_type() + if self.has_embedded_images: + self._write_value_metadata_type() self._xml_end_tag("metadataTypes") - def _write_metadata_type(self): + def _write_cell_metadata_type(self): # Write the element. attributes = [ ("name", "XLDAPR"), @@ -109,7 +133,26 @@ def _write_metadata_type(self): self._xml_empty_tag("metadataType", attributes) - def _write_future_metadata(self): + def _write_value_metadata_type(self): + # Write the element. + attributes = [ + ("name", "XLRICHVALUE"), + ("minSupportedVersion", 120000), + ("copy", 1), + ("pasteAll", 1), + ("pasteValues", 1), + ("merge", 1), + ("splitFirst", 1), + ("rowColShift", 1), + ("clearFormats", 1), + ("clearComments", 1), + ("assign", 1), + ("coerce", 1), + ] + + self._xml_empty_tag("metadataType", attributes) + + def _write_cell_future_metadata(self): # Write the element. attributes = [ ("name", "XLDAPR"), @@ -119,15 +162,30 @@ def _write_future_metadata(self): self._xml_start_tag("futureMetadata", attributes) self._xml_start_tag("bk") self._xml_start_tag("extLst") - - # Write the ext element. - self._write_ext() - + self._write_cell_ext() self._xml_end_tag("extLst") self._xml_end_tag("bk") self._xml_end_tag("futureMetadata") - def _write_ext(self): + def _write_value_future_metadata(self): + # Write the element. + attributes = [ + ("name", "XLRICHVALUE"), + ("count", self.num_embedded_images), + ] + + self._xml_start_tag("futureMetadata", attributes) + + for index in range(self.num_embedded_images): + self._xml_start_tag("bk") + self._xml_start_tag("extLst") + self._write_value_ext(index) + self._xml_end_tag("extLst") + self._xml_end_tag("bk") + + self._xml_end_tag("futureMetadata") + + def _write_cell_ext(self): # Write the element. attributes = [("uri", "{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}")] @@ -147,6 +205,23 @@ def _write_xda_dynamic_array_properties(self): self._xml_empty_tag("xda:dynamicArrayProperties", attributes) + def _write_value_ext(self, index): + # Write the element. + attributes = [("uri", "{3e2802c4-a4d2-4d8b-9148-e3be6c30e623}")] + + self._xml_start_tag("ext", attributes) + + # Write the xlrd:rvb element. + self._write_xlrd_rvb(index) + + self._xml_end_tag("ext") + + def _write_xlrd_rvb(self, index): + # Write the element. + attributes = [("i", index)] + + self._xml_empty_tag("xlrd:rvb", attributes) + def _write_cell_metadata(self): # Write the element. attributes = [("count", 1)] @@ -155,16 +230,36 @@ def _write_cell_metadata(self): self._xml_start_tag("bk") # Write the rc element. - self._write_rc() + self._write_rc(1, 0) self._xml_end_tag("bk") self._xml_end_tag("cellMetadata") - def _write_rc(self): + def _write_value_metadata(self): + # Write the element. + count = self.num_embedded_images + type = 1 + + if self.has_dynamic_functions: + type = 2 + + attributes = [("count", count)] + + self._xml_start_tag("valueMetadata", attributes) + + # Write the rc elements. + for index in range(self.num_embedded_images): + self._xml_start_tag("bk") + self._write_rc(type, index) + self._xml_end_tag("bk") + + self._xml_end_tag("valueMetadata") + + def _write_rc(self, type, index): # Write the element. attributes = [ - ("t", 1), - ("v", 0), + ("t", type), + ("v", index), ] self._xml_empty_tag("rc", attributes) diff --git a/xlsxwriter/packager.py b/xlsxwriter/packager.py index 772d21344..16892c171 100644 --- a/xlsxwriter/packager.py +++ b/xlsxwriter/packager.py @@ -23,6 +23,10 @@ from .metadata import Metadata from .relationships import Relationships from .sharedstrings import SharedStrings +from .rich_value import RichValue +from .rich_value_types import RichValueTypes +from .rich_value_rel import RichValueRel +from .rich_value_structure import RichValueStructure from .styles import Styles from .theme import Theme from .vml import Vml @@ -149,6 +153,7 @@ def _create_package(self): 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() @@ -156,6 +161,7 @@ def _create_package(self): self._write_core_file() self._write_app_file() self._write_metadata_file() + self._write_rich_value_files() return self.filenames @@ -358,9 +364,53 @@ def _write_metadata_file(self): 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_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 @@ -423,6 +473,10 @@ def _write_content_types_file(self): if self.workbook.has_metadata: content._add_metadata() + # 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() @@ -538,6 +592,10 @@ def _write_workbook_rels_file(self): 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() + rels._set_xml_writer(self._filename("xl/_rels/workbook.xml.rels")) rels._assemble_xml_file() @@ -657,12 +715,34 @@ def _write_vba_project_rels_file(self): 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): # Write the /xl/media/image?.xml files. workbook = self.workbook index = 1 - for image in workbook.images: + images = workbook.embedded_images.images + workbook.images + + for image in images: filename = image[0] ext = "." + image[1] image_data = image[2] diff --git a/xlsxwriter/relationships.py b/xlsxwriter/relationships.py index 0db069e40..435c10baa 100644 --- a/xlsxwriter/relationships.py +++ b/xlsxwriter/relationships.py @@ -75,6 +75,28 @@ def _add_ms_package_relationship(self, rel_type, target): self.relationships.append((rel_type, target, None)) + def _add_rich_value_relationship(self): + # Add RichValue relationship to XLSX .rels xml files. + schema = "http://schemas.microsoft.com/office/2022/10/relationships/" + rel_type = schema + "richValueRel" + target = "richData/richValueRel.xml" + self.relationships.append((rel_type, target, None)) + + schema = "http://schemas.microsoft.com/office/2017/06/relationships/" + rel_type = schema + "rdRichValue" + target = "richData/rdrichvalue.xml" + self.relationships.append((rel_type, target, None)) + + schema = "http://schemas.microsoft.com/office/2017/06/relationships/" + rel_type = schema + "rdRichValueStructure" + target = "richData/rdrichvaluestructure.xml" + self.relationships.append((rel_type, target, None)) + + schema = "http://schemas.microsoft.com/office/2017/06/relationships/" + rel_type = schema + "rdRichValueTypes" + target = "richData/rdRichValueTypes.xml" + self.relationships.append((rel_type, target, None)) + ########################################################################### # # XML methods. diff --git a/xlsxwriter/rich_value.py b/xlsxwriter/rich_value.py new file mode 100644 index 000000000..5054bab4f --- /dev/null +++ b/xlsxwriter/rich_value.py @@ -0,0 +1,96 @@ +############################################################################### +# +# RichValue - A class for writing the Excel XLSX rdrichvalue.xml file. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright 2013-2023, John McNamara, jmcnamara@cpan.org +# + +# Package imports. +from . import xmlwriter + + +class RichValue(xmlwriter.XMLwriter): + """ + A class for writing the Excel XLSX rdrichvalue.xml file. + + + """ + + ########################################################################### + # + # Public API. + # + ########################################################################### + + def __init__(self): + """ + Constructor. + + """ + + super(RichValue, self).__init__() + self.embedded_images = [] + + ########################################################################### + # + # Private API. + # + ########################################################################### + + def _assemble_xml_file(self): + # Assemble and write the XML file. + + # Write the XML declaration. + self._xml_declaration() + + # Write the rvData element. + self._write_rv_data() + + self._xml_end_tag("rvData") + + # Close the file. + self._xml_close() + + ########################################################################### + # + # XML methods. + # + ########################################################################### + def _write_rv_data(self): + # Write the element. + xmlns = "http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" + + attributes = [ + ("xmlns", xmlns), + ("count", len(self.embedded_images)), + ] + + self._xml_start_tag("rvData", attributes) + + for index, image_data in enumerate(self.embedded_images): + # Write the rv element. + self._write_rv(index, image_data[3], image_data[4]) + + def _write_rv(self, index, description, decorative): + # Write the element. + attributes = [("s", 0)] + value = 5 + + if decorative: + value = 6 + + self._xml_start_tag("rv", attributes) + + # Write the v elements. + self._write_v(index) + self._write_v(value) + + if description: + self._write_v(description) + + self._xml_end_tag("rv") + + def _write_v(self, data): + # Write the element. + self._xml_data_element("v", data) diff --git a/xlsxwriter/rich_value_rel.py b/xlsxwriter/rich_value_rel.py new file mode 100644 index 000000000..c437b6853 --- /dev/null +++ b/xlsxwriter/rich_value_rel.py @@ -0,0 +1,81 @@ +############################################################################### +# +# RichValueRel - A class for writing the Excel XLSX richValueRel.xml file. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright 2013-2023, John McNamara, jmcnamara@cpan.org +# + +# Package imports. +from . import xmlwriter + + +class RichValueRel(xmlwriter.XMLwriter): + """ + A class for writing the Excel XLSX richValueRel.xml file. + + + """ + + ########################################################################### + # + # Public API. + # + ########################################################################### + + def __init__(self): + """ + Constructor. + + """ + + super(RichValueRel, self).__init__() + self.num_embedded_images = 0 + + ########################################################################### + # + # Private API. + # + ########################################################################### + + def _assemble_xml_file(self): + # Assemble and write the XML file. + + # Write the XML declaration. + self._xml_declaration() + + # Write the richValueRels element. + self._write_rich_value_rels() + + self._xml_end_tag("richValueRels") + + # Close the file. + self._xml_close() + + ########################################################################### + # + # XML methods. + # + ########################################################################### + def _write_rich_value_rels(self): + # Write the element. + xmlns = "http://schemas.microsoft.com/office/spreadsheetml/2022/richvaluerel" + xmlns_r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" + + attributes = [ + ("xmlns", xmlns), + ("xmlns:r", xmlns_r), + ] + + self._xml_start_tag("richValueRels", attributes) + + # Write the rel elements. + for index in range(self.num_embedded_images): + self._write_rel(index + 1) + + def _write_rel(self, index): + # Write the element. + r_id = f"rId{index}" + attributes = [("r:id", r_id)] + + self._xml_empty_tag("rel", attributes) diff --git a/xlsxwriter/rich_value_structure.py b/xlsxwriter/rich_value_structure.py new file mode 100644 index 000000000..64cb14b05 --- /dev/null +++ b/xlsxwriter/rich_value_structure.py @@ -0,0 +1,98 @@ +############################################################################### +# +# RichValueStructure - A class for writing the Excel XLSX rdrichvaluestructure.xml file. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright 2013-2023, John McNamara, jmcnamara@cpan.org +# + +# Package imports. +from . import xmlwriter + + +class RichValueStructure(xmlwriter.XMLwriter): + """ + A class for writing the Excel XLSX rdrichvaluestructure.xml file. + + + """ + + ########################################################################### + # + # Public API. + # + ########################################################################### + + def __init__(self): + """ + Constructor. + + """ + + super(RichValueStructure, self).__init__() + self.has_embedded_descriptions = False + + ########################################################################### + # + # Private API. + # + ########################################################################### + + def _assemble_xml_file(self): + # Assemble and write the XML file. + + # Write the XML declaration. + self._xml_declaration() + + # Write the rvStructures element. + self._write_rv_structures() + + self._xml_end_tag("rvStructures") + + # Close the file. + self._xml_close() + + ########################################################################### + # + # XML methods. + # + ########################################################################### + def _write_rv_structures(self): + # Write the element. + xmlns = "http://schemas.microsoft.com/office/spreadsheetml/2017/richdata" + count = "1" + + attributes = [ + ("xmlns", xmlns), + ("count", count), + ] + + self._xml_start_tag("rvStructures", attributes) + + # Write the s element. + self._write_s() + + def _write_s(self): + # Write the element. + t = "_localImage" + attributes = [("t", t)] + + self._xml_start_tag("s", attributes) + + # Write the k elements. + self._write_k("_rvRel:LocalImageIdentifier", "i") + self._write_k("CalcOrigin", "i") + + if self.has_embedded_descriptions: + self._write_k("Text", "s") + + self._xml_end_tag("s") + + def _write_k(self, name, type): + # Write the element. + attributes = [ + ("n", name), + ("t", type), + ] + + self._xml_empty_tag("k", attributes) diff --git a/xlsxwriter/rich_value_types.py b/xlsxwriter/rich_value_types.py new file mode 100644 index 000000000..c44e4eb13 --- /dev/null +++ b/xlsxwriter/rich_value_types.py @@ -0,0 +1,124 @@ +############################################################################### +# +# RichValueTypes - A class for writing the Excel XLSX rdRichValueTypes.xml file. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright 2013-2023, John McNamara, jmcnamara@cpan.org +# + +# Package imports. +from . import xmlwriter + + +class RichValueTypes(xmlwriter.XMLwriter): + """ + A class for writing the Excel XLSX rdRichValueTypes.xml file. + + + """ + + ########################################################################### + # + # Public API. + # + ########################################################################### + + def __init__(self): + """ + Constructor. + + """ + + super(RichValueTypes, self).__init__() + + ########################################################################### + # + # Private API. + # + ########################################################################### + + def _assemble_xml_file(self): + # Assemble and write the XML file. + + # Write the XML declaration. + self._xml_declaration() + + # Write the rvTypesInfo element. + self._write_rv_types_info() + + # Write the global element. + self._write_global() + + self._xml_end_tag("rvTypesInfo") + + # Close the file. + self._xml_close() + + ########################################################################### + # + # XML methods. + # + ########################################################################### + + def _write_rv_types_info(self): + # Write the element. + xmlns = "http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2" + xmlns_x = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" + xmlns_mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" + mc_ignorable = "x" + + attributes = [ + ("xmlns", xmlns), + ("xmlns:mc", xmlns_mc), + ("mc:Ignorable", mc_ignorable), + ("xmlns:x", xmlns_x), + ] + + self._xml_start_tag("rvTypesInfo", attributes) + + def _write_global(self): + # Write the element. + key_flags = [ + ["_Self", ["ExcludeFromFile", "ExcludeFromCalcComparison"]], + ["_DisplayString", ["ExcludeFromCalcComparison"]], + ["_Flags", ["ExcludeFromCalcComparison"]], + ["_Format", ["ExcludeFromCalcComparison"]], + ["_SubLabel", ["ExcludeFromCalcComparison"]], + ["_Attribution", ["ExcludeFromCalcComparison"]], + ["_Icon", ["ExcludeFromCalcComparison"]], + ["_Display", ["ExcludeFromCalcComparison"]], + ["_CanonicalPropertyNames", ["ExcludeFromCalcComparison"]], + ["_ClassificationId", ["ExcludeFromCalcComparison"]], + ] + + self._xml_start_tag("global") + self._xml_start_tag("keyFlags") + + for key_flag in key_flags: + # Write the key element. + self._write_key(key_flag) + + self._xml_end_tag("keyFlags") + self._xml_end_tag("global") + + def _write_key(self, key_flag): + # Write the element. + name = key_flag[0] + attributes = [("name", name)] + + self._xml_start_tag("key", attributes) + + # Write the flag element. + for name in key_flag[1]: + self._write_flag(name) + + self._xml_end_tag("key") + + def _write_flag(self, name): + # Write the element. + attributes = [ + ("name", name), + ("value", "1"), + ] + + self._xml_empty_tag("flag", attributes) diff --git a/xlsxwriter/test/comparison/test_embed_image01.py b/xlsxwriter/test/comparison/test_embed_image01.py new file mode 100644 index 000000000..59ab8420b --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image01.py @@ -0,0 +1,34 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image01.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image(0, 0, self.image_dir + "red.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image02.py b/xlsxwriter/test/comparison/test_embed_image02.py new file mode 100644 index 000000000..78838fc41 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image02.py @@ -0,0 +1,35 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image02.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image(0, 0, self.image_dir + "red.png") + worksheet.embed_image(8, 4, self.image_dir + "red.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image03.py b/xlsxwriter/test/comparison/test_embed_image03.py new file mode 100644 index 000000000..16898efa0 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image03.py @@ -0,0 +1,35 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image03.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image(0, 0, self.image_dir + "red.png") + worksheet.embed_image(8, 4, self.image_dir + "blue.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image04.py b/xlsxwriter/test/comparison/test_embed_image04.py new file mode 100644 index 000000000..39c037bdd --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image04.py @@ -0,0 +1,36 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image04.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet1 = workbook.add_worksheet() + worksheet2 = workbook.add_worksheet() + + worksheet1.embed_image(0, 0, self.image_dir + "red.png") + worksheet2.embed_image(8, 4, self.image_dir + "blue.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image05.py b/xlsxwriter/test/comparison/test_embed_image05.py new file mode 100644 index 000000000..ecc1b2969 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image05.py @@ -0,0 +1,36 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image05.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.write_dynamic_array_formula(0, 0, 2, 0, "=LEN(B1:B3)", None, 0) + + worksheet.embed_image(8, 4, self.image_dir + "red.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image06.py b/xlsxwriter/test/comparison/test_embed_image06.py new file mode 100644 index 000000000..c53193d2e --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image06.py @@ -0,0 +1,35 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image06.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image(0, 0, self.image_dir + "red.png") + worksheet.insert_image(8, 4, self.image_dir + "red.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image07.py b/xlsxwriter/test/comparison/test_embed_image07.py new file mode 100644 index 000000000..500f9df62 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image07.py @@ -0,0 +1,36 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image07.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image(0, 0, self.image_dir + "red.png") + worksheet.embed_image(2, 0, self.image_dir + "blue.png") + worksheet.insert_image(8, 4, self.image_dir + "red.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image08.py b/xlsxwriter/test/comparison/test_embed_image08.py new file mode 100644 index 000000000..07c9445d6 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image08.py @@ -0,0 +1,36 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image08.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image( + 0, 0, self.image_dir + "red.png", {"description": "Some alt text"} + ) + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image09.py b/xlsxwriter/test/comparison/test_embed_image09.py new file mode 100644 index 000000000..ba6b820d9 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image09.py @@ -0,0 +1,39 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image09.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image( + 0, + 0, + self.image_dir + "red.png", + {"description": "Some alt text", "decorative": 1}, + ) + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image10.py b/xlsxwriter/test/comparison/test_embed_image10.py new file mode 100644 index 000000000..36aa7ba25 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image10.py @@ -0,0 +1,36 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image10.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.embed_image( + 0, 0, self.image_dir + "red.png", {"url": "http://www.cpan.org/"} + ) + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image11.py b/xlsxwriter/test/comparison/test_embed_image11.py new file mode 100644 index 000000000..0d7d91d94 --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image11.py @@ -0,0 +1,37 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image11.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + worksheet.set_column(0, 0, 11) + worksheet.set_row(0, 72) + + worksheet.embed_image(0, 0, self.image_dir + "red.png") + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/test_embed_image12.py b/xlsxwriter/test/comparison/test_embed_image12.py new file mode 100644 index 000000000..e36d03cfa --- /dev/null +++ b/xlsxwriter/test/comparison/test_embed_image12.py @@ -0,0 +1,38 @@ +############################################################################### +# +# Tests for XlsxWriter. +# +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c), 2013-2023, John McNamara, jmcnamara@cpan.org +# + +from ..excel_comparison_test import ExcelComparisonTest +from ...workbook import Workbook + + +class TestCompareXLSXFiles(ExcelComparisonTest): + """ + Test file created by XlsxWriter against a file created by Excel. + + """ + + def setUp(self): + + self.set_filename("embed_image12.xlsx") + + def test_create_file(self): + """Test the creation of a simple XlsxWriter file with image(s).""" + + workbook = Workbook(self.got_filename) + + worksheet = workbook.add_worksheet() + + format1 = workbook.add_format({"bg_color": "#FFFF00"}) + + worksheet.embed_image( + 0, 0, self.image_dir + "red.png", {"cell_format": format1} + ) + + workbook.close() + + self.assertExcelEqual() diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image01.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image01.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..cd3818c6452e73123e5e668a47f6c88603dc46e2 GIT binary patch literal 8567 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 Pz-wfFDnlxX0KoqMKF#-c literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image03.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image03.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..cfb4cf6b8091ec142aab1f8dcc1848077a78eb79 GIT binary patch literal 8954 zcma)BbzIZy_a9wD5b5rgPC@Awq+uXP4IJI6ND4?uBS?pm3Im2HjSlJ2DUC==2ul8j zet%xjd$0G8XZvig*WPF6yr1Ve=e&=m8X7t=006)Skkx4zs)`!}JB_?O?B`ivvK*RPP2uk;}sy4}gOH1^J8bAk~R#x90hXL-%*M z7@f4{T2P}kbx0*WB}2^iXb)i(D=BMF`%eyQJ?Z+hWpy}3Tr8&D8s-h)BWiZV7;p3I z?Z$irEl9+clRPVv>+7dR8bL{#Vk}W!2q+1&=k;&G{w5g8BoQXIpfK_mVz;1ZT-x(! zVw9-|cQN{H(zoarZg&OTiBe3t?He{z4qt0#oi~2+Xv)l^CV#^tcE-B&HE0B^+ga6p zFxk7$$@pYfhEbN!2shuQ!FfgQg>OO;1Gq>fh4_C^-gSf>um$$SG zi|0Bzmp;kO=}zBUhq67((x^t?{&ZD^@_it2;k8&6`N8teBNpQW?6%e#yTl>12({L$ z*_x>D+7r|nf;5ZJr0vrBZ`jun$cGzw*670Xd~-&mT6Q&i)&g#d43#IEr4>TE8SOej zG(D5c4H1W!9Oi2*d%>PQbgs|ox~5*N;!)7FP7*E8(U`H^PL(nC9OUPGhV@>#QNU2D z_trWV8C1{i*pFCaCfvgtPz zgDq0zCckV`8Hz>ag1#1X^SCbndo^AyvPz%3^}^~Mw+)5ZI@dgm#czBv3uvE#B`%~ zN9~dXs)39LEnM1D`L_G+2%=*(lORj?5z?#S*ufkW>YWVu~AwD2y#?mcTXH)kn9til5StI%$y2=5ui{*RN8^c^A%VcvF zs*-%=IPdDtTW+ zsgim@0SL0ZD;;==HX&*zK{P<;#I`j%T|5bx5n3{wCsw;}ssV>NRC%?DgMn#4_YrY2^b-Zz9jiVVa{dc229LN}V29jU6L^WFw;Y(~UN z1EV2WF)nLMHl3^8lF=*C+I!SM?h;C3jLx30o~F(dhzkKH9%dL5mVk3U@aaeEL?}ezEC(&>rwHqzKj{J^q@d z@R+|}*xu3DX*q7)JeS_a=%|C;>LyJ@pwHlD`a^?{Ih>k^B@_LTH%Hf>XDTCdvSI0W zFY6R(%yk+ydQeZ8;4Jk5a11~GYoa4e4m`q@Mg_W&286-;i+qKw>~tjK5) zAfx4N&+FynYG>i(WcR1N8Liccj2L0v4$1Hogw~eHNVw>&nyzesJfxR(N=TnZ0!q_= za(z{o!+E|+aQ;JIk8kZYkw^D)Jo-OT$EyH=9*~g1L+TqMk4HqC(wB^!!9pLMWwA=; zY{#hlz6yP8x@-D|+IDk7fw&e5fA}T>qBWofwr{yu)D&mC<2g0LR8ra4fCDC7s-7 zZBjw&;}aUi($-tR+&QA{Zh=6O&BSShZJtC1SH?34={30#eTz;1hp6DTjKP*&@qC@v zYY?k;prO=E25|!`L*x?KI?iIlo_JR!_oa`0y!*5MmSA7(eOhPPQ{t7hJvMu?_yChg zD`)aH)fcL&S2_?+G;G?b4Tm^9l*UW^Megxo%UQ8xfuW2E&;_jhf5Rm+>-%$CaUDzVwG?utX5 z{$i;e$x^!+JS+jp5)U#f|L@p1fZffl%-zj@lCz8?X7zV+%Hp~mC-?|MHZcw^p>GPX zj5(XgX%mtQ8#UDnMf7p0mvJ*5p{2Mw5Z~X|)?Rz7;@7D#=-TXLV;%W4Pk#YGTOiER z&C0=I7E)F)ma;qRpTW)E+@#)}B&^wgg}%P%hCjOyy6H}n3OYGAgeu5b;9)LCw~GbM zlTk?Nh~(S;O^Ry-b#PMpyYIGzG6cH|a+u70bQ}DG`?S3yVK`UJg)7yWFzQgiSx-`O z*M|@*jB6(gfQa%8oW9W#O#a(SqEez#4P_0EPND>N*!%h?J$gWN*;A%O5!VLDAC+$m zT87V)&*&E|S#;`Qi49U7(LR)NSAAH$D+XknIxzxyjC5F+hN5naSc>(Mag_)^c}^9> zzHe=B^x0wtT5M*3S(3XfyEJ>~LvzZvmncIkIC@XSC7q==JMPTL=^L0^ibMUe^J0Q3#5Kd@l2DPJ_>Y6EBayQZ^x@qLoZ z;yz_LW;XWx=I)}O&LBTu5kGMlO&kzCg84?Zfo9KZIzK#LlWX-dr?_n5tuHA8{dZ@- zpi2kgkaPJkt~8P<*lWz_*6m-X_cNkPXPkQYBK$s}z*5x}HtHZk5UPU-Hi6M{Jc1J_ zPrl_I1RrtrbU>j=3ML{`2lU}vu|bA1i}Xs8Ty`Du+a&F>fm22V)%_9ZQ7Js)U% zI*G8izB$EwB7C({Dw-r^FS#-Mxvc1}0tsX)=_n~P(d6=+7`Yne=>VVL7x22rcKo&N z&ibMjAbuGoHw~!`i@_n=UBOpvEGsqQerb97he~OKd*&-<$FyIhF0v{$y2((10RZSw z{b-nwiO&5l*a7_G^{*@SAGloysXrc2ByZT^QfvsGe|u?+1XR_|ifC!E71eY}AHCxD ze$=x2re}LukY$0Y9%M+ZV9K{}oH1|^?^t+3yIOaSclV1@{FXJ;%DjYB=2C>sQQb71 ze_O5V7nv>u!{zwxdrLvfwelH^ZJ3s9hjBV%U{o55VVJZ=(__qqKqz6Wc5^gL zuTv_y-s4^775?fV{k+wstoRqq*zhmu8X>LXIRjpzJeytLM(|ELUzxrfSr>Qn7Y7{P zFkIm_|KQ)b+~sYXJ?EP0Rr7IZlGAj4+OWmR{Thu^UXT;_=MAC;J-gQvUvQ^PX6nJm z5)&UBD}(k)zkVcYc;J(_tiL7BZXra$n^WoC!z36MCHBTKqy{jR#?piewj0w!u-WRp zc=z=N*?qu5^Sei^%IZ1-EjMOfi_zjf5=8M%Fk9ECSnMn)yGa_~kX>YJO!u6e(*nik z%Tb#_Z&ogHQA^$PJo=n6uk<*E?!=zHE+#>f?cTRzvIh?iISy8ry?E&!fZ=L1r-!$) zj`vnmth4(Ac^mw<+bY?38@?U&($P}QOrR2Yd<}rh=Nd0yukVoC3u4pDxrjWH34w&7 zDg_7u{5XpNPU`%Ev)A%h>fWGI2Hb&4KwkN ziC-&eVd>Wnmpany2;EUMa)v~WzzV(sx=n%X;@rwimW%1Sp8d;)CBo;HjfFHDvj z`PDV-;8C)oCx|GU&ko)~sj72Uc&4F#SX7&rGMW9*U619aj}czeZ4GaVlSkHJk(hR? zZZ18%rsB+x*)6ebJKn3O)>z}HV%;C@A`|bs$9jwD756(m=bWZ*!bG?4%j&rk&Jw>B zs}0diE|rVW=9y(SD_h8*W8)yt+VrUuq|dGxUzDl%farbbCi0Cl@pZN$+|0y0y3>iR zizC2J)lITeXj2yg`>0-s8B!VCI8aKK%V5dJB=d1UsF|C4iI$OKHXxDTHR_>QwD5;v z-}(_D2vu}V0!$;;-DLyUWlCJW2u94}S4$1jHpyW^bd>m!Zo7=b6!}z|!Re?{slxPK zE%^@LiiH-d-`(psb2GYDorGy1pD$ZX!<`qz*(mJi5zoE*($Dc@*baXaB6@frx6k!N z?&?}X4olwUt)WL5@1S*UY>&c&*~Mh#L@pna?|MeA;TDG2DBgz=YUVhmdJlE*mdq@0 zr9rRpsWIK&%TFdfM9sX@>+#+o&36y?!!#lhE}k}5-}uZb70=R+={dm_5xSq5rb@h84nI#{<9h(>?4f1Mi89Rl#UbnA<=^qSd*9P9z*H&H+epx?Y;=r3ySVm*DJ=9Nk z>z+5A)n=0nq$QDiiuHOxp0(Fr3d-jSvV3E*6O@a$|L2CHcXG&_zKsq5Q2xm2Kl;M+ z&CbOhG3$5LtSs?+$MZu^aUses(;RT*%;y_2wfQ+m;g$gwh=ynIrW| zmhA)IltA9bWEyKv}d#kqh1{sH(Os-cPg^5PT{ng@-=9_ zQ>7liKt!rI%yM_7d}b5w$cIMH#%YgBTWR?Jm$I{BUg(tJ+EA1jw97?~=p*IQ2$M7@b(hZKGgThC6B7;WMRq;bG09UQavM z)QN?~jw5{%OvHBdYad(fO2s>Oz1%Y!TCp0&$W2>?745l1VJ&(y7^@Yp^GbW$t};CZ zstzlgv+2EAlz(e{XK3xpMOx$z9(sV0wB#Xaq5naPE5!1yJhF`Db+yt)KI)s>dw{=d znt!Uk$`YsTTF#mttV250DdCl1DhsYW;~YM?^uFW^h*5A#K66pk>9NN1HL@1?LGo>$ ztj$G#tJ)PIMZe`bD693rR)|7BwlSwp+Zs3_+7YyX_JjyQNl|I)3sZgZGTE_lnQGZh zXDpl?-eylFTRAfsSvEM+W`tu?U)Ex1*zKUl!BFdz9@6hr0Hpk8FHk?L5#fM?V!cLF zg_y(Y6zNBpgEJmV8ymRcJC2AjS%?zq=4ggy1|*0_Rv9i-S6sr)k9{LpbBMp^hy0F% zqct8J4FlXvmKd|au9kYih?XW~Izq&?UG!C{?yS_qv(d9>;vjk+yUk z?bLi?&Bs-I4U0R(n@LWD2OiG4C6WCPWNEX630I!`x~uRFp@dJuI*>K6IwZY}erz!@#Ug7`#ZxP zZCsGtxQX(TGW~K_22uP2x>QeyM8p0}u;{vzco7#=o)gp4ga9{^iLP_3X=!x3e?wwl9?TDUbJC=3)*7V2II(mYoYqWfG548*|lQkJfM%cVA9&QlBqQ zxG>xG-PUZ;)z_dXoQATvQ%IEsWI{IG!6B|!YC)n_4X#Z!+_+*rIzFWwUeY94UFsb* z1)w{+w3}r;N_o86ee{c@0!1Ue`4$-!RAf|`e~pUO+5YxC+thCEt{#@|9)H#V)nnA` zTBU&@o1rIR3j4kZw~d0!I1kaeIQk`vtTOjYbBLnZUgU3@3&fUhj$bEyg+98{bjLXGk}|`JmC2D$|n?A0pUPaj#Tp9Jw=mUcpxG4Rl*A*+jZ;sG-WtLyKw|9H#K-us->iAbk+#xjMPkPeq1w*}iTPXEY7XIta@efPg3^H)9!Lk1xH z_j6Mp+pLPt4}7>8w5jP@lbRYFZg0a2EjIws(O0EvxTGb+xHcw?37bQ&dv8ApIX#qu zPCS6C-*+xzhzQgo$TqZhm8lD?8JL~L(RE;sfic_9w2=Qpb>IYiqiYb+&8?7$-r|$!{sG1K<|<3 zY@~(k&>X;45OZFLgSicupU2tJ=BI%BH_3Sw_}Oh~F@Da%%xvb%t}_m5KQ4V&GdlCB za-9hnGJ||LBf$q}p*&yW;F$|{D-vQ5hh*m$xT`K_zb%Nl=^%&2HE(UElmUO z_}{ijiL=bM`Cyr1CJZx@>4U@W<889@nC=BEy?=+NwD^QnN+`bHn9;(|(2EzX_2EL6 z#pcFMZmbpXdB0ImY0>^^kV%g89{@m}5I}z5+0);SH8FmSHGdI3HPtQxUmTpB2VO?v z|2{_hZ>SfiIpdj$!=-{TrnkiGHS3{|jNiYpUnbAK-jPzo@VxLC+M{e*yhn%sUTijQ1V%ytMb{ zD4aoFRFcj^^5cJp{9RZ2Z@?Ful=Hy6SH1)PW6Sd2@Gn-|=kejl^N8FNf2h6xY~}Z& z@Vu2!(qF9nlJE3%krvKM#6NI)vA{ZS;VIcK7XGo^`m-;;7b@p1)gwP#jM&e@?nl{z zG;mh7{EI8U7X{}HKq)R7_}3BvY3!^-_!nbm8~0*@{bB6vlFbhsp!{y^_jLQ`F#Vpr n&I9)%)z*u7{C~L&34E5ze*4E5$lK{`PJS6cgM4bEKKt~4hk<>r literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image04.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b626b7711b0b49bfe293ddb35d25fb9694b21bd3 GIT binary patch literal 9462 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 P5H9fY1fHOzm!JL*r6fNK literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image05.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image05.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5430cdc4f91c8d0d46d117a57694b6e57c8942c3 GIT binary patch literal 8763 zcma)iby!sG^ZpXjNJw|*A}t}(y_AHsSzJEMt&)MtRd#*G0JTvp$vnn72L_7chfC3<_Q`V9&^hnNt0{{Y%0DxNnGJvjx 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 literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image06.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image06.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3b9f0e35868ff3e6e9c8cf4357503c9d3f094f95 GIT binary patch literal 10329 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

_X-xB?(Y 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 literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image08.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image08.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ca94766f65b758ad0fffc0e25c9995548a95b6c6 GIT binary patch literal 8586 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 literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image10.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image10.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..38ae6342c6316e33c91709e1c168264f7f13ffc2 GIT binary patch literal 9114 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 bF!pDC`!`@@c(%IS&2HNJ literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image11.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image11.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..989ea03b6bf9f9abec7c5ac5429f0120b657eea7 GIT binary patch literal 8610 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 literal 0 HcmV?d00001 diff --git a/xlsxwriter/test/comparison/xlsx_files/embed_image12.xlsx b/xlsxwriter/test/comparison/xlsx_files/embed_image12.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5961f64ccb30b9c585f7b507e28b2f160284d105 GIT binary patch literal 8622 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 E4_s&GVE_OC literal 0 HcmV?d00001 diff --git a/xlsxwriter/workbook.py b/xlsxwriter/workbook.py index 0a54da011..268391501 100644 --- a/xlsxwriter/workbook.py +++ b/xlsxwriter/workbook.py @@ -7,7 +7,6 @@ # # Standard packages. -import hashlib import operator import os import re @@ -15,7 +14,6 @@ from datetime import datetime, timezone from decimal import Decimal from fractions import Fraction -from struct import unpack from warnings import warn from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED, LargeZipFile @@ -39,10 +37,9 @@ from .chart_stock import ChartStock from .exceptions import InvalidWorksheetName from .exceptions import DuplicateWorksheetName -from .exceptions import UndefinedImageSize -from .exceptions import UnsupportedImageFormat from .exceptions import FileCreateError from .exceptions import FileSizeError +from .utility import get_image_properties class Workbook(xmlwriter.XMLwriter): @@ -146,6 +143,10 @@ def __init__(self, filename=None, options=None): self.has_comments = False self.read_only = 0 self.has_metadata = False + self.has_embedded_images = False + self.has_dynamic_functions = False + self.has_embedded_descriptions = False + self.embedded_images = EmbeddedImages() # We can't do 'constant_memory' mode while doing 'in_memory' mode. if self.in_memory: @@ -812,6 +813,7 @@ def _add_sheet(self, name, worksheet_class=None): "remove_timezone": self.remove_timezone, "max_url_length": self.max_url_length, "use_future_functions": self.use_future_functions, + "embedded_images": self.embedded_images, } worksheet._initialize(init_data) @@ -1176,13 +1178,21 @@ def _sort_defined_names(self, names): def _prepare_drawings(self): # Iterate through the worksheets and set up chart and image drawings. chart_ref_id = 0 - image_ref_id = 0 ref_id = 0 drawing_id = 0 image_ids = {} header_image_ids = {} background_ids = {} + # Store the image types for any embedded images. + for image_data in self.embedded_images.images: + image_type = image_data[1] + self.image_types[image_type] = True + if image_data[3]: + self.has_embedded_descriptions = True + + image_ref_id = len(self.embedded_images.images) + for sheet in self.worksheets(): chart_count = len(sheet.charts) image_count = len(sheet.images) @@ -1225,7 +1235,9 @@ def _prepare_drawings(self): _, _, digest, - ) = self._get_image_properties(filename, image_data) + ) = get_image_properties(filename, image_data) + + self.image_types[image_type] = True if digest in background_ids: ref_id = background_ids[digest] @@ -1249,7 +1261,9 @@ def _prepare_drawings(self): x_dpi, y_dpi, digest, - ) = self._get_image_properties(filename, image_data) + ) = get_image_properties(filename, image_data) + + self.image_types[image_type] = True if digest in image_ids: ref_id = image_ids[digest] @@ -1295,7 +1309,9 @@ def _prepare_drawings(self): x_dpi, y_dpi, digest, - ) = self._get_image_properties(filename, image_data) + ) = get_image_properties(filename, image_data) + + self.image_types[image_type] = True if digest in header_image_ids: ref_id = header_image_ids[digest] @@ -1331,7 +1347,9 @@ def _prepare_drawings(self): x_dpi, y_dpi, digest, - ) = self._get_image_properties(filename, image_data) + ) = get_image_properties(filename, image_data) + + self.image_types[image_type] = True if digest in header_image_ids: ref_id = header_image_ids[digest] @@ -1368,246 +1386,6 @@ def _prepare_drawings(self): self.drawing_count = drawing_id - def _get_image_properties(self, filename, image_data): - # Extract dimension information from the image file. - height = 0 - width = 0 - x_dpi = 96 - y_dpi = 96 - - if not image_data: - # Open the image file and read in the data. - fh = open(filename, "rb") - data = fh.read() - else: - # Read the image data from the user supplied byte stream. - data = image_data.getvalue() - - digest = hashlib.sha256(data).hexdigest() - - # Get the image filename without the path. - image_name = os.path.basename(filename) - - # Look for some common image file markers. - marker1 = unpack("3s", data[1:4])[0] - marker2 = unpack(">H", data[:2])[0] - marker3 = unpack("2s", data[:2])[0] - marker4 = unpack("I", data[offset + 0 : offset + 4])[0] - marker = unpack("4s", data[offset + 4 : offset + 8])[0] - - # Read the image dimensions. - if marker == b"IHDR": - width = unpack(">I", data[offset + 8 : offset + 12])[0] - height = unpack(">I", data[offset + 12 : offset + 16])[0] - - # Read the image DPI. - if marker == b"pHYs": - x_density = unpack(">I", data[offset + 8 : offset + 12])[0] - y_density = unpack(">I", data[offset + 12 : offset + 16])[0] - units = unpack("b", data[offset + 16 : offset + 17])[0] - - if units == 1: - x_dpi = x_density * 0.0254 - y_dpi = y_density * 0.0254 - - if marker == b"IEND": - end_marker = True - continue - - offset = offset + length + 12 - - return "png", width, height, x_dpi, y_dpi - - def _process_jpg(self, data): - # Extract width and height information from a JPEG file. - offset = 2 - data_length = len(data) - end_marker = False - width = 0 - height = 0 - x_dpi = 96 - y_dpi = 96 - - # Search through the image data to read the JPEG markers. - while not end_marker and offset < data_length: - marker = unpack(">H", data[offset + 0 : offset + 2])[0] - length = unpack(">H", data[offset + 2 : offset + 4])[0] - - # Read the height and width in the 0xFFCn elements (except C4, C8 - # and CC which aren't SOF markers). - if ( - (marker & 0xFFF0) == 0xFFC0 - and marker != 0xFFC4 - and marker != 0xFFC8 - and marker != 0xFFCC - ): - height = unpack(">H", data[offset + 5 : offset + 7])[0] - width = unpack(">H", data[offset + 7 : offset + 9])[0] - - # Read the DPI in the 0xFFE0 element. - if marker == 0xFFE0: - units = unpack("b", data[offset + 11 : offset + 12])[0] - x_density = unpack(">H", data[offset + 12 : offset + 14])[0] - y_density = unpack(">H", data[offset + 14 : offset + 16])[0] - - if units == 1: - x_dpi = x_density - y_dpi = y_density - - if units == 2: - x_dpi = x_density * 2.54 - y_dpi = y_density * 2.54 - - # Workaround for incorrect dpi. - if x_dpi == 1: - x_dpi = 96 - if y_dpi == 1: - y_dpi = 96 - - if marker == 0xFFDA: - end_marker = True - continue - - offset = offset + length + 2 - - return "jpeg", width, height, x_dpi, y_dpi - - def _process_gif(self, data): - # Extract width and height information from a GIF file. - x_dpi = 96 - y_dpi = 96 - - width = unpack(" 0 diff --git a/xlsxwriter/worksheet.py b/xlsxwriter/worksheet.py index 28af985d9..5b89ea1fb 100644 --- a/xlsxwriter/worksheet.py +++ b/xlsxwriter/worksheet.py @@ -39,6 +39,7 @@ from .utility import get_sparkline_style from .utility import supported_datetime from .utility import datetime_to_excel_datetime +from .utility import get_image_properties from .utility import preserve_whitespace from .utility import quote_sheetname from .exceptions import DuplicateTableName @@ -182,6 +183,7 @@ def column_wrapper(self, *args, **kwargs): "ArrayFormula", "formula, format, value, range, atype" ) cell_rich_string_tuple = namedtuple("RichString", "string, format, raw_string") +cell_error_tuple = namedtuple("Error", "error, format, value") ############################################################################### @@ -416,6 +418,7 @@ def __init__(self): self.has_dynamic_arrays = False self.use_future_functions = False + self.ignore_write_string = False # Utility function for writing different types of strings. def _write_token_as_string(self, token, row, col, *args): @@ -1261,16 +1264,17 @@ def _write_url(self, row, col, url, cell_format=None, string=None, tip=None): ) return -4 - # Write previous row if in in-line string constant_memory mode. - if self.constant_memory and row > self.previous_row: - self._write_single_row(row) - # Add the default URL format. if cell_format is None: cell_format = self.default_url_format - # Write the hyperlink string. - self._write_string(row, col, string, cell_format) + if not self.ignore_write_string: + # Write previous row if in in-line string constant_memory mode. + if self.constant_memory and row > self.previous_row: + self._write_single_row(row) + + # Write the hyperlink string. + self._write_string(row, col, string, cell_format) # Store the hyperlink data in a separate structure. self.hyperlinks[row][col] = { @@ -1566,23 +1570,49 @@ def embed_image(self, row, col, filename, options=None): """ # Check insert (row, col) without storing. - if self._check_dimensions(row, col, True, True): + if self._check_dimensions(row, col): warn("Cannot embed image at (%d, %d)." % (row, col)) return -1 if options is None: options = {} - # url = options.get("url", None) - # tip = options.get("tip", None) + url = options.get("url", None) + tip = options.get("tip", None) + cell_format = options.get("cell_format", None) image_data = options.get("image_data", None) - # description = options.get("description", None) - # decorative = options.get("decorative", False) + description = options.get("description", None) + decorative = options.get("decorative", False) if not image_data and not os.path.exists(filename): warn("Image file '%s' not found." % filename) return -1 + if url: + if cell_format is None: + cell_format = self.default_url_format + + self.ignore_write_string = True + self.write_url(row, col, url, cell_format, None, tip) + self.ignore_write_string = False + + # Get the image properties, for the type and checksum. + ( + image_type, + _, + _, + _, + _, + _, + digest, + ) = get_image_properties(filename, image_data) + + image = [filename, image_type, image_data, description, decorative] + image_index = self.embedded_images.get_image_index(image, digest) + + # Store the cell error and image index in the worksheet data table. + self.table[row][col] = cell_error_tuple("#VALUE!", cell_format, image_index) + return 0 @convert_cell_args @@ -4626,6 +4656,7 @@ def _initialize(self, init_data): self.remove_timezone = init_data["remove_timezone"] self.max_url_length = init_data["max_url_length"] self.use_future_functions = init_data["use_future_functions"] + self.embedded_images = init_data["embedded_images"] if self.excel2003_style: self.original_row_height = 12.75 @@ -6419,7 +6450,6 @@ def _write_col_info(self, col_min, col_max, col_info): def _write_sheet_data(self): # Write the element. - if self.dim_rowmin is None: # If the dimensions aren't defined there is no data to write. self._xml_empty_tag("sheetData") @@ -6885,6 +6915,14 @@ def _write_cell(self, row, col, cell): self._write_cell_value(cell.boolean) self._xml_end_tag("c") + elif type_cell_name == "Error": + # Write a boolean cell. + attributes.append(("t", "e")) + attributes.append(("vm", cell.value)) + self._xml_start_tag("c", attributes) + self._write_cell_value(cell.error) + self._xml_end_tag("c") + def _write_cell_value(self, value): # Write the cell value element. if value is None: