1###############################################################################
2#
3# SharedStrings - A class for writing the Excel XLSX sharedStrings file.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6# Copyright 2013-2024, John McNamara, jmcnamara@cpan.org
7#
8
9# Package imports.
10from . import xmlwriter
11from .utility import preserve_whitespace
12
13
14class SharedStrings(xmlwriter.XMLwriter):
15 """
16 A class for writing the Excel XLSX sharedStrings file.
17
18 """
19
20 ###########################################################################
21 #
22 # Public API.
23 #
24 ###########################################################################
25
26 def __init__(self):
27 """
28 Constructor.
29
30 """
31
32 super(SharedStrings, self).__init__()
33
34 self.string_table = None
35
36 ###########################################################################
37 #
38 # Private API.
39 #
40 ###########################################################################
41
42 def _assemble_xml_file(self):
43 # Assemble and write the XML file.
44
45 # Write the XML declaration.
46 self._xml_declaration()
47
48 # Write the sst element.
49 self._write_sst()
50
51 # Write the sst strings.
52 self._write_sst_strings()
53
54 # Close the sst tag.
55 self._xml_end_tag("sst")
56
57 # Close the file.
58 self._xml_close()
59
60 ###########################################################################
61 #
62 # XML methods.
63 #
64 ###########################################################################
65
66 def _write_sst(self):
67 # Write the <sst> element.
68 xmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
69
70 attributes = [
71 ("xmlns", xmlns),
72 ("count", self.string_table.count),
73 ("uniqueCount", self.string_table.unique_count),
74 ]
75
76 self._xml_start_tag("sst", attributes)
77
78 def _write_sst_strings(self):
79 # Write the sst string elements.
80
81 for string in self.string_table.string_array:
82 self._write_si(string)
83
84 def _write_si(self, string):
85 # Write the <si> element.
86 attributes = []
87
88 # Convert control character to a _xHHHH_ escape.
89 string = self._escape_control_characters(string)
90
91 # Add attribute to preserve leading or trailing whitespace.
92 if preserve_whitespace(string):
93 attributes.append(("xml:space", "preserve"))
94
95 # Write any rich strings without further tags.
96 if string.startswith("<r>") and string.endswith("</r>"):
97 self._xml_rich_si_element(string)
98 else:
99 self._xml_si_element(string, attributes)
100
101
102# A metadata class to store Excel strings between worksheets.
103class SharedStringTable(object):
104 """
105 A class to track Excel shared strings between worksheets.
106
107 """
108
109 def __init__(self):
110 self.count = 0
111 self.unique_count = 0
112 self.string_table = {}
113 self.string_array = []
114
115 def _get_shared_string_index(self, string):
116 """ " Get the index of the string in the Shared String table."""
117 if string not in self.string_table:
118 # String isn't already stored in the table so add it.
119 index = self.unique_count
120 self.string_table[string] = index
121 self.count += 1
122 self.unique_count += 1
123 return index
124 else:
125 # String exists in the table.
126 index = self.string_table[string]
127 self.count += 1
128 return index
129
130 def _get_shared_string(self, index):
131 """ " Get a shared string from the index."""
132 return self.string_array[index]
133
134 def _sort_string_data(self):
135 """ " Sort the shared string data and convert from dict to list."""
136 self.string_array = sorted(self.string_table, key=self.string_table.__getitem__)
137 self.string_table = {}