fast_excel 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -7
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile +1 -1
  5. data/examples/example.rb +2 -0
  6. data/examples/example_date_time.rb +38 -0
  7. data/fast_excel.gemspec +2 -2
  8. data/lib/fast_excel/binding/format.rb +17 -0
  9. data/lib/fast_excel/binding/workbook.rb +39 -17
  10. data/lib/fast_excel/binding/worksheet.rb +57 -13
  11. data/lib/fast_excel/binding.rb +7 -7
  12. data/lib/fast_excel.rb +27 -20
  13. data/libxlsxwriter/.github/FUNDING.yml +1 -0
  14. data/libxlsxwriter/.github/ISSUE_TEMPLATE.md +85 -0
  15. data/libxlsxwriter/.github/PULL_REQUEST_TEMPLATE.md +130 -0
  16. data/libxlsxwriter/.github/workflows/cmake_actions.yml +48 -0
  17. data/libxlsxwriter/.github/workflows/code_style.yml +23 -0
  18. data/libxlsxwriter/.github/workflows/coverity.yml +22 -0
  19. data/libxlsxwriter/.github/workflows/make_actions.yml +52 -0
  20. data/libxlsxwriter/.github/workflows/valgrind.yml +23 -0
  21. data/libxlsxwriter/.github/workflows/windows_build.yml +54 -0
  22. data/libxlsxwriter/.github/workflows/zig_build.yml +22 -0
  23. data/libxlsxwriter/.gitignore +16 -1
  24. data/libxlsxwriter/.indent.pro +24 -0
  25. data/libxlsxwriter/CMakeLists.txt +156 -56
  26. data/libxlsxwriter/CONTRIBUTING.md +2 -2
  27. data/libxlsxwriter/Changes.txt +344 -2
  28. data/libxlsxwriter/LICENSE.txt +66 -8
  29. data/libxlsxwriter/Makefile +151 -54
  30. data/libxlsxwriter/Package.swift +42 -0
  31. data/libxlsxwriter/Readme.md +4 -2
  32. data/libxlsxwriter/build.zig +324 -0
  33. data/libxlsxwriter/build.zig.zon +11 -0
  34. data/libxlsxwriter/cmake/FindMINIZIP.cmake +3 -3
  35. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +6 -0
  36. data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
  37. data/libxlsxwriter/include/xlsxwriter/chart.h +236 -32
  38. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +7 -7
  39. data/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
  40. data/libxlsxwriter/include/xlsxwriter/common.h +111 -50
  41. data/libxlsxwriter/include/xlsxwriter/content_types.h +8 -1
  42. data/libxlsxwriter/include/xlsxwriter/core.h +1 -1
  43. data/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
  44. data/libxlsxwriter/include/xlsxwriter/drawing.h +11 -20
  45. data/libxlsxwriter/include/xlsxwriter/format.h +121 -8
  46. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  47. data/libxlsxwriter/include/xlsxwriter/metadata.h +49 -0
  48. data/libxlsxwriter/include/xlsxwriter/packager.h +27 -16
  49. data/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
  50. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
  51. data/libxlsxwriter/include/xlsxwriter/styles.h +13 -7
  52. data/libxlsxwriter/include/xlsxwriter/table.h +51 -0
  53. data/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
  54. data/libxlsxwriter/include/xlsxwriter/third_party/emyg_dtoa.h +26 -0
  55. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +27 -25
  56. data/libxlsxwriter/include/xlsxwriter/third_party/md5.h +45 -0
  57. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +155 -153
  58. data/libxlsxwriter/include/xlsxwriter/utility.h +70 -8
  59. data/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
  60. data/libxlsxwriter/include/xlsxwriter/workbook.h +218 -47
  61. data/libxlsxwriter/include/xlsxwriter/worksheet.h +2770 -241
  62. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +12 -8
  63. data/libxlsxwriter/include/xlsxwriter.h +4 -2
  64. data/libxlsxwriter/libxlsxwriter.podspec +8 -5
  65. data/libxlsxwriter/src/Makefile +58 -21
  66. data/libxlsxwriter/src/app.c +5 -2
  67. data/libxlsxwriter/src/chart.c +396 -81
  68. data/libxlsxwriter/src/chartsheet.c +22 -22
  69. data/libxlsxwriter/src/comment.c +443 -0
  70. data/libxlsxwriter/src/content_types.c +40 -1
  71. data/libxlsxwriter/src/core.c +2 -2
  72. data/libxlsxwriter/src/custom.c +1 -1
  73. data/libxlsxwriter/src/drawing.c +160 -40
  74. data/libxlsxwriter/src/format.c +109 -25
  75. data/libxlsxwriter/src/hash_table.c +1 -1
  76. data/libxlsxwriter/src/metadata.c +283 -0
  77. data/libxlsxwriter/src/packager.c +794 -94
  78. data/libxlsxwriter/src/relationships.c +1 -1
  79. data/libxlsxwriter/src/shared_strings.c +2 -4
  80. data/libxlsxwriter/src/styles.c +353 -58
  81. data/libxlsxwriter/src/table.c +304 -0
  82. data/libxlsxwriter/src/theme.c +1 -1
  83. data/libxlsxwriter/src/utility.c +143 -43
  84. data/libxlsxwriter/src/vml.c +1062 -0
  85. data/libxlsxwriter/src/workbook.c +567 -77
  86. data/libxlsxwriter/src/worksheet.c +6668 -1462
  87. data/libxlsxwriter/src/xmlwriter.c +95 -5
  88. data/libxlsxwriter/third_party/dtoa/Makefile +42 -0
  89. data/libxlsxwriter/third_party/dtoa/emyg_dtoa.c +461 -0
  90. data/libxlsxwriter/third_party/dtoa/emyg_dtoa.h +26 -0
  91. data/libxlsxwriter/third_party/md5/Makefile +42 -0
  92. data/libxlsxwriter/third_party/md5/md5.c +291 -0
  93. data/libxlsxwriter/third_party/md5/md5.h +45 -0
  94. data/libxlsxwriter/third_party/minizip/Makefile +3 -8
  95. data/libxlsxwriter/third_party/minizip/Makefile.orig +8 -4
  96. data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +1 -1
  97. data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
  98. data/libxlsxwriter/third_party/minizip/crypt.h +13 -16
  99. data/libxlsxwriter/third_party/minizip/ioapi.c +31 -57
  100. data/libxlsxwriter/third_party/minizip/ioapi.h +31 -23
  101. data/libxlsxwriter/third_party/minizip/iowin32.c +29 -45
  102. data/libxlsxwriter/third_party/minizip/iowin32.h +4 -4
  103. data/libxlsxwriter/third_party/minizip/miniunz.c +29 -56
  104. data/libxlsxwriter/third_party/minizip/minizip.c +38 -49
  105. data/libxlsxwriter/third_party/minizip/mztools.c +1 -7
  106. data/libxlsxwriter/third_party/minizip/unzip.c +202 -342
  107. data/libxlsxwriter/third_party/minizip/unzip.h +74 -74
  108. data/libxlsxwriter/third_party/minizip/zip.c +165 -218
  109. data/libxlsxwriter/third_party/minizip/zip.h +164 -154
  110. data/libxlsxwriter/third_party/tmpfileplus/Makefile +3 -3
  111. data/libxlsxwriter/version.txt +1 -1
  112. data/test/auto_width_test.rb +20 -0
  113. data/test/default_format_test.rb +1 -1
  114. data/test/validations_test.rb +3 -3
  115. data/test/worksheet_test.rb +6 -1
  116. metadata +33 -7
  117. data/libxlsxwriter/.travis.yml +0 -37
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5
5
  */
