xlsxwriter 0.2.1.pre.2 → 0.2.3.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -3
  3. data/ext/xlsxwriter/chart.c +84 -20
  4. data/ext/xlsxwriter/chart.h +1 -0
  5. data/ext/xlsxwriter/chartsheet.c +34 -13
  6. data/ext/xlsxwriter/common.h +5 -5
  7. data/ext/xlsxwriter/extconf.rb +8 -8
  8. data/ext/xlsxwriter/libxlsxwriter/License.txt +24 -2
  9. data/ext/xlsxwriter/libxlsxwriter/Makefile +46 -12
  10. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/app.h +1 -1
  11. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +196 -30
  12. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chartsheet.h +3 -3
  13. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
  14. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +24 -5
  15. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +5 -1
  16. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/core.h +1 -1
  17. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
  18. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +6 -17
  19. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +20 -6
  20. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  21. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/packager.h +3 -1
  22. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
  23. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
  24. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +11 -5
  25. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
  26. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/md5.h +43 -0
  27. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +42 -3
  28. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
  29. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +83 -18
  30. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +1519 -109
  31. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
  32. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +3 -2
  33. data/ext/xlsxwriter/libxlsxwriter/src/Makefile +25 -7
  34. data/ext/xlsxwriter/libxlsxwriter/src/app.c +1 -1
  35. data/ext/xlsxwriter/libxlsxwriter/src/chart.c +332 -48
  36. data/ext/xlsxwriter/libxlsxwriter/src/chartsheet.c +20 -19
  37. data/ext/xlsxwriter/libxlsxwriter/src/comment.c +443 -0
  38. data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +20 -1
  39. data/ext/xlsxwriter/libxlsxwriter/src/core.c +2 -2
  40. data/ext/xlsxwriter/libxlsxwriter/src/custom.c +1 -1
  41. data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +58 -20
  42. data/ext/xlsxwriter/libxlsxwriter/src/format.c +98 -25
  43. data/ext/xlsxwriter/libxlsxwriter/src/hash_table.c +1 -1
  44. data/ext/xlsxwriter/libxlsxwriter/src/packager.c +269 -12
  45. data/ext/xlsxwriter/libxlsxwriter/src/relationships.c +1 -1
  46. data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +2 -4
  47. data/ext/xlsxwriter/libxlsxwriter/src/styles.c +334 -48
  48. data/ext/xlsxwriter/libxlsxwriter/src/theme.c +1 -1
  49. data/ext/xlsxwriter/libxlsxwriter/src/utility.c +71 -8
  50. data/ext/xlsxwriter/libxlsxwriter/src/vml.c +1032 -0
  51. data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +343 -27
  52. data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +3759 -478
  53. data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +81 -2
  54. data/ext/xlsxwriter/libxlsxwriter/third_party/md5/Makefile +42 -0
  55. data/ext/xlsxwriter/libxlsxwriter/third_party/md5/md5.c +291 -0
  56. data/ext/xlsxwriter/libxlsxwriter/third_party/md5/md5.h +43 -0
  57. data/ext/xlsxwriter/rich_string.c +28 -9
  58. data/ext/xlsxwriter/shared_strings.c +75 -0
  59. data/ext/xlsxwriter/shared_strings.h +15 -0
  60. data/ext/xlsxwriter/workbook.c +87 -13
  61. data/ext/xlsxwriter/workbook.h +1 -0
  62. data/ext/xlsxwriter/workbook_properties.c +2 -2
  63. data/ext/xlsxwriter/worksheet.c +75 -23
  64. data/ext/xlsxwriter/worksheet.h +1 -0
  65. data/ext/xlsxwriter/xlsxwriter.c +2 -0
  66. data/lib/xlsxwriter/rich_string.rb +0 -2
  67. data/lib/xlsxwriter/version.rb +1 -1
  68. data/lib/xlsxwriter/worksheet.rb +2 -2
  69. data/test/{run-test.rb → run_test.rb} +3 -3
  70. data/test/support/chart_test.rb +3 -3
  71. data/test/support/with_xlsx_file.rb +4 -2
  72. data/test/support/xlsx_comparable.rb +40 -26
  73. data/test/test_array_formula.rb +42 -0
  74. data/test/test_autofilter.rb +72 -0
  75. data/test/{test-chart-area.rb → test_chart_area.rb} +2 -2
  76. data/test/{test-chart-axis.rb → test_chart_axis.rb} +16 -16
  77. data/test/test_chart_bar.rb +382 -0
  78. data/test/test_chart_blank.rb +27 -0
  79. data/test/{test-chart-column.rb → test_chart_column.rb} +2 -2
  80. data/test/{test-chart-doughnut.rb → test_chart_doughnut.rb} +2 -2
  81. data/test/{test-chart-legend.rb → test_chart_legend.rb} +2 -2
  82. data/test/{test-chart-pie.rb → test_chart_pie.rb} +2 -2
  83. data/test/{test-chart-scatter.rb → test_chart_scatter.rb} +3 -4
  84. data/test/{test-chart-size.rb → test_chart_size.rb} +2 -2
  85. data/test/{test-chart-title.rb → test_chart_title.rb} +3 -3
  86. data/test/{test-chartsheet.rb → test_chartsheet.rb} +2 -2
  87. data/test/{test-data.rb → test_data.rb} +1 -1
  88. data/test/{test-data-validation.rb → test_data_validation.rb} +23 -24
  89. data/test/{test-default-row.rb → test_default_row.rb} +1 -1
  90. data/test/{test-defined-name.rb → test_defined_name.rb} +12 -12
  91. data/test/{test-escapes.rb → test_escapes.rb} +5 -2
  92. data/test/{test-fit-to-pages.rb → test_fit_to_pages.rb} +6 -6
  93. data/test/{test-formatting.rb → test_formatting.rb} +10 -10
  94. data/test/{test-gridlines.rb → test_gridlines.rb} +3 -3
  95. data/test/{test-hyperlink.rb → test_hyperlink.rb} +22 -11
  96. data/test/{test-image.rb → test_image.rb} +6 -4
  97. data/test/{test-macro.rb → test_macro.rb} +1 -1
  98. data/test/{test-merge-range.rb → test_merge_range.rb} +1 -1
  99. data/test/{test-misc.rb → test_misc.rb} +2 -2
  100. data/test/{test-optimize.rb → test_optimize.rb} +2 -4
  101. data/test/{test-outline.rb → test_outline.rb} +14 -14
  102. data/test/{test-page-breaks.rb → test_page_breaks.rb} +2 -2
  103. data/test/{test-page-setup.rb → test_page_setup.rb} +2 -2
  104. data/test/{test-panes.rb → test_panes.rb} +1 -1
  105. data/test/{test-print-area.rb → test_print_area.rb} +3 -3
  106. data/test/{test-print-options.rb → test_print_options.rb} +7 -7
  107. data/test/{test-print-scale.rb → test_print_scale.rb} +2 -2
  108. data/test/{test-properties.rb → test_properties.rb} +2 -2
  109. data/test/{test-protect.rb → test_protect.rb} +3 -3
  110. data/test/{test-repeat.rb → test_repeat.rb} +3 -3
  111. data/test/{test-rich-string.rb → test_rich_string.rb} +5 -9
  112. data/test/{test-row-col-format.rb → test_row_col_format.rb} +1 -1
  113. data/test/{test-ruby-worksheet.rb → test_ruby_worksheet.rb} +2 -2
  114. data/test/{test-set-selection.rb → test_set_selection.rb} +2 -2
  115. data/test/{test-set-start-page.rb → test_set_start_page.rb} +2 -2
  116. data/test/{test-simple.rb → test_simple.rb} +10 -10
  117. data/test/{test-types.rb → test_types.rb} +1 -1
  118. data/test/{xlsx-func-testcase.rb → xlsx_func_testcase.rb} +1 -0
  119. metadata +127 -106
  120. data/test/test-array-formula.rb +0 -35
  121. data/test/test-autofilter.rb +0 -72
  122. data/test/test-chart-bar.rb +0 -74
  123. /data/test/{test-errors.rb → test_errors.rb} +0 -0
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -27,9 +27,11 @@ lxw_format_new(void)
27
27
  GOTO_LABEL_ON_MEM_ERROR(format, mem_error);
