diff --git a/.indent.pro b/.indent.pro index 4fc5b915..820363e5 100644 --- a/.indent.pro +++ b/.indent.pro @@ -57,6 +57,8 @@ -T lxw_chart_axis_tick_position -T lxw_chart_axis_type -T lxw_chart_blank +-T lxw_chart_custom_label +-T lxw_chart_data_label -T lxw_chart_error_bar_axis -T lxw_chart_error_bar_cap -T lxw_chart_error_bar_direction diff --git a/include/xlsxwriter/chart.h b/include/xlsxwriter/chart.h index 68f6e967..67e929dd 100644 --- a/include/xlsxwriter/chart.h +++ b/include/xlsxwriter/chart.h @@ -787,6 +787,29 @@ typedef struct lxw_chart_point { } lxw_chart_point; +typedef struct lxw_chart_data_label { + + char *value; + uint8_t delete; + lxw_chart_font *font; + +} lxw_chart_data_label; + +/* Internal version of lxw_chart_data_label with more metadata. */ +typedef struct lxw_chart_custom_label { + + char *value; + uint8_t delete; + lxw_chart_font *font; + + /* We use a range to hold the label formula properties even though it + * will only have 1 point in order to re-use similar functions.*/ + lxw_series_range *range; + + struct lxw_series_data_point data_point; + +} lxw_chart_custom_label; + /** * @brief Define how blank values are displayed in a chart. */ @@ -916,7 +939,9 @@ typedef struct lxw_chart_series { lxw_chart_pattern *pattern; lxw_chart_marker *marker; lxw_chart_point *points; + lxw_chart_custom_label *data_labels; uint16_t point_count; + uint16_t data_label_count; uint8_t smooth; uint8_t invert_if_negative; @@ -1659,6 +1684,9 @@ void chart_series_set_labels_options(lxw_chart_series *series, uint8_t show_name, uint8_t show_category, uint8_t show_value); +lxw_error chart_series_set_labels_custom(lxw_chart_series *series, lxw_chart_data_label + *data_labels[]); + /** * @brief Set the separator for the data label captions. * diff --git a/src/chart.c b/src/chart.c index ef185096..9d16d755 100644 --- a/src/chart.c +++ b/src/chart.c @@ -82,6 +82,23 @@ _chart_free_font(lxw_chart_font *font) free(font); } +STATIC void +_chart_free_data_labels(lxw_chart_series *series) +{ + uint16_t index; + + for (index = 0; index < series->data_label_count; index++) { + lxw_chart_custom_label *data_label = &series->data_labels[index]; + + free(data_label->value); + _chart_free_range(data_label->range); + _chart_free_font(data_label->font); + } + + series->data_label_count = 0; + free(series->data_labels); +} + /* * Free a series object. */ @@ -109,6 +126,7 @@ _chart_series_free(lxw_chart_series *series) _chart_free_range(series->values); _chart_free_range(series->title.range); _chart_free_points(series); + _chart_free_data_labels(series); if (series->x_error_bars) { free(series->x_error_bars->line); @@ -1067,12 +1085,14 @@ _chart_write_a_p_pie(lxw_chart *self, lxw_chart_font *font) * Write the element. */ STATIC void -_chart_write_a_p_rich(lxw_chart *self, char *name, lxw_chart_font *font) +_chart_write_a_p_rich(lxw_chart *self, char *name, lxw_chart_font *font, + uint8_t is_data_label) { lxw_xml_start_tag(self->file, "a:p", NULL); /* Write the a:pPr element. */ - _chart_write_a_p_pr_rich(self, font); + if (!is_data_label) + _chart_write_a_p_pr_rich(self, font); /* Write the a:r element. */ _chart_write_a_r(self, name, font); @@ -1454,8 +1474,8 @@ _chart_write_axis_font(lxw_chart *self, lxw_chart_font *font) * Write the element. */ STATIC void -_chart_write_rich(lxw_chart *self, char *name, uint8_t is_horizontal, - lxw_chart_font *font) +_chart_write_rich(lxw_chart *self, char *name, lxw_chart_font *font, + uint8_t is_horizontal, uint8_t is_data_label) { int32_t rotation = 0; @@ -1471,7 +1491,7 @@ _chart_write_rich(lxw_chart *self, char *name, uint8_t is_horizontal, _chart_write_a_lst_style(self); /* Write the a:p element. */ - _chart_write_a_p_rich(self, name, font); + _chart_write_a_p_rich(self, name, font, is_data_label); lxw_xml_end_tag(self->file, "c:rich"); } @@ -1487,7 +1507,7 @@ _chart_write_tx_rich(lxw_chart *self, char *name, uint8_t is_horizontal, lxw_xml_start_tag(self->file, "c:tx", NULL); /* Write the c:rich element. */ - _chart_write_rich(self, name, is_horizontal, font); + _chart_write_rich(self, name, font, is_horizontal, LXW_FALSE); lxw_xml_end_tag(self->file, "c:tx"); } @@ -2256,6 +2276,110 @@ _chart_write_label_num_fmt(lxw_chart *self, char *format) LXW_FREE_ATTRIBUTES(); } +/* + * Write parts of the elements for formula custom labels. + */ +STATIC void +_chart_write_custom_label_formula(lxw_chart *self, lxw_chart_series *series, + lxw_chart_custom_label *data_label) +{ + lxw_xml_empty_tag(self->file, "c:layout", NULL); + lxw_xml_start_tag(self->file, "c:tx", NULL); + + _chart_write_str_ref(self, data_label->range); + + lxw_xml_end_tag(self->file, "c:tx"); + + if (data_label->font) { + lxw_xml_empty_tag(self->file, "c:spPr", NULL); + _chart_write_tx_pr(self, LXW_FALSE, data_label->font); + } + + /* Write the c:showVal element. */ + if (series->show_labels_value) + _chart_write_show_val(self); + + /* Write the c:showCatName element. */ + if (series->show_labels_category) + _chart_write_show_cat_name(self); + + /* Write the c:showSerName element. */ + if (series->show_labels_name) + _chart_write_show_ser_name(self); + +} + +/* + * Write parts of the elements for string custom labels. + */ +STATIC void +_chart_write_custom_label_str(lxw_chart *self, lxw_chart_series *series, + lxw_chart_custom_label *data_label) +{ + lxw_xml_empty_tag(self->file, "c:layout", NULL); + lxw_xml_start_tag(self->file, "c:tx", NULL); + + /* Write the c:rich element. */ + _chart_write_rich(self, data_label->value, data_label->font, + LXW_FALSE, LXW_TRUE); + + lxw_xml_end_tag(self->file, "c:tx"); + + /* Write the c:showVal element. */ + if (series->show_labels_value) + _chart_write_show_val(self); + + /* Write the c:showCatName element. */ + if (series->show_labels_category) + _chart_write_show_cat_name(self); + + /* Write the c:showSerName element. */ + if (series->show_labels_name) + _chart_write_show_ser_name(self); + +} + +/* + * Write the elements for custom labels. + */ +STATIC void +_chart_write_custom_labels(lxw_chart *self, lxw_chart_series *series) +{ + uint16_t index = 0; + + for (index = 0; index < series->data_label_count; index++) { + lxw_chart_custom_label *data_label = &series->data_labels[index]; + + if (!data_label->value && !data_label->range && !data_label->delete + && !data_label->font) { + + continue; + } + + lxw_xml_start_tag(self->file, "c:dLbl", NULL); + + /* Write the c:idx element. */ + _chart_write_idx(self, index); + + if (data_label->delete) { + /* Write the c:delete element. */ + _chart_write_delete(self); + } + else if (data_label->value) { + _chart_write_custom_label_str(self, series, data_label); + } + else if (data_label->range) { + _chart_write_custom_label_formula(self, series, data_label); + } + else if (data_label->font) { + lxw_xml_empty_tag(self->file, "c:spPr", NULL); + _chart_write_tx_pr(self, LXW_FALSE, data_label->font); + } + + lxw_xml_end_tag(self->file, "c:dLbl"); + } +} + /* * Write the element. */ @@ -2267,6 +2391,9 @@ _chart_write_d_lbls(lxw_chart *self, lxw_chart_series *series) lxw_xml_start_tag(self->file, "c:dLbls", NULL); + if (series->data_labels) + _chart_write_custom_labels(self, series); + /* Write the c:numFmt element. */ if (series->label_num_format) _chart_write_label_num_fmt(self, series->label_num_format); @@ -3557,7 +3684,7 @@ _chart_write_legend_entry(lxw_chart *self, uint16_t index) /* Write the c:idx element. */ _chart_write_idx(self, self->delete_series[index]); - /* Write the c:delete element. */ + /* Write the c:dst_label element. */ _chart_write_delete(self); lxw_xml_end_tag(self->file, "c:legendEntry"); @@ -4999,7 +5126,7 @@ lxw_chart_add_data_cache(lxw_series_range *range, uint8_t *data, } /* - * Insert an image into the worksheet. + * Add a series to the chart. */ lxw_chart_series * chart_add_series(lxw_chart *self, const char *categories, const char *values) @@ -5306,7 +5433,7 @@ chart_series_set_marker_pattern(lxw_chart_series *series, } /* - * Store the horizontal page breaks on a worksheet. + * Store the points for a chart. */ lxw_error chart_series_set_points(lxw_chart_series *series, lxw_chart_point *points[]) @@ -5375,6 +5502,81 @@ chart_series_set_labels_options(lxw_chart_series *series, uint8_t show_name, series->show_labels_value = show_value; } +/* + * Store the custom data_labels for a chart. + */ +lxw_error +chart_series_set_labels_custom(lxw_chart_series *series, + lxw_chart_data_label *data_labels[]) +{ + uint16_t i = 0; + uint16_t data_label_count = 0; + + if (data_labels == NULL) + return LXW_ERROR_NULL_PARAMETER_IGNORED; + + while (data_labels[data_label_count]) + data_label_count++; + + if (data_label_count == 0) + return LXW_ERROR_NULL_PARAMETER_IGNORED; + + series->has_labels = LXW_TRUE; + + /* Set the Value label type if no other type is set. */ + if (!series->show_labels_name && !series->show_labels_category + && !series->show_labels_value) { + series->show_labels_value = LXW_TRUE; + } + + /* Free any existing resource. */ + _chart_free_data_labels(series); + + series->data_labels = calloc(data_label_count, + sizeof(lxw_chart_custom_label)); + RETURN_ON_MEM_ERROR(series->data_labels, LXW_ERROR_MEMORY_MALLOC_FAILED); + + /* Copy the user data into the array of new structs. The struct types + * are different since the internal version has more fields. */ + for (i = 0; i < data_label_count; i++) { + lxw_chart_data_label *user_data_label = data_labels[i]; + lxw_chart_custom_label *data_label = &series->data_labels[i]; + + char *src_value = user_data_label->value; + + data_label->delete = user_data_label->delete; + + data_label->font = _chart_convert_font_args(user_data_label->font); + + if (src_value) { + if (*src_value == '=') { + /* The value is a formula. Handle like other chart ranges. */ + data_label->range = calloc(1, sizeof(lxw_series_range)); + GOTO_LABEL_ON_MEM_ERROR(data_label->range, mem_error); + + data_label->range->formula = lxw_strdup(src_value + 1); + + /* Add the formula to the data cache to allow value to be looked + * up and filled in when the file is closed. */ + if (_chart_init_data_cache(data_label->range) != LXW_NO_ERROR) + goto mem_error; + } + else { + /* The value is a simple string. */ + data_label->value = lxw_strdup(src_value); + } + } + } + + series->data_label_count = data_label_count; + + return LXW_NO_ERROR; + +mem_error: + _chart_free_data_labels(series); + return LXW_ERROR_MEMORY_MALLOC_FAILED; +} + /* * Set the data labels separator for a series. */ diff --git a/src/workbook.c b/src/workbook.c index e54b6dd6..258f0a76 100644 --- a/src/workbook.c +++ b/src/workbook.c @@ -879,6 +879,9 @@ _populate_range_dimensions(lxw_workbook *self, lxw_series_range *range) STATIC void _populate_range(lxw_workbook *self, lxw_series_range *range) { + if (!range) + return; + _populate_range_dimensions(self, range); _populate_range_data_cache(self, range); } @@ -892,6 +895,7 @@ _add_chart_cache_data(lxw_workbook *self) { lxw_chart *chart; lxw_chart_series *series; + uint16_t i; STAILQ_FOREACH(chart, self->ordered_charts, ordered_list_pointers) { @@ -906,6 +910,11 @@ _add_chart_cache_data(lxw_workbook *self) _populate_range(self, series->categories); _populate_range(self, series->values); _populate_range(self, series->title.range); + + for (i = 0; i < series->data_label_count; i++) { + lxw_chart_custom_label *data_label = &series->data_labels[i]; + _populate_range(self, data_label->range); + } } } } diff --git a/test/functional/src/test_chart_data_labels26.c b/test/functional/src/test_chart_data_labels26.c new file mode 100644 index 00000000..0197b651 --- /dev/null +++ b/test/functional/src/test_chart_data_labels26.c @@ -0,0 +1,48 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels26.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 48514944; + chart->axis_id_2 = 48516480; + + uint8_t data[5][4] = { + {1, 2, 3, 10}, + {2, 4, 6, 20}, + {3, 6, 9, 30}, + {4, 8, 12, 40}, + {5, 10, 15, 50} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 4; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_data_label data_label1 = {.value = "33"}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels27.c b/test/functional/src/test_chart_data_labels27.c new file mode 100644 index 00000000..299cd0fc --- /dev/null +++ b/test/functional/src/test_chart_data_labels27.c @@ -0,0 +1,48 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels27.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 48514944; + chart->axis_id_2 = 48516480; + + uint8_t data[5][4] = { + {1, 2, 3, 10}, + {2, 4, 6, 20}, + {3, 6, 9, 30}, + {4, 8, 12, 40}, + {5, 10, 15, 50} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 4; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_data_label data_label1 = {.value = "=Sheet1!$D$1"}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels28.c b/test/functional/src/test_chart_data_labels28.c new file mode 100644 index 00000000..c4a39591 --- /dev/null +++ b/test/functional/src/test_chart_data_labels28.c @@ -0,0 +1,64 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels28.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 48514944; + chart->axis_id_2 = 48516480; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + worksheet_write_string(worksheet, CELL("D1"), "foo" , NULL); + worksheet_write_string(worksheet, CELL("D2"), "bar" , NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + + lxw_chart_data_label data_label1 = {.value = "123"}; + lxw_chart_data_label data_label2 = {.value = "abc"}; + lxw_chart_data_label data_label3 = {0}; + lxw_chart_data_label data_label4 = {.value = "=Sheet1!$D$1"}; + lxw_chart_data_label data_label5 = {.value = "=Sheet1!$D$2"}; + + lxw_chart_data_label *data_labels[] = { + &data_label1, + &data_label2, + &data_label3, + &data_label4, + &data_label5, + NULL + }; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels29.c b/test/functional/src/test_chart_data_labels29.c new file mode 100644 index 00000000..c2c77900 --- /dev/null +++ b/test/functional/src/test_chart_data_labels29.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels29.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 67858816; + chart->axis_id_2 = 67863296; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_data_label data_label1 = {.delete = LXW_TRUE}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels30.c b/test/functional/src/test_chart_data_labels30.c new file mode 100644 index 00000000..023b9c38 --- /dev/null +++ b/test/functional/src/test_chart_data_labels30.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels30.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 67858816; + chart->axis_id_2 = 67863296; + + uint8_t data[5][3] = { + {1, 2, 3}, + {2, 4, 6}, + {3, 6, 9}, + {4, 8, 12}, + {5, 10, 15} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 3; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_data_label data_label1 = {.delete = LXW_TRUE}; + lxw_chart_data_label data_label2 = {0}; + lxw_chart_data_label *data_labels[] = {&data_label1, &data_label2, &data_label1, &data_label2, &data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels31.c b/test/functional/src/test_chart_data_labels31.c new file mode 100644 index 00000000..270ad794 --- /dev/null +++ b/test/functional/src/test_chart_data_labels31.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels31.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 71248896; + chart->axis_id_2 = 71373568; + + uint8_t data[5][4] = { + {1, 2, 3, 10}, + {2, 4, 6, 20}, + {3, 6, 9, 30}, + {4, 8, 12, 40}, + {5, 10, 15, 50} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 4; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_data_label data_label1 = {.value = "33"}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + chart_series_set_labels_options(series, LXW_TRUE, LXW_TRUE, LXW_TRUE); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels32.c b/test/functional/src/test_chart_data_labels32.c new file mode 100644 index 00000000..ddd0e32b --- /dev/null +++ b/test/functional/src/test_chart_data_labels32.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels32.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 71374336; + chart->axis_id_2 = 71414144; + + uint8_t data[5][4] = { + {1, 2, 3, 10}, + {2, 4, 6, 20}, + {3, 6, 9, 30}, + {4, 8, 12, 40}, + {5, 10, 15, 50} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 4; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .color = LXW_COLOR_RED, .baseline = -1}; + lxw_chart_data_label data_label1 = {.value = "33", .font = &font1}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels33.c b/test/functional/src/test_chart_data_labels33.c new file mode 100644 index 00000000..bd1092a2 --- /dev/null +++ b/test/functional/src/test_chart_data_labels33.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels33.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 65546112; + chart->axis_id_2 = 70217728; + + uint8_t data[5][4] = { + {1, 2, 3, 10}, + {2, 4, 6, 20}, + {3, 6, 9, 30}, + {4, 8, 12, 40}, + {5, 10, 15, 50} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 4; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .baseline = -1}; + lxw_chart_data_label data_label1 = {.font = &font1}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/src/test_chart_data_labels34.c b/test/functional/src/test_chart_data_labels34.c new file mode 100644 index 00000000..d5ea7dbe --- /dev/null +++ b/test/functional/src/test_chart_data_labels34.c @@ -0,0 +1,49 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2020, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = workbook_new("test_chart_data_labels34.xlsx"); + lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); + lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_COLUMN); + + /* For testing, copy the randomly generated axis ids in the target file. */ + chart->axis_id_1 = 48497792; + chart->axis_id_2 = 48499712; + + uint8_t data[5][4] = { + {1, 2, 3, 10}, + {2, 4, 6, 20}, + {3, 6, 9, 30}, + {4, 8, 12, 40}, + {5, 10, 15, 50} + }; + + int row, col; + for (row = 0; row < 5; row++) + for (col = 0; col < 4; col++) + worksheet_write_number(worksheet, row, col, data[row][col], NULL); + + lxw_chart_series *series = chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + + lxw_chart_font font1 = {.bold = LXW_TRUE, .italic = LXW_TRUE, .color = LXW_COLOR_RED, .baseline = -1}; + lxw_chart_data_label data_label1 = {. value = "=Sheet1!$D$1", .font = &font1}; + lxw_chart_data_label *data_labels[] = {&data_label1, NULL}; + + chart_series_set_labels_custom(series, data_labels); + + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/test_chart_data_labels.py b/test/functional/test_chart_data_labels.py index 35c61941..3aaaec55 100644 --- a/test/functional/test_chart_data_labels.py +++ b/test/functional/test_chart_data_labels.py @@ -86,3 +86,30 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest): def test_chart_data_labels25(self): self.run_exe_test('test_chart_data_labels25') + + def test_chart_data_labels26(self): + self.run_exe_test('test_chart_data_labels26') + + def test_chart_data_labels27(self): + self.run_exe_test('test_chart_data_labels27') + + def test_chart_data_labels28(self): + self.run_exe_test('test_chart_data_labels28') + + def test_chart_data_labels29(self): + self.run_exe_test('test_chart_data_labels29') + + def test_chart_data_labels30(self): + self.run_exe_test('test_chart_data_labels30') + + def test_chart_data_labels31(self): + self.run_exe_test('test_chart_data_labels31') + + def test_chart_data_labels32(self): + self.run_exe_test('test_chart_data_labels32') + + def test_chart_data_labels33(self): + self.run_exe_test('test_chart_data_labels33') + + def test_chart_data_labels34(self): + self.run_exe_test('test_chart_data_labels34') diff --git a/test/functional/xlsx_files/chart_data_labels26.xlsx b/test/functional/xlsx_files/chart_data_labels26.xlsx new file mode 100644 index 00000000..1a8af804 Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels26.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels27.xlsx b/test/functional/xlsx_files/chart_data_labels27.xlsx new file mode 100644 index 00000000..03b68b5c Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels27.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels28.xlsx b/test/functional/xlsx_files/chart_data_labels28.xlsx new file mode 100644 index 00000000..11965380 Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels28.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels29.xlsx b/test/functional/xlsx_files/chart_data_labels29.xlsx new file mode 100644 index 00000000..314c7387 Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels29.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels30.xlsx b/test/functional/xlsx_files/chart_data_labels30.xlsx new file mode 100644 index 00000000..611139af Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels30.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels31.xlsx b/test/functional/xlsx_files/chart_data_labels31.xlsx new file mode 100644 index 00000000..fe5201ff Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels31.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels32.xlsx b/test/functional/xlsx_files/chart_data_labels32.xlsx new file mode 100644 index 00000000..42aebd2d Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels32.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels33.xlsx b/test/functional/xlsx_files/chart_data_labels33.xlsx new file mode 100644 index 00000000..61dcb2da Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels33.xlsx differ diff --git a/test/functional/xlsx_files/chart_data_labels34.xlsx b/test/functional/xlsx_files/chart_data_labels34.xlsx new file mode 100644 index 00000000..e7547050 Binary files /dev/null and b/test/functional/xlsx_files/chart_data_labels34.xlsx differ