fast_excel 0.4.1 → 0.5.0
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 +1 -7
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -1
- data/examples/example.rb +2 -0
- data/examples/example_date_time.rb +38 -0
- data/fast_excel.gemspec +2 -2
- data/lib/fast_excel/binding/format.rb +17 -0
- data/lib/fast_excel/binding/workbook.rb +39 -17
- data/lib/fast_excel/binding/worksheet.rb +57 -13
- data/lib/fast_excel/binding.rb +7 -7
- data/lib/fast_excel.rb +27 -20
- data/libxlsxwriter/.github/FUNDING.yml +1 -0
- data/libxlsxwriter/.github/ISSUE_TEMPLATE.md +85 -0
- data/libxlsxwriter/.github/PULL_REQUEST_TEMPLATE.md +130 -0
- data/libxlsxwriter/.github/workflows/cmake_actions.yml +48 -0
- data/libxlsxwriter/.github/workflows/code_style.yml +23 -0
- data/libxlsxwriter/.github/workflows/coverity.yml +22 -0
- data/libxlsxwriter/.github/workflows/make_actions.yml +52 -0
- data/libxlsxwriter/.github/workflows/valgrind.yml +23 -0
- data/libxlsxwriter/.github/workflows/windows_build.yml +54 -0
- data/libxlsxwriter/.github/workflows/zig_build.yml +22 -0
- data/libxlsxwriter/.gitignore +16 -1
- data/libxlsxwriter/.indent.pro +24 -0
- data/libxlsxwriter/CMakeLists.txt +156 -56
- data/libxlsxwriter/CONTRIBUTING.md +2 -2
- data/libxlsxwriter/Changes.txt +344 -2
- data/libxlsxwriter/LICENSE.txt +66 -8
- data/libxlsxwriter/Makefile +151 -54
- data/libxlsxwriter/Package.swift +42 -0
- data/libxlsxwriter/Readme.md +4 -2
- data/libxlsxwriter/build.zig +324 -0
- data/libxlsxwriter/build.zig.zon +11 -0
- data/libxlsxwriter/cmake/FindMINIZIP.cmake +3 -3
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +6 -0
- data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/chart.h +236 -32
- data/libxlsxwriter/include/xlsxwriter/chartsheet.h +7 -7
- data/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
- data/libxlsxwriter/include/xlsxwriter/common.h +111 -50
- data/libxlsxwriter/include/xlsxwriter/content_types.h +8 -1
- data/libxlsxwriter/include/xlsxwriter/core.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/drawing.h +11 -20
- data/libxlsxwriter/include/xlsxwriter/format.h +121 -8
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/metadata.h +49 -0
- data/libxlsxwriter/include/xlsxwriter/packager.h +27 -16
- data/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/styles.h +13 -7
- data/libxlsxwriter/include/xlsxwriter/table.h +51 -0
- data/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
- data/libxlsxwriter/include/xlsxwriter/third_party/emyg_dtoa.h +26 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +27 -25
- data/libxlsxwriter/include/xlsxwriter/third_party/md5.h +45 -0
- data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +155 -153
- data/libxlsxwriter/include/xlsxwriter/utility.h +70 -8
- data/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
- data/libxlsxwriter/include/xlsxwriter/workbook.h +218 -47
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +2770 -241
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +12 -8
- data/libxlsxwriter/include/xlsxwriter.h +4 -2
- data/libxlsxwriter/libxlsxwriter.podspec +8 -5
- data/libxlsxwriter/src/Makefile +58 -21
- data/libxlsxwriter/src/app.c +5 -2
- data/libxlsxwriter/src/chart.c +396 -81
- data/libxlsxwriter/src/chartsheet.c +22 -22
- data/libxlsxwriter/src/comment.c +443 -0
- data/libxlsxwriter/src/content_types.c +40 -1
- data/libxlsxwriter/src/core.c +2 -2
- data/libxlsxwriter/src/custom.c +1 -1
- data/libxlsxwriter/src/drawing.c +160 -40
- data/libxlsxwriter/src/format.c +109 -25
- data/libxlsxwriter/src/hash_table.c +1 -1
- data/libxlsxwriter/src/metadata.c +283 -0
- data/libxlsxwriter/src/packager.c +794 -94
- data/libxlsxwriter/src/relationships.c +1 -1
- data/libxlsxwriter/src/shared_strings.c +2 -4
- data/libxlsxwriter/src/styles.c +353 -58
- data/libxlsxwriter/src/table.c +304 -0
- data/libxlsxwriter/src/theme.c +1 -1
- data/libxlsxwriter/src/utility.c +143 -43
- data/libxlsxwriter/src/vml.c +1062 -0
- data/libxlsxwriter/src/workbook.c +567 -77
- data/libxlsxwriter/src/worksheet.c +6668 -1462
- data/libxlsxwriter/src/xmlwriter.c +95 -5
- data/libxlsxwriter/third_party/dtoa/Makefile +42 -0
- data/libxlsxwriter/third_party/dtoa/emyg_dtoa.c +461 -0
- data/libxlsxwriter/third_party/dtoa/emyg_dtoa.h +26 -0
- data/libxlsxwriter/third_party/md5/Makefile +42 -0
- data/libxlsxwriter/third_party/md5/md5.c +291 -0
- data/libxlsxwriter/third_party/md5/md5.h +45 -0
- data/libxlsxwriter/third_party/minizip/Makefile +3 -8
- data/libxlsxwriter/third_party/minizip/Makefile.orig +8 -4
- data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +1 -1
- data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
- data/libxlsxwriter/third_party/minizip/crypt.h +13 -16
- data/libxlsxwriter/third_party/minizip/ioapi.c +31 -57
- data/libxlsxwriter/third_party/minizip/ioapi.h +31 -23
- data/libxlsxwriter/third_party/minizip/iowin32.c +29 -45
- data/libxlsxwriter/third_party/minizip/iowin32.h +4 -4
- data/libxlsxwriter/third_party/minizip/miniunz.c +29 -56
- data/libxlsxwriter/third_party/minizip/minizip.c +38 -49
- data/libxlsxwriter/third_party/minizip/mztools.c +1 -7
- data/libxlsxwriter/third_party/minizip/unzip.c +202 -342
- data/libxlsxwriter/third_party/minizip/unzip.h +74 -74
- data/libxlsxwriter/third_party/minizip/zip.c +165 -218
- data/libxlsxwriter/third_party/minizip/zip.h +164 -154
- data/libxlsxwriter/third_party/tmpfileplus/Makefile +3 -3
- data/libxlsxwriter/version.txt +1 -1
- data/test/auto_width_test.rb +20 -0
- data/test/default_format_test.rb +1 -1
- data/test/validations_test.rb +3 -3
- data/test/worksheet_test.rb +6 -1
- metadata +33 -7
- data/libxlsxwriter/.travis.yml +0 -37
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/*****************************************************************************
|
|
2
|
+
* table - A library for creating Excel XLSX table files.
|
|
3
|
+
*
|
|
4
|
+
* Used in conjunction with the libxlsxwriter library.
|
|
5
|
+
*
|
|
6
|
+
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#include "xlsxwriter/xmlwriter.h"
|
|
11
|
+
#include "xlsxwriter/worksheet.h"
|
|
12
|
+
#include "xlsxwriter/table.h"
|
|
13
|
+
#include "xlsxwriter/utility.h"
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* Forward declarations.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/*****************************************************************************
|
|
20
|
+
*
|
|
21
|
+
* Private functions.
|
|
22
|
+
*
|
|
23
|
+
****************************************************************************/
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* Create a new table object.
|
|
27
|
+
*/
|
|
28
|
+
lxw_table *
|
|
29
|
+
lxw_table_new(void)
|
|
30
|
+
{
|
|
31
|
+
lxw_table *table = calloc(1, sizeof(lxw_table));
|
|
32
|
+
GOTO_LABEL_ON_MEM_ERROR(table, mem_error);
|
|
33
|
+
|
|
34
|
+
return table;
|
|
35
|
+
|
|
36
|
+
mem_error:
|
|
37
|
+
lxw_table_free(table);
|
|
38
|
+
return NULL;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* Free a table object.
|
|
43
|
+
*/
|
|
44
|
+
void
|
|
45
|
+
lxw_table_free(lxw_table *table)
|
|
46
|
+
{
|
|
47
|
+
if (!table)
|
|
48
|
+
return;
|
|
49
|
+
|
|
50
|
+
free(table);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/*****************************************************************************
|
|
54
|
+
*
|
|
55
|
+
* XML functions.
|
|
56
|
+
*
|
|
57
|
+
****************************************************************************/
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
* Write the XML declaration.
|
|
61
|
+
*/
|
|
62
|
+
STATIC void
|
|
63
|
+
_table_xml_declaration(lxw_table *self)
|
|
64
|
+
{
|
|
65
|
+
lxw_xml_declaration(self->file);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* Write the <table> element.
|
|
70
|
+
*/
|
|
71
|
+
STATIC void
|
|
72
|
+
_table_write_table(lxw_table *self)
|
|
73
|
+
{
|
|
74
|
+
struct xml_attribute_list attributes;
|
|
75
|
+
struct xml_attribute *attribute;
|
|
76
|
+
char xmlns[] =
|
|
77
|
+
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
|
|
78
|
+
lxw_table_obj *table_obj = self->table_obj;
|
|
79
|
+
|
|
80
|
+
LXW_INIT_ATTRIBUTES();
|
|
81
|
+
|
|
82
|
+
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
|
|
83
|
+
LXW_PUSH_ATTRIBUTES_INT("id", table_obj->id);
|
|
84
|
+
|
|
85
|
+
if (table_obj->name)
|
|
86
|
+
LXW_PUSH_ATTRIBUTES_STR("name", table_obj->name);
|
|
87
|
+
else
|
|
88
|
+
LXW_PUSH_ATTRIBUTES_STR("name", "Table1");
|
|
89
|
+
|
|
90
|
+
if (table_obj->name)
|
|
91
|
+
LXW_PUSH_ATTRIBUTES_STR("displayName", table_obj->name);
|
|
92
|
+
else
|
|
93
|
+
LXW_PUSH_ATTRIBUTES_STR("displayName", "Table1");
|
|
94
|
+
|
|
95
|
+
LXW_PUSH_ATTRIBUTES_STR("ref", table_obj->sqref);
|
|
96
|
+
|
|
97
|
+
if (table_obj->no_header_row)
|
|
98
|
+
LXW_PUSH_ATTRIBUTES_STR("headerRowCount", "0");
|
|
99
|
+
|
|
100
|
+
if (table_obj->total_row)
|
|
101
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowCount", "1");
|
|
102
|
+
else
|
|
103
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowShown", "0");
|
|
104
|
+
|
|
105
|
+
lxw_xml_start_tag(self->file, "table", &attributes);
|
|
106
|
+
|
|
107
|
+
LXW_FREE_ATTRIBUTES();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* Write the <autoFilter> element.
|
|
112
|
+
*/
|
|
113
|
+
STATIC void
|
|
114
|
+
_table_write_auto_filter(lxw_table *self)
|
|
115
|
+
{
|
|
116
|
+
struct xml_attribute_list attributes;
|
|
117
|
+
struct xml_attribute *attribute;
|
|
118
|
+
|
|
119
|
+
if (self->table_obj->no_autofilter)
|
|
120
|
+
return;
|
|
121
|
+
|
|
122
|
+
LXW_INIT_ATTRIBUTES();
|
|
123
|
+
LXW_PUSH_ATTRIBUTES_STR("ref", self->table_obj->filter_sqref);
|
|
124
|
+
|
|
125
|
+
lxw_xml_empty_tag(self->file, "autoFilter", &attributes);
|
|
126
|
+
|
|
127
|
+
LXW_FREE_ATTRIBUTES();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/*
|
|
131
|
+
* Write the <tableColumn> element.
|
|
132
|
+
*/
|
|
133
|
+
STATIC void
|
|
134
|
+
_table_write_table_column(lxw_table *self, uint16_t id,
|
|
135
|
+
lxw_table_column *column)
|
|
136
|
+
{
|
|
137
|
+
struct xml_attribute_list attributes;
|
|
138
|
+
struct xml_attribute *attribute;
|
|
139
|
+
int32_t dfx_id;
|
|
140
|
+
|
|
141
|
+
LXW_INIT_ATTRIBUTES();
|
|
142
|
+
LXW_PUSH_ATTRIBUTES_INT("id", id);
|
|
143
|
+
|
|
144
|
+
LXW_PUSH_ATTRIBUTES_STR("name", column->header);
|
|
145
|
+
|
|
146
|
+
if (column->total_string) {
|
|
147
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowLabel", column->total_string);
|
|
148
|
+
}
|
|
149
|
+
else if (column->total_function) {
|
|
150
|
+
if (column->total_function == LXW_TABLE_FUNCTION_AVERAGE)
|
|
151
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "average");
|
|
152
|
+
if (column->total_function == LXW_TABLE_FUNCTION_COUNT_NUMS)
|
|
153
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "countNums");
|
|
154
|
+
if (column->total_function == LXW_TABLE_FUNCTION_COUNT)
|
|
155
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "count");
|
|
156
|
+
if (column->total_function == LXW_TABLE_FUNCTION_MAX)
|
|
157
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "max");
|
|
158
|
+
if (column->total_function == LXW_TABLE_FUNCTION_MIN)
|
|
159
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "min");
|
|
160
|
+
if (column->total_function == LXW_TABLE_FUNCTION_STD_DEV)
|
|
161
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "stdDev");
|
|
162
|
+
if (column->total_function == LXW_TABLE_FUNCTION_SUM)
|
|
163
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "sum");
|
|
164
|
+
if (column->total_function == LXW_TABLE_FUNCTION_VAR)
|
|
165
|
+
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "var");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (column->format) {
|
|
169
|
+
dfx_id = lxw_format_get_dxf_index(column->format);
|
|
170
|
+
LXW_PUSH_ATTRIBUTES_INT("dataDxfId", dfx_id);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (column->formula) {
|
|
174
|
+
lxw_xml_start_tag(self->file, "tableColumn", &attributes);
|
|
175
|
+
lxw_xml_data_element(self->file, "calculatedColumnFormula",
|
|
176
|
+
column->formula, NULL);
|
|
177
|
+
lxw_xml_end_tag(self->file, "tableColumn");
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
lxw_xml_empty_tag(self->file, "tableColumn", &attributes);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
LXW_FREE_ATTRIBUTES();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* Write the <tableColumns> element.
|
|
188
|
+
*/
|
|
189
|
+
STATIC void
|
|
190
|
+
_table_write_table_columns(lxw_table *self)
|
|
191
|
+
{
|
|
192
|
+
struct xml_attribute_list attributes;
|
|
193
|
+
struct xml_attribute *attribute;
|
|
194
|
+
uint16_t i;
|
|
195
|
+
uint16_t num_cols = self->table_obj->num_cols;
|
|
196
|
+
lxw_table_column **columns = self->table_obj->columns;
|
|
197
|
+
|
|
198
|
+
LXW_INIT_ATTRIBUTES();
|
|
199
|
+
LXW_PUSH_ATTRIBUTES_INT("count", num_cols);
|
|
200
|
+
|
|
201
|
+
lxw_xml_start_tag(self->file, "tableColumns", &attributes);
|
|
202
|
+
|
|
203
|
+
for (i = 0; i < num_cols; i++)
|
|
204
|
+
_table_write_table_column(self, i + 1, columns[i]);
|
|
205
|
+
|
|
206
|
+
lxw_xml_end_tag(self->file, "tableColumns");
|
|
207
|
+
|
|
208
|
+
LXW_FREE_ATTRIBUTES();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/*
|
|
212
|
+
* Write the <tableStyleInfo> element.
|
|
213
|
+
*/
|
|
214
|
+
STATIC void
|
|
215
|
+
_table_write_table_style_info(lxw_table *self)
|
|
216
|
+
{
|
|
217
|
+
struct xml_attribute_list attributes;
|
|
218
|
+
struct xml_attribute *attribute;
|
|
219
|
+
char name[LXW_ATTR_32];
|
|
220
|
+
lxw_table_obj *table_obj = self->table_obj;
|
|
221
|
+
|
|
222
|
+
LXW_INIT_ATTRIBUTES();
|
|
223
|
+
|
|
224
|
+
if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_LIGHT) {
|
|
225
|
+
if (table_obj->style_type_number != 0) {
|
|
226
|
+
lxw_snprintf(name, LXW_ATTR_32, "TableStyleLight%d",
|
|
227
|
+
table_obj->style_type_number);
|
|
228
|
+
LXW_PUSH_ATTRIBUTES_STR("name", name);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_MEDIUM) {
|
|
232
|
+
lxw_snprintf(name, LXW_ATTR_32, "TableStyleMedium%d",
|
|
233
|
+
table_obj->style_type_number);
|
|
234
|
+
LXW_PUSH_ATTRIBUTES_STR("name", name);
|
|
235
|
+
}
|
|
236
|
+
else if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_DARK) {
|
|
237
|
+
lxw_snprintf(name, LXW_ATTR_32, "TableStyleDark%d",
|
|
238
|
+
table_obj->style_type_number);
|
|
239
|
+
LXW_PUSH_ATTRIBUTES_STR("name", name);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
LXW_PUSH_ATTRIBUTES_STR("name", "TableStyleMedium9");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (table_obj->first_column)
|
|
246
|
+
LXW_PUSH_ATTRIBUTES_STR("showFirstColumn", "1");
|
|
247
|
+
else
|
|
248
|
+
LXW_PUSH_ATTRIBUTES_STR("showFirstColumn", "0");
|
|
249
|
+
|
|
250
|
+
if (table_obj->last_column)
|
|
251
|
+
LXW_PUSH_ATTRIBUTES_STR("showLastColumn", "1");
|
|
252
|
+
else
|
|
253
|
+
LXW_PUSH_ATTRIBUTES_STR("showLastColumn", "0");
|
|
254
|
+
|
|
255
|
+
if (table_obj->no_banded_rows)
|
|
256
|
+
LXW_PUSH_ATTRIBUTES_STR("showRowStripes", "0");
|
|
257
|
+
else
|
|
258
|
+
LXW_PUSH_ATTRIBUTES_STR("showRowStripes", "1");
|
|
259
|
+
|
|
260
|
+
if (table_obj->banded_columns)
|
|
261
|
+
LXW_PUSH_ATTRIBUTES_STR("showColumnStripes", "1");
|
|
262
|
+
else
|
|
263
|
+
LXW_PUSH_ATTRIBUTES_STR("showColumnStripes", "0");
|
|
264
|
+
|
|
265
|
+
lxw_xml_empty_tag(self->file, "tableStyleInfo", &attributes);
|
|
266
|
+
|
|
267
|
+
LXW_FREE_ATTRIBUTES();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/*****************************************************************************
|
|
271
|
+
*
|
|
272
|
+
* XML file assembly functions.
|
|
273
|
+
*
|
|
274
|
+
****************************************************************************/
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
* Assemble and write the XML file.
|
|
278
|
+
*/
|
|
279
|
+
void
|
|
280
|
+
lxw_table_assemble_xml_file(lxw_table *self)
|
|
281
|
+
{
|
|
282
|
+
/* Write the XML declaration. */
|
|
283
|
+
_table_xml_declaration(self);
|
|
284
|
+
|
|
285
|
+
/* Write the table element. */
|
|
286
|
+
_table_write_table(self);
|
|
287
|
+
|
|
288
|
+
/* Write the autoFilter element. */
|
|
289
|
+
_table_write_auto_filter(self);
|
|
290
|
+
|
|
291
|
+
/* Write the tableColumns element. */
|
|
292
|
+
_table_write_table_columns(self);
|
|
293
|
+
|
|
294
|
+
/* Write the tableStyleInfo element. */
|
|
295
|
+
_table_write_table_style_info(self);
|
|
296
|
+
|
|
297
|
+
lxw_xml_end_tag(self->file, "table");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/*****************************************************************************
|
|
301
|
+
*
|
|
302
|
+
* Public functions.
|
|
303
|
+
*
|
|
304
|
+
****************************************************************************/
|
data/libxlsxwriter/src/theme.c
CHANGED
data/libxlsxwriter/src/utility.c
CHANGED
|
@@ -3,18 +3,27 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2014-
|
|
6
|
+
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
#ifdef USE_FMEMOPEN
|
|
11
|
+
#define _POSIX_C_SOURCE 200809L
|
|
12
|
+
#endif
|
|
13
|
+
|
|
10
14
|
#include <ctype.h>
|
|
11
15
|
#include <stdio.h>
|
|
12
16
|
#include <string.h>
|
|
13
17
|
#include <stdint.h>
|
|
14
18
|
#include <stdlib.h>
|
|
15
19
|
#include "xlsxwriter.h"
|
|
20
|
+
#include "xlsxwriter/common.h"
|
|
16
21
|
#include "xlsxwriter/third_party/tmpfileplus.h"
|
|
17
22
|
|
|
23
|
+
#ifdef USE_DTOA_LIBRARY
|
|
24
|
+
#include "xlsxwriter/third_party/emyg_dtoa.h"
|
|
25
|
+
#endif
|
|
26
|
+
|
|
18
27
|
char *error_strings[LXW_MAX_ERRNO + 1] = {
|
|
19
28
|
"No error.",
|
|
20
29
|
"Memory error, failed to malloc() required memory.",
|
|
@@ -27,19 +36,20 @@ char *error_strings[LXW_MAX_ERRNO + 1] = {
|
|
|
27
36
|
"Zip error ZIP_INTERNALERROR while creating the xlsx file.",
|
|
28
37
|
"File error or unknown zip error when adding sub file to xlsx file.",
|
|
29
38
|
"Unknown zip error when closing xlsx file.",
|
|
39
|
+
"Feature is not currently supported in this configuration.",
|
|
30
40
|
"NULL function parameter ignored.",
|
|
31
41
|
"Function parameter validation error.",
|
|
32
42
|
"Worksheet name exceeds Excel's limit of 31 characters.",
|
|
33
43
|
"Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'",
|
|
34
44
|
"Worksheet name cannot start or end with an apostrophe.",
|
|
35
45
|
"Worksheet name is already in use.",
|
|
36
|
-
"Worksheet name 'History' is reserved by Excel.",
|
|
37
46
|
"Parameter exceeds Excel's limit of 32 characters.",
|
|
38
47
|
"Parameter exceeds Excel's limit of 128 characters.",
|
|
39
48
|
"Parameter exceeds Excel's limit of 255 characters.",
|
|
40
49
|
"String exceeds Excel's limit of 32,767 characters.",
|
|
41
50
|
"Error finding internal string index.",
|
|
42
51
|
"Worksheet row or column index out of range.",
|
|
52
|
+
"Maximum hyperlink length (2079) exceeded.",
|
|
43
53
|
"Maximum number of worksheet URLs (65530) exceeded.",
|
|
44
54
|
"Couldn't read image dimensions or DPI.",
|
|
45
55
|
"Unknown error number."
|
|
@@ -62,7 +72,7 @@ lxw_col_to_name(char *col_name, lxw_col_t col_num, uint8_t absolute)
|
|
|
62
72
|
{
|
|
63
73
|
uint8_t pos = 0;
|
|
64
74
|
size_t len;
|
|
65
|
-
|
|
75
|
+
size_t i;
|
|
66
76
|
|
|
67
77
|
/* Change from 0 index to 1 index. */
|
|
68
78
|
col_num++;
|
|
@@ -312,10 +322,11 @@ lxw_name_to_col_2(const char *col_str)
|
|
|
312
322
|
}
|
|
313
323
|
|
|
314
324
|
/*
|
|
315
|
-
* Convert a lxw_datetime struct to an Excel serial date
|
|
325
|
+
* Convert a lxw_datetime struct to an Excel serial date, with a 1900
|
|
326
|
+
* or 1904 epoch.
|
|
316
327
|
*/
|
|
317
328
|
double
|
|
318
|
-
|
|
329
|
+
lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
|
|
319
330
|
{
|
|
320
331
|
int year = datetime->year;
|
|
321
332
|
int month = datetime->month;
|
|
@@ -392,7 +403,7 @@ lxw_datetime_to_excel_date(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
392
403
|
/* Add days for all previous years. */
|
|
393
404
|
days += range * 365;
|
|
394
405
|
/* Add 4 year leapdays. */
|
|
395
|
-
days +=
|
|
406
|
+
days += range / 4;
|
|
396
407
|
/* Remove 100 year leapdays. */
|
|
397
408
|
days -= (range + offset) / 100;
|
|
398
409
|
/* Add 400 year leapdays. */
|
|
@@ -407,6 +418,43 @@ lxw_datetime_to_excel_date(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
407
418
|
return days + seconds;
|
|
408
419
|
}
|
|
409
420
|
|
|
421
|
+
/*
|
|
422
|
+
* Convert a lxw_datetime struct to an Excel serial date, for the 1900 epoch.
|
|
423
|
+
*/
|
|
424
|
+
double
|
|
425
|
+
lxw_datetime_to_excel_datetime(lxw_datetime *datetime)
|
|
426
|
+
{
|
|
427
|
+
return lxw_datetime_to_excel_date_epoch(datetime, LXW_FALSE);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/*
|
|
431
|
+
* Convert a unix datetime (1970/01/01 epoch) to an Excel serial date, with a
|
|
432
|
+
* 1900 epoch.
|
|
433
|
+
*/
|
|
434
|
+
double
|
|
435
|
+
lxw_unixtime_to_excel_date(int64_t unixtime)
|
|
436
|
+
{
|
|
437
|
+
return lxw_unixtime_to_excel_date_epoch(unixtime, LXW_FALSE);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/*
|
|
441
|
+
* Convert a unix datetime (1970/01/01 epoch) to an Excel serial date, with a
|
|
442
|
+
* 1900 or 1904 epoch.
|
|
443
|
+
*/
|
|
444
|
+
double
|
|
445
|
+
lxw_unixtime_to_excel_date_epoch(int64_t unixtime, uint8_t date_1904)
|
|
446
|
+
{
|
|
447
|
+
double excel_datetime = 0.0;
|
|
448
|
+
double epoch = date_1904 ? 24107.0 : 25568.0;
|
|
449
|
+
|
|
450
|
+
excel_datetime = epoch + (unixtime / (24 * 60 * 60.0));
|
|
451
|
+
|
|
452
|
+
if (!date_1904 && excel_datetime >= 60.0)
|
|
453
|
+
excel_datetime = excel_datetime + 1.0;
|
|
454
|
+
|
|
455
|
+
return excel_datetime;
|
|
456
|
+
}
|
|
457
|
+
|
|
410
458
|
/* Simple strdup() implementation since it isn't ANSI C. */
|
|
411
459
|
char *
|
|
412
460
|
lxw_strdup(const char *str)
|
|
@@ -524,7 +572,7 @@ lxw_quote_sheetname(const char *str)
|
|
|
524
572
|
* version if required for safety or portability.
|
|
525
573
|
*/
|
|
526
574
|
FILE *
|
|
527
|
-
lxw_tmpfile(char *tmpdir)
|
|
575
|
+
lxw_tmpfile(const char *tmpdir)
|
|
528
576
|
{
|
|
529
577
|
#ifndef USE_STANDARD_TMPFILE
|
|
530
578
|
return tmpfileplus(tmpdir, NULL, NULL, 0);
|
|
@@ -534,34 +582,40 @@ lxw_tmpfile(char *tmpdir)
|
|
|
534
582
|
#endif
|
|
535
583
|
}
|
|
536
584
|
|
|
585
|
+
/**
|
|
586
|
+
* Return a memory-backed file if supported, otherwise a temporary one
|
|
587
|
+
*/
|
|
588
|
+
FILE *
|
|
589
|
+
lxw_get_filehandle(char **buf, size_t *size, const char *tmpdir)
|
|
590
|
+
{
|
|
591
|
+
static size_t s;
|
|
592
|
+
if (!size)
|
|
593
|
+
size = &s;
|
|
594
|
+
*buf = NULL;
|
|
595
|
+
*size = 0;
|
|
596
|
+
#ifdef USE_FMEMOPEN
|
|
597
|
+
(void) tmpdir;
|
|
598
|
+
return open_memstream(buf, size);
|
|
599
|
+
#else
|
|
600
|
+
return lxw_tmpfile(tmpdir);
|
|
601
|
+
#endif
|
|
602
|
+
}
|
|
603
|
+
|
|
537
604
|
/*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
* a function of the same name.
|
|
541
|
-
*
|
|
542
|
-
* The code below is a simplified example that changes numbers like 123,45 to
|
|
543
|
-
* 123.45. End-users can replace this with something more rigorous if
|
|
544
|
-
* required.
|
|
605
|
+
* Use third party function to handle sprintf of doubles for locale portable
|
|
606
|
+
* code.
|
|
545
607
|
*/
|
|
546
|
-
#ifdef
|
|
608
|
+
#ifdef USE_DTOA_LIBRARY
|
|
547
609
|
int
|
|
548
610
|
lxw_sprintf_dbl(char *data, double number)
|
|
549
611
|
{
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
lxw_snprintf(data, LXW_ATTR_32, "%.16g", number);
|
|
553
|
-
|
|
554
|
-
/* Replace comma with decimal point. */
|
|
555
|
-
tmp = strchr(data, ',');
|
|
556
|
-
if (tmp)
|
|
557
|
-
*tmp = '.';
|
|
558
|
-
|
|
612
|
+
emyg_dtoa(number, data);
|
|
559
613
|
return 0;
|
|
560
614
|
}
|
|
561
615
|
#endif
|
|
562
616
|
|
|
563
617
|
/*
|
|
564
|
-
* Retrieve runtime library version
|
|
618
|
+
* Retrieve runtime library version.
|
|
565
619
|
*/
|
|
566
620
|
const char *
|
|
567
621
|
lxw_version(void)
|
|
@@ -570,33 +624,79 @@ lxw_version(void)
|
|
|
570
624
|
}
|
|
571
625
|
|
|
572
626
|
/*
|
|
573
|
-
*
|
|
574
|
-
* of OpenOffice.
|
|
627
|
+
* Retrieve runtime library version ID.
|
|
575
628
|
*/
|
|
576
629
|
uint16_t
|
|
577
|
-
|
|
630
|
+
lxw_version_id(void)
|
|
578
631
|
{
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
uint16_t hash = 0x0000;
|
|
582
|
-
|
|
583
|
-
count = strlen(password);
|
|
632
|
+
return LXW_VERSION_ID;
|
|
633
|
+
}
|
|
584
634
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
635
|
+
/*
|
|
636
|
+
* Hash a worksheet password. Based on the algorithm in ECMA-376-4:2016,
|
|
637
|
+
* Office Open XML File Formats - Transitional Migration Features,
|
|
638
|
+
* Additional attributes for workbookProtection element (Part 1, §18.2.29).
|
|
639
|
+
*/
|
|
640
|
+
uint16_t
|
|
641
|
+
lxw_hash_password(const char *password)
|
|
642
|
+
{
|
|
643
|
+
uint16_t byte_count = (uint16_t) strlen(password);
|
|
644
|
+
uint16_t hash = 0;
|
|
645
|
+
const char *p = &password[byte_count];
|
|
589
646
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
high_15 = high_15 >> 15;
|
|
593
|
-
letter = low_15 | high_15;
|
|
647
|
+
if (!byte_count)
|
|
648
|
+
return hash;
|
|
594
649
|
|
|
595
|
-
|
|
650
|
+
while (p-- != password) {
|
|
651
|
+
hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
|
|
652
|
+
hash ^= *p & 0xFF;
|
|
596
653
|
}
|
|
597
654
|
|
|
598
|
-
hash
|
|
655
|
+
hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
|
|
656
|
+
hash ^= byte_count;
|
|
599
657
|
hash ^= 0xCE4B;
|
|
600
658
|
|
|
601
659
|
return hash;
|
|
602
660
|
}
|
|
661
|
+
|
|
662
|
+
/* Make a simple portable version of fopen() for Windows. */
|
|
663
|
+
#ifdef __MINGW32__
|
|
664
|
+
#undef _WIN32
|
|
665
|
+
#endif
|
|
666
|
+
|
|
667
|
+
#ifdef _WIN32
|
|
668
|
+
|
|
669
|
+
#include <windows.h>
|
|
670
|
+
|
|
671
|
+
FILE *
|
|
672
|
+
lxw_fopen(const char *filename, const char *mode)
|
|
673
|
+
{
|
|
674
|
+
int n;
|
|
675
|
+
wchar_t wide_filename[_MAX_PATH + 1] = L"";
|
|
676
|
+
wchar_t wide_mode[_MAX_PATH + 1] = L"";
|
|
677
|
+
|
|
678
|
+
n = MultiByteToWideChar(CP_UTF8, 0, filename, (int) strlen(filename),
|
|
679
|
+
wide_filename, _MAX_PATH);
|
|
680
|
+
|
|
681
|
+
if (n == 0) {
|
|
682
|
+
LXW_ERROR("MultiByteToWideChar error: filename");
|
|
683
|
+
return NULL;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
n = MultiByteToWideChar(CP_UTF8, 0, mode, (int) strlen(mode),
|
|
687
|
+
wide_mode, _MAX_PATH);
|
|
688
|
+
|
|
689
|
+
if (n == 0) {
|
|
690
|
+
LXW_ERROR("MultiByteToWideChar error: mode");
|
|
691
|
+
return NULL;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return _wfopen(wide_filename, wide_mode);
|
|
695
|
+
}
|
|
696
|
+
#else
|
|
697
|
+
FILE *
|
|
698
|
+
lxw_fopen(const char *filename, const char *mode)
|
|
699
|
+
{
|
|
700
|
+
return fopen(filename, mode);
|
|
701
|
+
}
|
|
702
|
+
#endif
|