diff --git a/dev/release/fix_example_docs.pl b/dev/release/fix_example_docs.pl
index eeb19183..d0e4f0a0 100644
--- a/dev/release/fix_example_docs.pl
+++ b/dev/release/fix_example_docs.pl
@@ -24,6 +24,7 @@ my @examples = (
[ 'dates_and_times03.c', 'Dates and times with different formats' ],
[ 'utf8.c', 'A example of some UTF-8 text' ],
[ 'constant_memory.c', 'Write a large file with constant memory usage' ],
+ [ 'defined_name.c', 'Example of how to create defined names' ],
);
# Convert the array refs to a hash for lookups.
diff --git a/docs/images/defined_name.png b/docs/images/defined_name.png
new file mode 100644
index 00000000..793507e2
Binary files /dev/null and b/docs/images/defined_name.png differ
diff --git a/docs/src/examples.dox b/docs/src/examples.dox
index 4d64cc7e..0db5d6b1 100644
--- a/docs/src/examples.dox
+++ b/docs/src/examples.dox
@@ -92,11 +92,22 @@ A simple Unicode UTF-8 example. Note, the source file is UTF-8 encoded.
Next example: @ref constant_memory.c
@image html utf8.png
+
@example constant_memory.c
Example of using libxlsxwriter for writing large files in constant memory
mode.
+Next example: @ref defined_name.c
@image html constant_memory.png
+@example defined_name.c
+Example of how to create defined names (named ranges) using libxlsxwriter.
+
+Defined names are used to define descriptive names to represent a value, a
+single cell or a range of cells in a workbook or worksheet.
+
+@image html defined_name.png
+
+
*/
diff --git a/examples/anatomy.c b/examples/anatomy.c
index e798ec84..d364be7e 100644
--- a/examples/anatomy.c
+++ b/examples/anatomy.c
@@ -1,7 +1,7 @@
/*
* Anatomy of a simple libxlsxwriter program.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/constant_memory.c b/examples/constant_memory.c
index 33ea2ec9..69a39040 100644
--- a/examples/constant_memory.c
+++ b/examples/constant_memory.c
@@ -2,7 +2,7 @@
* Example of using libxlsxwriter for writing large files in constant memory
* mode.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/dates_and_times01.c b/examples/dates_and_times01.c
index 70b124e1..5caf8370 100644
--- a/examples/dates_and_times01.c
+++ b/examples/dates_and_times01.c
@@ -6,7 +6,7 @@
* An easier approach using a lxw_datetime struct is shown in example
* dates_and_times02.c.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/dates_and_times02.c b/examples/dates_and_times02.c
index 2a63c260..c6708547 100644
--- a/examples/dates_and_times02.c
+++ b/examples/dates_and_times02.c
@@ -2,7 +2,7 @@
* Example of writing dates and times in Excel using an lxw_datetime struct
* and date formatting.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/dates_and_times03.c b/examples/dates_and_times03.c
index 1ef36384..8c9e0f10 100644
--- a/examples/dates_and_times03.c
+++ b/examples/dates_and_times03.c
@@ -1,7 +1,7 @@
/*
* Example of writing dates and times in Excel using different date formats.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/defined_name.c b/examples/defined_name.c
new file mode 100644
index 00000000..dbd62403
--- /dev/null
+++ b/examples/defined_name.c
@@ -0,0 +1,57 @@
+/*
+ * Example of how to create defined names using libxlsxwriter. This method is
+ * used to define a user friendly name to represent a value, a single cell or
+ * a range of cells in a workbook.
+ *
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
+ *
+ */
+
+#include "xlsxwriter.h"
+
+int main() {
+
+ lxw_workbook *workbook = new_workbook("defined_name.xlsx");
+ lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL);
+ lxw_worksheet *worksheet2 = workbook_add_worksheet(workbook, NULL);
+
+ /* Define some global/workbook names. */
+ workbook_define_name(workbook, "Sales", "=!G1:H10");
+
+ workbook_define_name(workbook, "Exchange_rate", "=0.96");
+ workbook_define_name(workbook, "Sales", "=Sheet1!$G$1:$H$10");
+
+ /* Define a local/worksheet name. */
+ workbook_define_name(workbook, "Sheet2!Sales", "=Sheet2!$G$1:$G$10");
+
+ /* Write some text to the first worksheet and a defined names in a formula. */
+ worksheet_set_column(worksheet1, 0, 0, 45, NULL, NULL);
+
+ worksheet_write_string(worksheet1, 0, 0,
+ "This worksheet contains some defined names.", NULL);
+
+ worksheet_write_string(worksheet1, 1, 0,
+ "See Formulas -> Name Manager above.", NULL);
+
+ worksheet_write_string(worksheet1, 2, 0,
+ "Example formula in cell B3 ->", NULL);
+
+ worksheet_write_formula(worksheet1, 2, 1, "=Exchange_rate", NULL);
+
+ /* Write some text to the second worksheet and a defined names in a formula. */
+ worksheet_set_column(worksheet2, 0, 0, 45, NULL, NULL);
+
+ worksheet_write_string(worksheet2, 0, 0,
+ "This worksheet contains some defined names.", NULL);
+
+ worksheet_write_string(worksheet2, 1, 0,
+ "See Formulas -> Name Manager above.", NULL);
+
+ worksheet_write_string(worksheet2, 2, 0,
+ "Example formula in cell B3 ->", NULL);
+
+ worksheet_write_formula(worksheet2, 2, 1, "=Exchange_rate", NULL);
+
+
+ return workbook_close(workbook);
+}
diff --git a/examples/demo.c b/examples/demo.c
index 8dc985fa..2c65bc31 100644
--- a/examples/demo.c
+++ b/examples/demo.c
@@ -1,7 +1,7 @@
/*
* A simple example of some of the features of the libxlsxwriter library.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/format_font.c b/examples/format_font.c
index 146fd177..f91ba059 100644
--- a/examples/format_font.c
+++ b/examples/format_font.c
@@ -2,7 +2,7 @@
* Example of writing some data with font formatting to a simple Excel
* file using libxlsxwriter.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/format_num_format.c b/examples/format_num_format.c
index 1dc9e089..9cd958a3 100644
--- a/examples/format_num_format.c
+++ b/examples/format_num_format.c
@@ -2,7 +2,7 @@
* Example of writing some data with numeric formatting to a simple Excel file
* using libxlsxwriter.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/hello.c b/examples/hello.c
index fce79e01..32c176ba 100644
--- a/examples/hello.c
+++ b/examples/hello.c
@@ -1,7 +1,7 @@
/*
* Example of writing some data to a simple Excel file using libxlsxwriter.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/tutorial1.c b/examples/tutorial1.c
index ae2df029..1ad194a1 100644
--- a/examples/tutorial1.c
+++ b/examples/tutorial1.c
@@ -5,7 +5,7 @@
* This program is shown, with explanations, in Tutorial 1 of the
* libxlsxwriter documentation.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/tutorial2.c b/examples/tutorial2.c
index ec65ee75..dc79621a 100644
--- a/examples/tutorial2.c
+++ b/examples/tutorial2.c
@@ -5,7 +5,7 @@
* This program is shown, with explanations, in Tutorial 2 of the
* libxlsxwriter documentation.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/tutorial3.c b/examples/tutorial3.c
index 311a9493..1e01d39f 100644
--- a/examples/tutorial3.c
+++ b/examples/tutorial3.c
@@ -5,7 +5,7 @@
* This program is shown, with explanations, in Tutorial 3 of the
* libxlsxwriter documentation.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/examples/utf8.c b/examples/utf8.c
index 3f9f1330..38750c73 100644
--- a/examples/utf8.c
+++ b/examples/utf8.c
@@ -3,7 +3,7 @@
*
* Note: The source file must be UTF-8 encoded.
*
- * Copyright 2014, John McNamara, jmcnamara@cpan.org
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
*
*/
diff --git a/include/xlsxwriter/utility.h b/include/xlsxwriter/utility.h
index 4ab4a2b5..329b5bb1 100644
--- a/include/xlsxwriter/utility.h
+++ b/include/xlsxwriter/utility.h
@@ -128,6 +128,8 @@ double _datetime_to_excel_date(lxw_datetime *datetime, uint8_t date_1904);
char *lxw_strdup(const char *str);
+void lxw_str_tolower(char *str);
+
FILE *lxw_tmpfile(void);
/* Declarations required for unit testing. */
diff --git a/include/xlsxwriter/workbook.h b/include/xlsxwriter/workbook.h
index 00c78ed7..ea320164 100644
--- a/include/xlsxwriter/workbook.h
+++ b/include/xlsxwriter/workbook.h
@@ -51,7 +51,7 @@
/* Define the queue.h structs for the workbook lists. */
STAILQ_HEAD(lxw_worksheets, lxw_worksheet);
-LIST_HEAD(lxw_defined_names, lxw_defined_name);
+TAILQ_HEAD(lxw_defined_names, lxw_defined_name);
#define LXW_DEFINED_NAME_LENGTH 128
@@ -61,9 +61,11 @@ typedef struct lxw_defined_name {
uint8_t hidden;
char name[LXW_DEFINED_NAME_LENGTH];
char range[LXW_DEFINED_NAME_LENGTH];
+ char normalised_name[LXW_DEFINED_NAME_LENGTH];
+ char normalised_sheetname[LXW_DEFINED_NAME_LENGTH];
/* List pointers for queue.h. */
- LIST_ENTRY (lxw_defined_name) list_pointers;
+ TAILQ_ENTRY (lxw_defined_name) list_pointers;
} lxw_defined_name;
/**
@@ -275,6 +277,58 @@ lxw_format *workbook_add_format(lxw_workbook *workbook);
*/
uint8_t workbook_close(lxw_workbook *workbook);
+/**
+ * @brief Create a defined name in the workbook to use as a variable.
+ *
+ * @param workbook Pointer to a lxw_workbook instance.
+ * @param name The defined name.
+ * @param formula The cell or range that the defined name refers to.
+ *
+ * @return 0 for success, non-zero on errror.
+ *
+ * This method is used to defined a name that can be used to represent a
+ * value, a single cell or a range of cells in a workbook: These defined names
+ * can then be used in formulas:
+ *
+ * @code
+ * workbook_define_name(workbook, "Exchange_rate", "=0.96");
+ * worksheet_write_formula(worksheet, 2, 1, "=Exchange_rate", NULL);
+ *
+ * @endcode
+ *
+ * @image html defined_name.png
+ *
+ * As in Excel a name defined like this is "global" to the workbook and can be
+ * referred to from any worksheet:
+ *
+ * @code
+ * // Global workbook name.
+ * workbook_define_name(workbook, "Sales", "=Sheet1!$G$1:$H$10");
+ * @endcode
+ *
+ * It is also possible to define a local/worksheet name by prefixing it with
+ * the sheet name using the syntax `'sheetname!definedname'`:
+ *
+ * @code
+ * // Local worksheet name.
+ * workbook_define_name(workbook, "Sheet2!Sales", "=Sheet2!$G$1:$G$10");
+ * @endcode
+ *
+ * If the sheet name contains spaces or special characters you must follow the
+ * Excel convention and enclose it in single quotes:
+ *
+ * @code
+ * workbook_define_name(workbook, "'New Data'!Sales", "=Sheet2!$G$1:$G$10");
+ * @endcode
+ *
+ * The rules for names in Excel are explained in the
+ * [Miscrosoft Office
+documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
+ *
+ */
+uint8_t workbook_define_name(lxw_workbook *workbook, const char *name,
+ const char *formula);
+
void _free_workbook(lxw_workbook *workbook);
void _workbook_assemble_xml_file(lxw_workbook *workbook);
void _set_default_xf_indices(lxw_workbook *workbook);
@@ -298,6 +352,10 @@ STATIC void _write_defined_name(lxw_workbook *self,
lxw_defined_name *define_name);
STATIC void _write_defined_names(lxw_workbook *self);
+STATIC uint8_t _store_defined_name(lxw_workbook *self, const char *name,
+ const char *formula, int16_t index,
+ uint8_t hidden);
+
#endif /* TESTING */
/* *INDENT-OFF* */
diff --git a/src/packager.c b/src/packager.c
index d8cd1651..3b02cd60 100644
--- a/src/packager.c
+++ b/src/packager.c
@@ -169,19 +169,38 @@ _write_app_file(lxw_packager *self)
{
lxw_workbook *workbook = self->workbook;
lxw_worksheet *worksheet;
+ lxw_defined_name *defined_name;
lxw_app *app = _new_app();
- char num_sheets[ATTR_32] = { 0 };
+ uint16_t named_range_count = 0;
+ char *tmp_name;
+ char number[ATTR_32] = { 0 };
app->file = lxw_tmpfile();
- __builtin_snprintf(num_sheets, ATTR_32, "%d", self->workbook->num_sheets);
+ __builtin_snprintf(number, ATTR_32, "%d", self->workbook->num_sheets);
- _add_heading_pair(app, "Worksheets", num_sheets);
+ _add_heading_pair(app, "Worksheets", number);
STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
_add_part_name(app, worksheet->name);
}
+ /* Add the Named Ranges parts. */
+ TAILQ_FOREACH(defined_name, workbook->defined_names, list_pointers) {
+ tmp_name = strstr(defined_name->name, "_xlnm.");
+
+ if (!tmp_name) {
+ _add_part_name(app, defined_name->name);
+ named_range_count++;
+ }
+ }
+
+ /* Add the Named Range heading pairs. */
+ if (named_range_count) {
+ __builtin_snprintf(number, ATTR_32, "%d", named_range_count);
+ _add_heading_pair(app, "Named Ranges", number);
+ }
+
_app_assemble_xml_file(app);
_add_file_to_zip(self, app->file, "docProps/app.xml");
diff --git a/src/utility.c b/src/utility.c
index ee1670ed..3759b0e0 100644
--- a/src/utility.c
+++ b/src/utility.c
@@ -342,6 +342,16 @@ lxw_strdup(const char *str)
return copy;
}
+/* Simple tolower() for strings. */
+void
+lxw_str_tolower(char *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ str[i] = tolower(str[i]);
+}
+
/*
* Thin wrapper for tmpfile() so it can be over-ridden with a safer version if
* required.
diff --git a/src/workbook.c b/src/workbook.c
index c90a025b..393e9b8f 100644
--- a/src/workbook.c
+++ b/src/workbook.c
@@ -65,9 +65,9 @@ _free_workbook(lxw_workbook *workbook)
}
/* Free the defined_names in the workbook. */
- while (!LIST_EMPTY(workbook->defined_names)) {
- defined_name = LIST_FIRST(workbook->defined_names);
- LIST_REMOVE(defined_name, list_pointers);
+ while (!TAILQ_EMPTY(workbook->defined_names)) {
+ defined_name = TAILQ_FIRST(workbook->defined_names);
+ TAILQ_REMOVE(workbook->defined_names, defined_name, list_pointers);
free(defined_name);
}
@@ -370,6 +370,141 @@ _prepare_workbook(lxw_workbook *self)
}
+/*
+ * Compare two defined_name structures.
+ */
+static int
+_compare_defined_names(lxw_defined_name *a, lxw_defined_name *b)
+{
+ int res = strcmp(a->normalised_name, b->normalised_name);
+
+ /* Primary comparison based on defined name. */
+ if (res)
+ return res;
+
+ /* Secondary comparison based on worksheet name. */
+ res = strcmp(a->normalised_sheetname, b->normalised_sheetname);
+ return res;
+}
+
+STATIC uint8_t
+_store_defined_name(lxw_workbook *self, const char *name,
+ const char *formula, int16_t index, uint8_t hidden)
+{
+ lxw_worksheet *worksheet;
+ lxw_defined_name *defined_name;
+ lxw_defined_name *list_defined_name;
+ char name_copy[LXW_DEFINED_NAME_LENGTH];
+ char *tmp_name;
+ char *worksheet_name;
+
+ /* Do some checks on the input data */
+ if (!name || !formula)
+ return 1;
+
+ if (strlen(name) > LXW_DEFINED_NAME_LENGTH ||
+ strlen(formula) > LXW_DEFINED_NAME_LENGTH) {
+ return 1;
+ }
+
+ defined_name = calloc(1, sizeof(struct lxw_defined_name));
+ RETURN_ON_MEM_ERROR(defined_name, 1);
+
+ /* Copy the user input string. */
+ strcpy(name_copy, name);
+
+ /* Set the worksheet index or -1 for a global defined name. */
+ defined_name->index = index;
+ defined_name->hidden = hidden;
+
+ /* Check for local defined names like like "Sheet1!name". */
+ tmp_name = strchr(name_copy, '!');
+
+ if (tmp_name != NULL) {
+ /* Split the string into the worksheet name and define name. */
+ *tmp_name = '\0';
+ tmp_name++;
+ worksheet_name = name_copy;
+
+ /* Remove any worksheet quoting. */
+ if (worksheet_name[0] == '\'')
+ worksheet_name++;
+ if (worksheet_name[strlen(worksheet_name) - 1] == '\'')
+ worksheet_name[strlen(worksheet_name) - 1] = '\0';
+
+ /* Search for worksheet name to get the equivalent worksheet index. */
+ STAILQ_FOREACH(worksheet, self->worksheets, list_pointers) {
+ if (strcmp(worksheet_name, worksheet->name) == 0) {
+ defined_name->index = worksheet->index;
+ strcpy(defined_name->normalised_sheetname, worksheet_name);
+ }
+ }
+
+ /* If we didn't find the worksheet name we exit. */
+ if (defined_name->index == -1)
+ goto mem_error;
+
+ strcpy(defined_name->name, tmp_name);
+ }
+ else {
+ /* For non-local names we just store the defined name string. */
+ strcpy(defined_name->name, name_copy);
+ }
+
+ /* We need to normalise the defined names for sorting. This involves
+ * removing any _xlnm namespace from the string and converting it to
+ * lowercase. */
+ tmp_name = strstr(defined_name->name, "_xlnm.");
+
+ if (tmp_name != NULL)
+ strcpy(defined_name->normalised_name, tmp_name + 6);
+ else
+ strcpy(defined_name->normalised_name, defined_name->name);
+
+ lxw_str_tolower(defined_name->normalised_name);
+ lxw_str_tolower(defined_name->normalised_sheetname);
+
+ /* Strip leading "=" from the formula. */
+ if (formula[0] == '=')
+ strcpy(defined_name->range, formula + 1);
+ else
+ strcpy(defined_name->range, formula);
+
+ /* We add the defined name to the list in sorted order. */
+ list_defined_name = TAILQ_FIRST(self->defined_names);
+
+ if (list_defined_name == NULL ||
+ _compare_defined_names(defined_name, list_defined_name) < 1) {
+ /* List is empty or defined name goes to the head. */
+ TAILQ_INSERT_HEAD(self->defined_names, defined_name, list_pointers);
+ return 0;
+ }
+
+ TAILQ_FOREACH(list_defined_name, self->defined_names, list_pointers) {
+ int res = _compare_defined_names(defined_name, list_defined_name);
+
+ /* The entry already exists. We exit and don't overwrite. */
+ if (res == 0)
+ goto mem_error;
+
+ /* New defined name is inserted in sorted order before other entries. */
+ if (res < 0) {
+ TAILQ_INSERT_BEFORE(list_defined_name, defined_name,
+ list_pointers);
+ return 0;
+ }
+ }
+
+ /* If the entry wasn't less than any of the entries in the list we add it
+ * to the end. */
+ TAILQ_INSERT_TAIL(self->defined_names, defined_name, list_pointers);
+ return 0;
+
+mem_error:
+ free(defined_name);
+ return 1;
+}
+
/*****************************************************************************
*
* XML functions.
@@ -578,12 +713,12 @@ _write_defined_names(lxw_workbook *self)
{
lxw_defined_name *defined_name;
- if (LIST_EMPTY(self->defined_names))
+ if (TAILQ_EMPTY(self->defined_names))
return;
_xml_start_tag(self->file, "definedNames", NULL);
- LIST_FOREACH(defined_name, self->defined_names, list_pointers) {
+ TAILQ_FOREACH(defined_name, self->defined_names, list_pointers) {
_write_defined_name(self, defined_name);
}
@@ -675,7 +810,7 @@ new_workbook_opt(const char *filename, lxw_workbook_options *options)
/* Add the defined_names list. */
workbook->defined_names = calloc(1, sizeof(struct lxw_defined_names));
GOTO_LABEL_ON_MEM_ERROR(workbook->defined_names, mem_error);
- LIST_INIT(workbook->defined_names);
+ TAILQ_INIT(workbook->defined_names);
/* Add the shared strings table. */
workbook->sst = _new_sst();
@@ -813,3 +948,14 @@ workbook_close(lxw_workbook *self)
mem_error:
return 1;
}
+
+/*
+ * Create a defined name in Excel. We handle global/workbook level names and
+ * local/worksheet names.
+ */
+uint8_t
+workbook_define_name(lxw_workbook *self, const char *name,
+ const char *formula)
+{
+ return _store_defined_name(self, name, formula, -1, 0);
+}
diff --git a/test/functional/src/test_defined_name02.c b/test/functional/src/test_defined_name02.c
new file mode 100644
index 00000000..0e2c4061
--- /dev/null
+++ b/test/functional/src/test_defined_name02.c
@@ -0,0 +1,22 @@
+/*****************************************************************************
+ * Test cases for libxlsxwriter.
+ *
+ * Simple test case for defined names.
+ *
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
+ *
+ */
+
+#include "xlsxwriter.h"
+
+int main() {
+
+ lxw_workbook *workbook = new_workbook("test_defined_name02.xlsx");
+ lxw_worksheet *worksheet = workbook_add_worksheet(workbook, "sheet One");
+
+ workbook_define_name(workbook, "Sales", "='sheet One'!$G$1:$H$10");
+
+ (void)worksheet;
+
+ return workbook_close(workbook);
+}
diff --git a/test/functional/src/test_defined_name03.c b/test/functional/src/test_defined_name03.c
new file mode 100644
index 00000000..eb762e38
--- /dev/null
+++ b/test/functional/src/test_defined_name03.c
@@ -0,0 +1,22 @@
+/*****************************************************************************
+ * Test cases for libxlsxwriter.
+ *
+ * Simple test case for defined names.
+ *
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
+ *
+ */
+
+#include "xlsxwriter.h"
+
+int main() {
+
+ lxw_workbook *workbook = new_workbook("test_defined_name03.xlsx");
+ lxw_worksheet *worksheet = workbook_add_worksheet(workbook, "sheet One");
+
+ workbook_define_name(workbook, "Sales", "='sheet One'!G1:H10");
+
+ (void)worksheet;
+
+ return workbook_close(workbook);
+}
diff --git a/test/functional/src/test_defined_name04.c b/test/functional/src/test_defined_name04.c
new file mode 100644
index 00000000..429b37ff
--- /dev/null
+++ b/test/functional/src/test_defined_name04.c
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * Test cases for libxlsxwriter.
+ *
+ * Simple test case for defined names.
+ *
+ * Copyright 2014-2015, John McNamara, jmcnamara@cpan.org
+ *
+ */
+
+#include "xlsxwriter.h"
+
+int main() {
+
+ lxw_workbook *workbook = new_workbook("test_defined_name04.xlsx");
+ lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
+
+ workbook_define_name(workbook, "\\__", "=Sheet1!$A$1");
+ workbook_define_name(workbook, "a3f6", "=Sheet1!$A$2");
+ workbook_define_name(workbook, "afoo.bar", "=Sheet1!$A$3");
+ workbook_define_name(workbook, "étude", "=Sheet1!$A$4");
+ workbook_define_name(workbook, "eésumé", "=Sheet1!$A$5");
+ workbook_define_name(workbook, "a", "=Sheet1!$A$6");
+
+ (void)worksheet;
+
+ return workbook_close(workbook);
+}
diff --git a/test/functional/test_defined_name.py b/test/functional/test_defined_name.py
new file mode 100644
index 00000000..d84bbc87
--- /dev/null
+++ b/test/functional/test_defined_name.py
@@ -0,0 +1,27 @@
+###############################################################################
+#
+# Tests for libxlsxwriter.
+#
+# Copyright 2014-2015, 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_defined_name01(self):
+ # self.run_exe_test('test_defined_name01')
+
+ def test_defined_name02(self):
+ self.run_exe_test('test_defined_name02')
+
+ def test_defined_name03(self):
+ self.run_exe_test('test_defined_name03')
+
+ def test_defined_name04(self):
+ self.run_exe_test('test_defined_name04')
+
diff --git a/test/functional/xlsx_files/defined_name01.xlsx b/test/functional/xlsx_files/defined_name01.xlsx
new file mode 100644
index 00000000..031b10e7
Binary files /dev/null and b/test/functional/xlsx_files/defined_name01.xlsx differ
diff --git a/test/functional/xlsx_files/defined_name02.xlsx b/test/functional/xlsx_files/defined_name02.xlsx
new file mode 100644
index 00000000..770b610a
Binary files /dev/null and b/test/functional/xlsx_files/defined_name02.xlsx differ
diff --git a/test/functional/xlsx_files/defined_name03.xlsx b/test/functional/xlsx_files/defined_name03.xlsx
new file mode 100644
index 00000000..37e9f44a
Binary files /dev/null and b/test/functional/xlsx_files/defined_name03.xlsx differ
diff --git a/test/functional/xlsx_files/defined_name04.xlsx b/test/functional/xlsx_files/defined_name04.xlsx
new file mode 100644
index 00000000..1e6d56e4
Binary files /dev/null and b/test/functional/xlsx_files/defined_name04.xlsx differ
diff --git a/test/unit/workbook/test_workbook_write_defined_name.c b/test/unit/workbook/test_workbook_write_defined_name.c
index b0cfdefb..ebf6e9d6 100644
--- a/test/unit/workbook/test_workbook_write_defined_name.c
+++ b/test/unit/workbook/test_workbook_write_defined_name.c
@@ -12,12 +12,10 @@
/* Test the _write_defined_name() method. */
CTEST(workbook, write_defined_name) {
-
-
char* got;
char exp[] = "Sheet1!$1:$1";
FILE* testfile = tmpfile();
- lxw_defined_name defined_name = {0, 0, "_xlnm.Print_Titles", "Sheet1!$1:$1", {NULL, NULL}};
+ lxw_defined_name defined_name = {0, 0, "_xlnm.Print_Titles", "Sheet1!$1:$1", "", "", {NULL, NULL}};
lxw_workbook *workbook = new_workbook(NULL);
diff --git a/test/unit/workbook/test_workbook_write_defined_names.c b/test/unit/workbook/test_workbook_write_defined_names.c
index dd327414..56d068eb 100644
--- a/test/unit/workbook/test_workbook_write_defined_names.c
+++ b/test/unit/workbook/test_workbook_write_defined_names.c
@@ -17,15 +17,12 @@ CTEST(workbook, write_defined_names) {
char* got;
char exp[] = "Sheet1!$1:$1";
FILE* testfile = tmpfile();
- lxw_defined_name *defined_name = calloc(1, sizeof(struct lxw_defined_name));
-
- strcpy(defined_name->name, "_xlnm.Print_Titles");
- strcpy(defined_name->range, "Sheet1!$1:$1");
-
lxw_workbook *workbook = new_workbook(NULL);
workbook->file = testfile;
- LIST_INSERT_HEAD(workbook->defined_names, defined_name, list_pointers);
+ workbook_add_worksheet(workbook, NULL);
+
+ _store_defined_name(workbook, "_xlnm.Print_Titles", "Sheet1!$1:$1", 0, 0);
_write_defined_names(workbook);
@@ -34,3 +31,36 @@ CTEST(workbook, write_defined_names) {
_free_workbook(workbook);
}
+
+
+/* Test the _write_defined_name() method. */
+CTEST(workbook, write_defined_names_sorted) {
+ char* got;
+ char exp[] = "Sheet1!$A$1Sheet1!$A$1Sheet2!$A$1Sheet1!$A$1'Sheet 3'!$A$1Sheet1!$A$1Sheet2!$A$10.98\"Saab 900\"";
+ FILE* testfile = tmpfile();
+
+
+ lxw_workbook *workbook = new_workbook(NULL);
+ workbook->file = testfile;
+
+ workbook_add_worksheet(workbook, NULL);
+ workbook_add_worksheet(workbook, NULL);
+ workbook_add_worksheet(workbook, "Sheet 3");
+
+
+ workbook_define_name(workbook, "'Sheet 3'!Bar", "='Sheet 3'!$A$1");
+ workbook_define_name(workbook, "Abc", "=Sheet1!$A$1" );
+ workbook_define_name(workbook, "Baz", "=0.98" );
+ workbook_define_name(workbook, "Sheet1!Bar", "=Sheet1!$A$1" );
+ workbook_define_name(workbook, "Sheet2!Bar", "=Sheet2!$A$1" );
+ workbook_define_name(workbook, "Sheet2!aaa", "=Sheet2!$A$1" );
+ workbook_define_name(workbook, "'Sheet 3'!car", "=\"Saab 900\"" );
+ workbook_define_name(workbook, "_Egg", "=Sheet1!$A$1" );
+ workbook_define_name(workbook, "_Fog", "=Sheet1!$A$1" );
+
+ _write_defined_names(workbook);
+
+ RUN_XLSX_STREQ(exp, got);
+
+ _free_workbook(workbook);
+}