/*****************************************************************************
* table - A library for creating Excel XLSX table files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/worksheet.h"
#include "xlsxwriter/table.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new table object.
*/
lxw_table *
lxw_table_new(void)
{
lxw_table *table = calloc(1, sizeof(lxw_table));
GOTO_LABEL_ON_MEM_ERROR(table, mem_error);
return table;
mem_error:
lxw_table_free(table);
return NULL;
}
/*
* Free a table object.
*/
void
lxw_table_free(lxw_table *table)
{
if (!table)
return;
free(table);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_table_xml_declaration(lxw_table *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the
element.
*/
STATIC void
_table_write_table(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] =
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
lxw_table_obj *table_obj = self->table_obj;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_INT("id", table_obj->id);
if (table_obj->name)
LXW_PUSH_ATTRIBUTES_STR("name", table_obj->name);
else
LXW_PUSH_ATTRIBUTES_STR("name", "Table1");
if (table_obj->name)
LXW_PUSH_ATTRIBUTES_STR("displayName", table_obj->name);
else
LXW_PUSH_ATTRIBUTES_STR("displayName", "Table1");
LXW_PUSH_ATTRIBUTES_STR("ref", table_obj->sqref);
if (table_obj->no_header_row)
LXW_PUSH_ATTRIBUTES_STR("headerRowCount", "0");
if (table_obj->total_row)
LXW_PUSH_ATTRIBUTES_STR("totalsRowCount", "1");
else
LXW_PUSH_ATTRIBUTES_STR("totalsRowShown", "0");
lxw_xml_start_tag(self->file, "table", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the element.
*/
STATIC void
_table_write_auto_filter(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
if (self->table_obj->no_autofilter)
return;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("ref", self->table_obj->filter_sqref);
lxw_xml_empty_tag(self->file, "autoFilter", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the element.
*/
STATIC void
_table_write_table_column(lxw_table *self, uint16_t id,
lxw_table_column *column)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
int32_t dfx_id;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("id", id);
LXW_PUSH_ATTRIBUTES_STR("name", column->header);
if (column->total_string) {
LXW_PUSH_ATTRIBUTES_STR("totalsRowLabel", column->total_string);
}
else if (column->total_function) {
if (column->total_function == LXW_TABLE_FUNCTION_AVERAGE)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "average");
if (column->total_function == LXW_TABLE_FUNCTION_COUNT_NUMS)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "countNums");
if (column->total_function == LXW_TABLE_FUNCTION_COUNT)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "count");
if (column->total_function == LXW_TABLE_FUNCTION_MAX)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "max");
if (column->total_function == LXW_TABLE_FUNCTION_MIN)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "min");
if (column->total_function == LXW_TABLE_FUNCTION_STD_DEV)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "stdDev");
if (column->total_function == LXW_TABLE_FUNCTION_SUM)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "sum");
if (column->total_function == LXW_TABLE_FUNCTION_VAR)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "var");
}
if (column->format) {
dfx_id = lxw_format_get_dxf_index(column->format);
LXW_PUSH_ATTRIBUTES_INT("dataDxfId", dfx_id);
}
if (column->formula) {
lxw_xml_start_tag(self->file, "tableColumn", &attributes);
lxw_xml_data_element(self->file, "calculatedColumnFormula",
column->formula, NULL);
lxw_xml_end_tag(self->file, "tableColumn");
}
else {
lxw_xml_empty_tag(self->file, "tableColumn", &attributes);
}
LXW_FREE_ATTRIBUTES();
}
/*
* Write the element.
*/
STATIC void
_table_write_table_columns(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
uint16_t i;
uint16_t num_cols = self->table_obj->num_cols;
lxw_table_column **columns = self->table_obj->columns;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("count", num_cols);
lxw_xml_start_tag(self->file, "tableColumns", &attributes);
for (i = 0; i < num_cols; i++)
_table_write_table_column(self, i + 1, columns[i]);
lxw_xml_end_tag(self->file, "tableColumns");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the element.
*/
STATIC void
_table_write_table_style_info(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char name[LXW_ATTR_32];
lxw_table_obj *table_obj = self->table_obj;
LXW_INIT_ATTRIBUTES();
if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_LIGHT) {
if (table_obj->style_type_number != 0) {
lxw_snprintf(name, LXW_ATTR_32, "TableStyleLight%d",
table_obj->style_type_number);
LXW_PUSH_ATTRIBUTES_STR("name", name);
}
}
else if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_MEDIUM) {
lxw_snprintf(name, LXW_ATTR_32, "TableStyleMedium%d",
table_obj->style_type_number);
LXW_PUSH_ATTRIBUTES_STR("name", name);
}
else if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_DARK) {
lxw_snprintf(name, LXW_ATTR_32, "TableStyleDark%d",
table_obj->style_type_number);
LXW_PUSH_ATTRIBUTES_STR("name", name);
}
else {
LXW_PUSH_ATTRIBUTES_STR("name", "TableStyleMedium9");
}
if (table_obj->first_column)
LXW_PUSH_ATTRIBUTES_STR("showFirstColumn", "1");
else
LXW_PUSH_ATTRIBUTES_STR("showFirstColumn", "0");
if (table_obj->last_column)
LXW_PUSH_ATTRIBUTES_STR("showLastColumn", "1");
else
LXW_PUSH_ATTRIBUTES_STR("showLastColumn", "0");
if (table_obj->no_banded_rows)
LXW_PUSH_ATTRIBUTES_STR("showRowStripes", "0");
else
LXW_PUSH_ATTRIBUTES_STR("showRowStripes", "1");
if (table_obj->banded_columns)
LXW_PUSH_ATTRIBUTES_STR("showColumnStripes", "1");
else
LXW_PUSH_ATTRIBUTES_STR("showColumnStripes", "0");
lxw_xml_empty_tag(self->file, "tableStyleInfo", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_table_assemble_xml_file(lxw_table *self)
{
/* Write the XML declaration. */
_table_xml_declaration(self);
/* Write the table element. */
_table_write_table(self);
/* Write the autoFilter element. */
_table_write_auto_filter(self);
/* Write the tableColumns element. */
_table_write_table_columns(self);
/* Write the tableStyleInfo element. */
_table_write_table_style_info(self);
lxw_xml_end_tag(self->file, "table");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/