xlsxwriter 0.0.2
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 +7 -0
- data/Rakefile +40 -0
- data/ext/xlsxwriter/chart.c +105 -0
- data/ext/xlsxwriter/chart.h +27 -0
- data/ext/xlsxwriter/extconf.rb +14 -0
- data/ext/xlsxwriter/format.c +67 -0
- data/ext/xlsxwriter/format.h +9 -0
- data/ext/xlsxwriter/libxlsxwriter/LICENSE.txt +89 -0
- data/ext/xlsxwriter/libxlsxwriter/Makefile +141 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter.h +23 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/app.h +79 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/chart.h +1093 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/common.h +336 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/core.h +51 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +215 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/workbook.h +751 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
- data/ext/xlsxwriter/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
- data/ext/xlsxwriter/libxlsxwriter/lib/.gitignore +0 -0
- data/ext/xlsxwriter/libxlsxwriter/src/Makefile +125 -0
- data/ext/xlsxwriter/libxlsxwriter/src/app.c +439 -0
- data/ext/xlsxwriter/libxlsxwriter/src/chart.c +3420 -0
- data/ext/xlsxwriter/libxlsxwriter/src/content_types.c +341 -0
- data/ext/xlsxwriter/libxlsxwriter/src/core.c +293 -0
- data/ext/xlsxwriter/libxlsxwriter/src/custom.c +224 -0
- data/ext/xlsxwriter/libxlsxwriter/src/drawing.c +746 -0
- data/ext/xlsxwriter/libxlsxwriter/src/format.c +728 -0
- data/ext/xlsxwriter/libxlsxwriter/src/hash_table.c +223 -0
- data/ext/xlsxwriter/libxlsxwriter/src/packager.c +877 -0
- data/ext/xlsxwriter/libxlsxwriter/src/relationships.c +242 -0
- data/ext/xlsxwriter/libxlsxwriter/src/shared_strings.c +264 -0
- data/ext/xlsxwriter/libxlsxwriter/src/styles.c +1086 -0
- data/ext/xlsxwriter/libxlsxwriter/src/theme.c +348 -0
- data/ext/xlsxwriter/libxlsxwriter/src/utility.c +512 -0
- data/ext/xlsxwriter/libxlsxwriter/src/workbook.c +1895 -0
- data/ext/xlsxwriter/libxlsxwriter/src/worksheet.c +4992 -0
- data/ext/xlsxwriter/libxlsxwriter/src/xmlwriter.c +355 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/Makefile +44 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/crypt.h +131 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/ioapi.h +209 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/minizip.c +520 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/mztools.c +291 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/mztools.h +37 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/unzip.h +437 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.c +2007 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/minizip/zip.h +367 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
- data/ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
- data/ext/xlsxwriter/workbook.c +257 -0
- data/ext/xlsxwriter/workbook.h +42 -0
- data/ext/xlsxwriter/workbook_properties.c +103 -0
- data/ext/xlsxwriter/workbook_properties.h +10 -0
- data/ext/xlsxwriter/worksheet.c +1064 -0
- data/ext/xlsxwriter/worksheet.h +74 -0
- data/ext/xlsxwriter/xlsxwriter.c +239 -0
- data/lib/xlsxwriter.rb +6 -0
- data/lib/xlsxwriter/version.rb +3 -0
- data/lib/xlsxwriter/worksheet.rb +72 -0
- data/test/run-test.rb +11 -0
- data/test/support/xlsx_comparable.rb +109 -0
- data/test/test-array-formula.rb +33 -0
- data/test/test-autofilter.rb +70 -0
- data/test/test-chart-area.rb +25 -0
- data/test/test-data.rb +65 -0
- data/test/test-default-row.rb +25 -0
- data/test/test-defined-name.rb +46 -0
- data/test/test-escapes.rb +33 -0
- data/test/test-fit-to-pages.rb +21 -0
- data/test/test-formatting.rb +137 -0
- data/test/test-gridlines.rb +15 -0
- data/test/test-hyperlink.rb +67 -0
- data/test/test-image.rb +84 -0
- data/test/test-merge-range.rb +18 -0
- data/test/test-misc.rb +29 -0
- data/test/test-optimize.rb +32 -0
- data/test/test-page-breaks.rb +13 -0
- data/test/test-page-setup.rb +28 -0
- data/test/test-panes.rb +45 -0
- data/test/test-print-area.rb +19 -0
- data/test/test-print-options.rb +61 -0
- data/test/test-print-scale.rb +12 -0
- data/test/test-properties.rb +51 -0
- data/test/test-protect.rb +27 -0
- data/test/test-repeat.rb +23 -0
- data/test/test-row-col-format.rb +35 -0
- data/test/test-set-selection.rb +13 -0
- data/test/test-set-start-page.rb +13 -0
- data/test/test-simple.rb +62 -0
- data/test/test-types.rb +17 -0
- data/test/xlsx-func-testcase.rb +36 -0
- metadata +228 -0
|
@@ -0,0 +1,3420 @@
|
|
|
1
|
+
/*****************************************************************************
|
|
2
|
+
* chart - A library for creating Excel XLSX chart files.
|
|
3
|
+
*
|
|
4
|
+
* Used in conjunction with the libxlsxwriter library.
|
|
5
|
+
*
|
|
6
|
+
* Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#include "xlsxwriter/xmlwriter.h"
|
|
11
|
+
#include "xlsxwriter/chart.h"
|
|
12
|
+
#include "xlsxwriter/utility.h"
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* Forward declarations.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/*****************************************************************************
|
|
19
|
+
*
|
|
20
|
+
* Private functions.
|
|
21
|
+
*
|
|
22
|
+
****************************************************************************/
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Free a series range object.
|
|
26
|
+
*/
|
|
27
|
+
STATIC void
|
|
28
|
+
_chart_free_range(lxw_series_range *range)
|
|
29
|
+
{
|
|
30
|
+
struct lxw_series_data_point *data_point;
|
|
31
|
+
|
|
32
|
+
if (!range)
|
|
33
|
+
return;
|
|
34
|
+
|
|
35
|
+
while (!STAILQ_EMPTY(range->data_cache)) {
|
|
36
|
+
data_point = STAILQ_FIRST(range->data_cache);
|
|
37
|
+
free(data_point->string);
|
|
38
|
+
STAILQ_REMOVE_HEAD(range->data_cache, list_pointers);
|
|
39
|
+
|
|
40
|
+
free(data_point);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
free(range->data_cache);
|
|
44
|
+
free(range->formula);
|
|
45
|
+
free(range->sheetname);
|
|
46
|
+
free(range);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
* Free a series object.
|
|
51
|
+
*/
|
|
52
|
+
STATIC void
|
|
53
|
+
_chart_series_free(lxw_chart_series *series)
|
|
54
|
+
{
|
|
55
|
+
if (!series)
|
|
56
|
+
return;
|
|
57
|
+
|
|
58
|
+
free(series->title.name);
|
|
59
|
+
free(series->line);
|
|
60
|
+
free(series->fill);
|
|
61
|
+
|
|
62
|
+
_chart_free_range(series->categories);
|
|
63
|
+
_chart_free_range(series->values);
|
|
64
|
+
_chart_free_range(series->title.range);
|
|
65
|
+
|
|
66
|
+
free(series);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/*
|
|
70
|
+
* Initialize the data cache in a range object.
|
|
71
|
+
*/
|
|
72
|
+
STATIC int
|
|
73
|
+
_chart_init_data_cache(lxw_series_range *range)
|
|
74
|
+
{
|
|
75
|
+
/* Initialize the series range data cache. */
|
|
76
|
+
range->data_cache = calloc(1, sizeof(struct lxw_series_data_points));
|
|
77
|
+
RETURN_ON_MEM_ERROR(range->data_cache, -1);
|
|
78
|
+
STAILQ_INIT(range->data_cache);
|
|
79
|
+
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* Free a chart font object.
|
|
85
|
+
*/
|
|
86
|
+
STATIC void
|
|
87
|
+
_chart_free_font(lxw_chart_font *font)
|
|
88
|
+
{
|
|
89
|
+
if (!font)
|
|
90
|
+
return;
|
|
91
|
+
|
|
92
|
+
free(font->name);
|
|
93
|
+
free(font);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/*
|
|
97
|
+
* Free a chart object.
|
|
98
|
+
*/
|
|
99
|
+
void
|
|
100
|
+
lxw_chart_free(lxw_chart *chart)
|
|
101
|
+
{
|
|
102
|
+
lxw_chart_series *series;
|
|
103
|
+
|
|
104
|
+
if (!chart)
|
|
105
|
+
return;
|
|
106
|
+
|
|
107
|
+
/* Chart series. */
|
|
108
|
+
if (chart->series_list) {
|
|
109
|
+
while (!STAILQ_EMPTY(chart->series_list)) {
|
|
110
|
+
series = STAILQ_FIRST(chart->series_list);
|
|
111
|
+
STAILQ_REMOVE_HEAD(chart->series_list, list_pointers);
|
|
112
|
+
|
|
113
|
+
_chart_series_free(series);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
free(chart->series_list);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* X Axis. */
|
|
120
|
+
if (chart->x_axis) {
|
|
121
|
+
_chart_free_font(chart->x_axis->title.font);
|
|
122
|
+
_chart_free_font(chart->x_axis->num_font);
|
|
123
|
+
_chart_free_range(chart->x_axis->title.range);
|
|
124
|
+
free(chart->x_axis->title.name);
|
|
125
|
+
free(chart->x_axis->line);
|
|
126
|
+
free(chart->x_axis->fill);
|
|
127
|
+
free(chart->x_axis);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Y Axis. */
|
|
131
|
+
if (chart->y_axis) {
|
|
132
|
+
_chart_free_font(chart->y_axis->title.font);
|
|
133
|
+
_chart_free_font(chart->y_axis->num_font);
|
|
134
|
+
_chart_free_range(chart->y_axis->title.range);
|
|
135
|
+
free(chart->y_axis->title.name);
|
|
136
|
+
free(chart->y_axis->line);
|
|
137
|
+
free(chart->y_axis->fill);
|
|
138
|
+
free(chart->y_axis);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Chart title. */
|
|
142
|
+
_chart_free_font(chart->title.font);
|
|
143
|
+
_chart_free_range(chart->title.range);
|
|
144
|
+
free(chart->title.name);
|
|
145
|
+
|
|
146
|
+
/* Chart legend. */
|
|
147
|
+
_chart_free_font(chart->legend.font);
|
|
148
|
+
free(chart->delete_series);
|
|
149
|
+
|
|
150
|
+
free(chart);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/*
|
|
154
|
+
* Create a new chart object.
|
|
155
|
+
*/
|
|
156
|
+
lxw_chart *
|
|
157
|
+
lxw_chart_new(uint8_t type)
|
|
158
|
+
{
|
|
159
|
+
lxw_chart *chart = calloc(1, sizeof(lxw_chart));
|
|
160
|
+
GOTO_LABEL_ON_MEM_ERROR(chart, mem_error);
|
|
161
|
+
|
|
162
|
+
chart->series_list = calloc(1, sizeof(struct lxw_chart_series_list));
|
|
163
|
+
GOTO_LABEL_ON_MEM_ERROR(chart->series_list, mem_error);
|
|
164
|
+
STAILQ_INIT(chart->series_list);
|
|
165
|
+
|
|
166
|
+
chart->x_axis = calloc(1, sizeof(struct lxw_chart_axis));
|
|
167
|
+
GOTO_LABEL_ON_MEM_ERROR(chart->x_axis, mem_error);
|
|
168
|
+
|
|
169
|
+
chart->y_axis = calloc(1, sizeof(struct lxw_chart_axis));
|
|
170
|
+
GOTO_LABEL_ON_MEM_ERROR(chart->y_axis, mem_error);
|
|
171
|
+
|
|
172
|
+
chart->title.range = calloc(1, sizeof(lxw_series_range));
|
|
173
|
+
GOTO_LABEL_ON_MEM_ERROR(chart->title.range, mem_error);
|
|
174
|
+
|
|
175
|
+
chart->x_axis->title.range = calloc(1, sizeof(lxw_series_range));
|
|
176
|
+
GOTO_LABEL_ON_MEM_ERROR(chart->x_axis->title.range, mem_error);
|
|
177
|
+
|
|
178
|
+
chart->y_axis->title.range = calloc(1, sizeof(lxw_series_range));
|
|
179
|
+
GOTO_LABEL_ON_MEM_ERROR(chart->y_axis->title.range, mem_error);
|
|
180
|
+
|
|
181
|
+
/* Initialize the ranges in the chart titles. */
|
|
182
|
+
if (_chart_init_data_cache(chart->title.range) != LXW_NO_ERROR)
|
|
183
|
+
goto mem_error;
|
|
184
|
+
|
|
185
|
+
if (_chart_init_data_cache(chart->x_axis->title.range) != LXW_NO_ERROR)
|
|
186
|
+
goto mem_error;
|
|
187
|
+
|
|
188
|
+
if (_chart_init_data_cache(chart->y_axis->title.range) != LXW_NO_ERROR)
|
|
189
|
+
goto mem_error;
|
|
190
|
+
|
|
191
|
+
chart->type = type;
|
|
192
|
+
chart->style_id = 2;
|
|
193
|
+
chart->hole_size = 50;
|
|
194
|
+
|
|
195
|
+
/* Set the default axis positions. */
|
|
196
|
+
chart->cat_axis_position = LXW_CHART_AXIS_BOTTOM;
|
|
197
|
+
chart->val_axis_position = LXW_CHART_AXIS_LEFT;
|
|
198
|
+
|
|
199
|
+
lxw_strcpy(chart->x_axis->default_num_format, "General");
|
|
200
|
+
lxw_strcpy(chart->y_axis->default_num_format, "General");
|
|
201
|
+
|
|
202
|
+
chart->x_axis->default_major_gridlines = LXW_FALSE;
|
|
203
|
+
chart->y_axis->default_major_gridlines = LXW_TRUE;
|
|
204
|
+
|
|
205
|
+
chart->series_overlap_1 = 100;
|
|
206
|
+
|
|
207
|
+
chart->has_horiz_cat_axis = LXW_FALSE;
|
|
208
|
+
chart->has_horiz_val_axis = LXW_TRUE;
|
|
209
|
+
|
|
210
|
+
chart->legend.position = LXW_CHART_LEGEND_RIGHT;
|
|
211
|
+
|
|
212
|
+
return chart;
|
|
213
|
+
|
|
214
|
+
mem_error:
|
|
215
|
+
lxw_chart_free(chart);
|
|
216
|
+
return NULL;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/*
|
|
220
|
+
* Create a copy of a user supplied font.
|
|
221
|
+
*/
|
|
222
|
+
STATIC lxw_chart_font *
|
|
223
|
+
_chart_convert_font_args(lxw_chart_font *user_font)
|
|
224
|
+
{
|
|
225
|
+
lxw_chart_font *font;
|
|
226
|
+
|
|
227
|
+
if (!user_font)
|
|
228
|
+
return NULL;
|
|
229
|
+
|
|
230
|
+
font = calloc(1, sizeof(struct lxw_chart_font));
|
|
231
|
+
RETURN_ON_MEM_ERROR(font, NULL);
|
|
232
|
+
|
|
233
|
+
memcpy(font, user_font, sizeof(lxw_chart_font));
|
|
234
|
+
|
|
235
|
+
font->name = lxw_strdup(user_font->name);
|
|
236
|
+
|
|
237
|
+
/* Convert font size units. */
|
|
238
|
+
if (font->size)
|
|
239
|
+
font->size = font->size * 100;
|
|
240
|
+
|
|
241
|
+
/* Convert rotation into 60,000ths of a degree. */
|
|
242
|
+
if (font->rotation)
|
|
243
|
+
font->rotation = font->rotation * 60000;
|
|
244
|
+
|
|
245
|
+
if (font->color) {
|
|
246
|
+
font->color = lxw_format_check_color(font->color);
|
|
247
|
+
font->has_color = LXW_TRUE;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return font;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/*
|
|
254
|
+
* Create a copy of a user supplied line.
|
|
255
|
+
*/
|
|
256
|
+
STATIC lxw_chart_line *
|
|
257
|
+
_chart_convert_line_args(lxw_chart_line *user_line)
|
|
258
|
+
{
|
|
259
|
+
lxw_chart_line *line;
|
|
260
|
+
|
|
261
|
+
if (!user_line)
|
|
262
|
+
return NULL;
|
|
263
|
+
|
|
264
|
+
line = calloc(1, sizeof(struct lxw_chart_line));
|
|
265
|
+
RETURN_ON_MEM_ERROR(line, NULL);
|
|
266
|
+
|
|
267
|
+
memcpy(line, user_line, sizeof(lxw_chart_line));
|
|
268
|
+
|
|
269
|
+
if (line->color) {
|
|
270
|
+
line->color = lxw_format_check_color(line->color);
|
|
271
|
+
line->has_color = LXW_TRUE;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (line->transparency > 100)
|
|
275
|
+
line->transparency = 0;
|
|
276
|
+
|
|
277
|
+
return line;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/*
|
|
281
|
+
* Create a copy of a user supplied fill.
|
|
282
|
+
*/
|
|
283
|
+
STATIC lxw_chart_fill *
|
|
284
|
+
_chart_convert_fill_args(lxw_chart_fill *user_fill)
|
|
285
|
+
{
|
|
286
|
+
lxw_chart_fill *fill;
|
|
287
|
+
|
|
288
|
+
if (!user_fill)
|
|
289
|
+
return NULL;
|
|
290
|
+
|
|
291
|
+
fill = calloc(1, sizeof(struct lxw_chart_fill));
|
|
292
|
+
RETURN_ON_MEM_ERROR(fill, NULL);
|
|
293
|
+
|
|
294
|
+
memcpy(fill, user_fill, sizeof(lxw_chart_fill));
|
|
295
|
+
|
|
296
|
+
if (fill->color) {
|
|
297
|
+
fill->color = lxw_format_check_color(fill->color);
|
|
298
|
+
fill->has_color = LXW_TRUE;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (fill->transparency > 100)
|
|
302
|
+
fill->transparency = 0;
|
|
303
|
+
|
|
304
|
+
return fill;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/*
|
|
308
|
+
* Add unique ids for primary or secondary axes.
|
|
309
|
+
*/
|
|
310
|
+
STATIC void
|
|
311
|
+
_chart_add_axis_ids(lxw_chart *self)
|
|
312
|
+
{
|
|
313
|
+
uint32_t chart_id = 50010000 + self->id;
|
|
314
|
+
uint32_t axis_count = 1;
|
|
315
|
+
|
|
316
|
+
self->axis_id_1 = chart_id + axis_count;
|
|
317
|
+
self->axis_id_2 = self->axis_id_1 + 1;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/*
|
|
321
|
+
* Utility function to set a chart range.
|
|
322
|
+
*/
|
|
323
|
+
STATIC void
|
|
324
|
+
_chart_set_range(lxw_series_range *range, const char *sheetname,
|
|
325
|
+
lxw_row_t first_row, lxw_col_t first_col,
|
|
326
|
+
lxw_row_t last_row, lxw_col_t last_col)
|
|
327
|
+
{
|
|
328
|
+
char formula[LXW_MAX_FORMULA_RANGE_LENGTH] = { 0 };
|
|
329
|
+
|
|
330
|
+
/* Set the range properties. */
|
|
331
|
+
range->sheetname = lxw_strdup(sheetname);
|
|
332
|
+
range->first_row = first_row;
|
|
333
|
+
range->first_col = first_col;
|
|
334
|
+
range->last_row = last_row;
|
|
335
|
+
range->last_col = last_col;
|
|
336
|
+
|
|
337
|
+
/* Free any existing range. */
|
|
338
|
+
free(range->formula);
|
|
339
|
+
|
|
340
|
+
/* Convert the range properties to a formula like: Sheet1!$A$1:$A$5. */
|
|
341
|
+
lxw_rowcol_to_formula_abs(formula, sheetname,
|
|
342
|
+
first_row, first_col, last_row, last_col);
|
|
343
|
+
|
|
344
|
+
range->formula = lxw_strdup(formula);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/*****************************************************************************
|
|
348
|
+
*
|
|
349
|
+
* XML functions.
|
|
350
|
+
*
|
|
351
|
+
****************************************************************************/
|
|
352
|
+
|
|
353
|
+
/*
|
|
354
|
+
* Write the XML declaration.
|
|
355
|
+
*/
|
|
356
|
+
STATIC void
|
|
357
|
+
_chart_xml_declaration(lxw_chart *self)
|
|
358
|
+
{
|
|
359
|
+
lxw_xml_declaration(self->file);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/*
|
|
363
|
+
* Write the <c:chartSpace> element.
|
|
364
|
+
*/
|
|
365
|
+
STATIC void
|
|
366
|
+
_chart_write_chart_space(lxw_chart *self)
|
|
367
|
+
{
|
|
368
|
+
struct xml_attribute_list attributes;
|
|
369
|
+
struct xml_attribute *attribute;
|
|
370
|
+
char xmlns_c[] = LXW_SCHEMA_DRAWING "/chart";
|
|
371
|
+
char xmlns_a[] = LXW_SCHEMA_DRAWING "/main";
|
|
372
|
+
char xmlns_r[] = LXW_SCHEMA_OFFICEDOC "/relationships";
|
|
373
|
+
|
|
374
|
+
LXW_INIT_ATTRIBUTES();
|
|
375
|
+
LXW_PUSH_ATTRIBUTES_STR("xmlns:c", xmlns_c);
|
|
376
|
+
LXW_PUSH_ATTRIBUTES_STR("xmlns:a", xmlns_a);
|
|
377
|
+
LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r);
|
|
378
|
+
|
|
379
|
+
lxw_xml_start_tag(self->file, "c:chartSpace", &attributes);
|
|
380
|
+
|
|
381
|
+
LXW_FREE_ATTRIBUTES();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/*
|
|
385
|
+
* Write the <c:lang> element.
|
|
386
|
+
*/
|
|
387
|
+
STATIC void
|
|
388
|
+
_chart_write_lang(lxw_chart *self)
|
|
389
|
+
{
|
|
390
|
+
struct xml_attribute_list attributes;
|
|
391
|
+
struct xml_attribute *attribute;
|
|
392
|
+
|
|
393
|
+
LXW_INIT_ATTRIBUTES();
|
|
394
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "en-US");
|
|
395
|
+
|
|
396
|
+
lxw_xml_empty_tag(self->file, "c:lang", &attributes);
|
|
397
|
+
|
|
398
|
+
LXW_FREE_ATTRIBUTES();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/*
|
|
402
|
+
* Write the <c:style> element.
|
|
403
|
+
*/
|
|
404
|
+
STATIC void
|
|
405
|
+
_chart_write_style(lxw_chart *self)
|
|
406
|
+
{
|
|
407
|
+
struct xml_attribute_list attributes;
|
|
408
|
+
struct xml_attribute *attribute;
|
|
409
|
+
|
|
410
|
+
/* Don"t write an element for the default style, 2. */
|
|
411
|
+
if (self->style_id == 2)
|
|
412
|
+
return;
|
|
413
|
+
|
|
414
|
+
LXW_INIT_ATTRIBUTES();
|
|
415
|
+
LXW_PUSH_ATTRIBUTES_INT("val", self->style_id);
|
|
416
|
+
|
|
417
|
+
lxw_xml_empty_tag(self->file, "c:style", &attributes);
|
|
418
|
+
|
|
419
|
+
LXW_FREE_ATTRIBUTES();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/*
|
|
423
|
+
* Write the <c:layout> element.
|
|
424
|
+
*/
|
|
425
|
+
STATIC void
|
|
426
|
+
_chart_write_layout(lxw_chart *self)
|
|
427
|
+
{
|
|
428
|
+
lxw_xml_empty_tag(self->file, "c:layout", NULL);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/*
|
|
432
|
+
* Write the <c:grouping> element.
|
|
433
|
+
*/
|
|
434
|
+
STATIC void
|
|
435
|
+
_chart_write_grouping(lxw_chart *self, uint8_t grouping)
|
|
436
|
+
{
|
|
437
|
+
struct xml_attribute_list attributes;
|
|
438
|
+
struct xml_attribute *attribute;
|
|
439
|
+
|
|
440
|
+
LXW_INIT_ATTRIBUTES();
|
|
441
|
+
|
|
442
|
+
if (grouping == LXW_GROUPING_STANDARD)
|
|
443
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "standard");
|
|
444
|
+
else if (grouping == LXW_GROUPING_PERCENTSTACKED)
|
|
445
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "percentStacked");
|
|
446
|
+
else if (grouping == LXW_GROUPING_STACKED)
|
|
447
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "stacked");
|
|
448
|
+
else
|
|
449
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "clustered");
|
|
450
|
+
|
|
451
|
+
lxw_xml_empty_tag(self->file, "c:grouping", &attributes);
|
|
452
|
+
|
|
453
|
+
LXW_FREE_ATTRIBUTES();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/*
|
|
457
|
+
* Write the <c:radarStyle> element.
|
|
458
|
+
*/
|
|
459
|
+
STATIC void
|
|
460
|
+
_chart_write_radar_style(lxw_chart *self)
|
|
461
|
+
{
|
|
462
|
+
struct xml_attribute_list attributes;
|
|
463
|
+
struct xml_attribute *attribute;
|
|
464
|
+
|
|
465
|
+
LXW_INIT_ATTRIBUTES();
|
|
466
|
+
|
|
467
|
+
if (self->type == LXW_CHART_RADAR_FILLED)
|
|
468
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "filled");
|
|
469
|
+
else
|
|
470
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "marker");
|
|
471
|
+
|
|
472
|
+
lxw_xml_empty_tag(self->file, "c:radarStyle", &attributes);
|
|
473
|
+
|
|
474
|
+
LXW_FREE_ATTRIBUTES();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/*
|
|
478
|
+
* Write the <c:varyColors> element.
|
|
479
|
+
*/
|
|
480
|
+
STATIC void
|
|
481
|
+
_chart_write_vary_colors(lxw_chart *self)
|
|
482
|
+
{
|
|
483
|
+
struct xml_attribute_list attributes;
|
|
484
|
+
struct xml_attribute *attribute;
|
|
485
|
+
|
|
486
|
+
LXW_INIT_ATTRIBUTES();
|
|
487
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "1");
|
|
488
|
+
|
|
489
|
+
lxw_xml_empty_tag(self->file, "c:varyColors", &attributes);
|
|
490
|
+
|
|
491
|
+
LXW_FREE_ATTRIBUTES();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/*
|
|
495
|
+
* Write the <c:firstSliceAng> element.
|
|
496
|
+
*/
|
|
497
|
+
STATIC void
|
|
498
|
+
_chart_write_first_slice_ang(lxw_chart *self)
|
|
499
|
+
{
|
|
500
|
+
struct xml_attribute_list attributes;
|
|
501
|
+
struct xml_attribute *attribute;
|
|
502
|
+
|
|
503
|
+
LXW_INIT_ATTRIBUTES();
|
|
504
|
+
LXW_PUSH_ATTRIBUTES_INT("val", self->rotation);
|
|
505
|
+
|
|
506
|
+
lxw_xml_empty_tag(self->file, "c:firstSliceAng", &attributes);
|
|
507
|
+
|
|
508
|
+
LXW_FREE_ATTRIBUTES();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/*
|
|
512
|
+
* Write the <c:holeSize> element.
|
|
513
|
+
*/
|
|
514
|
+
STATIC void
|
|
515
|
+
_chart_write_hole_size(lxw_chart *self)
|
|
516
|
+
{
|
|
517
|
+
struct xml_attribute_list attributes;
|
|
518
|
+
struct xml_attribute *attribute;
|
|
519
|
+
|
|
520
|
+
LXW_INIT_ATTRIBUTES();
|
|
521
|
+
LXW_PUSH_ATTRIBUTES_INT("val", self->hole_size);
|
|
522
|
+
|
|
523
|
+
lxw_xml_empty_tag(self->file, "c:holeSize", &attributes);
|
|
524
|
+
|
|
525
|
+
LXW_FREE_ATTRIBUTES();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/*
|
|
529
|
+
* Write the <a:alpha> element.
|
|
530
|
+
*/
|
|
531
|
+
STATIC void
|
|
532
|
+
_chart_write_a_alpha(lxw_chart *self, uint8_t transparency)
|
|
533
|
+
{
|
|
534
|
+
struct xml_attribute_list attributes;
|
|
535
|
+
struct xml_attribute *attribute;
|
|
536
|
+
uint32_t val;
|
|
537
|
+
|
|
538
|
+
LXW_INIT_ATTRIBUTES();
|
|
539
|
+
|
|
540
|
+
val = (100 - transparency) * 1000;
|
|
541
|
+
|
|
542
|
+
LXW_PUSH_ATTRIBUTES_INT("val", val);
|
|
543
|
+
|
|
544
|
+
lxw_xml_empty_tag(self->file, "a:alpha", &attributes);
|
|
545
|
+
|
|
546
|
+
LXW_FREE_ATTRIBUTES();
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/*
|
|
550
|
+
* Write the <a:srgbClr> element.
|
|
551
|
+
*/
|
|
552
|
+
STATIC void
|
|
553
|
+
_chart_write_a_srgb_clr(lxw_chart *self, lxw_color_t color,
|
|
554
|
+
uint8_t transparency)
|
|
555
|
+
{
|
|
556
|
+
struct xml_attribute_list attributes;
|
|
557
|
+
struct xml_attribute *attribute;
|
|
558
|
+
char rgb_str[LXW_ATTR_32];
|
|
559
|
+
|
|
560
|
+
LXW_INIT_ATTRIBUTES();
|
|
561
|
+
|
|
562
|
+
lxw_snprintf(rgb_str, LXW_ATTR_32, "%06X", color & LXW_COLOR_MASK);
|
|
563
|
+
LXW_PUSH_ATTRIBUTES_STR("val", rgb_str);
|
|
564
|
+
|
|
565
|
+
if (transparency) {
|
|
566
|
+
lxw_xml_start_tag(self->file, "a:srgbClr", &attributes);
|
|
567
|
+
|
|
568
|
+
/* Write the a:alpha element. */
|
|
569
|
+
_chart_write_a_alpha(self, transparency);
|
|
570
|
+
|
|
571
|
+
lxw_xml_end_tag(self->file, "a:srgbClr");
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
lxw_xml_empty_tag(self->file, "a:srgbClr", &attributes);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
LXW_FREE_ATTRIBUTES();
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/*
|
|
581
|
+
* Write the <a:solidFill> element.
|
|
582
|
+
*/
|
|
583
|
+
STATIC void
|
|
584
|
+
_chart_write_a_solid_fill(lxw_chart *self, lxw_color_t color,
|
|
585
|
+
uint8_t transparency)
|
|
586
|
+
{
|
|
587
|
+
|
|
588
|
+
lxw_xml_start_tag(self->file, "a:solidFill", NULL);
|
|
589
|
+
|
|
590
|
+
/* Write the a:srgbClr element. */
|
|
591
|
+
_chart_write_a_srgb_clr(self, color, transparency);
|
|
592
|
+
|
|
593
|
+
lxw_xml_end_tag(self->file, "a:solidFill");
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/*
|
|
597
|
+
* Write the <a:t> element.
|
|
598
|
+
*/
|
|
599
|
+
STATIC void
|
|
600
|
+
_chart_write_a_t(lxw_chart *self, char *name)
|
|
601
|
+
{
|
|
602
|
+
lxw_xml_data_element(self->file, "a:t", name, NULL);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/*
|
|
606
|
+
* Write the <a:endParaRPr> element.
|
|
607
|
+
*/
|
|
608
|
+
STATIC void
|
|
609
|
+
_chart_write_a_end_para_rpr(lxw_chart *self)
|
|
610
|
+
{
|
|
611
|
+
struct xml_attribute_list attributes;
|
|
612
|
+
struct xml_attribute *attribute;
|
|
613
|
+
|
|
614
|
+
LXW_INIT_ATTRIBUTES();
|
|
615
|
+
LXW_PUSH_ATTRIBUTES_STR("lang", "en-US");
|
|
616
|
+
|
|
617
|
+
lxw_xml_empty_tag(self->file, "a:endParaRPr", &attributes);
|
|
618
|
+
|
|
619
|
+
LXW_FREE_ATTRIBUTES();
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/*
|
|
623
|
+
* Write the <a:defRPr> element.
|
|
624
|
+
*/
|
|
625
|
+
STATIC void
|
|
626
|
+
_chart_write_a_def_rpr(lxw_chart *self, lxw_chart_font *font)
|
|
627
|
+
{
|
|
628
|
+
struct xml_attribute_list attributes;
|
|
629
|
+
struct xml_attribute *attribute;
|
|
630
|
+
uint8_t has_color = LXW_FALSE;
|
|
631
|
+
uint8_t has_latin = LXW_FALSE;
|
|
632
|
+
uint8_t use_font_default = LXW_FALSE;
|
|
633
|
+
|
|
634
|
+
LXW_INIT_ATTRIBUTES();
|
|
635
|
+
|
|
636
|
+
if (font) {
|
|
637
|
+
has_color = font->color || font->has_color;
|
|
638
|
+
has_latin = font->name || font->pitch_family || font->charset;
|
|
639
|
+
use_font_default = !(has_color || has_latin || font->baseline == -1);
|
|
640
|
+
|
|
641
|
+
/* Set the font attributes. */
|
|
642
|
+
if (font->size)
|
|
643
|
+
LXW_PUSH_ATTRIBUTES_INT("sz", font->size);
|
|
644
|
+
|
|
645
|
+
if (use_font_default || font->bold)
|
|
646
|
+
LXW_PUSH_ATTRIBUTES_INT("b", font->bold & 0x1);
|
|
647
|
+
|
|
648
|
+
if (use_font_default || font->italic)
|
|
649
|
+
LXW_PUSH_ATTRIBUTES_INT("i", font->italic & 0x1);
|
|
650
|
+
|
|
651
|
+
if (font->underline)
|
|
652
|
+
LXW_PUSH_ATTRIBUTES_STR("u", "sng");
|
|
653
|
+
|
|
654
|
+
if (font->baseline != -1)
|
|
655
|
+
LXW_PUSH_ATTRIBUTES_INT("baseline", font->baseline);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/* There are sub-elements if the font name or color have changed. */
|
|
659
|
+
if (has_latin || has_color) {
|
|
660
|
+
|
|
661
|
+
lxw_xml_start_tag(self->file, "a:defRPr", &attributes);
|
|
662
|
+
|
|
663
|
+
if (has_color) {
|
|
664
|
+
_chart_write_a_solid_fill(self, font->color, LXW_FALSE);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (has_latin) {
|
|
668
|
+
/* Free and reuse the attribute list for the latin attributes. */
|
|
669
|
+
LXW_FREE_ATTRIBUTES();
|
|
670
|
+
|
|
671
|
+
if (font->name)
|
|
672
|
+
LXW_PUSH_ATTRIBUTES_STR("typeface", font->name);
|
|
673
|
+
|
|
674
|
+
if (font->pitch_family)
|
|
675
|
+
LXW_PUSH_ATTRIBUTES_INT("pitchFamily", font->pitch_family);
|
|
676
|
+
|
|
677
|
+
if (font->pitch_family || font->charset)
|
|
678
|
+
LXW_PUSH_ATTRIBUTES_INT("charset", font->charset);
|
|
679
|
+
|
|
680
|
+
/* Write the <a:latin> element. */
|
|
681
|
+
lxw_xml_empty_tag(self->file, "a:latin", &attributes);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
lxw_xml_end_tag(self->file, "a:defRPr");
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
lxw_xml_empty_tag(self->file, "a:defRPr", &attributes);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
LXW_FREE_ATTRIBUTES();
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/*
|
|
694
|
+
* Write the <a:rPr> element.
|
|
695
|
+
*/
|
|
696
|
+
STATIC void
|
|
697
|
+
_chart_write_a_r_pr(lxw_chart *self, lxw_chart_font *font)
|
|
698
|
+
{
|
|
699
|
+
struct xml_attribute_list attributes;
|
|
700
|
+
struct xml_attribute *attribute;
|
|
701
|
+
uint8_t has_color = LXW_FALSE;
|
|
702
|
+
uint8_t has_latin = LXW_FALSE;
|
|
703
|
+
uint8_t use_font_default = LXW_FALSE;
|
|
704
|
+
|
|
705
|
+
LXW_INIT_ATTRIBUTES();
|
|
706
|
+
LXW_PUSH_ATTRIBUTES_STR("lang", "en-US");
|
|
707
|
+
|
|
708
|
+
if (font) {
|
|
709
|
+
has_color = font->color || font->has_color;
|
|
710
|
+
has_latin = font->name || font->pitch_family || font->charset;
|
|
711
|
+
use_font_default = !(has_color || has_latin || font->baseline == -1);
|
|
712
|
+
|
|
713
|
+
/* Set the font attributes. */
|
|
714
|
+
if (font->size)
|
|
715
|
+
LXW_PUSH_ATTRIBUTES_INT("sz", font->size);
|
|
716
|
+
|
|
717
|
+
if (use_font_default || font->bold)
|
|
718
|
+
LXW_PUSH_ATTRIBUTES_INT("b", font->bold & 0x1);
|
|
719
|
+
|
|
720
|
+
if (use_font_default || font->italic)
|
|
721
|
+
LXW_PUSH_ATTRIBUTES_INT("i", font->italic & 0x1);
|
|
722
|
+
|
|
723
|
+
if (font->underline)
|
|
724
|
+
LXW_PUSH_ATTRIBUTES_STR("u", "sng");
|
|
725
|
+
|
|
726
|
+
if (font->baseline != -1)
|
|
727
|
+
LXW_PUSH_ATTRIBUTES_INT("baseline", font->baseline);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/* There are sub-elements if the font name or color have changed. */
|
|
731
|
+
if (has_latin || has_color) {
|
|
732
|
+
|
|
733
|
+
lxw_xml_start_tag(self->file, "a:rPr", &attributes);
|
|
734
|
+
|
|
735
|
+
if (has_color) {
|
|
736
|
+
_chart_write_a_solid_fill(self, font->color, LXW_FALSE);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if (has_latin) {
|
|
740
|
+
/* Free and reuse the attribute list for the latin attributes. */
|
|
741
|
+
LXW_FREE_ATTRIBUTES();
|
|
742
|
+
|
|
743
|
+
if (font->name)
|
|
744
|
+
LXW_PUSH_ATTRIBUTES_STR("typeface", font->name);
|
|
745
|
+
|
|
746
|
+
if (font->pitch_family)
|
|
747
|
+
LXW_PUSH_ATTRIBUTES_INT("pitchFamily", font->pitch_family);
|
|
748
|
+
|
|
749
|
+
if (font->pitch_family || font->charset)
|
|
750
|
+
LXW_PUSH_ATTRIBUTES_INT("charset", font->charset);
|
|
751
|
+
|
|
752
|
+
/* Write the <a:latin> element. */
|
|
753
|
+
lxw_xml_empty_tag(self->file, "a:latin", &attributes);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
lxw_xml_end_tag(self->file, "a:rPr");
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
lxw_xml_empty_tag(self->file, "a:rPr", &attributes);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
LXW_FREE_ATTRIBUTES();
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/*
|
|
766
|
+
* Write the <a:r> element.
|
|
767
|
+
*/
|
|
768
|
+
STATIC void
|
|
769
|
+
_chart_write_a_r(lxw_chart *self, char *name, lxw_chart_font *font)
|
|
770
|
+
{
|
|
771
|
+
lxw_xml_start_tag(self->file, "a:r", NULL);
|
|
772
|
+
|
|
773
|
+
/* Write the a:rPr element. */
|
|
774
|
+
_chart_write_a_r_pr(self, font);
|
|
775
|
+
|
|
776
|
+
/* Write the a:t element. */
|
|
777
|
+
_chart_write_a_t(self, name);
|
|
778
|
+
|
|
779
|
+
lxw_xml_end_tag(self->file, "a:r");
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/*
|
|
783
|
+
* Write the <a:pPr> element.
|
|
784
|
+
*/
|
|
785
|
+
STATIC void
|
|
786
|
+
_chart_write_a_p_pr_formula(lxw_chart *self, lxw_chart_font *font)
|
|
787
|
+
{
|
|
788
|
+
lxw_xml_start_tag(self->file, "a:pPr", NULL);
|
|
789
|
+
|
|
790
|
+
/* Write the a:defRPr element. */
|
|
791
|
+
_chart_write_a_def_rpr(self, font);
|
|
792
|
+
|
|
793
|
+
lxw_xml_end_tag(self->file, "a:pPr");
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/*
|
|
797
|
+
* Write the <a:pPr> element for pie chart legends.
|
|
798
|
+
*/
|
|
799
|
+
STATIC void
|
|
800
|
+
_chart_write_a_p_pr_pie(lxw_chart *self, lxw_chart_font *font)
|
|
801
|
+
{
|
|
802
|
+
struct xml_attribute_list attributes;
|
|
803
|
+
struct xml_attribute *attribute;
|
|
804
|
+
|
|
805
|
+
LXW_INIT_ATTRIBUTES();
|
|
806
|
+
LXW_PUSH_ATTRIBUTES_STR("rtl", "0");
|
|
807
|
+
|
|
808
|
+
lxw_xml_start_tag(self->file, "a:pPr", &attributes);
|
|
809
|
+
|
|
810
|
+
/* Write the a:defRPr element. */
|
|
811
|
+
_chart_write_a_def_rpr(self, font);
|
|
812
|
+
|
|
813
|
+
lxw_xml_end_tag(self->file, "a:pPr");
|
|
814
|
+
|
|
815
|
+
LXW_FREE_ATTRIBUTES();
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/*
|
|
819
|
+
* Write the <a:pPr> element.
|
|
820
|
+
*/
|
|
821
|
+
STATIC void
|
|
822
|
+
_chart_write_a_p_pr_rich(lxw_chart *self, lxw_chart_font *font)
|
|
823
|
+
{
|
|
824
|
+
lxw_xml_start_tag(self->file, "a:pPr", NULL);
|
|
825
|
+
|
|
826
|
+
/* Write the a:defRPr element. */
|
|
827
|
+
_chart_write_a_def_rpr(self, font);
|
|
828
|
+
|
|
829
|
+
lxw_xml_end_tag(self->file, "a:pPr");
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/*
|
|
833
|
+
* Write the <a:p> element.
|
|
834
|
+
*/
|
|
835
|
+
STATIC void
|
|
836
|
+
_chart_write_a_p_formula(lxw_chart *self, lxw_chart_font *font)
|
|
837
|
+
{
|
|
838
|
+
lxw_xml_start_tag(self->file, "a:p", NULL);
|
|
839
|
+
|
|
840
|
+
/* Write the a:pPr element. */
|
|
841
|
+
_chart_write_a_p_pr_formula(self, font);
|
|
842
|
+
|
|
843
|
+
/* Write the a:endParaRPr element. */
|
|
844
|
+
_chart_write_a_end_para_rpr(self);
|
|
845
|
+
|
|
846
|
+
lxw_xml_end_tag(self->file, "a:p");
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/*
|
|
850
|
+
* Write the <a:p> element for pie chart legends.
|
|
851
|
+
*/
|
|
852
|
+
STATIC void
|
|
853
|
+
_chart_write_a_p_pie(lxw_chart *self, lxw_chart_font *font)
|
|
854
|
+
{
|
|
855
|
+
lxw_xml_start_tag(self->file, "a:p", NULL);
|
|
856
|
+
|
|
857
|
+
/* Write the a:pPr element. */
|
|
858
|
+
_chart_write_a_p_pr_pie(self, font);
|
|
859
|
+
|
|
860
|
+
/* Write the a:endParaRPr element. */
|
|
861
|
+
_chart_write_a_end_para_rpr(self);
|
|
862
|
+
|
|
863
|
+
lxw_xml_end_tag(self->file, "a:p");
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/*
|
|
867
|
+
* Write the <a:p> element.
|
|
868
|
+
*/
|
|
869
|
+
STATIC void
|
|
870
|
+
_chart_write_a_p_rich(lxw_chart *self, char *name, lxw_chart_font *font)
|
|
871
|
+
{
|
|
872
|
+
lxw_xml_start_tag(self->file, "a:p", NULL);
|
|
873
|
+
|
|
874
|
+
/* Write the a:pPr element. */
|
|
875
|
+
_chart_write_a_p_pr_rich(self, font);
|
|
876
|
+
|
|
877
|
+
/* Write the a:r element. */
|
|
878
|
+
_chart_write_a_r(self, name, font);
|
|
879
|
+
|
|
880
|
+
lxw_xml_end_tag(self->file, "a:p");
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/*
|
|
884
|
+
* Write the <a:lstStyle> element.
|
|
885
|
+
*/
|
|
886
|
+
STATIC void
|
|
887
|
+
_chart_write_a_lst_style(lxw_chart *self)
|
|
888
|
+
{
|
|
889
|
+
lxw_xml_empty_tag(self->file, "a:lstStyle", NULL);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/*
|
|
893
|
+
* Write the <a:bodyPr> element.
|
|
894
|
+
*/
|
|
895
|
+
STATIC void
|
|
896
|
+
_chart_write_a_body_pr(lxw_chart *self, int32_t rotation,
|
|
897
|
+
uint8_t is_horizontal)
|
|
898
|
+
{
|
|
899
|
+
struct xml_attribute_list attributes;
|
|
900
|
+
struct xml_attribute *attribute;
|
|
901
|
+
|
|
902
|
+
LXW_INIT_ATTRIBUTES();
|
|
903
|
+
|
|
904
|
+
if (rotation == 0 && is_horizontal)
|
|
905
|
+
rotation = -5400000;
|
|
906
|
+
|
|
907
|
+
if (rotation)
|
|
908
|
+
LXW_PUSH_ATTRIBUTES_INT("rot", rotation);
|
|
909
|
+
|
|
910
|
+
if (is_horizontal)
|
|
911
|
+
LXW_PUSH_ATTRIBUTES_STR("vert", "horz");
|
|
912
|
+
|
|
913
|
+
lxw_xml_empty_tag(self->file, "a:bodyPr", &attributes);
|
|
914
|
+
|
|
915
|
+
LXW_FREE_ATTRIBUTES();
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/*
|
|
919
|
+
* Write the <c:ptCount> element.
|
|
920
|
+
*/
|
|
921
|
+
STATIC void
|
|
922
|
+
_chart_write_pt_count(lxw_chart *self, uint16_t num_data_points)
|
|
923
|
+
{
|
|
924
|
+
struct xml_attribute_list attributes;
|
|
925
|
+
struct xml_attribute *attribute;
|
|
926
|
+
|
|
927
|
+
LXW_INIT_ATTRIBUTES();
|
|
928
|
+
LXW_PUSH_ATTRIBUTES_INT("val", num_data_points);
|
|
929
|
+
|
|
930
|
+
lxw_xml_empty_tag(self->file, "c:ptCount", &attributes);
|
|
931
|
+
|
|
932
|
+
LXW_FREE_ATTRIBUTES();
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/*
|
|
936
|
+
* Write the <c:v> element.
|
|
937
|
+
*/
|
|
938
|
+
STATIC void
|
|
939
|
+
_chart_write_v_num(lxw_chart *self, double number)
|
|
940
|
+
{
|
|
941
|
+
char data[LXW_ATTR_32];
|
|
942
|
+
|
|
943
|
+
lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
|
|
944
|
+
|
|
945
|
+
lxw_xml_data_element(self->file, "c:v", data, NULL);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/*
|
|
949
|
+
* Write the <c:v> element.
|
|
950
|
+
*/
|
|
951
|
+
STATIC void
|
|
952
|
+
_chart_write_v_str(lxw_chart *self, char *str)
|
|
953
|
+
{
|
|
954
|
+
lxw_xml_data_element(self->file, "c:v", str, NULL);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/*
|
|
958
|
+
* Write the <c:f> element.
|
|
959
|
+
*/
|
|
960
|
+
STATIC void
|
|
961
|
+
_chart_write_f(lxw_chart *self, char *formula)
|
|
962
|
+
{
|
|
963
|
+
lxw_xml_data_element(self->file, "c:f", formula, NULL);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/*
|
|
967
|
+
* Write the <c:pt> element.
|
|
968
|
+
*/
|
|
969
|
+
STATIC void
|
|
970
|
+
_chart_write_pt(lxw_chart *self, uint16_t index,
|
|
971
|
+
lxw_series_data_point *data_point)
|
|
972
|
+
{
|
|
973
|
+
struct xml_attribute_list attributes;
|
|
974
|
+
struct xml_attribute *attribute;
|
|
975
|
+
|
|
976
|
+
/* Ignore chart points that have no data. */
|
|
977
|
+
if (data_point->no_data)
|
|
978
|
+
return;
|
|
979
|
+
|
|
980
|
+
LXW_INIT_ATTRIBUTES();
|
|
981
|
+
LXW_PUSH_ATTRIBUTES_INT("idx", index);
|
|
982
|
+
|
|
983
|
+
lxw_xml_start_tag(self->file, "c:pt", &attributes);
|
|
984
|
+
|
|
985
|
+
if (data_point->is_string && data_point->string)
|
|
986
|
+
_chart_write_v_str(self, data_point->string);
|
|
987
|
+
else
|
|
988
|
+
_chart_write_v_num(self, data_point->number);
|
|
989
|
+
|
|
990
|
+
lxw_xml_end_tag(self->file, "c:pt");
|
|
991
|
+
|
|
992
|
+
LXW_FREE_ATTRIBUTES();
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/*
|
|
996
|
+
* Write the <c:pt> element.
|
|
997
|
+
*/
|
|
998
|
+
STATIC void
|
|
999
|
+
_chart_write_num_pt(lxw_chart *self, uint16_t index,
|
|
1000
|
+
lxw_series_data_point *data_point)
|
|
1001
|
+
{
|
|
1002
|
+
struct xml_attribute_list attributes;
|
|
1003
|
+
struct xml_attribute *attribute;
|
|
1004
|
+
|
|
1005
|
+
/* Ignore chart points that have no data. */
|
|
1006
|
+
if (data_point->no_data)
|
|
1007
|
+
return;
|
|
1008
|
+
|
|
1009
|
+
LXW_INIT_ATTRIBUTES();
|
|
1010
|
+
LXW_PUSH_ATTRIBUTES_INT("idx", index);
|
|
1011
|
+
|
|
1012
|
+
lxw_xml_start_tag(self->file, "c:pt", &attributes);
|
|
1013
|
+
|
|
1014
|
+
_chart_write_v_num(self, data_point->number);
|
|
1015
|
+
|
|
1016
|
+
lxw_xml_end_tag(self->file, "c:pt");
|
|
1017
|
+
|
|
1018
|
+
LXW_FREE_ATTRIBUTES();
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
/*
|
|
1022
|
+
* Write the <c:formatCode> element.
|
|
1023
|
+
*/
|
|
1024
|
+
STATIC void
|
|
1025
|
+
_chart_write_format_code(lxw_chart *self)
|
|
1026
|
+
{
|
|
1027
|
+
lxw_xml_data_element(self->file, "c:formatCode", "General", NULL);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/*
|
|
1031
|
+
* Write the <c:numCache> element.
|
|
1032
|
+
*/
|
|
1033
|
+
STATIC void
|
|
1034
|
+
_chart_write_num_cache(lxw_chart *self, lxw_series_range *range)
|
|
1035
|
+
{
|
|
1036
|
+
lxw_series_data_point *data_point;
|
|
1037
|
+
uint16_t index = 0;
|
|
1038
|
+
|
|
1039
|
+
lxw_xml_start_tag(self->file, "c:numCache", NULL);
|
|
1040
|
+
|
|
1041
|
+
/* Write the c:formatCode element. */
|
|
1042
|
+
_chart_write_format_code(self);
|
|
1043
|
+
|
|
1044
|
+
/* Write the c:ptCount element. */
|
|
1045
|
+
_chart_write_pt_count(self, range->num_data_points);
|
|
1046
|
+
|
|
1047
|
+
STAILQ_FOREACH(data_point, range->data_cache, list_pointers) {
|
|
1048
|
+
/* Write the c:pt element. */
|
|
1049
|
+
_chart_write_num_pt(self, index, data_point);
|
|
1050
|
+
index++;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
lxw_xml_end_tag(self->file, "c:numCache");
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/*
|
|
1057
|
+
* Write the <c:strCache> element.
|
|
1058
|
+
*/
|
|
1059
|
+
STATIC void
|
|
1060
|
+
_chart_write_str_cache(lxw_chart *self, lxw_series_range *range)
|
|
1061
|
+
{
|
|
1062
|
+
lxw_series_data_point *data_point;
|
|
1063
|
+
uint16_t index = 0;
|
|
1064
|
+
|
|
1065
|
+
lxw_xml_start_tag(self->file, "c:strCache", NULL);
|
|
1066
|
+
|
|
1067
|
+
/* Write the c:ptCount element. */
|
|
1068
|
+
_chart_write_pt_count(self, range->num_data_points);
|
|
1069
|
+
|
|
1070
|
+
STAILQ_FOREACH(data_point, range->data_cache, list_pointers) {
|
|
1071
|
+
/* Write the c:pt element. */
|
|
1072
|
+
_chart_write_pt(self, index, data_point);
|
|
1073
|
+
index++;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
lxw_xml_end_tag(self->file, "c:strCache");
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/*
|
|
1080
|
+
* Write the <c:numRef> element.
|
|
1081
|
+
*/
|
|
1082
|
+
STATIC void
|
|
1083
|
+
_chart_write_num_ref(lxw_chart *self, lxw_series_range *range)
|
|
1084
|
+
{
|
|
1085
|
+
lxw_xml_start_tag(self->file, "c:numRef", NULL);
|
|
1086
|
+
|
|
1087
|
+
/* Write the c:f element. */
|
|
1088
|
+
_chart_write_f(self, range->formula);
|
|
1089
|
+
|
|
1090
|
+
if (!STAILQ_EMPTY(range->data_cache)) {
|
|
1091
|
+
/* Write the c:numCache element. */
|
|
1092
|
+
_chart_write_num_cache(self, range);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
lxw_xml_end_tag(self->file, "c:numRef");
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
/*
|
|
1099
|
+
* Write the <c:strRef> element.
|
|
1100
|
+
*/
|
|
1101
|
+
STATIC void
|
|
1102
|
+
_chart_write_str_ref(lxw_chart *self, lxw_series_range *range)
|
|
1103
|
+
{
|
|
1104
|
+
lxw_xml_start_tag(self->file, "c:strRef", NULL);
|
|
1105
|
+
|
|
1106
|
+
/* Write the c:f element. */
|
|
1107
|
+
_chart_write_f(self, range->formula);
|
|
1108
|
+
|
|
1109
|
+
if (!STAILQ_EMPTY(range->data_cache)) {
|
|
1110
|
+
/* Write the c:strCache element. */
|
|
1111
|
+
_chart_write_str_cache(self, range);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
lxw_xml_end_tag(self->file, "c:strRef");
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/*
|
|
1118
|
+
* Write the cached data elements.
|
|
1119
|
+
*/
|
|
1120
|
+
STATIC void
|
|
1121
|
+
_chart_write_data_cache(lxw_chart *self, lxw_series_range *range,
|
|
1122
|
+
uint8_t has_string_cache)
|
|
1123
|
+
{
|
|
1124
|
+
if (has_string_cache) {
|
|
1125
|
+
/* Write the c:strRef element. */
|
|
1126
|
+
_chart_write_str_ref(self, range);
|
|
1127
|
+
}
|
|
1128
|
+
else {
|
|
1129
|
+
/* Write the c:numRef element. */
|
|
1130
|
+
_chart_write_num_ref(self, range);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/*
|
|
1135
|
+
* Write the <c:tx> element with a simple value such as for series names.
|
|
1136
|
+
*/
|
|
1137
|
+
STATIC void
|
|
1138
|
+
_chart_write_tx_value(lxw_chart *self, char *name)
|
|
1139
|
+
{
|
|
1140
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
|
1141
|
+
|
|
1142
|
+
/* Write the c:v element. */
|
|
1143
|
+
_chart_write_v_str(self, name);
|
|
1144
|
+
|
|
1145
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/*
|
|
1149
|
+
* Write the <c:tx> element with a simple value such as for series names.
|
|
1150
|
+
*/
|
|
1151
|
+
STATIC void
|
|
1152
|
+
_chart_write_tx_formula(lxw_chart *self, lxw_chart_title *title)
|
|
1153
|
+
{
|
|
1154
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
|
1155
|
+
|
|
1156
|
+
_chart_write_str_ref(self, title->range);
|
|
1157
|
+
|
|
1158
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/*
|
|
1162
|
+
* Write the <c:txPr> element.
|
|
1163
|
+
*/
|
|
1164
|
+
STATIC void
|
|
1165
|
+
_chart_write_tx_pr(lxw_chart *self, uint8_t is_horizontal,
|
|
1166
|
+
lxw_chart_font *font)
|
|
1167
|
+
{
|
|
1168
|
+
int32_t rotation = 0;
|
|
1169
|
+
|
|
1170
|
+
if (font)
|
|
1171
|
+
rotation = font->rotation;
|
|
1172
|
+
|
|
1173
|
+
lxw_xml_start_tag(self->file, "c:txPr", NULL);
|
|
1174
|
+
|
|
1175
|
+
/* Write the a:bodyPr element. */
|
|
1176
|
+
_chart_write_a_body_pr(self, rotation, is_horizontal);
|
|
1177
|
+
|
|
1178
|
+
/* Write the a:lstStyle element. */
|
|
1179
|
+
_chart_write_a_lst_style(self);
|
|
1180
|
+
|
|
1181
|
+
/* Write the a:p element. */
|
|
1182
|
+
_chart_write_a_p_formula(self, font);
|
|
1183
|
+
|
|
1184
|
+
lxw_xml_end_tag(self->file, "c:txPr");
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/*
|
|
1188
|
+
* Write the <c:txPr> element for pie chart legends.
|
|
1189
|
+
*/
|
|
1190
|
+
STATIC void
|
|
1191
|
+
_chart_write_tx_pr_pie(lxw_chart *self, uint8_t is_horizontal,
|
|
1192
|
+
lxw_chart_font *font)
|
|
1193
|
+
{
|
|
1194
|
+
int32_t rotation = 0;
|
|
1195
|
+
|
|
1196
|
+
if (font)
|
|
1197
|
+
rotation = font->rotation;
|
|
1198
|
+
|
|
1199
|
+
lxw_xml_start_tag(self->file, "c:txPr", NULL);
|
|
1200
|
+
|
|
1201
|
+
/* Write the a:bodyPr element. */
|
|
1202
|
+
_chart_write_a_body_pr(self, rotation, is_horizontal);
|
|
1203
|
+
|
|
1204
|
+
/* Write the a:lstStyle element. */
|
|
1205
|
+
_chart_write_a_lst_style(self);
|
|
1206
|
+
|
|
1207
|
+
/* Write the a:p element. */
|
|
1208
|
+
_chart_write_a_p_pie(self, font);
|
|
1209
|
+
|
|
1210
|
+
lxw_xml_end_tag(self->file, "c:txPr");
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/*
|
|
1214
|
+
* Write the <c:txPr> element.
|
|
1215
|
+
*/
|
|
1216
|
+
STATIC void
|
|
1217
|
+
_chart_write_axis_font(lxw_chart *self, lxw_chart_font *font)
|
|
1218
|
+
{
|
|
1219
|
+
if (!font)
|
|
1220
|
+
return;
|
|
1221
|
+
|
|
1222
|
+
lxw_xml_start_tag(self->file, "c:txPr", NULL);
|
|
1223
|
+
|
|
1224
|
+
/* Write the a:bodyPr element. */
|
|
1225
|
+
_chart_write_a_body_pr(self, font->rotation, LXW_FALSE);
|
|
1226
|
+
|
|
1227
|
+
/* Write the a:lstStyle element. */
|
|
1228
|
+
_chart_write_a_lst_style(self);
|
|
1229
|
+
|
|
1230
|
+
lxw_xml_start_tag(self->file, "a:p", NULL);
|
|
1231
|
+
|
|
1232
|
+
/* Write the a:pPr element. */
|
|
1233
|
+
_chart_write_a_p_pr_rich(self, font);
|
|
1234
|
+
|
|
1235
|
+
/* Write the a:endParaRPr element. */
|
|
1236
|
+
_chart_write_a_end_para_rpr(self);
|
|
1237
|
+
|
|
1238
|
+
lxw_xml_end_tag(self->file, "a:p");
|
|
1239
|
+
lxw_xml_end_tag(self->file, "c:txPr");
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/*
|
|
1243
|
+
* Write the <c:rich> element.
|
|
1244
|
+
*/
|
|
1245
|
+
STATIC void
|
|
1246
|
+
_chart_write_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
|
|
1247
|
+
lxw_chart_font *font)
|
|
1248
|
+
{
|
|
1249
|
+
int32_t rotation = 0;
|
|
1250
|
+
|
|
1251
|
+
if (font)
|
|
1252
|
+
rotation = font->rotation;
|
|
1253
|
+
|
|
1254
|
+
lxw_xml_start_tag(self->file, "c:rich", NULL);
|
|
1255
|
+
|
|
1256
|
+
/* Write the a:bodyPr element. */
|
|
1257
|
+
_chart_write_a_body_pr(self, rotation, is_horizontal);
|
|
1258
|
+
|
|
1259
|
+
/* Write the a:lstStyle element. */
|
|
1260
|
+
_chart_write_a_lst_style(self);
|
|
1261
|
+
|
|
1262
|
+
/* Write the a:p element. */
|
|
1263
|
+
_chart_write_a_p_rich(self, name, font);
|
|
1264
|
+
|
|
1265
|
+
lxw_xml_end_tag(self->file, "c:rich");
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/*
|
|
1269
|
+
* Write the <c:tx> element.
|
|
1270
|
+
*/
|
|
1271
|
+
STATIC void
|
|
1272
|
+
_chart_write_tx_rich(lxw_chart *self, char *name, uint8_t is_horizontal,
|
|
1273
|
+
lxw_chart_font *font)
|
|
1274
|
+
{
|
|
1275
|
+
|
|
1276
|
+
lxw_xml_start_tag(self->file, "c:tx", NULL);
|
|
1277
|
+
|
|
1278
|
+
/* Write the c:rich element. */
|
|
1279
|
+
_chart_write_rich(self, name, is_horizontal, font);
|
|
1280
|
+
|
|
1281
|
+
lxw_xml_end_tag(self->file, "c:tx");
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
/*
|
|
1285
|
+
* Write the <c:title> element for rich strings.
|
|
1286
|
+
*/
|
|
1287
|
+
STATIC void
|
|
1288
|
+
_chart_write_title_rich(lxw_chart *self, lxw_chart_title *title)
|
|
1289
|
+
{
|
|
1290
|
+
lxw_xml_start_tag(self->file, "c:title", NULL);
|
|
1291
|
+
|
|
1292
|
+
/* Write the c:tx element. */
|
|
1293
|
+
_chart_write_tx_rich(self, title->name, title->is_horizontal,
|
|
1294
|
+
title->font);
|
|
1295
|
+
|
|
1296
|
+
/* Write the c:layout element. */
|
|
1297
|
+
_chart_write_layout(self);
|
|
1298
|
+
|
|
1299
|
+
lxw_xml_end_tag(self->file, "c:title");
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
/*
|
|
1303
|
+
* Write the <c:title> element for a formula style title
|
|
1304
|
+
*/
|
|
1305
|
+
STATIC void
|
|
1306
|
+
_chart_write_title_formula(lxw_chart *self, lxw_chart_title *title)
|
|
1307
|
+
{
|
|
1308
|
+
lxw_xml_start_tag(self->file, "c:title", NULL);
|
|
1309
|
+
|
|
1310
|
+
/* Write the c:tx element. */
|
|
1311
|
+
_chart_write_tx_formula(self, title);
|
|
1312
|
+
|
|
1313
|
+
/* Write the c:layout element. */
|
|
1314
|
+
_chart_write_layout(self);
|
|
1315
|
+
|
|
1316
|
+
/* Write the c:txPr element. */
|
|
1317
|
+
_chart_write_tx_pr(self, title->is_horizontal, title->font);
|
|
1318
|
+
|
|
1319
|
+
lxw_xml_end_tag(self->file, "c:title");
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
/*
|
|
1323
|
+
* Write the <c:delete> element.
|
|
1324
|
+
*/
|
|
1325
|
+
STATIC void
|
|
1326
|
+
_chart_write_delete(lxw_chart *self)
|
|
1327
|
+
{
|
|
1328
|
+
struct xml_attribute_list attributes;
|
|
1329
|
+
struct xml_attribute *attribute;
|
|
1330
|
+
|
|
1331
|
+
LXW_INIT_ATTRIBUTES();
|
|
1332
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "1");
|
|
1333
|
+
|
|
1334
|
+
lxw_xml_empty_tag(self->file, "c:delete", &attributes);
|
|
1335
|
+
|
|
1336
|
+
LXW_FREE_ATTRIBUTES();
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
/*
|
|
1340
|
+
* Write the <c:autoTitleDeleted> element.
|
|
1341
|
+
*/
|
|
1342
|
+
STATIC void
|
|
1343
|
+
_chart_write_auto_title_deleted(lxw_chart *self)
|
|
1344
|
+
{
|
|
1345
|
+
struct xml_attribute_list attributes;
|
|
1346
|
+
struct xml_attribute *attribute;
|
|
1347
|
+
|
|
1348
|
+
LXW_INIT_ATTRIBUTES();
|
|
1349
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "1");
|
|
1350
|
+
|
|
1351
|
+
lxw_xml_empty_tag(self->file, "c:autoTitleDeleted", &attributes);
|
|
1352
|
+
|
|
1353
|
+
LXW_FREE_ATTRIBUTES();
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
/*
|
|
1357
|
+
* Write the <c:idx> element.
|
|
1358
|
+
*/
|
|
1359
|
+
STATIC void
|
|
1360
|
+
_chart_write_idx(lxw_chart *self, uint16_t index)
|
|
1361
|
+
{
|
|
1362
|
+
struct xml_attribute_list attributes;
|
|
1363
|
+
struct xml_attribute *attribute;
|
|
1364
|
+
|
|
1365
|
+
LXW_INIT_ATTRIBUTES();
|
|
1366
|
+
LXW_PUSH_ATTRIBUTES_INT("val", index);
|
|
1367
|
+
|
|
1368
|
+
lxw_xml_empty_tag(self->file, "c:idx", &attributes);
|
|
1369
|
+
|
|
1370
|
+
LXW_FREE_ATTRIBUTES();
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
/*
|
|
1374
|
+
* Write the <a:prstDash> element.
|
|
1375
|
+
*/
|
|
1376
|
+
STATIC void
|
|
1377
|
+
_chart_write_a_prst_dash(lxw_chart *self, uint8_t dash_type)
|
|
1378
|
+
{
|
|
1379
|
+
struct xml_attribute_list attributes;
|
|
1380
|
+
struct xml_attribute *attribute;
|
|
1381
|
+
|
|
1382
|
+
LXW_INIT_ATTRIBUTES();
|
|
1383
|
+
|
|
1384
|
+
if (dash_type == LXW_CHART_LINE_DASH_ROUND_DOT)
|
|
1385
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "sysDot");
|
|
1386
|
+
else if (dash_type == LXW_CHART_LINE_DASH_SQUARE_DOT)
|
|
1387
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "sysDash");
|
|
1388
|
+
else if (dash_type == LXW_CHART_LINE_DASH_DASH_DOT)
|
|
1389
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "dashDot");
|
|
1390
|
+
else if (dash_type == LXW_CHART_LINE_DASH_LONG_DASH)
|
|
1391
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "lgDash");
|
|
1392
|
+
else if (dash_type == LXW_CHART_LINE_DASH_LONG_DASH_DOT)
|
|
1393
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "lgDashDot");
|
|
1394
|
+
else if (dash_type == LXW_CHART_LINE_DASH_LONG_DASH_DOT_DOT)
|
|
1395
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "lgDashDotDot");
|
|
1396
|
+
else if (dash_type == LXW_CHART_LINE_DASH_DOT)
|
|
1397
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "dot");
|
|
1398
|
+
else if (dash_type == LXW_CHART_LINE_DASH_SYSTEM_DASH_DOT)
|
|
1399
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "sysDashDot");
|
|
1400
|
+
else if (dash_type == LXW_CHART_LINE_DASH_SYSTEM_DASH_DOT_DOT)
|
|
1401
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "sysDashDotDot");
|
|
1402
|
+
else
|
|
1403
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "dash");
|
|
1404
|
+
|
|
1405
|
+
lxw_xml_empty_tag(self->file, "a:prstDash", &attributes);
|
|
1406
|
+
|
|
1407
|
+
LXW_FREE_ATTRIBUTES();
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
/*
|
|
1411
|
+
* Write the <a:noFill> element.
|
|
1412
|
+
*/
|
|
1413
|
+
STATIC void
|
|
1414
|
+
_chart_write_a_no_fill(lxw_chart *self)
|
|
1415
|
+
{
|
|
1416
|
+
lxw_xml_empty_tag(self->file, "a:noFill", NULL);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
/*
|
|
1420
|
+
* Write the <a:ln> element.
|
|
1421
|
+
*/
|
|
1422
|
+
STATIC void
|
|
1423
|
+
_chart_write_a_ln(lxw_chart *self, lxw_chart_line *line)
|
|
1424
|
+
{
|
|
1425
|
+
struct xml_attribute_list attributes;
|
|
1426
|
+
struct xml_attribute *attribute;
|
|
1427
|
+
float width_flt = line->width;
|
|
1428
|
+
uint32_t width_int;
|
|
1429
|
+
|
|
1430
|
+
LXW_INIT_ATTRIBUTES();
|
|
1431
|
+
|
|
1432
|
+
/* Round width to nearest 0.25, like Excel. */
|
|
1433
|
+
width_flt = (float) (uint32_t) ((line->width + 0.125) * 4.0) / 4.0;
|
|
1434
|
+
|
|
1435
|
+
/* Convert to internal units. */
|
|
1436
|
+
width_int = (uint32_t) (0.5 + (12700.0 * width_flt));
|
|
1437
|
+
|
|
1438
|
+
if (width_int)
|
|
1439
|
+
LXW_PUSH_ATTRIBUTES_INT("w", width_int);
|
|
1440
|
+
|
|
1441
|
+
lxw_xml_start_tag(self->file, "a:ln", &attributes);
|
|
1442
|
+
|
|
1443
|
+
/* Write the line fill. */
|
|
1444
|
+
if (line->none) {
|
|
1445
|
+
/* Write the a:noFill element. */
|
|
1446
|
+
_chart_write_a_no_fill(self);
|
|
1447
|
+
}
|
|
1448
|
+
else if (line->has_color) {
|
|
1449
|
+
/* Write the a:solidFill element. */
|
|
1450
|
+
_chart_write_a_solid_fill(self, line->color, line->transparency);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
/* Write the line/dash type. */
|
|
1454
|
+
if (line->dash_type) {
|
|
1455
|
+
/* Write the a:prstDash element. */
|
|
1456
|
+
_chart_write_a_prst_dash(self, line->dash_type);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
lxw_xml_end_tag(self->file, "a:ln");
|
|
1460
|
+
|
|
1461
|
+
LXW_FREE_ATTRIBUTES();
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
/*
|
|
1465
|
+
* Write the <c:spPr> element.
|
|
1466
|
+
*/
|
|
1467
|
+
STATIC void
|
|
1468
|
+
_chart_write_sp_pr(lxw_chart *self, lxw_chart_line *line,
|
|
1469
|
+
lxw_chart_fill *fill)
|
|
1470
|
+
{
|
|
1471
|
+
if (!line && !fill)
|
|
1472
|
+
return;
|
|
1473
|
+
|
|
1474
|
+
lxw_xml_start_tag(self->file, "c:spPr", NULL);
|
|
1475
|
+
|
|
1476
|
+
/* Write the series fill. */
|
|
1477
|
+
if (fill) {
|
|
1478
|
+
if (fill->none) {
|
|
1479
|
+
/* Write the a:noFill element. */
|
|
1480
|
+
_chart_write_a_no_fill(self);
|
|
1481
|
+
}
|
|
1482
|
+
else {
|
|
1483
|
+
/* Write the a:solidFill element. */
|
|
1484
|
+
_chart_write_a_solid_fill(self, fill->color, fill->transparency);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
if (line) {
|
|
1489
|
+
/* Write the a:ln element. */
|
|
1490
|
+
_chart_write_a_ln(self, line);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
lxw_xml_end_tag(self->file, "c:spPr");
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
/*
|
|
1497
|
+
* Write the <c:order> element.
|
|
1498
|
+
*/
|
|
1499
|
+
STATIC void
|
|
1500
|
+
_chart_write_order(lxw_chart *self, uint16_t index)
|
|
1501
|
+
{
|
|
1502
|
+
struct xml_attribute_list attributes;
|
|
1503
|
+
struct xml_attribute *attribute;
|
|
1504
|
+
|
|
1505
|
+
LXW_INIT_ATTRIBUTES();
|
|
1506
|
+
LXW_PUSH_ATTRIBUTES_INT("val", index);
|
|
1507
|
+
|
|
1508
|
+
lxw_xml_empty_tag(self->file, "c:order", &attributes);
|
|
1509
|
+
|
|
1510
|
+
LXW_FREE_ATTRIBUTES();
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
/*
|
|
1514
|
+
* Write the <c:axId> element.
|
|
1515
|
+
*/
|
|
1516
|
+
STATIC void
|
|
1517
|
+
_chart_write_axis_id(lxw_chart *self, uint32_t axis_id)
|
|
1518
|
+
{
|
|
1519
|
+
struct xml_attribute_list attributes;
|
|
1520
|
+
struct xml_attribute *attribute;
|
|
1521
|
+
|
|
1522
|
+
LXW_INIT_ATTRIBUTES();
|
|
1523
|
+
LXW_PUSH_ATTRIBUTES_INT("val", axis_id);
|
|
1524
|
+
|
|
1525
|
+
lxw_xml_empty_tag(self->file, "c:axId", &attributes);
|
|
1526
|
+
|
|
1527
|
+
LXW_FREE_ATTRIBUTES();
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/*
|
|
1531
|
+
* Write the <c:axId> element.
|
|
1532
|
+
*/
|
|
1533
|
+
STATIC void
|
|
1534
|
+
_chart_write_axis_ids(lxw_chart *self)
|
|
1535
|
+
{
|
|
1536
|
+
if (!self->axis_id_1)
|
|
1537
|
+
_chart_add_axis_ids(self);
|
|
1538
|
+
|
|
1539
|
+
_chart_write_axis_id(self, self->axis_id_1);
|
|
1540
|
+
_chart_write_axis_id(self, self->axis_id_2);
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
/*
|
|
1544
|
+
* Write the series name.
|
|
1545
|
+
*/
|
|
1546
|
+
STATIC void
|
|
1547
|
+
_chart_write_series_name(lxw_chart *self, lxw_chart_series *series)
|
|
1548
|
+
{
|
|
1549
|
+
if (series->title.name) {
|
|
1550
|
+
/* Write the c:tx element. */
|
|
1551
|
+
_chart_write_tx_value(self, series->title.name);
|
|
1552
|
+
}
|
|
1553
|
+
else if (series->title.range->formula) {
|
|
1554
|
+
/* Write the c:tx element. */
|
|
1555
|
+
_chart_write_tx_formula(self, &series->title);
|
|
1556
|
+
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
/*
|
|
1561
|
+
* Write the <c:majorTickMark> element.
|
|
1562
|
+
*/
|
|
1563
|
+
STATIC void
|
|
1564
|
+
_chart_write_major_tick_mark(lxw_chart *self, lxw_chart_axis *axis)
|
|
1565
|
+
{
|
|
1566
|
+
struct xml_attribute_list attributes;
|
|
1567
|
+
struct xml_attribute *attribute;
|
|
1568
|
+
|
|
1569
|
+
if (!axis->major_tick_mark)
|
|
1570
|
+
return;
|
|
1571
|
+
|
|
1572
|
+
LXW_INIT_ATTRIBUTES();
|
|
1573
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "cross");
|
|
1574
|
+
|
|
1575
|
+
lxw_xml_empty_tag(self->file, "c:majorTickMark", &attributes);
|
|
1576
|
+
|
|
1577
|
+
LXW_FREE_ATTRIBUTES();
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/*
|
|
1581
|
+
* Write the <c:symbol> element.
|
|
1582
|
+
*/
|
|
1583
|
+
STATIC void
|
|
1584
|
+
_chart_write_symbol(lxw_chart *self)
|
|
1585
|
+
{
|
|
1586
|
+
struct xml_attribute_list attributes;
|
|
1587
|
+
struct xml_attribute *attribute;
|
|
1588
|
+
char val[] = "none";
|
|
1589
|
+
|
|
1590
|
+
LXW_INIT_ATTRIBUTES();
|
|
1591
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1592
|
+
|
|
1593
|
+
lxw_xml_empty_tag(self->file, "c:symbol", &attributes);
|
|
1594
|
+
|
|
1595
|
+
LXW_FREE_ATTRIBUTES();
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
/*
|
|
1599
|
+
* Write the <c:marker> element.
|
|
1600
|
+
*/
|
|
1601
|
+
STATIC void
|
|
1602
|
+
_chart_write_marker(lxw_chart *self)
|
|
1603
|
+
{
|
|
1604
|
+
if (!self->has_markers)
|
|
1605
|
+
return;
|
|
1606
|
+
|
|
1607
|
+
lxw_xml_start_tag(self->file, "c:marker", NULL);
|
|
1608
|
+
|
|
1609
|
+
/* Write the c:symbol element. */
|
|
1610
|
+
_chart_write_symbol(self);
|
|
1611
|
+
|
|
1612
|
+
lxw_xml_end_tag(self->file, "c:marker");
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/*
|
|
1616
|
+
* Write the <c:marker> element.
|
|
1617
|
+
*/
|
|
1618
|
+
STATIC void
|
|
1619
|
+
_chart_write_marker_value(lxw_chart *self)
|
|
1620
|
+
{
|
|
1621
|
+
struct xml_attribute_list attributes;
|
|
1622
|
+
struct xml_attribute *attribute;
|
|
1623
|
+
char val[] = "1";
|
|
1624
|
+
|
|
1625
|
+
LXW_INIT_ATTRIBUTES();
|
|
1626
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1627
|
+
|
|
1628
|
+
lxw_xml_empty_tag(self->file, "c:marker", &attributes);
|
|
1629
|
+
|
|
1630
|
+
LXW_FREE_ATTRIBUTES();
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/*
|
|
1634
|
+
* Write the <c:smooth> element.
|
|
1635
|
+
*/
|
|
1636
|
+
STATIC void
|
|
1637
|
+
_chart_write_smooth(lxw_chart *self)
|
|
1638
|
+
{
|
|
1639
|
+
struct xml_attribute_list attributes;
|
|
1640
|
+
struct xml_attribute *attribute;
|
|
1641
|
+
char val[] = "1";
|
|
1642
|
+
|
|
1643
|
+
LXW_INIT_ATTRIBUTES();
|
|
1644
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1645
|
+
|
|
1646
|
+
lxw_xml_empty_tag(self->file, "c:smooth", &attributes);
|
|
1647
|
+
|
|
1648
|
+
LXW_FREE_ATTRIBUTES();
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
/*
|
|
1652
|
+
* Write the <c:scatterStyle> element.
|
|
1653
|
+
*/
|
|
1654
|
+
STATIC void
|
|
1655
|
+
_chart_write_scatter_style(lxw_chart *self)
|
|
1656
|
+
{
|
|
1657
|
+
struct xml_attribute_list attributes;
|
|
1658
|
+
struct xml_attribute *attribute;
|
|
1659
|
+
|
|
1660
|
+
LXW_INIT_ATTRIBUTES();
|
|
1661
|
+
|
|
1662
|
+
if (self->type == LXW_CHART_SCATTER_SMOOTH
|
|
1663
|
+
|| self->type == LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS)
|
|
1664
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "smoothMarker");
|
|
1665
|
+
else
|
|
1666
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "lineMarker");
|
|
1667
|
+
|
|
1668
|
+
lxw_xml_empty_tag(self->file, "c:scatterStyle", &attributes);
|
|
1669
|
+
|
|
1670
|
+
LXW_FREE_ATTRIBUTES();
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
/*
|
|
1674
|
+
* Write the <c:cat> element.
|
|
1675
|
+
*/
|
|
1676
|
+
STATIC void
|
|
1677
|
+
_chart_write_cat(lxw_chart *self, lxw_chart_series *series)
|
|
1678
|
+
{
|
|
1679
|
+
uint8_t has_string_cache = series->categories->has_string_cache;
|
|
1680
|
+
|
|
1681
|
+
/* Ignore <c:cat> elements for charts without category values. */
|
|
1682
|
+
if (!series->categories->formula)
|
|
1683
|
+
return;
|
|
1684
|
+
|
|
1685
|
+
self->cat_has_num_fmt = !has_string_cache;
|
|
1686
|
+
|
|
1687
|
+
lxw_xml_start_tag(self->file, "c:cat", NULL);
|
|
1688
|
+
|
|
1689
|
+
/* Write the c:numRef element. */
|
|
1690
|
+
_chart_write_data_cache(self, series->categories, has_string_cache);
|
|
1691
|
+
|
|
1692
|
+
lxw_xml_end_tag(self->file, "c:cat");
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
/*
|
|
1696
|
+
* Write the <c:xVal> element.
|
|
1697
|
+
*/
|
|
1698
|
+
STATIC void
|
|
1699
|
+
_chart_write_x_val(lxw_chart *self, lxw_chart_series *series)
|
|
1700
|
+
{
|
|
1701
|
+
uint8_t has_string_cache = series->categories->has_string_cache;
|
|
1702
|
+
|
|
1703
|
+
lxw_xml_start_tag(self->file, "c:xVal", NULL);
|
|
1704
|
+
|
|
1705
|
+
/* Write the data cache elements. */
|
|
1706
|
+
_chart_write_data_cache(self, series->categories, has_string_cache);
|
|
1707
|
+
|
|
1708
|
+
lxw_xml_end_tag(self->file, "c:xVal");
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/*
|
|
1712
|
+
* Write the <c:val> element.
|
|
1713
|
+
*/
|
|
1714
|
+
STATIC void
|
|
1715
|
+
_chart_write_val(lxw_chart *self, lxw_chart_series *series)
|
|
1716
|
+
{
|
|
1717
|
+
lxw_xml_start_tag(self->file, "c:val", NULL);
|
|
1718
|
+
|
|
1719
|
+
/* Write the data cache elements. The string_cache is set to false since
|
|
1720
|
+
* this should always be a number series. */
|
|
1721
|
+
_chart_write_data_cache(self, series->values, LXW_FALSE);
|
|
1722
|
+
|
|
1723
|
+
lxw_xml_end_tag(self->file, "c:val");
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
/*
|
|
1727
|
+
* Write the <c:yVal> element.
|
|
1728
|
+
*/
|
|
1729
|
+
STATIC void
|
|
1730
|
+
_chart_write_y_val(lxw_chart *self, lxw_chart_series *series)
|
|
1731
|
+
{
|
|
1732
|
+
lxw_xml_start_tag(self->file, "c:yVal", NULL);
|
|
1733
|
+
|
|
1734
|
+
/* Write the data cache elements. The string_cache is set to false since
|
|
1735
|
+
* this should always be a number series. */
|
|
1736
|
+
_chart_write_data_cache(self, series->values, LXW_FALSE);
|
|
1737
|
+
|
|
1738
|
+
lxw_xml_end_tag(self->file, "c:yVal");
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
/*
|
|
1742
|
+
* Write the <c:ser> element.
|
|
1743
|
+
*/
|
|
1744
|
+
STATIC void
|
|
1745
|
+
_chart_write_ser(lxw_chart *self, lxw_chart_series *series)
|
|
1746
|
+
{
|
|
1747
|
+
uint16_t index = self->series_index++;
|
|
1748
|
+
|
|
1749
|
+
lxw_xml_start_tag(self->file, "c:ser", NULL);
|
|
1750
|
+
|
|
1751
|
+
/* Write the c:idx element. */
|
|
1752
|
+
_chart_write_idx(self, index);
|
|
1753
|
+
|
|
1754
|
+
/* Write the c:order element. */
|
|
1755
|
+
_chart_write_order(self, index);
|
|
1756
|
+
|
|
1757
|
+
/* Write the series name. */
|
|
1758
|
+
_chart_write_series_name(self, series);
|
|
1759
|
+
|
|
1760
|
+
/* Write the c:spPr element. */
|
|
1761
|
+
_chart_write_sp_pr(self, series->line, series->fill);
|
|
1762
|
+
|
|
1763
|
+
/* Write the c:marker element. */
|
|
1764
|
+
_chart_write_marker(self);
|
|
1765
|
+
|
|
1766
|
+
/* Write the c:cat element. */
|
|
1767
|
+
_chart_write_cat(self, series);
|
|
1768
|
+
|
|
1769
|
+
/* Write the c:val element. */
|
|
1770
|
+
_chart_write_val(self, series);
|
|
1771
|
+
|
|
1772
|
+
lxw_xml_end_tag(self->file, "c:ser");
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
/*
|
|
1776
|
+
* Write the <c:ser> element but with c:xVal/c:yVal instead of c:cat/c:val
|
|
1777
|
+
* elements.
|
|
1778
|
+
*/
|
|
1779
|
+
STATIC void
|
|
1780
|
+
_chart_write_xval_ser(lxw_chart *self, lxw_chart_series *series)
|
|
1781
|
+
{
|
|
1782
|
+
uint16_t index = self->series_index++;
|
|
1783
|
+
|
|
1784
|
+
lxw_xml_start_tag(self->file, "c:ser", NULL);
|
|
1785
|
+
|
|
1786
|
+
/* Write the c:idx element. */
|
|
1787
|
+
_chart_write_idx(self, index);
|
|
1788
|
+
|
|
1789
|
+
/* Write the c:order element. */
|
|
1790
|
+
_chart_write_order(self, index);
|
|
1791
|
+
|
|
1792
|
+
/* Write the series name. */
|
|
1793
|
+
_chart_write_series_name(self, series);
|
|
1794
|
+
|
|
1795
|
+
/* Write the c:spPr element. */
|
|
1796
|
+
_chart_write_sp_pr(self, series->line, series->fill);
|
|
1797
|
+
|
|
1798
|
+
if (self->type == LXW_CHART_SCATTER_STRAIGHT
|
|
1799
|
+
|| self->type == LXW_CHART_SCATTER_SMOOTH) {
|
|
1800
|
+
/* Write the c:marker element. */
|
|
1801
|
+
_chart_write_marker(self);
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
/* Write the c:xVal element. */
|
|
1805
|
+
_chart_write_x_val(self, series);
|
|
1806
|
+
|
|
1807
|
+
/* Write the yVal element. */
|
|
1808
|
+
_chart_write_y_val(self, series);
|
|
1809
|
+
|
|
1810
|
+
if (self->type == LXW_CHART_SCATTER_SMOOTH
|
|
1811
|
+
|| self->type == LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS) {
|
|
1812
|
+
/* Write the c:smooth element. */
|
|
1813
|
+
_chart_write_smooth(self);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
lxw_xml_end_tag(self->file, "c:ser");
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
/*
|
|
1820
|
+
* Write the <c:orientation> element.
|
|
1821
|
+
*/
|
|
1822
|
+
STATIC void
|
|
1823
|
+
_chart_write_orientation(lxw_chart *self)
|
|
1824
|
+
{
|
|
1825
|
+
struct xml_attribute_list attributes;
|
|
1826
|
+
struct xml_attribute *attribute;
|
|
1827
|
+
char val[] = "minMax";
|
|
1828
|
+
|
|
1829
|
+
LXW_INIT_ATTRIBUTES();
|
|
1830
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1831
|
+
|
|
1832
|
+
lxw_xml_empty_tag(self->file, "c:orientation", &attributes);
|
|
1833
|
+
|
|
1834
|
+
LXW_FREE_ATTRIBUTES();
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
/*
|
|
1838
|
+
* Write the <c:scaling> element.
|
|
1839
|
+
*/
|
|
1840
|
+
STATIC void
|
|
1841
|
+
_chart_write_scaling(lxw_chart *self)
|
|
1842
|
+
{
|
|
1843
|
+
lxw_xml_start_tag(self->file, "c:scaling", NULL);
|
|
1844
|
+
|
|
1845
|
+
/* Write the c:orientation element. */
|
|
1846
|
+
_chart_write_orientation(self);
|
|
1847
|
+
|
|
1848
|
+
lxw_xml_end_tag(self->file, "c:scaling");
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
/*
|
|
1852
|
+
* Write the <c:axPos> element.
|
|
1853
|
+
*/
|
|
1854
|
+
STATIC void
|
|
1855
|
+
_chart_write_axis_pos(lxw_chart *self, uint8_t position)
|
|
1856
|
+
{
|
|
1857
|
+
struct xml_attribute_list attributes;
|
|
1858
|
+
struct xml_attribute *attribute;
|
|
1859
|
+
|
|
1860
|
+
LXW_INIT_ATTRIBUTES();
|
|
1861
|
+
|
|
1862
|
+
if (position == LXW_CHART_AXIS_RIGHT)
|
|
1863
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "r");
|
|
1864
|
+
else if (position == LXW_CHART_AXIS_LEFT)
|
|
1865
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "l");
|
|
1866
|
+
else if (position == LXW_CHART_AXIS_TOP)
|
|
1867
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "t");
|
|
1868
|
+
else if (position == LXW_CHART_AXIS_BOTTOM)
|
|
1869
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "b");
|
|
1870
|
+
|
|
1871
|
+
lxw_xml_empty_tag(self->file, "c:axPos", &attributes);
|
|
1872
|
+
|
|
1873
|
+
LXW_FREE_ATTRIBUTES();
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
/*
|
|
1877
|
+
* Write the <c:tickLblPos> element.
|
|
1878
|
+
*/
|
|
1879
|
+
STATIC void
|
|
1880
|
+
_chart_write_tick_lbl_pos(lxw_chart *self)
|
|
1881
|
+
{
|
|
1882
|
+
struct xml_attribute_list attributes;
|
|
1883
|
+
struct xml_attribute *attribute;
|
|
1884
|
+
char val[] = "nextTo";
|
|
1885
|
+
|
|
1886
|
+
LXW_INIT_ATTRIBUTES();
|
|
1887
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1888
|
+
|
|
1889
|
+
lxw_xml_empty_tag(self->file, "c:tickLblPos", &attributes);
|
|
1890
|
+
|
|
1891
|
+
LXW_FREE_ATTRIBUTES();
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
/*
|
|
1895
|
+
* Write the <c:crossAx> element.
|
|
1896
|
+
*/
|
|
1897
|
+
STATIC void
|
|
1898
|
+
_chart_write_cross_axis(lxw_chart *self, uint32_t axis_id)
|
|
1899
|
+
{
|
|
1900
|
+
struct xml_attribute_list attributes;
|
|
1901
|
+
struct xml_attribute *attribute;
|
|
1902
|
+
|
|
1903
|
+
LXW_INIT_ATTRIBUTES();
|
|
1904
|
+
LXW_PUSH_ATTRIBUTES_INT("val", axis_id);
|
|
1905
|
+
|
|
1906
|
+
lxw_xml_empty_tag(self->file, "c:crossAx", &attributes);
|
|
1907
|
+
|
|
1908
|
+
LXW_FREE_ATTRIBUTES();
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
/*
|
|
1912
|
+
* Write the <c:crosses> element.
|
|
1913
|
+
*/
|
|
1914
|
+
STATIC void
|
|
1915
|
+
_chart_write_crosses(lxw_chart *self)
|
|
1916
|
+
{
|
|
1917
|
+
struct xml_attribute_list attributes;
|
|
1918
|
+
struct xml_attribute *attribute;
|
|
1919
|
+
char val[] = "autoZero";
|
|
1920
|
+
|
|
1921
|
+
LXW_INIT_ATTRIBUTES();
|
|
1922
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1923
|
+
|
|
1924
|
+
lxw_xml_empty_tag(self->file, "c:crosses", &attributes);
|
|
1925
|
+
|
|
1926
|
+
LXW_FREE_ATTRIBUTES();
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
/*
|
|
1930
|
+
* Write the <c:auto> element.
|
|
1931
|
+
*/
|
|
1932
|
+
STATIC void
|
|
1933
|
+
_chart_write_auto(lxw_chart *self)
|
|
1934
|
+
{
|
|
1935
|
+
struct xml_attribute_list attributes;
|
|
1936
|
+
struct xml_attribute *attribute;
|
|
1937
|
+
char val[] = "1";
|
|
1938
|
+
|
|
1939
|
+
LXW_INIT_ATTRIBUTES();
|
|
1940
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1941
|
+
|
|
1942
|
+
lxw_xml_empty_tag(self->file, "c:auto", &attributes);
|
|
1943
|
+
|
|
1944
|
+
LXW_FREE_ATTRIBUTES();
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
/*
|
|
1948
|
+
* Write the <c:lblAlgn> element.
|
|
1949
|
+
*/
|
|
1950
|
+
STATIC void
|
|
1951
|
+
_chart_write_lbl_algn(lxw_chart *self)
|
|
1952
|
+
{
|
|
1953
|
+
struct xml_attribute_list attributes;
|
|
1954
|
+
struct xml_attribute *attribute;
|
|
1955
|
+
char val[] = "ctr";
|
|
1956
|
+
|
|
1957
|
+
LXW_INIT_ATTRIBUTES();
|
|
1958
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1959
|
+
|
|
1960
|
+
lxw_xml_empty_tag(self->file, "c:lblAlgn", &attributes);
|
|
1961
|
+
|
|
1962
|
+
LXW_FREE_ATTRIBUTES();
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
/*
|
|
1966
|
+
* Write the <c:lblOffset> element.
|
|
1967
|
+
*/
|
|
1968
|
+
STATIC void
|
|
1969
|
+
_chart_write_lbl_offset(lxw_chart *self)
|
|
1970
|
+
{
|
|
1971
|
+
struct xml_attribute_list attributes;
|
|
1972
|
+
struct xml_attribute *attribute;
|
|
1973
|
+
char val[] = "100";
|
|
1974
|
+
|
|
1975
|
+
LXW_INIT_ATTRIBUTES();
|
|
1976
|
+
LXW_PUSH_ATTRIBUTES_STR("val", val);
|
|
1977
|
+
|
|
1978
|
+
lxw_xml_empty_tag(self->file, "c:lblOffset", &attributes);
|
|
1979
|
+
|
|
1980
|
+
LXW_FREE_ATTRIBUTES();
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
/*
|
|
1984
|
+
* Write the <c:majorGridlines> element.
|
|
1985
|
+
*/
|
|
1986
|
+
STATIC void
|
|
1987
|
+
_chart_write_major_gridlines(lxw_chart *self, lxw_chart_axis *axis)
|
|
1988
|
+
{
|
|
1989
|
+
|
|
1990
|
+
if (axis->default_major_gridlines)
|
|
1991
|
+
lxw_xml_empty_tag(self->file, "c:majorGridlines", NULL);
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
/*
|
|
1995
|
+
* Write the <c:numFmt> element.
|
|
1996
|
+
*/
|
|
1997
|
+
STATIC void
|
|
1998
|
+
_chart_write_number_format(lxw_chart *self, lxw_chart_axis *axis)
|
|
1999
|
+
{
|
|
2000
|
+
struct xml_attribute_list attributes;
|
|
2001
|
+
struct xml_attribute *attribute;
|
|
2002
|
+
char source_linked[] = "1";
|
|
2003
|
+
|
|
2004
|
+
LXW_INIT_ATTRIBUTES();
|
|
2005
|
+
LXW_PUSH_ATTRIBUTES_STR("formatCode", axis->default_num_format);
|
|
2006
|
+
LXW_PUSH_ATTRIBUTES_STR("sourceLinked", source_linked);
|
|
2007
|
+
|
|
2008
|
+
lxw_xml_empty_tag(self->file, "c:numFmt", &attributes);
|
|
2009
|
+
|
|
2010
|
+
LXW_FREE_ATTRIBUTES();
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
/*
|
|
2014
|
+
* Write the <c:crossBetween> element.
|
|
2015
|
+
*/
|
|
2016
|
+
STATIC void
|
|
2017
|
+
_chart_write_cross_between(lxw_chart *self)
|
|
2018
|
+
{
|
|
2019
|
+
struct xml_attribute_list attributes;
|
|
2020
|
+
struct xml_attribute *attribute;
|
|
2021
|
+
|
|
2022
|
+
LXW_INIT_ATTRIBUTES();
|
|
2023
|
+
|
|
2024
|
+
if (self->cross_between)
|
|
2025
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "midCat");
|
|
2026
|
+
else
|
|
2027
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "between");
|
|
2028
|
+
|
|
2029
|
+
lxw_xml_empty_tag(self->file, "c:crossBetween", &attributes);
|
|
2030
|
+
|
|
2031
|
+
LXW_FREE_ATTRIBUTES();
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
/*
|
|
2035
|
+
* Write the <c:overlay> element.
|
|
2036
|
+
*/
|
|
2037
|
+
STATIC void
|
|
2038
|
+
_chart_write_overlay(lxw_chart *self)
|
|
2039
|
+
{
|
|
2040
|
+
struct xml_attribute_list attributes;
|
|
2041
|
+
struct xml_attribute *attribute;
|
|
2042
|
+
|
|
2043
|
+
LXW_INIT_ATTRIBUTES();
|
|
2044
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "1");
|
|
2045
|
+
|
|
2046
|
+
lxw_xml_empty_tag(self->file, "c:overlay", &attributes);
|
|
2047
|
+
|
|
2048
|
+
LXW_FREE_ATTRIBUTES();
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
/*
|
|
2052
|
+
* Write the <c:legendPos> element.
|
|
2053
|
+
*/
|
|
2054
|
+
STATIC void
|
|
2055
|
+
_chart_write_legend_pos(lxw_chart *self, char *position)
|
|
2056
|
+
{
|
|
2057
|
+
struct xml_attribute_list attributes;
|
|
2058
|
+
struct xml_attribute *attribute;
|
|
2059
|
+
|
|
2060
|
+
LXW_INIT_ATTRIBUTES();
|
|
2061
|
+
|
|
2062
|
+
LXW_PUSH_ATTRIBUTES_STR("val", position);
|
|
2063
|
+
|
|
2064
|
+
lxw_xml_empty_tag(self->file, "c:legendPos", &attributes);
|
|
2065
|
+
|
|
2066
|
+
LXW_FREE_ATTRIBUTES();
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
/*
|
|
2070
|
+
* Write the <c:legendEntry> element.
|
|
2071
|
+
*/
|
|
2072
|
+
STATIC void
|
|
2073
|
+
_chart_write_legend_entry(lxw_chart *self, uint16_t index)
|
|
2074
|
+
{
|
|
2075
|
+
lxw_xml_start_tag(self->file, "c:legendEntry", NULL);
|
|
2076
|
+
|
|
2077
|
+
/* Write the c:idx element. */
|
|
2078
|
+
_chart_write_idx(self, self->delete_series[index]);
|
|
2079
|
+
|
|
2080
|
+
/* Write the c:delete element. */
|
|
2081
|
+
_chart_write_delete(self);
|
|
2082
|
+
|
|
2083
|
+
lxw_xml_end_tag(self->file, "c:legendEntry");
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
/*
|
|
2087
|
+
* Write the <c:legend> element.
|
|
2088
|
+
*/
|
|
2089
|
+
STATIC void
|
|
2090
|
+
_chart_write_legend(lxw_chart *self)
|
|
2091
|
+
{
|
|
2092
|
+
uint8_t has_overlay = LXW_FALSE;
|
|
2093
|
+
uint16_t index;
|
|
2094
|
+
|
|
2095
|
+
if (self->legend.position == LXW_CHART_LEGEND_NONE)
|
|
2096
|
+
return;
|
|
2097
|
+
|
|
2098
|
+
lxw_xml_start_tag(self->file, "c:legend", NULL);
|
|
2099
|
+
|
|
2100
|
+
/* Write the c:legendPos element. */
|
|
2101
|
+
switch (self->legend.position) {
|
|
2102
|
+
case LXW_CHART_LEGEND_LEFT:
|
|
2103
|
+
_chart_write_legend_pos(self, "l");
|
|
2104
|
+
break;
|
|
2105
|
+
case LXW_CHART_LEGEND_TOP:
|
|
2106
|
+
_chart_write_legend_pos(self, "t");
|
|
2107
|
+
break;
|
|
2108
|
+
case LXW_CHART_LEGEND_BOTTOM:
|
|
2109
|
+
_chart_write_legend_pos(self, "b");
|
|
2110
|
+
break;
|
|
2111
|
+
case LXW_CHART_LEGEND_OVERLAY_RIGHT:
|
|
2112
|
+
_chart_write_legend_pos(self, "r");
|
|
2113
|
+
has_overlay = LXW_TRUE;
|
|
2114
|
+
break;
|
|
2115
|
+
case LXW_CHART_LEGEND_OVERLAY_LEFT:
|
|
2116
|
+
_chart_write_legend_pos(self, "l");
|
|
2117
|
+
has_overlay = LXW_TRUE;
|
|
2118
|
+
break;
|
|
2119
|
+
default:
|
|
2120
|
+
_chart_write_legend_pos(self, "r");
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
/* Remove series labels from the legend. */
|
|
2124
|
+
for (index = 0; index < self->delete_series_count; index++) {
|
|
2125
|
+
/* Write the c:legendEntry element. */
|
|
2126
|
+
_chart_write_legend_entry(self, index);
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
/* Write the c:layout element. */
|
|
2130
|
+
_chart_write_layout(self);
|
|
2131
|
+
|
|
2132
|
+
if (self->type == LXW_CHART_PIE || self->type == LXW_CHART_DOUGHNUT) {
|
|
2133
|
+
/* Write the c:overlay element. */
|
|
2134
|
+
if (has_overlay)
|
|
2135
|
+
_chart_write_overlay(self);
|
|
2136
|
+
|
|
2137
|
+
/* Write the c:txPr element for Pie/Doughnut charts. */
|
|
2138
|
+
_chart_write_tx_pr_pie(self, LXW_FALSE, self->legend.font);
|
|
2139
|
+
}
|
|
2140
|
+
else {
|
|
2141
|
+
/* Write the c:txPr element for all other charts. */
|
|
2142
|
+
if (self->legend.font)
|
|
2143
|
+
_chart_write_tx_pr(self, LXW_FALSE, self->legend.font);
|
|
2144
|
+
|
|
2145
|
+
/* Write the c:overlay element. */
|
|
2146
|
+
if (has_overlay)
|
|
2147
|
+
_chart_write_overlay(self);
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
lxw_xml_end_tag(self->file, "c:legend");
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
/*
|
|
2154
|
+
* Write the <c:plotVisOnly> element.
|
|
2155
|
+
*/
|
|
2156
|
+
STATIC void
|
|
2157
|
+
_chart_write_plot_vis_only(lxw_chart *self)
|
|
2158
|
+
{
|
|
2159
|
+
struct xml_attribute_list attributes;
|
|
2160
|
+
struct xml_attribute *attribute;
|
|
2161
|
+
|
|
2162
|
+
LXW_INIT_ATTRIBUTES();
|
|
2163
|
+
LXW_PUSH_ATTRIBUTES_STR("val", "1");
|
|
2164
|
+
|
|
2165
|
+
lxw_xml_empty_tag(self->file, "c:plotVisOnly", &attributes);
|
|
2166
|
+
|
|
2167
|
+
LXW_FREE_ATTRIBUTES();
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
/*
|
|
2171
|
+
* Write the <c:headerFooter> element.
|
|
2172
|
+
*/
|
|
2173
|
+
STATIC void
|
|
2174
|
+
_chart_write_header_footer(lxw_chart *self)
|
|
2175
|
+
{
|
|
2176
|
+
lxw_xml_empty_tag(self->file, "c:headerFooter", NULL);
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
/*
|
|
2180
|
+
* Write the <c:pageMargins> element.
|
|
2181
|
+
*/
|
|
2182
|
+
STATIC void
|
|
2183
|
+
_chart_write_page_margins(lxw_chart *self)
|
|
2184
|
+
{
|
|
2185
|
+
struct xml_attribute_list attributes;
|
|
2186
|
+
struct xml_attribute *attribute;
|
|
2187
|
+
char b[] = "0.75";
|
|
2188
|
+
char l[] = "0.7";
|
|
2189
|
+
char r[] = "0.7";
|
|
2190
|
+
char t[] = "0.75";
|
|
2191
|
+
char header[] = "0.3";
|
|
2192
|
+
char footer[] = "0.3";
|
|
2193
|
+
|
|
2194
|
+
LXW_INIT_ATTRIBUTES();
|
|
2195
|
+
LXW_PUSH_ATTRIBUTES_STR("b", b);
|
|
2196
|
+
LXW_PUSH_ATTRIBUTES_STR("l", l);
|
|
2197
|
+
LXW_PUSH_ATTRIBUTES_STR("r", r);
|
|
2198
|
+
LXW_PUSH_ATTRIBUTES_STR("t", t);
|
|
2199
|
+
LXW_PUSH_ATTRIBUTES_STR("header", header);
|
|
2200
|
+
LXW_PUSH_ATTRIBUTES_STR("footer", footer);
|
|
2201
|
+
|
|
2202
|
+
lxw_xml_empty_tag(self->file, "c:pageMargins", &attributes);
|
|
2203
|
+
|
|
2204
|
+
LXW_FREE_ATTRIBUTES();
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
/*
|
|
2208
|
+
* Write the <c:pageSetup> element.
|
|
2209
|
+
*/
|
|
2210
|
+
STATIC void
|
|
2211
|
+
_chart_write_page_setup(lxw_chart *self)
|
|
2212
|
+
{
|
|
2213
|
+
lxw_xml_empty_tag(self->file, "c:pageSetup", NULL);
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
/*
|
|
2217
|
+
* Write the <c:printSettings> element.
|
|
2218
|
+
*/
|
|
2219
|
+
STATIC void
|
|
2220
|
+
_chart_write_print_settings(lxw_chart *self)
|
|
2221
|
+
{
|
|
2222
|
+
lxw_xml_start_tag(self->file, "c:printSettings", NULL);
|
|
2223
|
+
|
|
2224
|
+
/* Write the c:headerFooter element. */
|
|
2225
|
+
_chart_write_header_footer(self);
|
|
2226
|
+
|
|
2227
|
+
/* Write the c:pageMargins element. */
|
|
2228
|
+
_chart_write_page_margins(self);
|
|
2229
|
+
|
|
2230
|
+
/* Write the c:pageSetup element. */
|
|
2231
|
+
_chart_write_page_setup(self);
|
|
2232
|
+
|
|
2233
|
+
lxw_xml_end_tag(self->file, "c:printSettings");
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
/*
|
|
2237
|
+
* Write the <c:overlap> element.
|
|
2238
|
+
*/
|
|
2239
|
+
STATIC void
|
|
2240
|
+
_chart_write_overlap(lxw_chart *self, int overlap)
|
|
2241
|
+
{
|
|
2242
|
+
struct xml_attribute_list attributes;
|
|
2243
|
+
struct xml_attribute *attribute;
|
|
2244
|
+
|
|
2245
|
+
LXW_INIT_ATTRIBUTES();
|
|
2246
|
+
LXW_PUSH_ATTRIBUTES_INT("val", overlap);
|
|
2247
|
+
|
|
2248
|
+
lxw_xml_empty_tag(self->file, "c:overlap", &attributes);
|
|
2249
|
+
|
|
2250
|
+
LXW_FREE_ATTRIBUTES();
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
/*
|
|
2254
|
+
* Write the <c:title> element.
|
|
2255
|
+
*/
|
|
2256
|
+
STATIC void
|
|
2257
|
+
_chart_write_title(lxw_chart *self, lxw_chart_title *title)
|
|
2258
|
+
{
|
|
2259
|
+
if (title->name) {
|
|
2260
|
+
/* Write the c:title element. */
|
|
2261
|
+
_chart_write_title_rich(self, title);
|
|
2262
|
+
}
|
|
2263
|
+
else if (title->range->formula) {
|
|
2264
|
+
/* Write the c:title element. */
|
|
2265
|
+
_chart_write_title_formula(self, title);
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
/*
|
|
2270
|
+
* Write the <c:title> element.
|
|
2271
|
+
*/
|
|
2272
|
+
STATIC void
|
|
2273
|
+
_chart_write_chart_title(lxw_chart *self)
|
|
2274
|
+
{
|
|
2275
|
+
if (self->title.off) {
|
|
2276
|
+
/* Write the c:autoTitleDeleted element. */
|
|
2277
|
+
_chart_write_auto_title_deleted(self);
|
|
2278
|
+
}
|
|
2279
|
+
else {
|
|
2280
|
+
/* Write the c:title element. */
|
|
2281
|
+
_chart_write_title(self, &self->title);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
/*
|
|
2286
|
+
* Write the <c:catAx> element. Usually the X axis.
|
|
2287
|
+
*/
|
|
2288
|
+
STATIC void
|
|
2289
|
+
_chart_write_cat_axis(lxw_chart *self)
|
|
2290
|
+
{
|
|
2291
|
+
uint8_t position = self->cat_axis_position;
|
|
2292
|
+
|
|
2293
|
+
lxw_xml_start_tag(self->file, "c:catAx", NULL);
|
|
2294
|
+
|
|
2295
|
+
_chart_write_axis_id(self, self->axis_id_1);
|
|
2296
|
+
|
|
2297
|
+
/* Write the c:scaling element. */
|
|
2298
|
+
_chart_write_scaling(self);
|
|
2299
|
+
|
|
2300
|
+
/* Write the c:axPos element. */
|
|
2301
|
+
_chart_write_axis_pos(self, position);
|
|
2302
|
+
|
|
2303
|
+
/* Write the c:majorGridlines element. */
|
|
2304
|
+
_chart_write_major_gridlines(self, self->x_axis);
|
|
2305
|
+
|
|
2306
|
+
/* Write the axis title elements. */
|
|
2307
|
+
self->x_axis->title.is_horizontal = self->has_horiz_cat_axis;
|
|
2308
|
+
_chart_write_title(self, &self->x_axis->title);
|
|
2309
|
+
|
|
2310
|
+
/* Write the c:numFmt element. */
|
|
2311
|
+
if (self->cat_has_num_fmt)
|
|
2312
|
+
_chart_write_number_format(self, self->x_axis);
|
|
2313
|
+
|
|
2314
|
+
/* Write the c:majorTickMark element. */
|
|
2315
|
+
_chart_write_major_tick_mark(self, self->x_axis);
|
|
2316
|
+
|
|
2317
|
+
/* Write the c:tickLblPos element. */
|
|
2318
|
+
_chart_write_tick_lbl_pos(self);
|
|
2319
|
+
|
|
2320
|
+
/* Write the c:spPr element for the axis line. */
|
|
2321
|
+
_chart_write_sp_pr(self, self->x_axis->line, self->x_axis->fill);
|
|
2322
|
+
|
|
2323
|
+
/* Write the axis font elements. */
|
|
2324
|
+
_chart_write_axis_font(self, self->x_axis->num_font);
|
|
2325
|
+
|
|
2326
|
+
/* Write the c:crossAx element. */
|
|
2327
|
+
_chart_write_cross_axis(self, self->axis_id_2);
|
|
2328
|
+
|
|
2329
|
+
/* Write the c:crosses element. */
|
|
2330
|
+
_chart_write_crosses(self);
|
|
2331
|
+
|
|
2332
|
+
/* Write the c:auto element. */
|
|
2333
|
+
_chart_write_auto(self);
|
|
2334
|
+
|
|
2335
|
+
/* Write the c:lblAlgn element. */
|
|
2336
|
+
_chart_write_lbl_algn(self);
|
|
2337
|
+
|
|
2338
|
+
/* Write the c:lblOffset element. */
|
|
2339
|
+
_chart_write_lbl_offset(self);
|
|
2340
|
+
|
|
2341
|
+
lxw_xml_end_tag(self->file, "c:catAx");
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
/*
|
|
2345
|
+
* Write the <c:valAx> element.
|
|
2346
|
+
*/
|
|
2347
|
+
STATIC void
|
|
2348
|
+
_chart_write_val_axis(lxw_chart *self)
|
|
2349
|
+
{
|
|
2350
|
+
uint8_t position = self->val_axis_position;
|
|
2351
|
+
|
|
2352
|
+
lxw_xml_start_tag(self->file, "c:valAx", NULL);
|
|
2353
|
+
|
|
2354
|
+
_chart_write_axis_id(self, self->axis_id_2);
|
|
2355
|
+
|
|
2356
|
+
/* Write the c:scaling element. */
|
|
2357
|
+
_chart_write_scaling(self);
|
|
2358
|
+
|
|
2359
|
+
/* Write the c:axPos element. */
|
|
2360
|
+
_chart_write_axis_pos(self, position);
|
|
2361
|
+
|
|
2362
|
+
/* Write the c:majorGridlines element. */
|
|
2363
|
+
_chart_write_major_gridlines(self, self->y_axis);
|
|
2364
|
+
|
|
2365
|
+
/* Write the axis title elements. */
|
|
2366
|
+
self->y_axis->title.is_horizontal = self->has_horiz_val_axis;
|
|
2367
|
+
_chart_write_title(self, &self->y_axis->title);
|
|
2368
|
+
|
|
2369
|
+
/* Write the c:numFmt element. */
|
|
2370
|
+
_chart_write_number_format(self, self->y_axis);
|
|
2371
|
+
|
|
2372
|
+
/* Write the c:majorTickMark element. */
|
|
2373
|
+
_chart_write_major_tick_mark(self, self->y_axis);
|
|
2374
|
+
|
|
2375
|
+
/* Write the c:tickLblPos element. */
|
|
2376
|
+
_chart_write_tick_lbl_pos(self);
|
|
2377
|
+
|
|
2378
|
+
/* Write the c:spPr element for the axis line. */
|
|
2379
|
+
_chart_write_sp_pr(self, self->y_axis->line, self->y_axis->fill);
|
|
2380
|
+
|
|
2381
|
+
/* Write the axis font elements. */
|
|
2382
|
+
_chart_write_axis_font(self, self->y_axis->num_font);
|
|
2383
|
+
|
|
2384
|
+
/* Write the c:crossAx element. */
|
|
2385
|
+
_chart_write_cross_axis(self, self->axis_id_1);
|
|
2386
|
+
|
|
2387
|
+
/* Write the c:crosses element. */
|
|
2388
|
+
_chart_write_crosses(self);
|
|
2389
|
+
|
|
2390
|
+
/* Write the c:crossBetween element. */
|
|
2391
|
+
_chart_write_cross_between(self);
|
|
2392
|
+
|
|
2393
|
+
lxw_xml_end_tag(self->file, "c:valAx");
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
/*
|
|
2397
|
+
* Write the <c:valAx> element. This is for the second valAx in scatter plots.
|
|
2398
|
+
*/
|
|
2399
|
+
STATIC void
|
|
2400
|
+
_chart_write_cat_val_axis(lxw_chart *self)
|
|
2401
|
+
{
|
|
2402
|
+
uint8_t position = self->cat_axis_position;
|
|
2403
|
+
|
|
2404
|
+
lxw_xml_start_tag(self->file, "c:valAx", NULL);
|
|
2405
|
+
|
|
2406
|
+
_chart_write_axis_id(self, self->axis_id_1);
|
|
2407
|
+
|
|
2408
|
+
/* Write the c:scaling element. */
|
|
2409
|
+
_chart_write_scaling(self);
|
|
2410
|
+
|
|
2411
|
+
/* Write the c:axPos element. */
|
|
2412
|
+
_chart_write_axis_pos(self, position);
|
|
2413
|
+
|
|
2414
|
+
/* Write the axis title elements. */
|
|
2415
|
+
self->x_axis->title.is_horizontal = self->has_horiz_val_axis;
|
|
2416
|
+
_chart_write_title(self, &self->x_axis->title);
|
|
2417
|
+
|
|
2418
|
+
/* Write the c:numFmt element. */
|
|
2419
|
+
_chart_write_number_format(self, self->x_axis);
|
|
2420
|
+
|
|
2421
|
+
/* Write the c:majorTickMark element. */
|
|
2422
|
+
_chart_write_major_tick_mark(self, self->x_axis);
|
|
2423
|
+
|
|
2424
|
+
/* Write the c:tickLblPos element. */
|
|
2425
|
+
_chart_write_tick_lbl_pos(self);
|
|
2426
|
+
|
|
2427
|
+
/* Write the c:spPr element for the axis line. */
|
|
2428
|
+
_chart_write_sp_pr(self, self->x_axis->line, self->x_axis->fill);
|
|
2429
|
+
|
|
2430
|
+
/* Write the axis font elements. */
|
|
2431
|
+
_chart_write_axis_font(self, self->x_axis->num_font);
|
|
2432
|
+
|
|
2433
|
+
/* Write the c:crossAx element. */
|
|
2434
|
+
_chart_write_cross_axis(self, self->axis_id_2);
|
|
2435
|
+
|
|
2436
|
+
/* Write the c:crosses element. */
|
|
2437
|
+
_chart_write_crosses(self);
|
|
2438
|
+
|
|
2439
|
+
/* Write the c:crossBetween element. */
|
|
2440
|
+
_chart_write_cross_between(self);
|
|
2441
|
+
|
|
2442
|
+
lxw_xml_end_tag(self->file, "c:valAx");
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
/*
|
|
2446
|
+
* Write the <c:barDir> element.
|
|
2447
|
+
*/
|
|
2448
|
+
STATIC void
|
|
2449
|
+
_chart_write_bar_dir(lxw_chart *self, char *type)
|
|
2450
|
+
{
|
|
2451
|
+
struct xml_attribute_list attributes;
|
|
2452
|
+
struct xml_attribute *attribute;
|
|
2453
|
+
|
|
2454
|
+
LXW_INIT_ATTRIBUTES();
|
|
2455
|
+
LXW_PUSH_ATTRIBUTES_STR("val", type);
|
|
2456
|
+
|
|
2457
|
+
lxw_xml_empty_tag(self->file, "c:barDir", &attributes);
|
|
2458
|
+
|
|
2459
|
+
LXW_FREE_ATTRIBUTES();
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
/*
|
|
2463
|
+
* Write a area chart.
|
|
2464
|
+
*/
|
|
2465
|
+
STATIC void
|
|
2466
|
+
_chart_write_area_chart(lxw_chart *self)
|
|
2467
|
+
{
|
|
2468
|
+
lxw_chart_series *series;
|
|
2469
|
+
|
|
2470
|
+
lxw_xml_start_tag(self->file, "c:areaChart", NULL);
|
|
2471
|
+
|
|
2472
|
+
/* Write the c:grouping element. */
|
|
2473
|
+
_chart_write_grouping(self, self->grouping);
|
|
2474
|
+
|
|
2475
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2476
|
+
/* Write the c:ser element. */
|
|
2477
|
+
_chart_write_ser(self, series);
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
if (self->has_overlap) {
|
|
2481
|
+
/* Write the c:overlap element. */
|
|
2482
|
+
_chart_write_overlap(self, self->series_overlap_1);
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
/* Write the c:axId elements. */
|
|
2486
|
+
_chart_write_axis_ids(self);
|
|
2487
|
+
|
|
2488
|
+
lxw_xml_end_tag(self->file, "c:areaChart");
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
/*
|
|
2492
|
+
* Write a bar chart.
|
|
2493
|
+
*/
|
|
2494
|
+
STATIC void
|
|
2495
|
+
_chart_write_bar_chart(lxw_chart *self)
|
|
2496
|
+
{
|
|
2497
|
+
lxw_chart_series *series;
|
|
2498
|
+
|
|
2499
|
+
lxw_xml_start_tag(self->file, "c:barChart", NULL);
|
|
2500
|
+
|
|
2501
|
+
/* Write the c:barDir element. */
|
|
2502
|
+
_chart_write_bar_dir(self, "bar");
|
|
2503
|
+
|
|
2504
|
+
/* Write the c:grouping element. */
|
|
2505
|
+
_chart_write_grouping(self, self->grouping);
|
|
2506
|
+
|
|
2507
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2508
|
+
/* Write the c:ser element. */
|
|
2509
|
+
_chart_write_ser(self, series);
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
if (self->has_overlap) {
|
|
2513
|
+
/* Write the c:overlap element. */
|
|
2514
|
+
_chart_write_overlap(self, self->series_overlap_1);
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
/* Write the c:axId elements. */
|
|
2518
|
+
_chart_write_axis_ids(self);
|
|
2519
|
+
|
|
2520
|
+
lxw_xml_end_tag(self->file, "c:barChart");
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
/*
|
|
2524
|
+
* Write a column chart.
|
|
2525
|
+
*/
|
|
2526
|
+
STATIC void
|
|
2527
|
+
_chart_write_column_chart(lxw_chart *self)
|
|
2528
|
+
{
|
|
2529
|
+
lxw_chart_series *series;
|
|
2530
|
+
|
|
2531
|
+
lxw_xml_start_tag(self->file, "c:barChart", NULL);
|
|
2532
|
+
|
|
2533
|
+
/* Write the c:barDir element. */
|
|
2534
|
+
_chart_write_bar_dir(self, "col");
|
|
2535
|
+
|
|
2536
|
+
/* Write the c:grouping element. */
|
|
2537
|
+
_chart_write_grouping(self, self->grouping);
|
|
2538
|
+
|
|
2539
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2540
|
+
/* Write the c:ser element. */
|
|
2541
|
+
_chart_write_ser(self, series);
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
if (self->has_overlap) {
|
|
2545
|
+
/* Write the c:overlap element. */
|
|
2546
|
+
_chart_write_overlap(self, self->series_overlap_1);
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
/* Write the c:axId elements. */
|
|
2550
|
+
_chart_write_axis_ids(self);
|
|
2551
|
+
|
|
2552
|
+
lxw_xml_end_tag(self->file, "c:barChart");
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
/*
|
|
2556
|
+
* Write a doughnut chart.
|
|
2557
|
+
*/
|
|
2558
|
+
STATIC void
|
|
2559
|
+
_chart_write_doughnut_chart(lxw_chart *self)
|
|
2560
|
+
{
|
|
2561
|
+
lxw_chart_series *series;
|
|
2562
|
+
|
|
2563
|
+
lxw_xml_start_tag(self->file, "c:doughnutChart", NULL);
|
|
2564
|
+
|
|
2565
|
+
/* Write the c:varyColors element. */
|
|
2566
|
+
_chart_write_vary_colors(self);
|
|
2567
|
+
|
|
2568
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2569
|
+
/* Write the c:ser element. */
|
|
2570
|
+
_chart_write_ser(self, series);
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
/* Write the c:firstSliceAng element. */
|
|
2574
|
+
_chart_write_first_slice_ang(self);
|
|
2575
|
+
|
|
2576
|
+
/* Write the c:holeSize element. */
|
|
2577
|
+
_chart_write_hole_size(self);
|
|
2578
|
+
|
|
2579
|
+
lxw_xml_end_tag(self->file, "c:doughnutChart");
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
/*
|
|
2583
|
+
* Write a line chart.
|
|
2584
|
+
*/
|
|
2585
|
+
STATIC void
|
|
2586
|
+
_chart_write_line_chart(lxw_chart *self)
|
|
2587
|
+
{
|
|
2588
|
+
lxw_chart_series *series;
|
|
2589
|
+
|
|
2590
|
+
lxw_xml_start_tag(self->file, "c:lineChart", NULL);
|
|
2591
|
+
|
|
2592
|
+
/* Write the c:grouping element. */
|
|
2593
|
+
_chart_write_grouping(self, self->grouping);
|
|
2594
|
+
|
|
2595
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2596
|
+
/* Write the c:ser element. */
|
|
2597
|
+
_chart_write_ser(self, series);
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
/* Write the c:marker element. */
|
|
2601
|
+
_chart_write_marker_value(self);
|
|
2602
|
+
|
|
2603
|
+
/* Write the c:axId elements. */
|
|
2604
|
+
_chart_write_axis_ids(self);
|
|
2605
|
+
|
|
2606
|
+
lxw_xml_end_tag(self->file, "c:lineChart");
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
/*
|
|
2610
|
+
* Write a pie chart.
|
|
2611
|
+
*/
|
|
2612
|
+
STATIC void
|
|
2613
|
+
_chart_write_pie_chart(lxw_chart *self)
|
|
2614
|
+
{
|
|
2615
|
+
lxw_chart_series *series;
|
|
2616
|
+
|
|
2617
|
+
lxw_xml_start_tag(self->file, "c:pieChart", NULL);
|
|
2618
|
+
|
|
2619
|
+
/* Write the c:varyColors element. */
|
|
2620
|
+
_chart_write_vary_colors(self);
|
|
2621
|
+
|
|
2622
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2623
|
+
/* Write the c:ser element. */
|
|
2624
|
+
_chart_write_ser(self, series);
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
/* Write the c:firstSliceAng element. */
|
|
2628
|
+
_chart_write_first_slice_ang(self);
|
|
2629
|
+
|
|
2630
|
+
lxw_xml_end_tag(self->file, "c:pieChart");
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2633
|
+
/*
|
|
2634
|
+
* Write a scatter chart.
|
|
2635
|
+
*/
|
|
2636
|
+
STATIC void
|
|
2637
|
+
_chart_write_scatter_chart(lxw_chart *self)
|
|
2638
|
+
{
|
|
2639
|
+
lxw_chart_series *series;
|
|
2640
|
+
|
|
2641
|
+
lxw_xml_start_tag(self->file, "c:scatterChart", NULL);
|
|
2642
|
+
|
|
2643
|
+
/* Write the c:scatterStyle element. */
|
|
2644
|
+
_chart_write_scatter_style(self);
|
|
2645
|
+
|
|
2646
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2647
|
+
|
|
2648
|
+
/* Add default scatter chart formatting to the series data unless
|
|
2649
|
+
* it has already been specified by the user.*/
|
|
2650
|
+
if (self->type == LXW_CHART_SCATTER) {
|
|
2651
|
+
if (!series->line) {
|
|
2652
|
+
lxw_chart_line line = {
|
|
2653
|
+
0x000000,
|
|
2654
|
+
LXW_TRUE,
|
|
2655
|
+
2.25,
|
|
2656
|
+
LXW_CHART_LINE_DASH_SOLID,
|
|
2657
|
+
0,
|
|
2658
|
+
LXW_FALSE
|
|
2659
|
+
};
|
|
2660
|
+
series->line = _chart_convert_line_args(&line);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
/* Write the c:ser element. */
|
|
2665
|
+
_chart_write_xval_ser(self, series);
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
/* Write the c:axId elements. */
|
|
2669
|
+
_chart_write_axis_ids(self);
|
|
2670
|
+
|
|
2671
|
+
lxw_xml_end_tag(self->file, "c:scatterChart");
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
/*
|
|
2675
|
+
* Write a radar chart.
|
|
2676
|
+
*/
|
|
2677
|
+
STATIC void
|
|
2678
|
+
_chart_write_radar_chart(lxw_chart *self)
|
|
2679
|
+
{
|
|
2680
|
+
lxw_chart_series *series;
|
|
2681
|
+
|
|
2682
|
+
lxw_xml_start_tag(self->file, "c:radarChart", NULL);
|
|
2683
|
+
|
|
2684
|
+
/* Write the c:radarStyle element. */
|
|
2685
|
+
_chart_write_radar_style(self);
|
|
2686
|
+
|
|
2687
|
+
STAILQ_FOREACH(series, self->series_list, list_pointers) {
|
|
2688
|
+
/* Write the c:ser element. */
|
|
2689
|
+
_chart_write_ser(self, series);
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
if (self->has_overlap) {
|
|
2693
|
+
/* Write the c:overlap element. */
|
|
2694
|
+
_chart_write_overlap(self, self->series_overlap_1);
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
/* Write the c:axId elements. */
|
|
2698
|
+
_chart_write_axis_ids(self);
|
|
2699
|
+
|
|
2700
|
+
lxw_xml_end_tag(self->file, "c:radarChart");
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
/*
|
|
2704
|
+
* Write the <c:plotArea> element.
|
|
2705
|
+
*/
|
|
2706
|
+
STATIC void
|
|
2707
|
+
_chart_write_scatter_plot_area(lxw_chart *self)
|
|
2708
|
+
{
|
|
2709
|
+
lxw_xml_start_tag(self->file, "c:plotArea", NULL);
|
|
2710
|
+
|
|
2711
|
+
/* Write the c:layout element. */
|
|
2712
|
+
_chart_write_layout(self);
|
|
2713
|
+
|
|
2714
|
+
/* Write subclass chart type elements for primary and secondary axes. */
|
|
2715
|
+
self->write_chart_type(self);
|
|
2716
|
+
|
|
2717
|
+
/* Write the c:catAx element. */
|
|
2718
|
+
_chart_write_cat_val_axis(self);
|
|
2719
|
+
|
|
2720
|
+
self->has_horiz_val_axis = LXW_TRUE;
|
|
2721
|
+
|
|
2722
|
+
/* Write the c:valAx element. */
|
|
2723
|
+
_chart_write_val_axis(self);
|
|
2724
|
+
|
|
2725
|
+
lxw_xml_end_tag(self->file, "c:plotArea");
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
/*
|
|
2729
|
+
* Write the <c:plotArea> element. Special handling for pie/doughnut.
|
|
2730
|
+
*/
|
|
2731
|
+
STATIC void
|
|
2732
|
+
_chart_write_pie_plot_area(lxw_chart *self)
|
|
2733
|
+
{
|
|
2734
|
+
lxw_xml_start_tag(self->file, "c:plotArea", NULL);
|
|
2735
|
+
|
|
2736
|
+
/* Write the c:layout element. */
|
|
2737
|
+
_chart_write_layout(self);
|
|
2738
|
+
|
|
2739
|
+
/* Write subclass chart type elements for primary and secondary axes. */
|
|
2740
|
+
self->write_chart_type(self);
|
|
2741
|
+
|
|
2742
|
+
lxw_xml_end_tag(self->file, "c:plotArea");
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
/*
|
|
2746
|
+
* Write the <c:plotArea> element.
|
|
2747
|
+
*/
|
|
2748
|
+
STATIC void
|
|
2749
|
+
_chart_write_plot_area(lxw_chart *self)
|
|
2750
|
+
{
|
|
2751
|
+
lxw_xml_start_tag(self->file, "c:plotArea", NULL);
|
|
2752
|
+
|
|
2753
|
+
/* Write the c:layout element. */
|
|
2754
|
+
_chart_write_layout(self);
|
|
2755
|
+
|
|
2756
|
+
/* Write subclass chart type elements for primary and secondary axes. */
|
|
2757
|
+
self->write_chart_type(self);
|
|
2758
|
+
|
|
2759
|
+
/* Write the c:catAx element. */
|
|
2760
|
+
_chart_write_cat_axis(self);
|
|
2761
|
+
|
|
2762
|
+
/* Write the c:valAx element. */
|
|
2763
|
+
_chart_write_val_axis(self);
|
|
2764
|
+
|
|
2765
|
+
lxw_xml_end_tag(self->file, "c:plotArea");
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
/*
|
|
2769
|
+
* Write the <c:chart> element.
|
|
2770
|
+
*/
|
|
2771
|
+
STATIC void
|
|
2772
|
+
_chart_write_chart(lxw_chart *self)
|
|
2773
|
+
{
|
|
2774
|
+
lxw_xml_start_tag(self->file, "c:chart", NULL);
|
|
2775
|
+
|
|
2776
|
+
/* Write the c:title element. */
|
|
2777
|
+
_chart_write_chart_title(self);
|
|
2778
|
+
|
|
2779
|
+
/* Write the c:plotArea element. */
|
|
2780
|
+
self->write_plot_area(self);
|
|
2781
|
+
|
|
2782
|
+
/* Write the c:legend element. */
|
|
2783
|
+
_chart_write_legend(self);
|
|
2784
|
+
|
|
2785
|
+
/* Write the c:plotVisOnly element. */
|
|
2786
|
+
_chart_write_plot_vis_only(self);
|
|
2787
|
+
|
|
2788
|
+
lxw_xml_end_tag(self->file, "c:chart");
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
/*
|
|
2792
|
+
* Initialize a area chart.
|
|
2793
|
+
*/
|
|
2794
|
+
STATIC void
|
|
2795
|
+
_chart_initialize_area_chart(lxw_chart *self, uint8_t type)
|
|
2796
|
+
{
|
|
2797
|
+
self->grouping = LXW_GROUPING_STANDARD;
|
|
2798
|
+
self->cross_between = LXW_CHART_AXIS_POSITION_ON_TICK;
|
|
2799
|
+
|
|
2800
|
+
if (type == LXW_CHART_AREA_STACKED) {
|
|
2801
|
+
self->grouping = LXW_GROUPING_STACKED;
|
|
2802
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
if (type == LXW_CHART_AREA_STACKED_PERCENT) {
|
|
2806
|
+
self->grouping = LXW_GROUPING_PERCENTSTACKED;
|
|
2807
|
+
lxw_strcpy((self->y_axis)->default_num_format, "0%");
|
|
2808
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
/* Initialize the function pointers for this chart type. */
|
|
2812
|
+
self->write_chart_type = _chart_write_area_chart;
|
|
2813
|
+
self->write_plot_area = _chart_write_plot_area;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
/*
|
|
2817
|
+
* Initialize a bar chart.
|
|
2818
|
+
*/
|
|
2819
|
+
STATIC void
|
|
2820
|
+
_chart_initialize_bar_chart(lxw_chart *self, uint8_t type)
|
|
2821
|
+
{
|
|
2822
|
+
lxw_chart_axis *tmp;
|
|
2823
|
+
|
|
2824
|
+
/* Reverse the X and Y axes for Bar charts. */
|
|
2825
|
+
tmp = self->x_axis;
|
|
2826
|
+
self->x_axis = self->y_axis;
|
|
2827
|
+
self->y_axis = tmp;
|
|
2828
|
+
|
|
2829
|
+
/*Also reverse some of the defaults. */
|
|
2830
|
+
self->x_axis->default_major_gridlines = LXW_FALSE;
|
|
2831
|
+
self->y_axis->default_major_gridlines = LXW_TRUE;
|
|
2832
|
+
self->has_horiz_cat_axis = LXW_TRUE;
|
|
2833
|
+
self->has_horiz_val_axis = LXW_FALSE;
|
|
2834
|
+
|
|
2835
|
+
if (type == LXW_CHART_BAR_STACKED) {
|
|
2836
|
+
self->grouping = LXW_GROUPING_STACKED;
|
|
2837
|
+
self->has_overlap = LXW_TRUE;
|
|
2838
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
if (type == LXW_CHART_BAR_STACKED_PERCENT) {
|
|
2842
|
+
self->grouping = LXW_GROUPING_PERCENTSTACKED;
|
|
2843
|
+
lxw_strcpy((self->y_axis)->default_num_format, "0%");
|
|
2844
|
+
self->has_overlap = LXW_TRUE;
|
|
2845
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
/* Override the default axis positions for a bar chart. */
|
|
2849
|
+
self->cat_axis_position = LXW_CHART_AXIS_LEFT;
|
|
2850
|
+
self->val_axis_position = LXW_CHART_AXIS_BOTTOM;
|
|
2851
|
+
|
|
2852
|
+
/* Initialize the function pointers for this chart type. */
|
|
2853
|
+
self->write_chart_type = _chart_write_bar_chart;
|
|
2854
|
+
self->write_plot_area = _chart_write_plot_area;
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
/*
|
|
2858
|
+
* Initialize a column chart.
|
|
2859
|
+
*/
|
|
2860
|
+
STATIC void
|
|
2861
|
+
_chart_initialize_column_chart(lxw_chart *self, uint8_t type)
|
|
2862
|
+
{
|
|
2863
|
+
self->has_horiz_val_axis = LXW_FALSE;
|
|
2864
|
+
|
|
2865
|
+
if (type == LXW_CHART_COLUMN_STACKED) {
|
|
2866
|
+
self->grouping = LXW_GROUPING_STACKED;
|
|
2867
|
+
self->has_overlap = LXW_TRUE;
|
|
2868
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2871
|
+
if (type == LXW_CHART_COLUMN_STACKED_PERCENT) {
|
|
2872
|
+
self->grouping = LXW_GROUPING_PERCENTSTACKED;
|
|
2873
|
+
lxw_strcpy((self->y_axis)->default_num_format, "0%");
|
|
2874
|
+
self->has_overlap = LXW_TRUE;
|
|
2875
|
+
self->subtype = LXW_CHART_SUBTYPE_STACKED;
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
/* Initialize the function pointers for this chart type. */
|
|
2879
|
+
self->write_chart_type = _chart_write_column_chart;
|
|
2880
|
+
self->write_plot_area = _chart_write_plot_area;
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
/*
|
|
2884
|
+
* Initialize a doughnut chart.
|
|
2885
|
+
*/
|
|
2886
|
+
STATIC void
|
|
2887
|
+
_chart_initialize_doughnut_chart(lxw_chart *self)
|
|
2888
|
+
{
|
|
2889
|
+
self->has_markers = LXW_FALSE;
|
|
2890
|
+
|
|
2891
|
+
/* Initialize the function pointers for this chart type. */
|
|
2892
|
+
self->write_chart_type = _chart_write_doughnut_chart;
|
|
2893
|
+
self->write_plot_area = _chart_write_pie_plot_area;
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
/*
|
|
2897
|
+
* Initialize a line chart.
|
|
2898
|
+
*/
|
|
2899
|
+
STATIC void
|
|
2900
|
+
_chart_initialize_line_chart(lxw_chart *self)
|
|
2901
|
+
{
|
|
2902
|
+
self->has_markers = LXW_TRUE;
|
|
2903
|
+
self->grouping = LXW_GROUPING_STANDARD;
|
|
2904
|
+
|
|
2905
|
+
/* Initialize the function pointers for this chart type. */
|
|
2906
|
+
self->write_chart_type = _chart_write_line_chart;
|
|
2907
|
+
self->write_plot_area = _chart_write_plot_area;
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
/*
|
|
2911
|
+
* Initialize a pie chart.
|
|
2912
|
+
*/
|
|
2913
|
+
STATIC void
|
|
2914
|
+
_chart_initialize_pie_chart(lxw_chart *self)
|
|
2915
|
+
{
|
|
2916
|
+
self->has_markers = LXW_FALSE;
|
|
2917
|
+
|
|
2918
|
+
/* Initialize the function pointers for this chart type. */
|
|
2919
|
+
self->write_chart_type = _chart_write_pie_chart;
|
|
2920
|
+
self->write_plot_area = _chart_write_pie_plot_area;
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2923
|
+
/*
|
|
2924
|
+
* Initialize a scatter chart.
|
|
2925
|
+
*/
|
|
2926
|
+
STATIC void
|
|
2927
|
+
_chart_initialize_scatter_chart(lxw_chart *self)
|
|
2928
|
+
{
|
|
2929
|
+
self->has_horiz_val_axis = LXW_FALSE;
|
|
2930
|
+
self->cross_between = LXW_CHART_AXIS_POSITION_ON_TICK;
|
|
2931
|
+
self->is_scatter = LXW_TRUE;
|
|
2932
|
+
self->has_markers = LXW_TRUE;
|
|
2933
|
+
|
|
2934
|
+
/* Initialize the function pointers for this chart type. */
|
|
2935
|
+
self->write_chart_type = _chart_write_scatter_chart;
|
|
2936
|
+
self->write_plot_area = _chart_write_scatter_plot_area;
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
/*
|
|
2940
|
+
* Initialize a radar chart.
|
|
2941
|
+
*/
|
|
2942
|
+
STATIC void
|
|
2943
|
+
_chart_initialize_radar_chart(lxw_chart *self, uint8_t type)
|
|
2944
|
+
{
|
|
2945
|
+
if (type == LXW_CHART_RADAR)
|
|
2946
|
+
self->has_markers = LXW_TRUE;
|
|
2947
|
+
|
|
2948
|
+
self->x_axis->default_major_gridlines = LXW_TRUE;
|
|
2949
|
+
self->y_axis->major_tick_mark = LXW_TRUE;
|
|
2950
|
+
|
|
2951
|
+
/* Initialize the function pointers for this chart type. */
|
|
2952
|
+
self->write_chart_type = _chart_write_radar_chart;
|
|
2953
|
+
self->write_plot_area = _chart_write_plot_area;
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
/*
|
|
2957
|
+
* Initialize the chart specific properties.
|
|
2958
|
+
*/
|
|
2959
|
+
STATIC void
|
|
2960
|
+
_chart_initialize(lxw_chart *self, uint8_t type)
|
|
2961
|
+
{
|
|
2962
|
+
switch (type) {
|
|
2963
|
+
|
|
2964
|
+
case LXW_CHART_AREA:
|
|
2965
|
+
case LXW_CHART_AREA_STACKED:
|
|
2966
|
+
case LXW_CHART_AREA_STACKED_PERCENT:
|
|
2967
|
+
_chart_initialize_area_chart(self, type);
|
|
2968
|
+
break;
|
|
2969
|
+
|
|
2970
|
+
case LXW_CHART_BAR:
|
|
2971
|
+
case LXW_CHART_BAR_STACKED:
|
|
2972
|
+
case LXW_CHART_BAR_STACKED_PERCENT:
|
|
2973
|
+
_chart_initialize_bar_chart(self, type);
|
|
2974
|
+
break;
|
|
2975
|
+
|
|
2976
|
+
case LXW_CHART_COLUMN:
|
|
2977
|
+
case LXW_CHART_COLUMN_STACKED:
|
|
2978
|
+
case LXW_CHART_COLUMN_STACKED_PERCENT:
|
|
2979
|
+
_chart_initialize_column_chart(self, type);
|
|
2980
|
+
break;
|
|
2981
|
+
|
|
2982
|
+
case LXW_CHART_DOUGHNUT:
|
|
2983
|
+
_chart_initialize_doughnut_chart(self);
|
|
2984
|
+
break;
|
|
2985
|
+
|
|
2986
|
+
case LXW_CHART_LINE:
|
|
2987
|
+
_chart_initialize_line_chart(self);
|
|
2988
|
+
break;
|
|
2989
|
+
|
|
2990
|
+
case LXW_CHART_PIE:
|
|
2991
|
+
_chart_initialize_pie_chart(self);
|
|
2992
|
+
break;
|
|
2993
|
+
|
|
2994
|
+
case LXW_CHART_SCATTER:
|
|
2995
|
+
case LXW_CHART_SCATTER_STRAIGHT:
|
|
2996
|
+
case LXW_CHART_SCATTER_STRAIGHT_WITH_MARKERS:
|
|
2997
|
+
case LXW_CHART_SCATTER_SMOOTH:
|
|
2998
|
+
case LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS:
|
|
2999
|
+
_chart_initialize_scatter_chart(self);
|
|
3000
|
+
break;
|
|
3001
|
+
|
|
3002
|
+
case LXW_CHART_RADAR:
|
|
3003
|
+
case LXW_CHART_RADAR_WITH_MARKERS:
|
|
3004
|
+
case LXW_CHART_RADAR_FILLED:
|
|
3005
|
+
_chart_initialize_radar_chart(self, type);
|
|
3006
|
+
break;
|
|
3007
|
+
|
|
3008
|
+
default:
|
|
3009
|
+
LXW_WARN_FORMAT1("workbook_add_chart(): "
|
|
3010
|
+
"unhandled chart type '%d'", type);
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
/*
|
|
3015
|
+
* Assemble and write the XML file.
|
|
3016
|
+
*/
|
|
3017
|
+
void
|
|
3018
|
+
lxw_chart_assemble_xml_file(lxw_chart *self)
|
|
3019
|
+
{
|
|
3020
|
+
/* Initialize the chart specific properties. */
|
|
3021
|
+
_chart_initialize(self, self->type);
|
|
3022
|
+
|
|
3023
|
+
/* Write the XML declaration. */
|
|
3024
|
+
_chart_xml_declaration(self);
|
|
3025
|
+
|
|
3026
|
+
/* Write the c:chartSpace element. */
|
|
3027
|
+
_chart_write_chart_space(self);
|
|
3028
|
+
|
|
3029
|
+
/* Write the c:lang element. */
|
|
3030
|
+
_chart_write_lang(self);
|
|
3031
|
+
|
|
3032
|
+
/* Write the c:style element. */
|
|
3033
|
+
_chart_write_style(self);
|
|
3034
|
+
|
|
3035
|
+
/* Write the c:chart element. */
|
|
3036
|
+
_chart_write_chart(self);
|
|
3037
|
+
|
|
3038
|
+
/* Write the c:printSettings element. */
|
|
3039
|
+
_chart_write_print_settings(self);
|
|
3040
|
+
|
|
3041
|
+
lxw_xml_end_tag(self->file, "c:chartSpace");
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
/*****************************************************************************
|
|
3045
|
+
*
|
|
3046
|
+
* Public functions.
|
|
3047
|
+
*
|
|
3048
|
+
****************************************************************************/
|
|
3049
|
+
|
|
3050
|
+
/*
|
|
3051
|
+
* Add data to a data cache in a range object, for testing only.
|
|
3052
|
+
*/
|
|
3053
|
+
int
|
|
3054
|
+
lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data,
|
|
3055
|
+
uint16_t rows, uint8_t cols, uint8_t col)
|
|
3056
|
+
{
|
|
3057
|
+
struct lxw_series_data_point *data_point;
|
|
3058
|
+
uint16_t i;
|
|
3059
|
+
|
|
3060
|
+
range->ignore_cache = LXW_TRUE;
|
|
3061
|
+
range->num_data_points = rows;
|
|
3062
|
+
|
|
3063
|
+
/* Initialize the series range data cache. */
|
|
3064
|
+
for (i = 0; i < rows; i++) {
|
|
3065
|
+
data_point = calloc(1, sizeof(struct lxw_series_data_point));
|
|
3066
|
+
STAILQ_INSERT_TAIL(range->data_cache, data_point, list_pointers);
|
|
3067
|
+
data_point->number = data[i * cols + col];
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
return 0;
|
|
3071
|
+
}
|
|
3072
|
+
|
|
3073
|
+
/*
|
|
3074
|
+
* Insert an image into the worksheet.
|
|
3075
|
+
*/
|
|
3076
|
+
lxw_chart_series *
|
|
3077
|
+
chart_add_series(lxw_chart *self, const char *categories, const char *values)
|
|
3078
|
+
{
|
|
3079
|
+
lxw_chart_series *series;
|
|
3080
|
+
|
|
3081
|
+
/* Create a new object to hold the series. */
|
|
3082
|
+
series = calloc(1, sizeof(lxw_chart_series));
|
|
3083
|
+
GOTO_LABEL_ON_MEM_ERROR(series, mem_error);
|
|
3084
|
+
|
|
3085
|
+
series->categories = calloc(1, sizeof(lxw_series_range));
|
|
3086
|
+
GOTO_LABEL_ON_MEM_ERROR(series->categories, mem_error);
|
|
3087
|
+
|
|
3088
|
+
series->values = calloc(1, sizeof(lxw_series_range));
|
|
3089
|
+
GOTO_LABEL_ON_MEM_ERROR(series->values, mem_error);
|
|
3090
|
+
|
|
3091
|
+
series->title.range = calloc(1, sizeof(lxw_series_range));
|
|
3092
|
+
GOTO_LABEL_ON_MEM_ERROR(series->title.range, mem_error);
|
|
3093
|
+
|
|
3094
|
+
if (categories) {
|
|
3095
|
+
if (categories[0] == '=')
|
|
3096
|
+
series->categories->formula = lxw_strdup(categories + 1);
|
|
3097
|
+
else
|
|
3098
|
+
series->categories->formula = lxw_strdup(categories);
|
|
3099
|
+
}
|
|
3100
|
+
|
|
3101
|
+
if (values) {
|
|
3102
|
+
if (values[0] == '=')
|
|
3103
|
+
series->values->formula = lxw_strdup(values + 1);
|
|
3104
|
+
else
|
|
3105
|
+
series->values->formula = lxw_strdup(values);
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
if (_chart_init_data_cache(series->categories) != LXW_NO_ERROR)
|
|
3109
|
+
goto mem_error;
|
|
3110
|
+
|
|
3111
|
+
if (_chart_init_data_cache(series->values) != LXW_NO_ERROR)
|
|
3112
|
+
goto mem_error;
|
|
3113
|
+
|
|
3114
|
+
if (_chart_init_data_cache(series->title.range) != LXW_NO_ERROR)
|
|
3115
|
+
goto mem_error;
|
|
3116
|
+
|
|
3117
|
+
STAILQ_INSERT_TAIL(self->series_list, series, list_pointers);
|
|
3118
|
+
|
|
3119
|
+
return series;
|
|
3120
|
+
|
|
3121
|
+
mem_error:
|
|
3122
|
+
_chart_series_free(series);
|
|
3123
|
+
return NULL;
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
/*
|
|
3127
|
+
* Set on of the 48 built-in Excel chart styles.
|
|
3128
|
+
*/
|
|
3129
|
+
void
|
|
3130
|
+
chart_set_style(lxw_chart *self, uint8_t style_id)
|
|
3131
|
+
{
|
|
3132
|
+
/* The default style is 2. The range is 1 - 48 */
|
|
3133
|
+
if (style_id < 1 || style_id > 48)
|
|
3134
|
+
style_id = 2;
|
|
3135
|
+
|
|
3136
|
+
self->style_id = style_id;
|
|
3137
|
+
}
|
|
3138
|
+
|
|
3139
|
+
/*
|
|
3140
|
+
* Set a user defined name for a series.
|
|
3141
|
+
*/
|
|
3142
|
+
void
|
|
3143
|
+
chart_series_set_name(lxw_chart_series *series, const char *name)
|
|
3144
|
+
{
|
|
3145
|
+
if (!name)
|
|
3146
|
+
return;
|
|
3147
|
+
|
|
3148
|
+
if (name[0] == '=')
|
|
3149
|
+
series->title.range->formula = lxw_strdup(name + 1);
|
|
3150
|
+
else
|
|
3151
|
+
series->title.name = lxw_strdup(name);
|
|
3152
|
+
}
|
|
3153
|
+
|
|
3154
|
+
/*
|
|
3155
|
+
* Set an axis caption, with a range instead or a formula..
|
|
3156
|
+
*/
|
|
3157
|
+
void
|
|
3158
|
+
chart_series_set_name_range(lxw_chart_series *series, const char *sheetname,
|
|
3159
|
+
lxw_row_t row, lxw_col_t col)
|
|
3160
|
+
{
|
|
3161
|
+
if (!sheetname) {
|
|
3162
|
+
LXW_WARN("chart_series_set_name_range(): "
|
|
3163
|
+
"sheetname must be specified");
|
|
3164
|
+
return;
|
|
3165
|
+
}
|
|
3166
|
+
|
|
3167
|
+
/* Start and end row, col are the same for single cell range. */
|
|
3168
|
+
_chart_set_range(series->title.range, sheetname, row, col, row, col);
|
|
3169
|
+
}
|
|
3170
|
+
|
|
3171
|
+
/*
|
|
3172
|
+
* Set the categories range for a series.
|
|
3173
|
+
*/
|
|
3174
|
+
void
|
|
3175
|
+
chart_series_set_categories(lxw_chart_series *series, const char *sheetname,
|
|
3176
|
+
lxw_row_t first_row, lxw_col_t first_col,
|
|
3177
|
+
lxw_row_t last_row, lxw_col_t last_col)
|
|
3178
|
+
{
|
|
3179
|
+
if (!sheetname) {
|
|
3180
|
+
LXW_WARN("chart_series_set_categories(): "
|
|
3181
|
+
"sheetname must be specified");
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
_chart_set_range(series->categories, sheetname,
|
|
3186
|
+
first_row, first_col, last_row, last_col);
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
/*
|
|
3190
|
+
* Set the values range for a series.
|
|
3191
|
+
*/
|
|
3192
|
+
void
|
|
3193
|
+
chart_series_set_values(lxw_chart_series *series, const char *sheetname,
|
|
3194
|
+
lxw_row_t first_row, lxw_col_t first_col,
|
|
3195
|
+
lxw_row_t last_row, lxw_col_t last_col)
|
|
3196
|
+
{
|
|
3197
|
+
if (!sheetname) {
|
|
3198
|
+
LXW_WARN("chart_series_set_values(): sheetname must be specified");
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
_chart_set_range(series->values, sheetname,
|
|
3203
|
+
first_row, first_col, last_row, last_col);
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3206
|
+
/*
|
|
3207
|
+
* Set a line type for a series.
|
|
3208
|
+
*/
|
|
3209
|
+
void
|
|
3210
|
+
chart_series_set_line(lxw_chart_series *series, lxw_chart_line *line)
|
|
3211
|
+
{
|
|
3212
|
+
if (!line)
|
|
3213
|
+
return;
|
|
3214
|
+
|
|
3215
|
+
series->line = _chart_convert_line_args(line);
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
/*
|
|
3219
|
+
* Set a fill type for a series.
|
|
3220
|
+
*/
|
|
3221
|
+
void
|
|
3222
|
+
chart_series_set_fill(lxw_chart_series *series, lxw_chart_fill *fill)
|
|
3223
|
+
{
|
|
3224
|
+
if (!fill)
|
|
3225
|
+
return;
|
|
3226
|
+
|
|
3227
|
+
series->fill = _chart_convert_fill_args(fill);
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3230
|
+
/*
|
|
3231
|
+
* Set an axis caption.
|
|
3232
|
+
*/
|
|
3233
|
+
void
|
|
3234
|
+
chart_axis_set_name(lxw_chart_axis *axis, const char *name)
|
|
3235
|
+
{
|
|
3236
|
+
if (!name)
|
|
3237
|
+
return;
|
|
3238
|
+
|
|
3239
|
+
if (name[0] == '=')
|
|
3240
|
+
axis->title.range->formula = lxw_strdup(name + 1);
|
|
3241
|
+
else
|
|
3242
|
+
axis->title.name = lxw_strdup(name);
|
|
3243
|
+
}
|
|
3244
|
+
|
|
3245
|
+
/*
|
|
3246
|
+
* Set an axis caption, with a range instead or a formula..
|
|
3247
|
+
*/
|
|
3248
|
+
void
|
|
3249
|
+
chart_axis_set_name_range(lxw_chart_axis *axis, const char *sheetname,
|
|
3250
|
+
lxw_row_t row, lxw_col_t col)
|
|
3251
|
+
{
|
|
3252
|
+
if (!sheetname) {
|
|
3253
|
+
LXW_WARN("chart_axis_set_name_range(): sheetname must be specified");
|
|
3254
|
+
return;
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
/* Start and end row, col are the same for single cell range. */
|
|
3258
|
+
_chart_set_range(axis->title.range, sheetname, row, col, row, col);
|
|
3259
|
+
}
|
|
3260
|
+
|
|
3261
|
+
/*
|
|
3262
|
+
* Set an axis title/name font.
|
|
3263
|
+
*/
|
|
3264
|
+
void
|
|
3265
|
+
chart_axis_set_name_font(lxw_chart_axis *axis, lxw_chart_font *font)
|
|
3266
|
+
{
|
|
3267
|
+
axis->title.font = _chart_convert_font_args(font);
|
|
3268
|
+
}
|
|
3269
|
+
|
|
3270
|
+
/*
|
|
3271
|
+
* Set an axis number font.
|
|
3272
|
+
*/
|
|
3273
|
+
void
|
|
3274
|
+
chart_axis_set_num_font(lxw_chart_axis *axis, lxw_chart_font *font)
|
|
3275
|
+
{
|
|
3276
|
+
axis->num_font = _chart_convert_font_args(font);
|
|
3277
|
+
}
|
|
3278
|
+
|
|
3279
|
+
/*
|
|
3280
|
+
* Set a line type for an axis.
|
|
3281
|
+
*/
|
|
3282
|
+
void
|
|
3283
|
+
chart_axis_set_line(lxw_chart_axis *axis, lxw_chart_line *line)
|
|
3284
|
+
{
|
|
3285
|
+
if (!line)
|
|
3286
|
+
return;
|
|
3287
|
+
|
|
3288
|
+
axis->line = _chart_convert_line_args(line);
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
/*
|
|
3292
|
+
* Set a fill type for an axis.
|
|
3293
|
+
*/
|
|
3294
|
+
void
|
|
3295
|
+
chart_axis_set_fill(lxw_chart_axis *axis, lxw_chart_fill *fill)
|
|
3296
|
+
{
|
|
3297
|
+
if (!fill)
|
|
3298
|
+
return;
|
|
3299
|
+
|
|
3300
|
+
axis->fill = _chart_convert_fill_args(fill);
|
|
3301
|
+
}
|
|
3302
|
+
|
|
3303
|
+
/*
|
|
3304
|
+
* Set the chart title.
|
|
3305
|
+
*/
|
|
3306
|
+
void
|
|
3307
|
+
chart_title_set_name(lxw_chart *self, const char *name)
|
|
3308
|
+
{
|
|
3309
|
+
if (!name)
|
|
3310
|
+
return;
|
|
3311
|
+
|
|
3312
|
+
if (name[0] == '=')
|
|
3313
|
+
self->title.range->formula = lxw_strdup(name + 1);
|
|
3314
|
+
else
|
|
3315
|
+
self->title.name = lxw_strdup(name);
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
/*
|
|
3319
|
+
* Set the chart title, with a range instead or a formula.
|
|
3320
|
+
*/
|
|
3321
|
+
void
|
|
3322
|
+
chart_title_set_name_range(lxw_chart *self, const char *sheetname,
|
|
3323
|
+
lxw_row_t row, lxw_col_t col)
|
|
3324
|
+
{
|
|
3325
|
+
if (!sheetname) {
|
|
3326
|
+
LXW_WARN("chart_title_set_name_range(): sheetname must be specified");
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
/* Start and end row, col are the same for single cell range. */
|
|
3331
|
+
_chart_set_range(self->title.range, sheetname, row, col, row, col);
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3334
|
+
/*
|
|
3335
|
+
* Set the chart title font.
|
|
3336
|
+
*/
|
|
3337
|
+
void
|
|
3338
|
+
chart_title_set_name_font(lxw_chart *self, lxw_chart_font *font)
|
|
3339
|
+
{
|
|
3340
|
+
self->title.font = _chart_convert_font_args(font);
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
/*
|
|
3344
|
+
* Turn off the chart title.
|
|
3345
|
+
*/
|
|
3346
|
+
void
|
|
3347
|
+
chart_title_off(lxw_chart *self)
|
|
3348
|
+
{
|
|
3349
|
+
self->title.off = LXW_TRUE;
|
|
3350
|
+
}
|
|
3351
|
+
|
|
3352
|
+
/*
|
|
3353
|
+
* Set the chart legend position.
|
|
3354
|
+
*/
|
|
3355
|
+
void
|
|
3356
|
+
chart_legend_set_position(lxw_chart *self, uint8_t position)
|
|
3357
|
+
{
|
|
3358
|
+
self->legend.position = position;
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3361
|
+
/*
|
|
3362
|
+
* Set the legend font.
|
|
3363
|
+
*/
|
|
3364
|
+
void
|
|
3365
|
+
chart_legend_set_font(lxw_chart *self, lxw_chart_font *font)
|
|
3366
|
+
{
|
|
3367
|
+
self->legend.font = _chart_convert_font_args(font);
|
|
3368
|
+
}
|
|
3369
|
+
|
|
3370
|
+
/*
|
|
3371
|
+
* Remove one or more series from the the legend.
|
|
3372
|
+
*/
|
|
3373
|
+
lxw_error
|
|
3374
|
+
chart_legend_delete_series(lxw_chart *self, int16_t delete_series[])
|
|
3375
|
+
{
|
|
3376
|
+
uint16_t count = 0;
|
|
3377
|
+
|
|
3378
|
+
if (delete_series == NULL)
|
|
3379
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
3380
|
+
|
|
3381
|
+
while (delete_series[count] > 0)
|
|
3382
|
+
count++;
|
|
3383
|
+
|
|
3384
|
+
/* The maximum number of series in a chart is 255. */
|
|
3385
|
+
if (count > 255)
|
|
3386
|
+
count = 255;
|
|
3387
|
+
|
|
3388
|
+
self->delete_series = calloc(count, sizeof(int16_t));
|
|
3389
|
+
RETURN_ON_MEM_ERROR(self->delete_series, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
|
3390
|
+
memcpy(self->delete_series, delete_series, count * sizeof(int16_t));
|
|
3391
|
+
self->delete_series_count = count;
|
|
3392
|
+
|
|
3393
|
+
return LXW_NO_ERROR;
|
|
3394
|
+
}
|
|
3395
|
+
|
|
3396
|
+
/*
|
|
3397
|
+
* Set the Pie/Doughnut chart rotation: the angle of the first slice.
|
|
3398
|
+
*/
|
|
3399
|
+
void
|
|
3400
|
+
chart_set_rotation(lxw_chart *self, uint16_t rotation)
|
|
3401
|
+
{
|
|
3402
|
+
if (rotation <= 360)
|
|
3403
|
+
self->rotation = rotation;
|
|
3404
|
+
else
|
|
3405
|
+
LXW_WARN_FORMAT1("chart_set_rotation(): Chart rotation '%d' outside "
|
|
3406
|
+
"range: 0 <= rotation <= 360", rotation);
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
/*
|
|
3410
|
+
* Set the Doughnut chart hole size.
|
|
3411
|
+
*/
|
|
3412
|
+
void
|
|
3413
|
+
chart_set_hole_size(lxw_chart *self, uint8_t size)
|
|
3414
|
+
{
|
|
3415
|
+
if (size >= 10 && size <= 90)
|
|
3416
|
+
self->hole_size = size;
|
|
3417
|
+
else
|
|
3418
|
+
LXW_WARN_FORMAT1("chart_set_hole_size(): Hole size '%d' outside "
|
|
3419
|
+
"Excel range: 10 <= size <= 90", size);
|
|
3420
|
+
}
|