xlsxwriter 0.2.0 → 0.2.1.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5952e238ec4dc55988d50bacd80e39132daca19f62ad8c6191705b240ad40cf1
4
- data.tar.gz: '05824be3c90e0ebbf3a44df01034b3d300191ea8712cb7e4d24643aa68b0beef'
3
+ metadata.gz: 258446b7479b3f3677923a46fe56f3206d313a81776e797bf4232e08bbaa1926
4
+ data.tar.gz: '029fd9139e2047cbbd7e248f324c517c09383fa332f02edd83dabaf75c328886'
5
5
  SHA512:
6
- metadata.gz: b3733fc664a8e74657d194268b3b653a28bb886078fe92a35cdbcfefc1665d47add6117b35598726db1159caca7b983db0358f6e0c28be27a2a6d503b06fea81
7
- data.tar.gz: 630f607d92e91c348b0a126f121242fcafd81bece774f642363b272c721c5d10d4a12ac8213290c7fbef1b8b4519f745c7ee6b5c364cc19a84fe26af256f8411
6
+ metadata.gz: 356595ae4d443af888c87a9402727dae8438db5ee666fe75887762a3140d905e9473d7e9c63967c6cd94c92c7cc643696d9a044658691d8164c0464ed9b50a32
7
+ data.tar.gz: 96d899fd65b2b01a7ffb64f38749b71baa849786fc7a5cd61fecbafbae245aa2b7aff3d5e9b852694ad70a1bb399517a1ba8611b12ab52b8f5c8a33998f850f1
@@ -7,6 +7,13 @@ VALUE cChart;
7
7
  VALUE cChartSeries;
8
8
  VALUE cChartAxis;
9
9
 
10
+ #define DEF_PROP_SETTER(type, field, value, ptr_field) VALUE type ## _set_ ## field ## _ (VALUE self, VALUE val) { \
11
+ struct type *ptr; \
12
+ Data_Get_Struct(self, struct type, ptr); \
13
+ type ## _set_ ## field (ptr->ptr_field, value); \
14
+ return val; \
15
+ }
16
+
10
17
 
11
18
  VALUE
