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
|
@@ -1,12 +1,49 @@
|
|
|
1
1
|
/*****************************************************************************
|
|
2
|
-
* packager - A library for
|
|
2
|
+
* packager - A library for assembling xml files into an Excel XLSX file.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* A class for writing the Excel XLSX Packager file.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* This module is used in conjunction with libxlsxwriter to create an
|
|
7
|
+
* Excel XLSX container file.
|
|
8
|
+
*
|
|
9
|
+
* From Wikipedia: The Open Packaging Conventions (OPC) is a
|
|
10
|
+
* container-file technology initially created by Microsoft to store
|
|
11
|
+
* a combination of XML and non-XML files that together form a single
|
|
12
|
+
* entity such as an Open XML Paper Specification (OpenXPS)
|
|
13
|
+
* document. http://en.wikipedia.org/wiki/Open_Packaging_Conventions.
|
|
14
|
+
*
|
|
15
|
+
* At its simplest an Excel XLSX file contains the following elements::
|
|
16
|
+
*
|
|
17
|
+
* ____ [Content_Types].xml
|
|
18
|
+
* |
|
|
19
|
+
* |____ docProps
|
|
20
|
+
* | |____ app.xml
|
|
21
|
+
* | |____ core.xml
|
|
22
|
+
* |
|
|
23
|
+
* |____ xl
|
|
24
|
+
* | |____ workbook.xml
|
|
25
|
+
* | |____ worksheets
|
|
26
|
+
* | | |____ sheet1.xml
|
|
27
|
+
* | |
|
|
28
|
+
* | |____ styles.xml
|
|
29
|
+
* | |
|
|
30
|
+
* | |____ theme
|
|
31
|
+
* | | |____ theme1.xml
|
|
32
|
+
* | |
|
|
33
|
+
* | |_____rels
|
|
34
|
+
* | |____ workbook.xml.rels
|
|
35
|
+
* |
|
|
36
|
+
* |_____rels
|
|
37
|
+
* |____ .rels
|
|
38
|
+
*
|
|
39
|
+
* The Packager class coordinates the classes that represent the
|
|
40
|
+
* elements of the package and writes them into the XLSX file.
|
|
41
|
+
*
|
|
42
|
+
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
|
|
7
43
|
*
|
|
8
44
|
*/
|
|
9
45
|
|
|
46
|
+
#include <zlib.h>
|
|
10
47
|
#include "xlsxwriter/xmlwriter.h"
|
|
11
48
|
#include "xlsxwriter/packager.h"
|
|
12
49
|
#include "xlsxwriter/hash_table.h"
|
|
@@ -15,9 +52,17 @@
|
|
|
15
52
|
STATIC lxw_error _add_file_to_zip(lxw_packager *self, FILE * file,
|
|
16
53
|
const char *filename);
|
|
17
54
|
|
|
18
|
-
STATIC lxw_error _add_buffer_to_zip(lxw_packager *self,
|
|
55
|
+
STATIC lxw_error _add_buffer_to_zip(lxw_packager *self, const char *buffer,
|
|
19
56
|
size_t buffer_size, const char *filename);
|
|
20
57
|
|
|
58
|
+
STATIC lxw_error _add_to_zip(lxw_packager *self, FILE * file,
|
|
59
|
+
char **buffer, size_t *buffer_size,
|
|
60
|
+
const char *filename);
|
|
61
|
+
|
|
62
|
+
STATIC lxw_error _write_vml_drawing_rels_file(lxw_packager *self,
|
|
63
|
+
lxw_worksheet *worksheet,
|
|
64
|
+
uint32_t index);
|
|
65
|
+
|
|
21
66
|
/*
|
|
22
67
|
* Forward declarations.
|
|
23
68
|
*/
|
|
@@ -36,7 +81,7 @@ STATIC lxw_error _add_buffer_to_zip(lxw_packager *self, unsigned char *buffer,
|
|
|
36
81
|
#ifdef _WIN32
|
|
37
82
|
|
|
38
83
|
/* Silence Windows warning with duplicate symbol for SLIST_ENTRY in local
|
|
39
|
-
* queue.h and
|
|
84
|
+
* queue.h and windows.h. */
|
|
40
85
|
#undef SLIST_ENTRY
|
|
41
86
|
|
|
42
87
|
#include <windows.h>
|
|
@@ -72,21 +117,75 @@ _open_zipfile_win32(const char *filename)
|
|
|
72
117
|
|
|
73
118
|
#endif
|
|
74
119
|
|
|
120
|
+
STATIC voidpf ZCALLBACK
|
|
121
|
+
_fopen_memstream(voidpf opaque, const char *filename, int mode)
|
|
122
|
+
{
|
|
123
|
+
lxw_packager *packager = (lxw_packager *) opaque;
|
|
124
|
+
(void) filename;
|
|
125
|
+
(void) mode;
|
|
126
|
+
return lxw_get_filehandle(&packager->output_buffer,
|
|
127
|
+
&packager->output_buffer_size,
|
|
128
|
+
packager->tmpdir);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
STATIC int ZCALLBACK
|
|
132
|
+
_fclose_memstream(voidpf opaque, voidpf stream)
|
|
133
|
+
{
|
|
134
|
+
lxw_packager *packager = (lxw_packager *) opaque;
|
|
135
|
+
FILE *file = (FILE *) stream;
|
|
136
|
+
long size;
|
|
137
|
+
|
|
138
|
+
/* Ensure memstream buffer is updated */
|
|
139
|
+
if (fflush(file))
|
|
140
|
+
goto mem_error;
|
|
141
|
+
|
|
142
|
+
/* If the memstream is backed by a temporary file, no buffer is created,
|
|
143
|
+
so create it manually. */
|
|
144
|
+
if (!packager->output_buffer) {
|
|
145
|
+
if (fseek(file, 0L, SEEK_END))
|
|
146
|
+
goto mem_error;
|
|
147
|
+
|
|
148
|
+
size = ftell(file);
|
|
149
|
+
if (size == -1)
|
|
150
|
+
goto mem_error;
|
|
151
|
+
|
|
152
|
+
packager->output_buffer = malloc(size);
|
|
153
|
+
GOTO_LABEL_ON_MEM_ERROR(packager->output_buffer, mem_error);
|
|
154
|
+
|
|
155
|
+
rewind(file);
|
|
156
|
+
if (fread((void *) packager->output_buffer, size, 1, file) < 1)
|
|
157
|
+
goto mem_error;
|
|
158
|
+
|
|
159
|
+
packager->output_buffer_size = size;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return fclose(file);
|
|
163
|
+
|
|
164
|
+
mem_error:
|
|
165
|
+
fclose(file);
|
|
166
|
+
return EOF;
|
|
167
|
+
}
|
|
168
|
+
|
|
75
169
|
/*
|
|
76
170
|
* Create a new packager object.
|
|
77
171
|
*/
|
|
78
172
|
lxw_packager *
|
|
79
|
-
lxw_packager_new(const char *filename, char *tmpdir, uint8_t use_zip64)
|
|
173
|
+
lxw_packager_new(const char *filename, const char *tmpdir, uint8_t use_zip64)
|
|
80
174
|
{
|
|
175
|
+
zlib_filefunc_def filefunc;
|
|
81
176
|
lxw_packager *packager = calloc(1, sizeof(lxw_packager));
|
|
82
177
|
GOTO_LABEL_ON_MEM_ERROR(packager, mem_error);
|
|
83
178
|
|
|
84
179
|
packager->buffer = calloc(1, LXW_ZIP_BUFFER_SIZE);
|
|
85
180
|
GOTO_LABEL_ON_MEM_ERROR(packager->buffer, mem_error);
|
|
86
181
|
|
|
87
|
-
packager->filename =
|
|
182
|
+
packager->filename = NULL;
|
|
88
183
|
packager->tmpdir = tmpdir;
|
|
89
|
-
|
|
184
|
+
|
|
185
|
+
if (filename) {
|
|
186
|
+
packager->filename = lxw_strdup(filename);
|
|
187
|
+
GOTO_LABEL_ON_MEM_ERROR(packager->filename, mem_error);
|
|
188
|
+
}
|
|
90
189
|
|
|
91
190
|
packager->buffer_size = LXW_ZIP_BUFFER_SIZE;
|
|
92
191
|
packager->use_zip64 = use_zip64;
|
|
@@ -102,12 +201,24 @@ lxw_packager_new(const char *filename, char *tmpdir, uint8_t use_zip64)
|
|
|
102
201
|
packager->zipfile_info.internal_fa = 0;
|
|
103
202
|
packager->zipfile_info.external_fa = 0;
|
|
104
203
|
|
|
204
|
+
packager->output_buffer = NULL;
|
|
205
|
+
packager->output_buffer_size = 0;
|
|
206
|
+
|
|
105
207
|
/* Create a zip container for the xlsx file. */
|
|
208
|
+
if (packager->filename) {
|
|
106
209
|
#ifdef _WIN32
|
|
107
|
-
|
|
210
|
+
packager->zipfile = _open_zipfile_win32(packager->filename);
|
|
108
211
|
#else
|
|
109
|
-
|
|
212
|
+
packager->zipfile = zipOpen(packager->filename, 0);
|
|
110
213
|
#endif
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
fill_fopen_filefunc(&filefunc);
|
|
217
|
+
filefunc.opaque = packager;
|
|
218
|
+
filefunc.zopen_file = _fopen_memstream;
|
|
219
|
+
filefunc.zclose_file = _fclose_memstream;
|
|
220
|
+
packager->zipfile = zipOpen2(packager->filename, 0, NULL, &filefunc);
|
|
221
|
+
}
|
|
111
222
|
|
|
112
223
|
if (packager->zipfile == NULL)
|
|
113
224
|
goto mem_error;
|
|
@@ -128,8 +239,8 @@ lxw_packager_free(lxw_packager *packager)
|
|
|
128
239
|
if (!packager)
|
|
129
240
|
return;
|
|
130
241
|
|
|
131
|
-
free(packager->buffer);
|
|
132
|
-
free(packager->filename);
|
|
242
|
+
free((void *) packager->buffer);
|
|
243
|
+
free((void *) packager->filename);
|
|
133
244
|
free(packager);
|
|
134
245
|
}
|
|
135
246
|
|
|
@@ -147,16 +258,19 @@ _write_workbook_file(lxw_packager *self)
|
|
|
147
258
|
lxw_workbook *workbook = self->workbook;
|
|
148
259
|
lxw_error err;
|
|
149
260
|
|
|
150
|
-
|
|
261
|
+
char *buffer = NULL;
|
|
262
|
+
size_t buffer_size = 0;
|
|
263
|
+
workbook->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
151
264
|
if (!workbook->file)
|
|
152
265
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
153
266
|
|
|
154
267
|
lxw_workbook_assemble_xml_file(workbook);
|
|
155
268
|
|
|
156
|
-
err =
|
|
157
|
-
|
|
158
|
-
|
|
269
|
+
err = _add_to_zip(self, workbook->file, &buffer, &buffer_size,
|
|
270
|
+
"xl/workbook.xml");
|
|
159
271
|
fclose(workbook->file);
|
|
272
|
+
free(buffer);
|
|
273
|
+
RETURN_ON_ERROR(err);
|
|
160
274
|
|
|
161
275
|
return LXW_NO_ERROR;
|
|
162
276
|
}
|
|
@@ -171,6 +285,8 @@ _write_worksheet_files(lxw_packager *self)
|
|
|
171
285
|
lxw_sheet *sheet;
|
|
172
286
|
lxw_worksheet *worksheet;
|
|
173
287
|
char sheetname[LXW_FILENAME_LENGTH] = { 0 };
|
|
288
|
+
char *buffer = NULL;
|
|
289
|
+
size_t buffer_size = 0;
|
|
174
290
|
uint32_t index = 1;
|
|
175
291
|
lxw_error err;
|
|
176
292
|
|
|
@@ -186,16 +302,18 @@ _write_worksheet_files(lxw_packager *self)
|
|
|
186
302
|
if (worksheet->optimize_row)
|
|
187
303
|
lxw_worksheet_write_single_row(worksheet);
|
|
188
304
|
|
|
189
|
-
worksheet->file =
|
|
305
|
+
worksheet->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
306
|
+
self->tmpdir);
|
|
190
307
|
if (!worksheet->file)
|
|
191
308
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
192
309
|
|
|
193
310
|
lxw_worksheet_assemble_xml_file(worksheet);
|
|
194
311
|
|
|
195
|
-
err =
|
|
196
|
-
|
|
197
|
-
|
|
312
|
+
err = _add_to_zip(self, worksheet->file, &buffer, &buffer_size,
|
|
313
|
+
sheetname);
|
|
198
314
|
fclose(worksheet->file);
|
|
315
|
+
free(buffer);
|
|
316
|
+
RETURN_ON_ERROR(err);
|
|
199
317
|
}
|
|
200
318
|
|
|
201
319
|
return LXW_NO_ERROR;
|
|
@@ -211,6 +329,8 @@ _write_chartsheet_files(lxw_packager *self)
|
|
|
211
329
|
lxw_sheet *sheet;
|
|
212
330
|
lxw_chartsheet *chartsheet;
|
|
213
331
|
char sheetname[LXW_FILENAME_LENGTH] = { 0 };
|
|
332
|
+
char *buffer = NULL;
|
|
333
|
+
size_t buffer_size = 0;
|
|
214
334
|
uint32_t index = 1;
|
|
215
335
|
lxw_error err;
|
|
216
336
|
|
|
@@ -223,16 +343,18 @@ _write_chartsheet_files(lxw_packager *self)
|
|
|
223
343
|
lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
|
|
224
344
|
"xl/chartsheets/sheet%d.xml", index++);
|
|
225
345
|
|
|
226
|
-
chartsheet->file =
|
|
346
|
+
chartsheet->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
347
|
+
self->tmpdir);
|
|
227
348
|
if (!chartsheet->file)
|
|
228
349
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
229
350
|
|
|
230
351
|
lxw_chartsheet_assemble_xml_file(chartsheet);
|
|
231
352
|
|
|
232
|
-
err =
|
|
233
|
-
|
|
234
|
-
|
|
353
|
+
err = _add_to_zip(self, chartsheet->file, &buffer, &buffer_size,
|
|
354
|
+
sheetname);
|
|
235
355
|
fclose(chartsheet->file);
|
|
356
|
+
free(buffer);
|
|
357
|
+
RETURN_ON_ERROR(err);
|
|
236
358
|
}
|
|
237
359
|
|
|
238
360
|
return LXW_NO_ERROR;
|
|
@@ -247,7 +369,7 @@ _write_image_files(lxw_packager *self)
|
|
|
247
369
|
lxw_workbook *workbook = self->workbook;
|
|
248
370
|
lxw_sheet *sheet;
|
|
249
371
|
lxw_worksheet *worksheet;
|
|
250
|
-
|
|
372
|
+
lxw_object_properties *object_props;
|
|
251
373
|
lxw_error err;
|
|
252
374
|
FILE *image_stream;
|
|
253
375
|
|
|
@@ -260,21 +382,25 @@ _write_image_files(lxw_packager *self)
|
|
|
260
382
|
else
|
|
261
383
|
worksheet = sheet->u.worksheet;
|
|
262
384
|
|
|
263
|
-
if (STAILQ_EMPTY(worksheet->
|
|
385
|
+
if (STAILQ_EMPTY(worksheet->image_props))
|
|
264
386
|
continue;
|
|
265
387
|
|
|
266
|
-
STAILQ_FOREACH(
|
|
388
|
+
STAILQ_FOREACH(object_props, worksheet->image_props, list_pointers) {
|
|
389
|
+
|
|
390
|
+
if (object_props->is_duplicate)
|
|
391
|
+
continue;
|
|
267
392
|
|
|
268
393
|
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
269
|
-
"xl/media/image%d.%s", index++,
|
|
394
|
+
"xl/media/image%d.%s", index++,
|
|
395
|
+
object_props->extension);
|
|
270
396
|
|
|
271
|
-
if (!
|
|
397
|
+
if (!object_props->is_image_buffer) {
|
|
272
398
|
/* Check that the image file exists and can be opened. */
|
|
273
|
-
image_stream =
|
|
399
|
+
image_stream = lxw_fopen(object_props->filename, "rb");
|
|
274
400
|
if (!image_stream) {
|
|
275
401
|
LXW_WARN_FORMAT1("Error adding image to xlsx file: file "
|
|
276
402
|
"doesn't exist or can't be opened: %s.",
|
|
277
|
-
|
|
403
|
+
object_props->filename);
|
|
278
404
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
279
405
|
}
|
|
280
406
|
|
|
@@ -283,8 +409,9 @@ _write_image_files(lxw_packager *self)
|
|
|
283
409
|
}
|
|
284
410
|
else {
|
|
285
411
|
err = _add_buffer_to_zip(self,
|
|
286
|
-
|
|
287
|
-
|
|
412
|
+
object_props->image_buffer,
|
|
413
|
+
object_props->image_buffer_size,
|
|
414
|
+
filename);
|
|
288
415
|
}
|
|
289
416
|
|
|
290
417
|
RETURN_ON_ERROR(err);
|
|
@@ -308,7 +435,7 @@ _add_vba_project(lxw_packager *self)
|
|
|
308
435
|
return LXW_NO_ERROR;
|
|
309
436
|
|
|
310
437
|
/* Check that the image file exists and can be opened. */
|
|
311
|
-
image_stream =
|
|
438
|
+
image_stream = lxw_fopen(workbook->vba_project, "rb");
|
|
312
439
|
if (!image_stream) {
|
|
313
440
|
LXW_WARN_FORMAT1("Error adding vbaProject.bin to xlsx file: "
|
|
314
441
|
"file doesn't exist or can't be opened: %s.",
|
|
@@ -323,6 +450,35 @@ _add_vba_project(lxw_packager *self)
|
|
|
323
450
|
return LXW_NO_ERROR;
|
|
324
451
|
}
|
|
325
452
|
|
|
453
|
+
/*
|
|
454
|
+
* Write the xl/vbaProjectSignature.bin file.
|
|
455
|
+
*/
|
|
456
|
+
STATIC lxw_error
|
|
457
|
+
_add_vba_project_signature(lxw_packager *self)
|
|
458
|
+
{
|
|
459
|
+
lxw_workbook *workbook = self->workbook;
|
|
460
|
+
lxw_error err;
|
|
461
|
+
FILE *image_stream;
|
|
462
|
+
|
|
463
|
+
if (!workbook->vba_project_signature)
|
|
464
|
+
return LXW_NO_ERROR;
|
|
465
|
+
|
|
466
|
+
/* Check that the image file exists and can be opened. */
|
|
467
|
+
image_stream = lxw_fopen(workbook->vba_project_signature, "rb");
|
|
468
|
+
if (!image_stream) {
|
|
469
|
+
LXW_WARN_FORMAT1("Error adding vbaProjectSignature.bin to xlsx file: "
|
|
470
|
+
"file doesn't exist or can't be opened: %s.",
|
|
471
|
+
workbook->vba_project_signature);
|
|
472
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
err = _add_file_to_zip(self, image_stream, "xl/vbaProjectSignature.bin");
|
|
476
|
+
fclose(image_stream);
|
|
477
|
+
RETURN_ON_ERROR(err);
|
|
478
|
+
|
|
479
|
+
return LXW_NO_ERROR;
|
|
480
|
+
}
|
|
481
|
+
|
|
326
482
|
/*
|
|
327
483
|
* Write the chart files.
|
|
328
484
|
*/
|
|
@@ -332,6 +488,8 @@ _write_chart_files(lxw_packager *self)
|
|
|
332
488
|
lxw_workbook *workbook = self->workbook;
|
|
333
489
|
lxw_chart *chart;
|
|
334
490
|
char sheetname[LXW_FILENAME_LENGTH] = { 0 };
|
|
491
|
+
char *buffer = NULL;
|
|
492
|
+
size_t buffer_size = 0;
|
|
335
493
|
uint32_t index = 1;
|
|
336
494
|
lxw_error err;
|
|
337
495
|
|
|
@@ -340,16 +498,17 @@ _write_chart_files(lxw_packager *self)
|
|
|
340
498
|
lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
|
|
341
499
|
"xl/charts/chart%d.xml", index++);
|
|
342
500
|
|
|
343
|
-
chart->file =
|
|
501
|
+
chart->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
344
502
|
if (!chart->file)
|
|
345
503
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
346
504
|
|
|
347
505
|
lxw_chart_assemble_xml_file(chart);
|
|
348
506
|
|
|
349
|
-
err =
|
|
350
|
-
|
|
351
|
-
|
|
507
|
+
err = _add_to_zip(self, chart->file, &buffer, &buffer_size,
|
|
508
|
+
sheetname);
|
|
352
509
|
fclose(chart->file);
|
|
510
|
+
free(buffer);
|
|
511
|
+
RETURN_ON_ERROR(err);
|
|
353
512
|
}
|
|
354
513
|
|
|
355
514
|
return LXW_NO_ERROR;
|
|
@@ -383,6 +542,8 @@ _write_drawing_files(lxw_packager *self)
|
|
|
383
542
|
lxw_worksheet *worksheet;
|
|
384
543
|
lxw_drawing *drawing;
|
|
385
544
|
char filename[LXW_FILENAME_LENGTH] = { 0 };
|
|
545
|
+
char *buffer = NULL;
|
|
546
|
+
size_t buffer_size = 0;
|
|
386
547
|
uint32_t index = 1;
|
|
387
548
|
lxw_error err;
|
|
388
549
|
|
|
@@ -398,15 +559,18 @@ _write_drawing_files(lxw_packager *self)
|
|
|
398
559
|
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
399
560
|
"xl/drawings/drawing%d.xml", index++);
|
|
400
561
|
|
|
401
|
-
drawing->file =
|
|
562
|
+
drawing->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
563
|
+
self->tmpdir);
|
|
402
564
|
if (!drawing->file)
|
|
403
565
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
404
566
|
|
|
405
567
|
lxw_drawing_assemble_xml_file(drawing);
|
|
406
|
-
err = _add_file_to_zip(self, drawing->file, filename);
|
|
407
|
-
RETURN_ON_ERROR(err);
|
|
408
568
|
|
|
569
|
+
err = _add_to_zip(self, drawing->file, &buffer, &buffer_size,
|
|
570
|
+
filename);
|
|
409
571
|
fclose(drawing->file);
|
|
572
|
+
free(buffer);
|
|
573
|
+
RETURN_ON_ERROR(err);
|
|
410
574
|
}
|
|
411
575
|
}
|
|
412
576
|
|
|
@@ -440,6 +604,263 @@ _get_drawing_count(lxw_packager *self)
|
|
|
440
604
|
return drawing_count;
|
|
441
605
|
}
|
|
442
606
|
|
|
607
|
+
/*
|
|
608
|
+
* Write the worksheet table files.
|
|
609
|
+
*/
|
|
610
|
+
STATIC lxw_error
|
|
611
|
+
_write_table_files(lxw_packager *self)
|
|
612
|
+
{
|
|
613
|
+
lxw_workbook *workbook = self->workbook;
|
|
614
|
+
lxw_sheet *sheet;
|
|
615
|
+
lxw_worksheet *worksheet;
|
|
616
|
+
lxw_table *table;
|
|
617
|
+
lxw_table_obj *table_obj;
|
|
618
|
+
lxw_error err;
|
|
619
|
+
|
|
620
|
+
char filename[LXW_FILENAME_LENGTH] = { 0 };
|
|
621
|
+
char *buffer = NULL;
|
|
622
|
+
size_t buffer_size = 0;
|
|
623
|
+
uint32_t index = 1;
|
|
624
|
+
|
|
625
|
+
STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
|
|
626
|
+
if (sheet->is_chartsheet)
|
|
627
|
+
continue;
|
|
628
|
+
else
|
|
629
|
+
worksheet = sheet->u.worksheet;
|
|
630
|
+
|
|
631
|
+
if (STAILQ_EMPTY(worksheet->table_objs))
|
|
632
|
+
continue;
|
|
633
|
+
|
|
634
|
+
STAILQ_FOREACH(table_obj, worksheet->table_objs, list_pointers) {
|
|
635
|
+
|
|
636
|
+
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
637
|
+
"xl/tables/table%d.xml", index++);
|
|
638
|
+
|
|
639
|
+
table = lxw_table_new();
|
|
640
|
+
if (!table) {
|
|
641
|
+
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
642
|
+
RETURN_ON_ERROR(err);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
table->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
646
|
+
self->tmpdir);
|
|
647
|
+
if (!table->file) {
|
|
648
|
+
lxw_table_free(table);
|
|
649
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
table->table_obj = table_obj;
|
|
653
|
+
|
|
654
|
+
lxw_table_assemble_xml_file(table);
|
|
655
|
+
|
|
656
|
+
err = _add_to_zip(self, table->file, &buffer, &buffer_size,
|
|
657
|
+
filename);
|
|
658
|
+
fclose(table->file);
|
|
659
|
+
free(buffer);
|
|
660
|
+
lxw_table_free(table);
|
|
661
|
+
RETURN_ON_ERROR(err);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return LXW_NO_ERROR;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/*
|
|
669
|
+
* Count the table files.
|
|
670
|
+
*/
|
|
671
|
+
uint32_t
|
|
672
|
+
_get_table_count(lxw_packager *self)
|
|
673
|
+
{
|
|
674
|
+
lxw_workbook *workbook = self->workbook;
|
|
675
|
+
lxw_sheet *sheet;
|
|
676
|
+
lxw_worksheet *worksheet;
|
|
677
|
+
uint32_t table_count = 0;
|
|
678
|
+
|
|
679
|
+
STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
|
|
680
|
+
if (sheet->is_chartsheet)
|
|
681
|
+
worksheet = sheet->u.chartsheet->worksheet;
|
|
682
|
+
else
|
|
683
|
+
worksheet = sheet->u.worksheet;
|
|
684
|
+
|
|
685
|
+
table_count += worksheet->table_count;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return table_count;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/*
|
|
692
|
+
* Write the comment/header VML files.
|
|
693
|
+
*/
|
|
694
|
+
STATIC lxw_error
|
|
695
|
+
_write_vml_files(lxw_packager *self)
|
|
696
|
+
{
|
|
697
|
+
lxw_workbook *workbook = self->workbook;
|
|
698
|
+
lxw_sheet *sheet;
|
|
699
|
+
lxw_worksheet *worksheet;
|
|
700
|
+
lxw_vml *vml;
|
|
701
|
+
char filename[LXW_FILENAME_LENGTH] = { 0 };
|
|
702
|
+
char *buffer = NULL;
|
|
703
|
+
size_t buffer_size = 0;
|
|
704
|
+
uint32_t index = 1;
|
|
705
|
+
lxw_error err;
|
|
706
|
+
|
|
707
|
+
STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
|
|
708
|
+
if (sheet->is_chartsheet)
|
|
709
|
+
continue;
|
|
710
|
+
else
|
|
711
|
+
worksheet = sheet->u.worksheet;
|
|
712
|
+
|
|
713
|
+
if (!worksheet->has_vml && !worksheet->has_header_vml)
|
|
714
|
+
continue;
|
|
715
|
+
|
|
716
|
+
if (worksheet->has_vml) {
|
|
717
|
+
|
|
718
|
+
vml = lxw_vml_new();
|
|
719
|
+
if (!vml)
|
|
720
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
721
|
+
|
|
722
|
+
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
723
|
+
"xl/drawings/vmlDrawing%d.vml", index++);
|
|
724
|
+
|
|
725
|
+
vml->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
726
|
+
self->tmpdir);
|
|
727
|
+
if (!vml->file) {
|
|
728
|
+
lxw_vml_free(vml);
|
|
729
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
vml->comment_objs = worksheet->comment_objs;
|
|
733
|
+
vml->button_objs = worksheet->button_objs;
|
|
734
|
+
vml->vml_shape_id = worksheet->vml_shape_id;
|
|
735
|
+
vml->comment_display_default = worksheet->comment_display_default;
|
|
736
|
+
|
|
737
|
+
if (worksheet->vml_data_id_str) {
|
|
738
|
+
vml->vml_data_id_str = worksheet->vml_data_id_str;
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
fclose(vml->file);
|
|
742
|
+
free(buffer);
|
|
743
|
+
lxw_vml_free(vml);
|
|
744
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
lxw_vml_assemble_xml_file(vml);
|
|
748
|
+
|
|
749
|
+
err = _add_to_zip(self, vml->file, &buffer, &buffer_size,
|
|
750
|
+
filename);
|
|
751
|
+
|
|
752
|
+
fclose(vml->file);
|
|
753
|
+
free(buffer);
|
|
754
|
+
lxw_vml_free(vml);
|
|
755
|
+
|
|
756
|
+
RETURN_ON_ERROR(err);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (worksheet->has_header_vml) {
|
|
760
|
+
|
|
761
|
+
err = _write_vml_drawing_rels_file(self, worksheet, index);
|
|
762
|
+
RETURN_ON_ERROR(err);
|
|
763
|
+
|
|
764
|
+
vml = lxw_vml_new();
|
|
765
|
+
if (!vml)
|
|
766
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
767
|
+
|
|
768
|
+
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
769
|
+
"xl/drawings/vmlDrawing%d.vml", index++);
|
|
770
|
+
|
|
771
|
+
vml->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
772
|
+
self->tmpdir);
|
|
773
|
+
if (!vml->file) {
|
|
774
|
+
lxw_vml_free(vml);
|
|
775
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
vml->image_objs = worksheet->header_image_objs;
|
|
779
|
+
vml->vml_shape_id = worksheet->vml_header_id * 1024;
|
|
780
|
+
|
|
781
|
+
if (worksheet->vml_header_id_str) {
|
|
782
|
+
vml->vml_data_id_str = worksheet->vml_header_id_str;
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
fclose(vml->file);
|
|
786
|
+
free(buffer);
|
|
787
|
+
lxw_vml_free(vml);
|
|
788
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
lxw_vml_assemble_xml_file(vml);
|
|
792
|
+
|
|
793
|
+
err = _add_to_zip(self, vml->file, &buffer, &buffer_size,
|
|
794
|
+
filename);
|
|
795
|
+
|
|
796
|
+
fclose(vml->file);
|
|
797
|
+
free(buffer);
|
|
798
|
+
lxw_vml_free(vml);
|
|
799
|
+
|
|
800
|
+
RETURN_ON_ERROR(err);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return LXW_NO_ERROR;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/*
|
|
808
|
+
* Write the comment files.
|
|
809
|
+
*/
|
|
810
|
+
STATIC lxw_error
|
|
811
|
+
_write_comment_files(lxw_packager *self)
|
|
812
|
+
{
|
|
813
|
+
lxw_workbook *workbook = self->workbook;
|
|
814
|
+
lxw_sheet *sheet;
|
|
815
|
+
lxw_worksheet *worksheet;
|
|
816
|
+
lxw_comment *comment;
|
|
817
|
+
char filename[LXW_FILENAME_LENGTH] = { 0 };
|
|
818
|
+
char *buffer = NULL;
|
|
819
|
+
size_t buffer_size = 0;
|
|
820
|
+
uint32_t index = 1;
|
|
821
|
+
lxw_error err;
|
|
822
|
+
|
|
823
|
+
STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
|
|
824
|
+
if (sheet->is_chartsheet)
|
|
825
|
+
continue;
|
|
826
|
+
else
|
|
827
|
+
worksheet = sheet->u.worksheet;
|
|
828
|
+
|
|
829
|
+
if (!worksheet->has_comments)
|
|
830
|
+
continue;
|
|
831
|
+
|
|
832
|
+
comment = lxw_comment_new();
|
|
833
|
+
if (!comment)
|
|
834
|
+
return LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
835
|
+
|
|
836
|
+
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
837
|
+
"xl/comments%d.xml", index++);
|
|
838
|
+
|
|
839
|
+
comment->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
840
|
+
self->tmpdir);
|
|
841
|
+
if (!comment->file) {
|
|
842
|
+
lxw_comment_free(comment);
|
|
843
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
comment->comment_objs = worksheet->comment_objs;
|
|
847
|
+
comment->comment_author = worksheet->comment_author;
|
|
848
|
+
|
|
849
|
+
lxw_comment_assemble_xml_file(comment);
|
|
850
|
+
|
|
851
|
+
err = _add_to_zip(self, comment->file, &buffer, &buffer_size,
|
|
852
|
+
filename);
|
|
853
|
+
|
|
854
|
+
fclose(comment->file);
|
|
855
|
+
free(buffer);
|
|
856
|
+
lxw_comment_free(comment);
|
|
857
|
+
|
|
858
|
+
RETURN_ON_ERROR(err);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
return LXW_NO_ERROR;
|
|
862
|
+
}
|
|
863
|
+
|
|
443
864
|
/*
|
|
444
865
|
* Write the sharedStrings.xml file.
|
|
445
866
|
*/
|
|
@@ -447,22 +868,25 @@ STATIC lxw_error
|
|
|
447
868
|
_write_shared_strings_file(lxw_packager *self)
|
|
448
869
|
{
|
|
449
870
|
lxw_sst *sst = self->workbook->sst;
|
|
871
|
+
char *buffer = NULL;
|
|
872
|
+
size_t buffer_size = 0;
|
|
450
873
|
lxw_error err;
|
|
451
874
|
|
|
452
875
|
/* Skip the sharedStrings file if there are no shared strings. */
|
|
453
876
|
if (!sst->string_count)
|
|
454
877
|
return LXW_NO_ERROR;
|
|
455
878
|
|
|
456
|
-
sst->file =
|
|
879
|
+
sst->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
457
880
|
if (!sst->file)
|
|
458
881
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
459
882
|
|
|
460
883
|
lxw_sst_assemble_xml_file(sst);
|
|
461
884
|
|
|
462
|
-
err =
|
|
463
|
-
|
|
464
|
-
|
|
885
|
+
err = _add_to_zip(self, sst->file, &buffer, &buffer_size,
|
|
886
|
+
"xl/sharedStrings.xml");
|
|
465
887
|
fclose(sst->file);
|
|
888
|
+
free(buffer);
|
|
889
|
+
RETURN_ON_ERROR(err);
|
|
466
890
|
|
|
467
891
|
return LXW_NO_ERROR;
|
|
468
892
|
}
|
|
@@ -479,6 +903,8 @@ _write_app_file(lxw_packager *self)
|
|
|
479
903
|
lxw_chartsheet *chartsheet;
|
|
480
904
|
lxw_defined_name *defined_name;
|
|
481
905
|
lxw_app *app;
|
|
906
|
+
char *buffer = NULL;
|
|
907
|
+
size_t buffer_size = 0;
|
|
482
908
|
uint32_t named_range_count = 0;
|
|
483
909
|
char *autofilter;
|
|
484
910
|
char *has_range;
|
|
@@ -491,7 +917,7 @@ _write_app_file(lxw_packager *self)
|
|
|
491
917
|
goto mem_error;
|
|
492
918
|
}
|
|
493
919
|
|
|
494
|
-
app->file =
|
|
920
|
+
app->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
495
921
|
if (!app->file) {
|
|
496
922
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
497
923
|
goto mem_error;
|
|
@@ -545,11 +971,15 @@ _write_app_file(lxw_packager *self)
|
|
|
545
971
|
/* Set the app/doc properties. */
|
|
546
972
|
app->properties = workbook->properties;
|
|
547
973
|
|
|
974
|
+
app->doc_security = workbook->read_only;
|
|
975
|
+
|
|
548
976
|
lxw_app_assemble_xml_file(app);
|
|
549
977
|
|
|
550
|
-
err =
|
|
978
|
+
err = _add_to_zip(self, app->file, &buffer, &buffer_size,
|
|
979
|
+
"docProps/app.xml");
|
|
551
980
|
|
|
552
981
|
fclose(app->file);
|
|
982
|
+
free(buffer);
|
|
553
983
|
|
|
554
984
|
mem_error:
|
|
555
985
|
lxw_app_free(app);
|
|
@@ -565,13 +995,15 @@ _write_core_file(lxw_packager *self)
|
|
|
565
995
|
{
|
|
566
996
|
lxw_error err = LXW_NO_ERROR;
|
|
567
997
|
lxw_core *core = lxw_core_new();
|
|
998
|
+
char *buffer = NULL;
|
|
999
|
+
size_t buffer_size = 0;
|
|
568
1000
|
|
|
569
1001
|
if (!core) {
|
|
570
1002
|
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
571
1003
|
goto mem_error;
|
|
572
1004
|
}
|
|
573
1005
|
|
|
574
|
-
core->file =
|
|
1006
|
+
core->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
575
1007
|
if (!core->file) {
|
|
576
1008
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
577
1009
|
goto mem_error;
|
|
@@ -581,9 +1013,11 @@ _write_core_file(lxw_packager *self)
|
|
|
581
1013
|
|
|
582
1014
|
lxw_core_assemble_xml_file(core);
|
|
583
1015
|
|
|
584
|
-
err =
|
|
1016
|
+
err = _add_to_zip(self, core->file, &buffer, &buffer_size,
|
|
1017
|
+
"docProps/core.xml");
|
|
585
1018
|
|
|
586
1019
|
fclose(core->file);
|
|
1020
|
+
free(buffer);
|
|
587
1021
|
|
|
588
1022
|
mem_error:
|
|
589
1023
|
lxw_core_free(core);
|
|
@@ -591,6 +1025,47 @@ mem_error:
|
|
|
591
1025
|
return err;
|
|
592
1026
|
}
|
|
593
1027
|
|
|
1028
|
+
/*
|
|
1029
|
+
* Write the metadata.xml file.
|
|
1030
|
+
*/
|
|
1031
|
+
STATIC lxw_error
|
|
1032
|
+
_write_metadata_file(lxw_packager *self)
|
|
1033
|
+
{
|
|
1034
|
+
lxw_error err = LXW_NO_ERROR;
|
|
1035
|
+
lxw_metadata *metadata;
|
|
1036
|
+
char *buffer = NULL;
|
|
1037
|
+
size_t buffer_size = 0;
|
|
1038
|
+
|
|
1039
|
+
if (!self->workbook->has_metadata)
|
|
1040
|
+
return LXW_NO_ERROR;
|
|
1041
|
+
|
|
1042
|
+
metadata = lxw_metadata_new();
|
|
1043
|
+
|
|
1044
|
+
if (!metadata) {
|
|
1045
|
+
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
1046
|
+
goto mem_error;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
metadata->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
1050
|
+
if (!metadata->file) {
|
|
1051
|
+
err = LXW_ERROR_CREATING_TMPFILE;
|
|
1052
|
+
goto mem_error;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
lxw_metadata_assemble_xml_file(metadata);
|
|
1056
|
+
|
|
1057
|
+
err = _add_to_zip(self, metadata->file, &buffer, &buffer_size,
|
|
1058
|
+
"xl/metadata.xml");
|
|
1059
|
+
|
|
1060
|
+
fclose(metadata->file);
|
|
1061
|
+
free(buffer);
|
|
1062
|
+
|
|
1063
|
+
mem_error:
|
|
1064
|
+
lxw_metadata_free(metadata);
|
|
1065
|
+
|
|
1066
|
+
return err;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
594
1069
|
/*
|
|
595
1070
|
* Write the custom.xml file.
|
|
596
1071
|
*/
|
|
@@ -598,6 +1073,8 @@ STATIC lxw_error
|
|
|
598
1073
|
_write_custom_file(lxw_packager *self)
|
|
599
1074
|
{
|
|
600
1075
|
lxw_custom *custom;
|
|
1076
|
+
char *buffer = NULL;
|
|
1077
|
+
size_t buffer_size = 0;
|
|
601
1078
|
lxw_error err = LXW_NO_ERROR;
|
|
602
1079
|
|
|
603
1080
|
if (STAILQ_EMPTY(self->workbook->custom_properties))
|
|
@@ -609,7 +1086,7 @@ _write_custom_file(lxw_packager *self)
|
|
|
609
1086
|
goto mem_error;
|
|
610
1087
|
}
|
|
611
1088
|
|
|
612
|
-
custom->file =
|
|
1089
|
+
custom->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
613
1090
|
if (!custom->file) {
|
|
614
1091
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
615
1092
|
goto mem_error;
|
|
@@ -619,9 +1096,11 @@ _write_custom_file(lxw_packager *self)
|
|
|
619
1096
|
|
|
620
1097
|
lxw_custom_assemble_xml_file(custom);
|
|
621
1098
|
|
|
622
|
-
err =
|
|
1099
|
+
err = _add_to_zip(self, custom->file, &buffer, &buffer_size,
|
|
1100
|
+
"docProps/custom.xml");
|
|
623
1101
|
|
|
624
1102
|
fclose(custom->file);
|
|
1103
|
+
free(buffer);
|
|
625
1104
|
|
|
626
1105
|
mem_error:
|
|
627
1106
|
lxw_custom_free(custom);
|
|
@@ -636,13 +1115,15 @@ _write_theme_file(lxw_packager *self)
|
|
|
636
1115
|
{
|
|
637
1116
|
lxw_error err = LXW_NO_ERROR;
|
|
638
1117
|
lxw_theme *theme = lxw_theme_new();
|
|
1118
|
+
char *buffer = NULL;
|
|
1119
|
+
size_t buffer_size = 0;
|
|
639
1120
|
|
|
640
1121
|
if (!theme) {
|
|
641
1122
|
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
642
1123
|
goto mem_error;
|
|
643
1124
|
}
|
|
644
1125
|
|
|
645
|
-
theme->file =
|
|
1126
|
+
theme->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
646
1127
|
if (!theme->file) {
|
|
647
1128
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
648
1129
|
goto mem_error;
|
|
@@ -650,9 +1131,11 @@ _write_theme_file(lxw_packager *self)
|
|
|
650
1131
|
|
|
651
1132
|
lxw_theme_assemble_xml_file(theme);
|
|
652
1133
|
|
|
653
|
-
err =
|
|
1134
|
+
err = _add_to_zip(self, theme->file, &buffer, &buffer_size,
|
|
1135
|
+
"xl/theme/theme1.xml");
|
|
654
1136
|
|
|
655
1137
|
fclose(theme->file);
|
|
1138
|
+
free(buffer);
|
|
656
1139
|
|
|
657
1140
|
mem_error:
|
|
658
1141
|
lxw_theme_free(theme);
|
|
@@ -667,6 +1150,8 @@ STATIC lxw_error
|
|
|
667
1150
|
_write_styles_file(lxw_packager *self)
|
|
668
1151
|
{
|
|
669
1152
|
lxw_styles *styles = lxw_styles_new();
|
|
1153
|
+
char *buffer = NULL;
|
|
1154
|
+
size_t buffer_size = 0;
|
|
670
1155
|
lxw_hash_element *hash_element;
|
|
671
1156
|
lxw_error err = LXW_NO_ERROR;
|
|
672
1157
|
|
|
@@ -690,13 +1175,30 @@ _write_styles_file(lxw_packager *self)
|
|
|
690
1175
|
STAILQ_INSERT_TAIL(styles->xf_formats, style_format, list_pointers);
|
|
691
1176
|
}
|
|
692
1177
|
|
|
1178
|
+
/* Copy the unique and in-use dxf formats from the workbook to the styles
|
|
1179
|
+
* dxf_format list. */
|
|
1180
|
+
LXW_FOREACH_ORDERED(hash_element, self->workbook->used_dxf_formats) {
|
|
1181
|
+
lxw_format *workbook_format = (lxw_format *) hash_element->value;
|
|
1182
|
+
lxw_format *style_format = lxw_format_new();
|
|
1183
|
+
|
|
1184
|
+
if (!style_format) {
|
|
1185
|
+
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
1186
|
+
goto mem_error;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
memcpy(style_format, workbook_format, sizeof(lxw_format));
|
|
1190
|
+
STAILQ_INSERT_TAIL(styles->dxf_formats, style_format, list_pointers);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
693
1193
|
styles->font_count = self->workbook->font_count;
|
|
694
1194
|
styles->border_count = self->workbook->border_count;
|
|
695
1195
|
styles->fill_count = self->workbook->fill_count;
|
|
696
1196
|
styles->num_format_count = self->workbook->num_format_count;
|
|
697
1197
|
styles->xf_count = self->workbook->used_xf_formats->unique_count;
|
|
1198
|
+
styles->dxf_count = self->workbook->used_dxf_formats->unique_count;
|
|
1199
|
+
styles->has_comments = self->workbook->has_comments;
|
|
698
1200
|
|
|
699
|
-
styles->file =
|
|
1201
|
+
styles->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
700
1202
|
if (!styles->file) {
|
|
701
1203
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
702
1204
|
goto mem_error;
|
|
@@ -704,9 +1206,11 @@ _write_styles_file(lxw_packager *self)
|
|
|
704
1206
|
|
|
705
1207
|
lxw_styles_assemble_xml_file(styles);
|
|
706
1208
|
|
|
707
|
-
err =
|
|
1209
|
+
err = _add_to_zip(self, styles->file, &buffer, &buffer_size,
|
|
1210
|
+
"xl/styles.xml");
|
|
708
1211
|
|
|
709
1212
|
fclose(styles->file);
|
|
1213
|
+
free(buffer);
|
|
710
1214
|
|
|
711
1215
|
mem_error:
|
|
712
1216
|
lxw_styles_free(styles);
|
|
@@ -721,6 +1225,8 @@ STATIC lxw_error
|
|
|
721
1225
|
_write_content_types_file(lxw_packager *self)
|
|
722
1226
|
{
|
|
723
1227
|
lxw_content_types *content_types = lxw_content_types_new();
|
|
1228
|
+
char *buffer = NULL;
|
|
1229
|
+
size_t buffer_size = 0;
|
|
724
1230
|
lxw_workbook *workbook = self->workbook;
|
|
725
1231
|
lxw_sheet *sheet;
|
|
726
1232
|
char filename[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
|
|
@@ -729,6 +1235,7 @@ _write_content_types_file(lxw_packager *self)
|
|
|
729
1235
|
uint32_t chartsheet_index = 1;
|
|
730
1236
|
uint32_t drawing_count = _get_drawing_count(self);
|
|
731
1237
|
uint32_t chart_count = _get_chart_count(self);
|
|
1238
|
+
uint32_t table_count = _get_table_count(self);
|
|
732
1239
|
lxw_error err = LXW_NO_ERROR;
|
|
733
1240
|
|
|
734
1241
|
if (!content_types) {
|
|
@@ -736,7 +1243,8 @@ _write_content_types_file(lxw_packager *self)
|
|
|
736
1243
|
goto mem_error;
|
|
737
1244
|
}
|
|
738
1245
|
|
|
739
|
-
content_types->file =
|
|
1246
|
+
content_types->file = lxw_get_filehandle(&buffer, &buffer_size,
|
|
1247
|
+
self->tmpdir);
|
|
740
1248
|
if (!content_types->file) {
|
|
741
1249
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
742
1250
|
goto mem_error;
|
|
@@ -751,6 +1259,9 @@ _write_content_types_file(lxw_packager *self)
|
|
|
751
1259
|
if (workbook->has_bmp)
|
|
752
1260
|
lxw_ct_add_default(content_types, "bmp", "image/bmp");
|
|
753
1261
|
|
|
1262
|
+
if (workbook->has_gif)
|
|
1263
|
+
lxw_ct_add_default(content_types, "gif", "image/gif");
|
|
1264
|
+
|
|
754
1265
|
if (workbook->vba_project)
|
|
755
1266
|
lxw_ct_add_default(content_types, "bin",
|
|
756
1267
|
"application/vnd.ms-office.vbaProject");
|
|
@@ -762,6 +1273,10 @@ _write_content_types_file(lxw_packager *self)
|
|
|
762
1273
|
lxw_ct_add_override(content_types, "/xl/workbook.xml",
|
|
763
1274
|
LXW_APP_DOCUMENT "spreadsheetml.sheet.main+xml");
|
|
764
1275
|
|
|
1276
|
+
if (workbook->vba_project_signature)
|
|
1277
|
+
lxw_ct_add_override(content_types, "/xl/vbaProjectSignature.bin",
|
|
1278
|
+
"application/vnd.ms-office.vbaProjectSignature");
|
|
1279
|
+
|
|
765
1280
|
STAILQ_FOREACH(sheet, workbook->sheets, list_pointers) {
|
|
766
1281
|
if (sheet->is_chartsheet) {
|
|
767
1282
|
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
@@ -787,17 +1302,37 @@ _write_content_types_file(lxw_packager *self)
|
|
|
787
1302
|
lxw_ct_add_drawing_name(content_types, filename);
|
|
788
1303
|
}
|
|
789
1304
|
|
|
1305
|
+
for (index = 1; index <= table_count; index++) {
|
|
1306
|
+
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
1307
|
+
"/xl/tables/table%d.xml", index);
|
|
1308
|
+
lxw_ct_add_table_name(content_types, filename);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
if (workbook->has_vml)
|
|
1312
|
+
lxw_ct_add_vml_name(content_types);
|
|
1313
|
+
|
|
1314
|
+
for (index = 1; index <= workbook->comment_count; index++) {
|
|
1315
|
+
lxw_snprintf(filename, LXW_FILENAME_LENGTH,
|
|
1316
|
+
"/xl/comments%d.xml", index);
|
|
1317
|
+
lxw_ct_add_comment_name(content_types, filename);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
790
1320
|
if (workbook->sst->string_count)
|
|
791
1321
|
lxw_ct_add_shared_strings(content_types);
|
|
792
1322
|
|
|
793
1323
|
if (!STAILQ_EMPTY(self->workbook->custom_properties))
|
|
794
1324
|
lxw_ct_add_custom_properties(content_types);
|
|
795
1325
|
|
|
1326
|
+
if (workbook->has_metadata)
|
|
1327
|
+
lxw_ct_add_metadata(content_types);
|
|
1328
|
+
|
|
796
1329
|
lxw_content_types_assemble_xml_file(content_types);
|
|
797
1330
|
|
|
798
|
-
err =
|
|
1331
|
+
err = _add_to_zip(self, content_types->file, &buffer, &buffer_size,
|
|
1332
|
+
"[Content_Types].xml");
|
|
799
1333
|
|
|
800
1334
|
fclose(content_types->file);
|
|
1335
|
+
free(buffer);
|
|
801
1336
|
|
|
802
1337
|
mem_error:
|
|
803
1338
|
lxw_content_types_free(content_types);
|
|
@@ -812,6 +1347,8 @@ STATIC lxw_error
|
|
|
812
1347
|
_write_workbook_rels_file(lxw_packager *self)
|
|
813
1348
|
{
|
|
814
1349
|
lxw_relationships *rels = lxw_relationships_new();
|
|
1350
|
+
char *buffer = NULL;
|
|
1351
|
+
size_t buffer_size = 0;
|
|
815
1352
|
lxw_workbook *workbook = self->workbook;
|
|
816
1353
|
lxw_sheet *sheet;
|
|
817
1354
|
char sheetname[LXW_FILENAME_LENGTH] = { 0 };
|
|
@@ -824,7 +1361,7 @@ _write_workbook_rels_file(lxw_packager *self)
|
|
|
824
1361
|
goto mem_error;
|
|
825
1362
|
}
|
|
826
1363
|
|
|
827
|
-
rels->file =
|
|
1364
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
828
1365
|
if (!rels->file) {
|
|
829
1366
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
830
1367
|
goto mem_error;
|
|
@@ -856,11 +1393,16 @@ _write_workbook_rels_file(lxw_packager *self)
|
|
|
856
1393
|
lxw_add_ms_package_relationship(rels, "/vbaProject",
|
|
857
1394
|
"vbaProject.bin");
|
|
858
1395
|
|
|
1396
|
+
if (workbook->has_metadata)
|
|
1397
|
+
lxw_add_document_relationship(rels, "/sheetMetadata", "metadata.xml");
|
|
1398
|
+
|
|
859
1399
|
lxw_relationships_assemble_xml_file(rels);
|
|
860
1400
|
|
|
861
|
-
err =
|
|
1401
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size,
|
|
1402
|
+
"xl/_rels/workbook.xml.rels");
|
|
862
1403
|
|
|
863
1404
|
fclose(rels->file);
|
|
1405
|
+
free(buffer);
|
|
864
1406
|
|
|
865
1407
|
mem_error:
|
|
866
1408
|
lxw_free_relationships(rels);
|
|
@@ -876,6 +1418,8 @@ STATIC lxw_error
|
|
|
876
1418
|
_write_worksheet_rels_file(lxw_packager *self)
|
|
877
1419
|
{
|
|
878
1420
|
lxw_relationships *rels;
|
|
1421
|
+
char *buffer = NULL;
|
|
1422
|
+
size_t buffer_size = 0;
|
|
879
1423
|
lxw_rel_tuple *rel;
|
|
880
1424
|
lxw_workbook *workbook = self->workbook;
|
|
881
1425
|
lxw_sheet *sheet;
|
|
@@ -893,12 +1437,17 @@ _write_worksheet_rels_file(lxw_packager *self)
|
|
|
893
1437
|
index++;
|
|
894
1438
|
|
|
895
1439
|
if (STAILQ_EMPTY(worksheet->external_hyperlinks) &&
|
|
896
|
-
STAILQ_EMPTY(worksheet->external_drawing_links)
|
|
1440
|
+
STAILQ_EMPTY(worksheet->external_drawing_links) &&
|
|
1441
|
+
STAILQ_EMPTY(worksheet->external_table_links) &&
|
|
1442
|
+
!worksheet->external_vml_header_link &&
|
|
1443
|
+
!worksheet->external_vml_comment_link &&
|
|
1444
|
+
!worksheet->external_background_link &&
|
|
1445
|
+
!worksheet->external_comment_link)
|
|
897
1446
|
continue;
|
|
898
1447
|
|
|
899
1448
|
rels = lxw_relationships_new();
|
|
900
1449
|
|
|
901
|
-
rels->file =
|
|
1450
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
902
1451
|
if (!rels->file) {
|
|
903
1452
|
lxw_free_relationships(rels);
|
|
904
1453
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
@@ -914,14 +1463,40 @@ _write_worksheet_rels_file(lxw_packager *self)
|
|
|
914
1463
|
rel->target_mode);
|
|
915
1464
|
}
|
|
916
1465
|
|
|
1466
|
+
rel = worksheet->external_vml_comment_link;
|
|
1467
|
+
if (rel)
|
|
1468
|
+
lxw_add_worksheet_relationship(rels, rel->type, rel->target,
|
|
1469
|
+
rel->target_mode);
|
|
1470
|
+
|
|
1471
|
+
rel = worksheet->external_vml_header_link;
|
|
1472
|
+
if (rel)
|
|
1473
|
+
lxw_add_worksheet_relationship(rels, rel->type, rel->target,
|
|
1474
|
+
rel->target_mode);
|
|
1475
|
+
|
|
1476
|
+
rel = worksheet->external_background_link;
|
|
1477
|
+
if (rel)
|
|
1478
|
+
lxw_add_worksheet_relationship(rels, rel->type, rel->target,
|
|
1479
|
+
rel->target_mode);
|
|
1480
|
+
|
|
1481
|
+
STAILQ_FOREACH(rel, worksheet->external_table_links, list_pointers) {
|
|
1482
|
+
lxw_add_worksheet_relationship(rels, rel->type, rel->target,
|
|
1483
|
+
rel->target_mode);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
rel = worksheet->external_comment_link;
|
|
1487
|
+
if (rel)
|
|
1488
|
+
lxw_add_worksheet_relationship(rels, rel->type, rel->target,
|
|
1489
|
+
rel->target_mode);
|
|
1490
|
+
|
|
917
1491
|
lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
|
|
918
1492
|
"xl/worksheets/_rels/sheet%d.xml.rels", index);
|
|
919
1493
|
|
|
920
1494
|
lxw_relationships_assemble_xml_file(rels);
|
|
921
1495
|
|
|
922
|
-
err =
|
|
1496
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size, sheetname);
|
|
923
1497
|
|
|
924
1498
|
fclose(rels->file);
|
|
1499
|
+
free(buffer);
|
|
925
1500
|
lxw_free_relationships(rels);
|
|
926
1501
|
|
|
927
1502
|
RETURN_ON_ERROR(err);
|
|
@@ -938,6 +1513,8 @@ STATIC lxw_error
|
|
|
938
1513
|
_write_chartsheet_rels_file(lxw_packager *self)
|
|
939
1514
|
{
|
|
940
1515
|
lxw_relationships *rels;
|
|
1516
|
+
char *buffer = NULL;
|
|
1517
|
+
size_t buffer_size = 0;
|
|
941
1518
|
lxw_rel_tuple *rel;
|
|
942
1519
|
lxw_workbook *workbook = self->workbook;
|
|
943
1520
|
lxw_sheet *sheet;
|
|
@@ -954,13 +1531,12 @@ _write_chartsheet_rels_file(lxw_packager *self)
|
|
|
954
1531
|
|
|
955
1532
|
index++;
|
|
956
1533
|
|
|
957
|
-
/* TODO. This should never be empty. Put check higher up. */
|
|
958
1534
|
if (STAILQ_EMPTY(worksheet->external_drawing_links))
|
|
959
1535
|
continue;
|
|
960
1536
|
|
|
961
1537
|
rels = lxw_relationships_new();
|
|
962
1538
|
|
|
963
|
-
rels->file =
|
|
1539
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
964
1540
|
if (!rels->file) {
|
|
965
1541
|
lxw_free_relationships(rels);
|
|
966
1542
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
@@ -981,9 +1557,10 @@ _write_chartsheet_rels_file(lxw_packager *self)
|
|
|
981
1557
|
|
|
982
1558
|
lxw_relationships_assemble_xml_file(rels);
|
|
983
1559
|
|
|
984
|
-
err =
|
|
1560
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size, sheetname);
|
|
985
1561
|
|
|
986
1562
|
fclose(rels->file);
|
|
1563
|
+
free(buffer);
|
|
987
1564
|
lxw_free_relationships(rels);
|
|
988
1565
|
|
|
989
1566
|
RETURN_ON_ERROR(err);
|
|
@@ -1000,6 +1577,8 @@ STATIC lxw_error
|
|
|
1000
1577
|
_write_drawing_rels_file(lxw_packager *self)
|
|
1001
1578
|
{
|
|
1002
1579
|
lxw_relationships *rels;
|
|
1580
|
+
char *buffer = NULL;
|
|
1581
|
+
size_t buffer_size = 0;
|
|
1003
1582
|
lxw_rel_tuple *rel;
|
|
1004
1583
|
lxw_workbook *workbook = self->workbook;
|
|
1005
1584
|
lxw_sheet *sheet;
|
|
@@ -1019,7 +1598,7 @@ _write_drawing_rels_file(lxw_packager *self)
|
|
|
1019
1598
|
|
|
1020
1599
|
rels = lxw_relationships_new();
|
|
1021
1600
|
|
|
1022
|
-
rels->file =
|
|
1601
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
1023
1602
|
if (!rels->file) {
|
|
1024
1603
|
lxw_free_relationships(rels);
|
|
1025
1604
|
return LXW_ERROR_CREATING_TMPFILE;
|
|
@@ -1036,9 +1615,10 @@ _write_drawing_rels_file(lxw_packager *self)
|
|
|
1036
1615
|
|
|
1037
1616
|
lxw_relationships_assemble_xml_file(rels);
|
|
1038
1617
|
|
|
1039
|
-
err =
|
|
1618
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size, sheetname);
|
|
1040
1619
|
|
|
1041
1620
|
fclose(rels->file);
|
|
1621
|
+
free(buffer);
|
|
1042
1622
|
lxw_free_relationships(rels);
|
|
1043
1623
|
|
|
1044
1624
|
RETURN_ON_ERROR(err);
|
|
@@ -1047,6 +1627,93 @@ _write_drawing_rels_file(lxw_packager *self)
|
|
|
1047
1627
|
return LXW_NO_ERROR;
|
|
1048
1628
|
}
|
|
1049
1629
|
|
|
1630
|
+
/*
|
|
1631
|
+
* Write the vmlDrawing .rels files for worksheets that contain images in
|
|
1632
|
+
* headers or footers.
|
|
1633
|
+
*/
|
|
1634
|
+
STATIC lxw_error
|
|
1635
|
+
_write_vml_drawing_rels_file(lxw_packager *self, lxw_worksheet *worksheet,
|
|
1636
|
+
uint32_t index)
|
|
1637
|
+
{
|
|
1638
|
+
lxw_relationships *rels;
|
|
1639
|
+
char *buffer = NULL;
|
|
1640
|
+
size_t buffer_size = 0;
|
|
1641
|
+
lxw_rel_tuple *rel;
|
|
1642
|
+
char sheetname[LXW_FILENAME_LENGTH] = { 0 };
|
|
1643
|
+
lxw_error err = LXW_NO_ERROR;
|
|
1644
|
+
|
|
1645
|
+
rels = lxw_relationships_new();
|
|
1646
|
+
|
|
1647
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
1648
|
+
if (!rels->file) {
|
|
1649
|
+
lxw_free_relationships(rels);
|
|
1650
|
+
return LXW_ERROR_CREATING_TMPFILE;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
STAILQ_FOREACH(rel, worksheet->vml_drawing_links, list_pointers) {
|
|
1654
|
+
lxw_add_worksheet_relationship(rels, rel->type, rel->target,
|
|
1655
|
+
rel->target_mode);
|
|
1656
|
+
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
|
|
1660
|
+
"xl/drawings/_rels/vmlDrawing%d.vml.rels", index);
|
|
1661
|
+
|
|
1662
|
+
lxw_relationships_assemble_xml_file(rels);
|
|
1663
|
+
|
|
1664
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size, sheetname);
|
|
1665
|
+
|
|
1666
|
+
fclose(rels->file);
|
|
1667
|
+
free(buffer);
|
|
1668
|
+
lxw_free_relationships(rels);
|
|
1669
|
+
|
|
1670
|
+
return err;
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
/*
|
|
1674
|
+
* Write the vbaProject .rels xml file.
|
|
1675
|
+
*/
|
|
1676
|
+
STATIC lxw_error
|
|
1677
|
+
_write_vba_project_rels_file(lxw_packager *self)
|
|
1678
|
+
{
|
|
1679
|
+
lxw_relationships *rels;
|
|
1680
|
+
lxw_workbook *workbook = self->workbook;
|
|
1681
|
+
lxw_error err = LXW_NO_ERROR;
|
|
1682
|
+
char *buffer = NULL;
|
|
1683
|
+
size_t buffer_size = 0;
|
|
1684
|
+
|
|
1685
|
+
if (!workbook->vba_project_signature)
|
|
1686
|
+
return LXW_NO_ERROR;
|
|
1687
|
+
|
|
1688
|
+
rels = lxw_relationships_new();
|
|
1689
|
+
if (!rels) {
|
|
1690
|
+
err = LXW_ERROR_MEMORY_MALLOC_FAILED;
|
|
1691
|
+
goto mem_error;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
1695
|
+
if (!rels->file) {
|
|
1696
|
+
err = LXW_ERROR_CREATING_TMPFILE;
|
|
1697
|
+
goto mem_error;
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
lxw_add_ms_package_relationship(rels, "/vbaProjectSignature",
|
|
1701
|
+
"vbaProjectSignature.bin");
|
|
1702
|
+
|
|
1703
|
+
lxw_relationships_assemble_xml_file(rels);
|
|
1704
|
+
|
|
1705
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size,
|
|
1706
|
+
"xl/_rels/vbaProject.bin.rels");
|
|
1707
|
+
|
|
1708
|
+
fclose(rels->file);
|
|
1709
|
+
free(buffer);
|
|
1710
|
+
|
|
1711
|
+
mem_error:
|
|
1712
|
+
lxw_free_relationships(rels);
|
|
1713
|
+
|
|
1714
|
+
return err;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1050
1717
|
/*
|
|
1051
1718
|
* Write the _rels/.rels xml file.
|
|
1052
1719
|
*/
|
|
@@ -1054,6 +1721,8 @@ STATIC lxw_error
|
|
|
1054
1721
|
_write_root_rels_file(lxw_packager *self)
|
|
1055
1722
|
{
|
|
1056
1723
|
lxw_relationships *rels = lxw_relationships_new();
|
|
1724
|
+
char *buffer = NULL;
|
|
1725
|
+
size_t buffer_size = 0;
|
|
1057
1726
|
lxw_error err = LXW_NO_ERROR;
|
|
1058
1727
|
|
|
1059
1728
|
if (!rels) {
|
|
@@ -1061,7 +1730,7 @@ _write_root_rels_file(lxw_packager *self)
|
|
|
1061
1730
|
goto mem_error;
|
|
1062
1731
|
}
|
|
1063
1732
|
|
|
1064
|
-
rels->file =
|
|
1733
|
+
rels->file = lxw_get_filehandle(&buffer, &buffer_size, self->tmpdir);
|
|
1065
1734
|
if (!rels->file) {
|
|
1066
1735
|
err = LXW_ERROR_CREATING_TMPFILE;
|
|
1067
1736
|
goto mem_error;
|
|
@@ -1083,9 +1752,10 @@ _write_root_rels_file(lxw_packager *self)
|
|
|
1083
1752
|
|
|
1084
1753
|
lxw_relationships_assemble_xml_file(rels);
|
|
1085
1754
|
|
|
1086
|
-
err =
|
|
1755
|
+
err = _add_to_zip(self, rels->file, &buffer, &buffer_size, "_rels/.rels");
|
|
1087
1756
|
|
|
1088
1757
|
fclose(rels->file);
|
|
1758
|
+
free(buffer);
|
|
1089
1759
|
|
|
1090
1760
|
mem_error:
|
|
1091
1761
|
lxw_free_relationships(rels);
|
|
@@ -1122,12 +1792,12 @@ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
|
|
|
1122
1792
|
fflush(file);
|
|
1123
1793
|
rewind(file);
|
|
1124
1794
|
|
|
1125
|
-
size_read = fread(self->buffer, 1, self->buffer_size, file);
|
|
1795
|
+
size_read = fread((void *) self->buffer, 1, self->buffer_size, file);
|
|
1126
1796
|
|
|
1127
1797
|
while (size_read) {
|
|
1128
1798
|
|
|
1129
1799
|
if (size_read < self->buffer_size) {
|
|
1130
|
-
if (
|
|
1800
|
+
if (ferror(file)) {
|
|
1131
1801
|
LXW_ERROR("Error reading member file data");
|
|
1132
1802
|
RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
|
|
1133
1803
|
}
|
|
@@ -1141,7 +1811,8 @@ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
|
|
|
1141
1811
|
RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
|
|
1142
1812
|
}
|
|
1143
1813
|
|
|
1144
|
-
size_read =
|
|
1814
|
+
size_read =
|
|
1815
|
+
fread((void *) (void *) self->buffer, 1, self->buffer_size, file);
|
|
1145
1816
|
}
|
|
1146
1817
|
|
|
1147
1818
|
error = zipCloseFileInZip(self->zipfile);
|
|
@@ -1154,8 +1825,8 @@ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
|
|
|
1154
1825
|
}
|
|
1155
1826
|
|
|
1156
1827
|
STATIC lxw_error
|
|
1157
|
-
_add_buffer_to_zip(lxw_packager *self,
|
|
1158
|
-
|
|
1828
|
+
_add_buffer_to_zip(lxw_packager *self, const char *buffer, size_t buffer_size,
|
|
1829
|
+
const char *filename)
|
|
1159
1830
|
{
|
|
1160
1831
|
int16_t error = ZIP_OK;
|
|
1161
1832
|
|
|
@@ -1190,8 +1861,19 @@ _add_buffer_to_zip(lxw_packager *self, unsigned char *buffer,
|
|
|
1190
1861
|
return LXW_NO_ERROR;
|
|
1191
1862
|
}
|
|
1192
1863
|
|
|
1864
|
+
STATIC lxw_error
|
|
1865
|
+
_add_to_zip(lxw_packager *self, FILE * file, char **buffer,
|
|
1866
|
+
size_t *buffer_size, const char *filename)
|
|
1867
|
+
{
|
|
1868
|
+
/* Flush to ensure buffer is updated when using a memory-backed file. */
|
|
1869
|
+
fflush(file);
|
|
1870
|
+
return *buffer ?
|
|
1871
|
+
_add_buffer_to_zip(self, *buffer, *buffer_size, filename) :
|
|
1872
|
+
_add_file_to_zip(self, file, filename);
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1193
1875
|
/*
|
|
1194
|
-
* Write the xml files that make up the
|
|
1876
|
+
* Write the xml files that make up the XLSX OPC package.
|
|
1195
1877
|
*/
|
|
1196
1878
|
lxw_error
|
|
1197
1879
|
lxw_create_package(lxw_packager *self)
|
|
@@ -1200,61 +1882,79 @@ lxw_create_package(lxw_packager *self)
|
|
|
1200
1882
|
int8_t zip_error;
|
|
1201
1883
|
|
|
1202
1884
|
error = _write_content_types_file(self);
|
|
1203
|
-
|
|
1885
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1204
1886
|
|
|
1205
1887
|
error = _write_root_rels_file(self);
|
|
1206
|
-
|
|
1888
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1207
1889
|
|
|
1208
1890
|
error = _write_workbook_rels_file(self);
|
|
1209
|
-
|
|
1891
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1210
1892
|
|
|
1211
1893
|
error = _write_worksheet_files(self);
|
|
1212
|
-
|
|
1894
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1213
1895
|
|
|
1214
1896
|
error = _write_chartsheet_files(self);
|
|
1215
|
-
|
|
1897
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1216
1898
|
|
|
1217
1899
|
error = _write_workbook_file(self);
|
|
1218
|
-
|
|
1900
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1219
1901
|
|
|
1220
1902
|
error = _write_chart_files(self);
|
|
1221
|
-
|
|
1903
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1222
1904
|
|
|
1223
1905
|
error = _write_drawing_files(self);
|
|
1224
|
-
|
|
1906
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1907
|
+
|
|
1908
|
+
error = _write_vml_files(self);
|
|
1909
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1910
|
+
|
|
1911
|
+
error = _write_comment_files(self);
|
|
1912
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1913
|
+
|
|
1914
|
+
error = _write_table_files(self);
|
|
1915
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1225
1916
|
|
|
1226
1917
|
error = _write_shared_strings_file(self);
|
|
1227
|
-
|
|
1918
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1228
1919
|
|
|
1229
1920
|
error = _write_custom_file(self);
|
|
1230
|
-
|
|
1921
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1231
1922
|
|
|
1232
1923
|
error = _write_theme_file(self);
|
|
1233
|
-
|
|
1924
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1234
1925
|
|
|
1235
1926
|
error = _write_styles_file(self);
|
|
1236
|
-
|
|
1927
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1237
1928
|
|
|
1238
1929
|
error = _write_worksheet_rels_file(self);
|
|
1239
|
-
|
|
1930
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1240
1931
|
|
|
1241
1932
|
error = _write_chartsheet_rels_file(self);
|
|
1242
|
-
|
|
1933
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1243
1934
|
|
|
1244
1935
|
error = _write_drawing_rels_file(self);
|
|
1245
|
-
|
|
1936
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1246
1937
|
|
|
1247
1938
|
error = _write_image_files(self);
|
|
1248
|
-
|
|
1939
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1249
1940
|
|
|
1250
1941
|
error = _add_vba_project(self);
|
|
1251
|
-
|
|
1942
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1943
|
+
|
|
1944
|
+
error = _add_vba_project_signature(self);
|
|
1945
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1946
|
+
|
|
1947
|
+
error = _write_vba_project_rels_file(self);
|
|
1948
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1252
1949
|
|
|
1253
1950
|
error = _write_core_file(self);
|
|
1254
|
-
|
|
1951
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1952
|
+
|
|
1953
|
+
error = _write_metadata_file(self);
|
|
1954
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1255
1955
|
|
|
1256
1956
|
error = _write_app_file(self);
|
|
1257
|
-
|
|
1957
|
+
RETURN_AND_ZIPCLOSE_ON_ERROR(error);
|
|
1258
1958
|
|
|
1259
1959
|
zip_error = zipClose(self->zipfile, NULL);
|
|
1260
1960
|
if (zip_error) {
|