fast_excel 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +2 -0
  3. data/.gitignore +7 -0
  4. data/.travis.yml +44 -0
  5. data/CHANGELOG.md +41 -1
  6. data/Dockerfile.test +16 -0
  7. data/Gemfile +5 -2
  8. data/Gemfile.lock +30 -23
  9. data/LICENSE +21 -0
  10. data/Makefile +13 -0
  11. data/README.md +177 -40
  12. data/Rakefile +16 -0
  13. data/appveyor.yml +25 -0
  14. data/benchmarks/1k_rows.rb +17 -4
  15. data/benchmarks/20k_rows.rb +4 -0
  16. data/benchmarks/auto_width.rb +37 -0
  17. data/benchmarks/init.rb +14 -2
  18. data/benchmarks/memory.rb +8 -0
  19. data/benchmarks/profiler.rb +27 -0
  20. data/benchmarks/write_value.rb +62 -0
  21. data/examples/example.rb +3 -4
  22. data/examples/example_align.rb +23 -0
  23. data/examples/example_auto_width.rb +26 -0
  24. data/examples/example_colors.rb +37 -0
  25. data/examples/example_filters.rb +36 -0
  26. data/examples/example_formula.rb +1 -5
  27. data/examples/example_hyperlink.rb +20 -0
  28. data/examples/example_image.rb +1 -1
  29. data/examples/example_styles.rb +27 -0
  30. data/examples/logo.png +0 -0
  31. data/ext/fast_excel/extconf.rb +3 -0
  32. data/ext/fast_excel/text_width_ext.c +460 -0
  33. data/fast_excel.gemspec +2 -3
  34. data/letters.html +114 -0
  35. data/lib/fast_excel.rb +455 -78
  36. data/lib/fast_excel/binding.rb +31 -21
  37. data/lib/fast_excel/binding/chart.rb +20 -1
  38. data/lib/fast_excel/binding/format.rb +11 -4
  39. data/lib/fast_excel/binding/workbook.rb +10 -2
  40. data/lib/fast_excel/binding/worksheet.rb +44 -27
  41. data/libxlsxwriter/.gitignore +1 -0
  42. data/libxlsxwriter/.indent.pro +8 -0
  43. data/libxlsxwriter/.travis.yml +12 -0
  44. data/libxlsxwriter/CMakeLists.txt +338 -0
  45. data/libxlsxwriter/CONTRIBUTING.md +1 -1
  46. data/libxlsxwriter/Changes.txt +162 -0
  47. data/libxlsxwriter/LICENSE.txt +65 -4
  48. data/libxlsxwriter/Makefile +33 -11
  49. data/libxlsxwriter/Readme.md +3 -1
  50. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +2 -1
  51. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +2 -2
  52. data/libxlsxwriter/include/xlsxwriter.h +2 -2
  53. data/libxlsxwriter/include/xlsxwriter/app.h +2 -2
  54. data/libxlsxwriter/include/xlsxwriter/chart.h +164 -13
  55. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
  56. data/libxlsxwriter/include/xlsxwriter/common.h +35 -6
  57. data/libxlsxwriter/include/xlsxwriter/content_types.h +5 -2
  58. data/libxlsxwriter/include/xlsxwriter/core.h +2 -2
  59. data/libxlsxwriter/include/xlsxwriter/custom.h +2 -2
  60. data/libxlsxwriter/include/xlsxwriter/drawing.h +3 -2
  61. data/libxlsxwriter/include/xlsxwriter/format.h +8 -8
  62. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  63. data/libxlsxwriter/include/xlsxwriter/packager.h +18 -8
  64. data/libxlsxwriter/include/xlsxwriter/relationships.h +2 -2
  65. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +5 -3
  66. data/libxlsxwriter/include/xlsxwriter/styles.h +10 -5
  67. data/libxlsxwriter/include/xlsxwriter/theme.h +2 -2
  68. data/libxlsxwriter/include/xlsxwriter/utility.h +35 -5
  69. data/libxlsxwriter/include/xlsxwriter/workbook.h +234 -57
  70. data/libxlsxwriter/include/xlsxwriter/worksheet.h +780 -91
  71. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
  72. data/libxlsxwriter/libxlsxwriter.podspec +4 -2
  73. data/libxlsxwriter/src/Makefile +31 -6
  74. data/libxlsxwriter/src/app.c +2 -2
  75. data/libxlsxwriter/src/chart.c +116 -23
  76. data/libxlsxwriter/src/chartsheet.c +508 -0
  77. data/libxlsxwriter/src/content_types.c +12 -4
  78. data/libxlsxwriter/src/core.c +11 -11
  79. data/libxlsxwriter/src/custom.c +3 -3
  80. data/libxlsxwriter/src/drawing.c +114 -17
  81. data/libxlsxwriter/src/format.c +5 -5
  82. data/libxlsxwriter/src/hash_table.c +1 -1
  83. data/libxlsxwriter/src/packager.c +378 -61
  84. data/libxlsxwriter/src/relationships.c +2 -2
  85. data/libxlsxwriter/src/shared_strings.c +18 -4
  86. data/libxlsxwriter/src/styles.c +59 -12
  87. data/libxlsxwriter/src/theme.c +2 -2
  88. data/libxlsxwriter/src/utility.c +93 -6
  89. data/libxlsxwriter/src/workbook.c +379 -61
  90. data/libxlsxwriter/src/worksheet.c +1240 -174
  91. data/libxlsxwriter/src/xmlwriter.c +18 -9
  92. data/libxlsxwriter/third_party/minizip/Makefile +6 -1
  93. data/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
  94. data/libxlsxwriter/third_party/minizip/zip.c +2 -0
  95. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
  96. data/libxlsxwriter/version.txt +1 -1
  97. data/test/auto_width_test.rb +19 -0
  98. data/test/date_test.rb +34 -0
  99. data/test/format_test.rb +179 -0
  100. data/test/reopen_test.rb +22 -0
  101. data/test/test_helper.rb +23 -4
  102. data/test/text_width_test.rb +80 -0
  103. data/test/tmpfile_test.rb +1 -0
  104. data/test/validations_test.rb +47 -0
  105. data/test/worksheet_test.rb +129 -0
  106. metadata +34 -5
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5
5
  */
6
6
 
7
7
  /**
@@ -46,6 +46,7 @@
46
46
  #include <errno.h>
47
47
 
48
48
  #include "worksheet.h"
49
+ #include "chartsheet.h"
49
50
  #include "chart.h"
50
51
  #include "shared_strings.h"
51
52
  #include "hash_table.h"
@@ -55,12 +56,27 @@
55
56
 
56
57
  /* Define the tree.h RB structs for the red-black head types. */
57
58
  RB_HEAD(lxw_worksheet_names, lxw_worksheet_name);
59
+ RB_HEAD(lxw_chartsheet_names, lxw_chartsheet_name);
58
60
 
59
61
  /* Define the queue.h structs for the workbook lists. */
62
+ STAILQ_HEAD(lxw_sheets, lxw_sheet);
60
63
  STAILQ_HEAD(lxw_worksheets, lxw_worksheet);
64
+ STAILQ_HEAD(lxw_chartsheets, lxw_chartsheet);
61
65
  STAILQ_HEAD(lxw_charts, lxw_chart);
62
66
  TAILQ_HEAD(lxw_defined_names, lxw_defined_name);
63
67
 
68
+ /* TODO */
69
+ typedef struct lxw_sheet {
70
+ uint8_t is_chartsheet;
71
+
72
+ union {
73
+ lxw_worksheet *worksheet;
74
+ lxw_chartsheet *chartsheet;
75
+ } u;
76
+
77
+ STAILQ_ENTRY (lxw_sheet) list_pointers;
78
+ } lxw_sheet;
79
+
64
80
  /* Struct to represent a worksheet name/pointer pair. */
