fast_excel 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -7
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -1
- data/examples/example.rb +2 -0
- data/examples/example_date_time.rb +38 -0
- data/fast_excel.gemspec +2 -2
- data/lib/fast_excel/binding/format.rb +17 -0
- data/lib/fast_excel/binding/workbook.rb +39 -17
- data/lib/fast_excel/binding/worksheet.rb +57 -13
- data/lib/fast_excel/binding.rb +7 -7
- data/lib/fast_excel.rb +27 -20
- data/libxlsxwriter/.github/FUNDING.yml +1 -0
- data/libxlsxwriter/.github/ISSUE_TEMPLATE.md +85 -0
- data/libxlsxwriter/.github/PULL_REQUEST_TEMPLATE.md +130 -0
- data/libxlsxwriter/.github/workflows/cmake_actions.yml +48 -0
- data/libxlsxwriter/.github/workflows/code_style.yml +23 -0
- data/libxlsxwriter/.github/workflows/coverity.yml +22 -0
- data/libxlsxwriter/.github/workflows/make_actions.yml +52 -0
- data/libxlsxwriter/.github/workflows/valgrind.yml +23 -0
- data/libxlsxwriter/.github/workflows/windows_build.yml +54 -0
- data/libxlsxwriter/.github/workflows/zig_build.yml +22 -0
- data/libxlsxwriter/.gitignore +16 -1
- data/libxlsxwriter/.indent.pro +24 -0
- data/libxlsxwriter/CMakeLists.txt +156 -56
- data/libxlsxwriter/CONTRIBUTING.md +2 -2
- data/libxlsxwriter/Changes.txt +344 -2
- data/libxlsxwriter/LICENSE.txt +66 -8
- data/libxlsxwriter/Makefile +151 -54
- data/libxlsxwriter/Package.swift +42 -0
- data/libxlsxwriter/Readme.md +4 -2
- data/libxlsxwriter/build.zig +324 -0
- data/libxlsxwriter/build.zig.zon +11 -0
- data/libxlsxwriter/cmake/FindMINIZIP.cmake +3 -3
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +6 -0
- data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/chart.h +236 -32
- data/libxlsxwriter/include/xlsxwriter/chartsheet.h +7 -7
- data/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
- data/libxlsxwriter/include/xlsxwriter/common.h +111 -50
- data/libxlsxwriter/include/xlsxwriter/content_types.h +8 -1
- data/libxlsxwriter/include/xlsxwriter/core.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/drawing.h +11 -20
- data/libxlsxwriter/include/xlsxwriter/format.h +121 -8
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/metadata.h +49 -0
- data/libxlsxwriter/include/xlsxwriter/packager.h +27 -16
- data/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/styles.h +13 -7
- data/libxlsxwriter/include/xlsxwriter/table.h +51 -0
- data/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/third_party/emyg_dtoa.h +26 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +27 -25
- data/libxlsxwriter/include/xlsxwriter/third_party/md5.h +45 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +155 -153
- data/libxlsxwriter/include/xlsxwriter/utility.h +70 -8
- data/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
- data/libxlsxwriter/include/xlsxwriter/workbook.h +218 -47
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +2770 -241
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +12 -8
- data/libxlsxwriter/include/xlsxwriter.h +4 -2
- data/libxlsxwriter/libxlsxwriter.podspec +8 -5
- data/libxlsxwriter/src/Makefile +58 -21
- data/libxlsxwriter/src/app.c +5 -2
- data/libxlsxwriter/src/chart.c +396 -81
- data/libxlsxwriter/src/chartsheet.c +22 -22
- data/libxlsxwriter/src/comment.c +443 -0
- data/libxlsxwriter/src/content_types.c +40 -1
- data/libxlsxwriter/src/core.c +2 -2
- data/libxlsxwriter/src/custom.c +1 -1
- data/libxlsxwriter/src/drawing.c +160 -40
- data/libxlsxwriter/src/format.c +109 -25
- data/libxlsxwriter/src/hash_table.c +1 -1
- data/libxlsxwriter/src/metadata.c +283 -0
- data/libxlsxwriter/src/packager.c +794 -94
- data/libxlsxwriter/src/relationships.c +1 -1
- data/libxlsxwriter/src/shared_strings.c +2 -4
- data/libxlsxwriter/src/styles.c +353 -58
- data/libxlsxwriter/src/table.c +304 -0
- data/libxlsxwriter/src/theme.c +1 -1
- data/libxlsxwriter/src/utility.c +143 -43
- data/libxlsxwriter/src/vml.c +1062 -0
- data/libxlsxwriter/src/workbook.c +567 -77
- data/libxlsxwriter/src/worksheet.c +6668 -1462
- data/libxlsxwriter/src/xmlwriter.c +95 -5
- data/libxlsxwriter/third_party/dtoa/Makefile +42 -0
- data/libxlsxwriter/third_party/dtoa/emyg_dtoa.c +461 -0
- data/libxlsxwriter/third_party/dtoa/emyg_dtoa.h +26 -0
- data/libxlsxwriter/third_party/md5/Makefile +42 -0
- data/libxlsxwriter/third_party/md5/md5.c +291 -0
- data/libxlsxwriter/third_party/md5/md5.h +45 -0
- data/libxlsxwriter/third_party/minizip/Makefile +3 -8
- data/libxlsxwriter/third_party/minizip/Makefile.orig +8 -4
- data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +1 -1
- data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
- data/libxlsxwriter/third_party/minizip/crypt.h +13 -16
- data/libxlsxwriter/third_party/minizip/ioapi.c +31 -57
- data/libxlsxwriter/third_party/minizip/ioapi.h +31 -23
- data/libxlsxwriter/third_party/minizip/iowin32.c +29 -45
- data/libxlsxwriter/third_party/minizip/iowin32.h +4 -4
- data/libxlsxwriter/third_party/minizip/miniunz.c +29 -56
- data/libxlsxwriter/third_party/minizip/minizip.c +38 -49
- data/libxlsxwriter/third_party/minizip/mztools.c +1 -7
- data/libxlsxwriter/third_party/minizip/unzip.c +202 -342
- data/libxlsxwriter/third_party/minizip/unzip.h +74 -74
- data/libxlsxwriter/third_party/minizip/zip.c +165 -218
- data/libxlsxwriter/third_party/minizip/zip.h +164 -154
- data/libxlsxwriter/third_party/tmpfileplus/Makefile +3 -3
- data/libxlsxwriter/version.txt +1 -1
- data/test/auto_width_test.rb +20 -0
- data/test/default_format_test.rb +1 -1
- data/test/validations_test.rb +3 -3
- data/test/worksheet_test.rb +6 -1
- metadata +33 -7
- data/libxlsxwriter/.travis.yml +0 -37
data/libxlsxwriter/src/chart.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-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
7
7
|
*
|
8
8
|
*/
|
9
9
|
|
@@ -78,10 +78,30 @@ _chart_free_font(lxw_chart_font *font)
|
|
78
78
|
if (!font)
|
79
79
|
return;
|
80
80
|
|
81
|
-
free(font->name);
|
81
|
+
free((void *) font->name);
|
82
82
|
free(font);
|
83
83
|
}
|
84
84
|
|
85
|
+
STATIC void
|
86
|
+
_chart_free_data_labels(lxw_chart_series *series)
|
87
|
+
{
|
88
|
+
uint16_t index;
|
89
|
+
|
90
|
+
for (index = 0; index < series->data_label_count; index++) {
|
91
|
+
lxw_chart_custom_label *data_label = &series->data_labels[index];
|
92
|
+
|
93
|
+
free(data_label->value);
|
94
|
+
_chart_free_range(data_label->range);
|
95
|
+
_chart_free_font(data_label->font);
|
96
|
+
free(data_label->line);
|
97
|
+
free(data_label->fill);
|
98
|
+
free(data_label->pattern);
|
99
|
+
}
|
100
|
+
|
101
|
+
series->data_label_count = 0;
|
102
|
+
free(series->data_labels);
|
103
|
+
}
|
104
|
+
|
85
105
|
/*
|
86
106
|
* Free a series object.
|
87
107
|
*/
|
@@ -96,6 +116,10 @@ _chart_series_free(lxw_chart_series *series)
|
|
96
116
|
free(series->fill);
|
97
117
|
free(series->pattern);
|
98
118
|
free(series->label_num_format);
|
119
|
+
free(series->label_line);
|
120
|
+
free(series->label_fill);
|
121
|
+
free(series->label_pattern);
|
122
|
+
|
99
123
|
_chart_free_font(series->label_font);
|
100
124
|
|
101
125
|
if (series->marker) {
|
@@ -109,6 +133,7 @@ _chart_series_free(lxw_chart_series *series)
|
|
109
133
|
_chart_free_range(series->values);
|
110
134
|
_chart_free_range(series->title.range);
|
111
135
|
_chart_free_points(series);
|
136
|
+
_chart_free_data_labels(series);
|
112
137
|
|
113
138
|
if (series->x_error_bars) {
|
114
139
|
free(series->x_error_bars->line);
|
@@ -331,11 +356,6 @@ _chart_convert_font_args(lxw_chart_font *user_font)
|
|
331
356
|
if (font->rotation)
|
332
357
|
font->rotation = font->rotation * 60000;
|
333
358
|
|
334
|
-
if (font->color) {
|
335
|
-
font->color = lxw_format_check_color(font->color);
|
336
|
-
font->has_color = LXW_TRUE;
|
337
|
-
}
|
338
|
-
|
339
359
|
return font;
|
340
360
|
}
|
341
361
|
|
@@ -360,11 +380,6 @@ _chart_convert_line_args(lxw_chart_line *user_line)
|
|
360
380
|
line->dash_type = user_line->dash_type;
|
361
381
|
line->transparency = user_line->transparency;
|
362
382
|
|
363
|
-
if (line->color) {
|
364
|
-
line->color = lxw_format_check_color(line->color);
|
365
|
-
line->has_color = LXW_TRUE;
|
366
|
-
}
|
367
|
-
|
368
383
|
if (line->transparency > 100)
|
369
384
|
line->transparency = 0;
|
370
385
|
|
@@ -390,11 +405,6 @@ _chart_convert_fill_args(lxw_chart_fill *user_fill)
|
|
390
405
|
fill->none = user_fill->none;
|
391
406
|
fill->transparency = user_fill->transparency;
|
392
407
|
|
393
|
-
if (fill->color) {
|
394
|
-
fill->color = lxw_format_check_color(fill->color);
|
395
|
-
fill->has_color = LXW_TRUE;
|
396
|
-
}
|
397
|
-
|
398
408
|
if (fill->transparency > 100)
|
399
409
|
fill->transparency = 0;
|
400
410
|
|
@@ -430,17 +440,9 @@ _chart_convert_pattern_args(lxw_chart_pattern *user_pattern)
|
|
430
440
|
pattern->bg_color = user_pattern->bg_color;
|
431
441
|
pattern->type = user_pattern->type;
|
432
442
|
|
433
|
-
|
434
|
-
pattern->has_fg_color = LXW_TRUE;
|
435
|
-
|
436
|
-
if (pattern->bg_color) {
|
437
|
-
pattern->bg_color = lxw_format_check_color(pattern->bg_color);
|
438
|
-
pattern->has_bg_color = LXW_TRUE;
|
439
|
-
}
|
440
|
-
else {
|
443
|
+
if (!pattern->bg_color) {
|
441
444
|
/* Default background color in Excel is white, when unspecified. */
|
442
445
|
pattern->bg_color = LXW_COLOR_WHITE;
|
443
|
-
pattern->has_bg_color = LXW_TRUE;
|
444
446
|
}
|
445
447
|
|
446
448
|
return pattern;
|
@@ -464,7 +466,7 @@ _chart_set_default_marker_type(lxw_chart *self, uint8_t type)
|
|
464
466
|
/*
|
465
467
|
* Set an axis number format.
|
466
468
|
*/
|
467
|
-
void
|
469
|
+
STATIC void
|
468
470
|
_chart_axis_set_default_num_format(lxw_chart_axis *axis, char *num_format)
|
469
471
|
{
|
470
472
|
if (!num_format)
|
@@ -857,7 +859,7 @@ _chart_write_a_def_rpr(lxw_chart *self, lxw_chart_font *font)
|
|
857
859
|
LXW_INIT_ATTRIBUTES();
|
858
860
|
|
859
861
|
if (font) {
|
860
|
-
has_color = font->color
|
862
|
+
has_color = !!font->color;
|
861
863
|
has_latin = font->name || font->pitch_family || font->charset;
|
862
864
|
use_font_default = !(has_color || has_latin || font->baseline == -1);
|
863
865
|
|
@@ -929,7 +931,7 @@ _chart_write_a_r_pr(lxw_chart *self, lxw_chart_font *font)
|
|
929
931
|
LXW_PUSH_ATTRIBUTES_STR("lang", "en-US");
|
930
932
|
|
931
933
|
if (font) {
|
932
|
-
has_color = font->color
|
934
|
+
has_color = !!font->color;
|
933
935
|
has_latin = font->name || font->pitch_family || font->charset;
|
934
936
|
use_font_default = !(has_color || has_latin || font->baseline == -1);
|
935
937
|
|
@@ -1090,12 +1092,14 @@ _chart_write_a_p_pie(lxw_chart *self, lxw_chart_font *font)
|
|
1090
1092
|
* Write the <a:p> element.
|
1091
1093
|
*/
|
1092
1094
|
STATIC void
|
1093
|
-
_chart_write_a_p_rich(lxw_chart *self, char *name, lxw_chart_font *font
|
1095
|
+
_chart_write_a_p_rich(lxw_chart *self, char *name, lxw_chart_font *font,
|
1096
|
+
uint8_t ignore_rich_pr)
|
1094
1097
|
{
|
1095
1098
|
lxw_xml_start_tag(self->file, "a:p", NULL);
|
1096
1099
|
|
1097
1100
|
/* Write the a:pPr element. */
|
1098
|
-
|
1101
|
+
if (!ignore_rich_pr)
|
1102
|
+
_chart_write_a_p_pr_rich(self, font);
|
1099
1103
|
|
1100
1104
|
/* Write the a:r element. */
|
1101
1105
|
_chart_write_a_r(self, name, font);
|
@@ -1127,11 +1131,27 @@ _chart_write_a_body_pr(lxw_chart *self, int32_t rotation,
|
|
1127
1131
|
if (rotation == 0 && is_horizontal)
|
1128
1132
|
rotation = -5400000;
|
1129
1133
|
|
1130
|
-
if (rotation)
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1134
|
+
if (rotation) {
|
1135
|
+
if (rotation == 16200000) {
|
1136
|
+
/* 270 deg/stacked angle. */
|
1137
|
+
LXW_PUSH_ATTRIBUTES_STR("rot", "0");
|
1138
|
+
LXW_PUSH_ATTRIBUTES_STR("vert", "wordArtVert");
|
1139
|
+
}
|
1140
|
+
else if (rotation == 16260000) {
|
1141
|
+
/* 271 deg/East Asian vertical. */
|
1142
|
+
LXW_PUSH_ATTRIBUTES_STR("rot", "0");
|
1143
|
+
LXW_PUSH_ATTRIBUTES_STR("vert", "eaVert");
|
1144
|
+
}
|
1145
|
+
else if (rotation == 21600000) {
|
1146
|
+
/* 360 deg = 0 for y axis. */
|
1147
|
+
LXW_PUSH_ATTRIBUTES_STR("rot", "0");
|
1148
|
+
LXW_PUSH_ATTRIBUTES_STR("vert", "horz");
|
1149
|
+
}
|
1150
|
+
else {
|
1151
|
+
LXW_PUSH_ATTRIBUTES_INT("rot", rotation);
|
1152
|
+
LXW_PUSH_ATTRIBUTES_STR("vert", "horz");
|
1153
|
+
}
|
1154
|
+
}
|
1135
1155
|
|
1136
1156
|
lxw_xml_empty_tag(self->file, "a:bodyPr", &attributes);
|
1137
1157
|
|
@@ -1466,8 +1486,8 @@ _chart_write_axis_font(lxw_chart *self, lxw_chart_font *font)
|
|
1466
1486
|
* Write the <c:rich> element.
|
1467
1487
|
*/
|
1468
1488
|
STATIC void
|
1469
|
-
_chart_write_rich(lxw_chart *self, char *name,
|
1470
|
-
|
1489
|
+
_chart_write_rich(lxw_chart *self, char *name, lxw_chart_font *font,
|
1490
|
+
uint8_t is_horizontal, uint8_t ignore_rich_pr)
|
1471
1491
|
{
|
1472
1492
|
int32_t rotation = 0;
|
1473
1493
|
|
@@ -1483,7 +1503,7 @@ _chart_write_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
|
|
1483
1503
|
_chart_write_a_lst_style(self);
|
1484
1504
|
|
1485
1505
|
/* Write the a:p element. */
|
1486
|
-
_chart_write_a_p_rich(self, name, font);
|
1506
|
+
_chart_write_a_p_rich(self, name, font, ignore_rich_pr);
|
1487
1507
|
|
1488
1508
|
lxw_xml_end_tag(self->file, "c:rich");
|
1489
1509
|
}
|
@@ -1499,7 +1519,7 @@ _chart_write_tx_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
|
|
1499
1519
|
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
1500
1520
|
|
1501
1521
|
/* Write the c:rich element. */
|
1502
|
-
_chart_write_rich(self, name, is_horizontal,
|
1522
|
+
_chart_write_rich(self, name, font, is_horizontal, LXW_FALSE);
|
1503
1523
|
|
1504
1524
|
lxw_xml_end_tag(self->file, "c:tx");
|
1505
1525
|
}
|
@@ -1658,28 +1678,33 @@ _chart_write_a_ln(lxw_chart *self, lxw_chart_line *line)
|
|
1658
1678
|
/* Convert to internal units. */
|
1659
1679
|
width_int = (uint32_t) (0.5 + (12700.0 * width_flt));
|
1660
1680
|
|
1661
|
-
if (
|
1681
|
+
if (line->width > 0.0)
|
1662
1682
|
LXW_PUSH_ATTRIBUTES_INT("w", width_int);
|
1663
1683
|
|
1664
|
-
|
1684
|
+
if (line->none || line->color || line->dash_type) {
|
1685
|
+
lxw_xml_start_tag(self->file, "a:ln", &attributes);
|
1665
1686
|
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1687
|
+
/* Write the line fill. */
|
1688
|
+
if (line->none) {
|
1689
|
+
/* Write the a:noFill element. */
|
1690
|
+
_chart_write_a_no_fill(self);
|
1691
|
+
}
|
1692
|
+
else if (line->color) {
|
1693
|
+
/* Write the a:solidFill element. */
|
1694
|
+
_chart_write_a_solid_fill(self, line->color, line->transparency);
|
1695
|
+
}
|
1675
1696
|
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1697
|
+
/* Write the line/dash type. */
|
1698
|
+
if (line->dash_type) {
|
1699
|
+
/* Write the a:prstDash element. */
|
1700
|
+
_chart_write_a_prst_dash(self, line->dash_type);
|
1701
|
+
}
|
1681
1702
|
|
1682
|
-
|
1703
|
+
lxw_xml_end_tag(self->file, "a:ln");
|
1704
|
+
}
|
1705
|
+
else {
|
1706
|
+
lxw_xml_empty_tag(self->file, "a:ln", &attributes);
|
1707
|
+
}
|
1683
1708
|
|
1684
1709
|
LXW_FREE_ATTRIBUTES();
|
1685
1710
|
}
|
@@ -1824,10 +1849,10 @@ _chart_write_a_patt_fill(lxw_chart *self, lxw_chart_pattern *pattern)
|
|
1824
1849
|
|
1825
1850
|
lxw_xml_start_tag(self->file, "a:pattFill", &attributes);
|
1826
1851
|
|
1827
|
-
if (pattern->
|
1852
|
+
if (pattern->fg_color)
|
1828
1853
|
_chart_write_a_fg_clr(self, pattern->fg_color);
|
1829
1854
|
|
1830
|
-
if (pattern->
|
1855
|
+
if (pattern->bg_color)
|
1831
1856
|
_chart_write_a_bg_clr(self, pattern->bg_color);
|
1832
1857
|
|
1833
1858
|
lxw_xml_end_tag(self->file, "a:pattFill");
|
@@ -2268,6 +2293,141 @@ _chart_write_label_num_fmt(lxw_chart *self, char *format)
|
|
2268
2293
|
LXW_FREE_ATTRIBUTES();
|
2269
2294
|
}
|
2270
2295
|
|
2296
|
+
/*
|
2297
|
+
* Write parts of the <c:dLbl> elements where only formatting is changed.
|
2298
|
+
*/
|
2299
|
+
STATIC void
|
2300
|
+
_chart_write_custom_label_format_only(lxw_chart *self,
|
2301
|
+
lxw_chart_custom_label *data_label)
|
2302
|
+
{
|
2303
|
+
if (data_label->line || data_label->fill || data_label->pattern) {
|
2304
|
+
_chart_write_sp_pr(self, data_label->line, data_label->fill,
|
2305
|
+
data_label->pattern);
|
2306
|
+
_chart_write_tx_pr(self, LXW_FALSE, data_label->font);
|
2307
|
+
}
|
2308
|
+
else if (data_label->font) {
|
2309
|
+
lxw_xml_empty_tag(self->file, "c:spPr", NULL);
|
2310
|
+
_chart_write_tx_pr(self, LXW_FALSE, data_label->font);
|
2311
|
+
}
|
2312
|
+
}
|
2313
|
+
|
2314
|
+
/*
|
2315
|
+
* Write parts of the <c:dLbl> elements for formula custom labels.
|
2316
|
+
*/
|
2317
|
+
STATIC void
|
2318
|
+
_chart_write_custom_label_formula(lxw_chart *self, lxw_chart_series *series,
|
2319
|
+
lxw_chart_custom_label *data_label)
|
2320
|
+
{
|
2321
|
+
lxw_xml_empty_tag(self->file, "c:layout", NULL);
|
2322
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
2323
|
+
|
2324
|
+
_chart_write_str_ref(self, data_label->range);
|
2325
|
+
|
2326
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
2327
|
+
|
2328
|
+
_chart_write_custom_label_format_only(self, data_label);
|
2329
|
+
|
2330
|
+
/* Write the c:dLblPos element. */
|
2331
|
+
if (series->label_position)
|
2332
|
+
_chart_write_d_lbl_pos(self, series->label_position);
|
2333
|
+
|
2334
|
+
/* Write the c:showVal element. */
|
2335
|
+
if (series->show_labels_value)
|
2336
|
+
_chart_write_show_val(self);
|
2337
|
+
|
2338
|
+
/* Write the c:showCatName element. */
|
2339
|
+
if (series->show_labels_category)
|
2340
|
+
_chart_write_show_cat_name(self);
|
2341
|
+
|
2342
|
+
/* Write the c:showSerName element. */
|
2343
|
+
if (series->show_labels_name)
|
2344
|
+
_chart_write_show_ser_name(self);
|
2345
|
+
|
2346
|
+
}
|
2347
|
+
|
2348
|
+
/*
|
2349
|
+
* Write parts of the <c:dLbl> elements for string custom labels.
|
2350
|
+
*/
|
2351
|
+
STATIC void
|
2352
|
+
_chart_write_custom_label_str(lxw_chart *self, lxw_chart_series *series,
|
2353
|
+
lxw_chart_custom_label *data_label)
|
2354
|
+
{
|
2355
|
+
uint8_t ignore_rich_pr = LXW_TRUE;
|
2356
|
+
|
2357
|
+
if (data_label->line || data_label->fill || data_label->pattern)
|
2358
|
+
ignore_rich_pr = LXW_FALSE;
|
2359
|
+
|
2360
|
+
lxw_xml_empty_tag(self->file, "c:layout", NULL);
|
2361
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
2362
|
+
|
2363
|
+
/* Write the c:rich element. */
|
2364
|
+
_chart_write_rich(self, data_label->value, data_label->font,
|
2365
|
+
LXW_FALSE, ignore_rich_pr);
|
2366
|
+
|
2367
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
2368
|
+
|
2369
|
+
/* Write the c:spPr element. */
|
2370
|
+
_chart_write_sp_pr(self, data_label->line, data_label->fill,
|
2371
|
+
data_label->pattern);
|
2372
|
+
|
2373
|
+
/* Write the c:dLblPos element. */
|
2374
|
+
if (series->label_position)
|
2375
|
+
_chart_write_d_lbl_pos(self, series->label_position);
|
2376
|
+
|
2377
|
+
/* Write the c:showVal element. */
|
2378
|
+
if (series->show_labels_value)
|
2379
|
+
_chart_write_show_val(self);
|
2380
|
+
|
2381
|
+
/* Write the c:showCatName element. */
|
2382
|
+
if (series->show_labels_category)
|
2383
|
+
_chart_write_show_cat_name(self);
|
2384
|
+
|
2385
|
+
/* Write the c:showSerName element. */
|
2386
|
+
if (series->show_labels_name)
|
2387
|
+
_chart_write_show_ser_name(self);
|
2388
|
+
|
2389
|
+
}
|
2390
|
+
|
2391
|
+
/*
|
2392
|
+
* Write the <c:dLbl> elements for custom labels.
|
2393
|
+
*/
|
2394
|
+
STATIC void
|
2395
|
+
_chart_write_custom_labels(lxw_chart *self, lxw_chart_series *series)
|
2396
|
+
{
|
2397
|
+
uint16_t index = 0;
|
2398
|
+
|
2399
|
+
for (index = 0; index < series->data_label_count; index++) {
|
2400
|
+
lxw_chart_custom_label *data_label = &series->data_labels[index];
|
2401
|
+
|
2402
|
+
if (!data_label->value && !data_label->range && !data_label->hide
|
2403
|
+
&& !data_label->font) {
|
2404
|
+
|
2405
|
+
continue;
|
2406
|
+
}
|
2407
|
+
|
2408
|
+
lxw_xml_start_tag(self->file, "c:dLbl", NULL);
|
2409
|
+
|
2410
|
+
/* Write the c:idx element. */
|
2411
|
+
_chart_write_idx(self, index);
|
2412
|
+
|
2413
|
+
if (data_label->hide) {
|
2414
|
+
/* Write the c:delete element. */
|
2415
|
+
_chart_write_delete(self);
|
2416
|
+
}
|
2417
|
+
else if (data_label->value) {
|
2418
|
+
_chart_write_custom_label_str(self, series, data_label);
|
2419
|
+
}
|
2420
|
+
else if (data_label->range) {
|
2421
|
+
_chart_write_custom_label_formula(self, series, data_label);
|
2422
|
+
}
|
2423
|
+
else if (data_label->font) {
|
2424
|
+
_chart_write_custom_label_format_only(self, data_label);
|
2425
|
+
}
|
2426
|
+
|
2427
|
+
lxw_xml_end_tag(self->file, "c:dLbl");
|
2428
|
+
}
|
2429
|
+
}
|
2430
|
+
|
2271
2431
|
/*
|
2272
2432
|
* Write the <c:dLbls> element.
|
2273
2433
|
*/
|
@@ -2279,10 +2439,17 @@ _chart_write_d_lbls(lxw_chart *self, lxw_chart_series *series)
|
|
2279
2439
|
|
2280
2440
|
lxw_xml_start_tag(self->file, "c:dLbls", NULL);
|
2281
2441
|
|
2442
|
+
if (series->data_labels)
|
2443
|
+
_chart_write_custom_labels(self, series);
|
2444
|
+
|
2282
2445
|
/* Write the c:numFmt element. */
|
2283
2446
|
if (series->label_num_format)
|
2284
2447
|
_chart_write_label_num_fmt(self, series->label_num_format);
|
2285
2448
|
|
2449
|
+
/* Write the c:spPr element. */
|
2450
|
+
_chart_write_sp_pr(self, series->label_line, series->label_fill,
|
2451
|
+
series->label_pattern);
|
2452
|
+
|
2286
2453
|
if (series->label_font)
|
2287
2454
|
_chart_write_tx_pr(self, LXW_FALSE, series->label_font);
|
2288
2455
|
|
@@ -3161,7 +3328,9 @@ _chart_write_crosses(lxw_chart *self, lxw_chart_axis *axis)
|
|
3161
3328
|
|
3162
3329
|
LXW_INIT_ATTRIBUTES();
|
3163
3330
|
|
3164
|
-
if (axis->
|
3331
|
+
if (axis->crossing_min)
|
3332
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "min");
|
3333
|
+
else if (axis->crossing_max)
|
3165
3334
|
LXW_PUSH_ATTRIBUTES_STR("val", "max");
|
3166
3335
|
else
|
3167
3336
|
LXW_PUSH_ATTRIBUTES_STR("val", "autoZero");
|
@@ -3569,7 +3738,7 @@ _chart_write_legend_entry(lxw_chart *self, uint16_t index)
|
|
3569
3738
|
/* Write the c:idx element. */
|
3570
3739
|
_chart_write_idx(self, self->delete_series[index]);
|
3571
3740
|
|
3572
|
-
/* Write the c:
|
3741
|
+
/* Write the c:dst_label element. */
|
3573
3742
|
_chart_write_delete(self);
|
3574
3743
|
|
3575
3744
|
lxw_xml_end_tag(self->file, "c:legendEntry");
|
@@ -4104,7 +4273,8 @@ _chart_write_cat_axis(lxw_chart *self)
|
|
4104
4273
|
_chart_write_cross_axis(self, self->axis_id_2);
|
4105
4274
|
|
4106
4275
|
/* Write the c:crosses element. */
|
4107
|
-
if (!self->y_axis->has_crossing || self->y_axis->
|
4276
|
+
if (!self->y_axis->has_crossing || self->y_axis->crossing_min
|
4277
|
+
|| self->y_axis->crossing_max)
|
4108
4278
|
_chart_write_crosses(self, self->y_axis);
|
4109
4279
|
else
|
4110
4280
|
_chart_write_crosses_at(self, self->y_axis);
|
@@ -4185,7 +4355,8 @@ _chart_write_val_axis(lxw_chart *self)
|
|
4185
4355
|
_chart_write_cross_axis(self, self->axis_id_1);
|
4186
4356
|
|
4187
4357
|
/* Write the c:crosses element. */
|
4188
|
-
if (!self->x_axis->has_crossing || self->x_axis->
|
4358
|
+
if (!self->x_axis->has_crossing || self->x_axis->crossing_min
|
4359
|
+
|| self->x_axis->crossing_max)
|
4189
4360
|
_chart_write_crosses(self, self->x_axis);
|
4190
4361
|
else
|
4191
4362
|
_chart_write_crosses_at(self, self->x_axis);
|
@@ -4263,7 +4434,8 @@ _chart_write_cat_val_axis(lxw_chart *self)
|
|
4263
4434
|
_chart_write_cross_axis(self, self->axis_id_2);
|
4264
4435
|
|
4265
4436
|
/* Write the c:crosses element. */
|
4266
|
-
if (!self->y_axis->has_crossing || self->y_axis->
|
4437
|
+
if (!self->y_axis->has_crossing || self->y_axis->crossing_min
|
4438
|
+
|| self->y_axis->crossing_max)
|
4267
4439
|
_chart_write_crosses(self, self->y_axis);
|
4268
4440
|
else
|
4269
4441
|
_chart_write_crosses_at(self, self->y_axis);
|
@@ -4497,18 +4669,15 @@ _chart_write_scatter_chart(lxw_chart *self)
|
|
4497
4669
|
|
4498
4670
|
/* Add default scatter chart formatting to the series data unless
|
4499
4671
|
* it has already been specified by the user.*/
|
4500
|
-
if (self->type == LXW_CHART_SCATTER) {
|
4501
|
-
|
4502
|
-
|
4503
|
-
|
4504
|
-
|
4505
|
-
|
4506
|
-
|
4507
|
-
|
4508
|
-
|
4509
|
-
};
|
4510
|
-
series->line = _chart_convert_line_args(&line);
|
4511
|
-
}
|
4672
|
+
if (self->type == LXW_CHART_SCATTER && !series->line) {
|
4673
|
+
lxw_chart_line line = {
|
4674
|
+
0x000000,
|
4675
|
+
LXW_TRUE,
|
4676
|
+
2.25,
|
4677
|
+
LXW_CHART_LINE_DASH_SOLID,
|
4678
|
+
0
|
4679
|
+
};
|
4680
|
+
series->line = _chart_convert_line_args(&line);
|
4512
4681
|
}
|
4513
4682
|
|
4514
4683
|
/* Write the c:ser element. */
|
@@ -4797,7 +4966,7 @@ _chart_initialize_doughnut_chart(lxw_chart *self)
|
|
4797
4966
|
* Initialize a line chart.
|
4798
4967
|
*/
|
4799
4968
|
STATIC void
|
4800
|
-
_chart_initialize_line_chart(lxw_chart *self)
|
4969
|
+
_chart_initialize_line_chart(lxw_chart *self, uint8_t type)
|
4801
4970
|
{
|
4802
4971
|
self->chart_group = LXW_CHART_LINE;
|
4803
4972
|
_chart_set_default_marker_type(self, LXW_CHART_MARKER_NONE);
|
@@ -4806,6 +4975,17 @@ _chart_initialize_line_chart(lxw_chart *self)
|
|
4806
4975
|
self->y_axis->is_value = LXW_TRUE;
|
4807
4976
|
self->default_label_position = LXW_CHART_LABEL_POSITION_RIGHT;
|
4808
4977
|
|
4978
|
+
if (type == LXW_CHART_LINE_STACKED) {
|
4979
|
+
self->grouping = LXW_GROUPING_STACKED;
|
4980
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
4981
|
+
}
|
4982
|
+
|
4983
|
+
if (type == LXW_CHART_LINE_STACKED_PERCENT) {
|
4984
|
+
self->grouping = LXW_GROUPING_PERCENTSTACKED;
|
4985
|
+
_chart_axis_set_default_num_format(self->y_axis, "0%");
|
4986
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
4987
|
+
}
|
4988
|
+
|
4809
4989
|
/* Initialize the function pointers for this chart type. */
|
4810
4990
|
self->write_chart_type = _chart_write_line_chart;
|
4811
4991
|
self->write_plot_area = _chart_write_plot_area;
|
@@ -4900,7 +5080,9 @@ _chart_initialize(lxw_chart *self, uint8_t type)
|
|
4900
5080
|
break;
|
4901
5081
|
|
4902
5082
|
case LXW_CHART_LINE:
|
4903
|
-
|
5083
|
+
case LXW_CHART_LINE_STACKED:
|
5084
|
+
case LXW_CHART_LINE_STACKED_PERCENT:
|
5085
|
+
_chart_initialize_line_chart(self, type);
|
4904
5086
|
break;
|
4905
5087
|
|
4906
5088
|
case LXW_CHART_PIE:
|
@@ -4999,7 +5181,7 @@ lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data,
|
|
4999
5181
|
}
|
5000
5182
|
|
5001
5183
|
/*
|
5002
|
-
*
|
5184
|
+
* Add a series to the chart.
|
5003
5185
|
*/
|
5004
5186
|
lxw_chart_series *
|
5005
5187
|
chart_add_series(lxw_chart *self, const char *categories, const char *values)
|
@@ -5306,7 +5488,7 @@ chart_series_set_marker_pattern(lxw_chart_series *series,
|
|
5306
5488
|
}
|
5307
5489
|
|
5308
5490
|
/*
|
5309
|
-
* Store the
|
5491
|
+
* Store the points for a chart.
|
5310
5492
|
*/
|
5311
5493
|
lxw_error
|
5312
5494
|
chart_series_set_points(lxw_chart_series *series, lxw_chart_point *points[])
|
@@ -5375,6 +5557,83 @@ chart_series_set_labels_options(lxw_chart_series *series, uint8_t show_name,
|
|
5375
5557
|
series->show_labels_value = show_value;
|
5376
5558
|
}
|
5377
5559
|
|
5560
|
+
/*
|
5561
|
+
* Store the custom data_labels for a chart.
|
5562
|
+
*/
|
5563
|
+
lxw_error
|
5564
|
+
chart_series_set_labels_custom(lxw_chart_series *series,
|
5565
|
+
lxw_chart_data_label *data_labels[])
|
5566
|
+
{
|
5567
|
+
uint16_t i = 0;
|
5568
|
+
uint16_t data_label_count = 0;
|
5569
|
+
|
5570
|
+
if (data_labels == NULL)
|
5571
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
5572
|
+
|
5573
|
+
while (data_labels[data_label_count])
|
5574
|
+
data_label_count++;
|
5575
|
+
|
5576
|
+
if (data_label_count == 0)
|
5577
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
5578
|
+
|
5579
|
+
series->has_labels = LXW_TRUE;
|
5580
|
+
|
5581
|
+
/* Set the Value label type if no other type is set. */
|
5582
|
+
if (!series->show_labels_name && !series->show_labels_category
|
5583
|
+
&& !series->show_labels_value) {
|
5584
|
+
series->show_labels_value = LXW_TRUE;
|
5585
|
+
}
|
5586
|
+
|
5587
|
+
/* Free any existing resource. */
|
5588
|
+
_chart_free_data_labels(series);
|
5589
|
+
|
5590
|
+
series->data_labels = calloc(data_label_count,
|
5591
|
+
sizeof(lxw_chart_custom_label));
|
5592
|
+
RETURN_ON_MEM_ERROR(series->data_labels, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
5593
|
+
|
5594
|
+
/* Copy the user data into the array of new structs. The struct types
|
5595
|
+
* are different since the internal version has more fields. */
|
5596
|
+
for (i = 0; i < data_label_count; i++) {
|
5597
|
+
lxw_chart_data_label *user_label = data_labels[i];
|
5598
|
+
lxw_chart_custom_label *data_label = &series->data_labels[i];
|
5599
|
+
const char *src_value = user_label->value;
|
5600
|
+
|
5601
|
+
data_label->hide = user_label->hide;
|
5602
|
+
data_label->font = _chart_convert_font_args(user_label->font);
|
5603
|
+
data_label->line = _chart_convert_line_args(user_label->line);
|
5604
|
+
data_label->fill = _chart_convert_fill_args(user_label->fill);
|
5605
|
+
data_label->pattern =
|
5606
|
+
_chart_convert_pattern_args(user_label->pattern);
|
5607
|
+
|
5608
|
+
if (src_value) {
|
5609
|
+
if (*src_value == '=') {
|
5610
|
+
/* The value is a formula. Handle like other chart ranges. */
|
5611
|
+
data_label->range = calloc(1, sizeof(lxw_series_range));
|
5612
|
+
GOTO_LABEL_ON_MEM_ERROR(data_label->range, mem_error);
|
5613
|
+
|
5614
|
+
data_label->range->formula = lxw_strdup(src_value + 1);
|
5615
|
+
|
5616
|
+
/* Add the formula to the data cache to allow value to be looked
|
5617
|
+
* up and filled in when the file is closed. */
|
5618
|
+
if (_chart_init_data_cache(data_label->range) != LXW_NO_ERROR)
|
5619
|
+
goto mem_error;
|
5620
|
+
}
|
5621
|
+
else {
|
5622
|
+
/* The value is a simple string. */
|
5623
|
+
data_label->value = lxw_strdup(src_value);
|
5624
|
+
}
|
5625
|
+
}
|
5626
|
+
}
|
5627
|
+
|
5628
|
+
series->data_label_count = data_label_count;
|
5629
|
+
|
5630
|
+
return LXW_NO_ERROR;
|
5631
|
+
|
5632
|
+
mem_error:
|
5633
|
+
_chart_free_data_labels(series);
|
5634
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
5635
|
+
}
|
5636
|
+
|
5378
5637
|
/*
|
5379
5638
|
* Set the data labels separator for a series.
|
5380
5639
|
*/
|
@@ -5459,6 +5718,52 @@ chart_series_set_labels_font(lxw_chart_series *series, lxw_chart_font *font)
|
|
5459
5718
|
series->label_font = _chart_convert_font_args(font);
|
5460
5719
|
}
|
5461
5720
|
|
5721
|
+
/*
|
5722
|
+
* Set a line type for a series data labels.
|
5723
|
+
*/
|
5724
|
+
void
|
5725
|
+
chart_series_set_labels_line(lxw_chart_series *series, lxw_chart_line *line)
|
5726
|
+
{
|
5727
|
+
if (!line)
|
5728
|
+
return;
|
5729
|
+
|
5730
|
+
/* Free any previously allocated resource. */
|
5731
|
+
free(series->label_line);
|
5732
|
+
|
5733
|
+
series->label_line = _chart_convert_line_args(line);
|
5734
|
+
}
|
5735
|
+
|
5736
|
+
/*
|
5737
|
+
* Set a fill type for a series data labels.
|
5738
|
+
*/
|
5739
|
+
void
|
5740
|
+
chart_series_set_labels_fill(lxw_chart_series *series, lxw_chart_fill *fill)
|
5741
|
+
{
|
5742
|
+
if (!fill)
|
5743
|
+
return;
|
5744
|
+
|
5745
|
+
/* Free any previously allocated resource. */
|
5746
|
+
free(series->label_fill);
|
5747
|
+
|
5748
|
+
series->label_fill = _chart_convert_fill_args(fill);
|
5749
|
+
}
|
5750
|
+
|
5751
|
+
/*
|
5752
|
+
* Set a pattern type for a series data labels.
|
5753
|
+
*/
|
5754
|
+
void
|
5755
|
+
chart_series_set_labels_pattern(lxw_chart_series *series,
|
5756
|
+
lxw_chart_pattern *pattern)
|
5757
|
+
{
|
5758
|
+
if (!pattern)
|
5759
|
+
return;
|
5760
|
+
|
5761
|
+
/* Free any previously allocated resource. */
|
5762
|
+
free(series->label_pattern);
|
5763
|
+
|
5764
|
+
series->label_pattern = _chart_convert_pattern_args(pattern);
|
5765
|
+
}
|
5766
|
+
|
5462
5767
|
/*
|
5463
5768
|
* Set the trendline for a chart series.
|
5464
5769
|
*/
|
@@ -5847,7 +6152,17 @@ chart_axis_set_crossing(lxw_chart_axis *axis, double value)
|
|
5847
6152
|
}
|
5848
6153
|
|
5849
6154
|
/*
|
5850
|
-
* Set the axis crossing position as the
|
6155
|
+
* Set the axis crossing position as the minimum possible value.
|
6156
|
+
*/
|
6157
|
+
void
|
6158
|
+
chart_axis_set_crossing_min(lxw_chart_axis *axis)
|
6159
|
+
{
|
6160
|
+
axis->has_crossing = LXW_TRUE;
|
6161
|
+
axis->crossing_min = LXW_TRUE;
|
6162
|
+
}
|
6163
|
+
|
6164
|
+
/*
|
6165
|
+
* Set the axis crossing position as the maximum possible value.
|
5851
6166
|
*/
|
5852
6167
|
void
|
5853
6168
|
chart_axis_set_crossing_max(lxw_chart_axis *axis)
|