Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/xlsxwriter/styles.py: 56%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

381 statements  

1############################################################################### 

2# 

3# Styles - A class for writing the Excel XLSX Worksheet file. 

4# 

5# SPDX-License-Identifier: BSD-2-Clause 

6# 

7# Copyright (c) 2013-2026, John McNamara, jmcnamara@cpan.org 

8# 

9 

10from enum import Enum 

11 

12# Package imports. 

13from xlsxwriter import xmlwriter 

14 

15 

16class XFormatType(Enum): 

17 """ 

18 Enum to distinguish the type of cell xf format since style and the default 

19 (the first format) are handled slightly differently. 

20 

21 """ 

22 

23 USER = 1 

24 STYLE = 2 

25 DEFAULT = 3 

26 

27 

28class Styles(xmlwriter.XMLwriter): 

29 """ 

30 A class for writing the Excel XLSX Styles file. 

31 

32 

33 """ 

34 

35 ########################################################################### 

36 # 

37 # Public API. 

38 # 

39 ########################################################################### 

40 

41 def __init__(self) -> None: 

42 """ 

43 Constructor. 

44 

45 """ 

46 

47 super().__init__() 

48 

49 self.xf_formats = [] 

50 self.palette = [] 

51 self.font_count = 0 

52 self.num_formats = [] 

53 self.border_count = 0 

54 self.fill_count = 0 

55 self.custom_colors = [] 

56 self.dxf_formats = [] 

57 self.has_hyperlink = False 

58 self.hyperlink_font_id = 0 

59 self.has_comments = False 

60 

61 ########################################################################### 

62 # 

63 # Private API. 

64 # 

65 ########################################################################### 

66 

67 def _assemble_xml_file(self) -> None: 

68 # Assemble and write the XML file. 

69 

70 # Write the XML declaration. 

71 self._xml_declaration() 

72 

73 # Add the style sheet. 

74 self._write_style_sheet() 

75 

76 # Write the number formats. 

77 self._write_num_fmts() 

78 

79 # Write the fonts. 

80 self._write_fonts() 

81 

82 # Write the fills. 

83 self._write_fills() 

84 

85 # Write the borders element. 

86 self._write_borders() 

87 

88 # Write the cellStyleXfs element. 

89 self._write_cell_style_xfs() 

90 

91 # Write the cellXfs element. 

92 self._write_cell_xfs() 

93 

94 # Write the cellStyles element. 

95 self._write_cell_styles() 

96 

97 # Write the dxfs element. 

98 self._write_dxfs() 

99 

100 # Write the tableStyles element. 

101 self._write_table_styles() 

102 

103 # Write the colors element. 

104 self._write_colors() 

105 

106 # Close the style sheet tag. 

107 self._xml_end_tag("styleSheet") 

108 

109 # Close the file. 

110 self._xml_close() 

111 

112 def _set_style_properties(self, properties) -> None: 

113 # Pass in the Format objects and other properties used in the styles. 

114 

115 self.xf_formats = properties[0] 

116 self.palette = properties[1] 

117 self.font_count = properties[2] 

118 self.num_formats = properties[3] 

119 self.border_count = properties[4] 

120 self.fill_count = properties[5] 

121 self.custom_colors = properties[6] 

122 self.dxf_formats = properties[7] 

123 self.has_comments = properties[8] 

124 

125 ########################################################################### 

126 # 

127 # XML methods. 

128 # 

129 ########################################################################### 

130 

131 def _write_style_sheet(self) -> None: 

132 # Write the <styleSheet> element. 

133 xmlns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" 

134 

135 attributes = [("xmlns", xmlns)] 

136 self._xml_start_tag("styleSheet", attributes) 

137 

138 def _write_num_fmts(self) -> None: 

139 # Write the <numFmts> element. 

140 if not self.num_formats: 

141 return 

142 

143 attributes = [("count", len(self.num_formats))] 

144 self._xml_start_tag("numFmts", attributes) 

