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.
- checksums.yaml +5 -5
- data/.dockerignore +2 -0
- data/.gitignore +7 -0
- data/.travis.yml +32 -9
- data/CHANGELOG.md +36 -1
- data/Dockerfile.test +17 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +33 -24
- data/LICENSE +21 -0
- data/Makefile +13 -0
- data/README.md +177 -40
- data/Rakefile +11 -1
- data/benchmarks/1k_rows.rb +17 -4
- data/benchmarks/20k_rows.rb +4 -0
- data/benchmarks/auto_width.rb +37 -0
- data/benchmarks/init.rb +14 -2
- data/benchmarks/memory.rb +8 -0
- data/benchmarks/profiler.rb +27 -0
- data/benchmarks/write_value.rb +62 -0
- data/examples/example.rb +3 -3
- data/examples/example_auto_width.rb +26 -0
- data/examples/example_filters.rb +36 -0
- data/examples/example_formula.rb +1 -3
- data/examples/example_hyperlink.rb +20 -0
- data/ext/fast_excel/extconf.rb +3 -0
- data/ext/fast_excel/text_width_ext.c +460 -0
- data/fast_excel.gemspec +3 -4
- data/letters.html +114 -0
- data/lib/fast_excel.rb +131 -25
- data/lib/fast_excel/binding.rb +33 -21
- data/lib/fast_excel/binding/chart.rb +20 -1
- data/lib/fast_excel/binding/format.rb +11 -4
- data/lib/fast_excel/binding/workbook.rb +10 -2
- data/lib/fast_excel/binding/worksheet.rb +44 -27
- data/libxlsxwriter/.gitignore +1 -0
- data/libxlsxwriter/.indent.pro +8 -0
- data/libxlsxwriter/.travis.yml +12 -0
- data/libxlsxwriter/CMakeLists.txt +338 -0
- data/libxlsxwriter/CONTRIBUTING.md +1 -1
- data/libxlsxwriter/Changes.txt +162 -0
- data/libxlsxwriter/LICENSE.txt +65 -4
- data/libxlsxwriter/Makefile +33 -11
- data/libxlsxwriter/Readme.md +3 -1
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +2 -1
- data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +2 -2
- data/libxlsxwriter/include/xlsxwriter.h +2 -2
- data/libxlsxwriter/include/xlsxwriter/app.h +2 -2
- data/libxlsxwriter/include/xlsxwriter/chart.h +164 -13
- data/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
- data/libxlsxwriter/include/xlsxwriter/common.h +35 -6
- data/libxlsxwriter/include/xlsxwriter/content_types.h +5 -2
- data/libxlsxwriter/include/xlsxwriter/core.h +2 -2
- data/libxlsxwriter/include/xlsxwriter/custom.h +2 -2
- data/libxlsxwriter/include/xlsxwriter/drawing.h +3 -2
- data/libxlsxwriter/include/xlsxwriter/format.h +8 -8
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/packager.h +18 -8
- data/libxlsxwriter/include/xlsxwriter/relationships.h +2 -2
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +5 -3
- data/libxlsxwriter/include/xlsxwriter/styles.h +10 -5
- data/libxlsxwriter/include/xlsxwriter/theme.h +2 -2
- data/libxlsxwriter/include/xlsxwriter/utility.h +35 -5
- data/libxlsxwriter/include/xlsxwriter/workbook.h +234 -57
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +780 -91
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
- data/libxlsxwriter/libxlsxwriter.podspec +4 -2
- data/libxlsxwriter/src/Makefile +31 -6
- data/libxlsxwriter/src/app.c +2 -2
- data/libxlsxwriter/src/chart.c +116 -23
- data/libxlsxwriter/src/chartsheet.c +508 -0
- data/libxlsxwriter/src/content_types.c +12 -4
- data/libxlsxwriter/src/core.c +11 -11
- data/libxlsxwriter/src/custom.c +3 -3
- data/libxlsxwriter/src/drawing.c +114 -17
- data/libxlsxwriter/src/format.c +5 -5
- data/libxlsxwriter/src/hash_table.c +1 -1
- data/libxlsxwriter/src/packager.c +378 -61
- data/libxlsxwriter/src/relationships.c +2 -2
- data/libxlsxwriter/src/shared_strings.c +18 -4
- data/libxlsxwriter/src/styles.c +59 -12
- data/libxlsxwriter/src/theme.c +2 -2
- data/libxlsxwriter/src/utility.c +93 -6
- data/libxlsxwriter/src/workbook.c +379 -61
- data/libxlsxwriter/src/worksheet.c +1240 -174
- data/libxlsxwriter/src/xmlwriter.c +18 -9
- data/libxlsxwriter/third_party/minizip/Makefile +6 -1
- data/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
- data/libxlsxwriter/third_party/minizip/zip.c +2 -0
- data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
- data/libxlsxwriter/version.txt +1 -1
- data/test/auto_width_test.rb +19 -0
- data/test/date_test.rb +34 -0
- data/test/format_test.rb +8 -0
- data/test/reopen_test.rb +22 -0
- data/test/test_helper.rb +8 -5
- data/test/text_width_test.rb +80 -0
- data/test/tmpfile_test.rb +1 -0
- data/test/validations_test.rb +47 -0
- data/test/worksheet_test.rb +44 -1
- metadata +33 -9
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2014-
|
|
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
|
*/
|
data/libxlsxwriter/src/core.c
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2014-
|
|
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
|
-
|
|
56
|
+
_datetime_to_iso8601_date(time_t *timer, char *str, size_t size)
|
|
57
57
|
{
|
|
58
|
-
struct tm *
|
|
58
|
+
struct tm *tmp_datetime;
|
|
59
59
|
time_t current_time = time(NULL);
|
|
60
60
|
|
|
61
61
|
if (*timer)
|
|
62
|
-
|
|
62
|
+
tmp_datetime = gmtime(timer);
|
|
63
63
|
else
|
|
64
|
-
|
|
64
|
+
tmp_datetime = gmtime(¤t_time);
|
|
65
65
|
|
|
66
|
-
strftime(str, size - 1, "%Y-%m-%dT%H:%M:%SZ",
|
|
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
|
-
|
|
148
|
-
|
|
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
|
-
|
|
170
|
-
|
|
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");
|
data/libxlsxwriter/src/custom.c
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2014-
|
|
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
|
-
|
|
84
|
+
lxw_sprintf_dbl(data, value);
|
|
85
85
|
|
|
86
86
|
lxw_xml_data_element(self->file, "vt:r8", data, NULL);
|
|
87
87
|
}
|
data/libxlsxwriter/src/drawing.c
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2014-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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");
|
data/libxlsxwriter/src/format.c
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2014-
|
|
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,
|
|
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
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
174
|
+
uint32_t index = 1;
|
|
165
175
|
lxw_error err;
|
|
166
176
|
|
|
167
|
-
STAILQ_FOREACH(
|
|
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
|
-
|
|
255
|
+
uint32_t index = 1;
|
|
202
256
|
|
|
203
|
-
STAILQ_FOREACH(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
386
|
+
uint32_t index = 1;
|
|
270
387
|
lxw_error err;
|
|
271
388
|
|
|
272
|
-
STAILQ_FOREACH(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
356
|
-
|
|
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
|
-
|
|
725
|
+
lxw_sheet *sheet;
|
|
559
726
|
char filename[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
|
|
560
|
-
|
|
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
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
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 <=
|
|
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 <=
|
|
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
|
-
|
|
816
|
+
lxw_sheet *sheet;
|
|
628
817
|
char sheetname[LXW_FILENAME_LENGTH] = { 0 };
|
|
629
|
-
|
|
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(
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
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
|
-
|
|
884
|
+
uint32_t index = 0;
|
|
681
885
|
lxw_error err;
|
|
682
886
|
|
|
683
|
-
STAILQ_FOREACH(
|
|
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
|
-
|
|
1008
|
+
uint32_t index = 1;
|
|
738
1009
|
lxw_error err;
|
|
739
1010
|
|
|
740
|
-
STAILQ_FOREACH(
|
|
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,
|
|
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
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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);
|