kmadej_fast_excel_fork 0.2.2

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 (119) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.travis.yml +28 -0
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +70 -0
  7. data/Makefile +14 -0
  8. data/README.md +95 -0
  9. data/Rakefile +24 -0
  10. data/appveyor.yml +25 -0
  11. data/benchmarks/1k_rows.rb +59 -0
  12. data/benchmarks/20k_rows.rb +26 -0
  13. data/benchmarks/init.rb +59 -0
  14. data/benchmarks/memory.rb +49 -0
  15. data/examples/example.rb +42 -0
  16. data/examples/example_align.rb +23 -0
  17. data/examples/example_chart.rb +21 -0
  18. data/examples/example_colors.rb +37 -0
  19. data/examples/example_formula.rb +18 -0
  20. data/examples/example_image.rb +13 -0
  21. data/examples/example_styles.rb +27 -0
  22. data/examples/logo.png +0 -0
  23. data/extconf.rb +0 -0
  24. data/fast_excel.gemspec +20 -0
  25. data/lib/fast_excel.rb +600 -0
  26. data/lib/fast_excel/binding.rb +2819 -0
  27. data/lib/fast_excel/binding/chart.rb +2666 -0
  28. data/lib/fast_excel/binding/format.rb +1177 -0
  29. data/lib/fast_excel/binding/workbook.rb +338 -0
  30. data/lib/fast_excel/binding/worksheet.rb +1555 -0
  31. data/libxlsxwriter/.gitignore +49 -0
  32. data/libxlsxwriter/.indent.pro +125 -0
  33. data/libxlsxwriter/.travis.yml +25 -0
  34. data/libxlsxwriter/CONTRIBUTING.md +226 -0
  35. data/libxlsxwriter/Changes.txt +557 -0
  36. data/libxlsxwriter/LICENSE.txt +89 -0
  37. data/libxlsxwriter/Makefile +156 -0
  38. data/libxlsxwriter/Readme.md +78 -0
  39. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +30 -0
  40. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +7 -0
  41. data/libxlsxwriter/include/xlsxwriter.h +23 -0
  42. data/libxlsxwriter/include/xlsxwriter/app.h +79 -0
  43. data/libxlsxwriter/include/xlsxwriter/chart.h +3476 -0
  44. data/libxlsxwriter/include/xlsxwriter/common.h +372 -0
  45. data/libxlsxwriter/include/xlsxwriter/content_types.h +74 -0
  46. data/libxlsxwriter/include/xlsxwriter/core.h +51 -0
  47. data/libxlsxwriter/include/xlsxwriter/custom.h +52 -0
  48. data/libxlsxwriter/include/xlsxwriter/drawing.h +111 -0
  49. data/libxlsxwriter/include/xlsxwriter/format.h +1214 -0
  50. data/libxlsxwriter/include/xlsxwriter/hash_table.h +76 -0
  51. data/libxlsxwriter/include/xlsxwriter/packager.h +80 -0
  52. data/libxlsxwriter/include/xlsxwriter/relationships.h +77 -0
  53. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +83 -0
  54. data/libxlsxwriter/include/xlsxwriter/styles.h +77 -0
  55. data/libxlsxwriter/include/xlsxwriter/theme.h +47 -0
  56. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +214 -0
  57. data/libxlsxwriter/include/xlsxwriter/third_party/queue.h +694 -0
  58. data/libxlsxwriter/include/xlsxwriter/third_party/tmpfileplus.h +53 -0
  59. data/libxlsxwriter/include/xlsxwriter/third_party/tree.h +801 -0
  60. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +375 -0
  61. data/libxlsxwriter/include/xlsxwriter/utility.h +166 -0
  62. data/libxlsxwriter/include/xlsxwriter/workbook.h +757 -0
  63. data/libxlsxwriter/include/xlsxwriter/worksheet.h +2641 -0
  64. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +178 -0
  65. data/libxlsxwriter/lib/.gitignore +0 -0
  66. data/libxlsxwriter/libxlsxwriter.podspec +47 -0
  67. data/libxlsxwriter/src/Makefile +130 -0
  68. data/libxlsxwriter/src/app.c +443 -0
  69. data/libxlsxwriter/src/chart.c +6346 -0
  70. data/libxlsxwriter/src/content_types.c +345 -0
  71. data/libxlsxwriter/src/core.c +293 -0
  72. data/libxlsxwriter/src/custom.c +224 -0
  73. data/libxlsxwriter/src/drawing.c +746 -0
  74. data/libxlsxwriter/src/format.c +729 -0
  75. data/libxlsxwriter/src/hash_table.c +223 -0
  76. data/libxlsxwriter/src/packager.c +948 -0
  77. data/libxlsxwriter/src/relationships.c +245 -0
  78. data/libxlsxwriter/src/shared_strings.c +266 -0
  79. data/libxlsxwriter/src/styles.c +1088 -0
  80. data/libxlsxwriter/src/theme.c +348 -0
  81. data/libxlsxwriter/src/utility.c +515 -0
  82. data/libxlsxwriter/src/workbook.c +1930 -0
  83. data/libxlsxwriter/src/worksheet.c +5022 -0
  84. data/libxlsxwriter/src/xmlwriter.c +355 -0
  85. data/libxlsxwriter/third_party/minizip/Makefile +44 -0
  86. data/libxlsxwriter/third_party/minizip/Makefile.am +45 -0
  87. data/libxlsxwriter/third_party/minizip/Makefile.orig +25 -0
  88. data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +6 -0
  89. data/libxlsxwriter/third_party/minizip/MiniZip64_info.txt +74 -0
  90. data/libxlsxwriter/third_party/minizip/README.txt +5 -0
  91. data/libxlsxwriter/third_party/minizip/configure.ac +32 -0
  92. data/libxlsxwriter/third_party/minizip/crypt.h +131 -0
  93. data/libxlsxwriter/third_party/minizip/ioapi.c +247 -0
  94. data/libxlsxwriter/third_party/minizip/ioapi.h +208 -0
  95. data/libxlsxwriter/third_party/minizip/iowin32.c +456 -0
  96. data/libxlsxwriter/third_party/minizip/iowin32.h +28 -0
  97. data/libxlsxwriter/third_party/minizip/make_vms.com +25 -0
  98. data/libxlsxwriter/third_party/minizip/miniunz.c +660 -0
  99. data/libxlsxwriter/third_party/minizip/miniunzip.1 +63 -0
  100. data/libxlsxwriter/third_party/minizip/minizip.1 +46 -0
  101. data/libxlsxwriter/third_party/minizip/minizip.c +520 -0
  102. data/libxlsxwriter/third_party/minizip/minizip.pc.in +12 -0
  103. data/libxlsxwriter/third_party/minizip/mztools.c +291 -0
  104. data/libxlsxwriter/third_party/minizip/mztools.h +37 -0
  105. data/libxlsxwriter/third_party/minizip/unzip.c +2125 -0
  106. data/libxlsxwriter/third_party/minizip/unzip.h +437 -0
  107. data/libxlsxwriter/third_party/minizip/zip.c +2007 -0
  108. data/libxlsxwriter/third_party/minizip/zip.h +367 -0
  109. data/libxlsxwriter/third_party/tmpfileplus/Makefile +42 -0
  110. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +342 -0
  111. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h +53 -0
  112. data/libxlsxwriter/version.txt +1 -0
  113. data/test/date_test.rb +22 -0
  114. data/test/default_format_test.rb +19 -0
  115. data/test/format_test.rb +171 -0
  116. data/test/test_helper.rb +52 -0
  117. data/test/tmpfile_test.rb +23 -0
  118. data/test/worksheet_test.rb +86 -0
  119. metadata +182 -0
