############################################################################### # # App - A class for writing the Excel XLSX App file. # # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org # # Package imports. from . import xmlwriter class App(xmlwriter.XMLwriter): """ A class for writing the Excel XLSX App file. """ ########################################################################### # # Public API. # ########################################################################### def __init__(self): """ Constructor. """ super().__init__() self.part_names = [] self.heading_pairs = [] self.properties = {} self.doc_security = 0 def _add_part_name(self, part_name): # Add the name of a workbook Part such as 'Sheet1' or 'Print_Titles'. self.part_names.append(part_name) def _add_heading_pair(self, heading_pair): # Add the name of a workbook Heading Pair such as 'Worksheets', # 'Charts' or 'Named Ranges'. # Ignore empty pairs such as chartsheets. if not heading_pair[1]: return self.heading_pairs.append(("lpstr", heading_pair[0])) self.heading_pairs.append(("i4", heading_pair[1])) def _set_properties(self, properties): # Set the document properties. self.properties = properties ########################################################################### # # Private API. # ########################################################################### def _assemble_xml_file(self): # Assemble and write the XML file. # Write the XML declaration. self._xml_declaration() self._write_properties() self._write_application() self._write_doc_security() self._write_scale_crop() self._write_heading_pairs() self._write_titles_of_parts() self._write_manager() self._write_company() self._write_links_up_to_date() self._write_shared_doc() self._write_hyperlink_base() self._write_hyperlinks_changed() self._write_app_version() self._xml_end_tag("Properties") # Close the file. self._xml_close() ########################################################################### # # XML methods. # ########################################################################### def _write_properties(self): # Write the element. schema = "http://schemas.openxmlformats.org/officeDocument/2006/" xmlns = schema + "extended-properties" xmlns_vt = schema + "docPropsVTypes" attributes = [ ("xmlns", xmlns), ("xmlns:vt", xmlns_vt), ] self._xml_start_tag("Properties", attributes) def _write_application(self): # Write the element. self._xml_data_element("Application", "Microsoft Excel") def _write_doc_security(self): # Write the element. self._xml_data_element("DocSecurity", self.doc_security) def _write_scale_crop(self): # Write the element. self._xml_data_element("ScaleCrop", "false") def _write_heading_pairs(self): # Write the element. self._xml_start_tag("HeadingPairs") self._write_vt_vector("variant", self.heading_pairs) self._xml_end_tag("HeadingPairs") def _write_titles_of_parts(self): # Write the element. parts_data = [] self._xml_start_tag("TitlesOfParts") for part_name in self.part_names: parts_data.append(("lpstr", part_name)) self._write_vt_vector("lpstr", parts_data) self._xml_end_tag("TitlesOfParts") def _write_vt_vector(self, base_type, vector_data): # Write the element. attributes = [ ("size", len(vector_data)), ("baseType", base_type), ] self._xml_start_tag("vt:vector", attributes) for vt_data in vector_data: if base_type == "variant": self._xml_start_tag("vt:variant") self._write_vt_data(vt_data) if base_type == "variant": self._xml_end_tag("vt:variant") self._xml_end_tag("vt:vector") def _write_vt_data(self, vt_data): # Write the elements such as and . self._xml_data_element(f"vt:{vt_data[0]}", vt_data[1]) def _write_company(self): company = self.properties.get("company", "") self._xml_data_element("Company", company) def _write_manager(self): # Write the element. if "manager" not in self.properties: return self._xml_data_element("Manager", self.properties["manager"]) def _write_links_up_to_date(self): # Write the element. self._xml_data_element("LinksUpToDate", "false") def _write_shared_doc(self): # Write the element. self._xml_data_element("SharedDoc", "false") def _write_hyperlink_base(self): # Write the element. hyperlink_base = self.properties.get("hyperlink_base") if hyperlink_base is None: return self._xml_data_element("HyperlinkBase", hyperlink_base) def _write_hyperlinks_changed(self): # Write the element. self._xml_data_element("HyperlinksChanged", "false") def _write_app_version(self): # Write the element. self._xml_data_element("AppVersion", "12.0000")