fast_excel 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +2 -0
  3. data/.gitignore +7 -0
  4. data/.travis.yml +32 -9
  5. data/CHANGELOG.md +36 -1
  6. data/Dockerfile.test +17 -0
  7. data/Gemfile +2 -1
  8. data/Gemfile.lock +33 -24
  9. data/LICENSE +21 -0
  10. data/Makefile +13 -0
  11. data/README.md +177 -40
  12. data/Rakefile +11 -1
  13. data/benchmarks/1k_rows.rb +17 -4
  14. data/benchmarks/20k_rows.rb +4 -0
  15. data/benchmarks/auto_width.rb +37 -0
  16. data/benchmarks/init.rb +14 -2
  17. data/benchmarks/memory.rb +8 -0
  18. data/benchmarks/profiler.rb +27 -0
  19. data/benchmarks/write_value.rb +62 -0
  20. data/examples/example.rb +3 -3
  21. data/examples/example_auto_width.rb +26 -0
  22. data/examples/example_filters.rb +36 -0
  23. data/examples/example_formula.rb +1 -3
  24. data/examples/example_hyperlink.rb +20 -0
  25. data/ext/fast_excel/extconf.rb +3 -0
  26. data/ext/fast_excel/text_width_ext.c +460 -0
  27. data/fast_excel.gemspec +3 -4
  28. data/letters.html +114 -0
  29. data/lib/fast_excel.rb +131 -25
  30. data/lib/fast_excel/binding.rb +33 -21
  31. data/lib/fast_excel/binding/chart.rb +20 -1
  32. data/lib/fast_excel/binding/format.rb +11 -4
  33. data/lib/fast_excel/binding/workbook.rb +10 -2
  34. data/lib/fast_excel/binding/worksheet.rb +44 -27
  35. data/libxlsxwriter/.gitignore +1 -0
  36. data/libxlsxwriter/.indent.pro +8 -0
  37. data/libxlsxwriter/.travis.yml +12 -0
  38. data/libxlsxwriter/CMakeLists.txt +338 -0
  39. data/libxlsxwriter/CONTRIBUTING.md +1 -1
  40. data/libxlsxwriter/Changes.txt +162 -0
  41. data/libxlsxwriter/LICENSE.txt +65 -4
  42. data/libxlsxwriter/Makefile +33 -11
  43. data/libxlsxwriter/Readme.md +3 -1
  44. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +2 -1
  45. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +2 -2
  46. data/libxlsxwriter/include/xlsxwriter.h +2 -2
  47. data/libxlsxwriter/include/xlsxwriter/app.h +2 -2
  48. data/libxlsxwriter/include/xlsxwriter/chart.h +164 -13
  49. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
  50. data/libxlsxwriter/include/xlsxwriter/common.h +35 -6
  51. data/libxlsxwriter/include/xlsxwriter/content_types.h +5 -2
  52. data/libxlsxwriter/include/xlsxwriter/core.h +2 -2
  53. data/libxlsxwriter/include/xlsxwriter/custom.h +2 -2
  54. data/libxlsxwriter/include/xlsxwriter/drawing.h +3 -2
  55. data/libxlsxwriter/include/xlsxwriter/format.h +8 -8
  56. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  57. data/libxlsxwriter/include/xlsxwriter/packager.h +18 -8
  58. data/libxlsxwriter/include/xlsxwriter/relationships.h +2 -2
  59. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +5 -3
  60. data/libxlsxwriter/include/xlsxwriter/styles.h +10 -5
  61. data/libxlsxwriter/include/xlsxwriter/theme.h +2 -2
  62. data/libxlsxwriter/include/xlsxwriter/utility.h +35 -5
  63. data/libxlsxwriter/include/xlsxwriter/workbook.h +234 -57
  64. data/libxlsxwriter/include/xlsxwriter/worksheet.h +780 -91
  65. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
  66. data/libxlsxwriter/libxlsxwriter.podspec +4 -2
  67. data/libxlsxwriter/src/Makefile +31 -6
  68. data/libxlsxwriter/src/app.c +2 -2
  69. data/libxlsxwriter/src/chart.c +116 -23
  70. data/libxlsxwriter/src/chartsheet.c +508 -0
  71. data/libxlsxwriter/src/content_types.c +12 -4
  72. data/libxlsxwriter/src/core.c +11 -11
  73. data/libxlsxwriter/src/custom.c +3 -3
  74. data/libxlsxwriter/src/drawing.c +114 -17
  75. data/libxlsxwriter/src/format.c +5 -5
  76. data/libxlsxwriter/src/hash_table.c +1 -1
  77. data/libxlsxwriter/src/packager.c +378 -61
  78. data/libxlsxwriter/src/relationships.c +2 -2
  79. data/libxlsxwriter/src/shared_strings.c +18 -4
  80. data/libxlsxwriter/src/styles.c +59 -12
  81. data/libxlsxwriter/src/theme.c +2 -2
  82. data/libxlsxwriter/src/utility.c +93 -6
  83. data/libxlsxwriter/src/workbook.c +379 -61
  84. data/libxlsxwriter/src/worksheet.c +1240 -174
  85. data/libxlsxwriter/src/xmlwriter.c +18 -9
  86. data/libxlsxwriter/third_party/minizip/Makefile +6 -1
  87. data/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
  88. data/libxlsxwriter/third_party/minizip/zip.c +2 -0
  89. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
  90. data/libxlsxwriter/version.txt +1 -1
  91. data/test/auto_width_test.rb +19 -0
  92. data/test/date_test.rb +34 -0
  93. data/test/format_test.rb +8 -0
  94. data/test/reopen_test.rb +22 -0
  95. data/test/test_helper.rb +8 -5
  96. data/test/text_width_test.rb +80 -0
  97. data/test/tmpfile_test.rb +1 -0
  98. data/test/validations_test.rb +47 -0
  99. data/test/worksheet_test.rb +44 -1
  100. metadata +33 -9
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -25,7 +25,7 @@
25
25
  * Create a new content_types object.
26
26
  */
27
27
  lxw_content_types *
28
- lxw_content_types_new()
28
+ lxw_content_types_new(void)
29
29
  {
30
30
  lxw_content_types *content_types = calloc(1, sizeof(lxw_content_types));
31
31
  GOTO_LABEL_ON_MEM_ERROR(content_types, mem_error);
@@ -50,8 +50,6 @@ lxw_content_types_new()
50
50
  LXW_APP_DOCUMENT "spreadsheetml.styles+xml");
51
51
  lxw_ct_add_override(content_types, "/xl/theme/theme1.xml",
52
52
  LXW_APP_DOCUMENT "theme+xml");