28
28
 
29
29
  format->xf_format_indices = NULL;
30
+ format->dxf_format_indices = NULL;
30
31
 
31
32
  format->xf_index = LXW_PROPERTY_UNSET;
32
33
  format->dxf_index = LXW_PROPERTY_UNSET;
34
+ format->xf_id = 0;
33
35
 
34
36
  format->font_name[0] = '\0';
35
37
  format->font_scheme[0] = '\0';
@@ -42,7 +44,7 @@ lxw_format_new(void)
42
44
  format->bold = LXW_FALSE;
43
45
  format->italic = LXW_FALSE;
44
46
  format->font_color = LXW_COLOR_UNSET;
45
- format->underline = LXW_FALSE;
47
+ format->underline = LXW_UNDERLINE_NONE;
46
48
  format->font_strikeout = LXW_FALSE;
47
49
  format->font_outline = LXW_FALSE;
48
50
  format->font_shadow = LXW_FALSE;
@@ -51,7 +53,7 @@ lxw_format_new(void)
51
53
  format->font_charset = LXW_FALSE;
52
54
  format->font_condense = LXW_FALSE;
53
55
  format->font_extend = LXW_FALSE;
54
- format->theme = LXW_FALSE;
56
+ format->theme = 0;
55
57
  format->hyperlink = LXW_FALSE;