145 

146 # Write the numFmts elements. 

147 for index, num_format in enumerate(self.num_formats, 164): 

148 self._write_num_fmt(index, num_format) 

149 

150 self._xml_end_tag("numFmts") 

151 

152 def _write_num_fmt(self, num_fmt_id, format_code) -> None: 

153 # Write the <numFmt> element. 

154 format_codes = { 

155 0: "General", 

156 1: "0", 

157 2: "0.00", 

158 3: "#,##0", 

159 4: "#,##0.00", 

160 5: "($#,##0_);($#,##0)", 

161 6: "($#,##0_);[Red]($#,##0)", 

162 7: "($#,##0.00_);($#,##0.00)", 

163 8: "($#,##0.00_);[Red]($#,##0.00)", 

164 9: "0%", 

165 10: "0.00%", 

166 11: "0.00E+00", 

167 12: "# ?/?", 

168 13: "# ??/??", 

169 14: "m/d/yy", 

170 15: "d-mmm-yy", 

171 16: "d-mmm", 

172 17: "mmm-yy", 

173 18: "h:mm AM/PM", 

174 19: "h:mm:ss AM/PM", 

175 20: "h:mm", 

176 21: "h:mm:ss", 

177 22: "m/d/yy h:mm", 

178 37: "(#,##0_);(#,##0)", 

179 38: "(#,##0_);[Red](#,##0)", 

180 39: "(#,##0.00_);(#,##0.00)", 

181 40: "(#,##0.00_);[Red](#,##0.00)", 

182 41: '_(* #,##0_);_(* (#,##0);_(* "-"_);_(_)', 

183 42: '_($* #,##0_);_($* (#,##0);_($* "-"_);_(_)', 

184 43: '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(_)', 

185 44: '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(_)', 

186 45: "mm:ss", 

187 46: "[h]:mm:ss", 

188 47: "mm:ss.0", 

189 48: "##0.0E+0", 

190 49: "@", 

191 } 

192 

193 # Set the format code for built-in number formats. 

194 if num_fmt_id < 164: 

195 format_code = format_codes.get(num_fmt_id, "General") 

196 

197 attributes = [ 

198 ("numFmtId", num_fmt_id), 

199 ("formatCode", format_code), 

200 ] 

201 

202 self._xml_empty_tag("numFmt", attributes) 

203 

204 def _write_fonts(self) -> None: 

205 # Write the <fonts> element. 

206 if self.has_comments: 

207 # Add extra font for comments. 

208 attributes = [("count", self.font_count + 1)] 

209 else: 

210 attributes = [("count", self.font_count)] 

211 

212 self._xml_start_tag("fonts", attributes) 

213 

214 # Write the font elements for xf_format objects that have them. 

215 for xf_format in self.xf_formats: 

216 if xf_format.has_font: 

217 self._write_font(xf_format) 

218 

219 if self.has_comments: 

220 self._write_comment_font() 

221 

222 self._xml_end_tag("fonts") 

223 

224 def _write_font(self, xf_format, is_dxf_format=False) -> None: 

225 # Write the <font> element. 

226 self._xml_start_tag("font") 

227 

228 # The condense and extend elements are mainly used in dxf formats. 

229 if xf_format.font_condense: 

230 self._write_condense() 

231 

232 if xf_format.font_extend: 

233 self._write_extend() 

234 

235 if xf_format.bold: 

236 self._xml_empty_tag("b") 

237 

238 if xf_format.italic: 

239 self._xml_empty_tag("i") 

240 

241 if xf_format.font_strikeout: 

242 self._xml_empty_tag("strike") 

243 

244 if xf_format.font_outline: 

245 self._xml_empty_tag("outline") 

246 

247 if xf_format.font_shadow: 

248 self._xml_empty_tag("shadow") 

249 

250 # Handle the underline variants. 

251 if xf_format.underline: 

252 self._write_underline(xf_format.underline) 

253 