6
6
 
7
7
  /**
@@ -57,6 +57,7 @@
57
57
  /* Define the tree.h RB structs for the red-black head types. */
58
58
  RB_HEAD(lxw_worksheet_names, lxw_worksheet_name);
59
59
  RB_HEAD(lxw_chartsheet_names, lxw_chartsheet_name);
60
+ RB_HEAD(lxw_image_md5s, lxw_image_md5);
60
61
 
61
62
  /* Define the queue.h structs for the workbook lists. */
62
63
  STAILQ_HEAD(lxw_sheets, lxw_sheet);
@@ -65,7 +66,7 @@ STAILQ_HEAD(lxw_chartsheets, lxw_chartsheet);
65
66
  STAILQ_HEAD(lxw_charts, lxw_chart);
66
67
  TAILQ_HEAD(lxw_defined_names, lxw_defined_name);
67
68
 
68
- /* TODO */
69
+ /* Struct to hold the 2 sheet types. */
69
70
  typedef struct lxw_sheet {
70
71
  uint8_t is_chartsheet;
71
72
 
@@ -93,6 +94,14 @@ typedef struct lxw_chartsheet_name {
93
94
  RB_ENTRY (lxw_chartsheet_name) tree_pointers;
94
95
  } lxw_chartsheet_name;
95
96
 
97
+ /* Struct to represent an image MD5/ID pair. */
98
+ typedef struct lxw_image_md5 {
99
+ uint32_t id;
100
+ char *md5;
101
+
102
+ RB_ENTRY (lxw_image_md5) tree_pointers;
103
+ } lxw_image_md5;
104
+
96
105
  /* Wrapper around RB_GENERATE_STATIC from tree.h to avoid unused function
97
106
  * warnings and to avoid portability issues with the _unused attribute. */
98
107
  #define LXW_RB_GENERATE_WORKSHEET_NAMES(name, type, field, cmp) \
@@ -117,6 +126,17 @@ typedef struct lxw_chartsheet_name {
117
126
  /* Add unused struct to allow adding a semicolon */ \
118
127
  struct lxw_rb_generate_charsheet_names{int unused;}
119
128
 
129
+ #define LXW_RB_GENERATE_IMAGE_MD5S(name, type, field, cmp) \
130
+ RB_GENERATE_INSERT_COLOR(name, type, field, static) \
131
+ RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
132
+ RB_GENERATE_INSERT(name, type, field, cmp, static) \
133
+ RB_GENERATE_REMOVE(name, type, field, static) \
134
+ RB_GENERATE_FIND(name, type, field, cmp, static) \
135
+ RB_GENERATE_NEXT(name, type, field, static) \
136
+ RB_GENERATE_MINMAX(name, type, field, static) \
137
+ /* Add unused struct to allow adding a semicolon */ \
138
+ struct lxw_rb_generate_image_md5s{int unused;}
139
+
120
140
  /**
121
141
  * @brief Macro to loop over all the worksheets in a workbook.
122
142
  *
@@ -158,39 +178,43 @@ typedef struct lxw_defined_name {
158
178
  } lxw_defined_name;
159
179
 
160
180
  /**
161
- * Workbook document properties.
181
+ * Workbook document properties. Set any unused fields to NULL or 0.
162
182
  */
163
183
  typedef struct lxw_doc_properties {
164
184
  /** The title of the Excel Document. */
165
- char *title;
185
+ const char *title;
166
186
 
167
187
  /** The subject of the Excel Document. */
168
- char *subject;
188
+ const char *subject;
169
189
 
170
190
  /** The author of the Excel Document. */
171
- char *author;
191
+ const char *author;
172
192
 
173
193
  /** The manager field of the Excel Document. */
174
- char *manager;
194
+ const char *manager;
175
195
 
176
196
  /** The company field of the Excel Document. */
177
- char *company;
197
+ const char *company;
178
198
 
179
199
  /** The category of the Excel Document. */
180
- char *category;
200
+ const char *category;
181
201
 
182
202
  /** The keywords of the Excel Document. */
183
- char *keywords;
203
+ const char *keywords;
184
204
 
185
205
  /** The comment field of the Excel Document. */
186
- char *comments;
206
+ const char *comments;
187
207
 
188
208
  /** The status of the Excel Document. */
189
- char *status;
209
+ const char *status;
190
210
 
191
- /** The hyperlink base url of the Excel Document. */
192
- char *hyperlink_base;
211
+ /** The hyperlink base URL of the Excel Document. */
212
+ const char *hyperlink_base;
193
213
 
214
+ /** The file creation date/time shown in Excel. This defaults to the
215
+ * current time and date if set to 0. If you wish to create files that are
216
+ * binary equivalent (for the same input data) then you should set this
217
+ * creation date/time to a known value. */
194
218
  time_t created;
195
219
 
196
220
  } lxw_doc_properties;
@@ -205,7 +229,7 @@ typedef struct lxw_doc_properties {
205
229
  *
206
230
  * - `constant_memory`: This option reduces the amount of data stored in
207
231
  * memory so that large files can be written efficiently. This option is off
208
- * by default. See the note below for limitations when this mode is on.
232
+ * by default. See the notes below for limitations when this mode is on.
209
233
  *
210
234
  * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior to
211
235
  * assembling the final XLSX file. The temporary files are created in the
@@ -219,24 +243,43 @@ typedef struct lxw_doc_properties {
219
243
  * for more information. This option is off by default.
220
244
  *
221
245
  * [zip64_wiki]: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
222
- *
223
- * @note In `constant_memory` mode a row of data is written and then discarded
224
- * when a cell in a new row is added via one of the `worksheet_write_*()`
225
- * functions. Therefore, once this option is active, data should be written in
226
- * sequential row order. For this reason the `worksheet_merge_range()` doesn't
227
- * work in this mode. See also @ref ww_mem_constant.
228
- *
246
+
247
+ * - `output_buffer`: Output to a buffer instead of a file. The buffer must be
248
+ * freed manually by calling free(). This option can only be used if filename
249
+ * is NULL.
250
+ *
251
+ * - `output_buffer_size`: Used with output_buffer to get the size of the
252
+ * created buffer. This option can only be used if filename is NULL.
253
+ *
254
+ * @note In `constant_memory` mode each row of in-memory data is written to
255
+ * disk and then freed when a new row is started via one of the
256
+ * `worksheet_write_*()` functions. Therefore, once this option is active data
257
+ * should be written in sequential row by row order. For this reason
258
+ * `worksheet_merge_range()` and some other row based functionality doesn't
259
+ * work in this mode. See @ref ww_mem_constant for more details.
260
+ *
261
+ * @note Also, in `constant_memory` mode the library uses temp file storage
262
+ * for worksheet data. This can lead to an issue on OSes that map the `/tmp`
263
+ * directory into memory since it is possible to consume the "system" memory
264
+ * even though the "process" memory remains constant. In these cases you
265
+ * should use an alternative temp file location by using the `tmpdir` option
266
+ * shown above. See @ref ww_mem_temp for more details.
229
267
  */
230
268
  typedef struct lxw_workbook_options {
231
269
  /** Optimize the workbook to use constant memory for worksheets. */
232
270
  uint8_t constant_memory;
233
271
 
234
272
  /** Directory to use for the temporary files created by libxlsxwriter. */
235
- char *tmpdir;
273
+ const char *tmpdir;
236
274
 
237
275
  /** Allow ZIP64 extensions when creating the xlsx file zip container. */
238
276
  uint8_t use_zip64;
239
277
 
278
+ /** Output buffer to use instead of writing to a file */
279
+ const char **output_buffer;
280
+
281
+ /** Used with output_buffer to get the size of the created buffer */
282
+ size_t *output_buffer_size;
240
283
  } lxw_workbook_options;
241
284
 
242
285
  /**
@@ -254,6 +297,9 @@ typedef struct lxw_workbook {
254
297
  struct lxw_chartsheets *chartsheets;
255
298
  struct lxw_worksheet_names *worksheet_names;
256
299
  struct lxw_chartsheet_names *chartsheet_names;
300
+ struct lxw_image_md5s *image_md5s;
301
+ struct lxw_image_md5s *header_image_md5s;
302
+ struct lxw_image_md5s *background_md5s;
257
303
  struct lxw_charts *charts;
258
304
  struct lxw_charts *ordered_charts;
259
305
  struct lxw_formats *formats;
@@ -271,23 +317,35 @@ typedef struct lxw_workbook {
271
317
  uint16_t first_sheet;
272
318
  uint16_t active_sheet;
273
319
  uint16_t num_xf_formats;
320
+ uint16_t num_dxf_formats;
274
321
  uint16_t num_format_count;
275
322
  uint16_t drawing_count;
323
+ uint16_t comment_count;
276
324
 
277
325
  uint16_t font_count;
278
326
  uint16_t border_count;
279
327
  uint16_t fill_count;
280
328
  uint8_t optimize;
329
+ uint16_t max_url_length;
330
+ uint8_t read_only;
281
331
 
282
332
  uint8_t has_png;
283
333
  uint8_t has_jpeg;
284
334
  uint8_t has_bmp;
335
+ uint8_t has_gif;
336
+ uint8_t has_vml;
337
+ uint8_t has_comments;
338
+ uint8_t has_metadata;
285
339
 
286
340
  lxw_hash_table *used_xf_formats;
341
+ lxw_hash_table *used_dxf_formats;
287
342
 
288
343
  char *vba_project;
344
+ char *vba_project_signature;
289
345
  char *vba_codename;
290
346
 
347
+ lxw_format *default_url_format;
348
+
291
349
  } lxw_workbook;
292
350
 
293
351
 
@@ -331,7 +389,9 @@ lxw_workbook *workbook_new(const char *filename);
331
389
  * @code
332
390
  * lxw_workbook_options options = {.constant_memory = LXW_TRUE,
333
391
  * .tmpdir = "C:\\Temp",
334
- * .use_zip64 = LXW_FALSE};
392
+ * .use_zip64 = LXW_FALSE,
393
+ * .output_buffer = NULL,
394
+ * .output_buffer_size = NULL};
335
395
  *
336
396
  * lxw_workbook *workbook = workbook_new_opt("filename.xlsx", &options);
337
397
  * @endcode
@@ -355,23 +415,30 @@ lxw_workbook *workbook_new(const char *filename);
355
415
  *
356
416
  * [zip64_wiki]: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
357
417
  *
358
- * @note In `constant_memory` mode a row of data is written and then discarded
359
- * when a cell in a new row is added via one of the `worksheet_write_*()`
360
- * functions. Therefore, once this option is active, data should be written in
361
- * sequential row order. For this reason the `worksheet_merge_range()` doesn't
362
- * work in this mode. See also @ref ww_mem_constant.
363
- *
418
+ * - `output_buffer`: Output to a memory buffer instead of a file. The buffer
419
+ * must be freed manually by calling `free()`. This option can only be used if
420
+ * filename is NULL.
421
+ *
422
+ * - `output_buffer_size`: Used with output_buffer to get the size of the
423
+ * created buffer. This option can only be used if filename is `NULL`.
424
+ *
425
+ * @note In `constant_memory` mode each row of in-memory data is written to
426
+ * disk and then freed when a new row is started via one of the
427
+ * `worksheet_write_*()` functions. Therefore, once this option is active data
428
+ * should be written in sequential row by row order. For this reason
429
+ * `worksheet_merge_range()` and some other row based functionality doesn't
430
+ * work in this mode. See @ref ww_mem_constant for more details.
431
+ *
432
+ * @note Also, in `constant_memory` mode the library uses temp file storage
433
+ * for worksheet data. This can lead to an issue on OSes that map the `/tmp`
434
+ * directory into memory since it is possible to consume the "system" memory
435
+ * even though the "process" memory remains constant. In these cases you
436
+ * should use an alternative temp file location by using the `tmpdir` option
437
+ * shown above. See @ref ww_mem_temp for more details.
364
438
  */
365
439
  lxw_workbook *workbook_new_opt(const char *filename,
366
440
  lxw_workbook_options *options);
367
441
 
368
- /* Deprecated function name for backwards compatibility. */
369
- lxw_workbook *new_workbook(const char *filename);
370
-
371
- /* Deprecated function name for backwards compatibility. */
372
- lxw_workbook *new_workbook_opt(const char *filename,
373
- lxw_workbook_options *options);
374
-
375
442
  /**
376
443
  * @brief Add a new worksheet to a workbook.
377
444
  *
@@ -404,12 +471,15 @@ lxw_workbook *new_workbook_opt(const char *filename,
404
471
  * - The name is less than or equal to 31 UTF-8 characters.
405
472
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
406
473
  * - The name doesn't start or end with an apostrophe.
407
- * - The name isn't "History", which is reserved by Excel. (Case insensitive).
408
474
  * - The name isn't already in use. (Case insensitive).
409
475
  *
410
476
  * If any of these errors are encountered the function will return NULL.
411
477
  * You can check for valid name using the `workbook_validate_sheet_name()`
412
478
  * function.
479
+ *
480
+ * @note You should also avoid using the worksheet name "History" (case
481
+ * insensitive) which is reserved in English language versions of
482
+ * Excel. Non-English versions may have restrictions on the equivalent word.
413
483
  */
414
484
  lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
415
485
  const char *sheetname);
@@ -443,13 +513,16 @@ lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
443
513
  * - The name is less than or equal to 31 UTF-8 characters.
444
514
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
445
515
  * - The name doesn't start or end with an apostrophe.
446
- * - The name isn't "History", which is reserved by Excel. (Case insensitive).
447
516
  * - The name isn't already in use. (Case insensitive).
448
517
  *
449
518
  * If any of these errors are encountered the function will return NULL.
450
519
  * You can check for valid name using the `workbook_validate_sheet_name()`
451
520
  * function.
452
521
  *
522
+ * @note You should also avoid using the worksheet name "History" (case
523
+ * insensitive) which is reserved in English language versions of
524
+ * Excel. Non-English versions may have restrictions on the equivalent word.
525
+ *
453
526
  * At least one worksheet should be added to a new workbook when creating a
454
527
  * chartsheet in order to provide data for the chart. The @ref worksheet.h
455
528
  * "Worksheet" object is used to write data and configure a worksheet in the
@@ -533,6 +606,8 @@ lxw_format *workbook_default_format(lxw_workbook *workbook);
533
606
  * | #LXW_CHART_COLUMN_STACKED_PERCENT | Column chart - percentage stacked. |
534
607
  * | #LXW_CHART_DOUGHNUT | Doughnut chart. |
535
608
  * | #LXW_CHART_LINE | Line chart. |
609
+ * | #LXW_CHART_LINE_STACKED | Line chart - stacked. |
610
+ * | #LXW_CHART_LINE_STACKED_PERCENT | Line chart - percentage stacked. |
536
611
  * | #LXW_CHART_PIE | Pie chart. |
537
612
  * | #LXW_CHART_SCATTER | Scatter chart. |
538
613
  * | #LXW_CHART_SCATTER_STRAIGHT | Scatter chart - straight. |
@@ -600,10 +675,11 @@ lxw_error workbook_close(lxw_workbook *workbook);
600
675
  * - `keywords`
601
676
  * - `comments`
602
677
  * - `hyperlink_base`
678
+ * - `created`
603
679
  *
604
680
  * The properties are specified via a `lxw_doc_properties` struct. All the
605
- * members are `char *` and they are all optional. An example of how to create
606
- * and pass the properties is:
681
+ * fields are all optional. An example of how to create and pass the
682
+ * properties is:
607
683
  *
608
684
  * @code
609
685
  * // Create a properties structure and set some of the fields.
@@ -625,6 +701,12 @@ lxw_error workbook_close(lxw_workbook *workbook);
625
701
  *
626
702
  * @image html doc_properties.png
627
703
  *
704
+ * The `created` parameter sets the file creation date/time shown in
705
+ * Excel. This defaults to the current time and date if set to 0. If you wish
706
+ * to create files that are binary equivalent (for the same input data) then
707
+ * you should set this creation date/time to a known value using a `time_t`
708
+ * value.
709
+ *
628
710
  */
629
711
  lxw_error workbook_set_properties(lxw_workbook *workbook,
630
712
  lxw_doc_properties *properties);
@@ -777,13 +859,32 @@ lxw_error workbook_set_custom_property_datetime(lxw_workbook *workbook,
777
859
  * @endcode
778
860
  *
779
861
  * The rules for names in Excel are explained in the
780
- * [Microsoft Office
781
- documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
862
+ * [Microsoft Office documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
782
863
  *
783
864
  */
784
865
  lxw_error workbook_define_name(lxw_workbook *workbook, const char *name,
785
866
  const char *formula);
786
867
 
868
+ /**
869
+ * @brief Get the default URL format used with `worksheet_write_url()`.
870
+ *
871
+ * @param workbook Pointer to a lxw_workbook instance.
872
+ * @return A lxw_format instance that has hyperlink properties set.
873
+ *
874
+ * This function returns a lxw_format instance that is used for the default
875
+ * blue underline hyperlink in the `worksheet_write_url()` function when a
876
+ * format isn't specified:
877
+ *
878
+ * @code
879
+ * lxw_format *url_format = workbook_get_default_url_format(workbook);
880
+ * @endcode
881
+ *
882
+ * The format is the hyperlink style defined by Excel for the default theme.
883
+ * This format is only ever required when overwriting a string URL with
884
+ * data of a different type. See the example below.
885
+ */
886
+ lxw_format *workbook_get_default_url_format(lxw_workbook *workbook);
887
+
787
888
  /**
788
889
  * @brief Get a worksheet object from its name.
789
890
  *
@@ -834,7 +935,6 @@ lxw_chartsheet *workbook_get_chartsheet_by_name(lxw_workbook *workbook,
834
935
  * - The name is less than or equal to 31 UTF-8 characters.
835
936
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
836
937
  * - The name doesn't start or end with an apostrophe.
837
- * - The name isn't "History", which is reserved by Excel. (Case insensitive).
838
938
  * - The name isn't already in use. (Case insensitive, see the note below).
839
939
  *
840
940
  * @code
@@ -845,6 +945,10 @@ lxw_chartsheet *workbook_get_chartsheet_by_name(lxw_workbook *workbook,
845
945
  * `workbook_add_chartsheet()` but it can be explicitly called by the user
846
946
  * beforehand to ensure that the sheet name is valid.
847
947
  *
948
+ * @note You should also avoid using the worksheet name "History" (case
949
+ * insensitive) which is reserved in English language versions of
950
+ * Excel. Non-English versions may have restrictions on the equivalent word.
951
+ *
848
952
  * @note This function does an ASCII lowercase string comparison to determine
849
953
  * if the sheet name is already in use. It doesn't take UTF-8 characters into
850
954
  * account. Thus it would flag "Café" and "café" as a duplicate (just like
@@ -869,13 +973,54 @@ lxw_error workbook_validate_sheet_name(lxw_workbook *workbook,
869
973
  * workbook_add_vba_project(workbook, "vbaProject.bin");
870
974
  * @endcode
871
975
  *
872
- * Only one `vbaProject.bin file` can be added per workbook.
976
+ * Only one `vbaProject.bin` file can be added per workbook. The name doesn't
977
+ * have to be `vbaProject.bin`. Any suitable path/name for an existing VBA bin
978
+ * file will do.
979
+ *
980
+ * Once you add a VBA project had been add to an libxlsxwriter workbook you
981
+ * should ensure that the file extension is `.xlsm` to prevent Excel from
982
+ * giving a warning when it opens the file:
983
+ *
984
+ * @code
985
+ * lxw_workbook *workbook = new_workbook("macro.xlsm");
986
+ * @endcode
987
+ *
988
+ * See also @ref working_with_macros
873
989
  *
874
990
  * @return A #lxw_error.
875
991
  */
876
992
  lxw_error workbook_add_vba_project(lxw_workbook *workbook,
877
993
  const char *filename);
878
994
 
995
+ /**
996
+ * @brief Add a vbaProject binary and a vbaProjectSignature binary to the Excel
997
+ * workbook.
998
+ *
999
+ * @param workbook Pointer to a lxw_workbook instance.
1000
+ * @param vba_project The path/filename of the vbaProject.bin file.
1001
+ * @param signature The path/filename of the vbaProjectSignature.bin file.
1002
+ *
1003
+ * The `%workbook_add_signed_vba_project()` function can be used to add digitally
1004
+ * signed macros or functions to a workbook. The function adds a binary VBA project
1005
+ * file and a binary VBA project signature file that have been extracted from an
1006
+ * existing Excel xlsm file with digitally signed macros:
1007
+ *
1008
+ * @code
1009
+ * workbook_add_signed_vba_project(workbook, "vbaProject.bin", "vbaProjectSignature.bin");
1010
+ * @endcode
1011
+ *
1012
+ * Only one `vbaProject.bin` file can be added per workbook. The name doesn't
1013
+ * have to be `vbaProject.bin`. Any suitable path/name for an existing VBA bin
1014
+ * file will do. The same applies for `vbaProjectSignature.bin`.
1015
+ *
1016
+ * See also @ref working_with_macros
1017
+ *
1018
+ * @return A #lxw_error.
1019
+ */
1020
+ lxw_error workbook_add_signed_vba_project(lxw_workbook *workbook,
1021
+ const char *vba_project,
1022
+ const char *signature);
1023
+
879
1024
  /**
880
1025
  * @brief Set the VBA name for the workbook.
881
1026
  *
@@ -884,21 +1029,47 @@ lxw_error workbook_add_vba_project(lxw_workbook *workbook,
884
1029
  *
885
1030
  * The `workbook_set_vba_name()` function can be used to set the VBA name for
886
1031
  * the workbook. This is sometimes required when a vbaProject macro included
887
- * via `workbook_add_vba_project()` refers to the workbook.
1032
+ * via `workbook_add_vba_project()` refers to the workbook by a name other
1033
+ * than `ThisWorkbook`.
888
1034
  *
889
1035
  * @code
890
1036
  * workbook_set_vba_name(workbook, "MyWorkbook");
891
1037
  * @endcode
892
1038
  *
893
- * The most common Excel VBA name for a workbook is `ThisWorkbook`.
1039
+ * If an Excel VBA name for the workbook isn't specified then libxlsxwriter
1040
+ * will use `ThisWorkbook`.
1041
+ *
1042
+ * See also @ref working_with_macros
894
1043
  *
895
1044
  * @return A #lxw_error.
896
1045
  */
897
1046
  lxw_error workbook_set_vba_name(lxw_workbook *workbook, const char *name);
898
1047
 
1048
+ /**
1049
+ * @brief Add a recommendation to open the file in "read-only" mode.
1050
+ *
1051
+ * @param workbook Pointer to a lxw_workbook instance.
1052
+ *
1053
+ * This function can be used to set the Excel "Read-only Recommended" option
1054
+ * that is available when saving a file. This presents the user of the file
1055
+ * with an option to open it in "read-only" mode. This means that any changes
1056
+ * to the file can't be saved back to the same file and must be saved to a new
1057
+ * file. It can be set as follows:
1058
+ *
1059
+ * @code
1060
+ * workbook_read_only_recommended(workbook);
1061
+ * @endcode
1062
+ *
1063
+ * Which will raise a dialog like the following when opening the file:
1064
+ *
1065
+ * @image html read_only.png
1066
+ */
1067
+ void workbook_read_only_recommended(lxw_workbook *workbook);
1068
+
899
1069
  void lxw_workbook_free(lxw_workbook *workbook);
900
1070
  void lxw_workbook_assemble_xml_file(lxw_workbook *workbook);
901
1071
  void lxw_workbook_set_default_xf_indices(lxw_workbook *workbook);
1072
+ void workbook_unset_default_url_format(lxw_workbook *workbook);
902
1073
 
903
1074
  /* Declarations required for unit testing. */
904
1075
  #ifdef TESTING