56
58
 
57
59
  format->hidden = LXW_FALSE;
@@ -116,18 +118,6 @@ lxw_format_free(lxw_format *format)
116
118
  format = NULL;
117
119
  }
118
120
 
119
- /*
120
- * Check a user input color.
121
- */
122
- lxw_color_t
123
- lxw_format_check_color(lxw_color_t color)
124
- {
125
- if (color == LXW_COLOR_UNSET)
126
- return color;
127
- else
128
- return color & LXW_COLOR_MASK;
129
- }
130
-
131
121
  /*
132
122
  * Check a user input border.
133
123
  */
@@ -160,7 +150,9 @@ _get_format_key(lxw_format *self)
160
150
 
161
151
  /* Set pointer members to NULL since they aren't part of the comparison. */
162
152
  key->xf_format_indices = NULL;
153
+ key->dxf_format_indices = NULL;
163
154
  key->num_xf_formats = NULL;
155
+ key->num_dxf_formats = NULL;
164
156
  key->list_pointers.stqe_next = NULL;
165
157
 
166
158
  return key;
@@ -182,8 +174,9 @@ lxw_format_get_font_key(lxw_format *self)
182
174
  key->font_size = self->font_size;
183
175
  key->bold = self->bold;
184
176
  key->italic = self->italic;
185
- key->font_color = self->font_color;
186
177
  key->underline = self->underline;
178
+ key->theme = self->theme;
179
+ key->font_color = self->font_color;
187
180
  key->font_strikeout = self->font_strikeout;
188
181
  key->font_outline = self->font_outline;
189
182
  key->font_shadow = self->font_shadow;
@@ -296,6 +289,57 @@ lxw_format_get_xf_index(lxw_format *self)
296
289
  }
297
290
  }
298
291
 
292
+ /*
293
+ * Returns the DXF index number used by Excel to identify a format.
294
+ */
295
+ int32_t
296
+ lxw_format_get_dxf_index(lxw_format *self)
297
+ {
298
+ lxw_format *format_key;
299
+ lxw_format *existing_format;
300
+ lxw_hash_element *hash_element;
301
+ lxw_hash_table *formats_hash_table = self->dxf_format_indices;
302
+ int32_t index;
303
+
304
+ /* Note: The formats_hash_table/dxf_format_indices contains the unique and
305
+ * more importantly the *used* formats in the workbook.
306
+ */
307
+
308
+ /* Format already has an index number so return it. */
309
+ if (self->dxf_index != LXW_PROPERTY_UNSET) {
310
+ return self->dxf_index;
311
+ }
312
+
313
+ /* Otherwise, the format doesn't have an index number so we assign one.
314
+ * First generate a unique key to identify the format in the hash table.
315
+ */
316
+ format_key = _get_format_key(self);
317
+
318
+ /* Return the default format index if the key generation failed. */
319
+ if (!format_key)
320
+ return 0;
321
+
322
+ /* Look up the format in the hash table. */
323
+ hash_element =
324
+ lxw_hash_key_exists(formats_hash_table, format_key,
325
+ sizeof(lxw_format));
326
+
327
+ if (hash_element) {
328
+ /* Format matches existing format with an index. */
329
+ free(format_key);
330
+ existing_format = hash_element->value;
331
+ return existing_format->dxf_index;
332
+ }
333
+ else {
334
+ /* New format requiring an index. */
335
+ index = formats_hash_table->unique_count;
336
+ self->dxf_index = index;
337
+ lxw_insert_hash_element(formats_hash_table, format_key, self,
338
+ sizeof(lxw_format));
339
+ return index;
340
+ }
341
+ }
342
+
299
343
  /*
300
344
  * Set the font_name property.
301
345
  */
