Added support for object positioning.

Added support for setting the image or chart object_position
property to specify if they should be moved or sized with cell.

Issue #263
This commit is contained in:
John McNamara 2020-01-14 21:03:01 +00:00
parent 3b7cf20de1
commit 139cd8cc41
47 changed files with 699 additions and 71 deletions

View File

@ -23,19 +23,6 @@ enum lxw_drawing_types {
LXW_DRAWING_SHAPE LXW_DRAWING_SHAPE
}; };
enum lxw_anchor_types {
LXW_ANCHOR_TYPE_NONE = 0,
LXW_ANCHOR_TYPE_IMAGE,
LXW_ANCHOR_TYPE_CHART
};
enum lxw_anchor_edit_types {
LXW_ANCHOR_EDIT_AS_NONE = 0,
LXW_ANCHOR_EDIT_AS_RELATIVE,
LXW_ANCHOR_EDIT_AS_ONE_CELL,
LXW_ANCHOR_EDIT_AS_ABSOLUTE
};
enum image_types { enum image_types {
LXW_IMAGE_UNKNOWN = 0, LXW_IMAGE_UNKNOWN = 0,
LXW_IMAGE_PNG, LXW_IMAGE_PNG,
@ -53,8 +40,8 @@ typedef struct lxw_drawing_coords {
/* Object to represent the properties of a drawing. */ /* Object to represent the properties of a drawing. */
typedef struct lxw_drawing_object { typedef struct lxw_drawing_object {
uint8_t anchor_type; uint8_t type;
uint8_t edit_as; uint8_t anchor;
struct lxw_drawing_coords from; struct lxw_drawing_coords from;
struct lxw_drawing_coords to; struct lxw_drawing_coords to;
uint32_t col_absolute; uint32_t col_absolute;

View File

@ -218,6 +218,27 @@ enum lxw_comment_display_types {
LXW_COMMENT_DISPLAY_VISIBLE LXW_COMMENT_DISPLAY_VISIBLE
}; };
/** Options to control the positioning of worksheet objects such as images
* or charts. */
enum lxw_object_position {
/** Default positioning for the object. */
LXW_OBJECT_POSITION_DEFAULT,
/** Move and size with the worksheet object with the cells. */
LXW_OBJECT_MOVE_AND_SIZE,
/** Move but don't size with the worksheet object with the cells. */
LXW_OBJECT_MOVE_DONT_SIZE,
/** Don't move or size the worksheet object with the cells. */
LXW_OBJECT_DONT_MOVE_DONT_SIZE,
/** Same as LXW_OBJECT_MOVE_AND_SIZE except libxlsxwriter applies hidden
* cells after the object is inserted. */
LXW_OBJECT_MOVE_AND_SIZE_AFTER
};
enum cell_types { enum cell_types {
NUMBER_CELL = 1, NUMBER_CELL = 1,
STRING_CELL, STRING_CELL,
@ -602,7 +623,7 @@ typedef struct lxw_image_options {
/** Y scale of the image as a decimal. */ /** Y scale of the image as a decimal. */
double y_scale; double y_scale;
/** Object position - not implemented yet. Set to 0.*/ /** Object position - use one of the values of #lxw_object_position. */
uint8_t object_position; uint8_t object_position;
/** Optional description of the image. Defaults to the image filename /** Optional description of the image. Defaults to the image filename
@ -638,7 +659,7 @@ typedef struct lxw_chart_options {
/** Y scale of the chart as a decimal. */ /** Y scale of the chart as a decimal. */
double y_scale; double y_scale;
/** Object position - not implemented yet. Set to 0. */ /** Object position - use one of the values of #lxw_object_position. */
uint8_t object_position; uint8_t object_position;
} lxw_chart_options; } lxw_chart_options;

View File

@ -10,6 +10,7 @@
#include "xlsxwriter/xmlwriter.h" #include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/common.h" #include "xlsxwriter/common.h"
#include "xlsxwriter/drawing.h" #include "xlsxwriter/drawing.h"
#include "xlsxwriter/worksheet.h"
#include "xlsxwriter/utility.h" #include "xlsxwriter/utility.h"
#define LXW_OBJ_NAME_LENGTH 14 /* "Picture 65536", or "Chart 65536" */ #define LXW_OBJ_NAME_LENGTH 14 /* "Picture 65536", or "Chart 65536" */
@ -737,24 +738,21 @@ _drawing_write_two_cell_anchor(lxw_drawing *self, uint32_t index,
LXW_INIT_ATTRIBUTES(); LXW_INIT_ATTRIBUTES();
if (drawing_object->anchor_type == LXW_ANCHOR_TYPE_IMAGE) { if (drawing_object->anchor == LXW_OBJECT_MOVE_DONT_SIZE)
LXW_PUSH_ATTRIBUTES_STR("editAs", "oneCell");
if (drawing_object->edit_as == LXW_ANCHOR_EDIT_AS_ABSOLUTE) else if (drawing_object->anchor == LXW_OBJECT_DONT_MOVE_DONT_SIZE)
LXW_PUSH_ATTRIBUTES_STR("editAs", "absolute"); LXW_PUSH_ATTRIBUTES_STR("editAs", "absolute");
else if (drawing_object->edit_as != LXW_ANCHOR_EDIT_AS_RELATIVE)
LXW_PUSH_ATTRIBUTES_STR("editAs", "oneCell");
}
lxw_xml_start_tag(self->file, "xdr:twoCellAnchor", &attributes); lxw_xml_start_tag(self->file, "xdr:twoCellAnchor", &attributes);
_drawing_write_from(self, &drawing_object->from); _drawing_write_from(self, &drawing_object->from);
_drawing_write_to(self, &drawing_object->to); _drawing_write_to(self, &drawing_object->to);
if (drawing_object->anchor_type == LXW_ANCHOR_TYPE_CHART) { if (drawing_object->type == LXW_DRAWING_CHART) {
/* Write the xdr:graphicFrame element for charts. */ /* Write the xdr:graphicFrame element for charts. */
_drawing_write_graphic_frame(self, index, drawing_object->rel_index); _drawing_write_graphic_frame(self, index, drawing_object->rel_index);
} }
else if (drawing_object->anchor_type == LXW_ANCHOR_TYPE_IMAGE) { else if (drawing_object->type == LXW_DRAWING_IMAGE) {
/* Write the xdr:pic element. */ /* Write the xdr:pic element. */
_drawing_write_pic(self, index, drawing_object); _drawing_write_pic(self, index, drawing_object);
} }

View File

@ -1934,7 +1934,7 @@ _write_row(lxw_worksheet *self, lxw_row *row, char *spans)
* we use the default value. If the column is hidden it has a value of zero. * we use the default value. If the column is hidden it has a value of zero.
*/ */
STATIC int32_t STATIC int32_t
_worksheet_size_col(lxw_worksheet *self, lxw_col_t col_num) _worksheet_size_col(lxw_worksheet *self, lxw_col_t col_num, uint8_t anchor)
{ {
lxw_col_options *col_opt = NULL; lxw_col_options *col_opt = NULL;
uint32_t pixels; uint32_t pixels;
@ -1958,13 +1958,10 @@ _worksheet_size_col(lxw_worksheet *self, lxw_col_t col_num)
} }
if (col_opt) { if (col_opt) {
if (col_opt->hidden)
return 0;
width = col_opt->width; width = col_opt->width;
/* Convert to pixels. */ /* Convert to pixels. */
if (width == 0) { if (col_opt->hidden && anchor != LXW_OBJECT_MOVE_AND_SIZE_AFTER) {
pixels = 0; pixels = 0;
} }
else if (width < 1.0) { else if (width < 1.0) {
@ -1987,24 +1984,18 @@ _worksheet_size_col(lxw_worksheet *self, lxw_col_t col_num)
* it has a value of zero. * it has a value of zero.
*/ */
STATIC int32_t STATIC int32_t
_worksheet_size_row(lxw_worksheet *self, lxw_row_t row_num) _worksheet_size_row(lxw_worksheet *self, lxw_row_t row_num, uint8_t anchor)
{ {
lxw_row *row; lxw_row *row;
uint32_t pixels; uint32_t pixels;
double height;
row = lxw_worksheet_find_row(self, row_num); row = lxw_worksheet_find_row(self, row_num);
if (row) { if (row) {
if (row->hidden) if (row->hidden && anchor != LXW_OBJECT_MOVE_AND_SIZE_AFTER)
return 0;
height = row->height;
if (height == 0)
pixels = 0; pixels = 0;
else else
pixels = (uint32_t) (4.0 / 3.0 * height); pixels = (uint32_t) (4.0 / 3.0 * row->height);
} }
else { else {
pixels = (uint32_t) (4.0 / 3.0 * self->default_row_height); pixels = (uint32_t) (4.0 / 3.0 * self->default_row_height);
@ -2072,6 +2063,8 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
uint32_t y_abs = 0; /* Abs. distance to top side of object. */ uint32_t y_abs = 0; /* Abs. distance to top side of object. */
uint32_t i; uint32_t i;
uint8_t anchor = drawing_object->anchor;
uint8_t ignore_anchor = LXW_OBJECT_POSITION_DEFAULT;
col_start = object_props->col; col_start = object_props->col;
row_start = object_props->row; row_start = object_props->row;
@ -2082,13 +2075,13 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
/* Adjust start column for negative offsets. */ /* Adjust start column for negative offsets. */
while (x1 < 0 && col_start > 0) { while (x1 < 0 && col_start > 0) {
x1 += _worksheet_size_col(self, col_start - 1); x1 += _worksheet_size_col(self, col_start - 1, ignore_anchor);
col_start--; col_start--;
} }
/* Adjust start row for negative offsets. */ /* Adjust start row for negative offsets. */
while (y1 < 0 && row_start > 0) { while (y1 < 0 && row_start > 0) {
y1 += _worksheet_size_row(self, row_start - 1); y1 += _worksheet_size_row(self, row_start - 1, ignore_anchor);
row_start--; row_start--;
} }
@ -2102,7 +2095,7 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
/* Calculate the absolute x offset of the top-left vertex. */ /* Calculate the absolute x offset of the top-left vertex. */
if (self->col_size_changed) { if (self->col_size_changed) {
for (i = 0; i < col_start; i++) for (i = 0; i < col_start; i++)
x_abs += _worksheet_size_col(self, i); x_abs += _worksheet_size_col(self, i, ignore_anchor);
} }
else { else {
/* Optimization for when the column widths haven't changed. */ /* Optimization for when the column widths haven't changed. */
@ -2115,7 +2108,7 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
/* Store the column change to allow optimizations. */ /* Store the column change to allow optimizations. */
if (self->row_size_changed) { if (self->row_size_changed) {
for (i = 0; i < row_start; i++) for (i = 0; i < row_start; i++)
y_abs += _worksheet_size_row(self, i); y_abs += _worksheet_size_row(self, i, ignore_anchor);
} }
else { else {
/* Optimization for when the row heights haven"t changed. */ /* Optimization for when the row heights haven"t changed. */
@ -2125,40 +2118,36 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
y_abs += y1; y_abs += y1;
/* Adjust start col for offsets that are greater than the col width. */ /* Adjust start col for offsets that are greater than the col width. */
if (_worksheet_size_col(self, col_start) > 0) { while (x1 >= _worksheet_size_col(self, col_start, anchor)) {
while (x1 >= _worksheet_size_col(self, col_start)) { x1 -= _worksheet_size_col(self, col_start, ignore_anchor);
x1 -= _worksheet_size_col(self, col_start); col_start++;
col_start++;
}
} }
/* Adjust start row for offsets that are greater than the row height. */ /* Adjust start row for offsets that are greater than the row height. */
if (_worksheet_size_row(self, row_start) > 0) { while (y1 >= _worksheet_size_row(self, row_start, anchor)) {
while (y1 >= _worksheet_size_row(self, row_start)) { y1 -= _worksheet_size_row(self, row_start, ignore_anchor);
y1 -= _worksheet_size_row(self, row_start); row_start++;
row_start++;
}
} }
/* Initialize end cell to the same as the start cell. */ /* Initialize end cell to the same as the start cell. */
col_end = col_start; col_end = col_start;
row_end = row_start; row_end = row_start;
/* Only offset the image in the cell if the row/col isn't hidden. */ /* Only offset the image in the cell if the row/col is hidden. */
if (_worksheet_size_col(self, col_start) > 0) if (_worksheet_size_col(self, col_start, anchor) > 0)
width = width + x1; width = width + x1;
if (_worksheet_size_row(self, row_start) > 0) if (_worksheet_size_row(self, row_start, anchor) > 0)
height = height + y1; height = height + y1;
/* Subtract the underlying cell widths to find the end cell. */ /* Subtract the underlying cell widths to find the end cell. */
while (width >= _worksheet_size_col(self, col_end)) { while (width >= _worksheet_size_col(self, col_end, anchor)) {
width -= _worksheet_size_col(self, col_end); width -= _worksheet_size_col(self, col_end, anchor);
col_end++; col_end++;
} }
/* Subtract the underlying cell heights to find the end cell. */ /* Subtract the underlying cell heights to find the end cell. */
while (height >= _worksheet_size_row(self, row_end)) { while (height >= _worksheet_size_row(self, row_end, anchor)) {
height -= _worksheet_size_row(self, row_end); height -= _worksheet_size_row(self, row_end, anchor);
row_end++; row_end++;
} }
@ -2393,8 +2382,11 @@ lxw_worksheet_prepare_image(lxw_worksheet *self,
drawing_object = calloc(1, sizeof(lxw_drawing_object)); drawing_object = calloc(1, sizeof(lxw_drawing_object));
RETURN_VOID_ON_MEM_ERROR(drawing_object); RETURN_VOID_ON_MEM_ERROR(drawing_object);
drawing_object->anchor_type = LXW_ANCHOR_TYPE_IMAGE; drawing_object->anchor = LXW_OBJECT_MOVE_DONT_SIZE;
drawing_object->edit_as = LXW_ANCHOR_EDIT_AS_ONE_CELL; if (object_props->object_position)
drawing_object->anchor = object_props->object_position;
drawing_object->type = LXW_DRAWING_IMAGE;
drawing_object->description = lxw_strdup(object_props->description); drawing_object->description = lxw_strdup(object_props->description);
drawing_object->tip = lxw_strdup(object_props->tip); drawing_object->tip = lxw_strdup(object_props->tip);
drawing_object->rel_index = 0; drawing_object->rel_index = 0;
@ -2563,8 +2555,11 @@ lxw_worksheet_prepare_chart(lxw_worksheet *self,
drawing_object = calloc(1, sizeof(lxw_drawing_object)); drawing_object = calloc(1, sizeof(lxw_drawing_object));
RETURN_VOID_ON_MEM_ERROR(drawing_object); RETURN_VOID_ON_MEM_ERROR(drawing_object);
drawing_object->anchor_type = LXW_ANCHOR_TYPE_CHART; drawing_object->anchor = LXW_OBJECT_MOVE_AND_SIZE;
drawing_object->edit_as = LXW_ANCHOR_EDIT_AS_ONE_CELL; if (object_props->object_position)
drawing_object->anchor = object_props->object_position;
drawing_object->type = LXW_DRAWING_CHART;
drawing_object->description = lxw_strdup("TODO_DESC"); drawing_object->description = lxw_strdup("TODO_DESC");
drawing_object->tip = NULL; drawing_object->tip = NULL;
drawing_object->rel_index = _get_drawing_rel_index(self, NULL); drawing_object->rel_index = _get_drawing_rel_index(self, NULL);
@ -6242,6 +6237,7 @@ worksheet_insert_image_opt(lxw_worksheet *self,
object_props->y_offset = user_options->y_offset; object_props->y_offset = user_options->y_offset;
object_props->x_scale = user_options->x_scale; object_props->x_scale = user_options->x_scale;
object_props->y_scale = user_options->y_scale; object_props->y_scale = user_options->y_scale;
object_props->object_position = user_options->object_position;
object_props->url = lxw_strdup(user_options->url); object_props->url = lxw_strdup(user_options->url);
object_props->tip = lxw_strdup(user_options->tip); object_props->tip = lxw_strdup(user_options->tip);
@ -6340,6 +6336,7 @@ worksheet_insert_image_buffer_opt(lxw_worksheet *self,
object_props->y_offset = user_options->y_offset; object_props->y_offset = user_options->y_offset;
object_props->x_scale = user_options->x_scale; object_props->x_scale = user_options->x_scale;
object_props->y_scale = user_options->y_scale; object_props->y_scale = user_options->y_scale;
object_props->object_position = user_options->object_position;
object_props->description = lxw_strdup(user_options->description); object_props->description = lxw_strdup(user_options->description);
} }
@ -6429,6 +6426,7 @@ worksheet_insert_chart_opt(lxw_worksheet *self,
object_props->y_offset = user_options->y_offset; object_props->y_offset = user_options->y_offset;
object_props->x_scale = user_options->x_scale; object_props->x_scale = user_options->x_scale;
object_props->y_scale = user_options->y_scale; object_props->y_scale = user_options->y_scale;
object_props->object_position = user_options->object_position;
} }
/* Copy other options or set defaults. */ /* Copy other options or set defaults. */

View File

@ -14,10 +14,11 @@ int main() {
lxw_workbook *workbook = workbook_new("test_image45.xlsx"); lxw_workbook *workbook = workbook_new("test_image45.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
worksheet_insert_image(worksheet, CELL("E9"), "images/red.png"); lxw_image_options image_options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &image_options);
lxw_row_col_options options = {.hidden = LXW_TRUE}; lxw_row_col_options row_options = {.hidden = LXW_TRUE};
worksheet_set_row_opt(worksheet, 8, 30, NULL, &options); worksheet_set_row_opt(worksheet, 8, 30, NULL, &row_options);
return workbook_close(workbook); return workbook_close(workbook);
} }

View File

@ -14,7 +14,7 @@ int main() {
lxw_workbook *workbook = workbook_new("test_image46.xlsx"); lxw_workbook *workbook = workbook_new("test_image46.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL); lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options image_options = {.x_offset = 0, .y_offset = 4}; lxw_image_options image_options = {.y_offset = 4, .object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &image_options); worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &image_options);
lxw_row_col_options row_options = {.hidden = LXW_TRUE}; lxw_row_col_options row_options = {.hidden = LXW_TRUE};

View File

@ -0,0 +1,21 @@
/*****************************************************************************
* 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_object_position01.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,21 @@
/*****************************************************************************
* 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_object_position02.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.object_position = LXW_OBJECT_MOVE_DONT_SIZE};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,21 @@
/*****************************************************************************
* 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_object_position03.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.object_position = LXW_OBJECT_DONT_MOVE_DONT_SIZE};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,43 @@
/*****************************************************************************
* 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_object_position04.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 = 59106432;
chart->axis_id_2 = 60702720;
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_options options = {.object_position = LXW_OBJECT_MOVE_DONT_SIZE};
worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position06.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
lxw_row_col_options hidden = {.hidden = LXW_TRUE};
worksheet_set_row_opt(worksheet, 8, LXW_DEF_ROW_HEIGHT, NULL, &hidden);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position07.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
lxw_row_col_options hidden = {.hidden = LXW_TRUE};
worksheet_set_row_opt(worksheet, 8, 30, NULL, &hidden);
return workbook_close(workbook);
}

View File

@ -0,0 +1,58 @@
/*****************************************************************************
* 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_object_position08.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
lxw_format *bold = workbook_add_format(workbook);
format_set_bold(bold);
lxw_format *italic = workbook_add_format(workbook);
format_set_italic(italic);
/* For testing, copy the randomly generated axis ids in the target file. */
chart->axis_id_1 = 60888960;
chart->axis_id_2 = 79670656;
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 + 1, col, data[row][col], NULL);
worksheet_write_string(worksheet, CELL("A1"), "Foo", bold);
worksheet_write_string(worksheet, CELL("B1"), "Bar", italic);
lxw_row_col_options row_hidden = {.hidden = LXW_TRUE};
worksheet_set_row_opt(worksheet, 12, LXW_DEF_ROW_HEIGHT, NULL, &row_hidden);
lxw_row_col_options col_hidden = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("F:F"), LXW_DEF_COL_WIDTH, NULL, &col_hidden);
chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6");
chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6");
chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6");
lxw_chart_options chart_options = {.object_position = LXW_OBJECT_MOVE_DONT_SIZE};
worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &chart_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,58 @@
/*****************************************************************************
* 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_object_position09.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
lxw_format *bold = workbook_add_format(workbook);
format_set_bold(bold);
lxw_format *italic = workbook_add_format(workbook);
format_set_italic(italic);
/* For testing, copy the randomly generated axis ids in the target file. */
chart->axis_id_1 = 60910208;
chart->axis_id_2 = 69231360;
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 + 1, col, data[row][col], NULL);
worksheet_write_string(worksheet, CELL("A1"), "Foo", bold);
worksheet_write_string(worksheet, CELL("B1"), "Bar", italic);
lxw_row_col_options row_hidden = {.hidden = LXW_TRUE};
worksheet_set_row_opt(worksheet, 12, LXW_DEF_ROW_HEIGHT, NULL, &row_hidden);
lxw_row_col_options col_hidden = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("F:F"), 9, NULL, &col_hidden);
chart_add_series(chart, NULL, "=Sheet1!$A$2:$A$6");
chart_add_series(chart, NULL, "=Sheet1!$B$2:$B$6");
chart_add_series(chart, NULL, "=Sheet1!$C$2:$C$6");
lxw_chart_options chart_options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_chart_opt(worksheet, CELL("E9"), chart, &chart_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position10.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.object_position = LXW_OBJECT_MOVE_AND_SIZE_AFTER};
worksheet_insert_image_opt(worksheet, CELL("E9"), "images/red.png", &options);
lxw_row_col_options col_hidden = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("E:E"), LXW_DEF_COL_WIDTH, NULL, &col_hidden);
return workbook_close(workbook);
}

View File

@ -0,0 +1,22 @@
/*****************************************************************************
* 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_object_position12.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
worksheet_set_column_opt(worksheet, COLS("B:B"), 5, NULL, NULL);
worksheet_insert_image(worksheet, CELL("E9"), "images/red.png");
return workbook_close(workbook);
}

View File

@ -0,0 +1,23 @@
/*****************************************************************************
* 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_object_position13.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_row_col_options col_options = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("B:B"), LXW_DEF_COL_WIDTH, NULL, &col_options);
worksheet_insert_image(worksheet, CELL("E9"), "images/red.png");
return workbook_close(workbook);
}

View File

@ -0,0 +1,23 @@
/*****************************************************************************
* 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_object_position14.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_row_col_options col_options = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("B:B"), 5, NULL, &col_options);
worksheet_insert_image(worksheet, CELL("E9"), "images/red.png");
return workbook_close(workbook);
}

View File

@ -0,0 +1,23 @@
/*****************************************************************************
* 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_object_position15.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
worksheet_set_column_opt(worksheet, COLS("B:B"), 5, NULL, NULL);
lxw_image_options image_options = {.x_offset = 232};
worksheet_insert_image_opt(worksheet, CELL("A9"), "images/red.png", &image_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position16.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_row_col_options col_options = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("B:B"), LXW_DEF_COL_WIDTH, NULL, &col_options);
lxw_image_options image_options = {.x_offset = 192};
worksheet_insert_image_opt(worksheet, CELL("A9"), "images/red.png", &image_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position17.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_row_col_options col_options = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("B:B"), 5, NULL, &col_options);
lxw_image_options image_options = {.x_offset = 192};
worksheet_insert_image_opt(worksheet, CELL("A9"), "images/red.png", &image_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,23 @@
/*****************************************************************************
* 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_object_position18.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
worksheet_set_column_opt(worksheet, COLS("B:B"), 5, NULL, NULL);
lxw_image_options image_options = {.x_offset = 168};
worksheet_insert_image_opt(worksheet, CELL("B9"), "images/red.png", &image_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position19.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_row_col_options col_options = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("B:B"), LXW_DEF_COL_WIDTH, NULL, &col_options);
lxw_image_options image_options = {.x_offset = 128};
worksheet_insert_image_opt(worksheet, CELL("B9"), "images/red.png", &image_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,24 @@
/*****************************************************************************
* 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_object_position20.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_row_col_options col_options = {.hidden = LXW_TRUE};
worksheet_set_column_opt(worksheet, COLS("B:B"), 5, NULL, &col_options);
lxw_image_options image_options = {.x_offset = 128};
worksheet_insert_image_opt(worksheet, CELL("B9"), "images/red.png", &image_options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,44 @@
/*****************************************************************************
* Test cases for libxlsxwriter.
*
* Test to compare output against Excel files.
*
* Copyright 2014-2020, John McNamara, jmcnamara@cpan.org
*
*/
#include "xlsxwriter.h"
unsigned char image_buffer[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
0x08, 0x02, 0x00, 0x00, 0x00, 0xfc, 0x18, 0xed, 0xa3, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc,
0x61, 0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00,
0x7a, 0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00,
0x80, 0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00,
0x3a, 0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00,
0x00, 0x46, 0x49, 0x44, 0x41, 0x54, 0x48, 0x4b, 0x63, 0xfc, 0xcf, 0x40,
0x63, 0x00, 0xb4, 0x80, 0xa6, 0x88, 0xb6, 0xa6, 0x83, 0x82, 0x87, 0xa6,
0xce, 0x1f, 0xb5, 0x80, 0x98, 0xe0, 0x1d, 0x8d, 0x03, 0x82, 0xa1, 0x34,
0x1a, 0x44, 0xa3, 0x41, 0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45,
0xa3, 0x41, 0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45, 0xa3, 0x41,
0x44, 0x30, 0x04, 0x08, 0x2a, 0x18, 0x4d, 0x45, 0x03, 0x1f, 0x44, 0x00,
0xaa, 0x35, 0xdd, 0x4e, 0xe6, 0xd5, 0xa1, 0x22, 0x00, 0x00, 0x00, 0x00,
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int image_size = 200;
int main() {
lxw_workbook *workbook = workbook_new("test_object_position51.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.description = "red.png", .object_position = LXW_OBJECT_MOVE_AND_SIZE};
worksheet_insert_image_buffer_opt(worksheet, CELL("E9"), image_buffer, image_size, &options);
return workbook_close(workbook);
}

View File

@ -0,0 +1,74 @@
###############################################################################
#
# Tests for libxlsxwriter.
#
# Copyright 2014-2020, 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_object_position01(self):
self.run_exe_test('test_object_position01')
def test_object_position02(self):
self.run_exe_test('test_object_position02')
def test_object_position03(self):
self.run_exe_test('test_object_position03')
def test_object_position04(self):
self.run_exe_test('test_object_position04')
def test_object_position06(self):
self.run_exe_test('test_object_position06')
def test_object_position07(self):
self.run_exe_test('test_object_position07')
def test_object_position08(self):
self.ignore_files = ['xl/worksheets/sheet1.xml']
self.run_exe_test('test_object_position08')
def test_object_position09(self):
self.ignore_files = ['xl/worksheets/sheet1.xml']
self.run_exe_test('test_object_position09')
def test_object_position10(self):
self.run_exe_test('test_object_position10')
def test_object_position12(self):
self.run_exe_test('test_object_position12')
def test_object_position13(self):
self.run_exe_test('test_object_position13')
def test_object_position14(self):
self.run_exe_test('test_object_position14')
def test_object_position15(self):
self.run_exe_test('test_object_position15')
def test_object_position16(self):
self.run_exe_test('test_object_position16')
def test_object_position17(self):
self.run_exe_test('test_object_position17')
def test_object_position18(self):
self.run_exe_test('test_object_position18')
def test_object_position19(self):
self.run_exe_test('test_object_position19')
def test_object_position20(self):
self.run_exe_test('test_object_position20')
# Test in-memory image handling.
def test_object_position51(self):
self.run_exe_test('test_object_position51', 'object_position01.xlsx')

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.

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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -10,6 +10,7 @@
#include "../helper.h" #include "../helper.h"
#include "xlsxwriter/drawing.h" #include "xlsxwriter/drawing.h"
#include "xlsxwriter/worksheet.h"
// Test assembling a complete Drawing file. // Test assembling a complete Drawing file.
CTEST(drawing, drawing_image01) { CTEST(drawing, drawing_image01) {
@ -67,8 +68,8 @@ CTEST(drawing, drawing_image01) {
lxw_drawing_object *drawing_object = calloc(1, sizeof(lxw_drawing_object)); lxw_drawing_object *drawing_object = calloc(1, sizeof(lxw_drawing_object));
drawing_object->anchor_type = LXW_ANCHOR_TYPE_IMAGE; drawing_object->type = LXW_DRAWING_IMAGE;
drawing_object->edit_as = LXW_ANCHOR_EDIT_AS_ONE_CELL; drawing_object->anchor = LXW_OBJECT_MOVE_DONT_SIZE;
drawing_object->from.col = 2; drawing_object->from.col = 2;
drawing_object->from.col_offset = 0; drawing_object->from.col_offset = 0;