fast_excel 0.1.4 → 0.1.5

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -2
  3. data/Makefile +14 -0
  4. data/README.md +7 -2
  5. data/Rakefile +10 -0
  6. data/extconf.rb +0 -0
  7. data/fast_excel.gemspec +3 -1
  8. data/lib/fast_excel/binding.rb +3 -7
  9. data/lib/rubygems_plugin.rb +3 -0
  10. data/libxlsxwriter/.gitignore +49 -0
  11. data/libxlsxwriter/.indent.pro +125 -0
  12. data/libxlsxwriter/.travis.yml +25 -0
  13. data/libxlsxwriter/CONTRIBUTING.md +226 -0
  14. data/libxlsxwriter/Changes.txt +557 -0
  15. data/libxlsxwriter/LICENSE.txt +89 -0
  16. data/libxlsxwriter/Makefile +156 -0
  17. data/libxlsxwriter/Readme.md +78 -0
  18. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +30 -0
  19. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +7 -0
  20. data/libxlsxwriter/include/xlsxwriter/app.h +79 -0
  21. data/libxlsxwriter/include/xlsxwriter/chart.h +3476 -0
  22. data/libxlsxwriter/include/xlsxwriter/common.h +372 -0
  23. data/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
  24. data/libxlsxwriter/include/xlsxwriter/core.h +51 -0
  25. data/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
  26. data/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
  27. data/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
  28. data/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
  29. data/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
  30. data/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
  31. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
  32. data/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
  33. data/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
  34. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +214 -0
  35. data/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
  36. data/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
  37. data/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
  38. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
  39. data/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
  40. data/libxlsxwriter/include/xlsxwriter/workbook.h +757 -0
  41. data/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
  42. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
  43. data/libxlsxwriter/include/xlsxwriter.h +23 -0
  44. data/libxlsxwriter/lib/.gitignore +0 -0
  45. data/libxlsxwriter/libxlsxwriter.podspec +47 -0
  46. data/libxlsxwriter/src/Makefile +130 -0
  47. data/libxlsxwriter/src/app.c +443 -0
  48. data/libxlsxwriter/src/chart.c +6346 -0
  49. data/libxlsxwriter/src/content_types.c +345 -0
  50. data/libxlsxwriter/src/core.c +293 -0
  51. data/libxlsxwriter/src/custom.c +224 -0
  52. data/libxlsxwriter/src/drawing.c +746 -0
  53. data/libxlsxwriter/src/format.c +729 -0
  54. data/libxlsxwriter/src/hash_table.c +223 -0
  55. data/libxlsxwriter/src/packager.c +948 -0
  56. data/libxlsxwriter/src/relationships.c +245 -0
  57. data/libxlsxwriter/src/shared_strings.c +266 -0
  58. data/libxlsxwriter/src/styles.c +1088 -0
  59. data/libxlsxwriter/src/theme.c +348 -0
  60. data/libxlsxwriter/src/utility.c +515 -0
  61. data/libxlsxwriter/src/workbook.c +1930 -0
  62. data/libxlsxwriter/src/worksheet.c +5022 -0
  63. data/libxlsxwriter/src/xmlwriter.c +355 -0
  64. data/libxlsxwriter/third_party/minizip/Makefile +44 -0
  65. data/libxlsxwriter/third_party/minizip/Makefile.am +45 -0
  66. data/libxlsxwriter/third_party/minizip/Makefile.orig +25 -0
  67. data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +6 -0
  68. data/libxlsxwriter/third_party/minizip/MiniZip64_info.txt +74 -0
  69. data/libxlsxwriter/third_party/minizip/README.txt +5 -0
  70. data/libxlsxwriter/third_party/minizip/configure.ac +32 -0
  71. data/libxlsxwriter/third_party/minizip/crypt.h +131 -0
  72. data/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
  73. data/libxlsxwriter/third_party/minizip/ioapi.h +208 -0
  74. data/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
  75. data/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
  76. data/libxlsxwriter/third_party/minizip/make_vms.com +25 -0
  77. data/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
  78. data/libxlsxwriter/third_party/minizip/miniunzip.1 +63 -0
  79. data/libxlsxwriter/third_party/minizip/minizip.1 +46 -0
  80. data/libxlsxwriter/third_party/minizip/minizip.c +520 -0
  81. data/libxlsxwriter/third_party/minizip/minizip.pc.in +12 -0
  82. data/libxlsxwriter/third_party/minizip/mztools.c +291 -0
  83. data/libxlsxwriter/third_party/minizip/mztools.h +37 -0
  84. data/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
  85. data/libxlsxwriter/third_party/minizip/unzip.h +437 -0
  86. data/libxlsxwriter/third_party/minizip/zip.c +2007 -0
  87. data/libxlsxwriter/third_party/minizip/zip.h +367 -0
  88. data/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
  89. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
  90. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
  91. data/libxlsxwriter/version.txt +1 -0
  92. metadata +89 -6
  93. data/binaries/libxlsxwriter-alpine.so +0 -0
  94. data/binaries/libxlsxwriter-darwin.dylib +0 -0
  95. data/binaries/libxlsxwriter-glibc.so +0 -0
