xlsxwriter 0.0.5 → 0.0.6

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +1 -1
  3. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +55 -5
  4. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
  5. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +6 -0
  6. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +2 -0
  7. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +1 -0
  8. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +1 -1
  9. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +3 -1
  10. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +7 -2
  11. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +16 -0
  12. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +122 -24
  13. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +236 -48
  14. data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +2 -0
  15. data/ext/xlsxwriter/libxlsxwriter/src/chart.c +40 -4
  16. data/ext/xlsxwriter/libxlsxwriter/src/chartsheet.c +508 -0
  17. data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +10 -0
  18. data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +100 -3
  19. data/ext/xlsxwriter/libxlsxwriter/src/packager.c +252 -30
  20. data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +16 -2
  21. data/ext/xlsxwriter/libxlsxwriter/src/styles.c +54 -7
  22. data/ext/xlsxwriter/libxlsxwriter/src/utility.c +43 -1
  23. data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +254 -41
  24. data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +381 -65
  25. data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +16 -7
  26. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
  27. data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.c +2 -0
  28. data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
  29. data/ext/xlsxwriter/workbook.c +9 -6
  30. data/lib/xlsxwriter/version.rb +1 -1
  31. metadata +5 -4
@@ -296,6 +296,16 @@ lxw_ct_add_worksheet_name(lxw_content_types *self, const char *name)
296
296
  LXW_APP_DOCUMENT "spreadsheetml.worksheet+xml");
297
297
  }
298
298
 
299
+ /*
300
+ * Add the name of a chartsheet to the ContentTypes overrides.
301
+ */
302
+ void
303
+ lxw_ct_add_chartsheet_name(lxw_content_types *self, const char *name)
304
+ {
305
+ lxw_ct_add_override(self, name,
306
+ LXW_APP_DOCUMENT "spreadsheetml.chartsheet+xml");
307
+ }
308
+
299
309
  /*
300
310
  * Add the name of a chart to the ContentTypes overrides.
301
311
  */
@@ -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);
@@ -489,13 +489,40 @@ _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
  /*
@@ -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.
@@ -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");
@@ -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
  */
@@ -164,12 +167,18 @@ STATIC lxw_error
164
167
  _write_worksheet_files(lxw_packager *self)
165
168
  {
166
169
  lxw_workbook *workbook = self->workbook;
170
+ lxw_sheet *sheet;
167
171
  lxw_worksheet *worksheet;
168
172
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
169
173
  uint16_t index = 1;
170
174
  lxw_error err;
171
175
 
172
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
176
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
177
+ if (sheet->is_chartsheet)
178
+ continue;
179
+ else
180
+ worksheet = sheet->u.worksheet;
181
+
173
182
  lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
174
183
  "xl/worksheets/sheet%d.xml", index++);
175
184
 
@@ -191,6 +200,43 @@ _write_worksheet_files(lxw_packager *self)
191
200
  return LXW_NO_ERROR;
192
201
  }
193
202
 
203
+ /*
204
+ * Write the chartsheet files.
205
+ */
206
+ STATIC lxw_error
207
+ _write_chartsheet_files(lxw_packager *self)
208
+ {
209
+ lxw_workbook *workbook = self->workbook;
210
+ lxw_sheet *sheet;
211
+ lxw_chartsheet *chartsheet;
212
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
213
+ uint16_t index = 1;
214
+ lxw_error err;
215
+
216
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
217
+ if (sheet->is_chartsheet)
218
+ chartsheet = sheet->u.chartsheet;
219
+ else
220
+ continue;
221
+
222
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
223
+ "xl/chartsheets/sheet%d.xml", index++);
224
+
225
+ chartsheet->file = lxw_tmpfile(self->tmpdir);
226
+ if (!chartsheet->file)
227
+ return LXW_ERROR_CREATING_TMPFILE;
228
+
229
+ lxw_chartsheet_assemble_xml_file(chartsheet);
230
+
231
+ err = _add_file_to_zip(self, chartsheet->file, sheetname);
232
+ RETURN_ON_ERROR(err);
233
+
234
+ fclose(chartsheet->file);
235
+ }
236
+
237
+ return LXW_NO_ERROR;
238
+ }
239
+
194
240
  /*
195
241
  * Write the /xl/media/image?.xml files.
196
242
  */
