1 /*
2  * libxlsxwriter
3  *
4  * Copyright 2014-2016, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
5  */
6 
7 /**
8  * @page workbook_page The Workbook object
9  *
10  * The Workbook is the main object exposed by the libxlsxwriter library. It
11  * represents the entire spreadsheet as you see it in Excel and internally it
12  * represents the Excel file as it is written on disk.
13  *
14  * See @ref workbook.h for full details of the functionality.
15  *
16  * @file workbook.h
17  *
18  * @brief Functions related to creating an Excel xlsx workbook.
19  *
20  * The Workbook is the main object exposed by the libxlsxwriter library. It
21  * represents the entire spreadsheet as you see it in Excel and internally it
22  * represents the Excel file as it is written on disk.
23  *
24  * @code
25  *     #include "xlsxwriter.h"
26  *
27  *     int main() {
28  *
29  *         lxw_workbook  *workbook  = workbook_new("filename.xlsx");
30  *         lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
31  *
32  *         worksheet_write_string(worksheet, 0, 0, "Hello Excel", NULL);
33  *
34  *         return workbook_close(workbook);
35  *     }
36  * @endcode
37  *
38  * @image html workbook01.png
39  *
40  */
41 module xlsxwriter.workbook;
42 
43 import core.stdc.stdint;
44 import core.stdc.time;
45 
46 import xlsxwriter.worksheet;
47 import xlsxwriter.common;
48 import xlsxwriter.format;
49 import xlsxwriter.chart;
50 
51 extern(C):
52 enum LXW_DEFINED_NAME_LENGTH = 128;
53 
54 /**
55  * @brief Macro to loop over all the worksheets in a workbook.
56  *
57  * This macro allows you to loop over all the worksheets that have been
58  * added to a workbook. You must provide a lxw_worksheet pointer and
59  * a pointer to the lxw_workbook:
60  *
61  * @code
62  *    lxw_workbook  *workbook = workbook_new("test.xlsx");
63  *
64  *    lxw_worksheet *worksheet; // Generic worksheet pointer.
65  *
66  *    // Worksheet objects used in the program.
67  *    lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL);
68  *    lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, NULL);
69  *    lxw_worksheet *worksheet3 = workbook_add_worksheet(workbook, NULL);
70  *
71  *    // Iterate over the 3 worksheets and perform the same operation on each.
72  *    LXW_FOREACH_WORKSHEET(worksheet, workbook) {
73  *        worksheet_write_string(worksheet, 0, 0, "Hello", NULL);
74  *    }
75  * @endcode
76  */
77 /* #define LXW_FOREACH_WORKSHEET(worksheet, workbook) \ */
78 /*     STAILQ_FOREACH((worksheet), (workbook)->worksheets, list_pointers) */
79 
80 /* Struct to represent a defined name. */
81 /* struct lxw_defined_name { */
82 /*     int16_t index; */
83 /*     uint8_t hidden; */
84 /*     char name[LXW_DEFINED_NAME_LENGTH]; */
85 /*     char app_name[LXW_DEFINED_NAME_LENGTH]; */
86 /*     char formula[LXW_DEFINED_NAME_LENGTH]; */
87 /*     char normalised_name[LXW_DEFINED_NAME_LENGTH]; */
88 /*     char normalised_sheetname[LXW_DEFINED_NAME_LENGTH]; */
89 
90 /*     /1* List pointers for queue.h. *1/ */
91 /*     TAILQ_ENTRY (lxw_defined_name) list_pointers; */
92 /* } lxw_defined_name; */
93 
94 /**
95  * @brief Error codes from workbook functions.
96  */
97 enum lxw_workbook_error {
98     /** No error */
99     LXW_ERROR_WORKBOOK_NONE = 0,
100 
101     /** Error encountered when creating file */
102     LXW_ERROR_WORKBOOK_FILE_CREATE,
103 
104     /** Error encountered when creating a packager object */
105     LXW_ERROR_WORKBOOK_PACKAGER,
106 
107     /** Error encountered when creating file zip container */
108     LXW_ERROR_WORKBOOK_ZIP,
109 
110     /** Memory error. */
111     LXW_ERROR_WORKBOOK_MEMORY_ERROR
112 }
113 
114 /**
115  * Workbook document properties.
116  */
117 struct lxw_doc_properties {
118     /** The title of the Excel Document. */
119     char *title;
120 
121     /** The subject of the Excel Document. */
122     char *subject;
123 
124     /** The author of the Excel Document. */
125     char *author;
126 
127     /** The manager field of the Excel Document. */
128     char *manager;
129 
130     /** The company field of the Excel Document. */
131     char *company;
132 
133     /** The category of the Excel Document. */
134     char *category;
135 
136     /** The keywords of the Excel Document. */
137     char *keywords;
138 
139     /** The comment field of the Excel Document. */
140     char *comments;
141 
142     /** The status of the Excel Document. */
143     char *status;
144 
145     /** The hyperlink base url of the Excel Document. */
146     char *hyperlink_base;
147 
148     time_t created;
149 
150 }
151 
152 /**
153  * @brief Workbook options.
154  *
155  * Optional parameters when creating a new Workbook object via
156  * workbook_new_opt().
157  *
158  * Currently only the `constant_memory` property is supported:
159  *
160  * * `constant_memory`
161  */
162 struct lxw_workbook_options {
163     /** Optimize the workbook to use constant memory for worksheets */
164     uint8_t constant_memory;
165 }
166 
167 /**
168  * @brief Struct to represent an Excel workbook.
169  *
170  * The members of the lxw_workbook struct aren't modified directly. Instead
171  * the workbook properties are set by calling the functions shown in
172  * workbook.h.
173  */
174 struct lxw_workbook {}
175 
176 
177 /**
178  * @brief Create a new workbook object.
179  *
180  * @param filename The name of the new Excel file to create.
181  *
182  * @return A lxw_workbook instance.
183  *
184  * The `%workbook_new()` constructor is used to create a new Excel workbook
185  * with a given filename:
186  *
187  * @code
188  *     lxw_workbook *workbook  = workbook_new("filename.xlsx");
189  * @endcode
190  *
191  * When specifying a filename it is recommended that you use an `.xlsx`
192  * extension or Excel will generate a warning when opening the file.
193  *
194  */
195 lxw_workbook *workbook_new(const char *filename);
196 
197 /**
198  * @brief Create a new workbook object, and set the workbook options.
199  *
200  * @param filename The name of the new Excel file to create.
201  * @param options  Workbook options.
202  *
203  * @return A lxw_workbook instance.
204  *
205  * This method is the same as the `workbook_new()` constructor but allows
206  * additional options to be set.
207  *
208  * @code
209  *    lxw_workbook_options options = {.constant_memory = 1};
210  *
211  *    lxw_workbook  *workbook  = workbook_new_opt("filename.xlsx", &options);
212  * @endcode
213  *
214  * Note, in this mode a row of data is written and then discarded when a cell
215  * in a new row is added via one of the worksheet `worksheet_write_*()`
216  * methods.  Therefore, once this mode is active, data should be written in
217  * sequential row order.
218  *
219  * See @ref working_with_memory for more details.
220  *
221  */
222 lxw_workbook *workbook_new_opt(const char *filename,
223                                lxw_workbook_options *options);
224 
225 /* Deprecated function name for backwards compatibility. */
226 lxw_workbook *new_workbook(const char *filename);
227 
228 /* Deprecated function name for backwards compatibility. */
229 lxw_workbook *new_workbook_opt(const char *filename,
230                                lxw_workbook_options *options);
231 
232 /**
233  * @brief Add a new worksheet to a workbook:
234  *
235  * @param workbook  Pointer to a lxw_workbook instance.
236  * @param sheetname Optional worksheet name, defaults to Sheet1, etc.
237  *
238  * @return A lxw_worksheet instance.
239  *
240  * The `%workbook_add_worksheet()` method adds a new worksheet to a workbook:
241  *
242  * At least one worksheet should be added to a new workbook: The @ref
243  * worksheet.h "Worksheet" object is used to write data and configure a
244  * worksheet in the workbook.
245  *
246  * The `sheetname` parameter is optional. If it is `NULL` the default
247  * Excel convention will be followed, i.e. Sheet1, Sheet2, etc.:
248  *
249  * @code
250  *     worksheet = workbook_add_worksheet(workbook, NULL  );     // Sheet1
251  *     worksheet = workbook_add_worksheet(workbook, "Foglio2");  // Foglio2
252  *     worksheet = workbook_add_worksheet(workbook, "Data");     // Data
253  *     worksheet = workbook_add_worksheet(workbook, NULL  );     // Sheet4
254  *
255  * @endcode
256  *
257  * @image html workbook02.png
258  *
259  * The worksheet name must be a valid Excel worksheet name, i.e. it must be
260  * less than 32 character and it cannot contain any of the characters:
261  *
262  *     / \ [ ] : * ?
263  *
264  * In addition, you cannot use the same, case insensitive, `sheetname` for more
265  * than one worksheet.
266  *
267  */
268 lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
269                                       const char *sheetname);
270 
271 /**
272  * @brief Create a new @ref format.h "Format" object to formats cells in
273  *        worksheets.
274  *
275  * @param workbook Pointer to a lxw_workbook instance.
276  *
277  * @return A lxw_format instance.
278  *
279  * The `workbook_add_format()` function can be used to create new @ref
280  * format.h "Format" objects which are used to apply formatting to a cell.
281  *
282  * @code
283  *    // Create the Format.
284  *    lxw_format *format = workbook_add_format(workbook);
285  *
286  *    // Set some of the format properties.
287  *    format_set_bold(format);
288  *    format_set_font_color(format, LXW_COLOR_RED);
289  *
290  *    // Use the format to change the text format in a cell.
291  *    worksheet_write_string(worksheet, 0, 0, "Hello", format);
292  * @endcode
293  *
294  * See @ref format.h "the Format object" and @ref working_with_formats
295  * sections for more details about Format properties and how to set them.
296  *
297  */
298 lxw_format *workbook_add_format(lxw_workbook *workbook);
299 
300 /**
301  * @brief Close the Workbook object and write the XLSX file.
302  *
303  * @param workbook Pointer to a lxw_workbook instance.
304  *
305  * @return A #lxw_workbook_error.
306  *
307  * The `%workbook_close()` function closes a Workbook object, writes the Excel
308  * file to disk, frees any memory allocated internally to the Workbook and
309  * frees the object itself.
310  *
311  * @code
312  *     workbook_close(workbook);
313  * @endcode
314  *
315  * The `%workbook_close()` function returns any #lxw_workbook_error error codes
316  * encountered when creating the Excel file. The error code can be returned
317  * from the program main or the calling function:
318  *
319  * @code
320  *     return workbook_close(workbook);
321  * @endcode
322  *
323  */
324 lxw_error workbook_close(lxw_workbook *workbook);
325 
326 /**
327  * @brief Set the document properties such as Title, Author etc.
328  *
329  * @param workbook   Pointer to a lxw_workbook instance.
330  * @param properties Document properties to set.
331  *
332  * The `%workbook_set_properties` method can be used to set the document
333  * properties of the Excel file created by `libxlsxwriter`. These properties
334  * are visible when you use the `Office Button -> Prepare -> Properties`
335  * option in Excel and are also available to external applications that read
336  * or index windows files.
337  *
338  * The properties that can be set are:
339  *
340  * - `title`
341  * - `subject`
342  * - `author`
343  * - `manager`
344  * - `company`
345  * - `category`
346  * - `keywords`
347  * - `comments`
348  * - `hyperlink_base`
349  *
350  * The properties are specified via a `lxw_doc_properties` struct. All the
351  * members are `char *` and they are all optional. An example of how to create
352  * and pass the properties is:
353  *
354  * @code
355  *     // Create a properties structure and set some of the fields.
356  *     lxw_doc_properties properties = {
357  *         .title    = "This is an example spreadsheet",
358  *         .subject  = "With document properties",
359  *         .author   = "John McNamara",
360  *         .manager  = "Dr. Heinz Doofenshmirtz",
361  *         .company  = "of Wolves",
362  *         .category = "Example spreadsheets",
363  *         .keywords = "Sample, Example, Properties",
364  *         .comments = "Created with libxlsxwriter",
365  *         .status   = "Quo",
366  *     };
367  *
368  *     // Set the properties in the workbook.
369  *     workbook_set_properties(workbook, &properties);
370  * @endcode
371  *
372  * @image html doc_properties.png
373  *
374  * @return 0 for success, non-zero on error.
375  */
376 lxw_error workbook_set_properties(lxw_workbook *workbook,
377                                 lxw_doc_properties *properties);
378 
379 /**
380  * @brief Create a defined name in the workbook to use as a variable.
381  *
382  * @param workbook Pointer to a lxw_workbook instance.
383  * @param name     The defined name.
384  * @param formula  The cell or range that the defined name refers to.
385  *
386  * @return 0 for success, non-zero on error.
387  *
388  * This method is used to defined a name that can be used to represent a
389  * value, a single cell or a range of cells in a workbook: These defined names
390  * can then be used in formulas:
391  *
392  * @code
393  *     workbook_define_name(workbook, "Exchange_rate", "=0.96");
394  *     worksheet_write_formula(worksheet, 2, 1, "=Exchange_rate", NULL);
395  *
396  * @endcode
397  *
398  * @image html defined_name.png
399  *
400  * As in Excel a name defined like this is "global" to the workbook and can be
401  * referred to from any worksheet:
402  *
403  * @code
404  *     // Global workbook name.
405  *     workbook_define_name(workbook, "Sales", "=Sheet1!$G$1:$H$10");
406  * @endcode
407  *
408  * It is also possible to define a local/worksheet name by prefixing it with
409  * the sheet name using the syntax `'sheetname!definedname'`:
410  *
411  * @code
412  *     // Local worksheet name.
413  *     workbook_define_name(workbook, "Sheet2!Sales", "=Sheet2!$G$1:$G$10");
414  * @endcode
415  *
416  * If the sheet name contains spaces or special characters you must follow the
417  * Excel convention and enclose it in single quotes:
418  *
419  * @code
420  *     workbook_define_name(workbook, "'New Data'!Sales", "=Sheet2!$G$1:$G$10");
421  * @endcode
422  *
423  * The rules for names in Excel are explained in the
424  * [Microsoft Office
425 documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
426  *
427  */
428 lxw_error workbook_define_name(lxw_workbook *workbook, const char *name,
429                              const char *formula);
430 
431 void lxw_workbook_free(lxw_workbook *workbook);
432 void lxw_workbook_assemble_xml_file(lxw_workbook *workbook);
433 void lxw_workbook_set_default_xf_indices(lxw_workbook *workbook);
434 
435 /**
436  * @brief Create a new chart to be added to a worksheet:
437  *
438  * @param workbook   Pointer to a lxw_workbook instance.
439  * @param chart_type The type of chart to be created. See #lxw_chart_types.
440  *
441  * @return A lxw_chart object.
442  *
443  * The `%workbook_add_chart()` function creates a new chart object that can
444  * be added to a worksheet:
445  *
446  * @code
447  *     // Create a chart object.
448  *     lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
449  *
450  *     // Add data series to the chart.
451  *     chart_add_series(chart, NULL, "Sheet1!$A$1:$A$5");
452  *     chart_add_series(chart, NULL, "Sheet1!$B$1:$B$5");
453  *     chart_add_series(chart, NULL, "Sheet1!$C$1:$C$5");
454  *
455  *     // Insert the chart into the worksheet
456  *     worksheet_insert_chart(worksheet, CELL("B7"), chart);
457  * @endcode
458  *
459  * The available chart types are defined in #lxw_chart_types. The types of
460  * charts that are supported are:
461  *
462  * | Chart type                               | Description                            |
463  * | :--------------------------------------- | :------------------------------------  |
464  * | #LXW_CHART_AREA                          | Area chart.                            |
465  * | #LXW_CHART_AREA_STACKED                  | Area chart - stacked.                  |
466  * | #LXW_CHART_AREA_STACKED_PERCENT          | Area chart - percentage stacked.       |
467  * | #LXW_CHART_BAR                           | Bar chart.                             |
468  * | #LXW_CHART_BAR_STACKED                   | Bar chart - stacked.                   |
469  * | #LXW_CHART_BAR_STACKED_PERCENT           | Bar chart - percentage stacked.        |
470  * | #LXW_CHART_COLUMN                        | Column chart.                          |
471  * | #LXW_CHART_COLUMN_STACKED                | Column chart - stacked.                |
472  * | #LXW_CHART_COLUMN_STACKED_PERCENT        | Column chart - percentage stacked.     |
473  * | #LXW_CHART_DOUGHNUT                      | Doughnut chart.                        |
474  * | #LXW_CHART_LINE                          | Line chart.                            |
475  * | #LXW_CHART_PIE                           | Pie chart.                             |
476  * | #LXW_CHART_SCATTER                       | Scatter chart.                         |
477  * | #LXW_CHART_SCATTER_STRAIGHT              | Scatter chart - straight.              |
478  * | #LXW_CHART_SCATTER_STRAIGHT_WITH_MARKERS | Scatter chart - straight with markers. |
479  * | #LXW_CHART_SCATTER_SMOOTH                | Scatter chart - smooth.                |
480  * | #LXW_CHART_SCATTER_SMOOTH_WITH_MARKERS   | Scatter chart - smooth with markers.   |
481  * | #LXW_CHART_RADAR                         | Radar chart.                           |
482  * | #LXW_CHART_RADAR_WITH_MARKERS            | Radar chart - with markers.            |
483  * | #LXW_CHART_RADAR_FILLED                  | Radar chart - filled.                  |
484  *
485  *
486  *
487  * See @ref chart.h for details.
488  */
489 lxw_chart *workbook_add_chart(lxw_workbook *workbook, uint8_t chart_type);