libxlsxwriter/include/xlsxwriter/workbook.h in fast_excel-0.4.1 vs libxlsxwriter/include/xlsxwriter/workbook.h in fast_excel-0.5.0
- old
+ new
@@ -1,9 +1,9 @@
/*
* libxlsxwriter
*
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
+ * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*/
/**
* @page workbook_page The Workbook object
*
@@ -55,19 +55,20 @@
#define LXW_DEFINED_NAME_LENGTH 128
/* Define the tree.h RB structs for the red-black head types. */
RB_HEAD(lxw_worksheet_names, lxw_worksheet_name);
RB_HEAD(lxw_chartsheet_names, lxw_chartsheet_name);
+RB_HEAD(lxw_image_md5s, lxw_image_md5);
/* Define the queue.h structs for the workbook lists. */
STAILQ_HEAD(lxw_sheets, lxw_sheet);
STAILQ_HEAD(lxw_worksheets, lxw_worksheet);
STAILQ_HEAD(lxw_chartsheets, lxw_chartsheet);
STAILQ_HEAD(lxw_charts, lxw_chart);
TAILQ_HEAD(lxw_defined_names, lxw_defined_name);
-/* TODO */
+/* Struct to hold the 2 sheet types. */
typedef struct lxw_sheet {
uint8_t is_chartsheet;
union {
lxw_worksheet *worksheet;
@@ -91,10 +92,18 @@
lxw_chartsheet *chartsheet;
RB_ENTRY (lxw_chartsheet_name) tree_pointers;
} lxw_chartsheet_name;
+/* Struct to represent an image MD5/ID pair. */
+typedef struct lxw_image_md5 {
+ uint32_t id;
+ char *md5;
+
+ RB_ENTRY (lxw_image_md5) tree_pointers;
+} lxw_image_md5;
+
/* Wrapper around RB_GENERATE_STATIC from tree.h to avoid unused function
* warnings and to avoid portability issues with the _unused attribute. */
#define LXW_RB_GENERATE_WORKSHEET_NAMES(name, type, field, cmp) \
RB_GENERATE_INSERT_COLOR(name, type, field, static) \
RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
@@ -115,10 +124,21 @@
RB_GENERATE_NEXT(name, type, field, static) \
RB_GENERATE_MINMAX(name, type, field, static) \
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_charsheet_names{int unused;}
+#define LXW_RB_GENERATE_IMAGE_MD5S(name, type, field, cmp) \
+ RB_GENERATE_INSERT_COLOR(name, type, field, static) \
+ RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
+ RB_GENERATE_INSERT(name, type, field, cmp, static) \
+ RB_GENERATE_REMOVE(name, type, field, static) \
+ RB_GENERATE_FIND(name, type, field, cmp, static) \
+ RB_GENERATE_NEXT(name, type, field, static) \
+ RB_GENERATE_MINMAX(name, type, field, static) \
+ /* Add unused struct to allow adding a semicolon */ \
+ struct lxw_rb_generate_image_md5s{int unused;}
+
/**
* @brief Macro to loop over all the worksheets in a workbook.
*
* This macro allows you to loop over all the worksheets that have been
* added to a workbook. You must provide a lxw_worksheet pointer and
@@ -156,43 +176,47 @@
/* List pointers for queue.h. */
TAILQ_ENTRY (lxw_defined_name) list_pointers;
} lxw_defined_name;
/**
- * Workbook document properties.
+ * Workbook document properties. Set any unused fields to NULL or 0.
*/
typedef struct lxw_doc_properties {
/** The title of the Excel Document. */
- char *title;
+ const char *title;
/** The subject of the Excel Document. */
- char *subject;
+ const char *subject;
/** The author of the Excel Document. */
- char *author;
+ const char *author;
/** The manager field of the Excel Document. */
- char *manager;
+ const char *manager;
/** The company field of the Excel Document. */
- char *company;
+ const char *company;
/** The category of the Excel Document. */
- char *category;
+ const char *category;
/** The keywords of the Excel Document. */
- char *keywords;
+ const char *keywords;
/** The comment field of the Excel Document. */
- char *comments;
+ const char *comments;
/** The status of the Excel Document. */
- char *status;
+ const char *status;
- /** The hyperlink base url of the Excel Document. */
- char *hyperlink_base;
+ /** The hyperlink base URL of the Excel Document. */
+ const char *hyperlink_base;
+ /** The file creation date/time shown in Excel. This defaults to the
+ * current time and date if set to 0. If you wish to create files that are
+ * binary equivalent (for the same input data) then you should set this
+ * creation date/time to a known value. */
time_t created;
} lxw_doc_properties;
/**
@@ -203,11 +227,11 @@
*
* The following properties are supported:
*
* - `constant_memory`: This option reduces the amount of data stored in
* memory so that large files can be written efficiently. This option is off
- * by default. See the note below for limitations when this mode is on.
+ * by default. See the notes below for limitations when this mode is on.
*
* - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior to
* assembling the final XLSX file. The temporary files are created in the
* system's temp directory. If the default temporary directory isn't
* accessible to your application, or doesn't contain enough space, you can
@@ -217,28 +241,47 @@
* large xlsx files to allow the zip container, or individual XML files
* within it, to be greater than 4 GB. See [ZIP64 on Wikipedia][zip64_wiki]
* for more information. This option is off by default.
*
* [zip64_wiki]: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
+
+ * - `output_buffer`: Output to a buffer instead of a file. The buffer must be
+ * freed manually by calling free(). This option can only be used if filename
+ * is NULL.
*
- * @note In `constant_memory` mode a row of data is written and then discarded
- * when a cell in a new row is added via one of the `worksheet_write_*()`
- * functions. Therefore, once this option is active, data should be written in
- * sequential row order. For this reason the `worksheet_merge_range()` doesn't
- * work in this mode. See also @ref ww_mem_constant.
+ * - `output_buffer_size`: Used with output_buffer to get the size of the
+ * created buffer. This option can only be used if filename is NULL.
*
+ * @note In `constant_memory` mode each row of in-memory data is written to
+ * disk and then freed when a new row is started via one of the
+ * `worksheet_write_*()` functions. Therefore, once this option is active data
+ * should be written in sequential row by row order. For this reason
+ * `worksheet_merge_range()` and some other row based functionality doesn't
+ * work in this mode. See @ref ww_mem_constant for more details.
+ *
+ * @note Also, in `constant_memory` mode the library uses temp file storage
+ * for worksheet data. This can lead to an issue on OSes that map the `/tmp`
+ * directory into memory since it is possible to consume the "system" memory
+ * even though the "process" memory remains constant. In these cases you
+ * should use an alternative temp file location by using the `tmpdir` option
+ * shown above. See @ref ww_mem_temp for more details.
*/
typedef struct lxw_workbook_options {
/** Optimize the workbook to use constant memory for worksheets. */
uint8_t constant_memory;
/** Directory to use for the temporary files created by libxlsxwriter. */
- char *tmpdir;
+ const char *tmpdir;
/** Allow ZIP64 extensions when creating the xlsx file zip container. */
uint8_t use_zip64;
+ /** Output buffer to use instead of writing to a file */
+ const char **output_buffer;
+
+ /** Used with output_buffer to get the size of the created buffer */
+ size_t *output_buffer_size;
} lxw_workbook_options;
/**
* @brief Struct to represent an Excel workbook.
*
@@ -252,10 +295,13 @@
struct lxw_sheets *sheets;
struct lxw_worksheets *worksheets;
struct lxw_chartsheets *chartsheets;
struct lxw_worksheet_names *worksheet_names;
struct lxw_chartsheet_names *chartsheet_names;
+ struct lxw_image_md5s *image_md5s;
+ struct lxw_image_md5s *header_image_md5s;
+ struct lxw_image_md5s *background_md5s;
struct lxw_charts *charts;
struct lxw_charts *ordered_charts;
struct lxw_formats *formats;
struct lxw_defined_names *defined_names;
lxw_sst *sst;
@@ -269,27 +315,39 @@
uint16_t num_worksheets;
uint16_t num_chartsheets;
uint16_t first_sheet;
uint16_t active_sheet;
uint16_t num_xf_formats;
+ uint16_t num_dxf_formats;
uint16_t num_format_count;
uint16_t drawing_count;
+ uint16_t comment_count;
uint16_t font_count;
uint16_t border_count;
uint16_t fill_count;
uint8_t optimize;
+ uint16_t max_url_length;
+ uint8_t read_only;
uint8_t has_png;
uint8_t has_jpeg;
uint8_t has_bmp;
+ uint8_t has_gif;
+ uint8_t has_vml;
+ uint8_t has_comments;
+ uint8_t has_metadata;
lxw_hash_table *used_xf_formats;
+ lxw_hash_table *used_dxf_formats;
char *vba_project;
+ char *vba_project_signature;
char *vba_codename;
+ lxw_format *default_url_format;
+
} lxw_workbook;
/* *INDENT-OFF* */
#ifdef __cplusplus
@@ -329,11 +387,13 @@
* additional options to be set.
*
* @code
* lxw_workbook_options options = {.constant_memory = LXW_TRUE,
* .tmpdir = "C:\\Temp",
- * .use_zip64 = LXW_FALSE};
+ * .use_zip64 = LXW_FALSE,
+ * .output_buffer = NULL,
+ * .output_buffer_size = NULL};
*
* lxw_workbook *workbook = workbook_new_opt("filename.xlsx", &options);
* @endcode
*
* The options that can be set via #lxw_workbook_options are:
@@ -353,27 +413,34 @@
* within it, to be greater than 4 GB. See [ZIP64 on Wikipedia][zip64_wiki]
* for more information. This option is off by default.
*
* [zip64_wiki]: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
*
- * @note In `constant_memory` mode a row of data is written and then discarded
- * when a cell in a new row is added via one of the `worksheet_write_*()`
- * functions. Therefore, once this option is active, data should be written in
- * sequential row order. For this reason the `worksheet_merge_range()` doesn't
- * work in this mode. See also @ref ww_mem_constant.
+ * - `output_buffer`: Output to a memory buffer instead of a file. The buffer
+ * must be freed manually by calling `free()`. This option can only be used if
+ * filename is NULL.
*
+ * - `output_buffer_size`: Used with output_buffer to get the size of the
+ * created buffer. This option can only be used if filename is `NULL`.
+ *
+ * @note In `constant_memory` mode each row of in-memory data is written to
+ * disk and then freed when a new row is started via one of the
+ * `worksheet_write_*()` functions. Therefore, once this option is active data
+ * should be written in sequential row by row order. For this reason
+ * `worksheet_merge_range()` and some other row based functionality doesn't
+ * work in this mode. See @ref ww_mem_constant for more details.
+ *
+ * @note Also, in `constant_memory` mode the library uses temp file storage
+ * for worksheet data. This can lead to an issue on OSes that map the `/tmp`
+ * directory into memory since it is possible to consume the "system" memory
+ * even though the "process" memory remains constant. In these cases you
+ * should use an alternative temp file location by using the `tmpdir` option
+ * shown above. See @ref ww_mem_temp for more details.
*/
lxw_workbook *workbook_new_opt(const char *filename,
lxw_workbook_options *options);
-/* Deprecated function name for backwards compatibility. */
-lxw_workbook *new_workbook(const char *filename);
-
-/* Deprecated function name for backwards compatibility. */
-lxw_workbook *new_workbook_opt(const char *filename,
- lxw_workbook_options *options);
-
/**
* @brief Add a new worksheet to a workbook.
*
* @param workbook Pointer to a lxw_workbook instance.
* @param sheetname Optional worksheet name, defaults to Sheet1, etc.
@@ -402,16 +469,19 @@
* The worksheet name must be a valid Excel worksheet name, i.e:
*
* - The name is less than or equal to 31 UTF-8 characters.
* - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
* - The name doesn't start or end with an apostrophe.
- * - The name isn't "History", which is reserved by Excel. (Case insensitive).
* - The name isn't already in use. (Case insensitive).
*
* If any of these errors are encountered the function will return NULL.
* You can check for valid name using the `workbook_validate_sheet_name()`
* function.
+ *
+ * @note You should also avoid using the worksheet name "History" (case
+ * insensitive) which is reserved in English language versions of
+ * Excel. Non-English versions may have restrictions on the equivalent word.
*/
lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
const char *sheetname);
/**
@@ -441,17 +511,20 @@
* The chartsheet name must be a valid Excel worksheet name, i.e.:
*
* - The name is less than or equal to 31 UTF-8 characters.
* - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
* - The name doesn't start or end with an apostrophe.
- * - The name isn't "History", which is reserved by Excel. (Case insensitive).
* - The name isn't already in use. (Case insensitive).
*
* If any of these errors are encountered the function will return NULL.
* You can check for valid name using the `workbook_validate_sheet_name()`
* function.
*
+ * @note You should also avoid using the worksheet name "History" (case
+ * insensitive) which is reserved in English language versions of
+ * Excel. Non-English versions may have restrictions on the equivalent word.
+ *
* At least one worksheet should be added to a new workbook when creating a
* chartsheet in order to provide data for the chart. The @ref worksheet.h
* "Worksheet" object is used to write data and configure a worksheet in the
* workbook.
*/
@@ -531,10 +604,12 @@
* | #LXW_CHART_COLUMN | Column chart. |
* | #LXW_CHART_COLUMN_STACKED | Column chart - stacked. |
* | #LXW_CHART_COLUMN_STACKED_PERCENT | Column chart - percentage stacked. |
* | #LXW_CHART_DOUGHNUT | Doughnut chart. |
* | #LXW_CHART_LINE | Line chart. |
+ * | #LXW_CHART_LINE_STACKED | Line chart - stacked. |
+ * | #LXW_CHART_LINE_STACKED_PERCENT | Line chart - percentage stacked. |
* | #LXW_CHART_PIE | Pie chart. |
* | #LXW_CHART_SCATTER | Scatter chart. |
* | #LXW_CHART_SCATTER_STRAIGHT | Scatter chart - straight. |
* | #LXW_CHART_SCATTER_STRAIGHT_WITH_MARKERS | Scatter chart - straight with markers. |
* | #LXW_CHART_SCATTER_SMOOTH | Scatter chart - smooth. |
@@ -598,14 +673,15 @@
* - `company`
* - `category`
* - `keywords`
* - `comments`
* - `hyperlink_base`
+ * - `created`
*
* The properties are specified via a `lxw_doc_properties` struct. All the
- * members are `char *` and they are all optional. An example of how to create
- * and pass the properties is:
+ * fields are all optional. An example of how to create and pass the
+ * properties is:
*
* @code
* // Create a properties structure and set some of the fields.
* lxw_doc_properties properties = {
* .title = "This is an example spreadsheet",
@@ -623,10 +699,16 @@
* workbook_set_properties(workbook, &properties);
* @endcode
*
* @image html doc_properties.png
*
+ * The `created` parameter sets the file creation date/time shown in
+ * Excel. This defaults to the current time and date if set to 0. If you wish
+ * to create files that are binary equivalent (for the same input data) then
+ * you should set this creation date/time to a known value using a `time_t`
+ * value.
+ *
*/
lxw_error workbook_set_properties(lxw_workbook *workbook,
lxw_doc_properties *properties);
/**
@@ -775,18 +857,37 @@
* @code
* workbook_define_name(workbook, "'New Data'!Sales", "=Sheet2!$G$1:$G$10");
* @endcode
*
* The rules for names in Excel are explained in the
- * [Microsoft Office
-documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
+ * [Microsoft Office documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
*
*/
lxw_error workbook_define_name(lxw_workbook *workbook, const char *name,
const char *formula);
/**
+ * @brief Get the default URL format used with `worksheet_write_url()`.
+ *
+ * @param workbook Pointer to a lxw_workbook instance.
+ * @return A lxw_format instance that has hyperlink properties set.
+ *
+ * This function returns a lxw_format instance that is used for the default
+ * blue underline hyperlink in the `worksheet_write_url()` function when a
+ * format isn't specified:
+ *
+ * @code
+ * lxw_format *url_format = workbook_get_default_url_format(workbook);
+ * @endcode
+ *
+ * The format is the hyperlink style defined by Excel for the default theme.
+ * This format is only ever required when overwriting a string URL with
+ * data of a different type. See the example below.
+ */
+lxw_format *workbook_get_default_url_format(lxw_workbook *workbook);
+
+/**
* @brief Get a worksheet object from its name.
*
* @param workbook Pointer to a lxw_workbook instance.
* @param name Worksheet name.
*
@@ -832,21 +933,24 @@
* to the rules used by Excel:
*
* - The name is less than or equal to 31 UTF-8 characters.
* - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
* - The name doesn't start or end with an apostrophe.
- * - The name isn't "History", which is reserved by Excel. (Case insensitive).
* - The name isn't already in use. (Case insensitive, see the note below).
*
* @code
* lxw_error err = workbook_validate_sheet_name(workbook, "Foglio");
* @endcode
*
* This function is called by `workbook_add_worksheet()` and
* `workbook_add_chartsheet()` but it can be explicitly called by the user
* beforehand to ensure that the sheet name is valid.
*
+ * @note You should also avoid using the worksheet name "History" (case
+ * insensitive) which is reserved in English language versions of
+ * Excel. Non-English versions may have restrictions on the equivalent word.
+ *
* @note This function does an ASCII lowercase string comparison to determine
* if the sheet name is already in use. It doesn't take UTF-8 characters into
* account. Thus it would flag "Café" and "café" as a duplicate (just like
* Excel) but it wouldn't catch "CAFÉ". If you need a full UTF-8 case
* insensitive check you should use a third party library to implement it.
@@ -867,39 +971,106 @@
*
* @code
* workbook_add_vba_project(workbook, "vbaProject.bin");
* @endcode
*
- * Only one `vbaProject.bin file` can be added per workbook.
+ * Only one `vbaProject.bin` file can be added per workbook. The name doesn't
+ * have to be `vbaProject.bin`. Any suitable path/name for an existing VBA bin
+ * file will do.
*
+ * Once you add a VBA project had been add to an libxlsxwriter workbook you
+ * should ensure that the file extension is `.xlsm` to prevent Excel from
+ * giving a warning when it opens the file:
+ *
+ * @code
+ * lxw_workbook *workbook = new_workbook("macro.xlsm");
+ * @endcode
+ *
+ * See also @ref working_with_macros
+ *
* @return A #lxw_error.
*/
lxw_error workbook_add_vba_project(lxw_workbook *workbook,
const char *filename);
/**
+ * @brief Add a vbaProject binary and a vbaProjectSignature binary to the Excel
+ * workbook.
+ *
+ * @param workbook Pointer to a lxw_workbook instance.
+ * @param vba_project The path/filename of the vbaProject.bin file.
+ * @param signature The path/filename of the vbaProjectSignature.bin file.
+ *
+ * The `%workbook_add_signed_vba_project()` function can be used to add digitally
+ * signed macros or functions to a workbook. The function adds a binary VBA project
+ * file and a binary VBA project signature file that have been extracted from an
+ * existing Excel xlsm file with digitally signed macros:
+ *
+ * @code
+ * workbook_add_signed_vba_project(workbook, "vbaProject.bin", "vbaProjectSignature.bin");
+ * @endcode
+ *
+ * Only one `vbaProject.bin` file can be added per workbook. The name doesn't
+ * have to be `vbaProject.bin`. Any suitable path/name for an existing VBA bin
+ * file will do. The same applies for `vbaProjectSignature.bin`.
+ *
+ * See also @ref working_with_macros
+ *
+ * @return A #lxw_error.
+ */
+lxw_error workbook_add_signed_vba_project(lxw_workbook *workbook,
+ const char *vba_project,
+ const char *signature);
+
+/**
* @brief Set the VBA name for the workbook.
*
* @param workbook Pointer to a lxw_workbook instance.
* @param name Name of the workbook used by VBA.
*
* The `workbook_set_vba_name()` function can be used to set the VBA name for
* the workbook. This is sometimes required when a vbaProject macro included
- * via `workbook_add_vba_project()` refers to the workbook.
+ * via `workbook_add_vba_project()` refers to the workbook by a name other
+ * than `ThisWorkbook`.
*
* @code
* workbook_set_vba_name(workbook, "MyWorkbook");
* @endcode
*
- * The most common Excel VBA name for a workbook is `ThisWorkbook`.
+ * If an Excel VBA name for the workbook isn't specified then libxlsxwriter
+ * will use `ThisWorkbook`.
*
+ * See also @ref working_with_macros
+ *
* @return A #lxw_error.
*/
lxw_error workbook_set_vba_name(lxw_workbook *workbook, const char *name);
+/**
+ * @brief Add a recommendation to open the file in "read-only" mode.
+ *
+ * @param workbook Pointer to a lxw_workbook instance.
+ *
+ * This function can be used to set the Excel "Read-only Recommended" option
+ * that is available when saving a file. This presents the user of the file
+ * with an option to open it in "read-only" mode. This means that any changes
+ * to the file can't be saved back to the same file and must be saved to a new
+ * file. It can be set as follows:
+ *
+ * @code
+ * workbook_read_only_recommended(workbook);
+ * @endcode
+ *
+ * Which will raise a dialog like the following when opening the file:
+ *
+ * @image html read_only.png
+ */
+void workbook_read_only_recommended(lxw_workbook *workbook);
+
void lxw_workbook_free(lxw_workbook *workbook);
void lxw_workbook_assemble_xml_file(lxw_workbook *workbook);
void lxw_workbook_set_default_xf_indices(lxw_workbook *workbook);
+void workbook_unset_default_url_format(lxw_workbook *workbook);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _workbook_xml_declaration(lxw_workbook *self);