@@ -322,7 +366,7 @@ format_set_font_size(lxw_format *self, double size)
322
366
  void
323
367
  format_set_font_color(lxw_format *self, lxw_color_t color)
324
368
  {
325
- self->font_color = lxw_format_check_color(color);
369
+ self->font_color = color;
326
370
  }
327
371
 
328
372
  /*
@@ -508,7 +552,7 @@ format_set_pattern(lxw_format *self, uint8_t value)
508
552
  void
509
553
  format_set_bg_color(lxw_format *self, lxw_color_t color)
510
554
  {
511
- self->bg_color = lxw_format_check_color(color);
555
+ self->bg_color = color;
512
556
  }
513
557
 
514
558
  /*
@@ -517,7 +561,7 @@ format_set_bg_color(lxw_format *self, lxw_color_t color)
517
561
  void
518
562
  format_set_fg_color(lxw_format *self, lxw_color_t color)
519
563
  {
520
- self->fg_color = lxw_format_check_color(color);
564
+ self->fg_color = color;
521
565
  }
522
566
 
523
567
  /*
@@ -539,7 +583,6 @@ format_set_border(lxw_format *self, uint8_t style)
539
583
  void
540
584
  format_set_border_color(lxw_format *self, lxw_color_t color)
541
585
  {
542
- color = lxw_format_check_color(color);
543
586
  self->bottom_color = color;
544
587
  self->top_color = color;
545
588
  self->left_color = color;
@@ -561,7 +604,7 @@ format_set_bottom(lxw_format *self, uint8_t style)
561
604
  void
562
605
  format_set_bottom_color(lxw_format *self, lxw_color_t color)
563
606
  {
564
- self->bottom_color = lxw_format_check_color(color);
607
+ self->bottom_color = color;
565
608
  }
566
609
 
567
610
  /*
@@ -579,7 +622,7 @@ format_set_left(lxw_format *self, uint8_t style)
579
622
  void
580
623
  format_set_left_color(lxw_format *self, lxw_color_t color)
581
624
  {
582
- self->left_color = lxw_format_check_color(color);
625
+ self->left_color = color;
583
626
  }
584
627
 
585
628
  /*
@@ -597,7 +640,7 @@ format_set_right(lxw_format *self, uint8_t style)
597
640
  void
598
641
  format_set_right_color(lxw_format *self, lxw_color_t color)
599
642
  {
600
- self->right_color = lxw_format_check_color(color);
643
+ self->right_color = color;
601
644
  }
602
645
 
603
646
  /*
@@ -615,7 +658,7 @@ format_set_top(lxw_format *self, uint8_t style)
615
658
  void
616
659
  format_set_top_color(lxw_format *self, lxw_color_t color)
617
660
  {
618
- self->top_color = lxw_format_check_color(color);
661
+ self->top_color = color;
619
662
  }
620
663
 
621
664
  /*
@@ -634,7 +677,7 @@ format_set_diag_type(lxw_format *self, uint8_t type)
634
677
  void
635
678
  format_set_diag_color(lxw_format *self, lxw_color_t color)
636
679
  {
637
- self->diag_color = lxw_format_check_color(color);
680
+ self->diag_color = color;
638
681
  }
639
682
 
640
683
  /*
@@ -726,3 +769,33 @@ format_set_theme(lxw_format *self, uint8_t value)
726
769
  {
727
770
  self->theme = value;
728
771
  }
772
+
773
+ /*
774
+ * Set the color_indexed property.
775
+ */
776
+ void
777
+ format_set_color_indexed(lxw_format *self, uint8_t value)
778
+ {
779
+ self->color_indexed = value;
780
+ }
781
+
782
+ /*
783
+ * Set the font_only property.
784
+ */
785
+ void
786
+ format_set_font_only(lxw_format *self)
787
+ {
788
+ self->font_only = LXW_TRUE;
789
+ }
790
+
791
+ /*
792
+ * Set the theme property.
793
+ */
794
+ void
795
+ format_set_hyperlink(lxw_format *self)
796
+ {
797
+ self->hyperlink = LXW_TRUE;
798
+ self->xf_id = 1;
799
+ self->underline = LXW_UNDERLINE_SINGLE;
800
+ self->theme = 10;
801
+ }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -18,6 +18,10 @@ STATIC lxw_error _add_file_to_zip(lxw_packager *self, FILE * file,
18
18
  STATIC lxw_error _add_buffer_to_zip(lxw_packager *self, unsigned char *buffer,
19
19
  size_t buffer_size, const char *filename);
20
20
 
21
+ STATIC lxw_error _write_vml_drawing_rels_file(lxw_packager *self,
22
+ lxw_worksheet *worksheet,
23
+ uint32_t index);
24
+
21
25
  /*
22
26
  * Forward declarations.
23
27
  */
@@ -247,7 +251,7 @@ _write_image_files(lxw_packager *self)
247
251
  lxw_workbook *workbook = self->workbook;
248
252
  lxw_sheet *sheet;
249
253
  lxw_worksheet *worksheet;
250
- lxw_image_options *image;
254
+ lxw_object_properties *object_props;
251
255
  lxw_error err;
252
256
  FILE *image_stream;
253
257
 
@@ -260,21 +264,25 @@ _write_image_files(lxw_packager *self)
260
264
  else
261
265
  worksheet = sheet->u.worksheet;
262
266
 
263
- if (STAILQ_EMPTY(worksheet->image_data))
267
+ if (STAILQ_EMPTY(worksheet->image_props))
264
268
  continue;
265
269
 
266
- STAILQ_FOREACH(image, worksheet->image_data, list_pointers) {
270
+ STAILQ_FOREACH(object_props, worksheet->image_props, list_pointers) {
271
+
272
+ if (object_props->is_duplicate)
273
+ continue;
267
274
 
268
275
  lxw_snprintf(filename, LXW_FILENAME_LENGTH,
269
- "xl/media/image%d.%s", index++, image->extension);
276
+ "xl/media/image%d.%s", index++,
277
+ object_props->extension);
270
278
 
271
- if (!image->is_image_buffer) {
279
+ if (!object_props->is_image_buffer) {
272
280
  /* Check that the image file exists and can be opened. */
273
- image_stream = fopen(image->filename, "rb");
281
+ image_stream = lxw_fopen(object_props->filename, "rb");
274
282
  if (!image_stream) {
275
283
  LXW_WARN_FORMAT1("Error adding image to xlsx file: file "
276
284
  "doesn't exist or can't be opened: %s.",
277
- image->filename);
285
+ object_props->filename);
278
286
  return LXW_ERROR_CREATING_TMPFILE;
279
287
  }
280
288
 
@@ -283,8 +291,9 @@ _write_image_files(lxw_packager *self)
283
291
  }
284
292
  else {
285
293
  err = _add_buffer_to_zip(self,
286
- image->image_buffer,
287
- image->image_buffer_size, filename);
294
+ object_props->image_buffer,
295
+ object_props->image_buffer_size,
296
+ filename);
288
297
  }
289
298
 
290
299
  RETURN_ON_ERROR(err);
@@ -308,7 +317,7 @@ _add_vba_project(lxw_packager *self)
308
317
  return LXW_NO_ERROR;
309
318
 
310
319
  /* Check that the image file exists and can be opened. */
311
- image_stream = fopen(workbook->vba_project, "rb");
320
+ image_stream = lxw_fopen(workbook->vba_project, "rb");
312
321
  if (!image_stream) {
313
322
  LXW_WARN_FORMAT1("Error adding vbaProject.bin to xlsx file: "
314
323
  "file doesn't exist or can't be opened: %s.",
@@ -440,6 +449,164 @@ _get_drawing_count(lxw_packager *self)
440
449
  return drawing_count;
441
450
  }
442
451
 
452
+ /*
453
+ * Write the comment/header VML files.
454
+ */
455
+ STATIC lxw_error
456
+ _write_vml_files(lxw_packager *self)
457
+ {
458
+ lxw_workbook *workbook = self->workbook;
459
+ lxw_sheet *sheet;
460
+ lxw_worksheet *worksheet;
461
+ lxw_vml *vml;
462
+ char filename[LXW_FILENAME_LENGTH] = { 0 };
463
+ uint32_t index = 1;
464
+ lxw_error err;
465
+
466
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
467
+ if (sheet->is_chartsheet)
468
+ continue;
469
+ else
470
+ worksheet = sheet->u.worksheet;
471
+
472
+ if (!worksheet->has_vml && !worksheet->has_header_vml)
473
+ continue;
474
+
475
+ if (worksheet->has_vml) {
476
+
477
+ vml = lxw_vml_new();
478
+ if (!vml)
479
+ return LXW_ERROR_MEMORY_MALLOC_FAILED;
480
+
481
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
482
+ "xl/drawings/vmlDrawing%d.vml", index++);
483
+
484
+ vml->file = lxw_tmpfile(self->tmpdir);
485
+ if (!vml->file) {
486
+ lxw_vml_free(vml);
487
+ return LXW_ERROR_CREATING_TMPFILE;
488
+ }
489
+
490
+ vml->comment_objs = worksheet->comment_objs;
491
+ vml->vml_shape_id = worksheet->vml_shape_id;
492
+ vml->comment_display_default = worksheet->comment_display_default;
493
+
494
+ if (worksheet->vml_data_id_str) {
495
+ vml->vml_data_id_str = worksheet->vml_data_id_str;
496
+ }
497
+ else {
498
+ fclose(vml->file);
499
+ lxw_vml_free(vml);
500
+ return LXW_ERROR_MEMORY_MALLOC_FAILED;
501
+ }
502
+
503
+ lxw_vml_assemble_xml_file(vml);
504
+
505
+ err = _add_file_to_zip(self, vml->file, filename);
506
+
507
+ fclose(vml->file);
508
+ lxw_vml_free(vml);
509
+
510
+ RETURN_ON_ERROR(err);
511
+ }
512
+
513
+ if (worksheet->has_header_vml) {
514
+
515
+ err = _write_vml_drawing_rels_file(self, worksheet, index);
516
+ RETURN_ON_ERROR(err);
517
+
518
+ vml = lxw_vml_new();
519
+ if (!vml)
520
+ return LXW_ERROR_MEMORY_MALLOC_FAILED;
521
+
522
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
523
+ "xl/drawings/vmlDrawing%d.vml", index++);
524
+
525
+ vml->file = lxw_tmpfile(self->tmpdir);
526
+ if (!vml->file) {
527
+ lxw_vml_free(vml);
528
+ return LXW_ERROR_CREATING_TMPFILE;
529
+ }
530
+
531
+ vml->image_objs = worksheet->header_image_objs;
532
+ vml->vml_shape_id = worksheet->vml_header_id * 1024;
533
+
534
+ if (worksheet->vml_header_id_str) {
535
+ vml->vml_data_id_str = worksheet->vml_header_id_str;
536
+ }
537
+ else {
538
+ fclose(vml->file);
539
+ lxw_vml_free(vml);
540
+ return LXW_ERROR_MEMORY_MALLOC_FAILED;
541
+ }
542
+
543
+ lxw_vml_assemble_xml_file(vml);
544
+
545
+ err = _add_file_to_zip(self, vml->file, filename);
546
+
547
+ fclose(vml->file);
548
+ lxw_vml_free(vml);
549
+
550
+ RETURN_ON_ERROR(err);
551
+ }
552
+
553
+ }
554
+
555
+ return LXW_NO_ERROR;
556
+ }
557
+
558
+ /*
559
+ * Write the comment files.
560
+ */
561
+ STATIC lxw_error
562
+ _write_comment_files(lxw_packager *self)
563
+ {
564
+ lxw_workbook *workbook = self->workbook;
565
+ lxw_sheet *sheet;
566
+ lxw_worksheet *worksheet;
567
+ lxw_comment *comment;
568
+ char filename[LXW_FILENAME_LENGTH] = { 0 };
569
+ uint32_t index = 1;
570
+ lxw_error err;
571
+
572
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
573
+ if (sheet->is_chartsheet)
574
+ continue;
575
+ else
576
+ worksheet = sheet->u.worksheet;
577
+
578
+ if (!worksheet->has_comments)
579
+ continue;
580
+
581
+ comment = lxw_comment_new();
582
+ if (!comment)
583
+ return LXW_ERROR_MEMORY_MALLOC_FAILED;
584
+
585
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
586
+ "xl/comments%d.xml", index++);
587
+
588
+ comment->file = lxw_tmpfile(self->tmpdir);
589
+ if (!comment->file) {
590
+ lxw_comment_free(comment);
591
+ return LXW_ERROR_CREATING_TMPFILE;
592
+ }
593
+
594
+ comment->comment_objs = worksheet->comment_objs;
595
+ comment->comment_author = worksheet->comment_author;
596
+
597
+ lxw_comment_assemble_xml_file(comment);
598
+
599
+ err = _add_file_to_zip(self, comment->file, filename);
600
+
601
+ fclose(comment->file);
602
+ lxw_comment_free(comment);
603
+
604
+ RETURN_ON_ERROR(err);
605
+ }
606
+
607
+ return LXW_NO_ERROR;
608
+ }
609
+
443
610
  /*
444
611
  * Write the sharedStrings.xml file.
445
612
  */