254 if xf_format.font_script == 1: 

255 self._write_vert_align("superscript") 

256 

257 if xf_format.font_script == 2: 

258 self._write_vert_align("subscript") 

259 

260 if not is_dxf_format: 

261 self._xml_empty_tag("sz", [("val", xf_format.font_size)]) 

262 

263 if xf_format.theme == -1: 

264 # Ignore for excel2003_style. 

265 pass 

266 elif xf_format.theme: 

267 self._write_color([("theme", xf_format.theme)]) 

268 elif xf_format.color_indexed: 

269 self._write_color([("indexed", xf_format.color_indexed)]) 

270 elif xf_format.font_color: 

271 color = xf_format.font_color 

272 if not color._is_automatic: 

273 self._write_color(color._attributes()) 

274 elif not is_dxf_format: 

275 self._write_color([("theme", 1)]) 

276 

277 if not is_dxf_format: 

278 self._xml_empty_tag("name", [("val", xf_format.font_name)]) 

279 

280 if xf_format.font_family: 

281 self._xml_empty_tag("family", [("val", xf_format.font_family)]) 

282 

283 if xf_format.font_charset: 

284 self._xml_empty_tag("charset", [("val", xf_format.font_charset)]) 

285 

286 if xf_format.font_scheme in ("major", "minor"): 

287 self._xml_empty_tag("scheme", [("val", xf_format.font_scheme)]) 

288 

289 if xf_format.hyperlink: 

290 self.has_hyperlink = True 

291 if self.hyperlink_font_id == 0: 

292 self.hyperlink_font_id = xf_format.font_index 

293 

294 self._xml_end_tag("font") 

295 

296 def _write_comment_font(self) -> None: 

297 # Write the <font> element for comments. 

298 self._xml_start_tag("font") 

299 

300 self._xml_empty_tag("sz", [("val", 8)]) 

301 self._write_color([("indexed", 81)]) 

302 self._xml_empty_tag("name", [("val", "Tahoma")]) 

303 self._xml_empty_tag("family", [("val", 2)]) 

304 

305 self._xml_end_tag("font") 

306 

307 def _write_underline(self, underline) -> None: 

308 # Write the underline font element. 

309 

310 if underline == 2: 

311 attributes = [("val", "double")] 

312 elif underline == 33: 

313 attributes = [("val", "singleAccounting")] 

314 elif underline == 34: 

315 attributes = [("val", "doubleAccounting")] 

316 else: 

317 # Default to single underline. 

318 attributes = [] 

319 

320 self._xml_empty_tag("u", attributes) 

321 

322 def _write_vert_align(self, val) -> None: 

323 # Write the <vertAlign> font sub-element. 

324 attributes = [("val", val)] 

325 

326 self._xml_empty_tag("vertAlign", attributes) 

327 

328 def _write_color(self, attributes) -> None: 

329 # Write the <color> element. 

330 self._xml_empty_tag("color", attributes) 

331 

332 def _write_fills(self) -> None: 

333 # Write the <fills> element. 

334 attributes = [("count", self.fill_count)] 

335 

336 self._xml_start_tag("fills", attributes) 

337 

338 # Write the default fill element. 

339 self._write_default_fill("none") 

340 self._write_default_fill("gray125") 

341 

342 # Write the fill elements for xf_format objects that have them. 

343 for xf_format in self.xf_formats: 

344 if xf_format.has_fill: 

345 self._write_fill(xf_format) 

346 

347 self._xml_end_tag("fills") 

348 

349 def _write_default_fill(self, pattern_type) -> None: 

350 # Write the <fill> element for the default fills. 

351 self._xml_start_tag("fill") 

352 self._xml_empty_tag("patternFill", [("patternType", pattern_type)]) 

353 self._xml_end_tag("fill") 

354 

355 def _write_fill(self, xf_format, is_dxf_format=False) -> None: 

356 # Write the <fill> element. 

357 pattern = xf_format.pattern 