@@ -0,0 +1,223 @@
1
+ /*****************************************************************************
2
+ * hash_table - Hash table functions for libxlsxwriter.
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 <stdlib.h>
11
+ #include <stdio.h>
12
+ #include <string.h>
13
+ #include <stdint.h>
14
+ #include "xlsxwriter/hash_table.h"
15
+
16
+ /*
17
+ * Calculate the hash key using the FNV function. See:
18
+ * http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
19
+ */
20
+ STATIC size_t
21
+ _generate_hash_key(void *data, size_t data_len, size_t num_buckets)
22
+ {
23
+ unsigned char *p = data;
24
+ size_t hash = 2166136261U;
25
+ size_t i;
26
+
27
+ for (i = 0; i < data_len; i++)
28
+ hash = (hash * 16777619) ^ p[i];
29
+
30
+ return hash % num_buckets;
31
+ }
32
+
33
+ /*
34
+ * Check if an element exists in the hash table and return a pointer
35
+ * to it if it does.
36
+ */
37
+ lxw_hash_element *
38
+ lxw_hash_key_exists(lxw_hash_table *lxw_hash, void *key, size_t key_len)
39
+ {
40
+ size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
41
+ struct lxw_hash_bucket_list *list;
42
+ lxw_hash_element *element;
43
+
44
+ if (!lxw_hash->buckets[hash_key]) {
45
+ /* The key isn't in the LXW_HASH hash table. */
46
+ return NULL;
47
+ }
48
+ else {
49
+ /* The key is already in the table or there is a hash collision. */
50
+ list = lxw_hash->buckets[hash_key];
51
+
52
+ /* Iterate over the keys in the bucket's linked list. */
53
+ SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
54
+ if (memcmp(element->key, key, key_len) == 0) {
55
+ /* The key already exists in the table. */
56
+ return element;
57
+ }
58
+ }
59
+
60
+ /* Key doesn't exist in the list so this is a hash collision. */
61
+ return NULL;
62
+ }
63
+ }
64
+
65
+ /*
66
+ * Insert or update a value in the LXW_HASH table based on a key
67
+ * and return a pointer to the new or updated element.
68
+ */
69
+ lxw_hash_element *
70
+ lxw_insert_hash_element(lxw_hash_table *lxw_hash, void *key, void *value,
71
+ size_t key_len)
72
+ {
73
+ size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
74
+ struct lxw_hash_bucket_list *list = NULL;
75
+ lxw_hash_element *element = NULL;
76
+
77
+ if (!lxw_hash->buckets[hash_key]) {
78
+ /* The key isn't in the LXW_HASH hash table. */
79
+
80
+ /* Create a linked list in the bucket to hold the lxw_hash keys. */
81
+ list = calloc(1, sizeof(struct lxw_hash_bucket_list));
82
+ GOTO_LABEL_ON_MEM_ERROR(list, mem_error1);
83
+
84
+ /* Initialize the bucket linked list. */
85
+ SLIST_INIT(list);
86
+
87
+ /* Create an lxw_hash element to add to the linked list. */
88
+ element = calloc(1, sizeof(lxw_hash_element));
89
+ GOTO_LABEL_ON_MEM_ERROR(element, mem_error1);
90
+
91
+ /* Store the key and value. */
92
+ element->key = key;
93
+ element->value = value;
94
+
95
+ /* Add the lxw_hash element to the bucket's linked list. */
96
+ SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
97
+
98
+ /* Also add it to the insertion order linked list. */
99
+ STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
100
+ lxw_hash_order_pointers);
101
+
102
+ /* Store the bucket list at the hash index. */
103
+ lxw_hash->buckets[hash_key] = list;
104
+
105
+ lxw_hash->used_buckets++;
106
+ lxw_hash->unique_count++;
107
+
108
+ return element;
109
+ }
110
+ else {
111
+ /* The key is already in the table or there is a hash collision. */
112
+ list = lxw_hash->buckets[hash_key];
113
+
114
+ /* Iterate over the keys in the bucket's linked list. */
115
+ SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
116
+ if (memcmp(element->key, key, key_len) == 0) {
117
+ /* The key already exists in the table. Update the value. */
118
+ if (lxw_hash->free_value)
119
+ free(element->value);
120
+
121
+ element->value = value;
122
+ return element;
123
+ }
124
+ }
125
+
126
+ /* Key doesn't exist in the list so this is a hash collision.
127
+ * Create an lxw_hash element to add to the linked list. */
128
+ element = calloc(1, sizeof(lxw_hash_element));
129
+ GOTO_LABEL_ON_MEM_ERROR(element, mem_error2);
130
+
131
+ /* Store the key and value. */
132
+ element->key = key;
133
+ element->value = value;
134
+
135
+ /* Add the lxw_hash element to the bucket linked list. */
136
+ SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
137
+
138
+ /* Also add it to the insertion order linked list. */
139
+ STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
140
+ lxw_hash_order_pointers);
141
+
142
+ lxw_hash->unique_count++;
143
+
144
+ return element;
145
+ }
146
+
147
+ mem_error1:
148
+ free(list);
149
+
150
+ mem_error2:
151
+ free(element);
152
+ return NULL;
153
+ }
154
+
155
+ /*
156
+ * Create a new LXW_HASH hash table object.
157
+ */
158
+ lxw_hash_table *
159
+ lxw_hash_new(uint32_t num_buckets, uint8_t free_key, uint8_t free_value)
160
+ {
161
+ /* Create the new hash table. */
162
+ lxw_hash_table *lxw_hash = calloc(1, sizeof(lxw_hash_table));
163
+ RETURN_ON_MEM_ERROR(lxw_hash, NULL);
164
+
165
+ lxw_hash->free_key = free_key;
166
+ lxw_hash->free_value = free_value;
167
+
168
+ /* Add the lxw_hash element buckets. */
169
+ lxw_hash->buckets =
170
+ calloc(num_buckets, sizeof(struct lxw_hash_bucket_list *));
171
+ GOTO_LABEL_ON_MEM_ERROR(lxw_hash->buckets, mem_error);
172
+
173
+ /* Add a list for tracking the insertion order. */
174
+ lxw_hash->order_list = calloc(1, sizeof(struct lxw_hash_order_list));
175
+ GOTO_LABEL_ON_MEM_ERROR(lxw_hash->order_list, mem_error);
176
+
177
+ /* Initialize the order list. */
178
+ STAILQ_INIT(lxw_hash->order_list);
179
+
180
+ /* Store the number of buckets to calculate the load factor. */
181
+ lxw_hash->num_buckets = num_buckets;
182
+
183
+ return lxw_hash;
184
+
185
+ mem_error:
186
+ lxw_hash_free(lxw_hash);
187
+ return NULL;
188
+ }
189
+
190
+ /*
191
+ * Free the LXW_HASH hash table object.
192
+ */
193
+ void
194
+ lxw_hash_free(lxw_hash_table *lxw_hash)
195
+ {
196
+ size_t i;
197
+ lxw_hash_element *element;
198
+ lxw_hash_element *element_temp;
199
+
200
+ if (!lxw_hash)
201
+ return;
202
+
203
+ /* Free the lxw_hash_elements and data using the ordered linked list. */
204
+ if (lxw_hash->order_list) {
205
+ STAILQ_FOREACH_SAFE(element, lxw_hash->order_list,
206
+ lxw_hash_order_pointers, element_temp) {
207
+ if (lxw_hash->free_key)
208
+ free(element->key);
209
+ if (lxw_hash->free_value)
210
+ free(element->value);
211
+ free(element);
212
+ }
213
+ }
214
+
215
+ /* Free the buckets from the hash table. */
216
+ for (i = 0; i < lxw_hash->num_buckets; i++) {
217
+ free(lxw_hash->buckets[i]);
218
+ }
219
+
220
+ free(lxw_hash->order_list);
221
+ free(lxw_hash->buckets);
222
+ free(lxw_hash);
223
+ }
@@ -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
+ }