fast_excel 0.2.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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);