358 bg_color = xf_format.bg_color 

359 fg_color = xf_format.fg_color 

360 

361 # Colors for dxf formats are handled differently from normal formats 

362 # since the normal xf_format reverses the meaning of BG and FG for 

363 # solid fills. 

364 if is_dxf_format: 

365 bg_color = xf_format.dxf_bg_color 

366 fg_color = xf_format.dxf_fg_color 

367 

368 patterns = ( 

369 "none", 

370 "solid", 

371 "mediumGray", 

372 "darkGray", 

373 "lightGray", 

374 "darkHorizontal", 

375 "darkVertical", 

376 "darkDown", 

377 "darkUp", 

378 "darkGrid", 

379 "darkTrellis", 

380 "lightHorizontal", 

381 "lightVertical", 

382 "lightDown", 

383 "lightUp", 

384 "lightGrid", 

385 "lightTrellis", 

386 "gray125", 

387 "gray0625", 

388 ) 

389 

390 # Special handling for pattern only case. 

391 if not fg_color and not bg_color and patterns[pattern]: 

392 self._write_default_fill(patterns[pattern]) 

393 return 

394 

395 self._xml_start_tag("fill") 

396 

397 # The "none" pattern is handled differently for dxf formats. 

398 if is_dxf_format and pattern <= 1: 

399 self._xml_start_tag("patternFill") 

400 else: 

401 self._xml_start_tag("patternFill", [("patternType", patterns[pattern])]) 

402 

403 if fg_color and not fg_color._is_automatic: 

404 self._xml_empty_tag("fgColor", fg_color._attributes()) 

405 

406 if bg_color: 

407 if not bg_color._is_automatic: 

408 self._xml_empty_tag("bgColor", bg_color._attributes()) 

409 else: 

410 if not is_dxf_format and pattern <= 1: 

411 self._xml_empty_tag("bgColor", [("indexed", 64)]) 

412 

413 self._xml_end_tag("patternFill") 

414 self._xml_end_tag("fill") 

415 

416 def _write_borders(self) -> None: 

417 # Write the <borders> element. 

418 attributes = [("count", self.border_count)] 

419 

420 self._xml_start_tag("borders", attributes) 

421 

422 # Write the border elements for xf_format objects that have them. 

423 for xf_format in self.xf_formats: 

424 if xf_format.has_border: 

425 self._write_border(xf_format) 

426 

427 self._xml_end_tag("borders") 

428 

429 def _write_border(self, xf_format, is_dxf_format=False) -> None: 

430 # Write the <border> element. 

431 attributes = [] 

432 

433 # Diagonal borders add attributes to the <border> element. 

434 if xf_format.diag_type == 1: 

435 attributes.append(("diagonalUp", 1)) 

436 elif xf_format.diag_type == 2: 

437 attributes.append(("diagonalDown", 1)) 

438 elif xf_format.diag_type == 3: 

439 attributes.append(("diagonalUp", 1)) 

440 attributes.append(("diagonalDown", 1)) 

441 

442 # Ensure that a default diag border is set if the diag type is set. 

443 if xf_format.diag_type and not xf_format.diag_border: 

444 xf_format.diag_border = 1 

445 

446 # Write the start border tag. 

447 self._xml_start_tag("border", attributes) 

448 

449 # Write the <border> sub elements. 

450 self._write_sub_border("left", xf_format.left, xf_format.left_color) 

451 

452 self._write_sub_border("right", xf_format.right, xf_format.right_color) 

453 

454 self._write_sub_border("top", xf_format.top, xf_format.top_color) 

455 

456 self._write_sub_border("bottom", xf_format.bottom, xf_format.bottom_color) 

457 

458 # Condition DXF formats don't allow diagonal borders. 

459 if not is_dxf_format: 

460 self._write_sub_border( 

461 "diagonal", xf_format.diag_border, xf_format.diag_color 

462 ) 

463 

464 if is_dxf_format: 

465 self._write_sub_border("vertical", None, None) 

