xlsxwriter 0.0.5 → 0.0.6

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