1 /*
2  * libxlsxwriter
3  *
4  * Copyright 2014-2016, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5  *
6  * chart - A libxlsxwriter library for creating Excel XLSX chart files.
7  *
8  */
9 
10 /**
11  * @page chart_page The Chart object
12  *
13  * The Chart object represents an Excel chart. It provides functions for
14  * adding data series to the chart and for configuring the chart.
15  *
16  * See @ref chart.h for full details of the functionality.
17  *
18  * @file chart.h
19  *
20  * @brief Functions related to adding data to and configuring  a chart.
21  *
22  * The Chart object represents an Excel chart. It provides functions for
23  * adding data series to the chart and for configuring the chart.
24  *
25  * A Chart object isn't created directly. Instead a chart is created by
26  * calling the `workbook_add_chart()` function from a Workbook object. For
27  * example:
28  *
29  * @code
30  *
31  * #include "xlsxwriter.h"
32  *
33  * int main() {
34  *
35  *     lxw_workbook  *workbook  = new_workbook("chart.xlsx");
36  *     lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
37  *
38  *     // User function to add data to worksheet, not shown here.
39  *     write_worksheet_data(worksheet);
40  *
41  *     // Create a chart object.
42  *     lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
43  *
44  *     // In the simplest case we just add some value data series.
45  *     // The NULL categories will default to 1 to 5 like in Excel.
46  *     chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5");
47  *     chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5");
48  *     chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
49  *
50  *     // Insert the chart into the worksheet
51  *     worksheet_insert_chart(worksheet, CELL("B7"), chart);
52  *
53  *     return workbook_close(workbook);
54  * }
55  *
56  * @endcode
57  *
58  * The chart in the worksheet will look like this:
59  * @image html chart_simple.png
60  *
61  * The basic procedure for adding a chart to a worksheet is:
62  *
63  * 1. Create the chart with `workbook_add_chart()`.
64  * 2. Add one or more data series to the chart which refers to data in the
65  *    workbook using `chart_add_series()`.
66  * 3. Configure the chart with the other available functions shown below.
67  * 4. Insert the chart into a worksheet using `worksheet_insert_chart()`.
68  *
69  */
70 module xlsxwriter.chart;
71 
72 import core.stdc.stdint;
73 import xlsxwriter.worksheet, xlsxwriter.common;
74 
75 extern(C):
76 
77 enum LXW_CHART_NUM_FORMAT_LEN = 128;
78 
79 /** Available chart types . */
80 enum lxw_chart_types {
81 
82     /** None. */
83     LXW_CHART_NONE = 0,
84 
85     /** Area chart. */
86     LXW_CHART_AREA,
87 
88     /** Area chart - stacked. */
89     LXW_CHART_AREA_STACKED,
90 
91     /** Area chart - percentage stacked. */
92     LXW_CHART_AREA_STACKED_PERCENT,
93 
94     /** Bar chart. */
95     LXW_CHART_BAR,
96 
97     /** Bar chart - stacked. */
98     LXW_CHART_BAR_STACKED,
99 
100     /** Bar chart - percentage stacked. */
101     LXW_CHART_BAR_STACKED_PERCENT,
102 
103     /** Column chart. */
104     LXW_CHART_COLUMN,
105 
106     /** Column chart - stacked. */
107     LXW_CHART_COLUMN_STACKED,
108 
109     /** Column chart - percentage stacked. */
110     LXW_CHART_COLUMN_STACKED_PERCENT,
111 
112     /** Doughnut chart. */
113     LXW_CHART_DOUGHNUT,
114 
115     /** Line chart. */
116     LXW_CHART_LINE,
117 
118     /** Pie chart. */
119     LXW_CHART_PIE,
120 
121     /** Scatter chart. */
122     LXW_CHART_SCATTER,
123 
124     /** Scatter chart - straight. */
125     LXW_CHART_SCATTER_STRAIGHT,
126 
127     /** Scatter chart - straight with markers. */
128     LXW_CHART_SCATTER_STRAIGHT_WITH_MARKERS,
129 
130     /** Scatter chart - smooth. */
131     LXW_CHART_SCATTER_SMOOTH,
132 
133     /** Scatter chart - smooth with markers. */
134     LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS,
135 
136     /** Radar chart. */
137     LXW_CHART_RADAR,
138 
139     /** Radar chart - with markers. */
140     LXW_CHART_RADAR_WITH_MARKERS,
141 
142     /** Radar chart - filled. */
143     LXW_CHART_RADAR_FILLED
144 }
145 mixin(standaloneEnums!lxw_chart_types);
146 
147 enum lxw_chart_subtypes {
148 
149     LXW_CHART_SUBTYPE_NONE = 0,
150     LXW_CHART_SUBTYPE_STACKED,
151     LXW_CHART_SUBTYPE_STACKED_PERCENT
152 }
153 
154 enum lxw_chart_groupings {
155     LXW_GROUPING_CLUSTERED,
156     LXW_GROUPING_STANDARD,
157     LXW_GROUPING_PERCENTSTACKED,
158     LXW_GROUPING_STACKED
159 }
160 
161 enum lxw_chart_axis_positions {
162     LXW_CHART_AXIS_POSITION_BETWEEN,
163     LXW_CHART_AXIS_POSITION_ON_TICK
164 }
165 
166 enum lxw_chart_positions {
167     LXW_CHART_RIGHT,
168     LXW_CHART_LEFT,
169     LXW_CHART_TOP,
170     LXW_CHART_BOTTOM
171 }
172 
173 struct lxw_series_range {}
174 
175 struct lxw_series_data_point {}
176 
177 struct lxw_chart_font {}
178 
179 struct lxw_chart_title {}
180 
181 /**
182  * @brief Struct to represent an Excel chart data series.
183  *
184  * The lxw_chart_series is created using the chart_add_series function. It is
185  * used in functions that modify a chart series but the members of the struct
186  * aren't modified directly.
187  */
188 struct lxw_chart_series {}
189 
190 /**
191  * @brief Struct to represent an Excel chart axis. It is used in functions
192  * that modify a chart axis but the members of the struct aren't modified
193  * directly.
194  */
195 struct lxw_chart_axis {}
196 
197 /**
198  * @brief Struct to represent an Excel chart.
199  *
200  * The members of the lxw_chart struct aren't modified directly. Instead
201  * the chart properties are set by calling the functions shown in chart.h.
202  */
203 struct lxw_chart {}
204 
205 
206 lxw_chart *lxw_chart_new(uint8_t type);
207 void lxw_chart_free(lxw_chart *chart);
208 void lxw_chart_assemble_xml_file(lxw_chart *chart);
209 
210 /**
211  * @brief Add a data series to a chart.
212  *
213  * @param chart      Pointer to a lxw_chart instance to be configured.
214  * @param categories The range of categories in the data series.
215  * @param values     The range of values in the data series.
216  *
217  * @return A lxw_chart_series object pointer.
218  *
219  * In Excel a chart **series** is a collection of information that defines
220  * which data is plotted such as the categories and values. It is also used to
221  * define the formatting for the data.
222  *
223  * For an libxlsxwriter chart object the `%chart_add_series()` function is
224  * used to set the categories and values of the series:
225  *
226  * @code
227  *     chart_add_series(chart, "=Sheet1!$A$2:$A$7", "=Sheet1!$C$2:$C$7");
228  * @endcode
229  *
230  *
231  * The series parameters are:
232  *
233  * - `categories`: This sets the chart category labels. The category is more
234  *   or less the same as the X axis. In most Excel chart types the
235  *   `categories` property is optional and the chart will just assume a
236  *   sequential series from `1..n`:
237  *
238  * @code
239  *     // The NULL category will default to 1 to 5 like in Excel.
240  *     chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5");
241  * @endcode
242  *
243  *  - `values`: This is the most important property of a series and is the
244  *    only mandatory option for every chart object. This parameter links the
245  *    chart with the worksheet data that it displays.
246  *
247  * The `categories` and `values` should be a string formula like
248  * `"=Sheet1!$A$2:$A$7"` in the same way it is represented in Excel. This is
249  * convenient when recreating a chart from an example in Excel but it is
250  * trickier to generate programmatically. For these cases you can set the
251  * `categories` and `values` to `NULL` and use the
252  * `chart_series_set_categories()` and `chart_series_set_values()` functions:
253  *
254  * @code
255  *     lxw_chart_series *series = chart_add_series(chart, NULL, NULL);
256  *
257  *     // Configure the series using a syntax that is easier to define programmatically.
258  *     chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); // "=Sheet1!$A$2:$A$7"
259  *     chart_series_set_values(    series, "Sheet1", 1, 2, 6, 2); // "=Sheet1!$C$2:$C$7"
260  * @endcode
261  *
262  * As shown in the previous example the return value from
263  * `%chart_add_series()` is a lxw_chart_series pointer. This can be used in
264  * other functions that configure a series.
265  *
266  *
267  * More than one series can be added to a chart. The series numbering and
268  * order in the Excel chart will be the same as the order in which they are
269  * added in libxlsxwriter:
270  *
271  * @code
272  *    chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5");
273  *    chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5");
274  *    chart_add_series(chart, NULL, "Sheet1!$C$1:$C$5");
275  * @endcode
276  *
277  * It is also possible to specify non-contiguous ranges:
278  *
279  * @code
280  *    chart_add_series(
281  *        chart,
282  *        "=(Sheet1!$A$1:$A$9,Sheet1!$A$14:$A$25)",
283  *        "=(Sheet1!$B$1:$B$9,Sheet1!$B$14:$B$25)"
284  *    );
285  * @endcode
286  *
287  */
288 lxw_chart_series *chart_add_series(lxw_chart *chart,
289                                    const char *categories,
290                                    const char *values);
291 
292 /**
293  * @brief Set a series "categories" range using row and column values.
294  *
295  * @param series    A series object created via `chart_add_series()`.
296  * @param sheetname The name of the worksheet that contains the data range.
297  * @param first_row The first row of the range. (All zero indexed.)
298  * @param first_col The first column of the range.
299  * @param last_row  The last row of the range.
300  * @param last_col  The last col of the range.
301  *
302  * The `categories` and `values` of a chart data series are generally set
303  * using the `chart_add_series()` function and Excel range formulas like
304  * `"=Sheet1!$A$2:$A$7"`.
305  *
306  * The `%chart_series_set_categories()` function is an alternative method that
307  * is easier to generate programmatically. It requires that you set the
308  * `categories` and `values` parameters in `chart_add_series()`to `NULL` and
309  * then set them using row and column values in
310  * `chart_series_set_categories()` and `chart_series_set_values()`:
311  *
312  * @code
313  *     lxw_chart_series *series = chart_add_series(chart, NULL, NULL);
314  *
315  *     // Configure the series ranges programmatically.
316  *     chart_series_set_categories(series, "Sheet1", 1, 0, 6, 0); // "=Sheet1!$A$2:$A$7"
317  *     chart_series_set_values(    series, "Sheet1", 1, 2, 6, 2); // "=Sheet1!$C$2:$C$7"
318  * @endcode
319  *
320  */
321 void chart_series_set_categories(lxw_chart_series *series,
322                                  const char *sheetname, lxw_row_t first_row,
323                                  lxw_col_t first_col, lxw_row_t last_row,
324                                  lxw_col_t last_col);
325 
326 /**
327  * @brief Set a series "values" range using row and column values.
328  *
329  * @param series    A series object created via `chart_add_series()`.
330  * @param sheetname The name of the worksheet that contains the data range.
331  * @param first_row The first row of the range. (All zero indexed.)
332  * @param first_col The first column of the range.
333  * @param last_row  The last row of the range.
334  * @param last_col  The last col of the range.
335  *
336  * The `categories` and `values` of a chart data series are generally set
337  * using the `chart_add_series()` function and Excel range formulas like
338  * `"=Sheet1!$A$2:$A$7"`.
339  *
340  * The `%chart_series_set_values()` function is an alternative method that is
341  * easier to generate programmatically. See the documentation for
342  * `chart_series_set_categories()` above.
343  */
344 void chart_series_set_values(lxw_chart_series *series, const char *sheetname,
345                              lxw_row_t first_row, lxw_col_t first_col,
346                              lxw_row_t last_row, lxw_col_t last_col);
347 
348 /**
349  * @brief Set the name of a chart series range.
350  *
351  * @param series A series object created via `chart_add_series()`.
352  * @param name   The series name.
353  *
354  * The `%chart_series_set_name` function is used to set the name for a chart
355  * data series. The series name in Excel is displayed in the chart legend and
356  * in the formula bar. The name property is optional and if it isn't supplied
357  * it will default to `Series 1..n`.
358  *
359  * The function applies to a #lxw_chart_series object created using
360  * `chart_add_series()`:
361  *
362  * @code
363  *     lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$7");
364  *
365  *     chart_series_set_name(series, "Quarterly budget data");
366  * @endcode
367  *
368  * The name parameter can also be a formula such as `=Sheet1!$A$1` to point to
369  * a cell in the workbook that contains the name:
370  *
371  * @code
372  *     lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$7");
373  *
374  *     chart_series_set_name(series, "=Sheet1!$B1$1");
375  * @endcode
376  *
377  * See also the `chart_series_set_name_range()` function to see how to set the
378  * name formula programmatically.
379  */
380 void chart_series_set_name(lxw_chart_series *series, const char *name);
381 
382 /**
383  * @brief Set a series name formula using row and column values.
384  *
385  * @param series    A series object created via `chart_add_series()`.
386  * @param sheetname The name of the worksheet that contains the cell range.
387  * @param row       The zero indexed row number of the range.
388  * @param col       The zero indexed column number of the range.
389  *
390  * The `%chart_series_set_name_range()` function can be used to set a series
391  * name range and is an alternative to using `chart_series_set_name()` and a
392  * string formula:
393  *
394  * @code
395  *     lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$7");
396  *
397  *     chart_series_set_name_range(series, "Sheet1", 0, 2); // "=Sheet1!$C$1"
398  * @endcode
399  */
400 void chart_series_set_name_range(lxw_chart_series *series,
401                                  const char *sheetname, lxw_row_t row,
402                                  lxw_col_t col);
403 
404 /**
405  * @brief Set the name caption of the an axis.
406  *
407  * @param axis A pointer to a chart #lxw_chart_axis object.
408  * @param name The name caption of the axis.
409  *
410  * The `%chart_axis_set_name()` function sets the name (also known as title or
411  * caption) for an axis. It can be used for the X or Y axes. The name is
412  * displayed below an X axis and to the side of a Y axis.
413  *
414  * @code
415  *     chart_axis_set_name(chart->x_axis, "Earnings per Quarter");
416  *     chart_axis_set_name(chart->y_axis, "US Dollars (Millions)");
417  * @endcode
418  *
419  * @image html chart_axis_set_name.png
420  *
421  * The name parameter can also be a formula such as `=Sheet1!$A$1` to point to
422  * a cell in the workbook that contains the name:
423  *
424  * @code
425  *     chart_axis_set_name(chart->x_axis, "=Sheet1!$B1$1");
426  * @endcode
427  *
428  * See also the `chart_axis_set_name_range()` function to see how to set the
429  * name formula programmatically.
430  *
431  * This function is applicable to category, date and value axes.
432  */
433 void chart_axis_set_name(lxw_chart_axis *axis, const char *name);
434 
435 /**
436  * @brief Set a chart axis name formula using row and column values.
437  *
438  * @param axis      A pointer to a chart #lxw_chart_axis object.
439  * @param sheetname The name of the worksheet that contains the cell range.
440  * @param row       The zero indexed row number of the range.
441  * @param col       The zero indexed column number of the range.
442  *
443  * The `%chart_axis_set_name_range()` function can be used to set an axis name
444  * range and is an alternative to using `chart_axis_set_name()` and a string
445  * formula:
446  *
447  * @code
448  *     chart_axis_set_name_range(chart->x_axis, "Sheet1", 1, 0);
449  *     chart_axis_set_name_range(chart->y_axis, "Sheet1", 2, 0);
450  * @endcode
451  */
452 void chart_axis_set_name_range(lxw_chart_axis *axis, const char *sheetname,
453                                lxw_row_t row, lxw_col_t col);
454 /**
455  * @brief Set the title of the chart.
456  *
457  * @param chart Pointer to a lxw_chart instance to be configured.
458  * @param name  The chart title name.
459  *
460  * The `%chart_title_set_name()` function sets the name (title) for the
461  * chart. The name is displayed above the chart.
462  *
463  * @code
464  *     chart_title_set_name(chart, "Year End Results");
465  * @endcode
466  *
467  * @image html chart_title_set_name.png
468  *
469  * The name parameter can also be a formula such as `=Sheet1!$A$1` to point to
470  * a cell in the workbook that contains the name:
471  *
472  * @code
473  *     chart_title_set_name(chart, "=Sheet1!$B1$1");
474  * @endcode
475  *
476  * See also the `chart_title_set_name_range()` function to see how to set the
477  * name formula programmatically.
478  *
479  * The Excel default is to have no chart title.
480  */
481 void chart_title_set_name(lxw_chart *chart, const char *name);
482 
483 /**
484  * @brief Set a chart title formula using row and column values.
485  *
486  * @param chart     Pointer to a lxw_chart instance to be configured.
487  * @param sheetname The name of the worksheet that contains the cell range.
488  * @param row       The zero indexed row number of the range.
489  * @param col       The zero indexed column number of the range.
490  *
491  * The `%chart_title_set_name_range()` function can be used to set a chart
492  * title range and is an alternative to using `chart_title_set_name()` and a
493  * string formula:
494  *
495  * @code
496  *     chart_title_set_name_range(chart, "Sheet1", 1, 0);
497  * @endcode
498  */
499 void chart_title_set_name_range(lxw_chart *chart, const char *sheetname,
500                                 lxw_row_t row, lxw_col_t col);
501 /**
502  * @brief Turn off an automatic chart title.
503  *
504  * @param chart  Pointer to a lxw_chart instance to be configured.
505  *
506  * In general in Excel a chart title isn't displayed unless the user
507  * explicitly adds one. However, Excel adds an automatic chart title to charts
508  * with a single series and a user defined series name. The
509  * `chart_title_off()` function allows you to turn off this automatic chart
510  * title:
511  *
512  * @code
513  *     chart_title_off(chart);
514  * @endcode
515  */
516 void chart_title_off(lxw_chart *chart);
517 
518 /**
519  * @brief Set the chart style type.
520  *
521  * @param chart    Pointer to a lxw_chart instance to be configured.
522  * @param style_id An index representing the chart style, 1 - 48.
523  *
524  * The `%chart_set_style()` function is used to set the style of the chart to
525  * one of the 48 built-in styles available on the "Design" tab in Excel 2007:
526  *
527  * @code
528  *     chart_set_style(chart, 37)
529  * @endcode
530  *
531  * @image html chart_style.png
532  *
533  * The style index number is counted from 1 on the top left in the Excel
534  * dialog. The default style is 2.
535  *
536  * **Note:**
537  *
538  * In Excel 2013 the Styles section of the "Design" tab in Excel shows what
539  * were referred to as "Layouts" in previous versions of Excel. These layouts
540  * are not defined in the file format. They are a collection of modifications
541  * to the base chart type. They can not be defined by the `chart_set_style()``
542  * function.
543  *
544  *
545  */
546 void chart_set_style(lxw_chart *chart, uint8_t style_id);
547 
548 void chart_set_rotation(lxw_chart *chart, uint16_t rotation);
549 void chart_set_hole_size(lxw_chart *chart, uint8_t size);
550 
551 int lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data,
552                              uint16_t rows, uint8_t cols, uint8_t col);
553