466 self._write_sub_border("horizontal", None, None) 

467 

468 self._xml_end_tag("border") 

469 

470 def _write_sub_border(self, border_type, style, color) -> None: 

471 # Write the <border> sub elements such as <right>, <top>, etc. 

472 attributes = [] 

473 

474 if not style: 

475 self._xml_empty_tag(border_type) 

476 return 

477 

478 border_styles = ( 

479 "none", 

480 "thin", 

481 "medium", 

482 "dashed", 

483 "dotted", 

484 "thick", 

485 "double", 

486 "hair", 

487 "mediumDashed", 

488 "dashDot", 

489 "mediumDashDot", 

490 "dashDotDot", 

491 "mediumDashDotDot", 

492 "slantDashDot", 

493 ) 

494 

495 attributes.append(("style", border_styles[style])) 

496 

497 self._xml_start_tag(border_type, attributes) 

498 

499 if color and not color._is_automatic: 

500 self._xml_empty_tag("color", color._attributes()) 

501 else: 

502 self._xml_empty_tag("color", [("auto", 1)]) 

503 

504 self._xml_end_tag(border_type) 

505 

506 def _write_cell_style_xfs(self) -> None: 

507 # Write the <cellStyleXfs> element. 

508 count = 1 

509 

510 if self.has_hyperlink: 

511 count = 2 

512 

513 attributes = [("count", count)] 

514 

515 self._xml_start_tag("cellStyleXfs", attributes) 

516 style_format = self.xf_formats[0] 

517 self._write_xf(style_format, XFormatType.STYLE) 

518 

519 if self.has_hyperlink: 

520 self._write_style_xf(True, self.hyperlink_font_id) 

521 

522 self._xml_end_tag("cellStyleXfs") 

523 

524 def _write_cell_xfs(self) -> None: 

525 # Write the <cellXfs> element. 

526 formats = self.xf_formats 

527 

528 # Workaround for when the last xf_format is used for the comment font 

529 # and shouldn't be used for cellXfs. 

530 last_format = formats[-1] 

531 if last_format.font_only: 

532 formats.pop() 

533 

534 attributes = [("count", len(formats))] 

535 self._xml_start_tag("cellXfs", attributes) 

536 

537 # Write the xf elements. 

538 cell_type = XFormatType.DEFAULT 

539 for xf_format in formats: 

540 self._write_xf(xf_format, cell_type) 

541 cell_type = XFormatType.USER 

542 

543 self._xml_end_tag("cellXfs") 

544 

545 def _write_style_xf(self, has_hyperlink=False, font_id=0) -> None: 

546 # Write the style <xf> element. 

547 num_fmt_id = 0 

548 fill_id = 0 

549 border_id = 0 

550 

551 attributes = [ 

552 ("numFmtId", num_fmt_id), 

553 ("fontId", font_id), 

554 ("fillId", fill_id), 

555 ("borderId", border_id), 

556 ] 

557 

558 if has_hyperlink: 

559 attributes.append(("applyNumberFormat", 0)) 

560 attributes.append(("applyFill", 0)) 

561 attributes.append(("applyBorder", 0)) 

562 attributes.append(("applyAlignment", 0)) 

563 attributes.append(("applyProtection", 0)) 

564 

565 self._xml_start_tag("xf", attributes) 

566 self._xml_empty_tag("alignment", [("vertical", "top")]) 

567 self._xml_empty_tag("protection", [("locked", 0)]) 

568 self._xml_end_tag("xf") 

569 

570 else: 

571 self._xml_empty_tag("xf", attributes) 

572 

573 def _write_xf(self, xf_format, xf_type: XFormatType) -> None: 

574 # Write the <xf> element. 

575 xf_id = xf_format.xf_id 

576 font_id = xf_format.font_index 

577 fill_id = xf_format.fill_index 

578 border_id = xf_format.border_index 

579 num_fmt_id = xf_format.num_format_index 

580 