@@ -690,11 +857,28 @@ _write_styles_file(lxw_packager *self)
690
857
  STAILQ_INSERT_TAIL(styles->xf_formats, style_format, list_pointers);
691
858
  }
692
859
 
860
+ /* Copy the unique and in-use dxf formats from the workbook to the styles
861
+ * dxf_format list. */
862
+ LXW_FOREACH_ORDERED(hash_element, self->workbook->used_dxf_formats) {
863
+ lxw_format *workbook_format = (lxw_format *) hash_element->value;
864
+ lxw_format *style_format = lxw_format_new();
865
+
866
+ if (!style_format) {
867
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
868
+ goto mem_error;
869
+ }
870
+
871
+ memcpy(style_format, workbook_format, sizeof(lxw_format));
872
+ STAILQ_INSERT_TAIL(styles->dxf_formats, style_format, list_pointers);
873
+ }
874
+
693
875
  styles->font_count = self->workbook->font_count;
694
876
  styles->border_count = self->workbook->border_count;
695
877
  styles->fill_count = self->workbook->fill_count;
696
878
  styles->num_format_count = self->workbook->num_format_count;
697
879
  styles->xf_count = self->workbook->used_xf_formats->unique_count;
880
+ styles->dxf_count = self->workbook->used_dxf_formats->unique_count;
881
+ styles->has_comments = self->workbook->has_comments;
698
882
 
