Add chart gridline handling.

This commit is contained in:
John McNamara 2017-01-06 00:13:14 +00:00
parent 18f61f41be
commit 99849be9c6
21 changed files with 608 additions and 7 deletions

1
.indent.pro vendored
View file

@ -51,6 +51,7 @@
-T lxw_chart_axis
-T lxw_chart_fill
-T lxw_chart_font
-T lxw_chart_gridline
-T lxw_chart_legend
-T lxw_chart_legend_position
-T lxw_chart_line

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View file

@ -621,6 +621,14 @@ typedef struct lxw_chart_series {
} lxw_chart_series;
/* Struct for major/minor axis gridlines. */
typedef struct lxw_chart_gridline {
uint8_t visible;
lxw_chart_line *line;
} lxw_chart_gridline;
/**
* @brief Struct to represent an Excel chart axis.
*
@ -634,10 +642,12 @@ typedef struct lxw_chart_axis {
char num_format[LXW_CHART_NUM_FORMAT_LEN];
char default_num_format[LXW_CHART_NUM_FORMAT_LEN];
uint8_t default_major_gridlines;
uint8_t major_tick_mark;
uint8_t is_horizontal;
lxw_chart_gridline major_gridlines;
lxw_chart_gridline minor_gridlines;
lxw_chart_font *num_font;
lxw_chart_line *line;
lxw_chart_fill *fill;
@ -1382,6 +1392,100 @@ 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);
/**
* @brief Turn on/off the major gridlines for an axis.
*
* @param axis A pointer to a chart #lxw_chart_axis object.
* @param visible Turn off/on the major gridline. (0/1)
*
* Turn on or off the major gridlines for an X or Y axis. In most Excel charts
* the Y axis major gridlines are on by default and the X axis major
* gridlines are off by default.
*
* Example:
*
* @code
* // Reverse the normal visible/hidden gridlines for a column chart.
* chart_axis_major_gridlines_set_visible(chart->x_axis, LXW_TRUE);
* chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_FALSE);
* @endcode
*
* @image html chart_gridline1.png
*/
void chart_axis_major_gridlines_set_visible(lxw_chart_axis *axis,
uint8_t visible);
/**
* @brief Turn on/off the minor gridlines for an axis.
*
* @param axis A pointer to a chart #lxw_chart_axis object.
* @param visible Turn off/on the minor gridline. (0/1)
*
* Turn on or off the minor gridlines for an X or Y axis. In most Excel charts
* the X and Y axis minor gridlines are off by default.
*
* Example, turn on all major and minor gridlines:
*
* @code
* chart_axis_major_gridlines_set_visible(chart->x_axis, LXW_TRUE);
* chart_axis_minor_gridlines_set_visible(chart->x_axis, LXW_TRUE);
* chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_TRUE);
* chart_axis_minor_gridlines_set_visible(chart->y_axis, LXW_TRUE);
* @endcode
*
* @image html chart_gridline2.png
*/
void chart_axis_minor_gridlines_set_visible(lxw_chart_axis *axis,
uint8_t visible);
/**
* @brief Set the line properties for the chart axis major gridlines.
*
* @param axis A pointer to a chart #lxw_chart_axis object.
* @param line A #lxw_chart_line struct.
*
* Format the line properties of the major gridlines of a chart:
*
* @code
* lxw_chart_line line1 = {.color = LXW_COLOR_RED,
* .width = 0.5,
* .dash_type = LXW_CHART_LINE_DASH_SQUARE_DOT};
*
* lxw_chart_line line2 = {.color = LXW_COLOR_YELLOW};
*
* lxw_chart_line line3 = {.width = 1.25,
* .dash_type = LXW_CHART_LINE_DASH_DASH};
*
* lxw_chart_line line4 = {.color = 0x00B050};
*
* chart_axis_major_gridlines_set_line(chart->x_axis, &line1);
* chart_axis_minor_gridlines_set_line(chart->x_axis, &line2);
* chart_axis_major_gridlines_set_line(chart->y_axis, &line3);
* chart_axis_minor_gridlines_set_line(chart->y_axis, &line4);
* @endcode
*
* @image html chart_gridline3.png
*
* For more information see @ref chart_lines.
*/
void chart_axis_major_gridlines_set_line(lxw_chart_axis *axis,
lxw_chart_line *line);
/**
* @brief Set the line properties for the chart axis minor gridlines.
*
* @param axis A pointer to a chart #lxw_chart_axis object.
* @param line A #lxw_chart_line struct.
*
* Format the line properties of the minor gridlines of a chart, see the
* example above.
*
* For more information see @ref chart_lines.
*/
void chart_axis_minor_gridlines_set_line(lxw_chart_axis *axis,
lxw_chart_line *line);
/**
* @brief Set the title of the chart.
*

View file

@ -133,6 +133,8 @@ lxw_chart_free(lxw_chart *chart)
free(chart->x_axis->line);
free(chart->x_axis->fill);
free(chart->x_axis->pattern);
free(chart->x_axis->major_gridlines.line);
free(chart->x_axis->minor_gridlines.line);
free(chart->x_axis);
}
@ -145,6 +147,8 @@ lxw_chart_free(lxw_chart *chart)
free(chart->y_axis->line);
free(chart->y_axis->fill);
free(chart->y_axis->pattern);
free(chart->y_axis->major_gridlines.line);
free(chart->y_axis->minor_gridlines.line);
free(chart->y_axis);
}
@ -218,8 +222,8 @@ lxw_chart_new(uint8_t type)
lxw_strcpy(chart->x_axis->default_num_format, "General");
lxw_strcpy(chart->y_axis->default_num_format, "General");
chart->x_axis->default_major_gridlines = LXW_FALSE;
chart->y_axis->default_major_gridlines = LXW_TRUE;
chart->x_axis->major_gridlines.visible = LXW_FALSE;
chart->y_axis->major_gridlines.visible = LXW_TRUE;
chart->series_overlap_1 = 100;
@ -2340,9 +2344,43 @@ _chart_write_lbl_offset(lxw_chart *self)
STATIC void
_chart_write_major_gridlines(lxw_chart *self, lxw_chart_axis *axis)
{
if (!axis->major_gridlines.visible)
return;
if (axis->default_major_gridlines)
if (axis->major_gridlines.line) {
lxw_xml_start_tag(self->file, "c:majorGridlines", NULL);
/* Write the c:spPr element for the axis line. */
_chart_write_sp_pr(self, axis->major_gridlines.line, NULL, NULL);
lxw_xml_end_tag(self->file, "c:majorGridlines");
}
else {
lxw_xml_empty_tag(self->file, "c:majorGridlines", NULL);
}
}
/*
* Write the <c:minorGridlines> element.
*/
STATIC void
_chart_write_minor_gridlines(lxw_chart *self, lxw_chart_axis *axis)
{
if (!axis->minor_gridlines.visible)
return;
if (axis->minor_gridlines.line) {
lxw_xml_start_tag(self->file, "c:minorGridlines", NULL);
/* Write the c:spPr element for the axis line. */
_chart_write_sp_pr(self, axis->minor_gridlines.line, NULL, NULL);
lxw_xml_end_tag(self->file, "c:minorGridlines");
}
else {
lxw_xml_empty_tag(self->file, "c:minorGridlines", NULL);
}
}
/*
@ -2660,6 +2698,9 @@ _chart_write_cat_axis(lxw_chart *self)
/* Write the c:majorGridlines element. */
_chart_write_major_gridlines(self, self->x_axis);
/* Write the c:minorGridlines element. */
_chart_write_minor_gridlines(self, self->x_axis);
/* Write the axis title elements. */
self->x_axis->title.is_horizontal = self->has_horiz_cat_axis;
_chart_write_title(self, &self->x_axis->title);
@ -2724,6 +2765,9 @@ _chart_write_val_axis(lxw_chart *self)
/* Write the c:majorGridlines element. */
_chart_write_major_gridlines(self, self->y_axis);
/* Write the c:minorGridlines element. */
_chart_write_minor_gridlines(self, self->y_axis);
/* Write the axis title elements. */
self->y_axis->title.is_horizontal = self->has_horiz_val_axis;
_chart_write_title(self, &self->y_axis->title);
@ -2778,6 +2822,12 @@ _chart_write_cat_val_axis(lxw_chart *self)
/* Write the c:axPos element. */
_chart_write_axis_pos(self, position, self->y_axis->reverse);
/* Write the c:majorGridlines element. */
_chart_write_major_gridlines(self, self->x_axis);
/* Write the c:minorGridlines element. */
_chart_write_minor_gridlines(self, self->x_axis);
/* Write the axis title elements. */
self->x_axis->title.is_horizontal = self->has_horiz_val_axis;
_chart_write_title(self, &self->x_axis->title);
@ -3203,8 +3253,9 @@ _chart_initialize_bar_chart(lxw_chart *self, uint8_t type)
self->y_axis = tmp;
/*Also reverse some of the defaults. */
self->x_axis->default_major_gridlines = LXW_FALSE;
self->y_axis->default_major_gridlines = LXW_TRUE;
self->x_axis->major_gridlines.visible = LXW_FALSE;
self->y_axis->major_gridlines.visible = LXW_TRUE;
self->has_horiz_cat_axis = LXW_TRUE;
self->has_horiz_val_axis = LXW_FALSE;
@ -3322,7 +3373,8 @@ _chart_initialize_radar_chart(lxw_chart *self, uint8_t type)
if (type == LXW_CHART_RADAR)
_chart_set_default_marker_type(self, LXW_CHART_MARKER_NONE);
self->x_axis->default_major_gridlines = LXW_TRUE;
self->x_axis->major_gridlines.visible = LXW_TRUE;
self->y_axis->major_tick_mark = LXW_TRUE;
/* Initialize the function pointers for this chart type. */
@ -3863,6 +3915,64 @@ chart_axis_set_log_base(lxw_chart_axis *axis, uint16_t log_base)
axis->log_base = log_base;
}
/*
* Set the axis major gridlines on/off.
*/
void
chart_axis_major_gridlines_set_visible(lxw_chart_axis *axis, uint8_t visible)
{
axis->major_gridlines.visible = visible;
}
/*
* Set a line type for the major gridlines.
*/
void
chart_axis_major_gridlines_set_line(lxw_chart_axis *axis,
lxw_chart_line *line)
{
if (!line)
return;
/* Free any previously allocated resource. */
free(axis->major_gridlines.line);
axis->major_gridlines.line = _chart_convert_line_args(line);
/* If the gridline has a format it should also be visible. */
if (axis->major_gridlines.line)
axis->major_gridlines.visible = LXW_TRUE;
}
/*
* Set the axis minor gridlines on/off.
*/
void
chart_axis_minor_gridlines_set_visible(lxw_chart_axis *axis, uint8_t visible)
{
axis->minor_gridlines.visible = visible;
}
/*
* Set a line type for the minor gridlines.
*/
void
chart_axis_minor_gridlines_set_line(lxw_chart_axis *axis,
lxw_chart_line *line)
{
if (!line)
return;
/* Free any previously allocated resource. */
free(axis->minor_gridlines.line);
axis->minor_gridlines.line = _chart_convert_line_args(line);
/* If the gridline has a format it should also be visible. */
if (axis->minor_gridlines.line)
axis->minor_gridlines.visible = LXW_TRUE;
}
/*
* Set the chart title.
*/