581 has_checkbox = xf_format.checkbox 

582 has_alignment = False 

583 has_protection = False 

584 

585 attributes = [ 

586 ("numFmtId", num_fmt_id), 

587 ("fontId", font_id), 

588 ("fillId", fill_id), 

589 ("borderId", border_id), 

590 ] 

591 

592 if xf_type != XFormatType.STYLE: 

593 attributes.append(("xfId", xf_id)) 

594 

595 if xf_format.quote_prefix: 

596 attributes.append(("quotePrefix", 1)) 

597 

598 if xf_format.num_format_index > 0: 

599 attributes.append(("applyNumberFormat", 1)) 

600 

601 # Add applyFont attribute if XF format uses a font element. 

602 if xf_format.font_index > 0 and not xf_format.hyperlink: 

603 attributes.append(("applyFont", 1)) 

604 

605 # Add applyFill attribute if XF format uses a fill element. 

606 if xf_format.fill_index > 0: 

607 attributes.append(("applyFill", 1)) 

608 

609 # Add applyBorder attribute if XF format uses a border element. 

610 if xf_format.border_index > 0: 

611 attributes.append(("applyBorder", 1)) 

612 

613 # Check if XF format has alignment properties set. 

614 apply_align, align = xf_format._get_align_properties() 

615 

616 # Check if an alignment sub-element should be written. 

617 if apply_align and align: 

618 has_alignment = True 

619 

620 # We can also have applyAlignment without a sub-element. 

621 if (apply_align or xf_format.hyperlink) and xf_type == XFormatType.USER: 

622 attributes.append(("applyAlignment", 1)) 

623 

624 # Check for cell protection properties. 

625 protection = xf_format._get_protection_properties() 

626 

627 if protection or xf_format.hyperlink: 

628 attributes.append(("applyProtection", 1)) 

629 

630 if not xf_format.hyperlink: 

631 has_protection = True 

632 

633 # Write XF with sub-elements if required. 

634 if has_alignment or has_protection or has_checkbox: 

635 self._xml_start_tag("xf", attributes) 

636 

637 if has_alignment: 

638 self._xml_empty_tag("alignment", align) 

639 

640 if has_protection: 

641 self._xml_empty_tag("protection", protection) 

642 

643 if has_checkbox: 

644 self._write_xf_format_extensions() 

645 

646 self._xml_end_tag("xf") 

647 else: 

648 self._xml_empty_tag("xf", attributes) 

649 

650 def _write_cell_styles(self) -> None: 

651 # Write the <cellStyles> element. 

652 count = 1 

653 

654 if self.has_hyperlink: 

655 count = 2 

656 

657 attributes = [("count", count)] 

658 

659 self._xml_start_tag("cellStyles", attributes) 

660 

661 if self.has_hyperlink: 

662 self._write_cell_style("Hyperlink", 1, 8) 

663 

664 self._write_cell_style() 

665 

666 self._xml_end_tag("cellStyles") 

667 

668 def _write_cell_style(self, name="Normal", xf_id=0, builtin_id=0) -> None: 

669 # Write the <cellStyle> element. 

670 attributes = [ 

671 ("name", name), 

672 ("xfId", xf_id), 

673 ("builtinId", builtin_id), 

674 ] 

675 

676 self._xml_empty_tag("cellStyle", attributes) 

677 

678 def _write_dxfs(self) -> None: 

679 # Write the <dxfs> element. 

680 formats = self.dxf_formats 

681 count = len(formats) 

682 

683 attributes = [("count", len(formats))] 

684 

685 if count: 

686 self._xml_start_tag("dxfs", attributes) 

687 

688 # Write the font elements for xf_format objects that have them. 

689 for dxf_format in self.dxf_formats: 

690 self._xml_start_tag("dxf") 

691 if dxf_format.has_dxf_font: 

692 self._write_font(dxf_format, True) 

693 

694 if dxf_format.num_format_index: 

