rust_xlsxwriter/table.rs
1// table - A module for creating the Excel Table.xml file.
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4//
5// Copyright 2022-2025, John McNamara, jmcnamara@cpan.org
6
7#![warn(missing_docs)]
8
9mod tests;
10
11use std::io::Cursor;
12use std::{collections::HashSet, fmt};
13
14use crate::xmlwriter::{
15 xml_data_element_only, xml_declaration, xml_empty_tag, xml_end_tag, xml_start_tag,
16};
17use crate::{utility::ToXmlBoolean, CellRange, Format, Formula, RowNum, XlsxError};
18
19/// The `Table` struct represents a worksheet table.
20///
21/// Tables in Excel are a way of grouping a range of cells into a single entity
22/// that has common formatting or that can be referenced in formulas. Tables
23/// can have column headers, autofilters, total rows, column formulas, and
24/// different formatting styles.
25///
26/// The image below shows a default table in Excel with the default properties
27/// displayed in the ribbon bar.
28///
29/// <img src="https://rustxlsxwriter.github.io/images/table_intro.png">
30///
31/// A table is added to a worksheet via the
32/// [`Worksheet::add_table()`](crate::Worksheet::add_table) method. The headers
33/// and total row of a table should be configured via a `Table` struct, but the
34/// table data can be added using standard
35/// [`Worksheet::write()`](crate::Worksheet::write) methods:
36///
37/// ```
38/// # // This code is available in examples/doc_table_set_columns.rs
39/// #
40/// use rust_xlsxwriter::{Table, TableColumn, TableFunction, Workbook, XlsxError};
41///
42/// fn main() -> Result<(), XlsxError> {
43/// // Create a new Excel file object.
44/// let mut workbook = Workbook::new();
45///
46/// // Add a worksheet to the workbook.
47/// let worksheet = workbook.add_worksheet();
48///
49/// // Some sample data for the table.
50/// let items = ["Apples", "Pears", "Bananas", "Oranges"];
51/// let data = [
52/// [10000, 5000, 8000, 6000],
53/// [2000, 3000, 4000, 5000],
54/// [6000, 6000, 6500, 6000],
55/// [500, 300, 200, 700],
56/// ];
57///
58/// // Write the table data.
59/// worksheet.write_column(3, 1, items)?;
60/// worksheet.write_row_matrix(3, 2, data)?;
61///
62/// // Set the column widths for clarity.
63/// worksheet.set_column_range_width(1, 6, 12)?;
64///
65/// // Create a new table and configure it.
66/// let columns = vec![
67/// TableColumn::new()
68/// .set_header("Product")
69/// .set_total_label("Totals"),
70/// TableColumn::new()
71/// .set_header("Quarter 1")
72/// .set_total_function(TableFunction::Sum),
73/// TableColumn::new()
74/// .set_header("Quarter 2")
75/// .set_total_function(TableFunction::Sum),
76/// TableColumn::new()
77/// .set_header("Quarter 3")
78/// .set_total_function(TableFunction::Sum),
79/// TableColumn::new()
80/// .set_header("Quarter 4")
81/// .set_total_function(TableFunction::Sum),
82/// TableColumn::new()
83/// .set_header("Year")
84/// .set_total_function(TableFunction::Sum)
85/// .set_formula("SUM(Table1[@[Quarter 1]:[Quarter 4]])"),
86/// ];
87///
88/// let table = Table::new().set_columns(&columns).set_total_row(true);
89///
90/// // Add the table to the worksheet.
91/// worksheet.add_table(2, 1, 7, 6, &table)?;
92///
93/// // Save the file to disk.
94/// workbook.save("tables.xlsx")?;
95///
96/// Ok(())
97/// }
98/// ```
99///
100/// Output file:
101///
102/// <img src="https://rustxlsxwriter.github.io/images/table_set_columns.png">
103///
104/// For more information on tables see the Microsoft documentation on [Overview
105/// of Excel tables].
106///
107/// [Overview of Excel tables]:
108/// https://support.microsoft.com/en-us/office/overview-of-excel-tables-7ab0bb7d-3a9e-4b56-a3c9-6c94334e492c
109///
110#[derive(Clone)]
111pub struct Table {
112 pub(crate) writer: Cursor<Vec<u8>>,
113
114 pub(crate) columns: Vec<TableColumn>,
115
116 pub(crate) index: u32,
117 pub(crate) name: String,
118 pub(crate) style: TableStyle,
119
120 pub(crate) cell_range: CellRange,
121
122 pub(crate) show_header_row: bool,
123 pub(crate) show_total_row: bool,
124 pub(crate) show_first_column: bool,
125 pub(crate) show_last_column: bool,
126 pub(crate) show_banded_rows: bool,
127 pub(crate) show_banded_columns: bool,
128 pub(crate) show_autofilter: bool,
129 pub(crate) is_serde_table: bool,
130}
131
132impl Table {
133 // -----------------------------------------------------------------------
134 // Public (and crate public) methods.
135 // -----------------------------------------------------------------------
136
137 /// Create a new Table struct instance.
138 ///
139 /// Create a table that can be added to a data range of a worksheet. The
140 /// headers, totals, formulas, and other properties can be set via the
141 /// `Table::*` methods shown below. The data should be added to the table
142 /// region using the standard
143 /// [`Worksheet::write()`](crate::Worksheet::write) methods.
144 ///
145 /// # Examples
146 ///
147 /// Example of creating a new table and adding it to a worksheet.
148 ///
149 /// ```
150 /// # // This code is available in examples/doc_table_set_header_row2.rs
151 /// #
152 /// use rust_xlsxwriter::{Table, Workbook, XlsxError};
153 ///
154 /// fn main() -> Result<(), XlsxError> {
155 /// // Create a new Excel file object.
156 /// let mut workbook = Workbook::new();
157 ///
158 /// // Add a worksheet to the workbook.
159 /// let worksheet = workbook.add_worksheet();
160 ///
161 /// // Some sample data for the table.
162 /// let items = ["Apples", "Pears", "Bananas", "Oranges"];
163 /// let data = [
164 /// [10000, 5000, 8000, 6000],
165 /// [2000, 3000, 4000, 5000],
166 /// [6000, 6000, 6500, 6000],
167 /// [500, 300, 200, 700],
168 /// ];
169 ///
170 /// // Write the table data.
171 /// worksheet.write_column(3, 1, items)?;
172 /// worksheet.write_row_matrix(3, 2, data)?;
173 ///
174 /// // Set the column widths for clarity.
175 /// worksheet.set_column_range_width(1, 6, 12)?;
176 ///
177 /// // Create a new table.
178 /// let table = Table::new();
179 ///
180 /// // Add the table to the worksheet.
181 /// worksheet.add_table(2, 1, 6, 5, &table)?;
182 ///
183 /// // Save the file to disk.
184 /// workbook.save("tables.xlsx")?;
185 ///
186 /// Ok(())
187 /// }
188 /// ```
189 ///
190 /// Output file:
191 ///
192 /// <img
193 /// src="https://rustxlsxwriter.github.io/images/table_set_header_row2.png">
194 ///
195 ///
196 #[allow(clippy::new_without_default)]
197 pub fn new() -> Table {
198 let writer = Cursor::new(Vec::with_capacity(2048));
199
200 Table {
201 writer,
202 columns: vec![],
203 index: 0,
204 name: String::new(),
205 style: TableStyle::Medium9,
206 cell_range: CellRange::default(),
207 show_first_column: false,
208 show_last_column: false,
209 show_banded_rows: true,
210 show_banded_columns: false,
211 show_autofilter: true,
212 show_header_row: true,
213 show_total_row: false,
214 is_serde_table: false,
215 }
216 }
217
218 /// Turn on/off the header row for a table.
219 ///
220 /// Turn on or off the header row in the table. The header row displays the
221 /// column names and, unless it is turned off, an autofilter. It is on by
222 /// default.
223 ///
224 /// The header row will display default captions such as `Column 1`, `Column
225 /// 2`, etc. These captions can be overridden using the
226 /// [`Table::set_columns()`] method, see the examples below. They shouldn't
227 /// be written or overwritten using standard
228 /// [`Worksheet::write()`](crate::Worksheet::write) methods since that will
229 /// cause a warning when the file is loaded in Excel.
230 ///
231 /// # Parameters
232 ///
233 /// - `enable`: Turn the property on/off. It is on by default.
234 ///
235 /// # Examples
236 ///
237 /// Example of adding a worksheet table with a default header.
238 ///
239 /// ```
240 /// # // This code is available in examples/doc_table_set_header_row2.rs
241 /// #
242 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
243 /// #
244 /// # fn main() -> Result<(), XlsxError> {
245 /// # // Create a new Excel file object.
246 /// # let mut workbook = Workbook::new();
247 /// #
248 /// # // Add a worksheet to the workbook.
249 /// # let worksheet = workbook.add_worksheet();
250 /// #
251 /// # // Some sample data for the table.
252 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
253 /// # let data = [
254 /// # [10000, 5000, 8000, 6000],
255 /// # [2000, 3000, 4000, 5000],
256 /// # [6000, 6000, 6500, 6000],
257 /// # [500, 300, 200, 700],
258 /// # ];
259 /// #
260 /// # // Write the table data.
261 /// # worksheet.write_column(3, 1, items)?;
262 /// # worksheet.write_row_matrix(3, 2, data)?;
263 /// #
264 /// # // Set the column widths for clarity.
265 /// # worksheet.set_column_range_width(1, 6, 12)?;
266 /// #
267 /// // Create a new table.
268 /// let table = Table::new();
269 ///
270 /// // Add the table to the worksheet.
271 /// worksheet.add_table(2, 1, 6, 5, &table)?;
272 /// #
273 /// # // Save the file to disk.
274 /// # workbook.save("tables.xlsx")?;
275 /// #
276 /// # Ok(())
277 /// # }
278 /// ```
279 ///
280 /// Output file:
281 ///
282 /// <img
283 /// src="https://rustxlsxwriter.github.io/images/table_set_header_row2.png">
284 ///
285 ///
286 /// Example of turning off the default header on a worksheet table. Note,
287 /// that the table range has been adjusted in relation to the previous
288 /// example to account for the missing header.
289 ///
290 /// ```
291 /// # // This code is available in examples/doc_table_set_header_row.rs
292 /// #
293 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
294 /// #
295 /// # fn main() -> Result<(), XlsxError> {
296 /// # // Create a new Excel file object.
297 /// # let mut workbook = Workbook::new();
298 /// #
299 /// # // Add a worksheet to the workbook.
300 /// # let worksheet = workbook.add_worksheet();
301 /// #
302 /// # // Some sample data for the table.
303 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
304 /// # let data = [
305 /// # [10000, 5000, 8000, 6000],
306 /// # [2000, 3000, 4000, 5000],
307 /// # [6000, 6000, 6500, 6000],
308 /// # [500, 300, 200, 700],
309 /// # ];
310 /// #
311 /// # // Write the table data.
312 /// # worksheet.write_column(2, 1, items)?;
313 /// # worksheet.write_row_matrix(2, 2, data)?;
314 /// #
315 /// # // Set the column widths for clarity.
316 /// # worksheet.set_column_range_width(1, 6, 12)?;
317 /// #
318 /// // Create a new table and configure the header.
319 /// let table = Table::new().set_header_row(false);
320 ///
321 /// // Add the table to the worksheet.
322 /// worksheet.add_table(2, 1, 5, 5, &table)?;
323 /// #
324 /// # // Save the file to disk.
325 /// # workbook.save("tables.xlsx")?;
326 /// #
327 /// # Ok(())
328 /// # }
329 /// ```
330 ///
331 /// Output file:
332 ///
333 /// <img
334 /// src="https://rustxlsxwriter.github.io/images/table_set_header_row.png">
335 ///
336 /// Example of adding a worksheet table with a user defined header captions.
337 ///
338 /// ```
339 /// # // This code is available in examples/doc_table_set_header_row3.rs
340 /// #
341 /// # use rust_xlsxwriter::{Table, TableColumn, Workbook, XlsxError};
342 /// #
343 /// # fn main() -> Result<(), XlsxError> {
344 /// # // Create a new Excel file object.
345 /// # let mut workbook = Workbook::new();
346 /// #
347 /// # // Add a worksheet to the workbook.
348 /// # let worksheet = workbook.add_worksheet();
349 /// #
350 /// # // Some sample data for the table.
351 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
352 /// # let data = [
353 /// # [10000, 5000, 8000, 6000],
354 /// # [2000, 3000, 4000, 5000],
355 /// # [6000, 6000, 6500, 6000],
356 /// # [500, 300, 200, 700],
357 /// # ];
358 /// #
359 /// # // Write the table data.
360 /// # worksheet.write_column(3, 1, items)?;
361 /// # worksheet.write_row_matrix(3, 2, data)?;
362 /// #
363 /// # // Set the column widths for clarity.
364 /// # worksheet.set_column_range_width(1, 6, 12)?;
365 /// #
366 /// // Set the captions for the header row.
367 /// let columns = vec![
368 /// TableColumn::new().set_header("Product"),
369 /// TableColumn::new().set_header("Quarter 1"),
370 /// TableColumn::new().set_header("Quarter 2"),
371 /// TableColumn::new().set_header("Quarter 3"),
372 /// TableColumn::new().set_header("Quarter 4"),
373 /// ];
374 ///
375 /// // Create a new table and configure the column headers.
376 /// let table = Table::new().set_columns(&columns);
377 ///
378 /// // Add the table to the worksheet.
379 /// worksheet.add_table(2, 1, 6, 5, &table)?;
380 /// #
381 /// # // Save the file to disk.
382 /// # workbook.save("tables.xlsx")?;
383 /// #
384 /// # Ok(())
385 /// # }
386 /// ```
387 ///
388 /// Output file:
389 ///
390 /// <img
391 /// src="https://rustxlsxwriter.github.io/images/table_set_header_row3.png">
392 ///
393 pub fn set_header_row(mut self, enable: bool) -> Table {
394 self.show_header_row = enable;
395
396 // The table autofilter should be off if the header is off so that it
397 // isn't included in the autofit() calculation.
398 if !self.show_header_row {
399 self.show_autofilter = false;
400 }
401
402 self
403 }
404
405 /// Turn on a totals row for a table.
406 ///
407 /// The `set_total_row()` method can be used to turn on the total row in the
408 /// last row of a table. The total row is distinguished from the other rows
409 /// by a different formatting and with dropdown `SUBTOTAL()` functions.
410 ///
411 /// Note, you will need to use [`TableColumn`] methods to populate this row.
412 /// Overwriting the total row cells with `worksheet.write()` calls will
413 /// cause Excel to warn that the table is corrupt when loading the file.
414 ///
415 /// # Parameters
416 ///
417 /// - `enable`: Turn the property on/off. It is off by default.
418 ///
419 ///
420 /// # Examples
421 ///
422 /// Example of turning on the "totals" row at the bottom of a worksheet
423 /// table. Note, this just turns on the total run it doesn't add captions or
424 /// subtotal functions. See the next example below.
425 ///
426 /// ```
427 /// # // This code is available in examples/doc_table_set_total_row.rs
428 /// #
429 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
430 /// #
431 /// # fn main() -> Result<(), XlsxError> {
432 /// # // Create a new Excel file object.
433 /// # let mut workbook = Workbook::new();
434 /// #
435 /// # // Add a worksheet to the workbook.
436 /// # let worksheet = workbook.add_worksheet();
437 /// #
438 /// # // Some sample data for the table.
439 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
440 /// # let data = [
441 /// # [10000, 5000, 8000, 6000],
442 /// # [2000, 3000, 4000, 5000],
443 /// # [6000, 6000, 6500, 6000],
444 /// # [500, 300, 200, 700],
445 /// # ];
446 /// #
447 /// # // Write the table data.
448 /// # worksheet.write_column(3, 1, items)?;
449 /// # worksheet.write_row_matrix(3, 2, data)?;
450 /// #
451 /// # // Set the column widths for clarity.
452 /// # worksheet.set_column_range_width(1, 6, 12)?;
453 /// #
454 /// // Create a new table and configure the total row.
455 /// let table = Table::new().set_total_row(true);
456 ///
457 /// // Add the table to the worksheet.
458 /// worksheet.add_table(2, 1, 7, 5, &table)?;
459 /// #
460 /// # // Save the file to disk.
461 /// # workbook.save("tables.xlsx")?;
462 /// #
463 /// # Ok(())
464 /// # }
465 /// ```
466 ///
467 /// Output file:
468 ///
469 /// <img
470 /// src="https://rustxlsxwriter.github.io/images/table_set_total_row.png">
471 ///
472 /// Example of turning on the "totals" row at the bottom of a worksheet
473 /// table with captions and subtotal functions.
474 ///
475 /// ```
476 /// # // This code is available in examples/doc_table_set_total_row2.rs
477 /// #
478 /// # use rust_xlsxwriter::{Formula, Table, TableColumn, TableFunction, Workbook, XlsxError};
479 /// #
480 /// # fn main() -> Result<(), XlsxError> {
481 /// # // Create a new Excel file object.
482 /// # let mut workbook = Workbook::new();
483 /// #
484 /// # // Add a worksheet to the workbook.
485 /// # let worksheet = workbook.add_worksheet();
486 /// #
487 /// # // Some sample data for the table.
488 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
489 /// # let data = [
490 /// # [10000, 5000, 8000, 6000],
491 /// # [2000, 3000, 4000, 5000],
492 /// # [6000, 6000, 6500, 6000],
493 /// # [500, 300, 200, 700],
494 /// # ];
495 /// #
496 /// # // Write the table data.
497 /// # worksheet.write_column(3, 1, items)?;
498 /// # worksheet.write_row_matrix(3, 2, data)?;
499 /// #
500 /// # // Set the column widths for clarity.
501 /// # worksheet.set_column_range_width(1, 6, 12)?;
502 /// #
503 /// // Set the caption and subtotal in the total row.
504 /// let columns = vec![
505 /// TableColumn::new().set_total_label("Totals"),
506 /// TableColumn::new().set_total_function(TableFunction::Sum),
507 /// TableColumn::new().set_total_function(TableFunction::Sum),
508 /// TableColumn::new().set_total_function(TableFunction::Sum),
509 /// // Use a custom formula to get a similar summation.
510 /// TableColumn::new()
511 /// .set_total_function(TableFunction::Custom(Formula::new("SUM([Column5])"))),
512 /// ];
513 ///
514 /// // Create a new table and configure the total row.
515 /// let table = Table::new().set_total_row(true).set_columns(&columns);
516 ///
517 /// // Add the table to the worksheet.
518 /// worksheet.add_table(2, 1, 7, 5, &table)?;
519 /// #
520 /// # // Save the file to disk.
521 /// # workbook.save("tables.xlsx")?;
522 /// #
523 /// # Ok(())
524 /// # }
525 /// ```
526 ///
527 /// Output file:
528 ///
529 /// <img
530 /// src="https://rustxlsxwriter.github.io/images/table_set_total_row2.png">
531 ///
532 pub fn set_total_row(mut self, enable: bool) -> Table {
533 self.show_total_row = enable;
534 self
535 }
536
537 /// Turn on/off banded rows for a table.
538 ///
539 /// By default, Excel uses "banded" rows of alternating colors in a table to
540 /// distinguish each data row, like this:
541 ///
542 /// <img
543 /// src="https://rustxlsxwriter.github.io/images/table_set_header_row2.png">
544 ///
545 /// If you prefer not to have this type of formatting, you can turn it off,
546 /// see the example below.
547 ///
548 /// Note, you can also select a table style without banded rows using the
549 /// [`Table::set_style()`] method.
550 ///
551 /// # Parameters
552 ///
553 /// - `enable`: Turn the property on/off. It is on by default.
554 /// # Examples
555 ///
556 /// Example of turning off the banded rows property in a worksheet table.
557 ///
558 /// ```
559 /// # // This code is available in examples/doc_table_set_banded_rows.rs
560 /// #
561 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
562 /// #
563 /// # fn main() -> Result<(), XlsxError> {
564 /// # // Create a new Excel file object.
565 /// # let mut workbook = Workbook::new();
566 /// #
567 /// # // Add a worksheet to the workbook.
568 /// # let worksheet = workbook.add_worksheet();
569 /// #
570 /// # // Some sample data for the table.
571 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
572 /// # let data = [
573 /// # [10000, 5000, 8000, 6000],
574 /// # [2000, 3000, 4000, 5000],
575 /// # [6000, 6000, 6500, 6000],
576 /// # [500, 300, 200, 700],
577 /// # ];
578 /// #
579 /// # // Write the table data.
580 /// # worksheet.write_column(3, 1, items)?;
581 /// # worksheet.write_row_matrix(3, 2, data)?;
582 /// #
583 /// # // Set the column widths for clarity.
584 /// # worksheet.set_column_range_width(1, 6, 12)?;
585 /// #
586 /// // Create a new table and configure the banded rows.
587 /// let table = Table::new().set_banded_rows(false);
588 ///
589 /// // Add the table to the worksheet.
590 /// worksheet.add_table(2, 1, 6, 5, &table)?;
591 /// #
592 /// # // Save the file to disk.
593 /// # workbook.save("tables.xlsx")?;
594 /// #
595 /// # Ok(())
596 /// # }
597 /// ```
598 ///
599 /// Output file:
600 ///
601 /// <img
602 /// src="https://rustxlsxwriter.github.io/images/table_set_banded_rows.png">
603 ///
604 pub fn set_banded_rows(mut self, enable: bool) -> Table {
605 self.show_banded_rows = enable;
606 self
607 }
608
609 /// Turn on/off banded columns for a table.
610 ///
611 /// By default, Excel uses the same format color for each data column in a
612 /// table but alternates the color of rows. If you wish, you can set "banded"
613 /// columns of alternating colors in a table to distinguish each data column.
614 ///
615 /// # Parameters
616 ///
617 /// - `enable`: Turn the property on/off. It is off by default.
618 ///
619 /// # Examples
620 ///
621 /// Example of turning on the banded columns property in a worksheet table. These
622 /// are normally off by default,
623 ///
624 /// ```
625 /// # // This code is available in examples/doc_table_set_banded_columns.rs
626 /// #
627 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
628 /// #
629 /// # fn main() -> Result<(), XlsxError> {
630 /// # // Create a new Excel file object.
631 /// # let mut workbook = Workbook::new();
632 /// #
633 /// # // Add a worksheet to the workbook.
634 /// # let worksheet = workbook.add_worksheet();
635 /// #
636 /// # // Some sample data for the table.
637 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
638 /// # let data = [
639 /// # [10000, 5000, 8000, 6000],
640 /// # [2000, 3000, 4000, 5000],
641 /// # [6000, 6000, 6500, 6000],
642 /// # [500, 300, 200, 700],
643 /// # ];
644 /// #
645 /// # // Write the table data.
646 /// # worksheet.write_column(3, 1, items)?;
647 /// # worksheet.write_row_matrix(3, 2, data)?;
648 /// #
649 /// # // Set the column widths for clarity.
650 /// # worksheet.set_column_range_width(1, 6, 12)?;
651 /// #
652 /// // Create a new table and configure the banded columns (but turn off banded
653 /// // rows for clarity).
654 /// let table = Table::new().set_banded_columns(true).set_banded_rows(false);
655 ///
656 /// // Add the table to the worksheet.
657 /// worksheet.add_table(2, 1, 6, 5, &table)?;
658 /// #
659 /// # // Save the file to disk.
660 /// # workbook.save("tables.xlsx")?;
661 /// #
662 /// # Ok(())
663 /// # }
664 /// ```
665 ///
666 /// Output file:
667 ///
668 /// <img src="https://rustxlsxwriter.github.io/images/table_set_banded_columns.png">
669 ///
670 pub fn set_banded_columns(mut self, enable: bool) -> Table {
671 self.show_banded_columns = enable;
672 self
673 }
674
675 /// Turn on/off the first column highlighting for a table.
676 ///
677 /// The first column of a worksheet table is often used for a list of items,
678 /// whereas the other columns are more commonly used for data. In these
679 /// cases, it is sometimes desirable to highlight the first column differently.
680 ///
681 /// # Parameters
682 ///
683 /// - `enable`: Turn the property on/off. It is off by default.
684 ///
685 /// # Examples
686 ///
687 /// Example of turning on the first column highlighting property in a
688 /// worksheet table. This is normally off by default,
689 ///
690 /// ```
691 /// # // This code is available in examples/doc_table_set_first_column.rs
692 /// #
693 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
694 /// #
695 /// # fn main() -> Result<(), XlsxError> {
696 /// # // Create a new Excel file object.
697 /// # let mut workbook = Workbook::new();
698 /// #
699 /// # // Add a worksheet to the workbook.
700 /// # let worksheet = workbook.add_worksheet();
701 /// #
702 /// # // Some sample data for the table.
703 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
704 /// # let data = [
705 /// # [10000, 5000, 8000, 6000],
706 /// # [2000, 3000, 4000, 5000],
707 /// # [6000, 6000, 6500, 6000],
708 /// # [500, 300, 200, 700],
709 /// # ];
710 /// #
711 /// # // Write the table data.
712 /// # worksheet.write_column(3, 1, items)?;
713 /// # worksheet.write_row_matrix(3, 2, data)?;
714 /// #
715 /// # // Set the column widths for clarity.
716 /// # worksheet.set_column_range_width(1, 6, 12)?;
717 /// #
718 /// // Create a new table and configure the first column highlighting.
719 /// let table = Table::new().set_first_column(true);
720 ///
721 /// // Add the table to the worksheet.
722 /// worksheet.add_table(2, 1, 6, 5, &table)?;
723 /// #
724 /// # // Save the file to disk.
725 /// # workbook.save("tables.xlsx")?;
726 /// #
727 /// # Ok(())
728 /// # }
729 /// ```
730 ///
731 /// Output file:
732 ///
733 /// <img
734 /// src="https://rustxlsxwriter.github.io/images/table_set_first_column.png">
735 ///
736 pub fn set_first_column(mut self, enable: bool) -> Table {
737 self.show_first_column = enable;
738 self
739 }
740
741 /// Turn on/off the last column highlighting for a table.
742 ///
743 /// The last column of a worksheet table is often used for a `SUM()` or
744 /// other formula operating on the data in the other columns. In these
745 /// cases, it is sometimes required to highlight the last column differently.
746 ///
747 /// # Parameters
748 ///
749 /// - `enable`: Turn the property on/off. It is off by default.
750 ///
751 /// # Examples
752 ///
753 /// Example of turning on the last column highlighting property in a
754 /// worksheet table. This is normally off by default,
755 ///
756 /// ```
757 /// # // This code is available in examples/doc_table_set_last_column.rs
758 /// #
759 /// # use rust_xlsxwriter::{Table, TableColumn, Workbook, XlsxError};
760 /// #
761 /// # fn main() -> Result<(), XlsxError> {
762 /// # // Create a new Excel file object.
763 /// # let mut workbook = Workbook::new();
764 /// #
765 /// # // Add a worksheet to the workbook.
766 /// # let worksheet = workbook.add_worksheet();
767 /// #
768 /// # // Some sample data for the table.
769 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
770 /// # let data = [
771 /// # [10000, 5000, 8000, 6000],
772 /// # [2000, 3000, 4000, 5000],
773 /// # [6000, 6000, 6500, 6000],
774 /// # [500, 300, 200, 700],
775 /// # ];
776 /// #
777 /// # // Write the table data.
778 /// # worksheet.write_column(3, 1, items)?;
779 /// # worksheet.write_row_matrix(3, 2, data)?;
780 /// #
781 /// # // Set the column widths for clarity.
782 /// # worksheet.set_column_range_width(1, 6, 12)?;
783 /// #
784 /// // Add a structured reference formula to the last column and set the header
785 /// // caption. The last column in `add_table()` should be extended to account
786 /// // for this extra column.
787 /// let columns = vec![
788 /// TableColumn::default(),
789 /// TableColumn::default(),
790 /// TableColumn::default(),
791 /// TableColumn::default(),
792 /// TableColumn::default(),
793 /// TableColumn::new()
794 /// .set_header("Totals")
795 /// .set_formula("SUM(Table1[@[Column2]:[Column5]])"),
796 /// ];
797 ///
798 /// // Create a new table and configure the last column highlighting.
799 /// let table = Table::new().set_last_column(true).set_columns(&columns);
800 ///
801 /// // Add the table to the worksheet.
802 /// worksheet.add_table(2, 1, 6, 6, &table)?;
803 /// #
804 /// # // Save the file to disk.
805 /// # workbook.save("tables.xlsx")?;
806 /// #
807 /// # Ok(())
808 /// # }
809 /// ```
810 ///
811 /// Output file:
812 ///
813 /// <img
814 /// src="https://rustxlsxwriter.github.io/images/table_set_last_column.png">
815 ///
816 pub fn set_last_column(mut self, enable: bool) -> Table {
817 self.show_last_column = enable;
818 self
819 }
820
821 /// Turn on/off the autofilter for a table.
822 ///
823 /// By default, Excel adds an autofilter to the header of a table. This
824 /// method can be used to turn it off if necessary.
825 ///
826 /// # Parameters
827 ///
828 /// - `enable`: Turn the property on/off. It is on by default.
829 ///
830 /// # Examples
831 ///
832 /// Example of turning off the autofilter in a worksheet table.
833 ///
834 /// ```
835 /// # // This code is available in examples/doc_table_set_autofilter.rs
836 /// #
837 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
838 /// #
839 /// # fn main() -> Result<(), XlsxError> {
840 /// # // Create a new Excel file object.
841 /// # let mut workbook = Workbook::new();
842 /// #
843 /// # // Add a worksheet to the workbook.
844 /// # let worksheet = workbook.add_worksheet();
845 /// #
846 /// # // Some sample data for the table.
847 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
848 /// # let data = [
849 /// # [10000, 5000, 8000, 6000],
850 /// # [2000, 3000, 4000, 5000],
851 /// # [6000, 6000, 6500, 6000],
852 /// # [500, 300, 200, 700],
853 /// # ];
854 /// #
855 /// # // Write the table data.
856 /// # worksheet.write_column(3, 1, items)?;
857 /// # worksheet.write_row_matrix(3, 2, data)?;
858 /// #
859 /// # // Set the column widths for clarity.
860 /// # worksheet.set_column_range_width(1, 6, 12)?;
861 /// #
862 /// // Create a new table and configure the autofilter.
863 /// let table = Table::new().set_autofilter(false);
864 ///
865 /// // Add the table to the worksheet.
866 /// worksheet.add_table(2, 1, 6, 5, &table)?;
867 /// #
868 /// # // Save the file to disk.
869 /// # workbook.save("tables.xlsx")?;
870 /// #
871 /// # Ok(())
872 /// # }
873 /// ```
874 ///
875 /// Output file:
876 ///
877 /// <img src="https://rustxlsxwriter.github.io/images/table_set_autofilter.png">
878 ///
879 pub fn set_autofilter(mut self, enable: bool) -> Table {
880 self.show_autofilter = enable;
881 self
882 }
883
884 /// Set properties for the columns in a table.
885 ///
886 /// Set the properties for columns in a worksheet table via an array of
887 /// [`TableColumn`] structs. This can be used to set the following
888 /// properties of a table column:
889 ///
890 /// - The header caption.
891 /// - The total row caption.
892 /// - The total row subtotal function.
893 /// - A formula for the column.
894 ///
895 ///
896 /// # Parameters
897 ///
898 /// - `columns`: An array reference of [`TableColumn`] structs. Use
899 /// `TableColumn::default()` to get default values.
900 ///
901 ///
902 /// # Examples
903 ///
904 /// Example of creating a worksheet table.
905 ///
906 /// ```
907 /// # // This code is available in examples/doc_table_set_columns.rs
908 /// #
909 /// # use rust_xlsxwriter::{Table, TableColumn, TableFunction, Workbook, XlsxError};
910 /// #
911 /// # fn main() -> Result<(), XlsxError> {
912 /// # // Create a new Excel file object.
913 /// # let mut workbook = Workbook::new();
914 /// #
915 /// # // Add a worksheet to the workbook.
916 /// # let worksheet = workbook.add_worksheet();
917 /// #
918 /// # // Some sample data for the table.
919 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
920 /// # let data = [
921 /// # [10000, 5000, 8000, 6000],
922 /// # [2000, 3000, 4000, 5000],
923 /// # [6000, 6000, 6500, 6000],
924 /// # [500, 300, 200, 700],
925 /// # ];
926 /// #
927 /// # // Write the table data.
928 /// # worksheet.write_column(3, 1, items)?;
929 /// # worksheet.write_row_matrix(3, 2, data)?;
930 /// #
931 /// # // Set the column widths for clarity.
932 /// # worksheet.set_column_range_width(1, 6, 12)?;
933 /// #
934 /// // Create a new table and configure it.
935 /// let columns = vec![
936 /// TableColumn::new()
937 /// .set_header("Product")
938 /// .set_total_label("Totals"),
939 /// TableColumn::new()
940 /// .set_header("Quarter 1")
941 /// .set_total_function(TableFunction::Sum),
942 /// TableColumn::new()
943 /// .set_header("Quarter 2")
944 /// .set_total_function(TableFunction::Sum),
945 /// TableColumn::new()
946 /// .set_header("Quarter 3")
947 /// .set_total_function(TableFunction::Sum),
948 /// TableColumn::new()
949 /// .set_header("Quarter 4")
950 /// .set_total_function(TableFunction::Sum),
951 /// TableColumn::new()
952 /// .set_header("Year")
953 /// .set_total_function(TableFunction::Sum)
954 /// .set_formula("SUM(Table1[@[Quarter 1]:[Quarter 4]])"),
955 /// ];
956 ///
957 /// let table = Table::new().set_columns(&columns).set_total_row(true);
958 ///
959 /// // Add the table to the worksheet.
960 /// worksheet.add_table(2, 1, 7, 6, &table)?;
961 /// #
962 /// # // Save the file to disk.
963 /// # workbook.save("tables.xlsx")?;
964 /// #
965 /// # Ok(())
966 /// # }
967 /// ```
968 ///
969 /// Output file:
970 ///
971 /// <img
972 /// src="https://rustxlsxwriter.github.io/images/table_set_columns.png">
973 ///
974 pub fn set_columns(mut self, columns: &[TableColumn]) -> Table {
975 self.columns = columns.to_vec();
976 self
977 }
978
979 /// Set the name for a table.
980 ///
981 /// The name of a worksheet table in Excel is similar to a defined name
982 /// representing a data region, and it can be used in structured reference
983 /// formulas.
984 ///
985 /// By default, Excel and `rust_xlsxwriter` use a `Table1` .. `TableN`
986 /// naming convention for tables in a workbook. If required, you can set a
987 /// user-defined name. However, you need to ensure that this name is unique
988 /// across the workbook; otherwise, you will get a warning when you load the
989 /// file in Excel.
990 ///
991 /// # Parameters
992 ///
993 /// - `name`: The name of the table. It must be unique across the workbook.
994 ///
995 /// # Examples
996 ///
997 /// Example of setting the name of a worksheet table.
998 ///
999 /// ```
1000 /// # // This code is available in examples/doc_table_set_name.rs
1001 /// #
1002 /// # use rust_xlsxwriter::{Table, Workbook, XlsxError};
1003 /// #
1004 /// # fn main() -> Result<(), XlsxError> {
1005 /// # // Create a new Excel file object.
1006 /// # let mut workbook = Workbook::new();
1007 /// #
1008 /// # // Add a worksheet to the workbook.
1009 /// # let worksheet = workbook.add_worksheet();
1010 /// #
1011 /// # // Some sample data for the table.
1012 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1013 /// # let data = [
1014 /// # [10000, 5000, 8000, 6000],
1015 /// # [2000, 3000, 4000, 5000],
1016 /// # [6000, 6000, 6500, 6000],
1017 /// # [500, 300, 200, 700],
1018 /// # ];
1019 /// #
1020 /// # // Write the table data.
1021 /// # worksheet.write_column(3, 1, items)?;
1022 /// # worksheet.write_row_matrix(3, 2, data)?;
1023 /// #
1024 /// # // Set the column widths for clarity.
1025 /// # worksheet.set_column_range_width(1, 6, 12)?;
1026 /// #
1027 /// // Create a new table and set the name.
1028 /// let table = Table::new().set_name("ProduceSales");
1029 ///
1030 /// // Add the table to the worksheet.
1031 /// worksheet.add_table(2, 1, 6, 5, &table)?;
1032 /// #
1033 /// # // Save the file to disk.
1034 /// # workbook.save("tables.xlsx")?;
1035 /// #
1036 /// # Ok(())
1037 /// # }
1038 /// ```
1039 ///
1040 /// Output file:
1041 ///
1042 /// <img src="https://rustxlsxwriter.github.io/images/table_set_name.png">
1043 ///
1044 pub fn set_name(mut self, name: impl Into<String>) -> Table {
1045 self.name = name.into();
1046 self
1047 }
1048
1049 /// Set the style for a table.
1050 ///
1051 /// Excel supports 61 different styles for tables divided into Light, Medium,
1052 /// and Dark categories.
1053 ///
1054 /// <img src="https://rustxlsxwriter.github.io/images/table_styles.png">
1055 ///
1056 /// You can set one of these styles using a [`TableStyle`] enum value. The
1057 /// default table style in Excel is equivalent to [`TableStyle::Medium9`].
1058 ///
1059 /// # Parameters
1060 ///
1061 /// - `style`: a [`TableStyle`] enum value.
1062 ///
1063 /// # Examples
1064 ///
1065 /// Example of setting the style of a worksheet table.
1066 ///
1067 /// ```
1068 /// # // This code is available in examples/doc_table_set_style.rs
1069 /// #
1070 /// # use rust_xlsxwriter::{Table, TableStyle, Workbook, XlsxError};
1071 /// #
1072 /// # fn main() -> Result<(), XlsxError> {
1073 /// # // Create a new Excel file object.
1074 /// # let mut workbook = Workbook::new();
1075 /// #
1076 /// # // Add a worksheet to the workbook.
1077 /// # let worksheet = workbook.add_worksheet();
1078 /// #
1079 /// # // Some sample data for the table.
1080 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1081 /// # let data = [
1082 /// # [10000, 5000, 8000, 6000],
1083 /// # [2000, 3000, 4000, 5000],
1084 /// # [6000, 6000, 6500, 6000],
1085 /// # [500, 300, 200, 700],
1086 /// # ];
1087 /// #
1088 /// # // Write the table data.
1089 /// # worksheet.write_column(3, 1, items)?;
1090 /// # worksheet.write_row_matrix(3, 2, data)?;
1091 /// #
1092 /// # // Set the column widths for clarity.
1093 /// # worksheet.set_column_range_width(1, 6, 12)?;
1094 /// #
1095 /// // Create a new table and set the style.
1096 /// let table = Table::new().set_style(TableStyle::Medium10);
1097 ///
1098 /// // Add the table to the worksheet.
1099 /// worksheet.add_table(2, 1, 6, 5, &table)?;
1100 /// #
1101 /// # // Save the file to disk.
1102 /// # workbook.save("tables.xlsx")?;
1103 /// #
1104 /// # Ok(())
1105 /// # }
1106 /// ```
1107 ///
1108 /// Output file:
1109 ///
1110 /// <img src="https://rustxlsxwriter.github.io/images/table_set_style.png">
1111 ///
1112 pub fn set_style(mut self, style: TableStyle) -> Table {
1113 self.style = style;
1114 self
1115 }
1116
1117 /// Check if the table has a header row.
1118 ///
1119 /// This method is mainly used by polars_excel_writer and hidden from the
1120 /// general documentation.
1121 ///
1122 #[doc(hidden)]
1123 pub fn has_header_row(&self) -> bool {
1124 self.show_header_row
1125 }
1126
1127 /// Check if the table has a totals row.
1128 ///
1129 /// This method is mainly used by polars_excel_writer and hidden from the
1130 /// general documentation.
1131 ///
1132 #[doc(hidden)]
1133 pub fn has_total_row(&self) -> bool {
1134 self.show_total_row
1135 }
1136
1137 // Truncate or extend (with defaults) the table columns.
1138 pub(crate) fn initialize_columns(
1139 &mut self,
1140 default_headers: &[String],
1141 ) -> Result<(), XlsxError> {
1142 let mut seen_column_names = HashSet::new();
1143 let num_columns = self.cell_range.last_col - self.cell_range.first_col + 1;
1144
1145 self.columns
1146 .resize_with(num_columns as usize, TableColumn::default);
1147
1148 // Set the column header names,
1149 for (index, column) in self.columns.iter_mut().enumerate() {
1150 if column.name.is_empty() {
1151 column.name.clone_from(&default_headers[index]);
1152 }
1153
1154 if seen_column_names.contains(&column.name.to_lowercase()) {
1155 return Err(XlsxError::TableError(format!(
1156 "Column name '{}' already exists in Table at {}",
1157 column.name,
1158 self.cell_range.to_error_string()
1159 )));
1160 }
1161
1162 seen_column_names.insert(column.name.to_lowercase().clone());
1163 }
1164
1165 Ok(())
1166 }
1167
1168 // Get the first row that can be used to write data.
1169 pub(crate) fn first_data_row(&self) -> RowNum {
1170 if self.show_header_row {
1171 self.cell_range.first_row + 1
1172 } else {
1173 self.cell_range.first_row
1174 }
1175 }
1176
1177 // Get the last row that can be used to write data.
1178 pub(crate) fn last_data_row(&self) -> RowNum {
1179 if self.show_total_row {
1180 self.cell_range.last_row - 1
1181 } else {
1182 self.cell_range.last_row
1183 }
1184 }
1185
1186 // -----------------------------------------------------------------------
1187 // XML assembly methods.
1188 // -----------------------------------------------------------------------
1189
1190 // Assemble and generate the XML file.
1191 pub(crate) fn assemble_xml_file(&mut self) {
1192 xml_declaration(&mut self.writer);
1193
1194 // Write the table element.
1195 self.write_table();
1196
1197 if self.show_autofilter && self.show_header_row {
1198 // Write the autoFilter element.
1199 self.write_auto_filter();
1200 }
1201
1202 // Write the tableColumns element.
1203 self.write_columns();
1204
1205 // Write the tableStyleInfo element.
1206 self.write_table_style_info();
1207
1208 // Close the table tag.
1209 xml_end_tag(&mut self.writer, "table");
1210 }
1211
1212 // Write the <table> element.
1213 fn write_table(&mut self) {
1214 let schema = "http://schemas.openxmlformats.org/spreadsheetml/2006/main".to_string();
1215 let range = self.cell_range.to_range_string();
1216 let name = if self.name.is_empty() {
1217 format!("Table{}", self.index)
1218 } else {
1219 self.name.clone()
1220 };
1221
1222 let mut attributes = vec![
1223 ("xmlns", schema),
1224 ("id", self.index.to_string()),
1225 ("name", name.clone()),
1226 ("displayName", name),
1227 ("ref", range),
1228 ];
1229
1230 if !self.show_header_row {
1231 attributes.push(("headerRowCount", "0".to_string()));
1232 }
1233
1234 if self.show_total_row {
1235 attributes.push(("totalsRowCount", "1".to_string()));
1236 } else {
1237 attributes.push(("totalsRowShown", "0".to_string()));
1238 }
1239
1240 xml_start_tag(&mut self.writer, "table", &attributes);
1241 }
1242
1243 // Write the <autoFilter> element.
1244 fn write_auto_filter(&mut self) {
1245 let mut autofilter_range = self.cell_range.clone();
1246
1247 if self.show_total_row {
1248 autofilter_range.last_row -= 1;
1249 }
1250
1251 let attributes = vec![("ref", autofilter_range.to_range_string())];
1252
1253 xml_empty_tag(&mut self.writer, "autoFilter", &attributes);
1254 }
1255
1256 // Write the <tableColumns> element.
1257 fn write_columns(&mut self) {
1258 let attributes = vec![("count", self.columns.len().to_string())];
1259
1260 xml_start_tag(&mut self.writer, "tableColumns", &attributes);
1261
1262 for (index, column) in self.columns.clone().iter().enumerate() {
1263 // Write the tableColumn element.
1264 self.write_column(index + 1, column);
1265 }
1266
1267 xml_end_tag(&mut self.writer, "tableColumns");
1268 }
1269
1270 // Write the <tableColumn> element.
1271 fn write_column(&mut self, index: usize, column: &TableColumn) {
1272 let mut attributes = vec![("id", index.to_string()), ("name", column.name.clone())];
1273
1274 if !column.total_label.is_empty() {
1275 attributes.push(("totalsRowLabel", column.total_label.clone()));
1276 } else if column.total_function != TableFunction::None {
1277 attributes.push(("totalsRowFunction", column.total_function.to_string()));
1278 }
1279
1280 if let Some(format) = &column.format {
1281 attributes.push(("dataDxfId", format.dxf_index.to_string()));
1282 }
1283
1284 if column.formula.is_some() || matches!(&column.total_function, TableFunction::Custom(_)) {
1285 xml_start_tag(&mut self.writer, "tableColumn", &attributes);
1286
1287 if let Some(formula) = &column.formula {
1288 // Write the calculatedColumnFormula element.
1289 self.write_calculated_column_formula(&formula.formula_string);
1290 }
1291
1292 if let TableFunction::Custom(formula) = &column.total_function {
1293 // Write the totalsRowFormula element.
1294 self.write_totals_row_formula(&formula.formula_string);
1295 }
1296
1297 xml_end_tag(&mut self.writer, "tableColumn");
1298 } else {
1299 xml_empty_tag(&mut self.writer, "tableColumn", &attributes);
1300 }
1301 }
1302
1303 // Write the <calculatedColumnFormula> element.
1304 fn write_calculated_column_formula(&mut self, formula: &str) {
1305 xml_data_element_only(&mut self.writer, "calculatedColumnFormula", formula);
1306 }
1307
1308 // Write the <totalsRowFormula> element.
1309 fn write_totals_row_formula(&mut self, formula: &str) {
1310 xml_data_element_only(&mut self.writer, "totalsRowFormula", formula);
1311 }
1312
1313 // Write the <tableStyleInfo> element.
1314 fn write_table_style_info(&mut self) {
1315 let mut attributes = vec![];
1316
1317 if self.style != TableStyle::None {
1318 attributes.push(("name", self.style.to_string()));
1319 }
1320
1321 attributes.push(("showFirstColumn", self.show_first_column.to_xml_bool()));
1322 attributes.push(("showLastColumn", self.show_last_column.to_xml_bool()));
1323 attributes.push(("showRowStripes", self.show_banded_rows.to_xml_bool()));
1324 attributes.push(("showColumnStripes", self.show_banded_columns.to_xml_bool()));
1325
1326 xml_empty_tag(&mut self.writer, "tableStyleInfo", &attributes);
1327 }
1328}
1329
1330#[derive(Clone)]
1331/// The `TableColumn` struct represents a table column.
1332///
1333/// The `TableColumn` struct is used to set the properties for columns in a
1334/// worksheet [`Table`]. This can be used to set the following properties of a
1335/// table column:
1336///
1337/// - The header caption.
1338/// - The total row caption.
1339/// - The total row subtotal function.
1340/// - A formula for the column.
1341///
1342/// This struct is used in conjunction with the [`Table::set_columns()`] method.
1343///
1344/// # Examples
1345///
1346/// Example of creating a worksheet table.
1347///
1348/// ```
1349/// # // This code is available in examples/doc_table_set_columns.rs
1350/// #
1351/// use rust_xlsxwriter::{Table, TableColumn, TableFunction, Workbook, XlsxError};
1352///
1353/// fn main() -> Result<(), XlsxError> {
1354/// // Create a new Excel file object.
1355/// let mut workbook = Workbook::new();
1356///
1357/// // Add a worksheet to the workbook.
1358/// let worksheet = workbook.add_worksheet();
1359///
1360/// // Some sample data for the table.
1361/// let items = ["Apples", "Pears", "Bananas", "Oranges"];
1362/// let data = [
1363/// [10000, 5000, 8000, 6000],
1364/// [2000, 3000, 4000, 5000],
1365/// [6000, 6000, 6500, 6000],
1366/// [500, 300, 200, 700],
1367/// ];
1368///
1369/// // Write the table data.
1370/// worksheet.write_column(3, 1, items)?;
1371/// worksheet.write_row_matrix(3, 2, data)?;
1372///
1373/// // Set the column widths for clarity.
1374/// worksheet.set_column_range_width(1, 6, 12)?;
1375///
1376/// // Create a new table and configure it.
1377/// let columns = vec![
1378/// TableColumn::new()
1379/// .set_header("Product")
1380/// .set_total_label("Totals"),
1381/// TableColumn::new()
1382/// .set_header("Quarter 1")
1383/// .set_total_function(TableFunction::Sum),
1384/// TableColumn::new()
1385/// .set_header("Quarter 2")
1386/// .set_total_function(TableFunction::Sum),
1387/// TableColumn::new()
1388/// .set_header("Quarter 3")
1389/// .set_total_function(TableFunction::Sum),
1390/// TableColumn::new()
1391/// .set_header("Quarter 4")
1392/// .set_total_function(TableFunction::Sum),
1393/// TableColumn::new()
1394/// .set_header("Year")
1395/// .set_total_function(TableFunction::Sum)
1396/// .set_formula("SUM(Table1[@[Quarter 1]:[Quarter 4]])"),
1397/// ];
1398///
1399/// let table = Table::new().set_columns(&columns).set_total_row(true);
1400///
1401/// // Add the table to the worksheet.
1402/// worksheet.add_table(2, 1, 7, 6, &table)?;
1403///
1404/// // Save the file to disk.
1405/// workbook.save("tables.xlsx")?;
1406///
1407/// Ok(())
1408/// }
1409/// ```
1410///
1411/// Output file:
1412///
1413/// <img src="https://rustxlsxwriter.github.io/images/table_set_columns.png">
1414///
1415///
1416pub struct TableColumn {
1417 pub(crate) name: String,
1418 pub(crate) total_function: TableFunction,
1419 pub(crate) total_label: String,
1420 pub(crate) formula: Option<Formula>,
1421 pub(crate) format: Option<Format>,
1422 pub(crate) header_format: Option<Format>,
1423}
1424
1425impl TableColumn {
1426 /// Create a new `TableColumn` to configure a Table column.
1427 ///
1428 pub fn new() -> TableColumn {
1429 TableColumn {
1430 name: String::new(),
1431 total_function: TableFunction::None,
1432 total_label: String::new(),
1433 formula: None,
1434 format: None,
1435 header_format: None,
1436 }
1437 }
1438
1439 /// Set the header caption for a table column.
1440 ///
1441 /// Excel uses default captions such as `Column 1`, `Column 2`, etc., for
1442 /// the headers on a worksheet table. These can be set to a user-defined
1443 /// value using the `set_header()` method.
1444 ///
1445 /// The column header names in a table must be different from each other.
1446 /// Non-unique names will raise a validation error when using
1447 /// [`Worksheet::add_table()`](crate::Worksheet::add_table).
1448 ///
1449 /// # Parameters
1450 ///
1451 /// - `caption`: The caption/name of the column header. It must be unique
1452 /// for the table.
1453 ///
1454 /// # Examples
1455 ///
1456 /// Example of adding a worksheet table with a user defined header captions.
1457 ///
1458 /// ```
1459 /// # // This code is available in examples/doc_table_set_header_row3.rs
1460 /// #
1461 /// # use rust_xlsxwriter::{Table, TableColumn, Workbook, XlsxError};
1462 /// #
1463 /// # fn main() -> Result<(), XlsxError> {
1464 /// # // Create a new Excel file object.
1465 /// # let mut workbook = Workbook::new();
1466 /// #
1467 /// # // Add a worksheet to the workbook.
1468 /// # let worksheet = workbook.add_worksheet();
1469 /// #
1470 /// # // Some sample data for the table.
1471 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1472 /// # let data = [
1473 /// # [10000, 5000, 8000, 6000],
1474 /// # [2000, 3000, 4000, 5000],
1475 /// # [6000, 6000, 6500, 6000],
1476 /// # [500, 300, 200, 700],
1477 /// # ];
1478 /// #
1479 /// # // Write the table data.
1480 /// # worksheet.write_column(3, 1, items)?;
1481 /// # worksheet.write_row_matrix(3, 2, data)?;
1482 /// #
1483 /// # // Set the column widths for clarity.
1484 /// # worksheet.set_column_range_width(1, 6, 12)?;
1485 /// #
1486 /// // Set the captions for the header row.
1487 /// let columns = vec![
1488 /// TableColumn::new().set_header("Product"),
1489 /// TableColumn::new().set_header("Quarter 1"),
1490 /// TableColumn::new().set_header("Quarter 2"),
1491 /// TableColumn::new().set_header("Quarter 3"),
1492 /// TableColumn::new().set_header("Quarter 4"),
1493 /// ];
1494 ///
1495 /// // Create a new table and configure the column headers.
1496 /// let table = Table::new().set_columns(&columns);
1497 ///
1498 /// // Add the table to the worksheet.
1499 /// worksheet.add_table(2, 1, 6, 5, &table)?;
1500 /// #
1501 /// # // Save the file to disk.
1502 /// # workbook.save("tables.xlsx")?;
1503 /// #
1504 /// # Ok(())
1505 /// # }
1506 /// ```
1507 ///
1508 /// Output file:
1509 ///
1510 /// <img
1511 /// src="https://rustxlsxwriter.github.io/images/table_set_header_row3.png">
1512 ///
1513 pub fn set_header(mut self, caption: impl Into<String>) -> TableColumn {
1514 self.name = caption.into();
1515 self
1516 }
1517
1518 /// Set the total function for the total row of a table column.
1519 ///
1520 /// Set the `SUBTOTAL()` function for the "totals" row of a table column.
1521 ///
1522 /// The standard Excel subtotal functions are available via the
1523 /// [`TableFunction`] enum values. The Excel functions are:
1524 ///
1525 /// - Average
1526 /// - Count
1527 /// - Count Numbers
1528 /// - Maximum
1529 /// - Minimum
1530 /// - Sum
1531 /// - Standard Deviation
1532 /// - Variance
1533 /// - Custom - User-defined function or formula
1534 ///
1535 /// Note, overwriting the total row cells with `worksheet.write()` calls
1536 /// will cause Excel to warn that the table is corrupt when loading the
1537 /// file.
1538 ///
1539 /// # Parameters
1540 ///
1541 /// - `function`: A [`TableFunction`] enum value equivalent to one of the
1542 /// available Excel `SUBTOTAL()` options.
1543 ///
1544 /// # Examples
1545 ///
1546 /// Example of turning on the "totals" row at the bottom of a worksheet
1547 /// table with captions and subtotal functions.
1548 ///
1549 /// ```
1550 /// # // This code is available in examples/doc_table_set_total_row2.rs
1551 /// #
1552 /// # use rust_xlsxwriter::{Formula, Table, TableColumn, TableFunction, Workbook, XlsxError};
1553 /// #
1554 /// # fn main() -> Result<(), XlsxError> {
1555 /// # // Create a new Excel file object.
1556 /// # let mut workbook = Workbook::new();
1557 /// #
1558 /// # // Add a worksheet to the workbook.
1559 /// # let worksheet = workbook.add_worksheet();
1560 /// #
1561 /// # // Some sample data for the table.
1562 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1563 /// # let data = [
1564 /// # [10000, 5000, 8000, 6000],
1565 /// # [2000, 3000, 4000, 5000],
1566 /// # [6000, 6000, 6500, 6000],
1567 /// # [500, 300, 200, 700],
1568 /// # ];
1569 /// #
1570 /// # // Write the table data.
1571 /// # worksheet.write_column(3, 1, items)?;
1572 /// # worksheet.write_row_matrix(3, 2, data)?;
1573 /// #
1574 /// # // Set the column widths for clarity.
1575 /// # worksheet.set_column_range_width(1, 6, 12)?;
1576 /// #
1577 /// // Set the caption and subtotal in the total row.
1578 /// let columns = vec![
1579 /// TableColumn::new().set_total_label("Totals"),
1580 /// TableColumn::new().set_total_function(TableFunction::Sum),
1581 /// TableColumn::new().set_total_function(TableFunction::Sum),
1582 /// TableColumn::new().set_total_function(TableFunction::Sum),
1583 /// // Use a custom formula to get a similar summation.
1584 /// TableColumn::new()
1585 /// .set_total_function(TableFunction::Custom(Formula::new("SUM([Column5])"))),
1586 /// ];
1587 ///
1588 /// // Create a new table and configure the total row.
1589 /// let table = Table::new().set_total_row(true).set_columns(&columns);
1590 ///
1591 /// // Add the table to the worksheet.
1592 /// worksheet.add_table(2, 1, 7, 5, &table)?;
1593 /// #
1594 /// # // Save the file to disk.
1595 /// # workbook.save("tables.xlsx")?;
1596 /// #
1597 /// # Ok(())
1598 /// # }
1599 /// ```
1600 ///
1601 /// Output file:
1602 ///
1603 /// <img
1604 /// src="https://rustxlsxwriter.github.io/images/table_set_total_row2.png">
1605 ///
1606 pub fn set_total_function(mut self, function: TableFunction) -> TableColumn {
1607 self.total_function = function;
1608 self
1609 }
1610
1611 /// Set a label for the total row of a table column.
1612 ///
1613 /// It is possible to set a label for the totals row of a column instead of
1614 /// a subtotal function. This is most often used to set a caption like
1615 /// "Totals," as in the example above.
1616 ///
1617 /// Note, overwriting the total row cells with `worksheet.write()` calls
1618 /// will cause Excel to warn that the table is corrupt when loading the
1619 /// file.
1620 ///
1621 /// # Parameters
1622 ///
1623 /// - `label`: The label/caption of the total row of the column.
1624 ///
1625 pub fn set_total_label(mut self, label: impl Into<String>) -> TableColumn {
1626 self.total_label = label.into();
1627 self
1628 }
1629
1630 /// Set the formula for a table column.
1631 ///
1632 /// It is a common use case to add a summation column as the last column in a
1633 /// table. These are constructed with a special class of Excel formulas
1634 /// called [Structured References], which can refer to an entire table or
1635 /// rows or columns of data within the table. For example, to sum the data
1636 /// for several columns in a single row, you might use a formula like
1637 /// this: `SUM(Table1[@[Quarter 1]:[Quarter 4]])`.
1638 ///
1639 /// [Structured References]:
1640 /// https://support.microsoft.com/en-us/office/using-structured-references-with-excel-tables-f5ed2452-2337-4f71-bed3-c8ae6d2b276e
1641 ///
1642 /// # Parameters
1643 ///
1644 /// - `formula`: The formula to be applied to the column as a string or
1645 /// [`Formula`].
1646 ///
1647 /// # Examples
1648 ///
1649 /// Example of adding a formula to a column in a worksheet table.
1650 ///
1651 /// ```
1652 /// # // This code is available in examples/doc_tablecolumn_set_formula.rs
1653 /// #
1654 /// # use rust_xlsxwriter::{Table, TableColumn, Workbook, XlsxError};
1655 /// #
1656 /// # fn main() -> Result<(), XlsxError> {
1657 /// # // Create a new Excel file object.
1658 /// # let mut workbook = Workbook::new();
1659 /// #
1660 /// # // Add a worksheet to the workbook.
1661 /// # let worksheet = workbook.add_worksheet();
1662 /// #
1663 /// # // Some sample data for the table.
1664 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1665 /// # let data = [
1666 /// # [10000, 5000, 8000, 6000],
1667 /// # [2000, 3000, 4000, 5000],
1668 /// # [6000, 6000, 6500, 6000],
1669 /// # [500, 300, 200, 700],
1670 /// # ];
1671 /// #
1672 /// # // Write the table data.
1673 /// # worksheet.write_column(3, 1, items)?;
1674 /// # worksheet.write_row_matrix(3, 2, data)?;
1675 /// #
1676 /// # // Set the column widths for clarity.
1677 /// # worksheet.set_column_range_width(1, 6, 12)?;
1678 /// #
1679 /// // Add a structured reference formula to the last column and set the header
1680 /// // caption.
1681 /// let columns = vec![
1682 /// TableColumn::new().set_header("Product"),
1683 /// TableColumn::new().set_header("Quarter 1"),
1684 /// TableColumn::new().set_header("Quarter 2"),
1685 /// TableColumn::new().set_header("Quarter 3"),
1686 /// TableColumn::new().set_header("Quarter 4"),
1687 /// TableColumn::new()
1688 /// .set_header("Totals")
1689 /// .set_formula("SUM(Table1[@[Quarter 1]:[Quarter 4]])"),
1690 /// ];
1691 ///
1692 /// // Create a new table and configure the columns.
1693 /// let table = Table::new().set_columns(&columns);
1694 ///
1695 /// // Add the table to the worksheet.
1696 /// worksheet.add_table(2, 1, 6, 6, &table)?;
1697 /// #
1698 /// # // Save the file to disk.
1699 /// # workbook.save("tables.xlsx")?;
1700 /// #
1701 /// # Ok(())
1702 /// # }
1703 /// ```
1704 ///
1705 /// Output file:
1706 ///
1707 /// <img
1708 /// src="https://rustxlsxwriter.github.io/images/tablecolumn_set_formula.png">
1709 ///
1710 pub fn set_formula(mut self, formula: impl Into<Formula>) -> TableColumn {
1711 let mut formula = formula.into();
1712 formula = formula.clone().escape_table_functions();
1713 self.formula = Some(formula);
1714 self
1715 }
1716
1717 /// Set the format for a table column.
1718 ///
1719 /// It is sometimes required to format the data in the columns of a table.
1720 /// This can be done using the standard
1721 /// [`Worksheet::write_with_format()`](crate::Worksheet::write_with_format) method,
1722 /// but the format can also be applied separately using
1723 /// `TableColumn.set_format()`.
1724 ///
1725 /// The most common format property to set for a table column is the [number
1726 /// format](Format::set_num_format), see the example below.
1727 ///
1728 /// # Parameters
1729 ///
1730 /// - `format`: The [`Format`] property for the data cells in the column.
1731 ///
1732 /// # Examples
1733 ///
1734 /// Example of adding a format to a column in a worksheet table.
1735 ///
1736 /// ```
1737 /// # // This code is available in examples/doc_tablecolumn_set_format.rs
1738 /// #
1739 /// # use rust_xlsxwriter::{Format, Table, TableColumn, Workbook, XlsxError};
1740 /// #
1741 /// # fn main() -> Result<(), XlsxError> {
1742 /// # // Create a new Excel file object.
1743 /// # let mut workbook = Workbook::new();
1744 /// #
1745 /// # // Add a worksheet to the workbook.
1746 /// # let worksheet = workbook.add_worksheet();
1747 /// #
1748 /// # // Some sample data for the table.
1749 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1750 /// # let data = [
1751 /// # [10000, 5000, 8000, 6000],
1752 /// # [2000, 3000, 4000, 5000],
1753 /// # [6000, 6000, 6500, 6000],
1754 /// # [500, 300, 200, 700],
1755 /// # ];
1756 /// #
1757 /// # // Write the table data.
1758 /// # worksheet.write_column(3, 1, items)?;
1759 /// # worksheet.write_row_matrix(3, 2, data)?;
1760 /// #
1761 /// # // Set the column widths for clarity.
1762 /// # worksheet.set_column_range_width(1, 6, 12)?;
1763 /// #
1764 /// // Create a number format for number columns in the table.
1765 /// let format = Format::new().set_num_format("$#,##0.00");
1766 ///
1767 /// // Add a format to the number/currency columns.
1768 /// let columns = vec![
1769 /// TableColumn::new().set_header("Product"),
1770 /// TableColumn::new().set_header("Q1").set_format(&format),
1771 /// TableColumn::new().set_header("Q2").set_format(&format),
1772 /// TableColumn::new().set_header("Q3").set_format(&format),
1773 /// TableColumn::new().set_header("Q4").set_format(&format),
1774 /// ];
1775 ///
1776 /// // Create a new table and configure the columns.
1777 /// let table = Table::new().set_columns(&columns);
1778 ///
1779 /// // Add the table to the worksheet.
1780 /// worksheet.add_table(2, 1, 6, 5, &table)?;
1781 /// #
1782 /// # // Save the file to disk.
1783 /// # workbook.save("tables.xlsx")?;
1784 /// #
1785 /// # Ok(())
1786 /// # }
1787 /// ```
1788 ///
1789 /// Output file:
1790 ///
1791 /// <img src="https://rustxlsxwriter.github.io/images/tablecolumn_set_format.png">
1792 ///
1793 pub fn set_format(mut self, format: impl Into<Format>) -> TableColumn {
1794 self.format = Some(format.into());
1795 self
1796 }
1797
1798 /// Set the format for the header of the table column.
1799 ///
1800 /// The `set_header_format` method can be used to set the format for the
1801 /// column header in a worksheet table.
1802 ///
1803 /// # Parameters
1804 ///
1805 /// - `format`: The [`Format`] property for the column header.
1806 ///
1807 /// # Examples
1808 ///
1809 /// Example of adding a header format to a column in a worksheet table.
1810 ///
1811 /// ```
1812 /// # // This code is available in examples/doc_tablecolumn_set_header_format.rs
1813 /// #
1814 /// # use rust_xlsxwriter::{Format, Table, TableColumn, Workbook, XlsxError};
1815 /// #
1816 /// # fn main() -> Result<(), XlsxError> {
1817 /// # // Create a new Excel file object.
1818 /// # let mut workbook = Workbook::new();
1819 /// #
1820 /// # // Add a worksheet to the workbook.
1821 /// # let worksheet = workbook.add_worksheet();
1822 /// #
1823 /// # // Some sample data for the table.
1824 /// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1825 /// # let data = [
1826 /// # [10000, 5000, 8000, 6000],
1827 /// # [2000, 3000, 4000, 5000],
1828 /// # [6000, 6000, 6500, 6000],
1829 /// # [500, 300, 200, 700],
1830 /// # ];
1831 /// #
1832 /// # // Write the table data.
1833 /// # worksheet.write_column(3, 1, items)?;
1834 /// # worksheet.write_row_matrix(3, 2, data)?;
1835 /// #
1836 /// # // Set the column widths for clarity.
1837 /// # worksheet.set_column_range_width(1, 6, 12)?;
1838 /// #
1839 /// # // Create formats for the columns headers.
1840 /// let format1 = Format::new().set_font_color("#FF0000");
1841 /// let format2 = Format::new().set_font_color("#00FF00");
1842 /// let format3 = Format::new().set_font_color("#0000FF");
1843 /// let format4 = Format::new().set_font_color("#FFFF00");
1844 ///
1845 /// // Add a format to the columns headers.
1846 /// let columns = vec![
1847 /// TableColumn::new().set_header("Product"),
1848 /// TableColumn::new()
1849 /// .set_header("Quarter 1")
1850 /// .set_header_format(format1),
1851 /// TableColumn::new()
1852 /// .set_header("Quarter 2")
1853 /// .set_header_format(format2),
1854 /// TableColumn::new()
1855 /// .set_header("Quarter 3")
1856 /// .set_header_format(format3),
1857 /// TableColumn::new()
1858 /// .set_header("Quarter 4")
1859 /// .set_header_format(format4),
1860 /// ];
1861 ///
1862 /// // Create a new table and configure the columns.
1863 /// let table = Table::new().set_columns(&columns);
1864 ///
1865 /// // Add the table to the worksheet.
1866 /// worksheet.add_table(2, 1, 6, 5, &table)?;
1867 /// #
1868 /// # // Save the file to disk.
1869 /// # workbook.save("tables.xlsx")?;
1870 /// #
1871 /// # Ok(())
1872 /// # }
1873 /// ```
1874 ///
1875 /// Output file:
1876 ///
1877 /// <img src="https://rustxlsxwriter.github.io/images/tablecolumn_set_header_format.png">
1878 ///
1879 pub fn set_header_format(mut self, format: impl Into<Format>) -> TableColumn {
1880 self.header_format = Some(format.into());
1881 self
1882 }
1883
1884 // Convert the SUBTOTAL type to a worksheet formula.
1885 pub(crate) fn total_function(&self) -> Formula {
1886 let column_name = self
1887 .name
1888 .replace('\'', "''")
1889 .replace('#', "'#")
1890 .replace(']', "']")
1891 .replace('[', "'[");
1892
1893 match &self.total_function {
1894 TableFunction::None => Formula::new(""),
1895 TableFunction::Max => Formula::new(format!("SUBTOTAL(104,[{column_name}])")),
1896 TableFunction::Min => Formula::new(format!("SUBTOTAL(105,[{column_name}])")),
1897 TableFunction::Sum => Formula::new(format!("SUBTOTAL(109,[{column_name}])")),
1898 TableFunction::Var => Formula::new(format!("SUBTOTAL(110,[{column_name}])")),
1899 TableFunction::Count => Formula::new(format!("SUBTOTAL(103,[{column_name}])")),
1900 TableFunction::StdDev => Formula::new(format!("SUBTOTAL(107,[{column_name}])")),
1901 TableFunction::Average => Formula::new(format!("SUBTOTAL(101,[{column_name}])")),
1902 TableFunction::CountNumbers => Formula::new(format!("SUBTOTAL(102,[{column_name}])")),
1903 TableFunction::Custom(formula) => formula.clone(),
1904 }
1905 }
1906}
1907
1908impl Default for TableColumn {
1909 fn default() -> Self {
1910 Self::new()
1911 }
1912}
1913
1914/// The `TableFunction` enum defines functions for worksheet table total rows.
1915///
1916/// The `TableFunction` enum contains definitions for the standard Excel
1917/// "SUBTOTAL" functions that are available via the dropdown in the total row of
1918/// an Excel table. It also supports custom user defined functions or formulas.
1919///
1920/// # Examples
1921///
1922/// Example of turning on the totals row at the bottom of a worksheet table with
1923/// subtotal functions.
1924///
1925/// ```
1926/// # // This code is available in examples/doc_table_set_total_row2.rs
1927/// #
1928/// # use rust_xlsxwriter::{Formula, Table, TableColumn, TableFunction, Workbook, XlsxError};
1929/// #
1930/// # fn main() -> Result<(), XlsxError> {
1931/// # // Create a new Excel file object.
1932/// # let mut workbook = Workbook::new();
1933/// #
1934/// # // Add a worksheet to the workbook.
1935/// # let worksheet = workbook.add_worksheet();
1936/// #
1937/// # // Some sample data for the table.
1938/// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
1939/// # let data = [
1940/// # [10000, 5000, 8000, 6000],
1941/// # [2000, 3000, 4000, 5000],
1942/// # [6000, 6000, 6500, 6000],
1943/// # [500, 300, 200, 700],
1944/// # ];
1945/// #
1946/// # // Write the table data.
1947/// # worksheet.write_column(3, 1, items)?;
1948/// # worksheet.write_row_matrix(3, 2, data)?;
1949/// #
1950/// # // Set the column widths for clarity.
1951/// # worksheet.set_column_range_width(1, 6, 12)?;
1952/// #
1953/// // Set the caption and subtotal in the total row.
1954/// let columns = vec![
1955/// TableColumn::new().set_total_label("Totals"),
1956/// TableColumn::new().set_total_function(TableFunction::Sum),
1957/// TableColumn::new().set_total_function(TableFunction::Sum),
1958/// TableColumn::new().set_total_function(TableFunction::Sum),
1959/// // Use a custom formula to get a similar summation.
1960/// TableColumn::new()
1961/// .set_total_function(TableFunction::Custom(Formula::new("SUM([Column5])"))),
1962/// ];
1963///
1964/// // Create a new table and configure the total row.
1965/// let table = Table::new().set_total_row(true).set_columns(&columns);
1966///
1967/// // Add the table to the worksheet.
1968/// worksheet.add_table(2, 1, 7, 5, &table)?;
1969///
1970/// # // Save the file to disk.
1971/// # workbook.save("tables.xlsx")?;
1972/// #
1973/// # Ok(())
1974/// # }
1975/// ```
1976///
1977/// Output file:
1978///
1979/// <img src="https://rustxlsxwriter.github.io/images/table_set_total_row2.png">
1980///
1981#[derive(Clone, PartialEq)]
1982pub enum TableFunction {
1983 /// The "total row" option is enable but there is no total function.
1984 None,
1985
1986 /// Use the average function as the table total.
1987 Average,
1988
1989 /// Use the count function as the table total.
1990 Count,
1991
1992 /// Use the count numbers function as the table total.
1993 CountNumbers,
1994
1995 /// Use the max function as the table total.
1996 Max,
1997
1998 /// Use the min function as the table total.
1999 Min,
2000
2001 /// Use the sum function as the table total.
2002 Sum,
2003
2004 /// Use the standard deviation function as the table total.
2005 StdDev,
2006
2007 /// Use the var function as the table total.
2008 Var,
2009
2010 /// Use a custom/user specified function or formula.
2011 Custom(Formula),
2012}
2013
2014impl fmt::Display for TableFunction {
2015 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2016 match self {
2017 Self::Max => write!(f, "max"),
2018 Self::Min => write!(f, "min"),
2019 Self::Sum => write!(f, "sum"),
2020 Self::Var => write!(f, "var"),
2021 Self::None => write!(f, "None"),
2022 Self::Count => write!(f, "count"),
2023 Self::StdDev => write!(f, "stdDev"),
2024 Self::Average => write!(f, "average"),
2025 Self::CountNumbers => write!(f, "countNums"),
2026 Self::Custom(_) => write!(f, "custom"),
2027 }
2028 }
2029}
2030
2031/// The `TableStyle` enum defines the worksheet table styles.
2032///
2033/// Excel supports 61 different styles for tables divided into Light, Medium and
2034/// Dark categories. You can set one of these styles using a `TableStyle` enum
2035/// value.
2036///
2037/// <img src="https://rustxlsxwriter.github.io/images/table_styles.png">
2038///
2039/// The style is set via the [`Table::set_style()`] method. The default table
2040/// style in Excel is equivalent to [`TableStyle::Medium9`].
2041///
2042/// # Examples
2043///
2044/// Example of setting the style of a worksheet table.
2045///
2046/// ```
2047/// # // This code is available in examples/doc_table_set_style.rs
2048/// #
2049/// # use rust_xlsxwriter::{Table, TableStyle, Workbook, XlsxError};
2050/// #
2051/// # fn main() -> Result<(), XlsxError> {
2052/// # // Create a new Excel file object.
2053/// # let mut workbook = Workbook::new();
2054/// #
2055/// # // Add a worksheet to the workbook.
2056/// # let worksheet = workbook.add_worksheet();
2057/// #
2058/// # // Some sample data for the table.
2059/// # let items = ["Apples", "Pears", "Bananas", "Oranges"];
2060/// # let data = [
2061/// # [10000, 5000, 8000, 6000],
2062/// # [2000, 3000, 4000, 5000],
2063/// # [6000, 6000, 6500, 6000],
2064/// # [500, 300, 200, 700],
2065/// # ];
2066/// #
2067/// # // Write the table data.
2068/// # worksheet.write_column(3, 1, items)?;
2069/// # worksheet.write_row_matrix(3, 2, data)?;
2070/// #
2071/// # // Set the column widths for clarity.
2072/// # worksheet.set_column_range_width(1, 6, 12)?;
2073/// #
2074/// // Create a new table and set the style.
2075/// let table = Table::new().set_style(TableStyle::Medium10);
2076///
2077/// // Add the table to the worksheet.
2078/// worksheet.add_table(2, 1, 6, 5, &table)?;
2079///
2080/// # // Save the file to disk.
2081/// # workbook.save("tables.xlsx")?;
2082/// #
2083/// # Ok(())
2084/// # }
2085/// ```
2086///
2087/// Output file:
2088///
2089/// <img src="https://rustxlsxwriter.github.io/images/table_set_style.png">
2090///
2091#[derive(Clone, Copy, PartialEq, Eq)]
2092pub enum TableStyle {
2093 /// No table style.
2094 None,
2095
2096 /// Table Style Light 1, White.
2097 Light1,
2098
2099 /// Table Style Light 2, Light Blue.
2100 Light2,
2101
2102 /// Table Style Light 3, Light Orange.
2103 Light3,
2104
2105 /// Table Style Light 4, White.
2106 Light4,
2107
2108 /// Table Style Light 5, Light Yellow.
2109 Light5,
2110
2111 /// Table Style Light 6, Light Blue.
2112 Light6,
2113
2114 /// Table Style Light 7, Light Green.
2115 Light7,
2116
2117 /// Table Style Light 8, White.
2118 Light8,
2119
2120 /// Table Style Light 9, Blue.
2121 Light9,
2122
2123 /// Table Style Light 10, Orange.
2124 Light10,
2125
2126 /// Table Style Light 11, White.
2127 Light11,
2128
2129 /// Table Style Light 12, Gold.
2130 Light12,
2131
2132 /// Table Style Light 13, Blue.
2133 Light13,
2134
2135 /// Table Style Light 14, Green.
2136 Light14,
2137
2138 /// Table Style Light 15, White.
2139 Light15,
2140
2141 /// Table Style Light 16, Light Blue.
2142 Light16,
2143
2144 /// Table Style Light 17, Light Orange.
2145 Light17,
2146
2147 /// Table Style Light 18, White.
2148 Light18,
2149
2150 /// Table Style Light 19, Light Yellow.
2151 Light19,
2152
2153 /// Table Style Light 20, Light Blue.
2154 Light20,
2155
2156 /// Table Style Light 21, Light Green.
2157 Light21,
2158
2159 /// Table Style Medium 1, White.
2160 Medium1,
2161
2162 /// Table Style Medium 2, Blue.
2163 Medium2,
2164
2165 /// Table Style Medium 3, Orange.
2166 Medium3,
2167
2168 /// Table Style Medium 4, White.
2169 Medium4,
2170
2171 /// Table Style Medium 5, Gold.
2172 Medium5,
2173
2174 /// Table Style Medium 6, Blue.
2175 Medium6,
2176
2177 /// Table Style Medium 7, Green.
2178 Medium7,
2179
2180 /// Table Style Medium 8, Light Grey.
2181 Medium8,
2182
2183 /// Table Style Medium 9, Blue.
2184 Medium9,
2185
2186 /// Table Style Medium 10, Orange.
2187 Medium10,
2188
2189 /// Table Style Medium 11, Light Grey.
2190 Medium11,
2191
2192 /// Table Style Medium 12, Gold.
2193 Medium12,
2194
2195 /// Table Style Medium 13, Blue.
2196 Medium13,
2197
2198 /// Table Style Medium 14, Green.
2199 Medium14,
2200
2201 /// Table Style Medium 15, White.
2202 Medium15,
2203
2204 /// Table Style Medium 16, Blue.
2205 Medium16,
2206
2207 /// Table Style Medium 17, Orange.
2208 Medium17,
2209
2210 /// Table Style Medium 18, White.
2211 Medium18,
2212
2213 /// Table Style Medium 19, Gold.
2214 Medium19,
2215
2216 /// Table Style Medium 20, Blue.
2217 Medium20,
2218
2219 /// Table Style Medium 21, Green.
2220 Medium21,
2221
2222 /// Table Style Medium 22, Light Grey.
2223 Medium22,
2224
2225 /// Table Style Medium 23, Light Blue.
2226 Medium23,
2227
2228 /// Table Style Medium 24, Light Orange.
2229 Medium24,
2230
2231 /// Table Style Medium 25, Light Grey.
2232 Medium25,
2233
2234 /// Table Style Medium 26, Light Yellow.
2235 Medium26,
2236
2237 /// Table Style Medium 27, Light Blue.
2238 Medium27,
2239
2240 /// Table Style Medium 28, Light Green.
2241 Medium28,
2242
2243 /// Table Style Dark 1, Dark Grey.
2244 Dark1,
2245
2246 /// Table Style Dark 2, Dark Blue.
2247 Dark2,
2248
2249 /// Table Style Dark 3, Brown.
2250 Dark3,
2251
2252 /// Table Style Dark 4, Grey.
2253 Dark4,
2254
2255 /// Table Style Dark 5, Dark Yellow.
2256 Dark5,
2257
2258 /// Table Style Dark 6, Blue.
2259 Dark6,
2260
2261 /// Table Style Dark 7, Dark Green.
2262 Dark7,
2263
2264 /// Table Style Dark 8, Light Grey.
2265 Dark8,
2266
2267 /// Table Style Dark 9, Light Orange.
2268 Dark9,
2269
2270 /// Table Style Dark 10, Gold.
2271 Dark10,
2272
2273 /// Table Style Dark 11, Green.
2274 Dark11,
2275}
2276
2277impl fmt::Display for TableStyle {
2278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2279 match self {
2280 Self::None => write!(f, "TableStyleNone"),
2281 Self::Light1 => write!(f, "TableStyleLight1"),
2282 Self::Light2 => write!(f, "TableStyleLight2"),
2283 Self::Light3 => write!(f, "TableStyleLight3"),
2284 Self::Light4 => write!(f, "TableStyleLight4"),
2285 Self::Light5 => write!(f, "TableStyleLight5"),
2286 Self::Light6 => write!(f, "TableStyleLight6"),
2287 Self::Light7 => write!(f, "TableStyleLight7"),
2288 Self::Light8 => write!(f, "TableStyleLight8"),
2289 Self::Light9 => write!(f, "TableStyleLight9"),
2290 Self::Light10 => write!(f, "TableStyleLight10"),
2291 Self::Light11 => write!(f, "TableStyleLight11"),
2292 Self::Light12 => write!(f, "TableStyleLight12"),
2293 Self::Light13 => write!(f, "TableStyleLight13"),
2294 Self::Light14 => write!(f, "TableStyleLight14"),
2295 Self::Light15 => write!(f, "TableStyleLight15"),
2296 Self::Light16 => write!(f, "TableStyleLight16"),
2297 Self::Light17 => write!(f, "TableStyleLight17"),
2298 Self::Light18 => write!(f, "TableStyleLight18"),
2299 Self::Light19 => write!(f, "TableStyleLight19"),
2300 Self::Light20 => write!(f, "TableStyleLight20"),
2301 Self::Light21 => write!(f, "TableStyleLight21"),
2302 Self::Medium1 => write!(f, "TableStyleMedium1"),
2303 Self::Medium2 => write!(f, "TableStyleMedium2"),
2304 Self::Medium3 => write!(f, "TableStyleMedium3"),
2305 Self::Medium4 => write!(f, "TableStyleMedium4"),
2306 Self::Medium5 => write!(f, "TableStyleMedium5"),
2307 Self::Medium6 => write!(f, "TableStyleMedium6"),
2308 Self::Medium7 => write!(f, "TableStyleMedium7"),
2309 Self::Medium8 => write!(f, "TableStyleMedium8"),
2310 Self::Medium9 => write!(f, "TableStyleMedium9"),
2311 Self::Medium10 => write!(f, "TableStyleMedium10"),
2312 Self::Medium11 => write!(f, "TableStyleMedium11"),
2313 Self::Medium12 => write!(f, "TableStyleMedium12"),
2314 Self::Medium13 => write!(f, "TableStyleMedium13"),
2315 Self::Medium14 => write!(f, "TableStyleMedium14"),
2316 Self::Medium15 => write!(f, "TableStyleMedium15"),
2317 Self::Medium16 => write!(f, "TableStyleMedium16"),
2318 Self::Medium17 => write!(f, "TableStyleMedium17"),
2319 Self::Medium18 => write!(f, "TableStyleMedium18"),
2320 Self::Medium19 => write!(f, "TableStyleMedium19"),
2321 Self::Medium20 => write!(f, "TableStyleMedium20"),
2322 Self::Medium21 => write!(f, "TableStyleMedium21"),
2323 Self::Medium22 => write!(f, "TableStyleMedium22"),
2324 Self::Medium23 => write!(f, "TableStyleMedium23"),
2325 Self::Medium24 => write!(f, "TableStyleMedium24"),
2326 Self::Medium25 => write!(f, "TableStyleMedium25"),
2327 Self::Medium26 => write!(f, "TableStyleMedium26"),
2328 Self::Medium27 => write!(f, "TableStyleMedium27"),
2329 Self::Medium28 => write!(f, "TableStyleMedium28"),
2330 Self::Dark1 => write!(f, "TableStyleDark1"),
2331 Self::Dark2 => write!(f, "TableStyleDark2"),
2332 Self::Dark3 => write!(f, "TableStyleDark3"),
2333 Self::Dark4 => write!(f, "TableStyleDark4"),
2334 Self::Dark5 => write!(f, "TableStyleDark5"),
2335 Self::Dark6 => write!(f, "TableStyleDark6"),
2336 Self::Dark7 => write!(f, "TableStyleDark7"),
2337 Self::Dark8 => write!(f, "TableStyleDark8"),
2338 Self::Dark9 => write!(f, "TableStyleDark9"),
2339 Self::Dark10 => write!(f, "TableStyleDark10"),
2340 Self::Dark11 => write!(f, "TableStyleDark11"),
2341 }
2342 }
2343}
2344
2345/// Convert a [`Table`] ref to a [`Table`] object.
2346///
2347/// This is used as a syntactic shortcut for serialize APIs to allow either
2348/// `&Table` or `Table`.
2349///
2350impl From<&Table> for Table {
2351 fn from(value: &Table) -> Table {
2352 (*value).clone()
2353 }
2354}