@@ -198,6 +244,7 @@ STATIC lxw_error
198
244
  _write_image_files(lxw_packager *self)
199
245
  {
200
246
  lxw_workbook *workbook = self->workbook;
247
+ lxw_sheet *sheet;
201
248
  lxw_worksheet *worksheet;
202
249
  lxw_image_options *image;
203
250
  lxw_error err;
@@ -206,7 +253,11 @@ _write_image_files(lxw_packager *self)
206
253
  char filename[LXW_FILENAME_LENGTH] = { 0 };
207
254
  uint16_t index = 1;
208
255
 
209
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
256
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
257
+ if (sheet->is_chartsheet)
258
+ continue;
259
+ else
260
+ worksheet = sheet->u.worksheet;
210
261
 
211
262
  if (STAILQ_EMPTY(worksheet->image_data))
212
263
  continue;
@@ -216,17 +267,24 @@ _write_image_files(lxw_packager *self)
216
267
  lxw_snprintf(filename, LXW_FILENAME_LENGTH,
217
268
  "xl/media/image%d.%s", index++, image->extension);
218
269
 
219
- /* Check that the image file exists and can be opened. */
220
- image_stream = fopen(image->filename, "rb");
221
- if (!image_stream) {
222
- LXW_WARN_FORMAT1("Error adding image to xlsx file: file "
223
- "doesn't exist or can't be opened: %s.",
224
- image->filename);
225
- return LXW_ERROR_CREATING_TMPFILE;
270
+ if (!image->is_image_buffer) {
271
+ /* Check that the image file exists and can be opened. */
272
+ image_stream = fopen(image->filename, "rb");
273
+ if (!image_stream) {
274
+ LXW_WARN_FORMAT1("Error adding image to xlsx file: file "
275
+ "doesn't exist or can't be opened: %s.",
276
+ image->filename);
277
+ return LXW_ERROR_CREATING_TMPFILE;
278
+ }
279
+
280
+ err = _add_file_to_zip(self, image_stream, filename);
281
+ fclose(image_stream);
282
+ }
283
+ else {
284
+ err = _add_buffer_to_zip(self,
285
+ image->image_buffer,
286
+ image->image_buffer_size, filename);
226
287
  }
227
-
228
- err = _add_file_to_zip(self, image_stream, filename);
229
- fclose(image_stream);
230
288
 
231
289
  RETURN_ON_ERROR(err);
232
290
  }
@@ -276,13 +334,19 @@ STATIC lxw_error
276
334
  _write_drawing_files(lxw_packager *self)
277
335
  {
278
336
  lxw_workbook *workbook = self->workbook;
337
+ lxw_sheet *sheet;
279
338
  lxw_worksheet *worksheet;
280
339
  lxw_drawing *drawing;
281
340
  char filename[LXW_FILENAME_LENGTH] = { 0 };
282
341
  uint16_t index = 1;
283
342
  lxw_error err;
284
343
 
285
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
344
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
345
+ if (sheet->is_chartsheet)
346
+ worksheet = sheet->u.chartsheet->worksheet;
347
+ else
348
+ worksheet = sheet->u.worksheet;
349
+
286
350
  drawing = worksheet->drawing;
287
351
 
288
352
  if (drawing) {
@@ -340,7 +404,9 @@ STATIC lxw_error
340
404
  _write_app_file(lxw_packager *self)
341
405
  {
342
406
  lxw_workbook *workbook = self->workbook;
407
+ lxw_sheet *sheet;
343
408
  lxw_worksheet *worksheet;
409
+ lxw_chartsheet *chartsheet;
344
410
  lxw_defined_name *defined_name;
345
411
  lxw_app *app;
346
412
  uint16_t named_range_count = 0;
@@ -361,12 +427,30 @@ _write_app_file(lxw_packager *self)
361
427
  goto mem_error;
362
428
  }
363
429
 
364
- lxw_snprintf(number, LXW_ATTR_32, "%d", self->workbook->num_sheets);
430
+ if (self->workbook->num_worksheets) {
431
+ lxw_snprintf(number, LXW_ATTR_32, "%d",
432
+ self->workbook->num_worksheets);
433
+ lxw_app_add_heading_pair(app, "Worksheets", number);
434
+ }
435
+
436
+ if (self->workbook->num_chartsheets) {
437
+ lxw_snprintf(number, LXW_ATTR_32, "%d",
438
+ self->workbook->num_chartsheets);
439
+ lxw_app_add_heading_pair(app, "Charts", number);
440
+ }
365
441
 
366
- lxw_app_add_heading_pair(app, "Worksheets", number);
442
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
443
+ if (!sheet->is_chartsheet) {
444
+ worksheet = sheet->u.worksheet;
445
+ lxw_app_add_part_name(app, worksheet->name);
446
+ }
447
+ }
367
448
 
368
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
369
- lxw_app_add_part_name(app, worksheet->name);
449
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
450
+ if (sheet->is_chartsheet) {
451
+ chartsheet = sheet->u.chartsheet;
452
+ lxw_app_add_part_name(app, chartsheet->name);
453
+ }
370
454
  }
371
455
 
372
456
  /* Add the Named Ranges parts. */
@@ -568,9 +652,11 @@ _write_content_types_file(lxw_packager *self)
568
652
  {
569
653
  lxw_content_types *content_types = lxw_content_types_new();
570
654
  lxw_workbook *workbook = self->workbook;
571
- lxw_worksheet *worksheet;
655
+ lxw_sheet *sheet;
572
656
  char filename[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
573
657
  uint16_t index = 1;
658
+ uint16_t worksheet_index = 1;
659
+ uint16_t chartsheet_index = 1;
574
660
  lxw_error err = LXW_NO_ERROR;
575
661
 
576
662
  if (!content_types) {
@@ -593,10 +679,17 @@ _write_content_types_file(lxw_packager *self)
593
679
  if (workbook->has_bmp)
594
680
  lxw_ct_add_default(content_types, "bmp", "image/bmp");
595
681
 
596
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
597
- lxw_snprintf(filename, LXW_FILENAME_LENGTH,
598
- "/xl/worksheets/sheet%d.xml", index++);
599
- lxw_ct_add_worksheet_name(content_types, filename);
682
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
683
+ if (sheet->is_chartsheet) {
684
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
685
+ "/xl/chartsheets/sheet%d.xml", chartsheet_index++);
686
+ lxw_ct_add_chartsheet_name(content_types, filename);
687
+ }
688
+ else {
689
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
690
+ "/xl/worksheets/sheet%d.xml", worksheet_index++);
691
+ lxw_ct_add_worksheet_name(content_types, filename);
692
+ }
600
693
  }
601
694
 
602
695
  for (index = 1; index <= self->chart_count; index++) {
@@ -637,9 +730,10 @@ _write_workbook_rels_file(lxw_packager *self)
637
730
  {
638
731
  lxw_relationships *rels = lxw_relationships_new();
639
732
  lxw_workbook *workbook = self->workbook;
640
- lxw_worksheet *worksheet;
733
+ lxw_sheet *sheet;
641
734
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
642
- uint16_t index = 1;
735
+ uint16_t worksheet_index = 1;
736
+ uint16_t chartsheet_index = 1;
643
737
  lxw_error err = LXW_NO_ERROR;
644
738
 
645
739
  if (!rels) {
@@ -653,10 +747,19 @@ _write_workbook_rels_file(lxw_packager *self)
653
747
  goto mem_error;
654
748
  }
655
749
 
656
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
657
- lxw_snprintf(sheetname, LXW_FILENAME_LENGTH, "worksheets/sheet%d.xml",
658
- index++);
659
- lxw_add_document_relationship(rels, "/worksheet", sheetname);
750
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
751
+ if (sheet->is_chartsheet) {
752
+ lxw_snprintf(sheetname,
753
+ LXW_FILENAME_LENGTH,
754
+ "chartsheets/sheet%d.xml", chartsheet_index++);
755
+ lxw_add_document_relationship(rels, "/chartsheet", sheetname);
756
+ }
757
+ else {
758
+ lxw_snprintf(sheetname,
759
+ LXW_FILENAME_LENGTH,
760
+ "worksheets/sheet%d.xml", worksheet_index++);
761
+ lxw_add_document_relationship(rels, "/worksheet", sheetname);
762
+ }
660
763
  }
661
764
 
662
765
  lxw_add_document_relationship(rels, "/theme", "theme/theme1.xml");
@@ -688,12 +791,17 @@ _write_worksheet_rels_file(lxw_packager *self)
688
791
  lxw_relationships *rels;
689
792
  lxw_rel_tuple *rel;
690
793
  lxw_workbook *workbook = self->workbook;
794
+ lxw_sheet *sheet;
691
795
  lxw_worksheet *worksheet;
692
796
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
693
797
  uint16_t index = 0;
694
798
  lxw_error err;
695
799
 
696
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
800
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
801
+ if (sheet->is_chartsheet)
802
+ continue;
803
+ else
804
+ worksheet = sheet->u.worksheet;
697
805
 
698
806
  index++;
699
807
 
@@ -735,6 +843,68 @@ _write_worksheet_rels_file(lxw_packager *self)
735
843
  return LXW_NO_ERROR;
736
844
  }
737
845
 
846
+ /*
847
+ * Write the chartsheet .rels files for chartsheets that contain links to
848
+ * external data such as drawings.
849
+ */
850
+ STATIC lxw_error
851
+ _write_chartsheet_rels_file(lxw_packager *self)
852
+ {
853
+ lxw_relationships *rels;
854
+ lxw_rel_tuple *rel;
855
+ lxw_workbook *workbook = self->workbook;
856
+ lxw_sheet *sheet;
857
+ lxw_worksheet *worksheet;
858
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
859
+ uint16_t index = 0;
860
+ lxw_error err;
861
+
862
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
863
+ if (sheet->is_chartsheet)
864
+ worksheet = sheet->u.chartsheet->worksheet;
865
+ else
866
+ continue;
867
+
868
+ index++;
869
+
870
+ /* TODO. This should never be empty. Put check higher up. */
871
+ if (STAILQ_EMPTY(worksheet->external_drawing_links))
872
+ continue;
873
+
874
+ rels = lxw_relationships_new();
875
+
876
+ rels->file = lxw_tmpfile(self->tmpdir);
877
+ if (!rels->file) {
878
+ lxw_free_relationships(rels);
879
+ return LXW_ERROR_CREATING_TMPFILE;
880
+ }
881
+
882
+ STAILQ_FOREACH(rel, worksheet->external_hyperlinks, list_pointers) {
883
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
884
+ rel->target_mode);
885
+ }
886
+
887
+ STAILQ_FOREACH(rel, worksheet->external_drawing_links, list_pointers) {
888
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
889
+ rel->target_mode);
890
+ }
891
+
892
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
893
+ "xl/chartsheets/_rels/sheet%d.xml.rels", index);
894
+
895
+ lxw_relationships_assemble_xml_file(rels);
896
+
897
+ err = _add_file_to_zip(self, rels->file, sheetname);
898
+
899
+ fclose(rels->file);
900
+ lxw_free_relationships(rels);
901
+
902
+ RETURN_ON_ERROR(err);
903
+ }
904
+
905
+ return LXW_NO_ERROR;
906
+ }
907
+
738
908
  /*
739
909
  * Write the drawing .rels files for worksheets that contain charts or
740
910
  * drawings.
@@ -745,12 +915,17 @@ _write_drawing_rels_file(lxw_packager *self)
745
915
  lxw_relationships *rels;
746
916
  lxw_rel_tuple *rel;
747
917
  lxw_workbook *workbook = self->workbook;
918
+ lxw_sheet *sheet;
748
919
  lxw_worksheet *worksheet;
749
920
  char sheetname[LXW_FILENAME_LENGTH] = { 0 };
750
921
  uint16_t index = 1;
751
922
  lxw_error err;
752
923
 
753
- STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
924
+ STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
925
+ if (sheet->is_chartsheet)
926
+ worksheet = sheet->u.chartsheet->worksheet;
927
+ else
928
+ worksheet = sheet->u.worksheet;
754
929
 
755
930
  if (STAILQ_EMPTY(worksheet->drawing_links))
756
931
  continue;
@@ -895,6 +1070,47 @@ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
895
1070
  return LXW_NO_ERROR;
896
1071
  }
897
1072
 
1073
+ STATIC lxw_error
1074
+ _add_buffer_to_zip(lxw_packager *self, unsigned char *buffer,
1075
+ size_t buffer_size, const char *filename)
1076
+ {
1077
+ int16_t error = ZIP_OK;
1078
+
1079
+ error = zipOpenNewFileInZip4_64(self->zipfile,
1080
+ filename,
1081
+ &self->zipfile_info,
1082
+ NULL, 0, NULL, 0, NULL,
1083
+ Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0,
1084
+ -MAX_WBITS, DEF_MEM_LEVEL,
1085
+ Z_DEFAULT_STRATEGY, NULL, 0, 0, 0, 0);
1086
+
1087
+ if (error != ZIP_OK) {
1088
+ LXW_ERROR("Error adding member to zipfile");
1089
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
1090
+ }
1091
+
1092
+ error = zipWriteInFileInZip(self->zipfile,
1093
+ buffer, (unsigned int) buffer_size);
1094
+
1095
+ if (error < 0) {
1096
+ LXW_ERROR("Error in writing member in the zipfile");
1097
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
1098
+ }
1099
+
1100
+ if (error < 0) {
1101
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
1102
+ }
1103
+ else {
1104
+ error = zipCloseFileInZip(self->zipfile);
1105
+ if (error != ZIP_OK) {
1106
+ LXW_ERROR("Error in closing member in the zipfile");
1107
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
1108
+ }
1109
+ }
1110
+
1111
+ return LXW_NO_ERROR;
1112
+ }
1113
+
898
1114
  /*
899
1115
  * Write the xml files that make up the XLXS OPC package.
900
1116
  */
@@ -907,6 +1123,9 @@ lxw_create_package(lxw_packager *self)
907
1123
  error = _write_worksheet_files(self);
908
1124
  RETURN_ON_ERROR(error);
909
1125
 
1126
+ error = _write_chartsheet_files(self);
1127
+ RETURN_ON_ERROR(error);
1128
+
910
1129
  error = _write_workbook_file(self);
911
1130
  RETURN_ON_ERROR(error);
912
1131
 
@@ -943,6 +1162,9 @@ lxw_create_package(lxw_packager *self)
943
1162
  error = _write_worksheet_rels_file(self);
944
1163
  RETURN_ON_ERROR(error);
945
1164
 
1165
+ error = _write_chartsheet_rels_file(self);
1166
+ RETURN_ON_ERROR(error);
1167
+
946
1168
  error = _write_drawing_rels_file(self);
947
1169
  RETURN_ON_ERROR(error);
948
1170