65
81
  typedef struct lxw_worksheet_name {
66
82
  const char *name;
@@ -69,18 +85,37 @@ typedef struct lxw_worksheet_name {
69
85
  RB_ENTRY (lxw_worksheet_name) tree_pointers;
70
86
  } lxw_worksheet_name;
71
87
 
88
+ /* Struct to represent a chartsheet name/pointer pair. */
89
+ typedef struct lxw_chartsheet_name {
90
+ const char *name;
91
+ lxw_chartsheet *chartsheet;
92
+
93
+ RB_ENTRY (lxw_chartsheet_name) tree_pointers;
94
+ } lxw_chartsheet_name;
95
+
72
96
  /* Wrapper around RB_GENERATE_STATIC from tree.h to avoid unused function
73
97
  * warnings and to avoid portability issues with the _unused attribute. */
74
- #define LXW_RB_GENERATE_NAMES(name, type, field, cmp) \
75
- RB_GENERATE_INSERT_COLOR(name, type, field, static) \
76
- RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
77
- RB_GENERATE_INSERT(name, type, field, cmp, static) \
78
- RB_GENERATE_REMOVE(name, type, field, static) \
79
- RB_GENERATE_FIND(name, type, field, cmp, static) \
80
- RB_GENERATE_NEXT(name, type, field, static) \
81
- RB_GENERATE_MINMAX(name, type, field, static) \
82
- /* Add unused struct to allow adding a semicolon */ \
83
- struct lxw_rb_generate_names{int unused;}
98
+ #define LXW_RB_GENERATE_WORKSHEET_NAMES(name, type, field, cmp) \
99
+ RB_GENERATE_INSERT_COLOR(name, type, field, static) \
100
+ RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
101
+ RB_GENERATE_INSERT(name, type, field, cmp, static) \
102
+ RB_GENERATE_REMOVE(name, type, field, static) \
103
+ RB_GENERATE_FIND(name, type, field, cmp, static) \
104
+ RB_GENERATE_NEXT(name, type, field, static) \
105
+ RB_GENERATE_MINMAX(name, type, field, static) \
106
+ /* Add unused struct to allow adding a semicolon */ \
107
+ struct lxw_rb_generate_worksheet_names{int unused;}
108
+
109
+ #define LXW_RB_GENERATE_CHARTSHEET_NAMES(name, type, field, cmp) \
110
+ RB_GENERATE_INSERT_COLOR(name, type, field, static) \
111
+ RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
112
+ RB_GENERATE_INSERT(name, type, field, cmp, static) \
113
+ RB_GENERATE_REMOVE(name, type, field, static) \
114
+ RB_GENERATE_FIND(name, type, field, cmp, static) \
115
+ RB_GENERATE_NEXT(name, type, field, static) \
116
+ RB_GENERATE_MINMAX(name, type, field, static) \
117
+ /* Add unused struct to allow adding a semicolon */ \
118
+ struct lxw_rb_generate_charsheet_names{int unused;}
84
119
 
85
120
  /**
86
121
  * @brief Macro to loop over all the worksheets in a workbook.
@@ -168,27 +203,40 @@ typedef struct lxw_doc_properties {
168
203
  *
169
204
  * The following properties are supported:
170
205
  *
171
- * - `constant_memory`: Reduces the amount of data stored in memory so that
172
- * large files can be written efficiently.
173
- *
174
- * @note In this mode a row of data is written and then discarded when a
175
- * cell in a new row is added via one of the `worksheet_write_*()`
176
- * functions. Therefore, once this option is active, data should be written in
177
- * sequential row order. For this reason the `worksheet_merge_range()`
178
- * doesn't work in this mode. See also @ref ww_mem_constant.
206
+ * - `constant_memory`: This option reduces the amount of data stored in
207
+ * 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.
179
209
  *
180
- * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior
181
- * to assembling the final XLSX file. The temporary files are created in the
210
+ * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior to
211
+ * assembling the final XLSX file. The temporary files are created in the
182
212
  * system's temp directory. If the default temporary directory isn't
183
213
  * accessible to your application, or doesn't contain enough space, you can
184
- * specify an alternative location using the `tempdir` option.
214
+ * specify an alternative location using the `tmpdir` option.
215
+ *
216
+ * - `use_zip64`: Make the zip library use ZIP64 extensions when writing very
217
+ * large xlsx files to allow the zip container, or individual XML files
218
+ * within it, to be greater than 4 GB. See [ZIP64 on Wikipedia][zip64_wiki]
219
+ * for more information. This option is off by default.
220
+ *
221
+ * [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
+ *
185
229
  */
186
230
  typedef struct lxw_workbook_options {
187
- /** Optimize the workbook to use constant memory for worksheets */
231
+ /** Optimize the workbook to use constant memory for worksheets. */
188
232
  uint8_t constant_memory;
189
233
 
190
234
  /** Directory to use for the temporary files created by libxlsxwriter. */
191
235
  char *tmpdir;
236
+
237
+ /** Allow ZIP64 extensions when creating the xlsx file zip container. */
238
+ uint8_t use_zip64;
239
+
192
240
  } lxw_workbook_options;
193
241
 
194
242
  /**
@@ -201,8 +249,11 @@ typedef struct lxw_workbook_options {
201
249
  typedef struct lxw_workbook {
202
250
 
203
251
  FILE *file;
252
+ struct lxw_sheets *sheets;
204
253
  struct lxw_worksheets *worksheets;
254
+ struct lxw_chartsheets *chartsheets;
205
255
  struct lxw_worksheet_names *worksheet_names;
256
+ struct lxw_chartsheet_names *chartsheet_names;
206
257
  struct lxw_charts *charts;
207
258
  struct lxw_charts *ordered_charts;
208
259
  struct lxw_formats *formats;
@@ -215,6 +266,8 @@ typedef struct lxw_workbook {
215
266
  lxw_workbook_options options;
216
267
 
217
268
  uint16_t num_sheets;
269
+ uint16_t num_worksheets;
270
+ uint16_t num_chartsheets;
218
271
  uint16_t first_sheet;
219
272
  uint16_t active_sheet;
220
273
  uint16_t num_xf_formats;
@@ -232,6 +285,9 @@ typedef struct lxw_workbook {
232
285
 
233
286
  lxw_hash_table *used_xf_formats;
234
287
 
288
+ char *vba_project;
289
+ char *vba_codename;
290
+
235
291
  } lxw_workbook;
236
292
 
237
293
 
@@ -273,30 +329,37 @@ lxw_workbook *workbook_new(const char *filename);
273
329
  * additional options to be set.
274
330
  *
275
331
  * @code
276
- * lxw_workbook_options options = {.constant_memory = 1,
277
- * .tmpdir = "C:\\Temp"};
332
+ * lxw_workbook_options options = {.constant_memory = LXW_TRUE,
333
+ * .tmpdir = "C:\\Temp",
334
+ * .use_zip64 = LXW_FALSE};
278
335
  *
279
336
  * lxw_workbook *workbook = workbook_new_opt("filename.xlsx", &options);
280
337
  * @endcode
281
338
  *
282
339
  * The options that can be set via #lxw_workbook_options are:
283
340
  *
284
- * - `constant_memory`: Reduces the amount of data stored in memory so that
285
- * large files can be written efficiently.
286
- *
287
- * @note In this mode a row of data is written and then discarded when a
288
- * cell in a new row is added via one of the `worksheet_write_*()`
289
- * functions. Therefore, once this option is active, data should be written in
290
- * sequential row order. For this reason the `worksheet_merge_range()`
291
- * doesn't work in this mode. See also @ref ww_mem_constant.
341
+ * - `constant_memory`: This option reduces the amount of data stored in
342
+ * memory so that large files can be written efficiently. This option is off
343
+ * by default. See the note below for limitations when this mode is on.
292
344
  *
293
- * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior
294
- * to assembling the final XLSX file. The temporary files are created in the
345
+ * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior to
346
+ * assembling the final XLSX file. The temporary files are created in the
295
347
  * system's temp directory. If the default temporary directory isn't
296
348
  * accessible to your application, or doesn't contain enough space, you can
297
- * specify an alternative location using the `tempdir` option.*
349
+ * specify an alternative location using the `tmpdir` option.
298
350
  *
299
- * See @ref working_with_memory for more details.
351
+ * - `use_zip64`: Make the zip library use ZIP64 extensions when writing very
352
+ * large xlsx files to allow the zip container, or individual XML files
353
+ * within it, to be greater than 4 GB. See [ZIP64 on Wikipedia][zip64_wiki]
354
+ * for more information. This option is off by default.
355
+ *
356
+ * [zip64_wiki]: https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
357
+ *
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.
300
363
  *
301
364
  */
302
365
  lxw_workbook *workbook_new_opt(const char *filename,
@@ -317,7 +380,7 @@ lxw_workbook *new_workbook_opt(const char *filename,
317
380
  *
318
381
  * @return A lxw_worksheet object.
319
382
  *
320
- * The `%workbook_add_worksheet()` function adds a new worksheet to a workbook:
383
+ * The `%workbook_add_worksheet()` function adds a new worksheet to a workbook.
321
384
  *
322
385
  * At least one worksheet should be added to a new workbook: The @ref
323
386
  * worksheet.h "Worksheet" object is used to write data and configure a
@@ -336,18 +399,65 @@ lxw_workbook *new_workbook_opt(const char *filename,
336
399
  *
337
400
  * @image html workbook02.png
338
401
  *
339
- * The worksheet name must be a valid Excel worksheet name, i.e. it must be
340
- * less than 32 character and it cannot contain any of the characters:
402
+ * The worksheet name must be a valid Excel worksheet name, i.e:
341
403
  *
342
- * / \ [ ] : * ?
343
- *
344
- * In addition, you cannot use the same, case insensitive, `sheetname` for more
345
- * than one worksheet.
404
+ * - The name is less than or equal to 31 UTF-8 characters.
405
+ * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
406
+ * - The name doesn't start or end with an apostrophe.
407
+ * - The name isn't "History", which is reserved by Excel. (Case insensitive).
408
+ * - The name isn't already in use. (Case insensitive).
346
409
  *
410
+ * If any of these errors are encountered the function will return NULL.
411
+ * You can check for valid name using the `workbook_validate_sheet_name()`
412
+ * function.
347
413
  */
348
414
  lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
349
415
  const char *sheetname);
350
416
 
417
+ /**
418
+ * @brief Add a new chartsheet to a workbook.
419
+ *
420
+ * @param workbook Pointer to a lxw_workbook instance.
421
+ * @param sheetname Optional chartsheet name, defaults to Chart1, etc.
422
+ *
423
+ * @return A lxw_chartsheet object.
424
+ *
425
+ * The `%workbook_add_chartsheet()` function adds a new chartsheet to a
426
+ * workbook. The @ref chartsheet.h "Chartsheet" object is like a worksheet
427
+ * except it displays a chart instead of cell data.
428
+ *
429
+ * @image html chartsheet.png
430
+ *
431
+ * The `sheetname` parameter is optional. If it is `NULL` the default
432
+ * Excel convention will be followed, i.e. Chart1, Chart2, etc.:
433
+ *
434
+ * @code
435
+ * chartsheet = workbook_add_chartsheet(workbook, NULL ); // Chart1
436
+ * chartsheet = workbook_add_chartsheet(workbook, "My Chart"); // My Chart
437
+ * chartsheet = workbook_add_chartsheet(workbook, NULL ); // Chart3
438
+ *
439
+ * @endcode
440
+ *
441
+ * The chartsheet name must be a valid Excel worksheet name, i.e.:
442
+ *
443
+ * - The name is less than or equal to 31 UTF-8 characters.
444
+ * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
445
+ * - The name doesn't start or end with an apostrophe.
446
+ * - The name isn't "History", which is reserved by Excel. (Case insensitive).
447
+ * - The name isn't already in use. (Case insensitive).
448
+ *
449
+ * If any of these errors are encountered the function will return NULL.
450
+ * You can check for valid name using the `workbook_validate_sheet_name()`
451
+ * function.
452
+ *
453
+ * At least one worksheet should be added to a new workbook when creating a
454
+ * chartsheet in order to provide data for the chart. The @ref worksheet.h
455
+ * "Worksheet" object is used to write data and configure a worksheet in the
456
+ * workbook.
457
+ */
458
+ lxw_chartsheet *workbook_add_chartsheet(lxw_workbook *workbook,
459
+ const char *sheetname);
460
+
351
461
  /**
352
462
  * @brief Create a new @ref format.h "Format" object to formats cells in
353
463
  * worksheets.
@@ -677,8 +787,8 @@ lxw_error workbook_define_name(lxw_workbook *workbook, const char *name,
677
787
  /**
678
788
  * @brief Get a worksheet object from its name.
679
789
  *
680
- * @param workbook
681
- * @param name
790
+ * @param workbook Pointer to a lxw_workbook instance.
791
+ * @param name Worksheet name.
682
792
  *
683
793
  * @return A lxw_worksheet object.
684
794
  *
@@ -693,31 +803,98 @@ lxw_worksheet *workbook_get_worksheet_by_name(lxw_workbook *workbook,
693
803
  const char *name);
694
804
 
695
805
  /**
696
- * @brief Validate a worksheet name.
806
+ * @brief Get a chartsheet object from its name.
807
+ *
808
+ * @param workbook Pointer to a lxw_workbook instance.
809
+ * @param name chartsheet name.
810
+ *
811
+ * @return A lxw_chartsheet object.
812
+ *
813
+ * This function returns a lxw_chartsheet object reference based on its name:
814
+ *
815
+ * @code
816
+ * chartsheet = workbook_get_chartsheet_by_name(workbook, "Chart1");
817
+ * @endcode
818
+ *
819
+ */
820
+ lxw_chartsheet *workbook_get_chartsheet_by_name(lxw_workbook *workbook,
821
+ const char *name);
822
+
823
+ /**
824
+ * @brief Validate a worksheet or chartsheet name.
697
825
  *
698
826
  * @param workbook Pointer to a lxw_workbook instance.
699
- * @param sheetname Worksheet name to validate.
827
+ * @param sheetname Sheet name to validate.
700
828
  *
701
829
  * @return A #lxw_error.
702
830
  *
703
- * This function is used to validate a worksheet name according to the rules
704
- * used by Excel:
831
+ * This function is used to validate a worksheet or chartsheet name according
832
+ * to the rules used by Excel:
705
833
  *
706
834
  * - The name is less than or equal to 31 UTF-8 characters.
707
835
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
708
- * - The name isn't already in use.
836
+ * - The name doesn't start or end with an apostrophe.
837
+ * - The name isn't "History", which is reserved by Excel. (Case insensitive).
838
+ * - The name isn't already in use. (Case insensitive, see the note below).
709
839
  *
710
840
  * @code
711
- * lxw_error err = workbook_validate_worksheet_name(workbook, "Foglio");
841
+ * lxw_error err = workbook_validate_sheet_name(workbook, "Foglio");
712
842
  * @endcode
713
843
  *
714
- * This function is called by `workbook_add_worksheet()` but it can be
715
- * explicitly called by the user beforehand to ensure that the worksheet
716
- * name is valid.
844
+ * This function is called by `workbook_add_worksheet()` and
845
+ * `workbook_add_chartsheet()` but it can be explicitly called by the user
846
+ * beforehand to ensure that the sheet name is valid.
847
+ *
848
+ * @note This function does an ASCII lowercase string comparison to determine
849
+ * if the sheet name is already in use. It doesn't take UTF-8 characters into
850
+ * account. Thus it would flag "Café" and "café" as a duplicate (just like
851
+ * Excel) but it wouldn't catch "CAFÉ". If you need a full UTF-8 case
852
+ * insensitive check you should use a third party library to implement it.
853
+ *
854
+ */
855
+ lxw_error workbook_validate_sheet_name(lxw_workbook *workbook,
856
+ const char *sheetname);
857
+
858
+ /**
859
+ * @brief Add a vbaProject binary to the Excel workbook.
860
+ *
861
+ * @param workbook Pointer to a lxw_workbook instance.
862
+ * @param filename The path/filename of the vbaProject.bin file.
717
863
  *
864
+ * The `%workbook_add_vba_project()` function can be used to add macros or
865
+ * functions to a workbook using a binary VBA project file that has been
866
+ * extracted from an existing Excel xlsm file:
867
+ *
868
+ * @code
869
+ * workbook_add_vba_project(workbook, "vbaProject.bin");
870
+ * @endcode
871
+ *
872
+ * Only one `vbaProject.bin file` can be added per workbook.
873
+ *
874
+ * @return A #lxw_error.
875
+ */
876
+ lxw_error workbook_add_vba_project(lxw_workbook *workbook,
877
+ const char *filename);
878
+
879
+ /**
880
+ * @brief Set the VBA name for the workbook.
881
+ *
882
+ * @param workbook Pointer to a lxw_workbook instance.
883
+ * @param name Name of the workbook used by VBA.
884
+ *
885
+ * The `workbook_set_vba_name()` function can be used to set the VBA name for
886
+ * the workbook. This is sometimes required when a vbaProject macro included
887
+ * via `workbook_add_vba_project()` refers to the workbook.
888
+ *
889
+ * @code
890
+ * workbook_set_vba_name(workbook, "MyWorkbook");
891
+ * @endcode
892
+ *
893
+ * The most common Excel VBA name for a workbook is `ThisWorkbook`.
894
+ *
895
+ * @return A #lxw_error.
718
896
  */
719
- lxw_error workbook_validate_worksheet_name(lxw_workbook *workbook,
720
- const char *sheetname);
897
+ lxw_error workbook_set_vba_name(lxw_workbook *workbook, const char *name);
721
898
 
722
899
  void lxw_workbook_free(lxw_workbook *workbook);
723
900
  void lxw_workbook_assemble_xml_file(lxw_workbook *workbook);
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5
5
  */
6
6
 
7
7
  /**
@@ -53,18 +53,19 @@
53
53
  #include "drawing.h"
54
54
  #include "common.h"
55
55
  #include "format.h"
56
+ #include "styles.h"
56
57
  #include "utility.h"
57
58
 
58
- #define LXW_ROW_MAX 1048576
59
- #define LXW_COL_MAX 16384
60
- #define LXW_COL_META_MAX 128
59
+ #define LXW_ROW_MAX 1048576
60
+ #define LXW_COL_MAX 16384
61
+ #define LXW_COL_META_MAX 128
61
62
  #define LXW_HEADER_FOOTER_MAX 255
62
- #define LXW_MAX_NUMBER_URLS 65530
63
- #define LXW_PANE_NAME_LENGTH 12 /* bottomRight + 1 */
63
+ #define LXW_MAX_NUMBER_URLS 65530
64
+ #define LXW_PANE_NAME_LENGTH 12 /* bottomRight + 1 */
64
65
 
65
66
  /* The Excel 2007 specification says that the maximum number of page
66
67
  * breaks is 1026. However, in practice it is actually 1023. */
67
- #define LXW_BREAKS_MAX 1023
68
+ #define LXW_BREAKS_MAX 1023
68
69
 
69
70
  /** Default column width in Excel */
70
71
  #define LXW_DEF_COL_WIDTH (double)8.43
@@ -76,18 +77,136 @@
76
77
  enum lxw_gridlines {
77
78
  /** Hide screen and print gridlines. */
78
79
  LXW_HIDE_ALL_GRIDLINES = 0,
80
+
79
81
  /** Show screen gridlines. */
80
82
  LXW_SHOW_SCREEN_GRIDLINES,
83
+
81
84
  /** Show print gridlines. */
82
85
  LXW_SHOW_PRINT_GRIDLINES,
86
+
83
87
  /** Show screen and print gridlines. */
84
88
  LXW_SHOW_ALL_GRIDLINES
85
89
  };
86
90
 
91
+ /** Data validation property values. */
92
+ enum lxw_validation_boolean {
93
+ LXW_VALIDATION_DEFAULT,
94
+
95
+ /** Turn a data validation property off. */
96
+ LXW_VALIDATION_OFF,
97
+
98
+ /** Turn a data validation property on. Data validation properties are
99
+ * generally on by default. */
100
+ LXW_VALIDATION_ON
101
+ };
102
+
103
+ /** Data validation types. */
104
+ enum lxw_validation_types {
105
+ LXW_VALIDATION_TYPE_NONE,
106
+
107
+ /** Restrict cell input to whole/integer numbers only. */
108
+ LXW_VALIDATION_TYPE_INTEGER,
109
+
110
+ /** Restrict cell input to whole/integer numbers only, using a cell
111
+ * reference. */
112
+ LXW_VALIDATION_TYPE_INTEGER_FORMULA,
113
+
114
+ /** Restrict cell input to decimal numbers only. */
115
+ LXW_VALIDATION_TYPE_DECIMAL,
116
+
117
+ /** Restrict cell input to decimal numbers only, using a cell
118
+ * reference. */
119
+ LXW_VALIDATION_TYPE_DECIMAL_FORMULA,
120
+
121
+ /** Restrict cell input to a list of strings in a dropdown. */
122
+ LXW_VALIDATION_TYPE_LIST,
123
+
124
+ /** Restrict cell input to a list of strings in a dropdown, using a
125
+ * cell range. */
126
+ LXW_VALIDATION_TYPE_LIST_FORMULA,
127
+
128
+ /** Restrict cell input to date values only, using a lxw_datetime type. */
129
+ LXW_VALIDATION_TYPE_DATE,
130
+
131
+ /** Restrict cell input to date values only, using a cell reference. */
132
+ LXW_VALIDATION_TYPE_DATE_FORMULA,
133
+
134
+ /* Restrict cell input to date values only, as a serial number.
135
+ * Undocumented. */
136
+ LXW_VALIDATION_TYPE_DATE_NUMBER,
137
+
138
+ /** Restrict cell input to time values only, using a lxw_datetime type. */
139
+ LXW_VALIDATION_TYPE_TIME,
140
+
141
+ /** Restrict cell input to time values only, using a cell reference. */
142
+ LXW_VALIDATION_TYPE_TIME_FORMULA,
143
+
144
+ /* Restrict cell input to time values only, as a serial number.
145
+ * Undocumented. */
146
+ LXW_VALIDATION_TYPE_TIME_NUMBER,
147
+
148
+ /** Restrict cell input to strings of defined length, using a cell
149
+ * reference. */
150
+ LXW_VALIDATION_TYPE_LENGTH,
151
+
152
+ /** Restrict cell input to strings of defined length, using a cell
153
+ * reference. */
154
+ LXW_VALIDATION_TYPE_LENGTH_FORMULA,
155
+
156
+ /** Restrict cell to input controlled by a custom formula that returns
157
+ * `TRUE/FALSE`. */
158
+ LXW_VALIDATION_TYPE_CUSTOM_FORMULA,
159
+
160
+ /** Allow any type of input. Mainly only useful for pop-up messages. */
161
+ LXW_VALIDATION_TYPE_ANY
162
+ };
163
+
164
+ /** Data validation criteria uses to control the selection of data. */
165
+ enum lxw_validation_criteria {
166
+ LXW_VALIDATION_CRITERIA_NONE,
167
+
168
+ /** Select data between two values. */
169
+ LXW_VALIDATION_CRITERIA_BETWEEN,
170
+
171
+ /** Select data that is not between two values. */
172
+ LXW_VALIDATION_CRITERIA_NOT_BETWEEN,
173
+
174
+ /** Select data equal to a value. */
175
+ LXW_VALIDATION_CRITERIA_EQUAL_TO,
176
+
177
+ /** Select data not equal to a value. */
178
+ LXW_VALIDATION_CRITERIA_NOT_EQUAL_TO,
179
+
180
+ /** Select data greater than a value. */
181
+ LXW_VALIDATION_CRITERIA_GREATER_THAN,
182
+
183
+ /** Select data less than a value. */
184
+ LXW_VALIDATION_CRITERIA_LESS_THAN,
185
+
186
+ /** Select data greater than or equal to a value. */
187
+ LXW_VALIDATION_CRITERIA_GREATER_THAN_OR_EQUAL_TO,
188
+
189
+ /** Select data less than or equal to a value. */
190
+ LXW_VALIDATION_CRITERIA_LESS_THAN_OR_EQUAL_TO
191
+ };
192
+
193
+ /** Data validation error types for pop-up messages. */
194
+ enum lxw_validation_error_types {
195
+ /** Show a "Stop" data validation pop-up message. This is the default. */
196
+ LXW_VALIDATION_ERROR_TYPE_STOP,
197
+
198
+ /** Show an "Error" data validation pop-up message. */
199
+ LXW_VALIDATION_ERROR_TYPE_WARNING,
200
+
201
+ /** Show an "Information" data validation pop-up message. */
202
+ LXW_VALIDATION_ERROR_TYPE_INFORMATION
203
+ };
204
+
87
205
  enum cell_types {
88
206
  NUMBER_CELL = 1,
89
207
  STRING_CELL,
90
208
  INLINE_STRING_CELL,
209
+ INLINE_RICH_STRING_CELL,
91
210
  FORMULA_CELL,
92
211
  ARRAY_FORMULA_CELL,
93
212
  BLANK_CELL,
@@ -140,6 +259,7 @@ struct lxw_table_rows {
140
259
 
141
260
  STAILQ_HEAD(lxw_merged_ranges, lxw_merged_range);
142
261
  STAILQ_HEAD(lxw_selections, lxw_selection);
262
+ STAILQ_HEAD(lxw_data_validations, lxw_data_validation);
143
263
  STAILQ_HEAD(lxw_image_data, lxw_image_options);
144
264
  STAILQ_HEAD(lxw_chart_data, lxw_image_options);
145
265
 
@@ -149,12 +269,14 @@ STAILQ_HEAD(lxw_chart_data, lxw_image_options);
149
269
  * Options struct for the worksheet_set_column() and worksheet_set_row()
150
270
  * functions.
151
271
  *
152
- * It has the following members but currently only the `hidden` property is
153
- * supported:
272
+ * It has the following members:
154
273
  *
155
274
  * * `hidden`
156
275
  * * `level`
157
276
  * * `collapsed`
277
+ *
278
+ * The members of this struct are explained in @ref ww_outlines_grouping.
279
+ *
158
280
  */
159
281
  typedef struct lxw_row_col_options {
160
282
  /** Hide the row/column */
@@ -229,6 +351,180 @@ typedef struct lxw_selection {
229
351
 
230
352
  } lxw_selection;
231
353
 
354
+ /**
355
+ * @brief Worksheet data validation options.
356
+ */
357
+ typedef struct lxw_data_validation {
358
+
359
+ /**
360
+ * Set the validation type. Should be a #lxw_validation_types value.
361
+ */
362
+ uint8_t validate;
363
+
364
+ /**
365
+ * Set the validation criteria type to select the data. Should be a
366
+ * #lxw_validation_criteria value.
367
+ */
368
+ uint8_t criteria;
369
+
370
+ /** Controls whether a data validation is not applied to blank data in the
371
+ * cell. Should be a #lxw_validation_boolean value. It is on by
372
+ * default.
373
+ */
374
+ uint8_t ignore_blank;
375
+
376
+ /**
377
+ * This parameter is used to toggle on and off the 'Show input message
378
+ * when cell is selected' option in the Excel data validation dialog. When
379
+ * the option is off an input message is not displayed even if it has been
380
+ * set using input_message. Should be a #lxw_validation_boolean value. It
381
+ * is on by default.
382
+ */
383
+ uint8_t show_input;
384
+
385
+ /**
386
+ * This parameter is used to toggle on and off the 'Show error alert
387
+ * after invalid data is entered' option in the Excel data validation
388
+ * dialog. When the option is off an error message is not displayed even
389
+ * if it has been set using error_message. Should be a
390
+ * #lxw_validation_boolean value. It is on by default.
391
+ */
392
+ uint8_t show_error;
393
+
394
+ /**
395
+ * This parameter is used to specify the type of error dialog that is
396
+ * displayed. Should be a #lxw_validation_error_types value.
397
+ */
398
+ uint8_t error_type;
399
+
400
+ /**
401
+ * This parameter is used to toggle on and off the 'In-cell dropdown'
402
+ * option in the Excel data validation dialog. When the option is on a
403
+ * dropdown list will be shown for list validations. Should be a
404
+ * #lxw_validation_boolean value. It is on by default.
405
+ */
406
+ uint8_t dropdown;
407
+
408
+ uint8_t is_between;
409
+
410
+ /**
411
+ * This parameter is used to set the limiting value to which the criteria
412
+ * is applied using a whole or decimal number.
413
+ */
414
+ double value_number;
415
+
416
+ /**
417
+ * This parameter is used to set the limiting value to which the criteria
418
+ * is applied using a cell reference. It is valid for any of the
419
+ * `_FORMULA` validation types.
420
+ */
421
+ char *value_formula;
422
+
423
+ /**
424
+ * This parameter is used to set a list of strings for a drop down list.
425
+ * The list should be a `NULL` terminated array of char* strings:
426
+ *
427
+ * @code
428
+ * char *list[] = {"open", "high", "close", NULL};
429
+ *
430
+ * data_validation->validate = LXW_VALIDATION_TYPE_LIST;
431
+ * data_validation->value_list = list;
432
+ * @endcode
433
+ *
434
+ * The `value_formula` parameter can also be used to specify a list from
435
+ * an Excel cell range.
436
+ *
437
+ * Note, the string list is restricted by Excel to 255 characters,
438
+ * including comma separators.
439
+ */
440
+ char **value_list;
441
+
442
+ /**
443
+ * This parameter is used to set the limiting value to which the date or
444
+ * time criteria is applied using a #lxw_datetime struct.
445
+ */
446
+ lxw_datetime value_datetime;
447
+
448
+ /**
449
+ * This parameter is the same as `value_number` but for the minimum value
450
+ * when a `BETWEEN` criteria is used.
451
+ */
452
+ double minimum_number;
453
+
454
+ /**
455
+ * This parameter is the same as `value_formula` but for the minimum value
456
+ * when a `BETWEEN` criteria is used.
457
+ */
458
+ char *minimum_formula;
459
+
460
+ /**
461
+ * This parameter is the same as `value_datetime` but for the minimum value
462
+ * when a `BETWEEN` criteria is used.
463
+ */
464
+ lxw_datetime minimum_datetime;
465
+
466
+ /**
467
+ * This parameter is the same as `value_number` but for the maximum value
468
+ * when a `BETWEEN` criteria is used.
469
+ */
470
+ double maximum_number;
471
+
472
+ /**
473
+ * This parameter is the same as `value_formula` but for the maximum value
474
+ * when a `BETWEEN` criteria is used.
475
+ */
476
+ char *maximum_formula;
477
+
478
+ /**
479
+ * This parameter is the same as `value_datetime` but for the maximum value
480
+ * when a `BETWEEN` criteria is used.
481
+ */
482
+ lxw_datetime maximum_datetime;
483
+
484
+ /**
485
+ * The input_title parameter is used to set the title of the input message
486
+ * that is displayed when a cell is entered. It has no default value and
487
+ * is only displayed if the input message is displayed. See the
488
+ * `input_message` parameter below.
489
+ *
490
+ * The maximum title length is 32 characters.
491
+ */
492
+ char *input_title;
493
+
494
+ /**
495
+ * The input_message parameter is used to set the input message that is
496
+ * displayed when a cell is entered. It has no default value.
497
+ *
498
+ * The message can be split over several lines using newlines. The maximum
499
+ * message length is 255 characters.
500
+ */
501
+ char *input_message;
502
+
503
+ /**
504
+ * The error_title parameter is used to set the title of the error message
505
+ * that is displayed when the data validation criteria is not met. The
506
+ * default error title is 'Microsoft Excel'. The maximum title length is
507
+ * 32 characters.
508
+ */
509
+ char *error_title;
510
+
511
+ /**
512
+ * The error_message parameter is used to set the error message that is
513
+ * displayed when a cell is entered. The default error message is "The
514
+ * value you entered is not valid. A user has restricted values that can
515
+ * be entered into the cell".
516
+ *
517
+ * The message can be split over several lines using newlines. The maximum
518
+ * message length is 255 characters.
519
+ */
520
+ char *error_message;
521
+
522
+ char sqref[LXW_MAX_CELL_RANGE_LENGTH];
523
+
524
+ STAILQ_ENTRY (lxw_data_validation) list_pointers;
525
+
526
+ } lxw_data_validation;
527
+
232
528
  /**
233
529
  * @brief Options for inserted images
234
530
  *
@@ -252,6 +548,7 @@ typedef struct lxw_image_options {
252
548
  lxw_row_t row;
253
549
  lxw_col_t col;
254
550
  char *filename;
551
+ char *description;
255
552
  char *url;
256
553
  char *tip;
257
554
  uint8_t anchor;
@@ -259,9 +556,11 @@ typedef struct lxw_image_options {
259
556
  /* Internal metadata. */
260
557
  FILE *stream;
261
558
  uint8_t image_type;
559
+ uint8_t is_image_buffer;
560
+ unsigned char *image_buffer;
561
+ size_t image_buffer_size;
262
562
  double width;
263
563
  double height;
264
- char *short_name;
265
564
  char *extension;
266
565
  double x_dpi;
267
566
  double y_dpi;
@@ -329,15 +628,39 @@ typedef struct lxw_protection {
329
628
  /** Protect scenarios. */
330
629
  uint8_t scenarios;
331
630
 
332
- /** Protect drawing objects. */
631
+ /** Protect drawing objects. Worksheets only. */
333
632
  uint8_t objects;
334
633
 
634
+ /** Turn off chartsheet content protection. */
635
+ uint8_t no_content;
636
+
637
+ /** Turn off chartsheet objects. */
638
+ uint8_t no_objects;
639
+
335
640
  uint8_t no_sheet;
336
- uint8_t content;
337
641
  uint8_t is_configured;
338
642
  char hash[5];
339
643
  } lxw_protection;
340
644
 
645
+ /**
646
+ * @brief Struct to represent a rich string format/string pair.
647
+ *
648
+ * Arrays of this struct are used to define "rich" multi-format strings that
649
+ * are passed to `worksheet_write_rich_string()`. Each struct represents a
650
+ * fragment of the rich multi-format string with a lxw_format to define the
651
+ * format for the string part. If the string fragment is unformatted then
652
+ * `NULL` can be used for the format.
653
+ */
654
+ typedef struct lxw_rich_string_tuple {
655
+
656
+ /** The format for a string fragment in a rich string. NULL if the string
657
+ * isn't formatted. */
658
+ lxw_format *format;
659
+
660
+ /** The string fragment. */
661
+ char *string;
662
+ } lxw_rich_string_tuple;
663
+
341
664
  /**
342
665
  * @brief Struct to represent an Excel worksheet.
343
666
  *
@@ -354,6 +677,7 @@ typedef struct lxw_worksheet {
354
677
  struct lxw_cell **array;
355
678
  struct lxw_merged_ranges *merged_ranges;
356
679
  struct lxw_selections *selections;
680
+ struct lxw_data_validations *data_validations;
357
681
  struct lxw_image_data *image_data;
358
682
  struct lxw_chart_data *chart_data;
359
683
 
@@ -373,6 +697,7 @@ typedef struct lxw_worksheet {
373
697
  uint8_t hidden;
374
698
  uint16_t *active_sheet;
375
699
  uint16_t *first_sheet;
700
+ uint8_t is_chartsheet;
376
701
 
377
702
  lxw_col_options **col_options;
378
703
  uint16_t col_options_max;
@@ -403,6 +728,9 @@ typedef struct lxw_worksheet {
403
728
  uint8_t orientation;
404
729
  uint8_t outline_changed;
405
730
  uint8_t outline_on;
731
+ uint8_t outline_style;
732
+ uint8_t outline_below;
733
+ uint8_t outline_right;
406
734
  uint8_t page_order;
407
735
  uint8_t page_setup_changed;
408
736
  uint8_t page_view;
@@ -413,9 +741,10 @@ typedef struct lxw_worksheet {
413
741
  uint8_t right_to_left;
414
742
  uint8_t screen_gridlines;
415
743
  uint8_t show_zeros;
416
- uint8_t vba_codename;
417
744
  uint8_t vcenter;
418
745
  uint8_t zoom_scale_normal;
746
+ uint8_t num_validations;
747
+ char *vba_codename;
419
748
 
420
749
  lxw_color_t tab_color;
421
750
 
@@ -431,6 +760,8 @@ typedef struct lxw_worksheet {
431
760
  uint32_t default_col_pixels;
432
761
  uint8_t default_row_zeroed;
433
762
  uint8_t default_row_set;
763
+ uint8_t outline_row_level;
764
+ uint8_t outline_col_level;
434
765
 
435
766
  uint8_t header_footer_changed;
436
767
  char header[LXW_HEADER_FOOTER_MAX];
@@ -561,6 +892,10 @@ extern "C" {
561
892
  *
562
893
  * @image html write_number02.png
563
894
  *
895
+ * @note Excel doesn't support `NaN`, `Inf` or `-Inf` as a number value. If
896
+ * you are writing data that contains these values then your application
897
+ * should convert them to a string or handle them in some other way.
898
+ *
564
899
  */
565
900
  lxw_error worksheet_write_number(lxw_worksheet *worksheet,
566
901
  lxw_row_t row,
@@ -661,6 +996,7 @@ lxw_error worksheet_write_string(lxw_worksheet *worksheet,
661
996
  * worksheet_write_formula(worksheet, 1, 0, "=SUM(1; 2; 3)", NULL);
662
997
  * @endcode
663
998
  *
999
+ * See also @ref working_with_formulas.
664
1000
  */
665
1001
  lxw_error worksheet_write_formula(lxw_worksheet *worksheet,
666
1002
  lxw_row_t row,
@@ -669,7 +1005,7 @@ lxw_error worksheet_write_formula(lxw_worksheet *worksheet,
669
1005
  /**
670
1006
  * @brief Write an array formula to a worksheet cell.
671
1007
  *
672
- * @param worksheet
1008
+ * @param worksheet pointer to a lxw_worksheet instance to be updated.
673
1009
  * @param first_row The first row of the range. (All zero indexed.)
674
1010
  * @param first_col The first column of the range.
675
1011
  * @param last_row The last row of the range.
@@ -874,7 +1210,7 @@ lxw_error worksheet_write_url_opt(lxw_worksheet *worksheet,
874
1210
  * @endcode
875
1211
  *
876
1212
  *
877
- * Alternatively, you can use Windows style forward slashes. These are
1213
+ * Alternatively, you can use Unix style forward slashes. These are
878
1214
  * translated internally to backslashes:
879
1215
  *
880
1216
  * @code
@@ -991,6 +1327,7 @@ lxw_error worksheet_write_blank(lxw_worksheet *worksheet,
991
1327
  * worksheet_write_formula() function is the recommended way of writing
992
1328
  * formulas.
993
1329
  *
1330
+ * See also @ref working_with_formulas.
994
1331
  */
995
1332
  lxw_error worksheet_write_formula_num(lxw_worksheet *worksheet,
996
1333
  lxw_row_t row,
@@ -998,6 +1335,81 @@ lxw_error worksheet_write_formula_num(lxw_worksheet *worksheet,
998
1335
  const char *formula,
999
1336
  lxw_format *format, double result);
1000
1337
 
1338
+ /**
1339
+ * @brief Write a "Rich" multi-format string to a worksheet cell.
1340
+ *
1341
+ * @param worksheet pointer to a lxw_worksheet instance to be updated.
1342
+ * @param row The zero indexed row number.
1343
+ * @param col The zero indexed column number.
1344
+ * @param rich_string An array of format/string lxw_rich_string_tuple fragments.
1345
+ * @param format A pointer to a Format instance or NULL.
1346
+ *
1347
+ * @return A #lxw_error code.
1348
+ *
1349
+ * The `%worksheet_write_rich_string()` function is used to write strings with
1350
+ * multiple formats. For example to write the string 'This is **bold**
1351
+ * and this is *italic*' you would use the following:
1352
+ *
1353
+ * @code
1354
+ * lxw_format *bold = workbook_add_format(workbook);
1355
+ * format_set_bold(bold);
1356
+ *
1357
+ * lxw_format *italic = workbook_add_format(workbook);
1358
+ * format_set_italic(italic);
1359
+ *
1360
+ * lxw_rich_string_tuple fragment11 = {.format = NULL, .string = "This is " };
1361
+ * lxw_rich_string_tuple fragment12 = {.format = bold, .string = "bold" };
1362
+ * lxw_rich_string_tuple fragment13 = {.format = NULL, .string = " and this is "};
1363
+ * lxw_rich_string_tuple fragment14 = {.format = italic, .string = "italic" };
1364
+ *
1365
+ * lxw_rich_string_tuple *rich_string1[] = {&fragment11, &fragment12,
1366
+ * &fragment13, &fragment14, NULL};
1367
+ *
1368
+ * worksheet_write_rich_string(worksheet, CELL("A1"), rich_string1, NULL);
1369
+ *
1370
+ * @endcode
1371
+ *
1372
+ * @image html rich_strings_small.png
1373
+ *
1374
+ * The basic rule is to break the string into fragments and put a lxw_format
1375
+ * object before the fragment that you want to format. So if we look at the
1376
+ * above example again:
1377
+ *
1378
+ * This is **bold** and this is *italic*
1379
+ *
1380
+ * The would be broken down into 4 fragments:
1381
+ *
1382
+ * default: |This is |
1383
+ * bold: |bold|
1384
+ * default: | and this is |
1385
+ * italic: |italic|
1386
+ *
1387
+ * This in then converted to the lxw_rich_string_tuple fragments shown in the
1388
+ * example above. For the default format we use `NULL`.
1389
+ *
1390
+ * The fragments are passed to `%worksheet_write_rich_string()` as a `NULL`
1391
+ * terminated array:
1392
+ *
1393
+ * @code
1394
+ * lxw_rich_string_tuple *rich_string1[] = {&fragment11, &fragment12,
1395
+ * &fragment13, &fragment14, NULL};
1396
+ *
1397
+ * worksheet_write_rich_string(worksheet, CELL("A1"), rich_string1, NULL);
1398
+ *
1399
+ * @endcode
1400
+ *
1401
+ * **Note**:
1402
+ * Excel doesn't allow the use of two consecutive formats in a rich string or
1403
+ * an empty string fragment. For either of these conditions a warning is
1404
+ * raised and the input to `%worksheet_write_rich_string()` is ignored.
1405
+ *
1406
+ */
1407
+ lxw_error worksheet_write_rich_string(lxw_worksheet *worksheet,
1408
+ lxw_row_t row,
1409
+ lxw_col_t col,
1410
+ lxw_rich_string_tuple *rich_string[],
1411
+ lxw_format *format);
1412
+
1001
1413
  /**
1002
1414
  * @brief Set the properties for a row of cells.
1003
1415
  *
@@ -1066,7 +1478,7 @@ lxw_error worksheet_set_row(lxw_worksheet *worksheet,
1066
1478
  * `worksheet_set_row()` with an additional `options` parameter.
1067
1479
  *
1068
1480
  * The `options` parameter is a #lxw_row_col_options struct. It has the
1069
- * following members but currently only the `hidden` property is supported:
1481
+ * following members:
1070
1482
  *
1071
1483
  * - `hidden`
1072
1484
  * - `level`
@@ -1076,12 +1488,41 @@ lxw_error worksheet_set_row(lxw_worksheet *worksheet,
1076
1488
  * example, to hide intermediary steps in a complicated calculation:
1077
1489
  *
1078
1490
  * @code
1079
- * lxw_row_col_options options = {.hidden = 1, .level = 0, .collapsed = 0};
1491
+ * lxw_row_col_options options1 = {.hidden = 1, .level = 0, .collapsed = 0};
1492
+ *
1493
+ * // Hide the fourth and fifth (zero indexed) rows.
1494
+ * worksheet_set_row_opt(worksheet, 3, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1495
+ * worksheet_set_row_opt(worksheet, 4, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1080
1496
  *
1081
- * // Hide the fourth row.
1082
- * worksheet_set_row(worksheet, 3, 20, NULL, &options);
1083
1497
  * @endcode
1084
1498
  *
1499
+ * @image html hide_row_col2.png
1500
+ *
1501
+ * The `"hidden"`, `"level"`, and `"collapsed"`, options can also be used to
1502
+ * create Outlines and Grouping. See @ref working_with_outlines.
1503
+ *
1504
+ * @code
1505
+ * // The option structs with the outline level set.
1506
+ * lxw_row_col_options options1 = {.hidden = 0, .level = 2, .collapsed = 0};
1507
+ * lxw_row_col_options options2 = {.hidden = 0, .level = 1, .collapsed = 0};
1508
+ *
1509
+ *
1510
+ * // Set the row options with the outline level.
1511
+ * worksheet_set_row_opt(worksheet, 1, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1512
+ * worksheet_set_row_opt(worksheet, 2, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1513
+ * worksheet_set_row_opt(worksheet, 3, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1514
+ * worksheet_set_row_opt(worksheet, 4, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1515
+ * worksheet_set_row_opt(worksheet, 5, LXW_DEF_ROW_HEIGHT, NULL, &options2);
1516
+ *
1517
+ * worksheet_set_row_opt(worksheet, 6, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1518
+ * worksheet_set_row_opt(worksheet, 7, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1519
+ * worksheet_set_row_opt(worksheet, 8, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1520
+ * worksheet_set_row_opt(worksheet, 9, LXW_DEF_ROW_HEIGHT, NULL, &options1);
1521
+ * worksheet_set_row_opt(worksheet, 10, LXW_DEF_ROW_HEIGHT, NULL, &options2);
1522
+ * @endcode
1523
+ *
1524
+ * @image html outline1.png
1525
+ *
1085
1526
  */
1086
1527
  lxw_error worksheet_set_row_opt(lxw_worksheet *worksheet,
1087
1528
  lxw_row_t row,
@@ -1151,7 +1592,7 @@ lxw_error worksheet_set_row_opt(lxw_worksheet *worksheet,
1151
1592
  * format_set_bold(bold);
1152
1593
  *
1153
1594
  * // Set the first column to bold.
1154
- * worksheet_set_column(worksheet, 0, 0, LXW_DEF_COL_HEIGHT, bold);
1595
+ * worksheet_set_column(worksheet, 0, 0, LXW_DEF_COL_WIDTH, bold);
1155
1596
  * @endcode
1156
1597
  *
1157
1598
  * The `format` parameter will be applied to any cells in the column that
@@ -1189,36 +1630,48 @@ lxw_error worksheet_set_column(lxw_worksheet *worksheet,
1189
1630
  lxw_col_t last_col,
1190
1631
  double width, lxw_format *format);
1191
1632
 
1192
- /**
1193
- * @brief Set the properties for one or more columns of cells with options.
1194
- *
1195
- * @param worksheet Pointer to a lxw_worksheet instance to be updated.
1196
- * @param first_col The zero indexed first column.
1197
- * @param last_col The zero indexed last column.
1198
- * @param width The width of the column(s).
1199
- * @param format A pointer to a Format instance or NULL.
1200
- * @param options Optional row parameters: hidden, level, collapsed.
1201
- *
1202
- * The `%worksheet_set_column_opt()` function is the same as
1203
- * `worksheet_set_column()` with an additional `options` parameter.
1204
- *
1205
- * The `options` parameter is a #lxw_row_col_options struct. It has the
1206
- * following members but currently only the `hidden` property is supported:
1207
- *
1208
- * - `hidden`
1209
- * - `level`
1210
- * - `collapsed`
1211
- *
1212
- * The `"hidden"` option is used to hide a column. This can be used, for
1213
- * example, to hide intermediary steps in a complicated calculation:
1214
- *
1215
- * @code
1216
- * lxw_row_col_options options = {.hidden = 1, .level = 0, .collapsed = 0};
1217
- *
1218
- * worksheet_set_column_opt(worksheet, COLS("A:A"), 8.43, NULL, &options);
1219
- * @endcode
1220
- *
1221
- */
1633
+ /**
1634
+ * @brief Set the properties for one or more columns of cells with options.
1635
+ *
1636
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
1637
+ * @param first_col The zero indexed first column.
1638
+ * @param last_col The zero indexed last column.
1639
+ * @param width The width of the column(s).
1640
+ * @param format A pointer to a Format instance or NULL.
1641
+ * @param options Optional row parameters: hidden, level, collapsed.
1642
+ *
1643
+ * The `%worksheet_set_column_opt()` function is the same as
1644
+ * `worksheet_set_column()` with an additional `options` parameter.
1645
+ *
1646
+ * The `options` parameter is a #lxw_row_col_options struct. It has the
1647
+ * following members:
1648
+ *
1649
+ * - `hidden`
1650
+ * - `level`
1651
+ * - `collapsed`
1652
+ *
1653
+ * The `"hidden"` option is used to hide a column. This can be used, for
1654
+ * example, to hide intermediary steps in a complicated calculation:
1655
+ *
1656
+ * @code
1657
+ * lxw_row_col_options options1 = {.hidden = 1, .level = 0, .collapsed = 0};
1658
+ *
1659
+ * worksheet_set_column_opt(worksheet, COLS("D:E"), LXW_DEF_COL_WIDTH, NULL, &options1);
1660
+ * @endcode
1661
+ *
1662
+ * @image html hide_row_col3.png
1663
+ *
1664
+ * The `"hidden"`, `"level"`, and `"collapsed"`, options can also be used to
1665
+ * create Outlines and Grouping. See @ref working_with_outlines.
1666
+ *
1667
+ * @code
1668
+ * lxw_row_col_options options1 = {.hidden = 0, .level = 1, .collapsed = 0};
1669
+ *
1670
+ * worksheet_set_column_opt(worksheet, COLS("B:G"), 5, NULL, &options1);
1671
+ * @endcode
1672
+ *
1673
+ * @image html outline8.png
1674
+ */
1222
1675
  lxw_error worksheet_set_column_opt(lxw_worksheet *worksheet,
1223
1676
  lxw_col_t first_col,
1224
1677
  lxw_col_t last_col,
@@ -1295,6 +1748,77 @@ lxw_error worksheet_insert_image_opt(lxw_worksheet *worksheet,
1295
1748
  lxw_row_t row, lxw_col_t col,
1296
1749
  const char *filename,
1297
1750
  lxw_image_options *options);
1751
+
1752
+ /**
1753
+ * @brief Insert an image in a worksheet cell, from a memory buffer.
1754
+ *
1755
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
1756
+ * @param row The zero indexed row number.
1757
+ * @param col The zero indexed column number.
1758
+ * @param image_buffer Pointer to an array of bytes that holds the image data.
1759
+ * @param image_size The size of the array of bytes.
1760
+ *
1761
+ * @return A #lxw_error code.
1762
+ *
1763
+ * This function can be used to insert a image into a worksheet from a memory
1764
+ * buffer:
1765
+ *
1766
+ * @code
1767
+ * worksheet_insert_image_buffer(worksheet, CELL("B3"), image_buffer, image_size);
1768
+ * @endcode
1769
+ *
1770
+ * @image html image_buffer.png
1771
+ *
1772
+ * The buffer should be a pointer to an array of unsigned char data with a
1773
+ * specified size.
1774
+ *
1775
+ * See `worksheet_insert_image()` for details about the supported image
1776
+ * formats, and other image features.
1777
+ */
1778
+ lxw_error worksheet_insert_image_buffer(lxw_worksheet *worksheet,
1779
+ lxw_row_t row,
1780
+ lxw_col_t col,
1781
+ const unsigned char *image_buffer,
1782
+ size_t image_size);
1783
+
1784
+ /**
1785
+ * @brief Insert an image in a worksheet cell, from a memory buffer.
1786
+ *
1787
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
1788
+ * @param row The zero indexed row number.
1789
+ * @param col The zero indexed column number.
1790
+ * @param image_buffer Pointer to an array of bytes that holds the image data.
1791
+ * @param image_size The size of the array of bytes.
1792
+ * @param options Optional image parameters.
1793
+ *
1794
+ * @return A #lxw_error code.
1795
+ *
1796
+ * The `%worksheet_insert_image_buffer_opt()` function is like
1797
+ * `worksheet_insert_image_buffer()` function except that it takes an optional
1798
+ * #lxw_image_options struct to scale and position the image:
1799
+ *
1800
+ * @code
1801
+ * lxw_image_options options = {.x_offset = 32, .y_offset = 4,
1802
+ * .x_scale = 2, .y_scale = 1};
1803
+ *
1804
+ * worksheet_insert_image_buffer_opt(worksheet, CELL("B3"), image_buffer, image_size, &options);
1805
+ * @endcode
1806
+ *
1807
+ * @image html image_buffer_opt.png
1808
+ *
1809
+ * The buffer should be a pointer to an array of unsigned char data with a
1810
+ * specified size.
1811
+ *
1812
+ * See `worksheet_insert_image_buffer_opt()` for details about the supported
1813
+ * image formats, and other image options.
1814
+ */
1815
+ lxw_error worksheet_insert_image_buffer_opt(lxw_worksheet *worksheet,
1816
+ lxw_row_t row,
1817
+ lxw_col_t col,
1818
+ const unsigned char *image_buffer,
1819
+ size_t image_size,
1820
+ lxw_image_options *options);
1821
+
1298
1822
  /**
1299
1823
  * @brief Insert a chart object into a worksheet.
1300
1824
  *
@@ -1305,8 +1829,8 @@ lxw_error worksheet_insert_image_opt(lxw_worksheet *worksheet,
1305
1829
  *
1306
1830
  * @return A #lxw_error code.
1307
1831
  *
1308
- * The `%worksheet_insert_chart()` can be used to insert a chart into a
1309
- * worksheet. The chart object must be created first using the
1832
+ * The `%worksheet_insert_chart()` function can be used to insert a chart into
1833
+ * a worksheet. The chart object must be created first using the
1310
1834
  * `workbook_add_chart()` function and configured using the @ref chart.h
1311
1835
  * functions.
1312
1836
  *
@@ -1317,13 +1841,12 @@ lxw_error worksheet_insert_image_opt(lxw_worksheet *worksheet,
1317
1841
  * // Add a data series to the chart.
1318
1842
  * chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6");
1319
1843
  *
1320
- * // Insert the chart into the worksheet
1844
+ * // Insert the chart into the worksheet.
1321
1845
  * worksheet_insert_chart(worksheet, 0, 2, chart);
1322
1846
  * @endcode
1323
1847
  *
1324
1848
  * @image html chart_working.png
1325
1849
  *
1326
- *
1327
1850
  * **Note:**
1328
1851
  *
1329
1852
  * A chart may only be inserted into a worksheet once. If several similar
@@ -1470,6 +1993,87 @@ lxw_error worksheet_autofilter(lxw_worksheet *worksheet, lxw_row_t first_row,
1470
1993
  lxw_col_t first_col, lxw_row_t last_row,
1471
1994
  lxw_col_t last_col);
1472
1995
 
1996
+ /**
1997
+ * @brief Add a data validation to a cell.
1998
+ *
1999
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
2000
+ * @param row The zero indexed row number.
2001
+ * @param col The zero indexed column number.
2002
+ * @param validation A #lxw_data_validation object to control the validation.
2003
+ *
2004
+ * @return A #lxw_error code.
2005
+ *
2006
+ * The `%worksheet_data_validation_cell()` function is used to construct an
2007
+ * Excel data validation or to limit the user input to a dropdown list of
2008
+ * values:
2009
+ *
2010
+ * @code
2011
+ *
2012
+ * lxw_data_validation *data_validation = calloc(1, sizeof(lxw_data_validation));
2013
+ *
2014
+ * data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
2015
+ * data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
2016
+ * data_validation->minimum_number = 1;
2017
+ * data_validation->maximum_number = 10;
2018
+ *
2019
+ * worksheet_data_validation_cell(worksheet, 2, 1, data_validation);
2020
+ *
2021
+ * // Same as above with the CELL() macro.
2022
+ * worksheet_data_validation_cell(worksheet, CELL("B3"), data_validation);
2023
+ *
2024
+ * @endcode
2025
+ *
2026
+ * @image html data_validate4.png
2027
+ *
2028
+ * Data validation and the various options of #lxw_data_validation are
2029
+ * described in more detail in @ref working_with_data_validation.
2030
+ */
2031
+ lxw_error worksheet_data_validation_cell(lxw_worksheet *worksheet,
2032
+ lxw_row_t row, lxw_col_t col,
2033
+ lxw_data_validation *validation);
2034
+
2035
+ /**
2036
+ * @brief Add a data validation to a range cell.
2037
+ *
2038
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
2039
+ * @param first_row The first row of the range. (All zero indexed.)
2040
+ * @param first_col The first column of the range.
2041
+ * @param last_row The last row of the range.
2042
+ * @param last_col The last col of the range.
2043
+ * @param validation A #lxw_data_validation object to control the validation.
2044
+ *
2045
+ * @return A #lxw_error code.
2046
+ *
2047
+ * The `%worksheet_data_validation_range()` function is the same as the
2048
+ * `%worksheet_data_validation_cell()`, see above, except the data validation
2049
+ * is applied to a range of cells:
2050
+ *
2051
+ * @code
2052
+ *
2053
+ * lxw_data_validation *data_validation = calloc(1, sizeof(lxw_data_validation));
2054
+ *
2055
+ * data_validation->validate = LXW_VALIDATION_TYPE_INTEGER;
2056
+ * data_validation->criteria = LXW_VALIDATION_CRITERIA_BETWEEN;
2057
+ * data_validation->minimum_number = 1;
2058
+ * data_validation->maximum_number = 10;
2059
+ *
2060
+ * worksheet_data_validation_range(worksheet, 2, 1, 4, 1, data_validation);
2061
+ *
2062
+ * // Same as above with the RANGE() macro.
2063
+ * worksheet_data_validation_range(worksheet, RANGE("B3:B5"), data_validation);
2064
+ *
2065
+ * @endcode
2066
+ *
2067
+ * Data validation and the various options of #lxw_data_validation are
2068
+ * described in more detail in @ref working_with_data_validation.
2069
+ */
2070
+ lxw_error worksheet_data_validation_range(lxw_worksheet *worksheet,
2071
+ lxw_row_t first_row,
2072
+ lxw_col_t first_col,
2073
+ lxw_row_t last_row,
2074
+ lxw_col_t last_col,
2075
+ lxw_data_validation *validation);
2076
+
1473
2077
  /**
1474
2078
  * @brief Make a worksheet the active, i.e., visible worksheet.
1475
2079
  *
@@ -1853,26 +2457,26 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left,
1853
2457
  * @code
1854
2458
  * worksheet_set_header(worksheet, "&LHello");
1855
2459
  *
1856
- * ---------------------------------------------------------------
1857
- * | |
1858
- * | Hello |
1859
- * | |
2460
+ * // ---------------------------------------------------------------
2461
+ * // | |
2462
+ * // | Hello |
2463
+ * // | |
1860
2464
  *
1861
2465
  *
1862
2466
  * worksheet_set_header(worksheet, "&CHello");
1863
2467
  *
1864
- * ---------------------------------------------------------------
1865
- * | |
1866
- * | Hello |
1867
- * | |
2468
+ * // ---------------------------------------------------------------
2469
+ * // | |
2470
+ * // | Hello |
2471
+ * // | |
1868
2472
  *
1869
2473
  *
1870
2474
  * worksheet_set_header(worksheet, "&RHello");
1871
2475
  *
1872
- * ---------------------------------------------------------------
1873
- * | |
1874
- * | Hello |
1875
- * | |
2476
+ * // ---------------------------------------------------------------
2477
+ * // | |
2478
+ * // | Hello |
2479
+ * // | |
1876
2480
  *
1877
2481
  *
1878
2482
  * @endcode
@@ -1884,10 +2488,10 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left,
1884
2488
  * @code
1885
2489
  * worksheet_set_header(worksheet, "Hello");
1886
2490
  *
1887
- * ---------------------------------------------------------------
1888
- * | |
1889
- * | Hello |
1890
- * | |
2491
+ * // ---------------------------------------------------------------
2492
+ * // | |
2493
+ * // | Hello |
2494
+ * // | |
1891
2495
  *
1892
2496
  * @endcode
1893
2497
  *
@@ -1896,10 +2500,10 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left,
1896
2500
  * @code
1897
2501
  * worksheet_set_header(worksheet, "&LCiao&CBello&RCielo");
1898
2502
  *
1899
- * ---------------------------------------------------------------
1900
- * | |
1901
- * | Ciao Bello Cielo |
1902
- * | |
2503
+ * // ---------------------------------------------------------------
2504
+ * // | |
2505
+ * // | Ciao Bello Cielo |
2506
+ * // | |
1903
2507
  *
1904
2508
  * @endcode
1905
2509
  *
@@ -1910,17 +2514,17 @@ void worksheet_set_margins(lxw_worksheet *worksheet, double left,
1910
2514
  * @code
1911
2515
  * worksheet_set_header(worksheet, "&CPage &P of &N");
1912
2516
  *
1913
- * ---------------------------------------------------------------
1914
- * | |
1915
- * | Page 1 of 6 |
1916
- * | |
2517
+ * // ---------------------------------------------------------------
2518
+ * // | |
2519
+ * // | Page 1 of 6 |
2520
+ * // | |
1917
2521
  *
1918
2522
  * worksheet_set_header(worksheet, "&CUpdated at &T");
1919
2523
  *
1920
- * ---------------------------------------------------------------
1921
- * | |
1922
- * | Updated at 12:30 PM |
1923
- * | |
2524
+ * // ---------------------------------------------------------------
2525
+ * // | |
2526
+ * // | Updated at 12:30 PM |
2527
+ * // | |
1924
2528
  *
1925
2529
  * @endcode
1926
2530
  *
@@ -2460,8 +3064,8 @@ void worksheet_hide_zero(lxw_worksheet *worksheet);
2460
3064
  * @param worksheet Pointer to a lxw_worksheet instance to be updated.
2461
3065
  * @param color The tab color.
2462
3066
  *
2463
- * The `%worksheet_set_tab_color()` function is used to change the color of the worksheet
2464
- * tab:
3067
+ * The `%worksheet_set_tab_color()` function is used to change the color of
3068
+ * the worksheet tab:
2465
3069
  *
2466
3070
  * @code
2467
3071
  * worksheet_set_tab_color(worksheet1, LXW_COLOR_RED);
@@ -2544,15 +3148,62 @@ void worksheet_set_tab_color(lxw_worksheet *worksheet, lxw_color_t color);
2544
3148
  *
2545
3149
  * See also the format_set_unlocked() and format_set_hidden() format functions.
2546
3150
  *
2547
- * **Note:** Worksheet level passwords in Excel offer **very** weak
3151
+ * **Note:** Sheet level passwords in Excel offer **very** weak
2548
3152
  * protection. They don't encrypt your data and are very easy to
2549
3153
  * deactivate. Full workbook encryption is not supported by `libxlsxwriter`
2550
- * since it requires a completely different file format and would take several
2551
- * man months to implement.
3154
+ * since it requires a completely different file format.
2552
3155
  */
2553
3156
  void worksheet_protect(lxw_worksheet *worksheet, const char *password,
2554
3157
  lxw_protection *options);
2555
3158
 
3159
+ /**
3160
+ * @brief Set the Outline and Grouping display properties.
3161
+ *
3162
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
3163
+ * @param visible Outlines are visible. Optional, defaults to True.
3164
+ * @param symbols_below Show row outline symbols below the outline bar.
3165
+ * @param symbols_right Show column outline symbols to the right of outline.
3166
+ * @param auto_style Use Automatic outline style.
3167
+ *
3168
+ * The `%worksheet_outline_settings()` method is used to control the
3169
+ * appearance of outlines in Excel. Outlines are described the section on
3170
+ * @ref working_with_outlines.
3171
+ *
3172
+ * The `visible` parameter is used to control whether or not outlines are
3173
+ * visible. Setting this parameter to False will cause all outlines on the
3174
+ * worksheet to be hidden. They can be un-hidden in Excel by means of the
3175
+ * "Show Outline Symbols" command button. The default Excel setting is True
3176
+ * for visible outlines.
3177
+ *
3178
+ * The `symbols_below` parameter is used to control whether the row outline
3179
+ * symbol will appear above or below the outline level bar. The default Excel
3180
+ * setting is True for symbols to appear below the outline level bar.
3181
+ *
3182
+ * The `symbols_right` parameter is used to control whether the column outline
3183
+ * symbol will appear to the left or the right of the outline level bar. The
3184
+ * default Excel setting is True for symbols to appear to the right of the
3185
+ * outline level bar.
3186
+ *
3187
+ * The `auto_style` parameter is used to control whether the automatic outline
3188
+ * generator in Excel uses automatic styles when creating an outline. This has
3189
+ * no effect on a file generated by XlsxWriter but it does have an effect on
3190
+ * how the worksheet behaves after it is created. The default Excel setting is
3191
+ * False for "Automatic Styles" to be turned off.
3192
+ *
3193
+ * The default settings for all of these parameters in libxlsxwriter
3194
+ * correspond to Excel's default parameters and are shown below:
3195
+ *
3196
+ * @code
3197
+ * worksheet_outline_settings(worksheet1, LXW_TRUE, LXW_TRUE, LXW_TRUE, LXW_FALSE);
3198
+ * @endcode
3199
+ *
3200
+ * The worksheet parameters controlled by `worksheet_outline_settings()` are
3201
+ * rarely used.
3202
+ */
3203
+ void worksheet_outline_settings(lxw_worksheet *worksheet, uint8_t visible,
3204
+ uint8_t symbols_below, uint8_t symbols_right,
3205
+ uint8_t auto_style);
3206
+
2556
3207
  /**
2557
3208
  * @brief Set the default row properties.
2558
3209
  *
@@ -2584,22 +3235,58 @@ void worksheet_protect(lxw_worksheet *worksheet, const char *password,
2584
3235
  void worksheet_set_default_row(lxw_worksheet *worksheet, double height,
2585
3236
  uint8_t hide_unused_rows);
2586
3237
 
3238
+ /**
3239
+ * @brief Set the VBA name for the worksheet.
3240
+ *
3241
+ * @param worksheet Pointer to a lxw_worksheet instance.
3242
+ * @param name Name of the worksheet used by VBA.
3243
+ *
3244
+ * The `worksheet_set_vba_name()` function can be used to set the VBA name for
3245
+ * the worksheet. This is sometimes required when a vbaProject macro included
3246
+ * via `workbook_add_vba_project()` refers to the worksheet.
3247
+ *
3248
+ * @code
3249
+ * workbook_set_vba_name (workbook, "MyWorkbook");
3250
+ * worksheet_set_vba_name(worksheet, "MySheet1");
3251
+ * @endcode
3252
+ *
3253
+ * In general Excel uses the worksheet name such as "Sheet1" as the VBA name.
3254
+ * However, this can be changed in the VBA environment or if the the macro was
3255
+ * extracted from a foreign language version of Excel.
3256
+ *
3257
+ * @return A #lxw_error.
3258
+ */
3259
+ lxw_error worksheet_set_vba_name(lxw_worksheet *worksheet, const char *name);
3260
+
2587
3261
  lxw_worksheet *lxw_worksheet_new(lxw_worksheet_init_data *init_data);
2588
3262
  void lxw_worksheet_free(lxw_worksheet *worksheet);
2589
3263
  void lxw_worksheet_assemble_xml_file(lxw_worksheet *worksheet);
2590
3264
  void lxw_worksheet_write_single_row(lxw_worksheet *worksheet);
2591
3265
 
2592
3266
  void lxw_worksheet_prepare_image(lxw_worksheet *worksheet,
2593
- uint16_t image_ref_id, uint16_t drawing_id,
3267
+ uint32_t image_ref_id, uint32_t drawing_id,
2594
3268
  lxw_image_options *image_data);
2595
3269
 
2596
3270
  void lxw_worksheet_prepare_chart(lxw_worksheet *worksheet,
2597
- uint16_t chart_ref_id, uint16_t drawing_id,
2598
- lxw_image_options *image_data);
3271
+ uint32_t chart_ref_id, uint32_t drawing_id,
3272
+ lxw_image_options *image_data,
3273
+ uint8_t is_chartsheet);
2599
3274
 
2600
3275
  lxw_row *lxw_worksheet_find_row(lxw_worksheet *worksheet, lxw_row_t row_num);
2601
3276
  lxw_cell *lxw_worksheet_find_cell(lxw_row *row, lxw_col_t col_num);
2602
3277
 
3278
+ /*
3279
+ * External functions to call intern XML methods shared with chartsheet.
3280
+ */
3281
+ void lxw_worksheet_write_sheet_views(lxw_worksheet *worksheet);
3282
+ void lxw_worksheet_write_page_margins(lxw_worksheet *worksheet);
3283
+ void lxw_worksheet_write_drawings(lxw_worksheet *worksheet);
3284
+ void lxw_worksheet_write_sheet_protection(lxw_worksheet *worksheet,
3285
+ lxw_protection *protect);
3286
+ void lxw_worksheet_write_sheet_pr(lxw_worksheet *worksheet);
3287
+ void lxw_worksheet_write_page_setup(lxw_worksheet *worksheet);
3288
+ void lxw_worksheet_write_header_footer(lxw_worksheet *worksheet);
3289
+
2603
3290
  /* Declarations required for unit testing. */
2604
3291
  #ifdef TESTING
2605
3292
 
@@ -2629,7 +3316,9 @@ STATIC void _worksheet_write_header_footer(lxw_worksheet *worksheet);
2629
3316
  STATIC void _worksheet_write_print_options(lxw_worksheet *worksheet);
2630
3317
  STATIC void _worksheet_write_sheet_pr(lxw_worksheet *worksheet);
2631
3318
  STATIC void _worksheet_write_tab_color(lxw_worksheet *worksheet);
2632
- STATIC void _worksheet_write_sheet_protection(lxw_worksheet *worksheet);
3319
+ STATIC void _worksheet_write_sheet_protection(lxw_worksheet *worksheet,
3320
+ lxw_protection *protect);
3321
+ STATIC void _worksheet_write_data_validations(lxw_worksheet *self);
2633
3322
  #endif /* TESTING */
2634
3323
 
2635
3324
  /* *INDENT-OFF* */