53
- lxw_ct_add_override(content_types, "/xl/workbook.xml",
54
- LXW_APP_DOCUMENT "spreadsheetml.sheet.main+xml");
55
53
 
56
54
  return content_types;
57
55
 
@@ -296,6 +294,16 @@ lxw_ct_add_worksheet_name(lxw_content_types *self, const char *name)
296
294
  LXW_APP_DOCUMENT "spreadsheetml.worksheet+xml");
297
295
  }
298
296
 
297
+ /*
298
+ * Add the name of a chartsheet to the ContentTypes overrides.
299
+ */
300
+ void
301
+ lxw_ct_add_chartsheet_name(lxw_content_types *self, const char *name)
302
+ {
303
+ lxw_ct_add_override(self, name,
304
+ LXW_APP_DOCUMENT "spreadsheetml.chartsheet+xml");
305
+ }
306
+
299
307
  /*
300
308
  * Add the name of a chart to the ContentTypes overrides.
301
309
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -25,7 +25,7 @@
25
25
  * Create a new core object.
26
26
  */
27
27
  lxw_core *
28
- lxw_core_new()
28
+ lxw_core_new(void)
29
29
  {
30
30
  lxw_core *core = calloc(1, sizeof(lxw_core));
31
31
  GOTO_LABEL_ON_MEM_ERROR(core, mem_error);
@@ -53,17 +53,17 @@ lxw_core_free(lxw_core *core)
53
53
  * Convert a time_t struct to a ISO 8601 style "2010-01-01T00:00:00Z" date.
54
54
  */
55
55
  static void
56
- _localtime_to_iso8601_date(time_t *timer, char *str, size_t size)
56
+ _datetime_to_iso8601_date(time_t *timer, char *str, size_t size)
57
57
  {
58
- struct tm *tmp_localtime;
58
+ struct tm *tmp_datetime;
59
59
  time_t current_time = time(NULL);
60
60
 
61
61
  if (*timer)
62
- tmp_localtime = localtime(timer);
62
+ tmp_datetime = gmtime(timer);
63
63
  else
64
- tmp_localtime = localtime(&current_time);
64
+ tmp_datetime = gmtime(&current_time);
65
65
 
66
- strftime(str, size - 1, "%Y-%m-%dT%H:%M:%SZ", tmp_localtime);
66
+ strftime(str, size - 1, "%Y-%m-%dT%H:%M:%SZ", tmp_datetime);
67
67
  }
68
68
 
69
69
  /*****************************************************************************
@@ -144,8 +144,8 @@ _write_dcterms_created(lxw_core *self)
144
144
  struct xml_attribute *attribute;
145
145
  char datetime[LXW_ATTR_32];
146
146
 
147
- _localtime_to_iso8601_date(&self->properties->created, datetime,
148
- LXW_ATTR_32);
147
+ _datetime_to_iso8601_date(&self->properties->created, datetime,
148
+ LXW_ATTR_32);
149
149
 
150
150
  LXW_INIT_ATTRIBUTES();
151
151
  LXW_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
@@ -166,8 +166,8 @@ _write_dcterms_modified(lxw_core *self)
166
166
  struct xml_attribute *attribute;
167
167
  char datetime[LXW_ATTR_32];
168
168
 
169
- _localtime_to_iso8601_date(&self->properties->created, datetime,
170
- LXW_ATTR_32);
169
+ _datetime_to_iso8601_date(&self->properties->created, datetime,
170
+ LXW_ATTR_32);
171
171
 
172
172
  LXW_INIT_ATTRIBUTES();
173
173
  LXW_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -25,7 +25,7 @@
25
25
  * Create a new custom object.
26
26
  */
27
27
  lxw_custom *
28
- lxw_custom_new()
28
+ lxw_custom_new(void)
29
29
  {
30
30
  lxw_custom *custom = calloc(1, sizeof(lxw_custom));
31
31
  GOTO_LABEL_ON_MEM_ERROR(custom, mem_error);
@@ -81,7 +81,7 @@ _chart_write_vt_r_8(lxw_custom *self, double value)
81
81
  {
82
82
  char data[LXW_ATTR_32];
83
83
 
84
- lxw_snprintf(data, LXW_ATTR_32, "%.16g", value);
84
+ lxw_sprintf_dbl(data, value);
85
85
 
86
86
  lxw_xml_data_element(self->file, "vt:r8", data, NULL);
87
87
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -27,7 +27,7 @@
27
27
  * Create a new drawing collection.
28
28
  */
29
29
  lxw_drawing *
30
- lxw_drawing_new()
30
+ lxw_drawing_new(void)
31
31
  {
32
32
  lxw_drawing *drawing = calloc(1, sizeof(lxw_drawing));
33
33
  GOTO_LABEL_ON_MEM_ERROR(drawing, mem_error);
@@ -225,7 +225,7 @@ _drawing_write_to(lxw_drawing *self, lxw_drawing_coords *coords)
225
225
  * Write the <xdr:cNvPr> element.
226
226
  */
227
227
  STATIC void
228
- _drawing_write_c_nv_pr(lxw_drawing *self, char *object_name, uint16_t index,
228
+ _drawing_write_c_nv_pr(lxw_drawing *self, char *object_name, uint32_t index,
229
229
  lxw_drawing_object *drawing_object)
230
230
  {
231
231
  struct xml_attribute_list attributes;
@@ -239,7 +239,7 @@ _drawing_write_c_nv_pr(lxw_drawing *self, char *object_name, uint16_t index,
239
239
  LXW_PUSH_ATTRIBUTES_INT("id", index + 1);
240
240
  LXW_PUSH_ATTRIBUTES_STR("name", name);
241
241
 
242
- if (drawing_object)
242
+ if (drawing_object && drawing_object->description)
243
243
  LXW_PUSH_ATTRIBUTES_STR("descr", drawing_object->description);
244
244
 
245
245
  lxw_xml_empty_tag(self->file, "xdr:cNvPr", &attributes);
@@ -282,7 +282,7 @@ _drawing_write_c_nv_pic_pr(lxw_drawing *self)
282
282
  * Write the <xdr:nvPicPr> element.
283
283
  */
284
284
  STATIC void
285
- _drawing_write_nv_pic_pr(lxw_drawing *self, uint16_t index,
285
+ _drawing_write_nv_pic_pr(lxw_drawing *self, uint32_t index,
286
286
  lxw_drawing_object *drawing_object)
287
287
  {
288
288
  lxw_xml_start_tag(self->file, "xdr:nvPicPr", NULL);
@@ -300,7 +300,7 @@ _drawing_write_nv_pic_pr(lxw_drawing *self, uint16_t index,
300
300
  * Write the <a:blip> element.
301
301
  */
302
302
  STATIC void
303
- _drawing_write_a_blip(lxw_drawing *self, uint16_t index)
303
+ _drawing_write_a_blip(lxw_drawing *self, uint32_t index)
304
304
  {
305
305
  struct xml_attribute_list attributes;
306
306
  struct xml_attribute *attribute;
@@ -345,7 +345,7 @@ _drawing_write_a_stretch(lxw_drawing *self)
345
345
  * Write the <xdr:blipFill> element.
346
346
  */
347
347
  STATIC void
348
- _drawing_write_blip_fill(lxw_drawing *self, uint16_t index)
348
+ _drawing_write_blip_fill(lxw_drawing *self, uint32_t index)
349
349
  {
350
350
  lxw_xml_start_tag(self->file, "xdr:blipFill", NULL);
351
351
 
@@ -463,7 +463,7 @@ _drawing_write_sp_pr(lxw_drawing *self, lxw_drawing_object *drawing_object)
463
463
  * Write the <xdr:pic> element.
464
464
  */
465
465
  STATIC void
466
- _drawing_write_pic(lxw_drawing *self, uint16_t index,
466
+ _drawing_write_pic(lxw_drawing *self, uint32_t index,
467
467
  lxw_drawing_object *drawing_object)
468
468
  {
469
469
  lxw_xml_start_tag(self->file, "xdr:pic", NULL);
@@ -489,20 +489,47 @@ _drawing_write_client_data(lxw_drawing *self)
489
489
  lxw_xml_empty_tag(self->file, "xdr:clientData", NULL);
490
490
  }
491
491
 
492
+ /*
493
+ * Write the <a:graphicFrameLocks> element.
494
+ */
495
+ STATIC void
496
+ _drawing_write_a_graphic_frame_locks(lxw_drawing *self)
497
+ {
498
+ struct xml_attribute_list attributes;
499
+ struct xml_attribute *attribute;
500
+
501
+ LXW_INIT_ATTRIBUTES();
502
+ LXW_PUSH_ATTRIBUTES_INT("noGrp", 1);
503
+
504
+ lxw_xml_empty_tag(self->file, "a:graphicFrameLocks", &attributes);
505
+
506
+ LXW_FREE_ATTRIBUTES();
507
+ }
508
+
492
509
  /*
493
510
  * Write the <xdr:cNvGraphicFramePr> element.
494
511
  */
495
512
  STATIC void
496
513
  _drawing_write_c_nv_graphic_frame_pr(lxw_drawing *self)
497
514
  {
498
- lxw_xml_empty_tag(self->file, "xdr:cNvGraphicFramePr", NULL);
515
+ if (self->embedded) {
516
+ lxw_xml_empty_tag(self->file, "xdr:cNvGraphicFramePr", NULL);
517
+ }
518
+ else {
519
+ lxw_xml_start_tag(self->file, "xdr:cNvGraphicFramePr", NULL);
520
+
521
+ /* Write the a:graphicFrameLocks element. */
522
+ _drawing_write_a_graphic_frame_locks(self);
523
+
524
+ lxw_xml_end_tag(self->file, "xdr:cNvGraphicFramePr");
525
+ }
499
526
  }
500
527
 
501
528
  /*
502
529
  * Write the <xdr:nvGraphicFramePr> element.
503
530
  */
504
531
  STATIC void
505
- _drawing_write_nv_graphic_frame_pr(lxw_drawing *self, uint16_t index)
532
+ _drawing_write_nv_graphic_frame_pr(lxw_drawing *self, uint32_t index)
506
533
  {
507
534
  lxw_xml_start_tag(self->file, "xdr:nvGraphicFramePr", NULL);
508
535
 
@@ -572,7 +599,7 @@ _drawing_write_xfrm(lxw_drawing *self)
572
599
  * Write the <c:chart> element.
573
600
  */
574
601
  STATIC void
575
- _drawing_write_chart(lxw_drawing *self, uint16_t index)
602
+ _drawing_write_chart(lxw_drawing *self, uint32_t index)
576
603
  {
577
604
  struct xml_attribute_list attributes;
578
605
  struct xml_attribute *attribute;
@@ -596,7 +623,7 @@ _drawing_write_chart(lxw_drawing *self, uint16_t index)
596
623
  * Write the <a:graphicData> element.
597
624
  */
598
625
  STATIC void
599
- _drawing_write_a_graphic_data(lxw_drawing *self, uint16_t index)
626
+ _drawing_write_a_graphic_data(lxw_drawing *self, uint32_t index)
600
627
  {
601
628
  struct xml_attribute_list attributes;
602
629
  struct xml_attribute *attribute;
@@ -619,7 +646,7 @@ _drawing_write_a_graphic_data(lxw_drawing *self, uint16_t index)
619
646
  * Write the <a:graphic> element.
620
647
  */
621
648
  STATIC void
622
- _drawing_write_a_graphic(lxw_drawing *self, uint16_t index)
649
+ _drawing_write_a_graphic(lxw_drawing *self, uint32_t index)
623
650
  {
624
651
 
625
652
  lxw_xml_start_tag(self->file, "a:graphic", NULL);
@@ -634,7 +661,7 @@ _drawing_write_a_graphic(lxw_drawing *self, uint16_t index)
634
661
  * Write the <xdr:graphicFrame> element.
635
662
  */
636
663
  STATIC void
637
- _drawing_write_graphic_frame(lxw_drawing *self, uint16_t index)
664
+ _drawing_write_graphic_frame(lxw_drawing *self, uint32_t index)
638
665
  {
639
666
  struct xml_attribute_list attributes;
640
667
  struct xml_attribute *attribute;
@@ -662,7 +689,7 @@ _drawing_write_graphic_frame(lxw_drawing *self, uint16_t index)
662
689
  * Write the <xdr:twoCellAnchor> element.
663
690
  */
664
691
  STATIC void
665
- _drawing_write_two_cell_anchor(lxw_drawing *self, uint16_t index,
692
+ _drawing_write_two_cell_anchor(lxw_drawing *self, uint32_t index,
666
693
  lxw_drawing_object *drawing_object)
667
694
  {
668
695
  struct xml_attribute_list attributes;
@@ -705,6 +732,73 @@ _drawing_write_two_cell_anchor(lxw_drawing *self, uint16_t index,
705
732
  LXW_FREE_ATTRIBUTES();
706
733
  }
707
734
 
735
+ /*
736
+ * Write the <xdr:ext> element.
737
+ */
738
+ STATIC void
739
+ _drawing_write_ext(lxw_drawing *self, uint32_t cx, uint32_t cy)
740
+ {
741
+ struct xml_attribute_list attributes;
742
+ struct xml_attribute *attribute;
743
+
744
+ LXW_INIT_ATTRIBUTES();
745
+ LXW_PUSH_ATTRIBUTES_INT("cx", cx);
746
+ LXW_PUSH_ATTRIBUTES_INT("cy", cy);
747
+
748
+ lxw_xml_empty_tag(self->file, "xdr:ext", &attributes);
749
+
750
+ LXW_FREE_ATTRIBUTES();
751
+ }
752
+
753
+ /*
754
+ * Write the <xdr:pos> element.
755
+ */
756
+ STATIC void
757
+ _drawing_write_pos(lxw_drawing *self, int32_t x, int32_t y)
758
+ {
759
+ struct xml_attribute_list attributes;
760
+ struct xml_attribute *attribute;
761
+
762
+ LXW_INIT_ATTRIBUTES();
763
+ LXW_PUSH_ATTRIBUTES_INT("x", x);
764
+ LXW_PUSH_ATTRIBUTES_INT("y", y);
765
+
766
+ lxw_xml_empty_tag(self->file, "xdr:pos", &attributes);
767
+
768
+ LXW_FREE_ATTRIBUTES();
769
+ }
770
+
771
+ /*
772
+ * Write the <xdr:absoluteAnchor> element.
773
+ */
774
+ STATIC void
775
+ _drawing_write_absolute_anchor(lxw_drawing *self)
776
+ {
777
+ lxw_xml_start_tag(self->file, "xdr:absoluteAnchor", NULL);
778
+
779
+ if (self->orientation == LXW_LANDSCAPE) {
780
+ /* Write the xdr:pos element. */
781
+ _drawing_write_pos(self, 0, 0);
782
+
783
+ /* Write the xdr:ext element. */
784
+ _drawing_write_ext(self, 9308969, 6078325);
785
+ }
786
+ else {
787
+ /* Write the xdr:pos element. */
788
+ _drawing_write_pos(self, 0, -47625);
789
+
790
+ /* Write the xdr:ext element. */
791
+ _drawing_write_ext(self, 6162675, 6124575);
792
+ }
793
+
794
+ _drawing_write_graphic_frame(self, 1);
795
+
796
+ /* Write the xdr:clientData element. */
797
+ _drawing_write_client_data(self);
798
+
799
+ lxw_xml_end_tag(self->file, "xdr:absoluteAnchor");
800
+ }
801
+
708
802
  /*****************************************************************************
709
803
  *
710
804
  * XML file assembly functions.
@@ -717,7 +811,7 @@ _drawing_write_two_cell_anchor(lxw_drawing *self, uint16_t index,
717
811
  void
718
812
  lxw_drawing_assemble_xml_file(lxw_drawing *self)
719
813
  {
720
- uint16_t index;
814
+ uint32_t index;
721
815
  lxw_drawing_object *drawing_object;
722
816
 
723
817
  /* Write the XML declaration. */
@@ -733,7 +827,10 @@ lxw_drawing_assemble_xml_file(lxw_drawing *self)
733
827
  _drawing_write_two_cell_anchor(self, index, drawing_object);
734
828
  index++;
735
829
  }
736
-
830
+ }
831
+ else {
832
+ /* Write the xdr:absoluteAnchor element. Mainly for chartsheets. */
833
+ _drawing_write_absolute_anchor(self);
737
834
  }
738
835
 
739
836
  lxw_xml_end_tag(self->file, "xdr:wsDr");
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -21,7 +21,7 @@
21
21
  * Create a new format object.
22
22
  */
23
23
  lxw_format *
24
- lxw_format_new()
24
+ lxw_format_new(void)
25
25
  {
26
26
  lxw_format *format = calloc(1, sizeof(lxw_format));
27
27
  GOTO_LABEL_ON_MEM_ERROR(format, mem_error);
@@ -38,7 +38,7 @@ lxw_format_new()
38
38
  format->font_index = 0;
39
39
  format->has_font = LXW_FALSE;
40
40
  format->has_dxf_font = LXW_FALSE;
41
- format->font_size = 11;
41
+ format->font_size = 11.0;
42
42
  format->bold = LXW_FALSE;
43
43
  format->italic = LXW_FALSE;
44
44
  format->font_color = LXW_COLOR_UNSET;
@@ -309,7 +309,7 @@ format_set_font_name(lxw_format *self, const char *font_name)
309
309
  * Set the font_size property.
310
310
  */
311
311
  void
312
- format_set_font_size(lxw_format *self, uint16_t size)
312
+ format_set_font_size(lxw_format *self, double size)
313
313
  {
314
314
 
315
315
  if (size >= LXW_MIN_FONT_SIZE && size <= LXW_MAX_FONT_SIZE)
@@ -455,7 +455,7 @@ format_set_rotation(lxw_format *self, int16_t angle)
455
455
  if (angle == 270) {
456
456
  self->rotation = 255;
457
457
  }
458
- else if (angle >= -90 || angle <= 90) {
458
+ else if (angle >= -90 && angle <= 90) {
459
459
  if (angle < 0)
460
460
  angle = -angle + 90;
461
461
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, 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-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -15,6 +15,9 @@
15
15
  STATIC lxw_error _add_file_to_zip(lxw_packager *self, FILE * file,
16
16
  const char *filename);
17
17
 
18
+ STATIC lxw_error _add_buffer_to_zip(lxw_packager *self, unsigned char *buffer,
19
+ size_t buffer_size, const char *filename);
20
+
18
21
  /*
19
22
  * Forward declarations.
20
23
  */
@@ -37,7 +40,12 @@ STATIC lxw_error _add_file_to_zip(lxw_packager *self, FILE * file,
37
40
  #undef SLIST_ENTRY
38
41
 
39
42
  #include <windows.h>
43
+
44
+ #ifdef USE_SYSTEM_MINIZIP
45
+ #include "minizip/iowin32.h"
46
+ #else
40
47
  #include "../third_party/minizip/iowin32.h"
48
+ #endif
41
49
 
42
50
  zipFile
43
51
  _open_zipfile_win32(const char *filename)
@@ -57,7 +65,7 @@ _open_zipfile_win32(const char *filename)
57
65
  }
58
66
 
59
67
  /* Use the native Win32 file handling functions with minizip. */
60
- fill_win32_filefunc64(&filefunc);
68
+ fill_win32_filefunc64W(&filefunc);
61
69
 
62
70
  return zipOpen2_64(wide_filename, 0, NULL, &filefunc);
63
71
  }
@@ -68,7 +76,7 @@ _open_zipfile_win32(const char *filename)
68
76
  * Create a new packager object.
69
77
  */
70
78
  lxw_packager *
71
- lxw_packager_new(const char *filename, char *tmpdir)
79
+ lxw_packager_new(const char *filename, char *tmpdir, uint8_t use_zip64)
72
80
  {
73
81
  lxw_packager *packager = calloc(1, sizeof(lxw_packager));
74
82
  GOTO_LABEL_ON_MEM_ERROR(packager, mem_error);
@@ -81,6 +89,7 @@ lxw_packager_new(const char *filename, char *tmpdir)
81
89
  GOTO_LABEL_ON_MEM_ERROR(packager->filename, mem_error);
82
90
 
83
91
  packager->buffer_size = LXW_ZIP_BUFFER_SIZE;
92
+ packager->use_zip64 = use_zip64;
84
93
 
85
94
  /* Initialize the zip_fileinfo struct to Jan 1 1980 like Excel. */
86
95
  packager->zipfile_info.tmz_date.tm_sec = 0;
@@ -159,12 +168,18 @@ STATIC lxw_error
159
168
  _write_worksheet_files(lxw_packager *self)
160
169
  {
161
170
  lxw_workbook *workbook = self->workbook;
171
+ lxw_sheet *sheet;
162
172
  lxw_worksheet *worksheet;
163
173
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
164
- uint16_t index = 1;
174
+ uint32_t index = 1;
165
175
  lxw_error err;
166
176
 
167
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
177
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
178
+ if (sheet->is_chartsheet)
179
+ continue;
180
+ else
181
+ worksheet = sheet->u.worksheet;
182
+
168
183
  lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
169
184
  "xl/worksheets/sheet%d.xml", index++);
170
185
 
@@ -186,6 +201,43 @@ _write_worksheet_files(lxw_packager *self)
186
201
  return LXW_NO_ERROR;
187
202
  }
188
203
 
204
+ /*
205
+ * Write the chartsheet files.
206
+ */
207
+ STATIC lxw_error
208
+ _write_chartsheet_files(lxw_packager *self)
209
+ {
210
+ lxw_workbook *workbook = self->workbook;
211
+ lxw_sheet *sheet;
212
+ lxw_chartsheet *chartsheet;
213
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
214
+ uint32_t index = 1;
215
+ lxw_error err;
216
+
217
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
218
+ if (sheet->is_chartsheet)
219
+ chartsheet = sheet->u.chartsheet;
220
+ else
221
+ continue;
222
+
223
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
224
+ "xl/chartsheets/sheet%d.xml", index++);
225
+
226
+ chartsheet->file = lxw_tmpfile(self->tmpdir);
227
+ if (!chartsheet->file)
228
+ return LXW_ERROR_CREATING_TMPFILE;
229
+
230
+ lxw_chartsheet_assemble_xml_file(chartsheet);
231
+
232
+ err = _add_file_to_zip(self, chartsheet->file, sheetname);
233
+ RETURN_ON_ERROR(err);
234
+
235
+ fclose(chartsheet->file);
236
+ }
237
+
238
+ return LXW_NO_ERROR;
239
+ }
240
+
189
241
  /*
190
242
  * Write the /xl/media/image?.xml files.
191
243
  */
@@ -193,14 +245,20 @@ STATIC lxw_error
193
245
  _write_image_files(lxw_packager *self)
194
246
  {
195
247
  lxw_workbook *workbook = self->workbook;
248
+ lxw_sheet *sheet;
196
249
  lxw_worksheet *worksheet;
197
250
  lxw_image_options *image;
198
251
  lxw_error err;
252
+ FILE *image_stream;
199
253
 
200
254
  char filename[LXW_FILENAME_LENGTH] = { 0 };
201
- uint16_t index = 1;
255
+ uint32_t index = 1;
202
256
 
203
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
257
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
258
+ if (sheet->is_chartsheet)
259
+ continue;
260
+ else
261
+ worksheet = sheet->u.worksheet;
204
262
 
205
263
  if (STAILQ_EMPTY(worksheet->image_data))
206
264
  continue;
@@ -210,18 +268,61 @@ _write_image_files(lxw_packager *self)
210
268
  lxw_snprintf(filename, LXW_FILENAME_LENGTH,
211
269
  "xl/media/image%d.%s", index++, image->extension);
212
270
 
213
- rewind(image->stream);
271
+ if (!image->is_image_buffer) {
272
+ /* Check that the image file exists and can be opened. */
273
+ image_stream = fopen(image->filename, "rb");
274
+ if (!image_stream) {
275
+ LXW_WARN_FORMAT1("Error adding image to xlsx file: file "
276
+ "doesn't exist or can't be opened: %s.",
277
+ image->filename);
278
+ return LXW_ERROR_CREATING_TMPFILE;
279
+ }
280
+
281
+ err = _add_file_to_zip(self, image_stream, filename);
282
+ fclose(image_stream);
283
+ }
284
+ else {
285
+ err = _add_buffer_to_zip(self,
286
+ image->image_buffer,
287
+ image->image_buffer_size, filename);
288
+ }
214
289
 
215
- err = _add_file_to_zip(self, image->stream, filename);
216
290
  RETURN_ON_ERROR(err);
217
-
218
- fclose(image->stream);
219
291
  }
220
292
  }
221
293
 
222
294
  return LXW_NO_ERROR;
223
295
  }
224
296
 
297
+ /*
298
+ * Write the xl/vbaProject.bin file.
299
+ */
300
+ STATIC lxw_error
301
+ _add_vba_project(lxw_packager *self)
302
+ {
303
+ lxw_workbook *workbook = self->workbook;
304
+ lxw_error err;
305
+ FILE *image_stream;
306
+
307
+ if (!workbook->vba_project)
308
+ return LXW_NO_ERROR;
309
+
310
+ /* Check that the image file exists and can be opened. */
311
+ image_stream = fopen(workbook->vba_project, "rb");
312
+ if (!image_stream) {
313
+ LXW_WARN_FORMAT1("Error adding vbaProject.bin to xlsx file: "
314
+ "file doesn't exist or can't be opened: %s.",
315
+ workbook->vba_project);
316
+ return LXW_ERROR_CREATING_TMPFILE;
317
+ }
318
+
319
+ err = _add_file_to_zip(self, image_stream, "xl/vbaProject.bin");
320
+ fclose(image_stream);
321
+ RETURN_ON_ERROR(err);
322
+
323
+ return LXW_NO_ERROR;
324
+ }
325
+
225
326
  /*
226
327
  * Write the chart files.
227
328
  */
@@ -231,7 +332,7 @@ _write_chart_files(lxw_packager *self)
231
332
  lxw_workbook *workbook = self->workbook;
232
333
  lxw_chart *chart;
233
334
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
234
- uint16_t index = 1;
335
+ uint32_t index = 1;
235
336
  lxw_error err;
236
337
 
237
338
  STAILQ_FOREACH(chart, workbook->ordered_charts, ordered_list_pointers) {
@@ -248,14 +349,29 @@ _write_chart_files(lxw_packager *self)
248
349
  err = _add_file_to_zip(self, chart->file, sheetname);
249
350
  RETURN_ON_ERROR(err);
250
351
 
251
- self->chart_count++;
252
-
253
352
  fclose(chart->file);
254
353
  }
255
354
 
256
355
  return LXW_NO_ERROR;
257
356
  }
258
357
 
358
+ /*
359
+ * Count the chart files.
360
+ */
361
+ uint32_t
362
+ _get_chart_count(lxw_packager *self)
363
+ {
364
+ lxw_workbook *workbook = self->workbook;
365
+ lxw_chart *chart;
366
+ uint32_t chart_count = 0;
367
+
368
+ STAILQ_FOREACH(chart, workbook->ordered_charts, ordered_list_pointers) {
369
+ chart_count++;
370
+ }
371
+
372
+ return chart_count;
373
+ }
374
+
259
375
  /*
260
376
  * Write the drawing files.
261
377
  */
@@ -263,13 +379,19 @@ STATIC lxw_error
263
379
  _write_drawing_files(lxw_packager *self)
264
380
  {
265
381
  lxw_workbook *workbook = self->workbook;
382
+ lxw_sheet *sheet;
266
383
  lxw_worksheet *worksheet;
267
384
  lxw_drawing *drawing;
268
385
  char filename[LXW_FILENAME_LENGTH] = { 0 };
269
- uint16_t index = 1;
386
+ uint32_t index = 1;
270
387
  lxw_error err;
271
388
 
272
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
389
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
390
+ if (sheet->is_chartsheet)
391
+ worksheet = sheet->u.chartsheet->worksheet;
392
+ else
393
+ worksheet = sheet->u.worksheet;
394
+
273
395
  drawing = worksheet->drawing;
274
396
 
275
397
  if (drawing) {
@@ -285,14 +407,39 @@ _write_drawing_files(lxw_packager *self)
285
407
  RETURN_ON_ERROR(err);
286
408
 
287
409
  fclose(drawing->file);
288
-
289
- self->drawing_count++;
290
410
  }
291
411
  }
292
412
 
293
413
  return LXW_NO_ERROR;
294
414
  }
295
415
 
416
+ /*
417
+ * Count the drawing files.
418
+ */
419
+ uint32_t
420
+ _get_drawing_count(lxw_packager *self)
421
+ {
422
+ lxw_workbook *workbook = self->workbook;
423
+ lxw_sheet *sheet;
424
+ lxw_worksheet *worksheet;
425
+ lxw_drawing *drawing;
426
+ uint32_t drawing_count = 0;
427
+
428
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
429
+ if (sheet->is_chartsheet)
430
+ worksheet = sheet->u.chartsheet->worksheet;
431
+ else
432
+ worksheet = sheet->u.worksheet;
433
+
434
+ drawing = worksheet->drawing;
435
+
436
+ if (drawing)
437
+ drawing_count++;
438
+ }
439
+
440
+ return drawing_count;
441
+ }
442
+
296
443
  /*
297
444
  * Write the sharedStrings.xml file.
298
445
  */
@@ -327,10 +474,12 @@ STATIC lxw_error
327
474
  _write_app_file(lxw_packager *self)
328
475
  {
329
476
  lxw_workbook *workbook = self->workbook;
477
+ lxw_sheet *sheet;
330
478
  lxw_worksheet *worksheet;
479
+ lxw_chartsheet *chartsheet;
331
480
  lxw_defined_name *defined_name;
332
481
  lxw_app *app;
333
- uint16_t named_range_count = 0;
482
+ uint32_t named_range_count = 0;
334
483
  char *autofilter;
335
484
  char *has_range;
336
485
  char number[LXW_ATTR_32] = { 0 };
@@ -348,12 +497,30 @@ _write_app_file(lxw_packager *self)
348
497
  goto mem_error;
349
498
  }
350
499
 
351
- lxw_snprintf(number, LXW_ATTR_32, "%d", self->workbook->num_sheets);
500
+ if (self->workbook->num_worksheets) {
501
+ lxw_snprintf(number, LXW_ATTR_32, "%d",
502
+ self->workbook->num_worksheets);
503
+ lxw_app_add_heading_pair(app, "Worksheets", number);
504
+ }
352
505
 
353
- lxw_app_add_heading_pair(app, "Worksheets", number);
506
+ if (self->workbook->num_chartsheets) {
507
+ lxw_snprintf(number, LXW_ATTR_32, "%d",
508
+ self->workbook->num_chartsheets);
509
+ lxw_app_add_heading_pair(app, "Charts", number);
510
+ }
354
511
 
355
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
356
- lxw_app_add_part_name(app, worksheet->name);
512
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
513
+ if (!sheet->is_chartsheet) {
514
+ worksheet = sheet->u.worksheet;
515
+ lxw_app_add_part_name(app, worksheet->name);
516
+ }
517
+ }
518
+
519
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
520
+ if (sheet->is_chartsheet) {
521
+ chartsheet = sheet->u.chartsheet;
522
+ lxw_app_add_part_name(app, chartsheet->name);
523
+ }
357
524
  }
358
525
 
359
526
  /* Add the Named Ranges parts. */
@@ -555,9 +722,13 @@ _write_content_types_file(lxw_packager *self)
555
722
  {
556
723
  lxw_content_types *content_types = lxw_content_types_new();
557
724
  lxw_workbook *workbook = self->workbook;
558
- lxw_worksheet *worksheet;
725
+ lxw_sheet *sheet;
559
726
  char filename[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
560
- uint16_t index = 1;
727
+ uint32_t index = 1;
728
+ uint32_t worksheet_index = 1;
729
+ uint32_t chartsheet_index = 1;
730
+ uint32_t drawing_count = _get_drawing_count(self);
731
+ uint32_t chart_count = _get_chart_count(self);
561
732
  lxw_error err = LXW_NO_ERROR;
562
733
 
563
734
  if (!content_types) {
@@ -580,19 +751,37 @@ _write_content_types_file(lxw_packager *self)
580
751
  if (workbook->has_bmp)
581
752
  lxw_ct_add_default(content_types, "bmp", "image/bmp");
582
753
 
583
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
584
- lxw_snprintf(filename, LXW_FILENAME_LENGTH,
585
- "/xl/worksheets/sheet%d.xml", index++);
586
- lxw_ct_add_worksheet_name(content_types, filename);
754
+ if (workbook->vba_project)
755
+ lxw_ct_add_default(content_types, "bin",
756
+ "application/vnd.ms-office.vbaProject");
757
+
758
+ if (workbook->vba_project)
759
+ lxw_ct_add_override(content_types, "/xl/workbook.xml",
760
+ LXW_APP_MSEXCEL "sheet.macroEnabled.main+xml");
761
+ else
762
+ lxw_ct_add_override(content_types, "/xl/workbook.xml",
763
+ LXW_APP_DOCUMENT "spreadsheetml.sheet.main+xml");
764
+
765
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
766
+ if (sheet->is_chartsheet) {
767
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
768
+ "/xl/chartsheets/sheet%d.xml", chartsheet_index++);
769
+ lxw_ct_add_chartsheet_name(content_types, filename);
770
+ }
771
+ else {
772
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
773
+ "/xl/worksheets/sheet%d.xml", worksheet_index++);
774
+ lxw_ct_add_worksheet_name(content_types, filename);
775
+ }
587
776
  }
588
777
 
589
- for (index = 1; index <= self->chart_count; index++) {
778
+ for (index = 1; index <= chart_count; index++) {
590
779
  lxw_snprintf(filename, LXW_FILENAME_LENGTH, "/xl/charts/chart%d.xml",
591
780
  index);
592
781
  lxw_ct_add_chart_name(content_types, filename);
593
782
  }
594
783
 
595
- for (index = 1; index <= self->drawing_count; index++) {
784
+ for (index = 1; index <= drawing_count; index++) {
596
785
  lxw_snprintf(filename, LXW_FILENAME_LENGTH,
597
786
  "/xl/drawings/drawing%d.xml", index);
598
787
  lxw_ct_add_drawing_name(content_types, filename);
@@ -624,9 +813,10 @@ _write_workbook_rels_file(lxw_packager *self)
624
813
  {
625
814
  lxw_relationships *rels = lxw_relationships_new();
626
815
  lxw_workbook *workbook = self->workbook;
627
- lxw_worksheet *worksheet;
816
+ lxw_sheet *sheet;
628
817
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
629
- uint16_t index = 1;
818
+ uint32_t worksheet_index = 1;
819
+ uint32_t chartsheet_index = 1;
630
820
  lxw_error err = LXW_NO_ERROR;
631
821
 
632
822
  if (!rels) {
@@ -640,10 +830,19 @@ _write_workbook_rels_file(lxw_packager *self)
640
830
  goto mem_error;
641
831
  }
642
832
 
643
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
644
- lxw_snprintf(sheetname, LXW_FILENAME_LENGTH, "worksheets/sheet%d.xml",
645
- index++);
646
- lxw_add_document_relationship(rels, "/worksheet", sheetname);
833
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
834
+ if (sheet->is_chartsheet) {
835
+ lxw_snprintf(sheetname,
836
+ LXW_FILENAME_LENGTH,
837
+ "chartsheets/sheet%d.xml", chartsheet_index++);
838
+ lxw_add_document_relationship(rels, "/chartsheet", sheetname);
839
+ }
840
+ else {
841
+ lxw_snprintf(sheetname,
842
+ LXW_FILENAME_LENGTH,
843
+ "worksheets/sheet%d.xml", worksheet_index++);
844
+ lxw_add_document_relationship(rels, "/worksheet", sheetname);
845
+ }
647
846
  }
648
847
 
649
848
  lxw_add_document_relationship(rels, "/theme", "theme/theme1.xml");
@@ -653,6 +852,10 @@ _write_workbook_rels_file(lxw_packager *self)
653
852
  lxw_add_document_relationship(rels, "/sharedStrings",
654
853
  "sharedStrings.xml");
655
854
 
855
+ if (workbook->vba_project)
856
+ lxw_add_ms_package_relationship(rels, "/vbaProject",
857
+ "vbaProject.bin");
858
+
656
859
  lxw_relationships_assemble_xml_file(rels);
657
860
 
658
861
  err = _add_file_to_zip(self, rels->file, "xl/_rels/workbook.xml.rels");
@@ -675,12 +878,17 @@ _write_worksheet_rels_file(lxw_packager *self)
675
878
  lxw_relationships *rels;
676
879
  lxw_rel_tuple *rel;
677
880
  lxw_workbook *workbook = self->workbook;
881
+ lxw_sheet *sheet;
678
882
  lxw_worksheet *worksheet;
679
883
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
680
- uint16_t index = 0;
884
+ uint32_t index = 0;
681
885
  lxw_error err;
682
886
 
683
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
887
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
888
+ if (sheet->is_chartsheet)
889
+ continue;
890
+ else
891
+ worksheet = sheet->u.worksheet;
684
892
 
685
893
  index++;
686
894
 
@@ -722,6 +930,68 @@ _write_worksheet_rels_file(lxw_packager *self)
722
930
  return LXW_NO_ERROR;
723
931
  }
724
932
 
933
+ /*
934
+ * Write the chartsheet .rels files for chartsheets that contain links to
935
+ * external data such as drawings.
936
+ */
937
+ STATIC lxw_error
938
+ _write_chartsheet_rels_file(lxw_packager *self)
939
+ {
940
+ lxw_relationships *rels;
941
+ lxw_rel_tuple *rel;
942
+ lxw_workbook *workbook = self->workbook;
943
+ lxw_sheet *sheet;
944
+ lxw_worksheet *worksheet;
945
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
946
+ uint32_t index = 0;
947
+ lxw_error err;
948
+
949
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
950
+ if (sheet->is_chartsheet)
951
+ worksheet = sheet->u.chartsheet->worksheet;
952
+ else
953
+ continue;
954
+
955
+ index++;
956
+
957
+ /* TODO. This should never be empty. Put check higher up. */
958
+ if (STAILQ_EMPTY(worksheet->external_drawing_links))
959
+ continue;
960
+
961
+ rels = lxw_relationships_new();
962
+
963
+ rels->file = lxw_tmpfile(self->tmpdir);
964
+ if (!rels->file) {
965
+ lxw_free_relationships(rels);
966
+ return LXW_ERROR_CREATING_TMPFILE;
967
+ }
968
+
969
+ STAILQ_FOREACH(rel, worksheet->external_hyperlinks, list_pointers) {
970
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
971
+ rel->target_mode);
972
+ }
973
+
974
+ STAILQ_FOREACH(rel, worksheet->external_drawing_links, list_pointers) {
975
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
976
+ rel->target_mode);
977
+ }
978
+
979
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
980
+ "xl/chartsheets/_rels/sheet%d.xml.rels", index);
981
+
982
+ lxw_relationships_assemble_xml_file(rels);
983
+
984
+ err = _add_file_to_zip(self, rels->file, sheetname);
985
+
986
+ fclose(rels->file);
987
+ lxw_free_relationships(rels);
988
+
989
+ RETURN_ON_ERROR(err);
990
+ }
991
+
992
+ return LXW_NO_ERROR;
993
+ }
994
+
725
995
  /*
726
996
  * Write the drawing .rels files for worksheets that contain charts or
727
997
  * drawings.
@@ -732,12 +1002,17 @@ _write_drawing_rels_file(lxw_packager *self)
732
1002
  lxw_relationships *rels;
733
1003
  lxw_rel_tuple *rel;
734
1004
  lxw_workbook *workbook = self->workbook;
1005
+ lxw_sheet *sheet;
735
1006
  lxw_worksheet *worksheet;
736
1007
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
737
- uint16_t index = 1;
1008
+ uint32_t index = 1;
738
1009
  lxw_error err;
739
1010
 
740
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
1011
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
1012
+ if (sheet->is_chartsheet)
1013
+ worksheet = sheet->u.chartsheet->worksheet;
1014
+ else
1015
+ worksheet = sheet->u.worksheet;
741
1016
 
742
1017
  if (STAILQ_EMPTY(worksheet->drawing_links))
743
1018
  continue;
@@ -836,7 +1111,8 @@ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
836
1111
  NULL, 0, NULL, 0, NULL,
837
1112
  Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0,
838
1113
  -MAX_WBITS, DEF_MEM_LEVEL,
839
- Z_DEFAULT_STRATEGY, NULL, 0, 0, 0, 0);
1114
+ Z_DEFAULT_STRATEGY, NULL, 0, 0, 0,
1115
+ self->use_zip64);
840
1116
 
841
1117
  if (error != ZIP_OK) {
842
1118
  LXW_ERROR("Error adding member to zipfile");
@@ -868,15 +1144,47 @@ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
868
1144
  size_read = fread(self->buffer, 1, self->buffer_size, file);
869
1145
  }
870
1146
 
1147
+ error = zipCloseFileInZip(self->zipfile);
1148
+ if (error != ZIP_OK) {
1149
+ LXW_ERROR("Error in closing member in the zipfile");
1150
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
1151
+ }
1152
+
1153
+ return LXW_NO_ERROR;
1154
+ }
1155
+
1156
+ STATIC lxw_error
1157
+ _add_buffer_to_zip(lxw_packager *self, unsigned char *buffer,
1158
+ size_t buffer_size, const char *filename)
1159
+ {
1160
+ int16_t error = ZIP_OK;
1161
+
1162
+ error = zipOpenNewFileInZip4_64(self->zipfile,
1163
+ filename,
1164
+ &self->zipfile_info,
1165
+ NULL, 0, NULL, 0, NULL,
1166
+ Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0,
1167
+ -MAX_WBITS, DEF_MEM_LEVEL,
1168
+ Z_DEFAULT_STRATEGY, NULL, 0, 0, 0,
1169
+ self->use_zip64);
1170
+
1171
+ if (error != ZIP_OK) {
1172
+ LXW_ERROR("Error adding member to zipfile");
1173
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
1174
+ }
1175
+
1176
+ error = zipWriteInFileInZip(self->zipfile,
1177
+ buffer, (unsigned int) buffer_size);
1178
+
871
1179
  if (error < 0) {
1180
+ LXW_ERROR("Error in writing member in the zipfile");
872
1181
  RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
873
1182
  }
874
- else {
875
- error = zipCloseFileInZip(self->zipfile);
876
- if (error != ZIP_OK) {
877
- LXW_ERROR("Error in closing member in the zipfile");
878
- RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
879
- }
1183
+
1184
+ error = zipCloseFileInZip(self->zipfile);
1185
+ if (error != ZIP_OK) {
1186
+ LXW_ERROR("Error in closing member in the zipfile");
1187
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
880
1188
  }
881
1189
 
882
1190
  return LXW_NO_ERROR;
@@ -891,9 +1199,21 @@ lxw_create_package(lxw_packager *self)
891
1199
  lxw_error error;
892
1200
  int8_t zip_error;
893
1201
 
1202
+ error = _write_content_types_file(self);
1203
+ RETURN_ON_ERROR(error);
1204
+
1205
+ error = _write_root_rels_file(self);
1206
+ RETURN_ON_ERROR(error);
1207
+
1208
+ error = _write_workbook_rels_file(self);
1209
+ RETURN_ON_ERROR(error);
1210
+
894
1211
  error = _write_worksheet_files(self);
895
1212
  RETURN_ON_ERROR(error);
896
1213
 
1214
+ error = _write_chartsheet_files(self);
1215
+ RETURN_ON_ERROR(error);
1216
+
897
1217
  error = _write_workbook_file(self);
898
1218
  RETURN_ON_ERROR(error);
899
1219
 
@@ -906,12 +1226,6 @@ lxw_create_package(lxw_packager *self)
906
1226
  error = _write_shared_strings_file(self);
907
1227
  RETURN_ON_ERROR(error);
908
1228
 
909
- error = _write_app_file(self);
910
- RETURN_ON_ERROR(error);
911
-
912
- error = _write_core_file(self);
913
- RETURN_ON_ERROR(error);
914
-
915
1229
  error = _write_custom_file(self);
916
1230
  RETURN_ON_ERROR(error);
917
1231
 
@@ -921,22 +1235,25 @@ lxw_create_package(lxw_packager *self)
921
1235
  error = _write_styles_file(self);
922
1236
  RETURN_ON_ERROR(error);
923
1237
 
924
- error = _write_content_types_file(self);
925
- RETURN_ON_ERROR(error);
926
-
927
- error = _write_workbook_rels_file(self);
1238
+ error = _write_worksheet_rels_file(self);
928
1239
  RETURN_ON_ERROR(error);
929
1240
 
930
- error = _write_worksheet_rels_file(self);
1241
+ error = _write_chartsheet_rels_file(self);
931
1242
  RETURN_ON_ERROR(error);
932
1243
 
933
1244
  error = _write_drawing_rels_file(self);
934
1245
  RETURN_ON_ERROR(error);
935
1246
 
936
1247
  error = _write_image_files(self);
937
- RETURN_ON_ERROR(error);;
1248
+ RETURN_ON_ERROR(error);
938
1249
 
939
- error = _write_root_rels_file(self);
1250
+ error = _add_vba_project(self);
1251
+ RETURN_ON_ERROR(error);
1252
+
1253
+ error = _write_core_file(self);
1254
+ RETURN_ON_ERROR(error);
1255
+
1256
+ error = _write_app_file(self);
940
1257
  RETURN_ON_ERROR(error);
941
1258
 
942
1259
  zip_error = zipClose(self->zipfile, NULL);