1###############################################################################
2#
3# Comments - A class for writing the Excel XLSX Worksheet file.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6# Copyright 2013-2024, John McNamara, jmcnamara@cpan.org
7#
8
9from . import xmlwriter
10from .utility import preserve_whitespace
11from .utility import xl_rowcol_to_cell
12
13
14class Comments(xmlwriter.XMLwriter):
15 """
16 A class for writing the Excel XLSX Comments file.
17
18
19 """
20
21 ###########################################################################
22 #
23 # Public API.
24 #
25 ###########################################################################
26
27 def __init__(self):
28 """
29 Constructor.
30
31 """
32
33 super(Comments, self).__init__()
34 self.author_ids = {}
35
36 ###########################################################################
37 #
38 # Private API.
39 #
40 ###########################################################################
41
42 def _assemble_xml_file(self, comments_data=[]):
43 # Assemble and write the XML file.
44
45 # Write the XML declaration.
46 self._xml_declaration()
47
48 # Write the comments element.
49 self._write_comments()
50
51 # Write the authors element.
52 self._write_authors(comments_data)
53
54 # Write the commentList element.
55 self._write_comment_list(comments_data)
56
57 self._xml_end_tag("comments")
58
59 # Close the file.
60 self._xml_close()
61
62 ###########################################################################
63 #
64 # XML methods.
65 #
66 ###########################################################################
67
68 def _write_comments(self):
69 # Write the <comments> element.
70 xmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
71
72 attributes = [("xmlns", xmlns)]
73
74 self._xml_start_tag("comments", attributes)
75
76 def _write_authors(self, comment_data):
77 # Write the <authors> element.
78 author_count = 0
79
80 self._xml_start_tag("authors")
81
82 for comment in comment_data:
83 author = comment[3]
84
85 if author is not None and author not in self.author_ids:
86 # Store the author id.
87 self.author_ids[author] = author_count
88 author_count += 1
89
90 # Write the author element.
91 self._write_author(author)
92
93 self._xml_end_tag("authors")
94
95 def _write_author(self, data):
96 # Write the <author> element.
97 self._xml_data_element("author", data)
98
99 def _write_comment_list(self, comment_data):
100 # Write the <commentList> element.
101 self._xml_start_tag("commentList")
102
103 for comment in comment_data:
104 row = comment[0]
105 col = comment[1]
106 text = comment[2]
107 author = comment[3]
108 font_name = comment[6]
109 font_size = comment[7]
110 font_family = comment[8]
111
112 # Look up the author id.
113 author_id = None
114 if author is not None:
115 author_id = self.author_ids[author]
116
117 # Write the comment element.
118 font = (font_name, font_size, font_family)
119 self._write_comment(row, col, text, author_id, font)
120
121 self._xml_end_tag("commentList")
122
123 def _write_comment(self, row, col, text, author_id, font):
124 # Write the <comment> element.
125 ref = xl_rowcol_to_cell(row, col)
126
127 attributes = [("ref", ref)]
128
129 if author_id is not None:
130 attributes.append(("authorId", author_id))
131
132 self._xml_start_tag("comment", attributes)
133
134 # Write the text element.
135 self._write_text(text, font)
136
137 self._xml_end_tag("comment")
138
139 def _write_text(self, text, font):
140 # Write the <text> element.
141 self._xml_start_tag("text")
142
143 # Write the text r element.
144 self._write_text_r(text, font)
145
146 self._xml_end_tag("text")
147
148 def _write_text_r(self, text, font):
149 # Write the <r> element.
150 self._xml_start_tag("r")
151
152 # Write the rPr element.
153 self._write_r_pr(font)
154
155 # Write the text r element.
156 self._write_text_t(text)
157
158 self._xml_end_tag("r")
159
160 def _write_text_t(self, text):
161 # Write the text <t> element.
162 attributes = []
163
164 if preserve_whitespace(text):
165 attributes.append(("xml:space", "preserve"))
166
167 self._xml_data_element("t", text, attributes)
168
169 def _write_r_pr(self, font):
170 # Write the <rPr> element.
171 self._xml_start_tag("rPr")
172
173 # Write the sz element.
174 self._write_sz(font[1])
175
176 # Write the color element.
177 self._write_color()
178
179 # Write the rFont element.
180 self._write_r_font(font[0])
181
182 # Write the family element.
183 self._write_family(font[2])
184
185 self._xml_end_tag("rPr")
186
187 def _write_sz(self, font_size):
188 # Write the <sz> element.
189 attributes = [("val", font_size)]
190
191 self._xml_empty_tag("sz", attributes)
192
193 def _write_color(self):
194 # Write the <color> element.
195 attributes = [("indexed", 81)]
196
197 self._xml_empty_tag("color", attributes)
198
199 def _write_r_font(self, font_name):
200 # Write the <rFont> element.
201 attributes = [("val", font_name)]
202
203 self._xml_empty_tag("rFont", attributes)
204
205 def _write_family(self, font_family):
206 # Write the <family> element.
207 attributes = [("val", font_family)]
208
209 self._xml_empty_tag("family", attributes)