695 self._write_num_fmt( 

696 dxf_format.num_format_index, dxf_format.num_format 

697 ) 

698 

699 if dxf_format.has_dxf_fill: 

700 self._write_fill(dxf_format, True) 

701 

702 if dxf_format.has_dxf_border: 

703 self._write_border(dxf_format, True) 

704 

705 if dxf_format.checkbox: 

706 self._write_dxf_format_extensions() 

707 

708 self._xml_end_tag("dxf") 

709 

710 self._xml_end_tag("dxfs") 

711 else: 

712 self._xml_empty_tag("dxfs", attributes) 

713 

714 def _write_table_styles(self) -> None: 

715 # Write the <tableStyles> element. 

716 count = 0 

717 default_table_style = "TableStyleMedium9" 

718 default_pivot_style = "PivotStyleLight16" 

719 

720 attributes = [ 

721 ("count", count), 

722 ("defaultTableStyle", default_table_style), 

723 ("defaultPivotStyle", default_pivot_style), 

724 ] 

725 

726 self._xml_empty_tag("tableStyles", attributes) 

727 

728 def _write_colors(self) -> None: 

729 # Write the <colors> element. 

730 custom_colors = self.custom_colors 

731 

732 if not custom_colors: 

733 return 

734 

735 self._xml_start_tag("colors") 

736 self._write_mru_colors(custom_colors) 

737 self._xml_end_tag("colors") 

738 

739 def _write_mru_colors(self, custom_colors) -> None: 

740 # Write the <mruColors> element for the most recently used colors. 

741 

742 # Write the custom custom_colors in reverse order. 

743 custom_colors.reverse() 

744 

745 # Limit the mruColors to the last 10. 

746 if len(custom_colors) > 10: 

747 custom_colors = custom_colors[0:10] 

748 

749 self._xml_start_tag("mruColors") 

750 

751 # Write the custom custom_colors in reverse order. 

752 for color in custom_colors: 

753 # For backwards compatibility convert possible 

754 self._write_color(color._attributes()) 

755 

756 self._xml_end_tag("mruColors") 

757 

758 def _write_condense(self) -> None: 

759 # Write the <condense> element. 

760 attributes = [("val", 0)] 

761 

762 self._xml_empty_tag("condense", attributes) 

763 

764 def _write_extend(self) -> None: 

765 # Write the <extend> element. 

766 attributes = [("val", 0)] 

767 

768 self._xml_empty_tag("extend", attributes) 

769 

770 def _write_xf_format_extensions(self) -> None: 

771 # Write the xfComplement <extLst> elements. 

772 schema = "http://schemas.microsoft.com/office/spreadsheetml" 

773 attributes = [ 

774 ("uri", "{C7286773-470A-42A8-94C5-96B5CB345126}"), 

775 ( 

776 "xmlns:xfpb", 

777 schema + "/2022/featurepropertybag", 

778 ), 

779 ] 

780 

781 self._xml_start_tag("extLst") 

782 self._xml_start_tag("ext", attributes) 

783 

784 self._xml_empty_tag("xfpb:xfComplement", [("i", "0")]) 

785 

786 self._xml_end_tag("ext") 

787 self._xml_end_tag("extLst") 

788 

789 def _write_dxf_format_extensions(self) -> None: 

790 # Write the DXFComplement <extLst> elements. 

791 schema = "http://schemas.microsoft.com/office/spreadsheetml" 

792 attributes = [ 

793 ("uri", "{0417FA29-78FA-4A13-93AC-8FF0FAFDF519}"), 

794 ( 

795 "xmlns:xfpb", 

796 schema + "/2022/featurepropertybag", 

797 ), 

798 ] 

799 

800 self._xml_start_tag("extLst") 

801 self._xml_start_tag("ext", attributes) 

802 

803 self._xml_empty_tag("xfpb:DXFComplement", [("i", "0")]) 

804 

805 self._xml_end_tag("ext") 

806 self._xml_end_tag("extLst")