12
19
  chart_alloc(VALUE klass) {
@@ -233,38 +240,24 @@ chart_legend_delete_series_(VALUE self, VALUE series) {
233
240
  return self;
234
241
  }
235
242
 
236
- /* call-seq: chart.style=(style) -> style
243
+ /* Document-method: XlsxWriter::Workbook::Chart#style=
244
+ *
245
+ * call-seq: chart.style=(style) -> style
237
246
  *
238
247
  * Sets the chart +style+ (integer from 1 to 48, default is 2).
239
248
  */
240
- VALUE
241
- chart_set_style_(VALUE self, VALUE style) {
242
- struct chart *ptr;
243
- Data_Get_Struct(self, struct chart, ptr);
244
-
245
- chart_set_style(ptr->chart, NUM2INT(rb_check_to_int(style)));
246
- return style;
247
- }
248
-
249
- /* :nodoc: */
250
- VALUE
251
- chart_set_rotation_(VALUE self, VALUE rotation) {
252
- struct chart *ptr;
253
- Data_Get_Struct(self, struct chart, ptr);
249
+ DEF_PROP_SETTER(chart, style, NUM2INT(rb_check_to_int(val)), chart)
254
250
 
255
- chart_set_rotation(ptr->chart, NUM2UINT(rb_check_to_int(rotation)));
256
- return rotation;
257
- }
258
251
 
259
- /* :nodoc: */
260
- VALUE
261
- chart_set_hole_size_(VALUE self, VALUE size) {
262
- struct chart *ptr;
263
- Data_Get_Struct(self, struct chart, ptr);
252
+ /* Document-method: XlsxWriter::Workbook::Chart#rotation=
253
+ *
254
+ */
255
+ DEF_PROP_SETTER(chart, rotation, NUM2UINT(rb_check_to_int(val)), chart)
264
256
 
265
- chart_set_hole_size(ptr->chart, NUM2UINT(rb_check_to_int(size)));
266
- return size;
267
- }
257
+ /* Document-method: XlsxWriter::Workbook::Chart#hole_size=
258
+ *
259
+ */
260
+ DEF_PROP_SETTER(chart, hole_size, NUM2UINT(rb_check_to_int(val)), chart)
268
261
 
269
262
 
270
263
  /* :nodoc: */
@@ -302,18 +295,79 @@ chart_set_axis_id_2_(VALUE self, VALUE val) {
302
295
  }
303
296
 
304
297
 
305
- /* call-seq: axis.name=(name) -> name
298
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#name=
299
+ *
300
+ * call-seq: axis.name=(name) -> name
306
301
  *
307
302
  * Sets the chart axis +name+.
308
303
  */
309
- VALUE
310
- chart_axis_set_name_(VALUE self, VALUE val) {
311
- struct chart_axis *ptr;
312
- Data_Get_Struct(self, struct chart_axis, ptr);
304
+ DEF_PROP_SETTER(chart_axis, name, StringValueCStr(val), axis)
313
305
 
314
- chart_axis_set_name(ptr->axis, StringValueCStr(val));
315
- return val;
316
- }
306
+ /* Document-method XlsxWriter::Workbook::Chart::Axis#interval_unit=
307
+ *
308
+ */
309
+ DEF_PROP_SETTER(chart_axis, interval_unit, NUM2UINT(rb_check_to_int(val)), axis)
310
+
311
+ /* Document-method XlsxWriter::Workbook::Chart::Axis#interval_tick=
312
+ *
313
+ */
314
+ DEF_PROP_SETTER(chart_axis, interval_tick, NUM2UINT(rb_check_to_int(val)), axis)
315
+
316
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#max=
317
+ *
318
+ * call-seq: axis.max=(value) -> value
319
+ *
320
+ * Sets the chart axis +max+ value.
321
+ */
322
+ DEF_PROP_SETTER(chart_axis, max, NUM2DBL(rb_check_to_float(val)), axis)
323
+
324
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#min=
325
+ *
326
+ * call-seq: axis.min=(value) -> value
327
+ *
328
+ * Sets the chart axis +min+ value.
329
+ */
330
+ DEF_PROP_SETTER(chart_axis, min, NUM2DBL(rb_check_to_float(val)), axis)
331
+
332
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#major_tick_mark=
333
+ *
334
+ */
335
+ DEF_PROP_SETTER(chart_axis, major_tick_mark, NUM2UINT(rb_check_to_int(val)), axis)
336
+
337
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#minor_tick_mark=
338
+ *
339
+ */
340
+ DEF_PROP_SETTER(chart_axis, minor_tick_mark, NUM2UINT(rb_check_to_int(val)), axis)
341
+
342
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#major_unit=
343
+ *
344
+ */
345
+ DEF_PROP_SETTER(chart_axis, major_unit, NUM2DBL(rb_check_to_float(val)), axis)
346
+
347
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#minor_unit=
348
+ *
349
+ */
350
+ DEF_PROP_SETTER(chart_axis, minor_unit, NUM2DBL(rb_check_to_float(val)), axis)
351
+
352
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#label_align=
353
+ *
354
+ */
355
+ DEF_PROP_SETTER(chart_axis, label_align, NUM2UINT(rb_check_to_int(val)), axis)
356
+
357
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#label_position=
358
+ *
359
+ */
360
+ DEF_PROP_SETTER(chart_axis, label_position, NUM2DBL(rb_check_to_float(val)), axis)
361
+
362
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#log_base=
363
+ *
364
+ */
365
+ DEF_PROP_SETTER(chart_axis, log_base, NUM2DBL(rb_check_to_float(val)), axis)
366
+
367
+ /* Document-method: XlsxWriter::Workbook::Chart::Axis#num_format=
368
+ *
369
+ */
370
+ DEF_PROP_SETTER(chart_axis, num_format, StringValueCStr(val), axis)
317
371
 
318
372
  /* call-seq:
319
373
  * axis.set_name_range(name, cell) -> self
@@ -392,6 +446,38 @@ chart_axis_set_fill_(VALUE self, VALUE opts) {
392
446
  return self;
393
447
  }
394
448
 
449
+ /* Document-method XlsxWriter::Workbook::Chart::Axis#position=
450
+ *
451
+ */
452
+ DEF_PROP_SETTER(chart_axis, position, NUM2UINT(rb_check_to_int(val)), axis)
453
+
454
+ /* call-seq: axis.reverse = true
455
+ *
456
+ * Interpret axis values/categories in reverse order.
457
+ */
458
+ VALUE
459
+ chart_axis_set_reverse_(VALUE self, VALUE p) {
460
+ struct chart_axis *ptr;
461
+ if (RTEST(p)) {
462
+ Data_Get_Struct(self, struct chart_axis, ptr);
463
+
464
+ chart_axis_set_reverse(ptr->axis);
465
+ }
466
+ return p;
467
+ }
468
+
469
+ VALUE
470
+ chart_axis_set_source_linked_(VALUE self, VALUE val) {
471
+ struct chart_axis *ptr;
472
+
473
+ Data_Get_Struct(self, struct chart_axis, ptr);
474
+
475
+ ptr->axis->source_linked = NUM2UINT(rb_check_to_int(val));
476
+
477
+ return val;
478
+ }
479
+
480
+
395
481
  /* call-seq:
396
482
  * series.set_categories(sheetname, range)
397
483
  * series.set_categories(sheetname, cell_from, cell_to)
@@ -433,18 +519,13 @@ chart_series_set_values_(int argc, VALUE *argv, VALUE self) {
433
519
  return self;
434
520
  }
435
521
 
436
- /* call-seq: series.name=(name) -> name
522
+ /* Document-method: XlsxWriter::Workbook::Chart::Series#name=
523
+ *
524
+ * call-seq: series.name=(name) -> name
437
525
  *
438
526
  * Set chart series name.
439
527
  */
440
- VALUE
441
- chart_series_set_name_(VALUE self, VALUE name) {
442
- struct chart_series *ptr;
443
- Data_Get_Struct(self, struct chart_series, ptr);
444
-
445
- chart_series_set_name(ptr->series, StringValueCStr(name));
446
- return name;
447
- }
528
+ DEF_PROP_SETTER(chart_series, name, StringValueCStr(val), series)
448
529
 
449
530
  /* call-seq:
450
531
  * series.set_name_range(name, cell) -> self
@@ -465,6 +546,17 @@ chart_series_set_name_range_(int argc, VALUE *argv, VALUE self) {
465
546
  return self;
466
547
  }
467
548
 
549
+ VALUE
550
+ chart_series_set_invert_if_negative_(VALUE self, VALUE p) {
551
+ struct chart_series *ptr;
552
+ if (RTEST(p)) {
553
+ Data_Get_Struct(self, struct chart_series, ptr);
554
+
555
+ chart_series_set_invert_if_negative(ptr->series);
556
+ }
557
+ return p;
558
+ }
559
+
468
560
 
469
561
  #define SET_PROP(prop, vres) { \
470
562
  val = rb_hash_aref(opts, ID2SYM(rb_intern(#prop))); \
@@ -552,11 +644,26 @@ void init_xlsxwriter_chart() {
552
644
  rb_define_method(cChartAxis, "initialize", chart_axis_init, 2);
553
645
 
554
646
  rb_define_method(cChartAxis, "name=", chart_axis_set_name_, 1);
647
+ rb_define_method(cChartAxis, "interval_unit=", chart_axis_set_interval_unit_, 1);
648
+ rb_define_method(cChartAxis, "interval_tick=", chart_axis_set_interval_tick_, 1);
649
+ rb_define_method(cChartAxis, "max=", chart_axis_set_max_, 1);
650
+ rb_define_method(cChartAxis, "min=", chart_axis_set_min_, 1);
651
+ rb_define_method(cChartAxis, "major_tick_mark=", chart_axis_set_major_tick_mark_, 1);
652
+ rb_define_method(cChartAxis, "minor_tick_mark=", chart_axis_set_minor_tick_mark_, 1);
653
+ rb_define_method(cChartAxis, "major_unit=", chart_axis_set_major_unit_, 1);
654
+ rb_define_method(cChartAxis, "minor_unit=", chart_axis_set_minor_unit_, 1);
655
+ rb_define_method(cChartAxis, "label_align=", chart_axis_set_label_align_, 1);
656
+ rb_define_method(cChartAxis, "label_position=", chart_axis_set_label_position_, 1);
657
+ rb_define_method(cChartAxis, "log_base=", chart_axis_set_log_base_, 1);
658
+ rb_define_method(cChartAxis, "num_format=", chart_axis_set_num_format_, 1);
555
659
  rb_define_method(cChartAxis, "set_name_range", chart_axis_set_name_range_, -1);
556
660
  rb_define_method(cChartAxis, "set_name_font", chart_axis_set_name_font_, 1);
557
661
  rb_define_method(cChartAxis, "set_num_font", chart_axis_set_num_font_, 1);
558
662
  rb_define_method(cChartAxis, "set_line", chart_axis_set_line_, 1);
559
663
  rb_define_method(cChartAxis, "set_fill", chart_axis_set_fill_, 1);
664
+ rb_define_method(cChartAxis, "position=", chart_axis_set_position_, 1);
665
+ rb_define_method(cChartAxis, "reverse=", chart_axis_set_reverse_, 1);
666
+ rb_define_method(cChartAxis, "source_linked=", chart_axis_set_source_linked_, 1);
560
667
 
561
668
  rb_define_alloc_func(cChartSeries, chart_series_alloc);
562
669
  rb_define_method(cChartSeries, "initialize", chart_series_init, -1);
@@ -565,6 +672,7 @@ void init_xlsxwriter_chart() {
565
672
  rb_define_method(cChartSeries, "set_values", chart_series_set_values_, -1);
566
673
  rb_define_method(cChartSeries, "name=", chart_series_set_name_, 1);
567
674
  rb_define_method(cChartSeries, "set_name_range", chart_series_set_name_range_, -1);
675
+ rb_define_method(cChartSeries, "invert_if_negative=", chart_series_set_invert_if_negative_, 1);
568
676
 
569
677
  #define MAP_CHART_CONST(name) rb_define_const(cChart, #name, INT2NUM(LXW_CHART_##name))
570
678
  MAP_CHART_CONST(NONE);
@@ -602,7 +710,25 @@ void init_xlsxwriter_chart() {
602
710
  MAP_CHART_CONST(AXIS_LABEL_ALIGN_CENTER);
603
711
  MAP_CHART_CONST(AXIS_LABEL_ALIGN_LEFT);
604
712
  MAP_CHART_CONST(AXIS_LABEL_ALIGN_RIGHT);
605
-
606
-
607
713
  #undef MAP_CHART_CONST
714
+
715
+ #define MAP_CHART_AXIS_CONST(name) rb_define_const(cChartAxis, #name, INT2NUM(LXW_CHART_AXIS_##name))
716
+ MAP_CHART_AXIS_CONST(LABEL_ALIGN_CENTER);
717
+ MAP_CHART_AXIS_CONST(LABEL_ALIGN_LEFT);
718
+ MAP_CHART_AXIS_CONST(LABEL_ALIGN_RIGHT);
719
+
720
+ MAP_CHART_AXIS_CONST(LABEL_POSITION_NEXT_TO);
721
+ MAP_CHART_AXIS_CONST(LABEL_POSITION_HIGH);
722
+ MAP_CHART_AXIS_CONST(LABEL_POSITION_LOW);
723
+ MAP_CHART_AXIS_CONST(LABEL_POSITION_NONE);
724
+
725
+ MAP_CHART_AXIS_CONST(POSITION_BETWEEN);
726
+ MAP_CHART_AXIS_CONST(POSITION_ON_TICK);
727
+
728
+ MAP_CHART_AXIS_CONST(TICK_MARK_DEFAULT);
729
+ MAP_CHART_AXIS_CONST(TICK_MARK_NONE);
730
+ MAP_CHART_AXIS_CONST(TICK_MARK_INSIDE);
731
+ MAP_CHART_AXIS_CONST(TICK_MARK_OUTSIDE);
732
+ MAP_CHART_AXIS_CONST(TICK_MARK_CROSSING);
733
+ #undef MAP_CHART_AXIS_CONST
608
734
  }
@@ -18,6 +18,6 @@
18
18
  #include "xlsxwriter/format.h"
19
19
  #include "xlsxwriter/utility.h"
20
20
 
21
- #define LXW_VERSION "0.8.6"
21
+ #define LXW_VERSION "0.8.7"
22
22
 
23
23
  #endif /* __LXW_XLSXWRITER_H__ */
@@ -68,13 +68,22 @@ typedef enum lxw_error {
68
68
  /** Error reading a tmpfile. */
69
69
  LXW_ERROR_READING_TMPFILE,
70
70
 
71
- /** Zlib error with a file operation while creating xlsx file. */
71
+ /** Zip generic error ZIP_ERRNO while creating the xlsx file. */
72
72
  LXW_ERROR_ZIP_FILE_OPERATION,
73
73
 
74
- /** Zlib error when adding sub file to xlsx file. */
74
+ /** Zip error ZIP_PARAMERROR while creating the xlsx file. */
75
+ LXW_ERROR_ZIP_PARAMETER_ERROR,
76
+
77
+ /** Zip error ZIP_BADZIPFILE (use_zip64 option may be required). */
78
+ LXW_ERROR_ZIP_BAD_ZIP_FILE,
79
+
80
+ /** Zip error ZIP_INTERNALERROR while creating the xlsx file. */
81
+ LXW_ERROR_ZIP_INTERNAL_ERROR,
82
+
83
+ /** File error or unknown zip error when adding sub file to xlsx file. */
75
84
  LXW_ERROR_ZIP_FILE_ADD,
76
85
 
77
- /** Zlib error when closing xlsx file. */
86
+ /** Unknown zip error when closing xlsx file. */
78
87
  LXW_ERROR_ZIP_CLOSE,
79
88
 
80
89
  /** NULL function parameter ignored. */
@@ -86,12 +95,18 @@ typedef enum lxw_error {
86
95
  /** Worksheet name exceeds Excel's limit of 31 characters. */
87
96
  LXW_ERROR_SHEETNAME_LENGTH_EXCEEDED,
88
97
 
89
- /** Worksheet name contains invalid Excel character: '[]:*?/\\' */
98
+ /** Worksheet name cannot contain invalid characters: '[ ] : * ? / \\' */
90
99
  LXW_ERROR_INVALID_SHEETNAME_CHARACTER,
91
100
 
101
+ /** Worksheet name cannot start or end with an apostrophe. */
102
+ LXW_ERROR_SHEETNAME_START_END_APOSTROPHE,
103
+
92
104
  /** Worksheet name is already in use. */
93
105
  LXW_ERROR_SHEETNAME_ALREADY_USED,
94
106
 
107
+ /** Worksheet name 'History' is reserved by Excel. */
108
+ LXW_ERROR_SHEETNAME_RESERVED,
109
+
95
110
  /** Parameter exceeds Excel's limit of 32 characters. */
96
111
  LXW_ERROR_32_STRING_LENGTH_EXCEEDED,
97
112
 
@@ -17,6 +17,7 @@
17
17
 
18
18
  #define LXW_APP_PACKAGE "application/vnd.openxmlformats-package."
19
19
  #define LXW_APP_DOCUMENT "application/vnd.openxmlformats-officedocument."
20
+ #define LXW_APP_MSEXCEL "application/vnd.ms-excel."
20
21
 
21
22
  /*
22
23
  * Struct to represent a content_types.
@@ -32,11 +32,17 @@
32
32
 
33
33
  #define LXW_ZIP_BUFFER_SIZE (16384)
34
34
 
35
- /* If zlib returns Z_ERRNO then errno is set and we can trap that. Otherwise
36
- * return a default libxlsxwriter error. */
35
+ /* If zip returns a ZIP_XXX error then errno is set and we can trap that in
36
+ * workbook.c. Otherwise return a default libxlsxwriter error. */
37
37
  #define RETURN_ON_ZIP_ERROR(err, default_err) \
38
- if (err == Z_ERRNO) \
38
+ if (err == ZIP_ERRNO) \
39
39
  return LXW_ERROR_ZIP_FILE_OPERATION; \
40
+ else if (err == ZIP_PARAMERROR) \
41
+ return LXW_ERROR_ZIP_PARAMETER_ERROR; \
42
+ else if (err == ZIP_BADZIPFILE) \
43
+ return LXW_ERROR_ZIP_BAD_ZIP_FILE; \
44
+ else if (err == ZIP_INTERNALERROR) \
45
+ return LXW_ERROR_ZIP_INTERNAL_ERROR; \
40
46
  else \
41
47
  return default_err;
42
48
 
@@ -54,6 +60,7 @@ typedef struct lxw_packager {
54
60
  char *filename;
55
61
  char *buffer;
56
62
  char *tmpdir;
63
+ uint8_t use_zip64;
57
64
 
58
65
  } lxw_packager;
59
66
 
@@ -64,7 +71,8 @@ extern "C" {
64
71
  #endif
65
72
  /* *INDENT-ON* */
66
73
 
67
- lxw_packager *lxw_packager_new(const char *filename, char *tmpdir);
74
+ lxw_packager *lxw_packager_new(const char *filename, char *tmpdir,
75
+ uint8_t use_zip64);
68
76
  void lxw_packager_free(lxw_packager *packager);
69
77
  lxw_error lxw_create_package(lxw_packager *self);
70
78
 
@@ -17,6 +17,7 @@
17
17
  #define __LXW_UTILITY_H__
18
18
 
19
19
  #include <stdint.h>
20
+ #include <strings.h>
20
21
  #include "common.h"
21
22
  #include "xmlwriter.h"
22
23
 
@@ -166,6 +167,13 @@ size_t lxw_utf8_strlen(const char *str);
166
167
 
167
168
  void lxw_str_tolower(char *str);
168
169
 
170
+ /* Define a portable version of strcasecmp(). */
171
+ #ifdef _MSC_VER
172
+ #define lxw_strcasecmp _stricmp
173
+ #else
174
+ #define lxw_strcasecmp strcasecmp
175
+ #endif
176
+
169
177
  FILE *lxw_tmpfile(char *tmpdir);
170
178
 
171
179
  /* Use a user defined function to format doubles in sprintf or else a simple
@@ -203,27 +203,40 @@ typedef struct lxw_doc_properties {
203
203
  *
204
204
  * The following properties are supported:
205
205
  *
206
- * - `constant_memory`: Reduces the amount of data stored in memory so that
207
- * large files can be written efficiently.
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.
208
209
  *
209
- * @note In this mode a row of data is written and then discarded when a
210
- * cell in a new row is added via one of the `worksheet_write_*()`
211
- * functions. Therefore, once this option is active, data should be written in
212
- * sequential row order. For this reason the `worksheet_merge_range()`
213
- * doesn't work in this mode. See also @ref ww_mem_constant.
214
- *
215
- * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior
216
- * 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
217
212
  * system's temp directory. If the default temporary directory isn't
218
213
  * accessible to your application, or doesn't contain enough space, you can
219
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
+ *
220
229
  */
221
230
  typedef struct lxw_workbook_options {
222
- /** Optimize the workbook to use constant memory for worksheets */
231
+ /** Optimize the workbook to use constant memory for worksheets. */
223
232
  uint8_t constant_memory;
224
233
 
225
234
  /** Directory to use for the temporary files created by libxlsxwriter. */
226
235
  char *tmpdir;
236
+
237
+ /** Allow ZIP64 extensions when creating the xlsx file zip container. */
238
+ uint8_t use_zip64;
239
+
227
240
  } lxw_workbook_options;
228
241
 
229
242
  /**
@@ -272,6 +285,9 @@ typedef struct lxw_workbook {
272
285
 
273
286
  lxw_hash_table *used_xf_formats;
274
287
 
288
+ char *vba_project;
289
+ char *vba_codename;
290
+
275
291
  } lxw_workbook;
276
292
 
277
293
 
@@ -313,30 +329,37 @@ lxw_workbook *workbook_new(const char *filename);
313
329
  * additional options to be set.
314
330
  *
315
331
  * @code
316
- * lxw_workbook_options options = {.constant_memory = 1,
317
- * .tmpdir = "C:\\Temp"};
332
+ * lxw_workbook_options options = {.constant_memory = LXW_TRUE,
333
+ * .tmpdir = "C:\\Temp",
334
+ * .use_zip64 = LXW_FALSE};
318
335
  *
319
336
  * lxw_workbook *workbook = workbook_new_opt("filename.xlsx", &options);
320
337
  * @endcode
321
338
  *
322
339
  * The options that can be set via #lxw_workbook_options are:
323
340
  *
324
- * - `constant_memory`: Reduces the amount of data stored in memory so that
325
- * large files can be written efficiently.
326
- *
327
- * @note In this mode a row of data is written and then discarded when a
328
- * cell in a new row is added via one of the `worksheet_write_*()`
329
- * functions. Therefore, once this option is active, data should be written in
330
- * sequential row order. For this reason the `worksheet_merge_range()`
331
- * 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.
332
344
  *
333
- * - `tmpdir`: libxlsxwriter stores workbook data in temporary files prior
334
- * 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
335
347
  * system's temp directory. If the default temporary directory isn't
336
348
  * accessible to your application, or doesn't contain enough space, you can
337
- * specify an alternative location using the `tmpdir` option.*
349
+ * specify an alternative location using the `tmpdir` option.
350
+ *
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
338
357
  *
339
- * See @ref working_with_memory for more details.
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.
340
363
  *
341
364
  */
342
365
  lxw_workbook *workbook_new_opt(const char *filename,
@@ -376,14 +399,17 @@ lxw_workbook *new_workbook_opt(const char *filename,
376
399
  *
377
400
  * @image html workbook02.png
378
401
  *
379
- * The worksheet name must be a valid Excel worksheet name, i.e. it must be
380
- * 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:
381
403
  *
382
- * / \ [ ] : * ?
383
- *
384
- * In addition, you cannot use the same, case insensitive, `sheetname` for more
385
- * than one worksheet, or chartsheet.
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).
386
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.
387
413
  */
388
414
  lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
389
415
  const char *sheetname);
@@ -412,13 +438,17 @@ lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
412
438
  *
413
439
  * @endcode
414
440
  *
415
- * The chartsheet name must be a valid Excel worksheet name, i.e. it must be
416
- * less than 32 character and it cannot contain any of the characters:
441
+ * The chartsheet name must be a valid Excel worksheet name, i.e.:
417
442
  *
418
- * / \ [ ] : * ?
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).
419
448
  *
420
- * In addition, you cannot use the same, case insensitive, `sheetname` for more
421
- * than one chartsheet, or worksheet.
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.
422
452
  *
423
453
  * At least one worksheet should be added to a new workbook when creating a
424
454
  * chartsheet in order to provide data for the chart. The @ref worksheet.h
@@ -797,7 +827,9 @@ lxw_chartsheet *workbook_get_chartsheet_by_name(lxw_workbook *workbook,
797
827
  *
798
828
  * - The name is less than or equal to 31 UTF-8 characters.
799
829
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
800
- * - The name isn't already in use.
830
+ * - The name doesn't start or end with an apostrophe.
831
+ * - The name isn't "History", which is reserved by Excel. (Case insensitive).
832
+ * - The name isn't already in use. (Case insensitive, see the note below).
801
833
  *
802
834
  * @code
803
835
  * lxw_error err = workbook_validate_sheet_name(workbook, "Foglio");
@@ -807,10 +839,73 @@ lxw_chartsheet *workbook_get_chartsheet_by_name(lxw_workbook *workbook,
807
839
  * `workbook_add_chartsheet()` but it can be explicitly called by the user
808
840
  * beforehand to ensure that the sheet name is valid.
809
841
  *
842
+ * @note This function does an ASCII lowercase string comparison to determine
843
+ * if the sheet name is already in use. It doesn't take UTF-8 characters into
844
+ * account. Thus it would flag "Café" and "café" as a duplicate (just like
845
+ * Excel) but it wouldn't catch "CAFÉ". If you need a full UTF-8 case
846
+ * insensitive check you should use a third party library to implement it.
847
+ *
810
848
  */
811
849
  lxw_error workbook_validate_sheet_name(lxw_workbook *workbook,
812
850
  const char *sheetname);
813
851
 
852
+ /**
853
+ * @brief Add a vbaProject binary to the Excel workbook.
854
+ *
855
+ * @param workbook Pointer to a lxw_workbook instance.
856
+ * @param filename The path/filename of the vbaProject.bin file.
857
+ *
858
+ * The `%workbook_add_vba_project()` function can be used to add macros or
859
+ * functions to a workbook using a binary VBA project file that has been
860
+ * extracted from an existing Excel xlsm file:
861
+ *
862
+ * @code
863
+ * workbook_add_vba_project(workbook, "vbaProject.bin");
864
+ * @endcode
865
+ *
866
+ * Only one `vbaProject.bin file` can be added per workbook. The name doesn't
867
+ * have to be `vbaProject.bin`. Any suitable path/name for an existing VBA bin
868
+ * file will do.
869
+ *
870
+ * Once you add a VBA project had been add to an libxlsxwriter workbook you
871
+ * should ensure that the file extension is `.xlsm` to prevent Excel from
872
+ * giving a warning when it opens the file:
873
+ *
874
+ * @code
875
+ * lxw_workbook *workbook = new_workbook("macro.xlsm");
876
+ * @endcode
877
+ *
878
+ * See also @ref working_with_macros
879
+ *
880
+ * @return A #lxw_error.
881
+ */
882
+ lxw_error workbook_add_vba_project(lxw_workbook *workbook,
883
+ const char *filename);
884
+
885
+ /**
886
+ * @brief Set the VBA name for the workbook.
887
+ *
888
+ * @param workbook Pointer to a lxw_workbook instance.
889
+ * @param name Name of the workbook used by VBA.
890
+ *
891
+ * The `workbook_set_vba_name()` function can be used to set the VBA name for
892
+ * the workbook. This is sometimes required when a vbaProject macro included
893
+ * via `workbook_add_vba_project()` refers to the workbook by a name other
894
+ * than `ThisWorkbook`.
895
+ *
896
+ * @code
897
+ * workbook_set_vba_name(workbook, "MyWorkbook");
898
+ * @endcode
899
+ *
900
+ * If an Excel VBA name for the workbook isn't specified then libxlsxwriter
901
+ * will use `ThisWorkbook`.
902
+ *
903
+ * See also @ref working_with_macros
904
+ *
905
+ * @return A #lxw_error.
906
+ */
907
+ lxw_error workbook_set_vba_name(lxw_workbook *workbook, const char *name);
908
+
814
909
  void lxw_workbook_free(lxw_workbook *workbook);
815
910
  void lxw_workbook_assemble_xml_file(lxw_workbook *workbook);
816
911
  void lxw_workbook_set_default_xf_indices(lxw_workbook *workbook);