xlsxwriter 0.2.1.pre → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +4 -3
- data/ext/xlsxwriter/chart.c +88 -80
- data/ext/xlsxwriter/chart.h +2 -2
- data/ext/xlsxwriter/chartsheet.c +307 -0
- data/ext/xlsxwriter/chartsheet.h +15 -0
- data/ext/xlsxwriter/common.h +104 -0
- data/ext/xlsxwriter/extconf.rb +8 -8
- data/ext/xlsxwriter/libxlsxwriter/License.txt +24 -2
- data/ext/xlsxwriter/libxlsxwriter/Makefile +46 -12
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/app.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +196 -30
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chartsheet.h +3 -3
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +24 -5
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +5 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/core.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +6 -17
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +20 -6
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/packager.h +3 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +11 -5
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/md5.h +43 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +42 -3
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +83 -18
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +1519 -109
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +3 -2
- data/ext/xlsxwriter/libxlsxwriter/src/Makefile +25 -7
- data/ext/xlsxwriter/libxlsxwriter/src/app.c +1 -1
- data/ext/xlsxwriter/libxlsxwriter/src/chart.c +332 -48
- data/ext/xlsxwriter/libxlsxwriter/src/chartsheet.c +20 -19
- data/ext/xlsxwriter/libxlsxwriter/src/comment.c +443 -0
- data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +20 -1
- data/ext/xlsxwriter/libxlsxwriter/src/core.c +2 -2
- data/ext/xlsxwriter/libxlsxwriter/src/custom.c +1 -1
- data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +58 -20
- data/ext/xlsxwriter/libxlsxwriter/src/format.c +98 -25
- data/ext/xlsxwriter/libxlsxwriter/src/hash_table.c +1 -1
- data/ext/xlsxwriter/libxlsxwriter/src/packager.c +269 -12
- data/ext/xlsxwriter/libxlsxwriter/src/relationships.c +1 -1
- data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +2 -4
- data/ext/xlsxwriter/libxlsxwriter/src/styles.c +334 -48
- data/ext/xlsxwriter/libxlsxwriter/src/theme.c +1 -1
- data/ext/xlsxwriter/libxlsxwriter/src/utility.c +71 -8
- data/ext/xlsxwriter/libxlsxwriter/src/vml.c +1032 -0
- data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +343 -27
- data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +3759 -478
- data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +81 -2
- data/ext/xlsxwriter/libxlsxwriter/third_party/md5/Makefile +42 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/md5/md5.c +291 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/md5/md5.h +43 -0
- data/ext/xlsxwriter/shared_strings.c +65 -0
- data/ext/xlsxwriter/shared_strings.h +15 -0
- data/ext/xlsxwriter/workbook.c +96 -20
- data/ext/xlsxwriter/worksheet.c +125 -235
- data/ext/xlsxwriter/worksheet.h +2 -1
- data/ext/xlsxwriter/xlsxwriter.c +4 -0
- data/lib/xlsxwriter/rich_string.rb +0 -2
- data/lib/xlsxwriter/version.rb +1 -1
- data/lib/xlsxwriter/worksheet.rb +2 -2
- data/test/{run-test.rb → run_test.rb} +3 -3
- data/test/support/chart_test.rb +3 -3
- data/test/support/with_xlsx_file.rb +4 -2
- data/test/support/xlsx_comparable.rb +40 -26
- data/test/test_array_formula.rb +42 -0
- data/test/test_autofilter.rb +72 -0
- data/test/{test-chart-area.rb → test_chart_area.rb} +2 -2
- data/test/{test-chart-axis.rb → test_chart_axis.rb} +16 -16
- data/test/test_chart_bar.rb +382 -0
- data/test/test_chart_blank.rb +27 -0
- data/test/{test-chart-column.rb → test_chart_column.rb} +2 -2
- data/test/{test-chart-doughnut.rb → test_chart_doughnut.rb} +2 -2
- data/test/{test-chart-legend.rb → test_chart_legend.rb} +2 -2
- data/test/{test-chart-pie.rb → test_chart_pie.rb} +2 -2
- data/test/{test-chart-scatter.rb → test_chart_scatter.rb} +3 -4
- data/test/{test-chart-size.rb → test_chart_size.rb} +2 -2
- data/test/{test-chart-title.rb → test_chart_title.rb} +3 -3
- data/test/test_chartsheet.rb +201 -0
- data/test/{test-data.rb → test_data.rb} +1 -1
- data/test/{test-data-validation.rb → test_data_validation.rb} +23 -24
- data/test/{test-default-row.rb → test_default_row.rb} +1 -1
- data/test/{test-defined-name.rb → test_defined_name.rb} +12 -12
- data/test/{test-escapes.rb → test_escapes.rb} +5 -2
- data/test/{test-fit-to-pages.rb → test_fit_to_pages.rb} +6 -6
- data/test/{test-formatting.rb → test_formatting.rb} +10 -10
- data/test/{test-gridlines.rb → test_gridlines.rb} +3 -3
- data/test/{test-hyperlink.rb → test_hyperlink.rb} +22 -11
- data/test/{test-image.rb → test_image.rb} +6 -4
- data/test/{test-macro.rb → test_macro.rb} +1 -1
- data/test/{test-merge-range.rb → test_merge_range.rb} +1 -1
- data/test/{test-misc.rb → test_misc.rb} +2 -2
- data/test/{test-optimize.rb → test_optimize.rb} +2 -4
- data/test/{test-outline.rb → test_outline.rb} +14 -14
- data/test/{test-page-breaks.rb → test_page_breaks.rb} +2 -2
- data/test/{test-page-setup.rb → test_page_setup.rb} +2 -2
- data/test/{test-panes.rb → test_panes.rb} +1 -1
- data/test/{test-print-area.rb → test_print_area.rb} +3 -3
- data/test/{test-print-options.rb → test_print_options.rb} +7 -7
- data/test/{test-print-scale.rb → test_print_scale.rb} +2 -2
- data/test/{test-properties.rb → test_properties.rb} +2 -2
- data/test/{test-protect.rb → test_protect.rb} +3 -3
- data/test/{test-repeat.rb → test_repeat.rb} +3 -3
- data/test/{test-rich-string.rb → test_rich_string.rb} +5 -9
- data/test/{test-row-col-format.rb → test_row_col_format.rb} +1 -1
- data/test/{test-ruby-worksheet.rb → test_ruby_worksheet.rb} +2 -2
- data/test/{test-set-selection.rb → test_set_selection.rb} +2 -2
- data/test/{test-set-start-page.rb → test_set_start_page.rb} +2 -2
- data/test/{test-simple.rb → test_simple.rb} +10 -10
- data/test/{test-types.rb → test_types.rb} +1 -1
- data/test/{xlsx-func-testcase.rb → xlsx_func_testcase.rb} +1 -0
- metadata +135 -104
- data/test/test-array-formula.rb +0 -35
- data/test/test-autofilter.rb +0 -72
- data/test/test-chart-bar.rb +0 -74
- /data/test/{test-errors.rb → test_errors.rb} +0 -0
@@ -3,7 +3,7 @@
|
|
3
3
|
*
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
5
5
|
*
|
6
|
-
* Copyright 2014-
|
6
|
+
* Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
7
7
|
*
|
8
8
|
*/
|
9
9
|
|
@@ -82,6 +82,26 @@ _chart_free_font(lxw_chart_font *font)
|
|
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;
|
@@ -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,22 @@ _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 {
|
1146
|
+
LXW_PUSH_ATTRIBUTES_INT("rot", rotation);
|
1147
|
+
LXW_PUSH_ATTRIBUTES_STR("vert", "horz");
|
1148
|
+
}
|
1149
|
+
}
|
1135
1150
|
|
1136
1151
|
lxw_xml_empty_tag(self->file, "a:bodyPr", &attributes);
|
1137
1152
|
|
@@ -1466,8 +1481,8 @@ _chart_write_axis_font(lxw_chart *self, lxw_chart_font *font)
|
|
1466
1481
|
* Write the <c:rich> element.
|
1467
1482
|
*/
|
1468
1483
|
STATIC void
|
1469
|
-
_chart_write_rich(lxw_chart *self, char *name,
|
1470
|
-
|
1484
|
+
_chart_write_rich(lxw_chart *self, char *name, lxw_chart_font *font,
|
1485
|
+
uint8_t is_horizontal, uint8_t ignore_rich_pr)
|
1471
1486
|
{
|
1472
1487
|
int32_t rotation = 0;
|
1473
1488
|
|
@@ -1483,7 +1498,7 @@ _chart_write_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
|
|
1483
1498
|
_chart_write_a_lst_style(self);
|
1484
1499
|
|
1485
1500
|
/* Write the a:p element. */
|
1486
|
-
_chart_write_a_p_rich(self, name, font);
|
1501
|
+
_chart_write_a_p_rich(self, name, font, ignore_rich_pr);
|
1487
1502
|
|
1488
1503
|
lxw_xml_end_tag(self->file, "c:rich");
|
1489
1504
|
}
|
@@ -1499,7 +1514,7 @@ _chart_write_tx_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
|
|
1499
1514
|
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
1500
1515
|
|
1501
1516
|
/* Write the c:rich element. */
|
1502
|
-
_chart_write_rich(self, name, is_horizontal,
|
1517
|
+
_chart_write_rich(self, name, font, is_horizontal, LXW_FALSE);
|
1503
1518
|
|
1504
1519
|
lxw_xml_end_tag(self->file, "c:tx");
|
1505
1520
|
}
|
@@ -1668,7 +1683,7 @@ _chart_write_a_ln(lxw_chart *self, lxw_chart_line *line)
|
|
1668
1683
|
/* Write the a:noFill element. */
|
1669
1684
|
_chart_write_a_no_fill(self);
|
1670
1685
|
}
|
1671
|
-
else if (line->
|
1686
|
+
else if (line->color) {
|
1672
1687
|
/* Write the a:solidFill element. */
|
1673
1688
|
_chart_write_a_solid_fill(self, line->color, line->transparency);
|
1674
1689
|
}
|
@@ -1824,10 +1839,10 @@ _chart_write_a_patt_fill(lxw_chart *self, lxw_chart_pattern *pattern)
|
|
1824
1839
|
|
1825
1840
|
lxw_xml_start_tag(self->file, "a:pattFill", &attributes);
|
1826
1841
|
|
1827
|
-
if (pattern->
|
1842
|
+
if (pattern->fg_color)
|
1828
1843
|
_chart_write_a_fg_clr(self, pattern->fg_color);
|
1829
1844
|
|
1830
|
-
if (pattern->
|
1845
|
+
if (pattern->bg_color)
|
1831
1846
|
_chart_write_a_bg_clr(self, pattern->bg_color);
|
1832
1847
|
|
1833
1848
|
lxw_xml_end_tag(self->file, "a:pattFill");
|
@@ -2268,6 +2283,133 @@ _chart_write_label_num_fmt(lxw_chart *self, char *format)
|
|
2268
2283
|
LXW_FREE_ATTRIBUTES();
|
2269
2284
|
}
|
2270
2285
|
|
2286
|
+
/*
|
2287
|
+
* Write parts of the <c:dLbl> elements where only formatting is changed.
|
2288
|
+
*/
|
2289
|
+
STATIC void
|
2290
|
+
_chart_write_custom_label_format_only(lxw_chart *self,
|
2291
|
+
lxw_chart_custom_label *data_label)
|
2292
|
+
{
|
2293
|
+
if (data_label->line || data_label->fill || data_label->pattern) {
|
2294
|
+
_chart_write_sp_pr(self, data_label->line, data_label->fill,
|
2295
|
+
data_label->pattern);
|
2296
|
+
_chart_write_tx_pr(self, LXW_FALSE, data_label->font);
|
2297
|
+
}
|
2298
|
+
else if (data_label->font) {
|
2299
|
+
lxw_xml_empty_tag(self->file, "c:spPr", NULL);
|
2300
|
+
_chart_write_tx_pr(self, LXW_FALSE, data_label->font);
|
2301
|
+
}
|
2302
|
+
}
|
2303
|
+
|
2304
|
+
/*
|
2305
|
+
* Write parts of the <c:dLbl> elements for formula custom labels.
|
2306
|
+
*/
|
2307
|
+
STATIC void
|
2308
|
+
_chart_write_custom_label_formula(lxw_chart *self, lxw_chart_series *series,
|
2309
|
+
lxw_chart_custom_label *data_label)
|
2310
|
+
{
|
2311
|
+
lxw_xml_empty_tag(self->file, "c:layout", NULL);
|
2312
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
2313
|
+
|
2314
|
+
_chart_write_str_ref(self, data_label->range);
|
2315
|
+
|
2316
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
2317
|
+
|
2318
|
+
_chart_write_custom_label_format_only(self, data_label);
|
2319
|
+
|
2320
|
+
/* Write the c:showVal element. */
|
2321
|
+
if (series->show_labels_value)
|
2322
|
+
_chart_write_show_val(self);
|
2323
|
+
|
2324
|
+
/* Write the c:showCatName element. */
|
2325
|
+
if (series->show_labels_category)
|
2326
|
+
_chart_write_show_cat_name(self);
|
2327
|
+
|
2328
|
+
/* Write the c:showSerName element. */
|
2329
|
+
if (series->show_labels_name)
|
2330
|
+
_chart_write_show_ser_name(self);
|
2331
|
+
|
2332
|
+
}
|
2333
|
+
|
2334
|
+
/*
|
2335
|
+
* Write parts of the <c:dLbl> elements for string custom labels.
|
2336
|
+
*/
|
2337
|
+
STATIC void
|
2338
|
+
_chart_write_custom_label_str(lxw_chart *self, lxw_chart_series *series,
|
2339
|
+
lxw_chart_custom_label *data_label)
|
2340
|
+
{
|
2341
|
+
uint8_t ignore_rich_pr = LXW_TRUE;
|
2342
|
+
|
2343
|
+
if (data_label->line || data_label->fill || data_label->pattern)
|
2344
|
+
ignore_rich_pr = LXW_FALSE;
|
2345
|
+
|
2346
|
+
lxw_xml_empty_tag(self->file, "c:layout", NULL);
|
2347
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
2348
|
+
|
2349
|
+
/* Write the c:rich element. */
|
2350
|
+
_chart_write_rich(self, data_label->value, data_label->font,
|
2351
|
+
LXW_FALSE, ignore_rich_pr);
|
2352
|
+
|
2353
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
2354
|
+
|
2355
|
+
/* Write the c:spPr element. */
|
2356
|
+
_chart_write_sp_pr(self, data_label->line, data_label->fill,
|
2357
|
+
data_label->pattern);
|
2358
|
+
|
2359
|
+
/* Write the c:showVal element. */
|
2360
|
+
if (series->show_labels_value)
|
2361
|
+
_chart_write_show_val(self);
|
2362
|
+
|
2363
|
+
/* Write the c:showCatName element. */
|
2364
|
+
if (series->show_labels_category)
|
2365
|
+
_chart_write_show_cat_name(self);
|
2366
|
+
|
2367
|
+
/* Write the c:showSerName element. */
|
2368
|
+
if (series->show_labels_name)
|
2369
|
+
_chart_write_show_ser_name(self);
|
2370
|
+
|
2371
|
+
}
|
2372
|
+
|
2373
|
+
/*
|
2374
|
+
* Write the <c:dLbl> elements for custom labels.
|
2375
|
+
*/
|
2376
|
+
STATIC void
|
2377
|
+
_chart_write_custom_labels(lxw_chart *self, lxw_chart_series *series)
|
2378
|
+
{
|
2379
|
+
uint16_t index = 0;
|
2380
|
+
|
2381
|
+
for (index = 0; index < series->data_label_count; index++) {
|
2382
|
+
lxw_chart_custom_label *data_label = &series->data_labels[index];
|
2383
|
+
|
2384
|
+
if (!data_label->value && !data_label->range && !data_label->hide
|
2385
|
+
&& !data_label->font) {
|
2386
|
+
|
2387
|
+
continue;
|
2388
|
+
}
|
2389
|
+
|
2390
|
+
lxw_xml_start_tag(self->file, "c:dLbl", NULL);
|
2391
|
+
|
2392
|
+
/* Write the c:idx element. */
|
2393
|
+
_chart_write_idx(self, index);
|
2394
|
+
|
2395
|
+
if (data_label->hide) {
|
2396
|
+
/* Write the c:delete element. */
|
2397
|
+
_chart_write_delete(self);
|
2398
|
+
}
|
2399
|
+
else if (data_label->value) {
|
2400
|
+
_chart_write_custom_label_str(self, series, data_label);
|
2401
|
+
}
|
2402
|
+
else if (data_label->range) {
|
2403
|
+
_chart_write_custom_label_formula(self, series, data_label);
|
2404
|
+
}
|
2405
|
+
else if (data_label->font) {
|
2406
|
+
_chart_write_custom_label_format_only(self, data_label);
|
2407
|
+
}
|
2408
|
+
|
2409
|
+
lxw_xml_end_tag(self->file, "c:dLbl");
|
2410
|
+
}
|
2411
|
+
}
|
2412
|
+
|
2271
2413
|
/*
|
2272
2414
|
* Write the <c:dLbls> element.
|
2273
2415
|
*/
|
@@ -2279,10 +2421,17 @@ _chart_write_d_lbls(lxw_chart *self, lxw_chart_series *series)
|
|
2279
2421
|
|
2280
2422
|
lxw_xml_start_tag(self->file, "c:dLbls", NULL);
|
2281
2423
|
|
2424
|
+
if (series->data_labels)
|
2425
|
+
_chart_write_custom_labels(self, series);
|
2426
|
+
|
2282
2427
|
/* Write the c:numFmt element. */
|
2283
2428
|
if (series->label_num_format)
|
2284
2429
|
_chart_write_label_num_fmt(self, series->label_num_format);
|
2285
2430
|
|
2431
|
+
/* Write the c:spPr element. */
|
2432
|
+
_chart_write_sp_pr(self, series->label_line, series->label_fill,
|
2433
|
+
series->label_pattern);
|
2434
|
+
|
2286
2435
|
if (series->label_font)
|
2287
2436
|
_chart_write_tx_pr(self, LXW_FALSE, series->label_font);
|
2288
2437
|
|
@@ -3569,7 +3718,7 @@ _chart_write_legend_entry(lxw_chart *self, uint16_t index)
|
|
3569
3718
|
/* Write the c:idx element. */
|
3570
3719
|
_chart_write_idx(self, self->delete_series[index]);
|
3571
3720
|
|
3572
|
-
/* Write the c:
|
3721
|
+
/* Write the c:dst_label element. */
|
3573
3722
|
_chart_write_delete(self);
|
3574
3723
|
|
3575
3724
|
lxw_xml_end_tag(self->file, "c:legendEntry");
|
@@ -4504,8 +4653,7 @@ _chart_write_scatter_chart(lxw_chart *self)
|
|
4504
4653
|
LXW_TRUE,
|
4505
4654
|
2.25,
|
4506
4655
|
LXW_CHART_LINE_DASH_SOLID,
|
4507
|
-
0
|
4508
|
-
LXW_FALSE
|
4656
|
+
0
|
4509
4657
|
};
|
4510
4658
|
series->line = _chart_convert_line_args(&line);
|
4511
4659
|
}
|
@@ -4797,7 +4945,7 @@ _chart_initialize_doughnut_chart(lxw_chart *self)
|
|
4797
4945
|
* Initialize a line chart.
|
4798
4946
|
*/
|
4799
4947
|
STATIC void
|
4800
|
-
_chart_initialize_line_chart(lxw_chart *self)
|
4948
|
+
_chart_initialize_line_chart(lxw_chart *self, uint8_t type)
|
4801
4949
|
{
|
4802
4950
|
self->chart_group = LXW_CHART_LINE;
|
4803
4951
|
_chart_set_default_marker_type(self, LXW_CHART_MARKER_NONE);
|
@@ -4806,6 +4954,17 @@ _chart_initialize_line_chart(lxw_chart *self)
|
|
4806
4954
|
self->y_axis->is_value = LXW_TRUE;
|
4807
4955
|
self->default_label_position = LXW_CHART_LABEL_POSITION_RIGHT;
|
4808
4956
|
|
4957
|
+
if (type == LXW_CHART_LINE_STACKED) {
|
4958
|
+
self->grouping = LXW_GROUPING_STACKED;
|
4959
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
4960
|
+
}
|
4961
|
+
|
4962
|
+
if (type == LXW_CHART_LINE_STACKED_PERCENT) {
|
4963
|
+
self->grouping = LXW_GROUPING_PERCENTSTACKED;
|
4964
|
+
_chart_axis_set_default_num_format(self->y_axis, "0%");
|
4965
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
4966
|
+
}
|
4967
|
+
|
4809
4968
|
/* Initialize the function pointers for this chart type. */
|
4810
4969
|
self->write_chart_type = _chart_write_line_chart;
|
4811
4970
|
self->write_plot_area = _chart_write_plot_area;
|
@@ -4900,7 +5059,9 @@ _chart_initialize(lxw_chart *self, uint8_t type)
|
|
4900
5059
|
break;
|
4901
5060
|
|
4902
5061
|
case LXW_CHART_LINE:
|
4903
|
-
|
5062
|
+
case LXW_CHART_LINE_STACKED:
|
5063
|
+
case LXW_CHART_LINE_STACKED_PERCENT:
|
5064
|
+
_chart_initialize_line_chart(self, type);
|
4904
5065
|
break;
|
4905
5066
|
|
4906
5067
|
case LXW_CHART_PIE:
|
@@ -4999,7 +5160,7 @@ lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data,
|
|
4999
5160
|
}
|
5000
5161
|
|
5001
5162
|
/*
|
5002
|
-
*
|
5163
|
+
* Add a series to the chart.
|
5003
5164
|
*/
|
5004
5165
|
lxw_chart_series *
|
5005
5166
|
chart_add_series(lxw_chart *self, const char *categories, const char *values)
|
@@ -5306,7 +5467,7 @@ chart_series_set_marker_pattern(lxw_chart_series *series,
|
|
5306
5467
|
}
|
5307
5468
|
|
5308
5469
|
/*
|
5309
|
-
* Store the
|
5470
|
+
* Store the points for a chart.
|
5310
5471
|
*/
|
5311
5472
|
lxw_error
|
5312
5473
|
chart_series_set_points(lxw_chart_series *series, lxw_chart_point *points[])
|
@@ -5375,6 +5536,83 @@ chart_series_set_labels_options(lxw_chart_series *series, uint8_t show_name,
|
|
5375
5536
|
series->show_labels_value = show_value;
|
5376
5537
|
}
|
5377
5538
|
|
5539
|
+
/*
|
5540
|
+
* Store the custom data_labels for a chart.
|
5541
|
+
*/
|
5542
|
+
lxw_error
|
5543
|
+
chart_series_set_labels_custom(lxw_chart_series *series,
|
5544
|
+
lxw_chart_data_label *data_labels[])
|
5545
|
+
{
|
5546
|
+
uint16_t i = 0;
|
5547
|
+
uint16_t data_label_count = 0;
|
5548
|
+
|
5549
|
+
if (data_labels == NULL)
|
5550
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
5551
|
+
|
5552
|
+
while (data_labels[data_label_count])
|
5553
|
+
data_label_count++;
|
5554
|
+
|
5555
|
+
if (data_label_count == 0)
|
5556
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
5557
|
+
|
5558
|
+
series->has_labels = LXW_TRUE;
|
5559
|
+
|
5560
|
+
/* Set the Value label type if no other type is set. */
|
5561
|
+
if (!series->show_labels_name && !series->show_labels_category
|
5562
|
+
&& !series->show_labels_value) {
|
5563
|
+
series->show_labels_value = LXW_TRUE;
|
5564
|
+
}
|
5565
|
+
|
5566
|
+
/* Free any existing resource. */
|
5567
|
+
_chart_free_data_labels(series);
|
5568
|
+
|
5569
|
+
series->data_labels = calloc(data_label_count,
|
5570
|
+
sizeof(lxw_chart_custom_label));
|
5571
|
+
RETURN_ON_MEM_ERROR(series->data_labels, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
5572
|
+
|
5573
|
+
/* Copy the user data into the array of new structs. The struct types
|
5574
|
+
* are different since the internal version has more fields. */
|
5575
|
+
for (i = 0; i < data_label_count; i++) {
|
5576
|
+
lxw_chart_data_label *user_label = data_labels[i];
|
5577
|
+
lxw_chart_custom_label *data_label = &series->data_labels[i];
|
5578
|
+
char *src_value = user_label->value;
|
5579
|
+
|
5580
|
+
data_label->hide = user_label->hide;
|
5581
|
+
data_label->font = _chart_convert_font_args(user_label->font);
|
5582
|
+
data_label->line = _chart_convert_line_args(user_label->line);
|
5583
|
+
data_label->fill = _chart_convert_fill_args(user_label->fill);
|
5584
|
+
data_label->pattern =
|
5585
|
+
_chart_convert_pattern_args(user_label->pattern);
|
5586
|
+
|
5587
|
+
if (src_value) {
|
5588
|
+
if (*src_value == '=') {
|
5589
|
+
/* The value is a formula. Handle like other chart ranges. */
|
5590
|
+
data_label->range = calloc(1, sizeof(lxw_series_range));
|
5591
|
+
GOTO_LABEL_ON_MEM_ERROR(data_label->range, mem_error);
|
5592
|
+
|
5593
|
+
data_label->range->formula = lxw_strdup(src_value + 1);
|
5594
|
+
|
5595
|
+
/* Add the formula to the data cache to allow value to be looked
|
5596
|
+
* up and filled in when the file is closed. */
|
5597
|
+
if (_chart_init_data_cache(data_label->range) != LXW_NO_ERROR)
|
5598
|
+
goto mem_error;
|
5599
|
+
}
|
5600
|
+
else {
|
5601
|
+
/* The value is a simple string. */
|
5602
|
+
data_label->value = lxw_strdup(src_value);
|
5603
|
+
}
|
5604
|
+
}
|
5605
|
+
}
|
5606
|
+
|
5607
|
+
series->data_label_count = data_label_count;
|
5608
|
+
|
5609
|
+
return LXW_NO_ERROR;
|
5610
|
+
|
5611
|
+
mem_error:
|
5612
|
+
_chart_free_data_labels(series);
|
5613
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
5614
|
+
}
|
5615
|
+
|
5378
5616
|
/*
|
5379
5617
|
* Set the data labels separator for a series.
|
5380
5618
|
*/
|
@@ -5459,6 +5697,52 @@ chart_series_set_labels_font(lxw_chart_series *series, lxw_chart_font *font)
|
|
5459
5697
|
series->label_font = _chart_convert_font_args(font);
|
5460
5698
|
}
|
5461
5699
|
|
5700
|
+
/*
|
5701
|
+
* Set a line type for a series data labels.
|
5702
|
+
*/
|
5703
|
+
void
|
5704
|
+
chart_series_set_labels_line(lxw_chart_series *series, lxw_chart_line *line)
|
5705
|
+
{
|
5706
|
+
if (!line)
|
5707
|
+
return;
|
5708
|
+
|
5709
|
+
/* Free any previously allocated resource. */
|
5710
|
+
free(series->label_line);
|
5711
|
+
|
5712
|
+
series->label_line = _chart_convert_line_args(line);
|
5713
|
+
}
|
5714
|
+
|
5715
|
+
/*
|
5716
|
+
* Set a fill type for a series data labels.
|
5717
|
+
*/
|
5718
|
+
void
|
5719
|
+
chart_series_set_labels_fill(lxw_chart_series *series, lxw_chart_fill *fill)
|
5720
|
+
{
|
5721
|
+
if (!fill)
|
5722
|
+
return;
|
5723
|
+
|
5724
|
+
/* Free any previously allocated resource. */
|
5725
|
+
free(series->label_fill);
|
5726
|
+
|
5727
|
+
series->label_fill = _chart_convert_fill_args(fill);
|
5728
|
+
}
|
5729
|
+
|
5730
|
+
/*
|
5731
|
+
* Set a pattern type for a series data labels.
|
5732
|
+
*/
|
5733
|
+
void
|
5734
|
+
chart_series_set_labels_pattern(lxw_chart_series *series,
|
5735
|
+
lxw_chart_pattern *pattern)
|
5736
|
+
{
|
5737
|
+
if (!pattern)
|
5738
|
+
return;
|
5739
|
+
|
5740
|
+
/* Free any previously allocated resource. */
|
5741
|
+
free(series->label_pattern);
|
5742
|
+
|
5743
|
+
series->label_pattern = _chart_convert_pattern_args(pattern);
|
5744
|
+
}
|
5745
|
+
|
5462
5746
|
/*
|
5463
5747
|
* Set the trendline for a chart series.
|
5464
5748
|
*/
|
@@ -3,7 +3,7 @@
|
|
3
3
|
*
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
5
5
|
*
|
6
|
-
* Copyright 2014-
|
6
|
+
* Copyright 2014-2020, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
7
7
|
*
|
8
8
|
*/
|
9
9
|
|
@@ -225,9 +225,9 @@ lxw_chartsheet_assemble_xml_file(lxw_chartsheet *self)
|
|
225
225
|
*/
|
226
226
|
lxw_error
|
227
227
|
chartsheet_set_chart_opt(lxw_chartsheet *self,
|
228
|
-
lxw_chart *chart,
|
228
|
+
lxw_chart *chart, lxw_chart_options *user_options)
|
229
229
|
{
|
230
|
-
|
230
|
+
lxw_object_properties *object_props;
|
231
231
|
lxw_chart_series *series;
|
232
232
|
|
233
233
|
if (!chart) {
|
@@ -260,32 +260,33 @@ chartsheet_set_chart_opt(lxw_chartsheet *self,
|
|
260
260
|
}
|
261
261
|
}
|
262
262
|
|
263
|
-
/* Create a new object to hold the chart image
|
264
|
-
|
265
|
-
RETURN_ON_MEM_ERROR(
|
263
|
+
/* Create a new object to hold the chart image properties. */
|
264
|
+
object_props = calloc(1, sizeof(lxw_object_properties));
|
265
|
+
RETURN_ON_MEM_ERROR(object_props, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
266
266
|
|
267
267
|
if (user_options) {
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
268
|
+
object_props->x_offset = user_options->x_offset;
|
269
|
+
object_props->y_offset = user_options->y_offset;
|
270
|
+
object_props->x_scale = user_options->x_scale;
|
271
|
+
object_props->y_scale = user_options->y_scale;
|
272
272
|
}
|
273
273
|
|
274
274
|
/* TODO. Read defaults from chart. */
|
275
|
-
|
276
|
-
|
275
|
+
object_props->width = 480;
|
276
|
+
object_props->height = 288;
|
277
277
|
|
278
|
-
if (!
|
279
|
-
|
278
|
+
if (!object_props->x_scale)
|
279
|
+
object_props->x_scale = 1;
|
280
280
|
|
281
|
-
if (!
|
282
|
-
|
281
|
+
if (!object_props->y_scale)
|
282
|
+
object_props->y_scale = 1;
|
283
283
|
|
284
284
|
/* Store chart references so they can be ordered in the workbook. */
|
285
|
-
|
285
|
+
object_props->chart = chart;
|
286
286
|
|
287
287
|
/* Store the chart data in the embedded worksheet. */
|
288
|
-
STAILQ_INSERT_TAIL(self->worksheet->chart_data,
|
288
|
+
STAILQ_INSERT_TAIL(self->worksheet->chart_data, object_props,
|
289
|
+
list_pointers);
|
289
290
|
|
290
291
|
chart->in_use = LXW_TRUE;
|
291
292
|
chart->is_chartsheet = LXW_TRUE;
|
@@ -385,7 +386,7 @@ void
|
|
385
386
|
chartsheet_protect(lxw_chartsheet *self, const char *password,
|
386
387
|
lxw_protection *options)
|
387
388
|
{
|
388
|
-
struct
|
389
|
+
struct lxw_protection_obj *protect = &self->protection;
|
389
390
|
|
390
391
|
/* Copy any user parameters to the internal structure. */
|
391
392
|
if (options) {
|