@@ -0,0 +1,948 @@
1
+ /*****************************************************************************
2
+ * packager - A library for creating Excel XLSX packager files.
3
+ *
4
+ * Used in conjunction with the libxlsxwriter library.
5
+ *
6
+ * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
+ *
8
+ */
9
+
10
+ #include "xlsxwriter/xmlwriter.h"
11
+ #include "xlsxwriter/packager.h"
12
+ #include "xlsxwriter/hash_table.h"
13
+ #include "xlsxwriter/utility.h"
14
+
15
+ STATIC lxw_error _add_file_to_zip(lxw_packager *self, FILE * file,
16
+ const char *filename);
17
+
18
+ /*
19
+ * Forward declarations.
20
+ */
21
+
22
+ /*****************************************************************************
23
+ *
24
+ * Private functions.
25
+ *
26
+ ****************************************************************************/
27
+ /* Avoid non MSVC definition of _WIN32 in MinGW. */
28
+
29
+ #ifdef __MINGW32__
30
+ #undef _WIN32
31
+ #endif
32
+
33
+ #ifdef _WIN32
34
+
35
+ /* Silence Windows warning with duplicate symbol for SLIST_ENTRY in local
36
+ * queue.h and widows.h. */
37
+ #undef SLIST_ENTRY
38
+
39
+ #include <windows.h>
40
+ #include "../third_party/minizip/iowin32.h"
41
+
42
+ zipFile
43
+ _open_zipfile_win32(const char *filename)
44
+ {
45
+ int n;
46
+ zlib_filefunc64_def filefunc;
47
+
48
+ wchar_t wide_filename[_MAX_PATH + 1] = L"";
49
+
50
+ /* Build a UTF-16 filename for Win32. */
51
+ n = MultiByteToWideChar(CP_UTF8, 0, filename, (int) strlen(filename),
52
+ wide_filename, _MAX_PATH);
53
+
54
+ if (n == 0) {
55
+ LXW_ERROR("MultiByteToWideChar error");
56
+ return NULL;
57
+ }
58
+
59
+ /* Use the native Win32 file handling functions with minizip. */
60
+ fill_win32_filefunc64(&filefunc);
61
+
62
+ return zipOpen2_64(wide_filename, 0, NULL, &filefunc);
63
+ }
64
+
65
+ #endif
66
+
67
+ /*
68
+ * Create a new packager object.
69
+ */
70
+ lxw_packager *
71
+ lxw_packager_new(const char *filename, char *tmpdir)
72
+ {
73
+ lxw_packager *packager = calloc(1, sizeof(lxw_packager));
74
+ GOTO_LABEL_ON_MEM_ERROR(packager, mem_error);
75
+
76
+ packager->buffer = calloc(1, LXW_ZIP_BUFFER_SIZE);
77
+ GOTO_LABEL_ON_MEM_ERROR(packager->buffer, mem_error);
78
+
79
+ packager->filename = lxw_strdup(filename);
80
+ packager->tmpdir = tmpdir;
81
+ GOTO_LABEL_ON_MEM_ERROR(packager->filename, mem_error);
82
+
83
+ packager->buffer_size = LXW_ZIP_BUFFER_SIZE;
84
+
85
+ /* Initialize the zip_fileinfo struct to Jan 1 1980 like Excel. */
86
+ packager->zipfile_info.tmz_date.tm_sec = 0;
87
+ packager->zipfile_info.tmz_date.tm_min = 0;
88
+ packager->zipfile_info.tmz_date.tm_hour = 0;
89
+ packager->zipfile_info.tmz_date.tm_mday = 1;
90
+ packager->zipfile_info.tmz_date.tm_mon = 0;
91
+ packager->zipfile_info.tmz_date.tm_year = 1980;
92
+ packager->zipfile_info.dosDate = 0;
93
+ packager->zipfile_info.internal_fa = 0;
94
+ packager->zipfile_info.external_fa = 0;
95
+
96
+ /* Create a zip container for the xlsx file. */
97
+ #ifdef _WIN32
98
+ packager->zipfile = _open_zipfile_win32(packager->filename);
99
+ #else
100
+ packager->zipfile = zipOpen(packager->filename, 0);
101
+ #endif
102
+
103
+ if (packager->zipfile == NULL)
104
+ goto mem_error;
105
+
106
+ return packager;
107
+
108
+ mem_error:
109
+ lxw_packager_free(packager);
110
+ return NULL;
111
+ }
112
+
113
+ /*
114
+ * Free a packager object.
115
+ */
116
+ void
117
+ lxw_packager_free(lxw_packager *packager)
118
+ {
119
+ if (!packager)
120
+ return;
121
+
122
+ free(packager->buffer);
123
+ free(packager->filename);
124
+ free(packager);
125
+ }
126
+
127
+ /*****************************************************************************
128
+ *
129
+ * File assembly functions.
130
+ *
131
+ ****************************************************************************/
132
+ /*
133
+ * Write the workbook.xml file.
134
+ */
135
+ STATIC lxw_error
136
+ _write_workbook_file(lxw_packager *self)
137
+ {
138
+ lxw_workbook *workbook = self->workbook;
139
+ lxw_error err;
140
+
141
+ workbook->file = lxw_tmpfile(self->tmpdir);
142
+ if (!workbook->file)
143
+ return LXW_ERROR_CREATING_TMPFILE;
144
+
145
+ lxw_workbook_assemble_xml_file(workbook);
146
+
147
+ err = _add_file_to_zip(self, workbook->file, "xl/workbook.xml");
148
+ RETURN_ON_ERROR(err);
149
+
150
+ fclose(workbook->file);
151
+
152
+ return LXW_NO_ERROR;
153
+ }
154
+
155
+ /*
156
+ * Write the worksheet files.
157
+ */
158
+ STATIC lxw_error
159
+ _write_worksheet_files(lxw_packager *self)
160
+ {
161
+ lxw_workbook *workbook = self->workbook;
162
+ lxw_worksheet *worksheet;
163
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
164
+ uint16_t index = 1;
165
+ lxw_error err;
166
+
167
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
168
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
169
+ "xl/worksheets/sheet%d.xml", index++);
170
+
171
+ if (worksheet->optimize_row)
172
+ lxw_worksheet_write_single_row(worksheet);
173
+
174
+ worksheet->file = lxw_tmpfile(self->tmpdir);
175
+ if (!worksheet->file)
176
+ return LXW_ERROR_CREATING_TMPFILE;
177
+
178
+ lxw_worksheet_assemble_xml_file(worksheet);
179
+
180
+ err = _add_file_to_zip(self, worksheet->file, sheetname);
181
+ RETURN_ON_ERROR(err);
182
+
183
+ fclose(worksheet->file);
184
+ }
185
+
186
+ return LXW_NO_ERROR;
187
+ }
188
+
189
+ /*
190
+ * Write the /xl/media/image?.xml files.
191
+ */
192
+ STATIC lxw_error
193
+ _write_image_files(lxw_packager *self)
194
+ {
195
+ lxw_workbook *workbook = self->workbook;
196
+ lxw_worksheet *worksheet;
197
+ lxw_image_options *image;
198
+ lxw_error err;
199
+
200
+ char filename[LXW_FILENAME_LENGTH] = { 0 };
201
+ uint16_t index = 1;
202
+
203
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
204
+
205
+ if (STAILQ_EMPTY(worksheet->image_data))
206
+ continue;
207
+
208
+ STAILQ_FOREACH(image, worksheet->image_data, list_pointers) {
209
+
210
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
211
+ "xl/media/image%d.%s", index++, image->extension);
212
+
213
+ rewind(image->stream);
214
+
215
+ err = _add_file_to_zip(self, image->stream, filename);
216
+ RETURN_ON_ERROR(err);
217
+
218
+ fclose(image->stream);
219
+ }
220
+ }
221
+
222
+ return LXW_NO_ERROR;
223
+ }
224
+
225
+ /*
226
+ * Write the chart files.
227
+ */
228
+ STATIC lxw_error
229
+ _write_chart_files(lxw_packager *self)
230
+ {
231
+ lxw_workbook *workbook = self->workbook;
232
+ lxw_chart *chart;
233
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
234
+ uint16_t index = 1;
235
+ lxw_error err;
236
+
237
+ STAILQ_FOREACH(chart, workbook->ordered_charts, ordered_list_pointers) {
238
+
239
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
240
+ "xl/charts/chart%d.xml", index++);
241
+
242
+ chart->file = lxw_tmpfile(self->tmpdir);
243
+ if (!chart->file)
244
+ return LXW_ERROR_CREATING_TMPFILE;
245
+
246
+ lxw_chart_assemble_xml_file(chart);
247
+
248
+ err = _add_file_to_zip(self, chart->file, sheetname);
249
+ RETURN_ON_ERROR(err);
250
+
251
+ self->chart_count++;
252
+
253
+ fclose(chart->file);
254
+ }
255
+
256
+ return LXW_NO_ERROR;
257
+ }
258
+
259
+ /*
260
+ * Write the drawing files.
261
+ */
262
+ STATIC lxw_error
263
+ _write_drawing_files(lxw_packager *self)
264
+ {
265
+ lxw_workbook *workbook = self->workbook;
266
+ lxw_worksheet *worksheet;
267
+ lxw_drawing *drawing;
268
+ char filename[LXW_FILENAME_LENGTH] = { 0 };
269
+ uint16_t index = 1;
270
+ lxw_error err;
271
+
272
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
273
+ drawing = worksheet->drawing;
274
+
275
+ if (drawing) {
276
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
277
+ "xl/drawings/drawing%d.xml", index++);
278
+
279
+ drawing->file = lxw_tmpfile(self->tmpdir);
280
+ if (!drawing->file)
281
+ return LXW_ERROR_CREATING_TMPFILE;
282
+
283
+ lxw_drawing_assemble_xml_file(drawing);
284
+ err = _add_file_to_zip(self, drawing->file, filename);
285
+ RETURN_ON_ERROR(err);
286
+
287
+ fclose(drawing->file);
288
+
289
+ self->drawing_count++;
290
+ }
291
+ }
292
+
293
+ return LXW_NO_ERROR;
294
+ }
295
+
296
+ /*
297
+ * Write the sharedStrings.xml file.
298
+ */
299
+ STATIC lxw_error
300
+ _write_shared_strings_file(lxw_packager *self)
301
+ {
302
+ lxw_sst *sst = self->workbook->sst;
303
+ lxw_error err;
304
+
305
+ /* Skip the sharedStrings file if there are no shared strings. */
306
+ if (!sst->string_count)
307
+ return LXW_NO_ERROR;
308
+
309
+ sst->file = lxw_tmpfile(self->tmpdir);
310
+ if (!sst->file)
311
+ return LXW_ERROR_CREATING_TMPFILE;
312
+
313
+ lxw_sst_assemble_xml_file(sst);
314
+
315
+ err = _add_file_to_zip(self, sst->file, "xl/sharedStrings.xml");
316
+ RETURN_ON_ERROR(err);
317
+
318
+ fclose(sst->file);
319
+
320
+ return LXW_NO_ERROR;
321
+ }
322
+
323
+ /*
324
+ * Write the app.xml file.
325
+ */
326
+ STATIC lxw_error
327
+ _write_app_file(lxw_packager *self)
328
+ {
329
+ lxw_workbook *workbook = self->workbook;
330
+ lxw_worksheet *worksheet;
331
+ lxw_defined_name *defined_name;
332
+ lxw_app *app;
333
+ uint16_t named_range_count = 0;
334
+ char *autofilter;
335
+ char *has_range;
336
+ char number[LXW_ATTR_32] = { 0 };
337
+ lxw_error err = LXW_NO_ERROR;
338
+
339
+ app = lxw_app_new();
340
+ if (!app) {
341
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
342
+ goto mem_error;
343
+ }
344
+
345
+ app->file = lxw_tmpfile(self->tmpdir);
346
+ if (!app->file) {
347
+ err = LXW_ERROR_CREATING_TMPFILE;
348
+ goto mem_error;
349
+ }
350
+
351
+ lxw_snprintf(number, LXW_ATTR_32, "%d", self->workbook->num_sheets);
352
+
353
+ lxw_app_add_heading_pair(app, "Worksheets", number);
354
+
355
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
356
+ lxw_app_add_part_name(app, worksheet->name);
357
+ }
358
+
359
+ /* Add the Named Ranges parts. */
360
+ TAILQ_FOREACH(defined_name, workbook->defined_names, list_pointers) {
361
+
362
+ has_range = strchr(defined_name->formula, '!');
363
+ autofilter = strstr(defined_name->app_name, "_FilterDatabase");
364
+
365
+ /* Only store defined names with ranges (except for autofilters). */
366
+ if (has_range && !autofilter) {
367
+ lxw_app_add_part_name(app, defined_name->app_name);
368
+ named_range_count++;
369
+ }
370
+ }
371
+
372
+ /* Add the Named Range heading pairs. */
373
+ if (named_range_count) {
374
+ lxw_snprintf(number, LXW_ATTR_32, "%d", named_range_count);
375
+ lxw_app_add_heading_pair(app, "Named Ranges", number);
376
+ }
377
+
378
+ /* Set the app/doc properties. */
379
+ app->properties = workbook->properties;
380
+
381
+ lxw_app_assemble_xml_file(app);
382
+
383
+ err = _add_file_to_zip(self, app->file, "docProps/app.xml");
384
+
385
+ fclose(app->file);
386
+
387
+ mem_error:
388
+ lxw_app_free(app);
389
+
390
+ return err;
391
+ }
392
+
393
+ /*
394
+ * Write the core.xml file.
395
+ */
396
+ STATIC lxw_error
397
+ _write_core_file(lxw_packager *self)
398
+ {
399
+ lxw_error err = LXW_NO_ERROR;
400
+ lxw_core *core = lxw_core_new();
401
+
402
+ if (!core) {
403
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
404
+ goto mem_error;
405
+ }
406
+
407
+ core->file = lxw_tmpfile(self->tmpdir);
408
+ if (!core->file) {
409
+ err = LXW_ERROR_CREATING_TMPFILE;
410
+ goto mem_error;
411
+ }
412
+
413
+ core->properties = self->workbook->properties;
414
+
415
+ lxw_core_assemble_xml_file(core);
416
+
417
+ err = _add_file_to_zip(self, core->file, "docProps/core.xml");
418
+
419
+ fclose(core->file);
420
+
421
+ mem_error:
422
+ lxw_core_free(core);
423
+
424
+ return err;
425
+ }
426
+
427
+ /*
428
+ * Write the custom.xml file.
429
+ */
430
+ STATIC lxw_error
431
+ _write_custom_file(lxw_packager *self)
432
+ {
433
+ lxw_custom *custom;
434
+ lxw_error err = LXW_NO_ERROR;
435
+
436
+ if (STAILQ_EMPTY(self->workbook->custom_properties))
437
+ return LXW_NO_ERROR;
438
+
439
+ custom = lxw_custom_new();
440
+ if (!custom) {
441
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
442
+ goto mem_error;
443
+ }
444
+
445
+ custom->file = lxw_tmpfile(self->tmpdir);
446
+ if (!custom->file) {
447
+ err = LXW_ERROR_CREATING_TMPFILE;
448
+ goto mem_error;
449
+ }
450
+
451
+ custom->custom_properties = self->workbook->custom_properties;
452
+
453
+ lxw_custom_assemble_xml_file(custom);
454
+
455
+ err = _add_file_to_zip(self, custom->file, "docProps/custom.xml");
456
+
457
+ fclose(custom->file);
458
+
459
+ mem_error:
460
+ lxw_custom_free(custom);
461
+ return err;
462
+ }
463
+
464
+ /*
465
+ * Write the theme.xml file.
466
+ */
467
+ STATIC lxw_error
468
+ _write_theme_file(lxw_packager *self)
469
+ {
470
+ lxw_error err = LXW_NO_ERROR;
471
+ lxw_theme *theme = lxw_theme_new();
472
+
473
+ if (!theme) {
474
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
475
+ goto mem_error;
476
+ }
477
+
478
+ theme->file = lxw_tmpfile(self->tmpdir);
479
+ if (!theme->file) {
480
+ err = LXW_ERROR_CREATING_TMPFILE;
481
+ goto mem_error;
482
+ }
483
+
484
+ lxw_theme_assemble_xml_file(theme);
485
+
486
+ err = _add_file_to_zip(self, theme->file, "xl/theme/theme1.xml");
487
+
488
+ fclose(theme->file);
489
+
490
+ mem_error:
491
+ lxw_theme_free(theme);
492
+
493
+ return err;
494
+ }
495
+
496
+ /*
497
+ * Write the styles.xml file.
498
+ */
499
+ STATIC lxw_error
500
+ _write_styles_file(lxw_packager *self)
501
+ {
502
+ lxw_styles *styles = lxw_styles_new();
503
+ lxw_hash_element *hash_element;
504
+ lxw_error err = LXW_NO_ERROR;
505
+
506
+ if (!styles) {
507
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
508
+ goto mem_error;
509
+ }
510
+
511
+ /* Copy the unique and in-use formats from the workbook to the styles
512
+ * xf_format list. */
513
+ LXW_FOREACH_ORDERED(hash_element, self->workbook->used_xf_formats) {
514
+ lxw_format *workbook_format = (lxw_format *) hash_element->value;
515
+ lxw_format *style_format = lxw_format_new();
516
+
517
+ if (!style_format) {
518
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
519
+ goto mem_error;
520
+ }
521
+
522
+ memcpy(style_format, workbook_format, sizeof(lxw_format));
523
+ STAILQ_INSERT_TAIL(styles->xf_formats, style_format, list_pointers);
524
+ }
525
+
526
+ styles->font_count = self->workbook->font_count;
527
+ styles->border_count = self->workbook->border_count;
528
+ styles->fill_count = self->workbook->fill_count;
529
+ styles->num_format_count = self->workbook->num_format_count;
530
+ styles->xf_count = self->workbook->used_xf_formats->unique_count;
531
+
532
+ styles->file = lxw_tmpfile(self->tmpdir);
533
+ if (!styles->file) {
534
+ err = LXW_ERROR_CREATING_TMPFILE;
535
+ goto mem_error;
536
+ }
537
+
538
+ lxw_styles_assemble_xml_file(styles);
539
+
540
+ err = _add_file_to_zip(self, styles->file, "xl/styles.xml");
541
+
542
+ fclose(styles->file);
543
+
544
+ mem_error:
545
+ lxw_styles_free(styles);
546
+
547
+ return err;
548
+ }
549
+
550
+ /*
551
+ * Write the ContentTypes.xml file.
552
+ */
553
+ STATIC lxw_error
554
+ _write_content_types_file(lxw_packager *self)
555
+ {
556
+ lxw_content_types *content_types = lxw_content_types_new();
557
+ lxw_workbook *workbook = self->workbook;
558
+ lxw_worksheet *worksheet;
559
+ char filename[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
560
+ uint16_t index = 1;
561
+ lxw_error err = LXW_NO_ERROR;
562
+
563
+ if (!content_types) {
564
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
565
+ goto mem_error;
566
+ }
567
+
568
+ content_types->file = lxw_tmpfile(self->tmpdir);
569
+ if (!content_types->file) {
570
+ err = LXW_ERROR_CREATING_TMPFILE;
571
+ goto mem_error;
572
+ }
573
+
574
+ if (workbook->has_png)
575
+ lxw_ct_add_default(content_types, "png", "image/png");
576
+
577
+ if (workbook->has_jpeg)
578
+ lxw_ct_add_default(content_types, "jpeg", "image/jpeg");
579
+
580
+ if (workbook->has_bmp)
581
+ lxw_ct_add_default(content_types, "bmp", "image/bmp");
582
+
583
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
584
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
585
+ "/xl/worksheets/sheet%d.xml", index++);
586
+ lxw_ct_add_worksheet_name(content_types, filename);
587
+ }
588
+
589
+ for (index = 1; index <= self->chart_count; index++) {
590
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH, "/xl/charts/chart%d.xml",
591
+ index);
592
+ lxw_ct_add_chart_name(content_types, filename);
593
+ }
594
+
595
+ for (index = 1; index <= self->drawing_count; index++) {
596
+ lxw_snprintf(filename, LXW_FILENAME_LENGTH,
597
+ "/xl/drawings/drawing%d.xml", index);
598
+ lxw_ct_add_drawing_name(content_types, filename);
599
+ }
600
+
601
+ if (workbook->sst->string_count)
602
+ lxw_ct_add_shared_strings(content_types);
603
+
604
+ if (!STAILQ_EMPTY(self->workbook->custom_properties))
605
+ lxw_ct_add_custom_properties(content_types);
606
+
607
+ lxw_content_types_assemble_xml_file(content_types);
608
+
609
+ err = _add_file_to_zip(self, content_types->file, "[Content_Types].xml");
610
+
611
+ fclose(content_types->file);
612
+
613
+ mem_error:
614
+ lxw_content_types_free(content_types);
615
+
616
+ return err;
617
+ }
618
+
619
+ /*
620
+ * Write the workbook .rels xml file.
621
+ */
622
+ STATIC lxw_error
623
+ _write_workbook_rels_file(lxw_packager *self)
624
+ {
625
+ lxw_relationships *rels = lxw_relationships_new();
626
+ lxw_workbook *workbook = self->workbook;
627
+ lxw_worksheet *worksheet;
628
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
629
+ uint16_t index = 1;
630
+ lxw_error err = LXW_NO_ERROR;
631
+
632
+ if (!rels) {
633
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
634
+ goto mem_error;
635
+ }
636
+
637
+ rels->file = lxw_tmpfile(self->tmpdir);
638
+ if (!rels->file) {
639
+ err = LXW_ERROR_CREATING_TMPFILE;
640
+ goto mem_error;
641
+ }
642
+
643
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
644
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH, "worksheets/sheet%d.xml",
645
+ index++);
646
+ lxw_add_document_relationship(rels, "/worksheet", sheetname);
647
+ }
648
+
649
+ lxw_add_document_relationship(rels, "/theme", "theme/theme1.xml");
650
+ lxw_add_document_relationship(rels, "/styles", "styles.xml");
651
+
652
+ if (workbook->sst->string_count)
653
+ lxw_add_document_relationship(rels, "/sharedStrings",
654
+ "sharedStrings.xml");
655
+
656
+ lxw_relationships_assemble_xml_file(rels);
657
+
658
+ err = _add_file_to_zip(self, rels->file, "xl/_rels/workbook.xml.rels");
659
+
660
+ fclose(rels->file);
661
+
662
+ mem_error:
663
+ lxw_free_relationships(rels);
664
+
665
+ return err;
666
+ }
667
+
668
+ /*
669
+ * Write the worksheet .rels files for worksheets that contain links to
670
+ * external data such as hyperlinks or drawings.
671
+ */
672
+ STATIC lxw_error
673
+ _write_worksheet_rels_file(lxw_packager *self)
674
+ {
675
+ lxw_relationships *rels;
676
+ lxw_rel_tuple *rel;
677
+ lxw_workbook *workbook = self->workbook;
678
+ lxw_worksheet *worksheet;
679
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
680
+ uint16_t index = 0;
681
+ lxw_error err;
682
+
683
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
684
+
685
+ index++;
686
+
687
+ if (STAILQ_EMPTY(worksheet->external_hyperlinks) &&
688
+ STAILQ_EMPTY(worksheet->external_drawing_links))
689
+ continue;
690
+
691
+ rels = lxw_relationships_new();
692
+
693
+ rels->file = lxw_tmpfile(self->tmpdir);
694
+ if (!rels->file) {
695
+ lxw_free_relationships(rels);
696
+ return LXW_ERROR_CREATING_TMPFILE;
697
+ }
698
+
699
+ STAILQ_FOREACH(rel, worksheet->external_hyperlinks, list_pointers) {
700
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
701
+ rel->target_mode);
702
+ }
703
+
704
+ STAILQ_FOREACH(rel, worksheet->external_drawing_links, list_pointers) {
705
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
706
+ rel->target_mode);
707
+ }
708
+
709
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
710
+ "xl/worksheets/_rels/sheet%d.xml.rels", index);
711
+
712
+ lxw_relationships_assemble_xml_file(rels);
713
+
714
+ err = _add_file_to_zip(self, rels->file, sheetname);
715
+
716
+ fclose(rels->file);
717
+ lxw_free_relationships(rels);
718
+
719
+ RETURN_ON_ERROR(err);
720
+ }
721
+
722
+ return LXW_NO_ERROR;
723
+ }
724
+
725
+ /*
726
+ * Write the drawing .rels files for worksheets that contain charts or
727
+ * drawings.
728
+ */
729
+ STATIC lxw_error
730
+ _write_drawing_rels_file(lxw_packager *self)
731
+ {
732
+ lxw_relationships *rels;
733
+ lxw_rel_tuple *rel;
734
+ lxw_workbook *workbook = self->workbook;
735
+ lxw_worksheet *worksheet;
736
+ char sheetname[LXW_FILENAME_LENGTH] = { 0 };
737
+ uint16_t index = 1;
738
+ lxw_error err;
739
+
740
+ STAILQ_FOREACH(worksheet, workbook->worksheets, list_pointers) {
741
+
742
+ if (STAILQ_EMPTY(worksheet->drawing_links))
743
+ continue;
744
+
745
+ rels = lxw_relationships_new();
746
+
747
+ rels->file = lxw_tmpfile(self->tmpdir);
748
+ if (!rels->file) {
749
+ lxw_free_relationships(rels);
750
+ return LXW_ERROR_CREATING_TMPFILE;
751
+ }
752
+
753
+ STAILQ_FOREACH(rel, worksheet->drawing_links, list_pointers) {
754
+ lxw_add_worksheet_relationship(rels, rel->type, rel->target,
755
+ rel->target_mode);
756
+
757
+ }
758
+
759
+ lxw_snprintf(sheetname, LXW_FILENAME_LENGTH,
760
+ "xl/drawings/_rels/drawing%d.xml.rels", index++);
761
+
762
+ lxw_relationships_assemble_xml_file(rels);
763
+
764
+ err = _add_file_to_zip(self, rels->file, sheetname);
765
+
766
+ fclose(rels->file);
767
+ lxw_free_relationships(rels);
768
+
769
+ RETURN_ON_ERROR(err);
770
+ }
771
+
772
+ return LXW_NO_ERROR;
773
+ }
774
+
775
+ /*
776
+ * Write the _rels/.rels xml file.
777
+ */
778
+ STATIC lxw_error
779
+ _write_root_rels_file(lxw_packager *self)
780
+ {
781
+ lxw_relationships *rels = lxw_relationships_new();
782
+ lxw_error err = LXW_NO_ERROR;
783
+
784
+ if (!rels) {
785
+ err = LXW_ERROR_MEMORY_MALLOC_FAILED;
786
+ goto mem_error;
787
+ }
788
+
789
+ rels->file = lxw_tmpfile(self->tmpdir);
790
+ if (!rels->file) {
791
+ err = LXW_ERROR_CREATING_TMPFILE;
792
+ goto mem_error;
793
+ }
794
+
795
+ lxw_add_document_relationship(rels, "/officeDocument", "xl/workbook.xml");
796
+
797
+ lxw_add_package_relationship(rels,
798
+ "/metadata/core-properties",
799
+ "docProps/core.xml");
800
+
801
+ lxw_add_document_relationship(rels,
802
+ "/extended-properties", "docProps/app.xml");
803
+
804
+ if (!STAILQ_EMPTY(self->workbook->custom_properties))
805
+ lxw_add_document_relationship(rels,
806
+ "/custom-properties",
807
+ "docProps/custom.xml");
808
+
809
+ lxw_relationships_assemble_xml_file(rels);
810
+
811
+ err = _add_file_to_zip(self, rels->file, "_rels/.rels");
812
+
813
+ fclose(rels->file);
814
+
815
+ mem_error:
816
+ lxw_free_relationships(rels);
817
+
818
+ return err;
819
+ }
820
+
821
+ /*****************************************************************************
822
+ *
823
+ * Public functions.
824
+ *
825
+ ****************************************************************************/
826
+
827
+ STATIC lxw_error
828
+ _add_file_to_zip(lxw_packager *self, FILE * file, const char *filename)
829
+ {
830
+ int16_t error = ZIP_OK;
831
+ size_t size_read;
832
+
833
+ error = zipOpenNewFileInZip4_64(self->zipfile,
834
+ filename,
835
+ &self->zipfile_info,
836
+ NULL, 0, NULL, 0, NULL,
837
+ Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0,
838
+ -MAX_WBITS, DEF_MEM_LEVEL,
839
+ Z_DEFAULT_STRATEGY, NULL, 0, 0, 0, 0);
840
+
841
+ if (error != ZIP_OK) {
842
+ LXW_ERROR("Error adding member to zipfile");
843
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
844
+ }
845
+
846
+ fflush(file);
847
+ rewind(file);
848
+
849
+ size_read = fread(self->buffer, 1, self->buffer_size, file);
850
+
851
+ while (size_read) {
852
+
853
+ if (size_read < self->buffer_size) {
854
+ if (feof(file) == 0) {
855
+ LXW_ERROR("Error reading member file data");
856
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
857
+ }
858
+ }
859
+
860
+ error = zipWriteInFileInZip(self->zipfile,
861
+ self->buffer, (unsigned int) size_read);
862
+
863
+ if (error < 0) {
864
+ LXW_ERROR("Error in writing member in the zipfile");
865
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
866
+ }
867
+
868
+ size_read = fread(self->buffer, 1, self->buffer_size, file);
869
+ }
870
+
871
+ if (error < 0) {
872
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
873
+ }
874
+ else {
875
+ error = zipCloseFileInZip(self->zipfile);
876
+ if (error != ZIP_OK) {
877
+ LXW_ERROR("Error in closing member in the zipfile");
878
+ RETURN_ON_ZIP_ERROR(error, LXW_ERROR_ZIP_FILE_ADD);
879
+ }
880
+ }
881
+
882
+ return LXW_NO_ERROR;
883
+ }
884
+
885
+ /*
886
+ * Write the xml files that make up the XLXS OPC package.
887
+ */
888
+ lxw_error
889
+ lxw_create_package(lxw_packager *self)
890
+ {
891
+ lxw_error error;
892
+ int8_t zip_error;
893
+
894
+ error = _write_worksheet_files(self);
895
+ RETURN_ON_ERROR(error);
896
+
897
+ error = _write_workbook_file(self);
898
+ RETURN_ON_ERROR(error);
899
+
900
+ error = _write_chart_files(self);
901
+ RETURN_ON_ERROR(error);
902
+
903
+ error = _write_drawing_files(self);
904
+ RETURN_ON_ERROR(error);
905
+
906
+ error = _write_shared_strings_file(self);
907
+ RETURN_ON_ERROR(error);
908
+
909
+ error = _write_app_file(self);
910
+ RETURN_ON_ERROR(error);
911
+
912
+ error = _write_core_file(self);
913
+ RETURN_ON_ERROR(error);
914
+
915
+ error = _write_custom_file(self);
916
+ RETURN_ON_ERROR(error);
917
+
918
+ error = _write_theme_file(self);
919
+ RETURN_ON_ERROR(error);
920
+
921
+ error = _write_styles_file(self);
922
+ RETURN_ON_ERROR(error);
923
+
924
+ error = _write_content_types_file(self);
925
+ RETURN_ON_ERROR(error);
926
+
927
+ error = _write_workbook_rels_file(self);
928
+ RETURN_ON_ERROR(error);
929
+
930
+ error = _write_worksheet_rels_file(self);
931
+ RETURN_ON_ERROR(error);
932
+
933
+ error = _write_drawing_rels_file(self);
934
+ RETURN_ON_ERROR(error);
935
+
936
+ error = _write_image_files(self);
937
+ RETURN_ON_ERROR(error);;
938
+
939
+ error = _write_root_rels_file(self);
940
+ RETURN_ON_ERROR(error);
941
+
942
+ zip_error = zipClose(self->zipfile, NULL);
943
+ if (zip_error) {
944
+ RETURN_ON_ZIP_ERROR(zip_error, LXW_ERROR_ZIP_CLOSE);
945
+ }
946
+
947
+ return LXW_NO_ERROR;
948
+ }