699
883
  styles->file = lxw_tmpfile(self->tmpdir);
700
884
  if (!styles->file) {
@@ -787,6 +971,15 @@ _write_content_types_file(lxw_packager *self)
787
971
  lxw_ct_add_drawing_name(content_types, filename);
788
972
  }
789
973
 
974
+ if (workbook->has_vml)
975
+ lxw_ct_add_vml_name(content_types);
976
+
977
+ for (index = 1; index <= workbook->comment_count; index++) {
978
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
979
+ "/xl/comments%d.xml", index);
980
+ lxw_ct_add_comment_name(content_types, filename);
981
+ }
982
+
790
983
  if (workbook->sst->string_count)
791
984
  lxw_ct_add_shared_strings(content_types);
792
985
 
@@ -893,7 +1086,10 @@ _write_worksheet_rels_file(lxw_packager *self)
893
1086
  index++;
894
1087
 
895
1088
  if (STAILQ_EMPTY(worksheet->external_hyperlinks) &&
896
- STAILQ_EMPTY(worksheet->external_drawing_links))
1089
+ STAILQ_EMPTY(worksheet->external_drawing_links) &&
1090
+ !worksheet->external_vml_header_link &&
1091
+ !worksheet->external_vml_comment_link &&
1092
+ !worksheet->external_comment_link)
897
1093
  continue;
