diff --git a/.indent.pro b/.indent.pro index 73d5010d..65cfe9e6 100644 --- a/.indent.pro +++ b/.indent.pro @@ -51,6 +51,7 @@ -T lxw_chart_axis -T lxw_chart_axis_display_unit -T lxw_chart_axis_label_position +-T lxw_chart_axis_tick_mark -T lxw_chart_axis_tick_position -T lxw_chart_fill -T lxw_chart_font diff --git a/include/xlsxwriter/chart.h b/include/xlsxwriter/chart.h index 2b31029b..ab9fe927 100644 --- a/include/xlsxwriter/chart.h +++ b/include/xlsxwriter/chart.h @@ -492,6 +492,27 @@ typedef enum lxw_chart_axis_display_unit { LXW_CHART_AXIS_UNITS_TRILLIONS } lxw_chart_axis_display_unit; +/** + * @brief Tick mark types for an axis. + */ +typedef enum lxw_chart_axis_tick_mark { + + /** Default tick mark for the chart axis. Usually outside. */ + LXW_CHART_AXIS_TICK_MARK_DEFAULT, + + /** No tick mark for the axis. */ + LXW_CHART_AXIS_TICK_MARK_NONE, + + /** Tick mark inside the axis only. */ + LXW_CHART_AXIS_TICK_MARK_INSIDE, + + /** Tick mark outside the axis only. */ + LXW_CHART_AXIS_TICK_MARK_OUTSIDE, + + /** Tick mark inside and outside the axis. */ + LXW_CHART_AXIS_TICK_MARK_CROSSING +} lxw_chart_tick_mark; + enum lxw_chart_position { LXW_CHART_AXIS_RIGHT, LXW_CHART_AXIS_LEFT, @@ -708,6 +729,7 @@ typedef struct lxw_chart_axis { char default_num_format[LXW_CHART_NUM_FORMAT_LEN]; uint8_t major_tick_mark; + uint8_t minor_tick_mark; uint8_t is_horizontal; lxw_chart_gridline major_gridlines; @@ -1571,6 +1593,10 @@ void chart_axis_set_max(lxw_chart_axis *axis, double max); */ void chart_axis_set_log_base(lxw_chart_axis *axis, uint16_t log_base); +void chart_axis_set_major_tick_mark(lxw_chart_axis *axis, uint8_t type); + +void chart_axis_set_minor_tick_mark(lxw_chart_axis *axis, uint8_t type); + /** * @brief Set the interval between category values. * diff --git a/src/chart.c b/src/chart.c index 80464cea..2e8c2f73 100644 --- a/src/chart.c +++ b/src/chart.c @@ -1815,13 +1815,49 @@ _chart_write_major_tick_mark(lxw_chart *self, lxw_chart_axis *axis) return; LXW_INIT_ATTRIBUTES(); - LXW_PUSH_ATTRIBUTES_STR("val", "cross"); + + if (axis->major_tick_mark == LXW_CHART_AXIS_TICK_MARK_NONE) + LXW_PUSH_ATTRIBUTES_STR("val", "none"); + else if (axis->major_tick_mark == LXW_CHART_AXIS_TICK_MARK_INSIDE) + LXW_PUSH_ATTRIBUTES_STR("val", "in"); + else if (axis->major_tick_mark == LXW_CHART_AXIS_TICK_MARK_CROSSING) + LXW_PUSH_ATTRIBUTES_STR("val", "cross"); + else + LXW_PUSH_ATTRIBUTES_STR("val", "out"); lxw_xml_empty_tag(self->file, "c:majorTickMark", &attributes); LXW_FREE_ATTRIBUTES(); } +/* + * Write the element. + */ +STATIC void +_chart_write_minor_tick_mark(lxw_chart *self, lxw_chart_axis *axis) +{ + struct xml_attribute_list attributes; + struct xml_attribute *attribute; + + if (!axis->minor_tick_mark) + return; + + LXW_INIT_ATTRIBUTES(); + + if (axis->minor_tick_mark == LXW_CHART_AXIS_TICK_MARK_NONE) + LXW_PUSH_ATTRIBUTES_STR("val", "none"); + else if (axis->minor_tick_mark == LXW_CHART_AXIS_TICK_MARK_INSIDE) + LXW_PUSH_ATTRIBUTES_STR("val", "in"); + else if (axis->minor_tick_mark == LXW_CHART_AXIS_TICK_MARK_CROSSING) + LXW_PUSH_ATTRIBUTES_STR("val", "cross"); + else + LXW_PUSH_ATTRIBUTES_STR("val", "out"); + + lxw_xml_empty_tag(self->file, "c:minorTickMark", &attributes); + + LXW_FREE_ATTRIBUTES(); +} + /* * Write the element. */ @@ -2721,20 +2757,15 @@ _chart_write_page_margins(lxw_chart *self) { struct xml_attribute_list attributes; struct xml_attribute *attribute; - char b[] = "0.75"; - char l[] = "0.7"; - char r[] = "0.7"; - char t[] = "0.75"; - char header[] = "0.3"; - char footer[] = "0.3"; LXW_INIT_ATTRIBUTES(); - LXW_PUSH_ATTRIBUTES_STR("b", b); - LXW_PUSH_ATTRIBUTES_STR("l", l); - LXW_PUSH_ATTRIBUTES_STR("r", r); - LXW_PUSH_ATTRIBUTES_STR("t", t); - LXW_PUSH_ATTRIBUTES_STR("header", header); - LXW_PUSH_ATTRIBUTES_STR("footer", footer); + + LXW_PUSH_ATTRIBUTES_STR("b", "0.75"); + LXW_PUSH_ATTRIBUTES_STR("l", "0.7"); + LXW_PUSH_ATTRIBUTES_STR("r", "0.7"); + LXW_PUSH_ATTRIBUTES_STR("t", "0.7"); + LXW_PUSH_ATTRIBUTES_STR("header", "0.3"); + LXW_PUSH_ATTRIBUTES_STR("footer", "0.3"); lxw_xml_empty_tag(self->file, "c:pageMargins", &attributes); @@ -2861,6 +2892,9 @@ _chart_write_cat_axis(lxw_chart *self) /* Write the c:majorTickMark element. */ _chart_write_major_tick_mark(self, self->x_axis); + /* Write the c:minorTickMark element. */ + _chart_write_minor_tick_mark(self, self->x_axis); + /* Write the c:tickLblPos element. */ _chart_write_tick_label_pos(self, self->x_axis); @@ -2937,6 +2971,9 @@ _chart_write_val_axis(lxw_chart *self) /* Write the c:majorTickMark element. */ _chart_write_major_tick_mark(self, self->y_axis); + /* Write the c:minorTickMark element. */ + _chart_write_minor_tick_mark(self, self->y_axis); + /* Write the c:tickLblPos element. */ _chart_write_tick_label_pos(self, self->y_axis); @@ -3010,6 +3047,9 @@ _chart_write_cat_val_axis(lxw_chart *self) /* Write the c:majorTickMark element. */ _chart_write_major_tick_mark(self, self->x_axis); + /* Write the c:minorTickMark element. */ + _chart_write_minor_tick_mark(self, self->x_axis); + /* Write the c:tickLblPos element. */ _chart_write_tick_label_pos(self, self->x_axis); @@ -3572,7 +3612,7 @@ _chart_initialize_radar_chart(lxw_chart *self, uint8_t type) self->x_axis->is_category = LXW_TRUE; self->y_axis->is_value = LXW_TRUE; - self->y_axis->major_tick_mark = LXW_TRUE; + self->y_axis->major_tick_mark = LXW_CHART_AXIS_TICK_MARK_CROSSING; /* Initialize the function pointers for this chart type. */ self->write_chart_type = _chart_write_radar_chart; @@ -4150,6 +4190,24 @@ chart_axis_set_log_base(lxw_chart_axis *axis, uint16_t log_base) axis->log_base = log_base; } +/* + * Set the major mark for an axis. + */ +void +chart_axis_set_major_tick_mark(lxw_chart_axis *axis, uint8_t type) +{ + axis->major_tick_mark = type; +} + +/* + * Set the minor mark for an axis. + */ +void +chart_axis_set_minor_tick_mark(lxw_chart_axis *axis, uint8_t type) +{ + axis->minor_tick_mark = type; +} + /* * Set interval unit for a category axis. */ diff --git a/test/functional/src/test_chart_axis41.c b/test/functional/src/test_chart_axis41.c new file mode 100644 index 00000000..3c3a0b06 --- /dev/null +++ b/test/functional/src/test_chart_axis41.c @@ -0,0 +1,46 @@ +/***************************************************************************** + * Test cases for libxlsxwriter. + * + * Test to compare output against Excel files. + * + * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org + * + */ + +#include "xlsxwriter.h" + +int main() { + + lxw_workbook *workbook = new_workbook("test_chart_axis41.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 = 108321024; + chart->axis_id_2 = 108328448; + + 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); + + chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$5"); + chart_add_series(chart, NULL, "=Sheet1!$B$1:$B$5"); + chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5"); + + chart_axis_set_major_tick_mark(chart->x_axis, LXW_CHART_AXIS_TICK_MARK_NONE); + chart_axis_set_minor_tick_mark(chart->x_axis, LXW_CHART_AXIS_TICK_MARK_INSIDE); + chart_axis_set_minor_tick_mark(chart->y_axis, LXW_CHART_AXIS_TICK_MARK_CROSSING); + + worksheet_insert_chart(worksheet, CELL("E9"), chart); + + return workbook_close(workbook); +} diff --git a/test/functional/test_chart_axis.py b/test/functional/test_chart_axis.py index c40644a8..4b85437a 100644 --- a/test/functional/test_chart_axis.py +++ b/test/functional/test_chart_axis.py @@ -114,3 +114,6 @@ class TestCompareXLSXFiles(base_test_class.XLSXBaseTest): def test_chart_axis40(self): self.run_exe_test('test_chart_axis40') + + def test_chart_axis41(self): + self.run_exe_test('test_chart_axis41') diff --git a/test/functional/xlsx_files/chart_axis41.xlsx b/test/functional/xlsx_files/chart_axis41.xlsx new file mode 100644 index 00000000..3ac9342d Binary files /dev/null and b/test/functional/xlsx_files/chart_axis41.xlsx differ