fast_excel 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +5 -1
- data/.gitignore +3 -0
- data/.octocov.yml +28 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +4 -2
- data/Rakefile +4 -1
- data/examples/comment_options.rb +39 -0
- data/fast_excel.gemspec +3 -2
- data/lib/fast_excel/binding/workbook.rb +53 -6
- data/lib/fast_excel/binding/worksheet.rb +28 -4
- data/lib/fast_excel/binding.rb +116 -13
- data/lib/fast_excel.rb +13 -12
- data/libxlsxwriter/.cirrus.yml +9 -0
- data/libxlsxwriter/.github/workflows/cmake_actions.yml +10 -6
- data/libxlsxwriter/.github/workflows/code_style.yml +2 -0
- data/libxlsxwriter/.github/workflows/make_32_actions.yml +43 -0
- data/libxlsxwriter/.github/workflows/windows_build.yml +7 -6
- data/libxlsxwriter/.github/workflows/zig_build.yml +1 -3
- data/libxlsxwriter/.gitignore +9 -7
- data/libxlsxwriter/.indent.pro +6 -0
- data/libxlsxwriter/CMakeLists.txt +377 -238
- data/libxlsxwriter/Changes.txt +189 -0
- data/libxlsxwriter/LICENSE.txt +1 -1
- data/libxlsxwriter/Makefile +36 -4
- data/libxlsxwriter/Readme.md +1 -1
- data/libxlsxwriter/build.zig +181 -92
- data/libxlsxwriter/build.zig.zon +15 -4
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +4 -0
- data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/chart.h +134 -1
- data/libxlsxwriter/include/xlsxwriter/chartsheet.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/comment.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/common.h +12 -8
- data/libxlsxwriter/include/xlsxwriter/content_types.h +3 -1
- data/libxlsxwriter/include/xlsxwriter/core.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/custom.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/drawing.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/format.h +34 -3
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/metadata.h +5 -1
- data/libxlsxwriter/include/xlsxwriter/packager.h +6 -1
- data/libxlsxwriter/include/xlsxwriter/relationships.h +3 -1
- data/libxlsxwriter/include/xlsxwriter/rich_value.h +51 -0
- data/libxlsxwriter/include/xlsxwriter/rich_value_rel.h +50 -0
- data/libxlsxwriter/include/xlsxwriter/rich_value_structure.h +53 -0
- data/libxlsxwriter/include/xlsxwriter/rich_value_types.h +49 -0
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/styles.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/table.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/theme.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +4 -4
- data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +3 -3
- data/libxlsxwriter/include/xlsxwriter/utility.h +58 -7
- data/libxlsxwriter/include/xlsxwriter/vml.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/workbook.h +59 -2
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +159 -13
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +11 -10
- data/libxlsxwriter/include/xlsxwriter.h +5 -4
- data/libxlsxwriter/libxlsxwriter.podspec +6 -6
- data/libxlsxwriter/src/Makefile +2 -1
- data/libxlsxwriter/src/app.c +2 -1
- data/libxlsxwriter/src/chart.c +360 -63
- data/libxlsxwriter/src/chartsheet.c +2 -1
- data/libxlsxwriter/src/comment.c +2 -1
- data/libxlsxwriter/src/content_types.c +22 -1
- data/libxlsxwriter/src/core.c +2 -1
- data/libxlsxwriter/src/custom.c +2 -1
- data/libxlsxwriter/src/drawing.c +7 -3
- data/libxlsxwriter/src/format.c +21 -1
- data/libxlsxwriter/src/hash_table.c +2 -1
- data/libxlsxwriter/src/metadata.c +176 -20
- data/libxlsxwriter/src/packager.c +306 -6
- data/libxlsxwriter/src/relationships.c +25 -1
- data/libxlsxwriter/src/rich_value.c +191 -0
- data/libxlsxwriter/src/rich_value_rel.c +142 -0
- data/libxlsxwriter/src/rich_value_structure.c +162 -0
- data/libxlsxwriter/src/rich_value_types.c +199 -0
- data/libxlsxwriter/src/shared_strings.c +2 -1
- data/libxlsxwriter/src/styles.c +31 -7
- data/libxlsxwriter/src/table.c +2 -1
- data/libxlsxwriter/src/theme.c +2 -1
- data/libxlsxwriter/src/utility.c +136 -46
- data/libxlsxwriter/src/vml.c +2 -1
- data/libxlsxwriter/src/workbook.c +191 -10
- data/libxlsxwriter/src/worksheet.c +514 -34
- data/libxlsxwriter/src/xmlwriter.c +17 -22
- data/libxlsxwriter/third_party/minizip/Makefile.orig +1 -1
- data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
- data/libxlsxwriter/third_party/minizip/ioapi.h +6 -6
- data/libxlsxwriter/third_party/minizip/miniunz.c +16 -2
- data/libxlsxwriter/third_party/minizip/unzip.c +4 -4
- data/libxlsxwriter/third_party/minizip/unzip.h +1 -1
- data/libxlsxwriter/third_party/minizip/zip.c +5 -5
- data/libxlsxwriter/third_party/minizip/zip.h +3 -3
- data/libxlsxwriter/version.txt +1 -1
- data/sonar-project.properties +4 -0
- data/test/color_to_hex_test.rb +15 -0
- data/test/comment_opt_test.rb +76 -0
- data/test/date_test.rb +14 -0
- data/test/format_test.rb +5 -1
- data/test/get_worksheet_test.rb +28 -0
- data/test/test_helper.rb +7 -4
- data/test/tmpdir_test.rb +32 -0
- data/test/validations_test.rb +25 -19
- data/test/worksheet_test.rb +10 -2
- metadata +42 -12
- data/libxlsxwriter/cmake/FindMINIZIP.cmake +0 -121
- data/libxlsxwriter/cmake/FindPackage.cmake +0 -183
- data/libxlsxwriter/cmake/i686-toolchain.cmake +0 -7
- data/test/reopen_test.rb +0 -22
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* SPDX-License-Identifier: BSD-2-Clause
|
|
7
|
+
* Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
|
|
7
8
|
*
|
|
8
9
|
*/
|
|
9
10
|
|
|
@@ -141,6 +142,11 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
|
|
|
141
142
|
GOTO_LABEL_ON_MEM_ERROR(worksheet->image_props, mem_error);
|
|
142
143
|
STAILQ_INIT(worksheet->image_props);
|
|
143
144
|
|
|
145
|
+
worksheet->embedded_image_props =
|
|
146
|
+
calloc(1, sizeof(struct lxw_embedded_image_props));
|
|
147
|
+
GOTO_LABEL_ON_MEM_ERROR(worksheet->embedded_image_props, mem_error);
|
|
148
|
+
STAILQ_INIT(worksheet->embedded_image_props);
|
|
149
|
+
|
|
144
150
|
worksheet->chart_data = calloc(1, sizeof(struct lxw_chart_props));
|
|
145
151
|
GOTO_LABEL_ON_MEM_ERROR(worksheet->chart_data, mem_error);
|
|
146
152
|
STAILQ_INIT(worksheet->chart_data);
|
|
@@ -288,6 +294,7 @@ lxw_worksheet_new(lxw_worksheet_init_data *init_data)
|
|
|
288
294
|
worksheet->first_sheet = init_data->first_sheet;
|
|
289
295
|
worksheet->default_url_format = init_data->default_url_format;
|
|
290
296
|
worksheet->max_url_length = init_data->max_url_length;
|
|
297
|
+
worksheet->use_1904_epoch = init_data->use_1904_epoch;
|
|
291
298
|
}
|
|
292
299
|
|
|
293
300
|
return worksheet;
|
|
@@ -367,7 +374,8 @@ _free_cell(lxw_cell *cell)
|
|
|
367
374
|
return;
|
|
368
375
|
|
|
369
376
|
if (cell->type != NUMBER_CELL && cell->type != STRING_CELL
|
|
370
|
-
&& cell->type != BLANK_CELL && cell->type != BOOLEAN_CELL
|
|
377
|
+
&& cell->type != BLANK_CELL && cell->type != BOOLEAN_CELL
|
|
378
|
+
&& cell->type != ERROR_CELL) {
|
|
371
379
|
|
|
372
380
|
free((void *) cell->u.string);
|
|
373
381
|
}
|
|
@@ -606,6 +614,17 @@ lxw_worksheet_free(lxw_worksheet *worksheet)
|
|
|
606
614
|
free(worksheet->image_props);
|
|
607
615
|
}
|
|
608
616
|
|
|
617
|
+
if (worksheet->embedded_image_props) {
|
|
618
|
+
while (!STAILQ_EMPTY(worksheet->embedded_image_props)) {
|
|
619
|
+
object_props = STAILQ_FIRST(worksheet->embedded_image_props);
|
|
620
|
+
STAILQ_REMOVE_HEAD(worksheet->embedded_image_props,
|
|
621
|
+
list_pointers);
|
|
622
|
+
_free_object_properties(object_props);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
free(worksheet->embedded_image_props);
|
|
626
|
+
}
|
|
627
|
+
|
|
609
628
|
if (worksheet->chart_data) {
|
|
610
629
|
while (!STAILQ_EMPTY(worksheet->chart_data)) {
|
|
611
630
|
object_props = STAILQ_FIRST(worksheet->chart_data);
|
|
@@ -990,6 +1009,25 @@ _new_boolean_cell(lxw_row_t row_num, lxw_col_t col_num, int value,
|
|
|
990
1009
|
return cell;
|
|
991
1010
|
}
|
|
992
1011
|
|
|
1012
|
+
/*
|
|
1013
|
+
* Create a new worksheet error cell object.
|
|
1014
|
+
*/
|
|
1015
|
+
STATIC lxw_cell *
|
|
1016
|
+
_new_error_cell(lxw_row_t row_num, lxw_col_t col_num, uint32_t value,
|
|
1017
|
+
lxw_format *format)
|
|
1018
|
+
{
|
|
1019
|
+
lxw_cell *cell = calloc(1, sizeof(lxw_cell));
|
|
1020
|
+
RETURN_ON_MEM_ERROR(cell, cell);
|
|
1021
|
+
|
|
1022
|
+
cell->row_num = row_num;
|
|
1023
|
+
cell->col_num = col_num;
|
|
1024
|
+
cell->type = ERROR_CELL;
|
|
1025
|
+
cell->format = format;
|
|
1026
|
+
cell->u.number = value;
|
|
1027
|
+
|
|
1028
|
+
return cell;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
993
1031
|
/*
|
|
994
1032
|
* Create a new comment cell object.
|
|
995
1033
|
*/
|
|
@@ -1454,13 +1492,13 @@ lxw_basename(const char *path)
|
|
|
1454
1492
|
size_t
|
|
1455
1493
|
_validation_list_length(const char **list)
|
|
1456
1494
|
{
|
|
1457
|
-
|
|
1495
|
+
size_t i = 0;
|
|
1458
1496
|
size_t length = 0;
|
|
1459
1497
|
|
|
1460
1498
|
if (!list || !list[0])
|
|
1461
1499
|
return 0;
|
|
1462
1500
|
|
|
1463
|
-
while (list[i]
|
|
1501
|
+
while (list[i]) {
|
|
1464
1502
|
/* Include commas in the length. */
|
|
1465
1503
|
length += 1 + lxw_utf8_strlen(list[i]);
|
|
1466
1504
|
i++;
|
|
@@ -1477,7 +1515,7 @@ _validation_list_length(const char **list)
|
|
|
1477
1515
|
char *
|
|
1478
1516
|
_validation_list_to_csv(const char **list)
|
|
1479
1517
|
{
|
|
1480
|
-
|
|
1518
|
+
size_t i = 0;
|
|
1481
1519
|
char *str;
|
|
1482
1520
|
|
|
1483
1521
|
/* Create a buffer for the concatenated, and quoted, string. */
|
|
@@ -1651,7 +1689,7 @@ _set_default_table_columns(lxw_table_obj *table_obj)
|
|
|
1651
1689
|
for (i = 0; i < num_cols; i++) {
|
|
1652
1690
|
lxw_snprintf(col_name, LXW_ATTR_32, "Column%d", i + 1);
|
|
1653
1691
|
|
|
1654
|
-
column = calloc(
|
|
1692
|
+
column = calloc(1, sizeof(lxw_table_column));
|
|
1655
1693
|
RETURN_ON_MEM_ERROR(column, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
|
1656
1694
|
|
|
1657
1695
|
header = lxw_strdup(col_name);
|
|
@@ -1680,9 +1718,11 @@ _expand_table_formula(const char *formula)
|
|
|
1680
1718
|
|
|
1681
1719
|
ptr = formula;
|
|
1682
1720
|
|
|
1683
|
-
while (*ptr
|
|
1721
|
+
while (*ptr) {
|
|
1684
1722
|
if (*ptr == '@')
|
|
1685
1723
|
ref_count++;
|
|
1724
|
+
|
|
1725
|
+
ptr++;
|
|
1686
1726
|
}
|
|
1687
1727
|
|
|
1688
1728
|
if (ref_count == 0) {
|
|
@@ -2967,13 +3007,15 @@ _worksheet_position_object_pixels(lxw_worksheet *self,
|
|
|
2967
3007
|
height = height + y1;
|
|
2968
3008
|
|
|
2969
3009
|
/* Subtract the underlying cell widths to find the end cell. */
|
|
2970
|
-
while (width >= _worksheet_size_col(self, col_end, anchor)
|
|
3010
|
+
while (width >= _worksheet_size_col(self, col_end, anchor)
|
|
3011
|
+
&& col_end < LXW_COL_MAX) {
|
|
2971
3012
|
width -= _worksheet_size_col(self, col_end, anchor);
|
|
2972
3013
|
col_end++;
|
|
2973
3014
|
}
|
|
2974
3015
|
|
|
2975
3016
|
/* Subtract the underlying cell heights to find the end cell. */
|
|
2976
|
-
while (height >= _worksheet_size_row(self, row_end, anchor)
|
|
3017
|
+
while (height >= _worksheet_size_row(self, row_end, anchor)
|
|
3018
|
+
&& row_end < LXW_ROW_MAX) {
|
|
2977
3019
|
height -= _worksheet_size_row(self, row_end, anchor);
|
|
2978
3020
|
row_end++;
|
|
2979
3021
|
}
|
|
@@ -4138,11 +4180,13 @@ _process_bmp(lxw_object_properties *image_props)
|
|
|
4138
4180
|
height = 0;
|
|
4139
4181
|
|
|
4140
4182
|
/* Ensure that we read some valid data from the file. */
|
|
4141
|
-
if (width == 0)
|
|
4183
|
+
if (width == 0 || height == 0)
|
|
4142
4184
|
goto file_error;
|
|
4143
4185
|
|
|
4144
|
-
height
|
|
4145
|
-
|
|
4186
|
+
/* The height can be stored as negative for a top-down DIB so we need to
|
|
4187
|
+
* take the absolute value. */
|
|
4188
|
+
height = (uint32_t) abs(LXW_INT32_HOST(height));
|
|
4189
|
+
width = (uint32_t) LXW_INT32_HOST(width);
|
|
4146
4190
|
|
|
4147
4191
|
/* Set the image metadata. */
|
|
4148
4192
|
image_props->image_type = LXW_IMAGE_BMP;
|
|
@@ -4521,6 +4565,15 @@ _write_boolean_cell(lxw_worksheet *self, lxw_cell *cell)
|
|
|
4521
4565
|
lxw_xml_data_element(self->file, "v", data, NULL);
|
|
4522
4566
|
}
|
|
4523
4567
|
|
|
4568
|
+
/*
|
|
4569
|
+
* Write out a error worksheet cell.
|
|
4570
|
+
*/
|
|
4571
|
+
STATIC void
|
|
4572
|
+
_write_error_cell(lxw_worksheet *self)
|
|
4573
|
+
{
|
|
4574
|
+
lxw_xml_data_element(self->file, "v", "#VALUE!", NULL);
|
|
4575
|
+
}
|
|
4576
|
+
|
|
4524
4577
|
/*
|
|
4525
4578
|
* Calculate the "spans" attribute of the <row> tag. This is an XLSX
|
|
4526
4579
|
* optimization and isn't strictly required. However, it makes comparing
|
|
@@ -4651,6 +4704,13 @@ _write_cell(lxw_worksheet *self, lxw_cell *cell, lxw_format *row_format)
|
|
|
4651
4704
|
_write_array_formula_num_cell(self, cell);
|
|
4652
4705
|
lxw_xml_end_tag(self->file, "c");
|
|
4653
4706
|
}
|
|
4707
|
+
else if (cell->type == ERROR_CELL) {
|
|
4708
|
+
LXW_PUSH_ATTRIBUTES_STR("t", "e");
|
|
4709
|
+
LXW_PUSH_ATTRIBUTES_DBL("vm", cell->u.number);
|
|
4710
|
+
lxw_xml_start_tag(self->file, "c", &attributes);
|
|
4711
|
+
_write_error_cell(self);
|
|
4712
|
+
lxw_xml_end_tag(self->file, "c");
|
|
4713
|
+
}
|
|
4654
4714
|
|
|
4655
4715
|
LXW_FREE_ATTRIBUTES();
|
|
4656
4716
|
}
|
|
@@ -7492,6 +7552,105 @@ _validate_conditional_cell(lxw_cond_format_obj *cond_format,
|
|
|
7492
7552
|
return LXW_NO_ERROR;
|
|
7493
7553
|
}
|
|
7494
7554
|
|
|
7555
|
+
/* Check that the correct criteria and used with the correct conditional format. */
|
|
7556
|
+
lxw_error
|
|
7557
|
+
_validate_conditional_criteria(lxw_cond_format_obj *cond_format)
|
|
7558
|
+
{
|
|
7559
|
+
uint8_t criteria_mismatch = LXW_FALSE;
|
|
7560
|
+
|
|
7561
|
+
if (cond_format->type == LXW_CONDITIONAL_TYPE_CELL) {
|
|
7562
|
+
switch (cond_format->criteria) {
|
|
7563
|
+
case LXW_CONDITIONAL_CRITERIA_EQUAL_TO:
|
|
7564
|
+
case LXW_CONDITIONAL_CRITERIA_NOT_EQUAL_TO:
|
|
7565
|
+
case LXW_CONDITIONAL_CRITERIA_GREATER_THAN:
|
|
7566
|
+
case LXW_CONDITIONAL_CRITERIA_LESS_THAN:
|
|
7567
|
+
case LXW_CONDITIONAL_CRITERIA_GREATER_THAN_OR_EQUAL_TO:
|
|
7568
|
+
case LXW_CONDITIONAL_CRITERIA_LESS_THAN_OR_EQUAL_TO:
|
|
7569
|
+
case LXW_CONDITIONAL_CRITERIA_BETWEEN:
|
|
7570
|
+
case LXW_CONDITIONAL_CRITERIA_NOT_BETWEEN:
|
|
7571
|
+
criteria_mismatch = LXW_FALSE;
|
|
7572
|
+
break;
|
|
7573
|
+
default:
|
|
7574
|
+
criteria_mismatch = LXW_TRUE;
|
|
7575
|
+
}
|
|
7576
|
+
}
|
|
7577
|
+
else if (cond_format->type == LXW_CONDITIONAL_TYPE_TIME_PERIOD) {
|
|
7578
|
+
switch (cond_format->criteria) {
|
|
7579
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_YESTERDAY:
|
|
7580
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_TODAY:
|
|
7581
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_TOMORROW:
|
|
7582
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_LAST_7_DAYS:
|
|
7583
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_LAST_WEEK:
|
|
7584
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_THIS_WEEK:
|
|
7585
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_NEXT_WEEK:
|
|
7586
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_LAST_MONTH:
|
|
7587
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_THIS_MONTH:
|
|
7588
|
+
case LXW_CONDITIONAL_CRITERIA_TIME_PERIOD_NEXT_MONTH:
|
|
7589
|
+
criteria_mismatch = LXW_FALSE;
|
|
7590
|
+
break;
|
|
7591
|
+
default:
|
|
7592
|
+
criteria_mismatch = LXW_TRUE;
|
|
7593
|
+
}
|
|
7594
|
+
}
|
|
7595
|
+
else if (cond_format->type == LXW_CONDITIONAL_TYPE_TEXT) {
|
|
7596
|
+
switch (cond_format->criteria) {
|
|
7597
|
+
case LXW_CONDITIONAL_CRITERIA_TEXT_CONTAINING:
|
|
7598
|
+
case LXW_CONDITIONAL_CRITERIA_TEXT_NOT_CONTAINING:
|
|
7599
|
+
case LXW_CONDITIONAL_CRITERIA_TEXT_BEGINS_WITH:
|
|
7600
|
+
case LXW_CONDITIONAL_CRITERIA_TEXT_ENDS_WITH:
|
|
7601
|
+
criteria_mismatch = LXW_FALSE;
|
|
7602
|
+
break;
|
|
7603
|
+
default:
|
|
7604
|
+
criteria_mismatch = LXW_TRUE;
|
|
7605
|
+
}
|
|
7606
|
+
}
|
|
7607
|
+
else if (cond_format->type == LXW_CONDITIONAL_TYPE_AVERAGE) {
|
|
7608
|
+
switch (cond_format->criteria) {
|
|
7609
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_ABOVE:
|
|
7610
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_BELOW:
|
|
7611
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_ABOVE_OR_EQUAL:
|
|
7612
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_BELOW_OR_EQUAL:
|
|
7613
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_1_STD_DEV_ABOVE:
|
|
7614
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_1_STD_DEV_BELOW:
|
|
7615
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_2_STD_DEV_ABOVE:
|
|
7616
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_2_STD_DEV_BELOW:
|
|
7617
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_3_STD_DEV_ABOVE:
|
|
7618
|
+
case LXW_CONDITIONAL_CRITERIA_AVERAGE_3_STD_DEV_BELOW:
|
|
7619
|
+
criteria_mismatch = LXW_FALSE;
|
|
7620
|
+
break;
|
|
7621
|
+
default:
|
|
7622
|
+
criteria_mismatch = LXW_TRUE;
|
|
7623
|
+
}
|
|
7624
|
+
}
|
|
7625
|
+
else if (cond_format->type == LXW_CONDITIONAL_TYPE_TOP
|
|
7626
|
+
|| cond_format->type == LXW_CONDITIONAL_TYPE_BOTTOM) {
|
|
7627
|
+
switch (cond_format->criteria) {
|
|
7628
|
+
case LXW_CONDITIONAL_CRITERIA_NONE:
|
|
7629
|
+
case LXW_CONDITIONAL_CRITERIA_TOP_OR_BOTTOM_PERCENT:
|
|
7630
|
+
criteria_mismatch = LXW_FALSE;
|
|
7631
|
+
break;
|
|
7632
|
+
default:
|
|
7633
|
+
criteria_mismatch = LXW_TRUE;
|
|
7634
|
+
}
|
|
7635
|
+
}
|
|
7636
|
+
else {
|
|
7637
|
+
/* Any other conditional type should have a zero criteria. */
|
|
7638
|
+
cond_format->criteria = LXW_CONDITIONAL_CRITERIA_NONE;
|
|
7639
|
+
}
|
|
7640
|
+
|
|
7641
|
+
if (criteria_mismatch) {
|
|
7642
|
+
LXW_WARN_FORMAT2("worksheet_conditional_format_cell()/_range(): "
|
|
7643
|
+
"LXW_CONDITIONAL_CRITERIA_* = %d is not valid for "
|
|
7644
|
+
"LXW_CONDITIONAL_TYPE_* = %d", cond_format->criteria,
|
|
7645
|
+
cond_format->type);
|
|
7646
|
+
|
|
7647
|
+
return LXW_ERROR_PARAMETER_VALIDATION;
|
|
7648
|
+
}
|
|
7649
|
+
else {
|
|
7650
|
+
return LXW_NO_ERROR;
|
|
7651
|
+
}
|
|
7652
|
+
}
|
|
7653
|
+
|
|
7495
7654
|
/*
|
|
7496
7655
|
* Write the <ignoredErrors> element.
|
|
7497
7656
|
*/
|
|
@@ -7844,6 +8003,9 @@ worksheet_write_formula_num(lxw_worksheet *self,
|
|
|
7844
8003
|
if (!formula)
|
|
7845
8004
|
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
7846
8005
|
|
|
8006
|
+
if (lxw_str_is_empty(formula))
|
|
8007
|
+
return LXW_ERROR_PARAMETER_IS_EMPTY;
|
|
8008
|
+
|
|
7847
8009
|
err = _check_dimensions(self, row_num, col_num, LXW_FALSE, LXW_FALSE);
|
|
7848
8010
|
if (err)
|
|
7849
8011
|
return err;
|
|
@@ -7879,6 +8041,9 @@ worksheet_write_formula_str(lxw_worksheet *self,
|
|
|
7879
8041
|
if (!formula)
|
|
7880
8042
|
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
7881
8043
|
|
|
8044
|
+
if (lxw_str_is_empty(formula))
|
|
8045
|
+
return LXW_ERROR_PARAMETER_IS_EMPTY;
|
|
8046
|
+
|
|
7882
8047
|
err = _check_dimensions(self, row_num, col_num, LXW_FALSE, LXW_FALSE);
|
|
7883
8048
|
if (err)
|
|
7884
8049
|
return err;
|
|
@@ -7944,6 +8109,9 @@ _store_array_formula(lxw_worksheet *self,
|
|
|
7944
8109
|
if (!formula)
|
|
7945
8110
|
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
7946
8111
|
|
|
8112
|
+
if (lxw_str_is_empty(formula))
|
|
8113
|
+
return LXW_ERROR_PARAMETER_IS_EMPTY;
|
|
8114
|
+
|
|
7947
8115
|
/* Check that row and col are valid and store max and min values. */
|
|
7948
8116
|
err = _check_dimensions(self, first_row, first_col, LXW_FALSE, LXW_FALSE);
|
|
7949
8117
|
if (err)
|
|
@@ -7964,7 +8132,7 @@ _store_array_formula(lxw_worksheet *self,
|
|
|
7964
8132
|
|
|
7965
8133
|
/* Copy and trip leading "{=" from formula. */
|
|
7966
8134
|
if (formula[0] == '{')
|
|
7967
|
-
if (formula[1] == '=')
|
|
8135
|
+
if (strlen(formula) >= 2 && formula[1] == '=')
|
|
7968
8136
|
formula_copy = lxw_strdup(formula + 2);
|
|
7969
8137
|
else
|
|
7970
8138
|
formula_copy = lxw_strdup(formula + 1);
|
|
@@ -7972,8 +8140,17 @@ _store_array_formula(lxw_worksheet *self,
|
|
|
7972
8140
|
formula_copy = lxw_strdup_formula(formula);
|
|
7973
8141
|
|
|
7974
8142
|
/* Strip trailing "}" from formula. */
|
|
7975
|
-
if (
|
|
8143
|
+
if (strlen(formula_copy) > 0
|
|
8144
|
+
&& formula_copy[strlen(formula_copy) - 1] == '}') {
|
|
7976
8145
|
formula_copy[strlen(formula_copy) - 1] = '\0';
|
|
8146
|
+
}
|
|
8147
|
+
|
|
8148
|
+
/* Check for empty formula that started as {=}. */
|
|
8149
|
+
if (lxw_str_is_empty(formula_copy)) {
|
|
8150
|
+
free(formula_copy);
|
|
8151
|
+
free(range);
|
|
8152
|
+
return LXW_ERROR_PARAMETER_IS_EMPTY;
|
|
8153
|
+
}
|
|
7977
8154
|
|
|
7978
8155
|
/* Create a new array formula cell object. */
|
|
7979
8156
|
cell = _new_array_formula_cell(first_row, first_col,
|
|
@@ -7984,7 +8161,7 @@ _store_array_formula(lxw_worksheet *self,
|
|
|
7984
8161
|
_insert_cell(self, first_row, first_col, cell);
|
|
7985
8162
|
|
|
7986
8163
|
if (is_dynamic)
|
|
7987
|
-
self->
|
|
8164
|
+
self->has_dynamic_functions = LXW_TRUE;
|
|
7988
8165
|
|
|
7989
8166
|
/* Pad out the rest of the area with formatted zeroes. */
|
|
7990
8167
|
if (!self->optimize) {
|
|
@@ -8159,7 +8336,12 @@ worksheet_write_datetime(lxw_worksheet *self,
|
|
|
8159
8336
|
if (err)
|
|
8160
8337
|
return err;
|
|
8161
8338
|
|
|
8162
|
-
|
|
8339
|
+
err = lxw_datetime_validate(datetime);
|
|
8340
|
+
if (err)
|
|
8341
|
+
return err;
|
|
8342
|
+
|
|
8343
|
+
excel_date =
|
|
8344
|
+
lxw_datetime_to_excel_date_with_epoch(datetime, self->use_1904_epoch);
|
|
8163
8345
|
|
|
8164
8346
|
cell = _new_number_cell(row_num, col_num, excel_date, format);
|
|
8165
8347
|
|
|
@@ -8185,7 +8367,8 @@ worksheet_write_unixtime(lxw_worksheet *self,
|
|
|
8185
8367
|
if (err)
|
|
8186
8368
|
return err;
|
|
8187
8369
|
|
|
8188
|
-
excel_date =
|
|
8370
|
+
excel_date =
|
|
8371
|
+
lxw_unixtime_to_excel_date_with_epoch(unixtime, self->use_1904_epoch);
|
|
8189
8372
|
|
|
8190
8373
|
cell = _new_number_cell(row_num, col_num, excel_date, format);
|
|
8191
8374
|
|
|
@@ -8362,9 +8545,13 @@ worksheet_write_url_opt(lxw_worksheet *self,
|
|
|
8362
8545
|
else
|
|
8363
8546
|
format = user_format;
|
|
8364
8547
|
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8548
|
+
if (!self->storing_embedded_image) {
|
|
8549
|
+
err =
|
|
8550
|
+
worksheet_write_string(self, row_num, col_num, string_copy,
|
|
8551
|
+
format);
|
|
8552
|
+
if (err)
|
|
8553
|
+
goto mem_error;
|
|
8554
|
+
}
|
|
8368
8555
|
|
|
8369
8556
|
/* Reset default error condition. */
|
|
8370
8557
|
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
@@ -8419,7 +8606,7 @@ worksheet_write_rich_string(lxw_worksheet *self,
|
|
|
8419
8606
|
int32_t string_id;
|
|
8420
8607
|
struct sst_element *sst_element;
|
|
8421
8608
|
lxw_error err;
|
|
8422
|
-
|
|
8609
|
+
size_t i;
|
|
8423
8610
|
long file_size;
|
|
8424
8611
|
char *rich_string = NULL;
|
|
8425
8612
|
const char *string_copy = NULL;
|
|
@@ -8570,6 +8757,9 @@ worksheet_write_comment_opt(lxw_worksheet *self,
|
|
|
8570
8757
|
if (!text)
|
|
8571
8758
|
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
8572
8759
|
|
|
8760
|
+
if (lxw_str_is_empty(text))
|
|
8761
|
+
return LXW_ERROR_PARAMETER_IS_EMPTY;
|
|
8762
|
+
|
|
8573
8763
|
if (lxw_utf8_strlen(text) > LXW_STR_MAX)
|
|
8574
8764
|
return LXW_ERROR_MAX_STRING_LENGTH_EXCEEDED;
|
|
8575
8765
|
|
|
@@ -9433,7 +9623,7 @@ worksheet_hide(lxw_worksheet *self)
|
|
|
9433
9623
|
/*
|
|
9434
9624
|
* Set which cell or cells are selected in a worksheet.
|
|
9435
9625
|
*/
|
|
9436
|
-
|
|
9626
|
+
lxw_error
|
|
9437
9627
|
worksheet_set_selection(lxw_worksheet *self,
|
|
9438
9628
|
lxw_row_t first_row, lxw_col_t first_col,
|
|
9439
9629
|
lxw_row_t last_row, lxw_col_t last_col)
|
|
@@ -9441,19 +9631,33 @@ worksheet_set_selection(lxw_worksheet *self,
|
|
|
9441
9631
|
lxw_selection *selection;
|
|
9442
9632
|
lxw_row_t tmp_row;
|
|
9443
9633
|
lxw_col_t tmp_col;
|
|
9634
|
+
lxw_error err;
|
|
9444
9635
|
char active_cell[LXW_MAX_CELL_RANGE_LENGTH];
|
|
9445
9636
|
char sqref[LXW_MAX_CELL_RANGE_LENGTH];
|
|
9446
9637
|
|
|
9447
9638
|
/* Only allow selection to be set once to avoid freeing/re-creating it. */
|
|
9448
9639
|
if (!STAILQ_EMPTY(self->selections))
|
|
9449
|
-
return;
|
|
9640
|
+
return LXW_ERROR_PARAMETER_VALIDATION;
|
|
9450
9641
|
|
|
9451
9642
|
/* Excel doesn't set a selection for cell A1 since it is the default. */
|
|
9452
9643
|
if (first_row == 0 && first_col == 0 && last_row == 0 && last_col == 0)
|
|
9453
|
-
return;
|
|
9644
|
+
return LXW_NO_ERROR;
|
|
9454
9645
|
|
|
9455
9646
|
selection = calloc(1, sizeof(lxw_selection));
|
|
9456
|
-
|
|
9647
|
+
RETURN_ON_MEM_ERROR(selection, LXW_ERROR_MEMORY_MALLOC_FAILED);
|
|
9648
|
+
|
|
9649
|
+
/* Check that row and col are valid without storing. */
|
|
9650
|
+
err = _check_dimensions(self, first_row, first_col, LXW_TRUE, LXW_TRUE);
|
|
9651
|
+
if (err) {
|
|
9652
|
+
free(selection);
|
|
9653
|
+
return err;
|
|
9654
|
+
}
|
|
9655
|
+
|
|
9656
|
+
err = _check_dimensions(self, last_row, last_col, LXW_TRUE, LXW_TRUE);
|
|
9657
|
+
if (err) {
|
|
9658
|
+
free(selection);
|
|
9659
|
+
return err;
|
|
9660
|
+
}
|
|
9457
9661
|
|
|
9458
9662
|
/* Set the cell range selection. Do this before swapping max/min to */
|
|
9459
9663
|
/* allow the selection direction to be reversed. */
|
|
@@ -9483,6 +9687,8 @@ worksheet_set_selection(lxw_worksheet *self,
|
|
|
9483
9687
|
lxw_strcpy(selection->sqref, sqref);
|
|
9484
9688
|
|
|
9485
9689
|
STAILQ_INSERT_TAIL(self->selections, selection, list_pointers);
|
|
9690
|
+
|
|
9691
|
+
return LXW_NO_ERROR;
|
|
9486
9692
|
}
|
|
9487
9693
|
|
|
9488
9694
|
/*
|
|
@@ -9591,6 +9797,12 @@ worksheet_set_page_view(lxw_worksheet *self)
|
|
|
9591
9797
|
void
|
|
9592
9798
|
worksheet_set_paper(lxw_worksheet *self, uint8_t paper_size)
|
|
9593
9799
|
{
|
|
9800
|
+
if (paper_size > 118) {
|
|
9801
|
+
LXW_WARN_FORMAT1("worksheet_set_paper(): invalid paper size: %d. "
|
|
9802
|
+
"Valid range is 0-118", paper_size);
|
|
9803
|
+
return;
|
|
9804
|
+
}
|
|
9805
|
+
|
|
9594
9806
|
self->paper_size = paper_size;
|
|
9595
9807
|
self->page_setup_changed = LXW_TRUE;
|
|
9596
9808
|
}
|
|
@@ -10094,7 +10306,7 @@ worksheet_print_black_and_white(lxw_worksheet *self)
|
|
|
10094
10306
|
lxw_error
|
|
10095
10307
|
worksheet_set_h_pagebreaks(lxw_worksheet *self, lxw_row_t hbreaks[])
|
|
10096
10308
|
{
|
|
10097
|
-
|
|
10309
|
+
size_t count = 0;
|
|
10098
10310
|
|
|
10099
10311
|
if (hbreaks == NULL)
|
|
10100
10312
|
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
@@ -10121,7 +10333,7 @@ worksheet_set_h_pagebreaks(lxw_worksheet *self, lxw_row_t hbreaks[])
|
|
|
10121
10333
|
lxw_error
|
|
10122
10334
|
worksheet_set_v_pagebreaks(lxw_worksheet *self, lxw_col_t vbreaks[])
|
|
10123
10335
|
{
|
|
10124
|
-
|
|
10336
|
+
size_t count = 0;
|
|
10125
10337
|
|
|
10126
10338
|
if (vbreaks == NULL)
|
|
10127
10339
|
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
@@ -10311,9 +10523,9 @@ worksheet_insert_image_opt(lxw_worksheet *self,
|
|
|
10311
10523
|
object_props->y_offset = user_options->y_offset;
|
|
10312
10524
|
object_props->x_scale = user_options->x_scale;
|
|
10313
10525
|
object_props->y_scale = user_options->y_scale;
|
|
10314
|
-
object_props->object_position = user_options->object_position;
|
|
10315
10526
|
object_props->url = lxw_strdup(user_options->url);
|
|
10316
10527
|
object_props->tip = lxw_strdup(user_options->tip);
|
|
10528
|
+
object_props->object_position = user_options->object_position;
|
|
10317
10529
|
object_props->decorative = user_options->decorative;
|
|
10318
10530
|
|
|
10319
10531
|
if (user_options->description)
|
|
@@ -10467,6 +10679,253 @@ worksheet_insert_image_buffer(lxw_worksheet *self,
|
|
|
10467
10679
|
image_buffer, image_size, NULL);
|
|
10468
10680
|
}
|
|
10469
10681
|
|
|
10682
|
+
/*
|
|
10683
|
+
* Embed an image with options into the worksheet.
|
|
10684
|
+
*/
|
|
10685
|
+
lxw_error
|
|
10686
|
+
worksheet_embed_image_opt(lxw_worksheet *self,
|
|
10687
|
+
lxw_row_t row_num, lxw_col_t col_num,
|
|
10688
|
+
const char *filename,
|
|
10689
|
+
lxw_image_options *user_options)
|
|
10690
|
+
{
|
|
10691
|
+
FILE *image_stream;
|
|
10692
|
+
lxw_object_properties *object_props;
|
|
10693
|
+
lxw_error err;
|
|
10694
|
+
|
|
10695
|
+
if (!filename) {
|
|
10696
|
+
LXW_WARN("worksheet_embed_image()/_opt(): "
|
|
10697
|
+
"filename must be specified.");
|
|
10698
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
10699
|
+
}
|
|
10700
|
+
|
|
10701
|
+
/* Check that the image file exists and can be opened. */
|
|
10702
|
+
image_stream = lxw_fopen(filename, "rb");
|
|
10703
|
+
if (!image_stream) {
|
|
10704
|
+
LXW_WARN_FORMAT1("worksheet_embed_image()/_opt(): "
|
|
10705
|
+
"file doesn't exist or can't be opened: %s.",
|
|
10706
|
+
filename);
|
|
10707
|
+
return LXW_ERROR_PARAMETER_VALIDATION;
|
|
10708
|
+
}
|
|
10709
|
+
|
|
10710
|
+
/* Check and store the cell dimensions. */
|
|
10711
|
+
err = _check_dimensions(self, row_num, col_num, LXW_FALSE, LXW_FALSE);
|
|
10712
|
+
if (err) {
|
|
10713
|
+
fclose(image_stream);
|
|
10714
|
+
return err;
|
|
10715
|
+
}
|
|
10716
|
+
|
|
10717
|
+
/* Create a new object to hold the image properties. */
|
|
10718
|
+
object_props = calloc(1, sizeof(lxw_object_properties));
|
|
10719
|
+
if (!object_props) {
|
|
10720
|
+
fclose(image_stream);
|
|
10721
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
10722
|
+
}
|
|
10723
|
+
|
|
10724
|
+
/* We only copy/use a limited number of options for embedded images. */
|
|
10725
|
+
if (user_options) {
|
|
10726
|
+
if (user_options->cell_format)
|
|
10727
|
+
object_props->format = user_options->cell_format;
|
|
10728
|
+
|
|
10729
|
+
/* The url for embedded images is written as a cell url. */
|
|
10730
|
+
if (user_options->url) {
|
|
10731
|
+
if (!user_options->cell_format)
|
|
10732
|
+
object_props->format = self->default_url_format;
|
|
10733
|
+
|
|
10734
|
+
self->storing_embedded_image = LXW_TRUE;
|
|
10735
|
+
err = worksheet_write_url(self,
|
|
10736
|
+
row_num,
|
|
10737
|
+
col_num,
|
|
10738
|
+
user_options->url,
|
|
10739
|
+
object_props->format);
|
|
10740
|
+
if (err) {
|
|
10741
|
+
_free_object_properties(object_props);
|
|
10742
|
+
fclose(image_stream);
|
|
10743
|
+
return err;
|
|
10744
|
+
}
|
|
10745
|
+
|
|
10746
|
+
self->storing_embedded_image = LXW_FALSE;
|
|
10747
|
+
}
|
|
10748
|
+
|
|
10749
|
+
object_props->decorative = user_options->decorative;
|
|
10750
|
+
if (user_options->description)
|
|
10751
|
+
object_props->description = lxw_strdup(user_options->description);
|
|
10752
|
+
}
|
|
10753
|
+
|
|
10754
|
+
/* Copy other options or set defaults. */
|
|
10755
|
+
object_props->filename = lxw_strdup(filename);
|
|
10756
|
+
object_props->stream = image_stream;
|
|
10757
|
+
object_props->row = row_num;
|
|
10758
|
+
object_props->col = col_num;
|
|
10759
|
+
|
|
10760
|
+
if (object_props->x_scale == 0.0)
|
|
10761
|
+
object_props->x_scale = 1;
|
|
10762
|
+
|
|
10763
|
+
if (object_props->y_scale == 0.0)
|
|
10764
|
+
object_props->y_scale = 1;
|
|
10765
|
+
|
|
10766
|
+
if (_get_image_properties(object_props) == LXW_NO_ERROR) {
|
|
10767
|
+
STAILQ_INSERT_TAIL(self->embedded_image_props, object_props,
|
|
10768
|
+
list_pointers);
|
|
10769
|
+
fclose(image_stream);
|
|
10770
|
+
|
|
10771
|
+
return LXW_NO_ERROR;
|
|
10772
|
+
}
|
|
10773
|
+
else {
|
|
10774
|
+
_free_object_properties(object_props);
|
|
10775
|
+
fclose(image_stream);
|
|
10776
|
+
return LXW_ERROR_IMAGE_DIMENSIONS;
|
|
10777
|
+
}
|
|
10778
|
+
}
|
|
10779
|
+
|
|
10780
|
+
/*
|
|
10781
|
+
* Embed an image into the worksheet.
|
|
10782
|
+
*/
|
|
10783
|
+
lxw_error
|
|
10784
|
+
worksheet_embed_image(lxw_worksheet *self,
|
|
10785
|
+
lxw_row_t row_num, lxw_col_t col_num,
|
|
10786
|
+
const char *filename)
|
|
10787
|
+
{
|
|
10788
|
+
return worksheet_embed_image_opt(self, row_num, col_num, filename, NULL);
|
|
10789
|
+
}
|
|
10790
|
+
|
|
10791
|
+
/*
|
|
10792
|
+
* Embed an image buffer, with options, into the worksheet.
|
|
10793
|
+
*/
|
|
10794
|
+
lxw_error
|
|
10795
|
+
worksheet_embed_image_buffer_opt(lxw_worksheet *self,
|
|
10796
|
+
lxw_row_t row_num,
|
|
10797
|
+
lxw_col_t col_num,
|
|
10798
|
+
const unsigned char *image_buffer,
|
|
10799
|
+
size_t image_size,
|
|
10800
|
+
lxw_image_options *user_options)
|
|
10801
|
+
{
|
|
10802
|
+
FILE *image_stream;
|
|
10803
|
+
lxw_object_properties *object_props;
|
|
10804
|
+
lxw_error err;
|
|
10805
|
+
|
|
10806
|
+
if (!image_size) {
|
|
10807
|
+
LXW_WARN("worksheet_embed_image_buffer()/_opt(): "
|
|
10808
|
+
"size must be non-zero.");
|
|
10809
|
+
return LXW_ERROR_NULL_PARAMETER_IGNORED;
|
|
10810
|
+
}
|
|
10811
|
+
|
|
10812
|
+
/* Write the image buffer to a file (preferably in memory) so we can read
|
|
10813
|
+
* the dimensions like an ordinary file. For embedded images we really only
|
|
10814
|
+
* need the image type. */
|
|
10815
|
+
#ifdef USE_FMEMOPEN
|
|
10816
|
+
image_stream = fmemopen((void *) image_buffer, image_size, "rb");
|
|
10817
|
+
|
|
10818
|
+
if (!image_stream)
|
|
10819
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
10820
|
+
#else
|
|
10821
|
+
image_stream = lxw_tmpfile(self->tmpdir);
|
|
10822
|
+
|
|
10823
|
+
if (!image_stream)
|
|
10824
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
10825
|
+
|
|
10826
|
+
if (fwrite(image_buffer, 1, image_size, image_stream) != image_size) {
|
|
10827
|
+
fclose(image_stream);
|
|
10828
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
10829
|
+
}
|
|
10830
|
+
|
|
10831
|
+
rewind(image_stream);
|
|
10832
|
+
#endif
|
|
10833
|
+
|
|
10834
|
+
/* Check and store the cell dimensions. */
|
|
10835
|
+
err = _check_dimensions(self, row_num, col_num, LXW_FALSE, LXW_FALSE);
|
|
10836
|
+
if (err)
|
|
10837
|
+
return err;
|
|
10838
|
+
|
|
10839
|
+
/* Create a new object to hold the image properties. */
|
|
10840
|
+
object_props = calloc(1, sizeof(lxw_object_properties));
|
|
10841
|
+
if (!object_props) {
|
|
10842
|
+
fclose(image_stream);
|
|
10843
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
10844
|
+
}
|
|
10845
|
+
|
|
10846
|
+
/* Store the image data in the properties structure. */
|
|
10847
|
+
object_props->image_buffer = calloc(1, image_size);
|
|
10848
|
+
if (!object_props->image_buffer) {
|
|
10849
|
+
_free_object_properties(object_props);
|
|
10850
|
+
fclose(image_stream);
|
|
10851
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
10852
|
+
}
|
|
10853
|
+
else {
|
|
10854
|
+
memcpy(object_props->image_buffer, image_buffer, image_size);
|
|
10855
|
+
object_props->image_buffer_size = image_size;
|
|
10856
|
+
object_props->is_image_buffer = LXW_TRUE;
|
|
10857
|
+
}
|
|
10858
|
+
|
|
10859
|
+
/* We only copy/use a limited number of options for embedded images. */
|
|
10860
|
+
if (user_options) {
|
|
10861
|
+
if (user_options->cell_format)
|
|
10862
|
+
object_props->format = user_options->cell_format;
|
|
10863
|
+
|
|
10864
|
+
/* The url for embedded images is written as a cell url. */
|
|
10865
|
+
if (user_options->url) {
|
|
10866
|
+
if (!user_options->cell_format)
|
|
10867
|
+
object_props->format = self->default_url_format;
|
|
10868
|
+
|
|
10869
|
+
self->storing_embedded_image = LXW_TRUE;
|
|
10870
|
+
err = worksheet_write_url(self,
|
|
10871
|
+
row_num,
|
|
10872
|
+
col_num,
|
|
10873
|
+
user_options->url,
|
|
10874
|
+
object_props->format);
|
|
10875
|
+
if (err) {
|
|
10876
|
+
_free_object_properties(object_props);
|
|
10877
|
+
fclose(image_stream);
|
|
10878
|
+
return err;
|
|
10879
|
+
}
|
|
10880
|
+
|
|
10881
|
+
self->storing_embedded_image = LXW_FALSE;
|
|
10882
|
+
}
|
|
10883
|
+
|
|
10884
|
+
object_props->decorative = user_options->decorative;
|
|
10885
|
+
if (user_options->description)
|
|
10886
|
+
object_props->description = lxw_strdup(user_options->description);
|
|
10887
|
+
}
|
|
10888
|
+
|
|
10889
|
+
/* Copy other options or set defaults. */
|
|
10890
|
+
object_props->filename = lxw_strdup("image_buffer");
|
|
10891
|
+
object_props->stream = image_stream;
|
|
10892
|
+
object_props->row = row_num;
|
|
10893
|
+
object_props->col = col_num;
|
|
10894
|
+
|
|
10895
|
+
if (object_props->x_scale == 0.0)
|
|
10896
|
+
object_props->x_scale = 1;
|
|
10897
|
+
|
|
10898
|
+
if (object_props->y_scale == 0.0)
|
|
10899
|
+
object_props->y_scale = 1;
|
|
10900
|
+
|
|
10901
|
+
if (_get_image_properties(object_props) == LXW_NO_ERROR) {
|
|
10902
|
+
STAILQ_INSERT_TAIL(self->embedded_image_props, object_props,
|
|
10903
|
+
list_pointers);
|
|
10904
|
+
fclose(image_stream);
|
|
10905
|
+
|
|
10906
|
+
return LXW_NO_ERROR;
|
|
10907
|
+
}
|
|
10908
|
+
else {
|
|
10909
|
+
_free_object_properties(object_props);
|
|
10910
|
+
fclose(image_stream);
|
|
10911
|
+
return LXW_ERROR_IMAGE_DIMENSIONS;
|
|
10912
|
+
}
|
|
10913
|
+
}
|
|
10914
|
+
|
|
10915
|
+
/*
|
|
10916
|
+
* Insert an image buffer into the worksheet.
|
|
10917
|
+
*/
|
|
10918
|
+
lxw_error
|
|
10919
|
+
worksheet_embed_image_buffer(lxw_worksheet *self,
|
|
10920
|
+
lxw_row_t row_num,
|
|
10921
|
+
lxw_col_t col_num,
|
|
10922
|
+
const unsigned char *image_buffer,
|
|
10923
|
+
size_t image_size)
|
|
10924
|
+
{
|
|
10925
|
+
return worksheet_embed_image_buffer_opt(self, row_num, col_num,
|
|
10926
|
+
image_buffer, image_size, NULL);
|
|
10927
|
+
}
|
|
10928
|
+
|
|
10470
10929
|
/*
|
|
10471
10930
|
* Set an image as a worksheet background.
|
|
10472
10931
|
*/
|
|
@@ -10921,16 +11380,16 @@ worksheet_data_validation_range(lxw_worksheet *self, lxw_row_t first_row,
|
|
|
10921
11380
|
|| validation->validate == LXW_VALIDATION_TYPE_TIME) {
|
|
10922
11381
|
if (is_between) {
|
|
10923
11382
|
copy->value_number =
|
|
10924
|
-
|
|
10925
|
-
(&validation->minimum_datetime,
|
|
11383
|
+
lxw_datetime_to_excel_date_with_epoch
|
|
11384
|
+
(&validation->minimum_datetime, self->use_1904_epoch);
|
|
10926
11385
|
copy->maximum_number =
|
|
10927
|
-
|
|
10928
|
-
(&validation->maximum_datetime,
|
|
11386
|
+
lxw_datetime_to_excel_date_with_epoch
|
|
11387
|
+
(&validation->maximum_datetime, self->use_1904_epoch);
|
|
10929
11388
|
}
|
|
10930
11389
|
else {
|
|
10931
11390
|
copy->value_number =
|
|
10932
|
-
|
|
10933
|
-
|
|
11391
|
+
lxw_datetime_to_excel_date_with_epoch
|
|
11392
|
+
(&validation->value_datetime, self->use_1904_epoch);
|
|
10934
11393
|
}
|
|
10935
11394
|
}
|
|
10936
11395
|
|
|
@@ -11064,6 +11523,11 @@ worksheet_conditional_format_range(lxw_worksheet *self, lxw_row_t first_row,
|
|
|
11064
11523
|
cond_format->stop_if_true = user_options->stop_if_true;
|
|
11065
11524
|
cond_format->type_string = lxw_strdup(type_strings[cond_format->type]);
|
|
11066
11525
|
|
|
11526
|
+
/* Check that the criteria matches the conditional type. */
|
|
11527
|
+
err = _validate_conditional_criteria(cond_format);
|
|
11528
|
+
if (err)
|
|
11529
|
+
goto error;
|
|
11530
|
+
|
|
11067
11531
|
/* Validate the user input for various types of rules. */
|
|
11068
11532
|
if (user_options->type == LXW_CONDITIONAL_TYPE_CELL
|
|
11069
11533
|
|| cond_format->type == LXW_CONDITIONAL_TYPE_DUPLICATE
|
|
@@ -11292,3 +11756,19 @@ worksheet_ignore_errors(lxw_worksheet *self, uint8_t type, const char *range)
|
|
|
11292
11756
|
|
|
11293
11757
|
return LXW_NO_ERROR;
|
|
11294
11758
|
}
|
|
11759
|
+
|
|
11760
|
+
/*
|
|
11761
|
+
* Write an error cell for versions of Excel that don't support embedded images.
|
|
11762
|
+
*/
|
|
11763
|
+
void
|
|
11764
|
+
worksheet_set_error_cell(lxw_worksheet *self,
|
|
11765
|
+
lxw_object_properties *object_props, uint32_t ref_id)
|
|
11766
|
+
{
|
|
11767
|
+
lxw_row_t row_num = object_props->row;
|
|
11768
|
+
lxw_col_t col_num = object_props->col;
|
|
11769
|
+
|
|
11770
|
+
lxw_cell *cell =
|
|
11771
|
+
_new_error_cell(row_num, col_num, ref_id, object_props->format);
|
|
11772
|
+
_insert_cell(self, row_num, col_num, cell);
|
|
11773
|
+
|
|
11774
|
+
}
|