View file

@ -0,0 +1,45 @@
/*****************************************************************************
* 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_gridlines01.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 = 67390848;
chart->axis_id_2 = 68472192;
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_major_gridlines_set_visible(chart->x_axis, LXW_TRUE);
chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_FALSE);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,51 @@
/*****************************************************************************
* 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_gridlines02.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_SCATTER);
/* For testing, copy the randomly generated axis ids in the target file. */
chart->axis_id_1 = 57940608;
chart->axis_id_2 = 57938688;
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,
"=Sheet1!$A$1:$A$5",
"=Sheet1!$B$1:$B$5"
);
chart_add_series(chart,
"=Sheet1!$A$1:$A$5",
"=Sheet1!$C$1:$C$5"
);
chart_axis_major_gridlines_set_visible(chart->x_axis, LXW_TRUE);
chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_FALSE);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,44 @@
/*****************************************************************************
* 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_gridlines04.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_RADAR);
/* For testing, copy the randomly generated axis ids in the target file. */
chart->axis_id_1 = 54977280;
chart->axis_id_2 = 54978816;
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_major_gridlines_set_visible(chart->y_axis, LXW_FALSE);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,49 @@
/*****************************************************************************
* 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_gridlines05.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 = 80072064;
chart->axis_id_2 = 79959168;
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_major_gridlines_set_visible(chart->x_axis, LXW_TRUE);
chart_axis_minor_gridlines_set_visible(chart->x_axis, LXW_TRUE);
chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_TRUE);
chart_axis_minor_gridlines_set_visible(chart->y_axis, LXW_TRUE);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,53 @@
/*****************************************************************************
* 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_gridlines06.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_SCATTER);
/* For testing, copy the randomly generated axis ids in the target file. */
chart->axis_id_1 = 82812288;
chart->axis_id_2 = 46261376;
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,
"=Sheet1!$A$1:$A$5",
"=Sheet1!$B$1:$B$5"
);
chart_add_series(chart,
"=Sheet1!$A$1:$A$5",
"=Sheet1!$C$1:$C$5"
);
chart_axis_major_gridlines_set_visible(chart->x_axis, LXW_TRUE);
chart_axis_minor_gridlines_set_visible(chart->x_axis, LXW_TRUE);
chart_axis_major_gridlines_set_visible(chart->y_axis, LXW_TRUE);
chart_axis_minor_gridlines_set_visible(chart->y_axis, LXW_TRUE);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,45 @@
/*****************************************************************************
* 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_gridlines08.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_RADAR);
/* For testing, copy the randomly generated axis ids in the target file. */
chart->axis_id_1 = 60019072;
chart->axis_id_2 = 60020608;
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_major_gridlines_set_visible(chart->y_axis, LXW_TRUE);
chart_axis_minor_gridlines_set_visible(chart->y_axis, LXW_TRUE);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,60 @@
/*****************************************************************************
* 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_gridlines09.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 = 48744320;
chart->axis_id_2 = 49566848;
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");
lxw_chart_line line1 = {.color = LXW_COLOR_RED,
.width = 0.5,
.dash_type = LXW_CHART_LINE_DASH_SQUARE_DOT};
lxw_chart_line line2 = {.color = LXW_COLOR_YELLOW};
lxw_chart_line line3 = {.width = 1.25,
.dash_type = LXW_CHART_LINE_DASH_DASH};
lxw_chart_line line4 = {.color = 0x00B050};
chart_axis_major_gridlines_set_line(chart->x_axis, &line1);
chart_axis_minor_gridlines_set_line(chart->x_axis, &line2);
chart_axis_major_gridlines_set_line(chart->y_axis, &line3);
chart_axis_minor_gridlines_set_line(chart->y_axis, &line4);
worksheet_insert_chart(worksheet, CELL("E9"), chart);
return workbook_close(workbook);
}

View file

@ -0,0 +1,39 @@
###############################################################################
#
# Tests for libxlsxwriter.
#
# Copyright 2014-2017, John McNamara, jmcnamara@cpan.org
#
import base_test_class
class TestCompareXLSXFiles(base_test_class.XLSXBaseTest):
"""
Test file created with libxlsxwriter against a file created by Excel.
"""
def test_chart_gridlines01(self):
self.run_exe_test('test_chart_gridlines01')
def test_chart_gridlines02(self):
self.run_exe_test('test_chart_gridlines02')
# test_chart_gridlines03 is a stock chart.
def test_chart_gridlines04(self):
self.run_exe_test('test_chart_gridlines04')
def test_chart_gridlines05(self):
self.run_exe_test('test_chart_gridlines05')
def test_chart_gridlines06(self):
self.run_exe_test('test_chart_gridlines06')
# test_chart_gridlines07 is a stock chart.
def test_chart_gridlines08(self):
self.run_exe_test('test_chart_gridlines08')
def test_chart_gridlines09(self):
self.run_exe_test('test_chart_gridlines09')

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.