diff --git a/.indent.pro b/.indent.pro index 3d677b0f..a7183b2a 100644 --- a/.indent.pro +++ b/.indent.pro @@ -50,6 +50,7 @@ -T lxw_chart -T lxw_chart_axis -T lxw_chart_axis_display_unit +-T lxw_chart_axis_label_alignment -T lxw_chart_axis_label_position -T lxw_chart_axis_tick_mark -T lxw_chart_axis_tick_position @@ -77,6 +78,7 @@ -T lxw_chart_title -T lxw_chart_trendline_type -T lxw_chart_type +-T lxw_chartsheet -T lxw_col_options -T lxw_col_t -T lxw_color_t diff --git a/docs/Doxyfile b/docs/Doxyfile index a6d6adef..56d0b641 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -764,6 +764,7 @@ INPUT = src/mainpage.dox \ ../include/xlsxwriter/worksheet.h \ ../include/xlsxwriter/format.h \ ../include/xlsxwriter/chart.h \ + ../include/xlsxwriter/chartsheet.h \ ../include/xlsxwriter/utility.h \ ../include/xlsxwriter/common.h \ src/working_with_formats.dox \ diff --git a/docs/src/mainpage.dox b/docs/src/mainpage.dox index 43d9948b..39f563c8 100644 --- a/docs/src/mainpage.dox +++ b/docs/src/mainpage.dox @@ -42,11 +42,12 @@ following sections for more information: - @ref tutorial02 - @ref tutorial03 -- @ref workbook.h "The Workbook object" -- @ref worksheet.h "The Worksheet object" -- @ref format.h "The Format object" -- @ref chart.h "The Chart object" -- @ref utility.h "Utility functions and macros" +- @ref workbook.h "The Workbook object" +- @ref worksheet.h "The Worksheet object" +- @ref format.h "The Format object" +- @ref chart.h "The Chart object" +- @ref chartsheet.h "The Chartsheet object" +- @ref utility.h "Utility functions and macros" - @ref working_with_formats - @ref working_with_colors diff --git a/include/xlsxwriter/chartsheet.h b/include/xlsxwriter/chartsheet.h new file mode 100644 index 00000000..a0a4a21e --- /dev/null +++ b/include/xlsxwriter/chartsheet.h @@ -0,0 +1,93 @@ +/* + * libxlsxwriter + * + * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt. + * + * chartsheet - A libxlsxwriter library for creating Excel XLSX chartsheet files. + * + */ + +/** + * @page chartsheet_page The Chartsheet object + * + * The Chartsheet object represents an Excel chartsheet. It handles + * operations such as writing data to cells or formatting chartsheet + * layout. + * + * See @ref chartsheet.h for full details of the functionality. + * + * @file chartsheet.h + * + * @brief Functions related to adding data and formatting to a chartsheet. + * + * The Chartsheet object represents an Excel chartsheet. It handles + * operations such as writing data to cells or formatting chartsheet + * layout. + * + * A Chartsheet object isn't created directly. Instead a chartsheet is + * created by calling the workbook_add_chartsheet() function from a + * Workbook object: + * + * @code + * #include "xlsxwriter.h" + * + * int main() { + * + * lxw_workbook *workbook = workbook_new("filename.xlsx"); + * lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + * + * worksheet_write_string(worksheet, 0, 0, "Hello Excel", NULL); + * + * return workbook_close(workbook); + * } + * @endcode + * + */ + +#ifndef __LXW_CHARTSHEET_H__ +#define __LXW_CHARTSHEET_H__ + +#include + +#include "common.h" +#include "worksheet.h" +#include "drawing.h" + +/* + * Struct to represent a chartsheet object. + */ +typedef struct lxw_chartsheet { + + FILE *file; + lxw_worksheet *worksheet; + lxw_drawing *drawing; + + uint16_t rel_count; + +} lxw_chartsheet; + + +/* *INDENT-OFF* */ +#ifdef __cplusplus +extern "C" { +#endif +/* *INDENT-ON* */ + +lxw_chartsheet *lxw_chartsheet_new(); +void lxw_chartsheet_free(lxw_chartsheet *chartsheet); +void lxw_chartsheet_assemble_xml_file(lxw_chartsheet *self); + +/* Declarations required for unit testing. */ +#ifdef TESTING + +STATIC void _chartsheet_xml_declaration(lxw_chartsheet *self); + +#endif /* TESTING */ + +/* *INDENT-OFF* */ +#ifdef __cplusplus +} +#endif +/* *INDENT-ON* */ + +#endif /* __LXW_CHARTSHEET_H__ */ diff --git a/include/xlsxwriter/worksheet.h b/include/xlsxwriter/worksheet.h index d23fc114..9cdb33f0 100644 --- a/include/xlsxwriter/worksheet.h +++ b/include/xlsxwriter/worksheet.h @@ -3151,6 +3151,12 @@ void lxw_worksheet_prepare_chart(lxw_worksheet *worksheet, lxw_row *lxw_worksheet_find_row(lxw_worksheet *worksheet, lxw_row_t row_num); lxw_cell *lxw_worksheet_find_cell(lxw_row *row, lxw_col_t col_num); +/* + * External functions to call intern XML methods shared with chartsheet. + */ +void lxw_worksheet_write_sheet_views(lxw_worksheet *worksheet); +void lxw_worksheet_write_page_margins(lxw_worksheet *worksheet); + /* Declarations required for unit testing. */ #ifdef TESTING diff --git a/src/chartsheet.c b/src/chartsheet.c new file mode 100644 index 00000000..e21d3431 --- /dev/null +++ b/src/chartsheet.c @@ -0,0 +1,201 @@ +/***************************************************************************** + * chartsheet - A library for creating Excel XLSX chartsheet files. + * + * Used in conjunction with the libxlsxwriter library. + * + * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org. See LICENSE.txt. + * + */ + +#include "xlsxwriter/xmlwriter.h" +#include "xlsxwriter/chartsheet.h" +#include "xlsxwriter/utility.h" + +/* + * Forward declarations. + */ + +/***************************************************************************** + * + * Private functions. + * + ****************************************************************************/ + +/* + * Create a new chartsheet object. + */ +lxw_chartsheet * +lxw_chartsheet_new() +{ + lxw_chartsheet *chartsheet = calloc(1, sizeof(lxw_chartsheet)); + GOTO_LABEL_ON_MEM_ERROR(chartsheet, mem_error); + + /* Use an embedded worksheet instance to write XML records that are + * shared with worksheet.c. */ + chartsheet->worksheet = lxw_worksheet_new(NULL); + GOTO_LABEL_ON_MEM_ERROR(chartsheet->worksheet, mem_error); + + return chartsheet; + +mem_error: + lxw_chartsheet_free(chartsheet); + return NULL; +} + +/* + * Free a chartsheet object. + */ +void +lxw_chartsheet_free(lxw_chartsheet *chartsheet) +{ + if (!chartsheet) + return; + + lxw_worksheet_free(chartsheet->worksheet); + + if (chartsheet->drawing) + lxw_drawing_free(chartsheet->drawing); + + free(chartsheet); +} + +/***************************************************************************** + * + * XML functions. + * + ****************************************************************************/ + +/* + * Write the XML declaration. + */ +STATIC void +_chartsheet_xml_declaration(lxw_chartsheet *self) +{ + lxw_xml_declaration(self->file); +} + +/* + * Write the element. + */ +STATIC void +_chartsheet_write_chartsheet(lxw_chartsheet *self) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + char xmlns[] = "http://schemas.openxmlformats.org/" + "spreadsheetml/2006/main"; + char xmlns_r[] = "http://schemas.openxmlformats.org/" + "officeDocument/2006/relationships"; + + LXW_INIT_ATTRIBUTES(); + LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns); + LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r); + + lxw_xml_start_tag(self->file, "chartsheet", &attributes); + LXW_FREE_ATTRIBUTES(); +} + +/* + * Write the element. + */ +STATIC void +_chartsheet_write_sheet_pr(lxw_chartsheet *self) +{ + lxw_xml_empty_tag(self->file, "sheetPr", NULL); +} + +/* + * Write the element. + */ +STATIC void +_chartsheet_write_sheet_views(lxw_chartsheet *self) +{ + lxw_worksheet_write_sheet_views(self->worksheet); +} + +/* + * Write the element. + */ +STATIC void +_chartsheet_write_page_margins(lxw_chartsheet *self) +{ + lxw_worksheet_write_page_margins(self->worksheet); +} + +/* + * Write the element. + */ +STATIC void +_chartsheet_write_drawing(lxw_chartsheet *self, uint16_t id) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + char r_id[LXW_MAX_ATTRIBUTE_LENGTH]; + + lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", id); + + LXW_INIT_ATTRIBUTES(); + + LXW_PUSH_ATTRIBUTES_STR("r:id", r_id); + + lxw_xml_empty_tag(self->file, "drawing", &attributes); + + LXW_FREE_ATTRIBUTES(); + +} + +/* + * Write the elements. + */ +STATIC void +_chartsheet_write_drawings(lxw_chartsheet *self) +{ + if (!self->drawing) + return; + + self->rel_count++; + + _chartsheet_write_drawing(self, self->rel_count); +} + +/***************************************************************************** + * + * XML file assembly functions. + * + ****************************************************************************/ + +/* + * Assemble and write the XML file. + */ +void +lxw_chartsheet_assemble_xml_file(lxw_chartsheet *self) +{ + /* Set the embedded worksheet filehandle to the same as the chartsheet. */ + self->worksheet->file = self->file; + + /* Write the XML declaration. */ + _chartsheet_xml_declaration(self); + + /* Write the chartsheet element. */ + _chartsheet_write_chartsheet(self); + + /* Write the sheetPr element. */ + _chartsheet_write_sheet_pr(self); + + /* Write the sheetViews element. */ + _chartsheet_write_sheet_views(self); + + /* Write the pageMargins element. */ + _chartsheet_write_page_margins(self); + + /* Write the drawing element. */ + _chartsheet_write_drawings(self); + + lxw_xml_end_tag(self->file, "chartsheet"); +} + +/***************************************************************************** + * + * Public functions. + * + ****************************************************************************/ diff --git a/src/worksheet.c b/src/worksheet.c index 500bc137..f2427a81 100644 --- a/src/worksheet.c +++ b/src/worksheet.c @@ -3437,7 +3437,7 @@ _worksheet_write_sheet_protection(lxw_worksheet *self) * Write the element. */ STATIC void -_write_drawing(lxw_worksheet *self, uint16_t id) +_worksheet_write_drawing(lxw_worksheet *self, uint16_t id) { struct xml_attribute_list attributes; struct xml_attribute *attribute; @@ -3459,14 +3459,14 @@ _write_drawing(lxw_worksheet *self, uint16_t id) * Write the elements. */ STATIC void -_write_drawings(lxw_worksheet *self) +_worksheet_write_drawings(lxw_worksheet *self) { if (!self->drawing) return; self->rel_count++; - _write_drawing(self, self->rel_count); + _worksheet_write_drawing(self, self->rel_count); } /* @@ -3687,6 +3687,21 @@ _worksheet_write_data_validations(lxw_worksheet *self) LXW_FREE_ATTRIBUTES(); } +/* + * External functions to call intern XML methods shared with chartsheet. + */ +void +lxw_worksheet_write_sheet_views(lxw_worksheet *self) +{ + _worksheet_write_sheet_views(self); +} + +void +lxw_worksheet_write_page_margins(lxw_worksheet *self) +{ + _worksheet_write_page_margins(self); +} + /* * Assemble and write the XML file. */ @@ -3754,7 +3769,7 @@ lxw_worksheet_assemble_xml_file(lxw_worksheet *self) _worksheet_write_col_breaks(self); /* Write the drawing element. */ - _write_drawings(self); + _worksheet_write_drawings(self); /* Close the worksheet tag. */ lxw_xml_end_tag(self->file, "worksheet"); diff --git a/test/unit/Makefile b/test/unit/Makefile index eaf373ca..95735630 100644 --- a/test/unit/Makefile +++ b/test/unit/Makefile @@ -37,6 +37,7 @@ SRCS += $(wildcard styles/test*.c) SRCS += $(wildcard drawing/test*.c) SRCS += $(wildcard chart/test*.c) SRCS += $(wildcard custom/test*.c) +SRCS += $(wildcard chartsheet/test*.c) # End of SRCS OBJS = $(patsubst %.c,%.o,$(SRCS)) @@ -70,6 +71,7 @@ all : $(Q)$(MAKE) -C drawing $(Q)$(MAKE) -C chart $(Q)$(MAKE) -C custom + $(Q)$(MAKE) -C chartsheet # END make all clean : @@ -87,6 +89,7 @@ clean : $(Q)$(MAKE) clean -C drawing $(Q)$(MAKE) clean -C chart $(Q)$(MAKE) clean -C custom + $(Q)$(MAKE) clean -C chartsheet # END make clean diff --git a/test/unit/chartsheet/Makefile b/test/unit/chartsheet/Makefile new file mode 100644 index 00000000..2c05b8e2 --- /dev/null +++ b/test/unit/chartsheet/Makefile @@ -0,0 +1,8 @@ +############################################################################### +# +# Makefile for libxlsxwriter library. +# +# Copyright 2014-2015, John McNamara, jmcnamara@cpan.org +# + +include ../Makefile.unit diff --git a/test/unit/chartsheet/main.c b/test/unit/chartsheet/main.c new file mode 100644 index 00000000..72a4e6f5 --- /dev/null +++ b/test/unit/chartsheet/main.c @@ -0,0 +1,15 @@ +/* + * Test runner for xmlwriter using ctest. + * + * Copyright 2014-2016 John McNamara, jmcnamara@cpan.org + * + */ +#define CTEST_MAIN + +#include "../ctest.h" + +int main(int argc, const char *argv[]) +{ + return ctest_main(argc, argv); +} + diff --git a/test/unit/chartsheet/test_chartsheet.c b/test/unit/chartsheet/test_chartsheet.c new file mode 100644 index 00000000..ea8a89d8 --- /dev/null +++ b/test/unit/chartsheet/test_chartsheet.c @@ -0,0 +1,39 @@ +/* + * Tests for the lib_xlsx_writer library. + * + * Copyright 2014-2018, John McNamara, jmcnamara@cpan.org + * + */ + +#include "../ctest.h" +#include "../helper.h" + +#include "xlsxwriter/chartsheet.h" + +// Test assembling a complete Chartsheet file. +CTEST(chartsheet, chartsheet) { + + char* got; + char exp[] = + "\n" + "" + "" + "" + "" + "" + "" + "" + ""; + + FILE* testfile = lxw_tmpfile(NULL); + + lxw_chartsheet *chartsheet = lxw_chartsheet_new(NULL); + chartsheet->file = testfile; + chartsheet->drawing = lxw_drawing_new(NULL); + + lxw_chartsheet_assemble_xml_file(chartsheet); + + RUN_XLSX_STREQ_SHORT(exp, got); + + lxw_chartsheet_free(chartsheet); +} diff --git a/test/unit/chartsheet/test_chartsheet_xml_declaration.c b/test/unit/chartsheet/test_chartsheet_xml_declaration.c new file mode 100644 index 00000000..212dc51c --- /dev/null +++ b/test/unit/chartsheet/test_chartsheet_xml_declaration.c @@ -0,0 +1,28 @@ +/* + * Tests for the libxlsxwriter library. + * + * Copyright 2014-2016, John McNamara, jmcnamara@cpan.org + * + */ + +#include "../ctest.h" +#include "../helper.h" + +#include "xlsxwriter/chartsheet.h" + +// Test _xml_declaration(). +CTEST(chartsheet, xml_declaration) { + + char* got; + char exp[] = "\n"; + FILE* testfile = tmpfile(); + + lxw_chartsheet *chartsheet = lxw_chartsheet_new(); + chartsheet->file = testfile; + + _chartsheet_xml_declaration(chartsheet); + + RUN_XLSX_STREQ(exp, got); + + lxw_chartsheet_free(chartsheet); +}