/* * libxlsxwriter * * SPDX-License-Identifier: BSD-2-Clause * Copyright 2014-2024, John McNamara, jmcnamara@cpan.org. * * chartsheet - A libxlsxwriter library for creating Excel XLSX chartsheet files. * */ /** * @page chartsheet_page The Chartsheet object * * The Chartsheet object represents an Excel chartsheet, which is a type of * worksheet that only contains a chart. The Chartsheet object handles * operations such as adding a chart and setting the page layout. * * See @ref chartsheet.h for full details of the functionality. * * @file chartsheet.h * * @brief Functions related to adding data and formatting to a chartsheet. * * The Chartsheet object represents an Excel chartsheet. It handles operations * such as adding a chart and setting the page layout. * * A Chartsheet object isn't created directly. Instead a chartsheet is created * by calling the workbook_add_chartsheet() function from a Workbook object. A * chartsheet object functions as a worksheet and not as a chart. In order to * have it display data a #lxw_chart object must be created and added to the * chartsheet: * * @code * #include "xlsxwriter.h" * * int main() { * * lxw_workbook *workbook = new_workbook("chartsheet.xlsx"); * lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); * lxw_chartsheet *chartsheet = workbook_add_chartsheet(workbook, NULL); * lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR); * * //... Set up the chart. * * // Add the chart to the chartsheet. * return workbook_close(workbook); * * } * @endcode * * @image html chartsheet.png * * The data for the chartsheet chart must be contained on a separate * worksheet. That is why it is always created in conjunction with at least * one data worksheet, as shown above. */ #ifndef __LXW_CHARTSHEET_H__ #define __LXW_CHARTSHEET_H__ #include #include "common.h" #include "worksheet.h" #include "drawing.h" #include "utility.h" /** * @brief Struct to represent an Excel chartsheet. * * The members of the lxw_chartsheet struct aren't modified directly. Instead * the chartsheet properties are set by calling the functions shown in * chartsheet.h. */ typedef struct lxw_chartsheet { FILE *file; lxw_worksheet *worksheet; lxw_chart *chart; struct lxw_protection_obj protection; uint8_t is_protected; const char *name; const char *quoted_name; const char *tmpdir; uint16_t index; uint8_t active; uint8_t selected; uint8_t hidden; uint16_t *active_sheet; uint16_t *first_sheet; uint16_t rel_count; STAILQ_ENTRY (lxw_chartsheet) list_pointers; } lxw_chartsheet; /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ /** * @brief Insert a chart object into a chartsheet. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param chart A #lxw_chart object created via workbook_add_chart(). * * @return A #lxw_error code. * * The `%chartsheet_set_chart()` function can be used to insert a chart into a * chartsheet. The chart object must be created first using the * `workbook_add_chart()` function and configured using the @ref chart.h * functions. * * @code * // Create the chartsheet. * lxw_chartsheet *chartsheet = workbook_add_chartsheet(workbook, NULL); * * // Create a chart object. * lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE); * * // Add a data series to the chart. * chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6"); * * // Insert the chart into the chartsheet. * chartsheet_set_chart(chartsheet, chart); * @endcode * * @image html chartsheet2.png * * **Note:** * * A chart may only be inserted once into a chartsheet or a worksheet. If * several similar charts are required then each one must be created * separately. * */ lxw_error chartsheet_set_chart(lxw_chartsheet *chartsheet, lxw_chart *chart); /* Not currently required since scale options aren't useful in a chartsheet. */ lxw_error chartsheet_set_chart_opt(lxw_chartsheet *chartsheet, lxw_chart *chart, lxw_chart_options *user_options); /** * @brief Make a chartsheet the active, i.e., visible chartsheet. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * * The `%chartsheet_activate()` function is used to specify which chartsheet * is initially visible in a multi-sheet workbook: * * @code * lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL); * lxw_chartsheet *chartsheet1 = workbook_add_chartsheet(workbook, NULL); * lxw_chartsheet *chartsheet2 = workbook_add_chartsheet(workbook, NULL); * lxw_chartsheet *chartsheet3 = workbook_add_chartsheet(workbook, NULL); * * chartsheet_activate(chartsheet3); * @endcode * * @image html chartsheet_activate.png * * More than one chartsheet can be selected via the `chartsheet_select()` * function, see below, however only one chartsheet can be active. * * The default active chartsheet is the first chartsheet. * * See also `worksheet_activate()`. * */ void chartsheet_activate(lxw_chartsheet *chartsheet); /** * @brief Set a chartsheet tab as selected. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * * The `%chartsheet_select()` function is used to indicate that a chartsheet * is selected in a multi-sheet workbook: * * @code * chartsheet_activate(chartsheet1); * chartsheet_select(chartsheet2); * chartsheet_select(chartsheet3); * * @endcode * * A selected chartsheet has its tab highlighted. Selecting chartsheets is a * way of grouping them together so that, for example, several chartsheets * could be printed in one go. A chartsheet that has been activated via the * `chartsheet_activate()` function will also appear as selected. * * See also `worksheet_select()`. * */ void chartsheet_select(lxw_chartsheet *chartsheet); /** * @brief Hide the current chartsheet. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * * The `%chartsheet_hide()` function is used to hide a chartsheet: * * @code * chartsheet_hide(chartsheet2); * @endcode * * You may wish to hide a chartsheet in order to avoid confusing a user with * intermediate data or calculations. * * @image html hide_sheet.png * * A hidden chartsheet can not be activated or selected so this function is * mutually exclusive with the `chartsheet_activate()` and * `chartsheet_select()` functions. In addition, since the first chartsheet * will default to being the active chartsheet, you cannot hide the first * chartsheet without activating another sheet: * * @code * chartsheet_activate(chartsheet2); * chartsheet_hide(chartsheet1); * @endcode * * See also `worksheet_hide()`. * */ void chartsheet_hide(lxw_chartsheet *chartsheet); /** * @brief Set current chartsheet as the first visible sheet tab. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * * The `chartsheet_activate()` function determines which chartsheet is * initially selected. However, if there are a large number of chartsheets the * selected chartsheet may not appear on the screen. To avoid this you can * select the leftmost visible chartsheet tab using * `%chartsheet_set_first_sheet()`: * * @code * chartsheet_set_first_sheet(chartsheet19); // First visible chartsheet tab. * chartsheet_activate(chartsheet20); // First visible chartsheet. * @endcode * * This function is not required very often. The default value is the first * chartsheet. * * See also `worksheet_set_first_sheet()`. * */ void chartsheet_set_first_sheet(lxw_chartsheet *chartsheet); /** * @brief Set the color of the chartsheet tab. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param color The tab color. * * The `%chartsheet_set_tab_color()` function is used to change the color of * the chartsheet tab: * * @code * chartsheet_set_tab_color(chartsheet1, LXW_COLOR_RED); * chartsheet_set_tab_color(chartsheet2, LXW_COLOR_GREEN); * chartsheet_set_tab_color(chartsheet3, 0xFF9900); // Orange. * @endcode * * The color should be an RGB integer value, see @ref working_with_colors. * * See also `worksheet_set_tab_color()`. */ void chartsheet_set_tab_color(lxw_chartsheet *chartsheet, lxw_color_t color); /** * @brief Protect elements of a chartsheet from modification. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param password A chartsheet password. * @param options Chartsheet elements to protect. * * The `%chartsheet_protect()` function protects chartsheet elements from * modification: * * @code * chartsheet_protect(chartsheet, "Some Password", options); * @endcode * * The `password` and lxw_protection pointer are both optional: * * @code * chartsheet_protect(chartsheet2, NULL, my_options); * chartsheet_protect(chartsheet3, "password", NULL); * chartsheet_protect(chartsheet4, "password", my_options); * @endcode * * Passing a `NULL` password is the same as turning on protection without a * password. Passing a `NULL` password and `NULL` options had no effect on * chartsheets. * * You can specify which chartsheet elements you wish to protect by passing a * lxw_protection pointer in the `options` argument. In Excel chartsheets only * have two protection options: * * no_content * no_objects * * All parameters are off by default. Individual elements can be protected as * follows: * * @code * lxw_protection options = { * .no_content = 1, * .no_objects = 1, * }; * * chartsheet_protect(chartsheet, NULL, &options); * * @endcode * * See also worksheet_protect(). * * **Note:** Sheet level passwords in Excel offer **very** weak * protection. They don't encrypt your data and are very easy to * deactivate. Full workbook encryption is not supported by `libxlsxwriter` * since it requires a completely different file format. */ void chartsheet_protect(lxw_chartsheet *chartsheet, const char *password, lxw_protection *options); /** * @brief Set the chartsheet zoom factor. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param scale Chartsheet zoom factor. * * Set the chartsheet zoom factor in the range `10 <= zoom <= 400`: * * @code * chartsheet_set_zoom(chartsheet, 75); * @endcode * * The default zoom factor is 100. It isn't possible to set the zoom to * "Selection" because it is calculated by Excel at run-time. * * See also `worksheet_set_zoom()`. */ void chartsheet_set_zoom(lxw_chartsheet *chartsheet, uint16_t scale); /** * @brief Set the page orientation as landscape. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * * This function is used to set the orientation of a chartsheet's printed page * to landscape. The default chartsheet orientation is landscape, so this * function isn't generally required: * * @code * chartsheet_set_landscape(chartsheet); * @endcode */ void chartsheet_set_landscape(lxw_chartsheet *chartsheet); /** * @brief Set the page orientation as portrait. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * * This function is used to set the orientation of a chartsheet's printed page * to portrait: * * @code * chartsheet_set_portrait(chartsheet); * @endcode */ void chartsheet_set_portrait(lxw_chartsheet *chartsheet); /** * @brief Set the paper type for printing. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param paper_type The Excel paper format type. * * This function is used to set the paper format for the printed output of a * chartsheet: * * @code * chartsheet_set_paper(chartsheet1, 1); // US Letter * chartsheet_set_paper(chartsheet2, 9); // A4 * @endcode * * If you do not specify a paper type the chartsheet will print using the * printer's default paper style. * * See `worksheet_set_paper()` for a full list of available paper sizes. */ void chartsheet_set_paper(lxw_chartsheet *chartsheet, uint8_t paper_type); /** * @brief Set the chartsheet margins for the printed page. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param left Left margin in inches. Excel default is 0.7. * @param right Right margin in inches. Excel default is 0.7. * @param top Top margin in inches. Excel default is 0.75. * @param bottom Bottom margin in inches. Excel default is 0.75. * * The `%chartsheet_set_margins()` function is used to set the margins of the * chartsheet when it is printed. The units are in inches. Specifying `-1` for * any parameter will give the default Excel value as shown above. * * @code * chartsheet_set_margins(chartsheet, 1.3, 1.2, -1, -1); * @endcode * */ void chartsheet_set_margins(lxw_chartsheet *chartsheet, double left, double right, double top, double bottom); /** * @brief Set the printed page header caption. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param string The header string. * * @return A #lxw_error code. * * Headers and footers are generated using a string which is a combination of * plain text and control characters * * @code * chartsheet_set_header(chartsheet, "&LHello"); * * // --------------------------------------------------------------- * // | | * // | Hello | * // | | * * * chartsheet_set_header(chartsheet, "&CHello"); * * // --------------------------------------------------------------- * // | | * // | Hello | * // | | * * * chartsheet_set_header(chartsheet, "&RHello"); * * // --------------------------------------------------------------- * // | | * // | Hello | * // | | * * * @endcode * * See `worksheet_set_header()` for a full explanation of the syntax of * Excel's header formatting and control characters. * */ lxw_error chartsheet_set_header(lxw_chartsheet *chartsheet, const char *string); /** * @brief Set the printed page footer caption. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param string The footer string. * * @return A #lxw_error code. * * The syntax of this function is the same as chartsheet_set_header(). * */ lxw_error chartsheet_set_footer(lxw_chartsheet *chartsheet, const char *string); /** * @brief Set the printed page header caption with additional options. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param string The header string. * @param options Header options. * * @return A #lxw_error code. * * The syntax of this function is the same as chartsheet_set_header() with an * additional parameter to specify options for the header. * * Currently, the only available option is the header margin: * * @code * * lxw_header_footer_options header_options = { 0.2 }; * * chartsheet_set_header_opt(chartsheet, "Some text", &header_options); * * @endcode * */ lxw_error chartsheet_set_header_opt(lxw_chartsheet *chartsheet, const char *string, lxw_header_footer_options *options); /** * @brief Set the printed page footer caption with additional options. * * @param chartsheet Pointer to a lxw_chartsheet instance to be updated. * @param string The footer string. * @param options Footer options. * * @return A #lxw_error code. * * The syntax of this function is the same as chartsheet_set_header_opt(). * */ lxw_error chartsheet_set_footer_opt(lxw_chartsheet *chartsheet, const char *string, lxw_header_footer_options *options); lxw_chartsheet *lxw_chartsheet_new(lxw_worksheet_init_data *init_data); void lxw_chartsheet_free(lxw_chartsheet *chartsheet); void lxw_chartsheet_assemble_xml_file(lxw_chartsheet *chartsheet); /* Declarations required for unit testing. */ #ifdef TESTING STATIC void _chartsheet_xml_declaration(lxw_chartsheet *chartsheet); STATIC void _chartsheet_write_sheet_protection(lxw_chartsheet *chartsheet); #endif /* TESTING */ /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* __LXW_CHARTSHEET_H__ */