898
1094
 
899
1095
  rels = lxw_relationships_new();
@@ -914,6 +1110,21 @@ _write_worksheet_rels_file(lxw_packager *self)
914
1110
  rel->target_mode);
915
1111
  }
916
1112
 
1113
+ rel = worksheet->external_vml_comment_link;
1114
+ if (rel)
1115
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
1116
+ rel->target_mode);
1117
+
1118
+ rel = worksheet->external_vml_header_link;
1119
+ if (rel)
1120
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
1121
+ rel->target_mode);
1122
+
1123
+ rel = worksheet->external_comment_link;
1124
+ if (rel)
1125
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
1126
+ rel->target_mode);
1127
+
917
1128
  lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
918
1129
  "xl/worksheets/_rels/sheet%d.xml.rels", index);
919
1130
 
@@ -1047,6 +1258,46 @@ _write_drawing_rels_file(lxw_packager *self)
1047
1258
  return LXW_NO_ERROR;
1048
1259
  }
1049
1260
 
1261
+ /*
1262
+ * Write the vmlDrawing .rels files for worksheets that contain images in
1263
+ * headers or footers.
1264
+ */
1265
+ STATIC lxw_error
1266
+ _write_vml_drawing_rels_file(lxw_packager *self, lxw_worksheet *worksheet,
1267
+ uint32_t index)
1268
+ {
1269
+ lxw_relationships *rels;
1270
+ lxw_rel_tuple *rel;
1271
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
1272
+ lxw_error err = LXW_NO_ERROR;
1273
+
1274
+ rels = lxw_relationships_new();
1275
+
1276
+ rels->file = lxw_tmpfile(self->tmpdir);
1277
+ if (!rels->file) {
1278
+ lxw_free_relationships(rels);
1279
+ return LXW_ERROR_CREATING_TMPFILE;
1280
+ }
1281
+
1282
+ STAILQ_FOREACH(rel, worksheet->vml_drawing_links, list_pointers) {
1283
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
1284
+ rel->target_mode);
1285
+
1286
+ }
1287
+
1288
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
1289
+ "xl/drawings/_rels/vmlDrawing%d.vml.rels", index);
1290
+
1291
+ lxw_relationships_assemble_xml_file(rels);
1292
+
1293
+ err = _add_file_to_zip(self, rels->file, sheetname);
1294
+
1295
+ fclose(rels->file);
1296
+ lxw_free_relationships(rels);
1297
+
1298
+ return err;
1299
+ }
1300
+
1050
1301
  /*
1051
1302
  * Write the _rels/.rels xml file.
1052
1303
  */
@@ -1223,6 +1474,12 @@ lxw_create_package(lxw_packager *self)
1223
1474
  error = _write_drawing_files(self);
1224
1475
  RETURN_ON_ERROR(error);
1225
1476
 
1477
+ error = _write_vml_files(self);
1478
+ RETURN_ON_ERROR(error);
1479
+
1480
+ error = _write_comment_files(self);
1481
+ RETURN_ON_ERROR(error);
1482
+
1226
1483
  error = _write_shared_strings_file(self);
1227
1484
  RETURN_ON_ERROR(error);
1228
1485
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -145,9 +145,7 @@ _write_si(lxw_sst *self, char *string)
145
145
  lxw_xml_start_tag(self->file, "si", NULL);
146
146
 
147
147
  /* Look for and escape control chars in the string. */
148
- if (strpbrk(string, "\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C"
149
- "\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16"
150
- "\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F")) {
148
+ if (lxw_has_control_characters(string)) {
151
149
  string = lxw_escape_control_characters(string);
152
150
  escaped_string = LXW_TRUE;
153
151
  }