kmadej_fast_excel_fork 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }