From 6e18bbabeaea42be6b24881e1bafc81ed856c1fe Mon Sep 17 00:00:00 2001 From: viest Date: Tue, 26 Oct 2021 16:23:23 +0800 Subject: [PATCH] Feat: Customize to enable or disable zip64, as WPS cannot open zip64 files --- include/xlswriter.h | 2 ++ kernel/excel.c | 7 +++-- kernel/write.c | 63 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/include/xlswriter.h b/include/xlswriter.h index 3ca25c6..c4665bf 100644 --- a/include/xlswriter.h +++ b/include/xlswriter.h @@ -231,6 +231,8 @@ typedef struct _vtiful_rich_string_object { Z_PARAM_LONG_EX(dest, is_null, 1, 0) #define Z_PARAM_ARRAY_OR_NULL(dest) \ Z_PARAM_ARRAY_EX(dest, 1, 0) +#define Z_PARAM_BOOL_OR_NULL(dest, is_null) \ + Z_PARAM_BOOL_EX(dest, is_null, 1, 0) #endif static inline xls_object *php_vtiful_xls_fetch_object(zend_object *obj) { diff --git a/kernel/excel.c b/kernel/excel.c index 44621dc..c1dd447 100644 --- a/kernel/excel.c +++ b/kernel/excel.c @@ -76,6 +76,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(xls_const_memory_arginfo, 0, 0, 1) ZEND_ARG_INFO(0, file_name) ZEND_ARG_INFO(0, sheet_name) + ZEND_ARG_INFO(0, use_zip64) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(xls_file_add_sheet, 0, 0, 1) @@ -507,13 +508,15 @@ PHP_METHOD(vtiful_xls, activateSheet) PHP_METHOD(vtiful_xls, constMemory) { char *sheet_name = NULL; + zend_bool use_zip64 = LXW_TRUE; zval file_path, *dir_path = NULL; zend_string *zs_file_name = NULL, *zs_sheet_name = NULL; - ZEND_PARSE_PARAMETERS_START(1, 2) + ZEND_PARSE_PARAMETERS_START(1, 3) Z_PARAM_STR(zs_file_name) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_NULL(zs_sheet_name) + Z_PARAM_BOOL_OR_NULL(use_zip64, _dummy) ZEND_PARSE_PARAMETERS_END(); ZVAL_COPY(return_value, getThis()); @@ -528,7 +531,7 @@ PHP_METHOD(vtiful_xls, constMemory) lxw_workbook_options options = { .constant_memory = LXW_TRUE, .tmpdir = NULL, - .use_zip64 = LXW_TRUE + .use_zip64 = use_zip64 }; if(zs_sheet_name != NULL) { diff --git a/kernel/write.c b/kernel/write.c index 3228352..fe33b47 100644 --- a/kernel/write.c +++ b/kernel/write.c @@ -451,9 +451,11 @@ void margins(xls_resource_write_t *res, double left, double right, double top, d lxw_error workbook_file(xls_resource_write_t *self) { + lxw_sheet *sheet = NULL; lxw_worksheet *worksheet = NULL; lxw_packager *packager = NULL; lxw_error error = LXW_NO_ERROR; + char codename[LXW_MAX_SHEETNAME_LENGTH] = { 0 }; /* Add a default worksheet if non have been added. */ if (!self->workbook->num_sheets) @@ -461,15 +463,46 @@ workbook_file(xls_resource_write_t *self) /* Ensure that at least one worksheet has been selected. */ if (self->workbook->active_sheet == 0) { - worksheet = STAILQ_FIRST(self->workbook->worksheets); - worksheet->selected = 1; - worksheet->hidden = 0; + sheet = STAILQ_FIRST(self->workbook->sheets); + if (!sheet->is_chartsheet) { + worksheet = sheet->u.worksheet; + worksheet->selected = 1; + worksheet->hidden = 0; + } } - /* Set the active sheet. */ - STAILQ_FOREACH(worksheet, self->workbook->worksheets, list_pointers) { + /* Set the active sheet and check if a metadata file is needed. */ + STAILQ_FOREACH(sheet, self->workbook->sheets, list_pointers) { + if (sheet->is_chartsheet) + continue; + else + worksheet = sheet->u.worksheet; + if (worksheet->index == self->workbook->active_sheet) worksheet->active = 1; + + if (worksheet->has_dynamic_arrays) + self->workbook->has_metadata = LXW_TRUE; + } + + /* Set workbook and worksheet VBA codenames if a macro has been added. */ + if (self->workbook->vba_project) { + if (!self->workbook->vba_codename) + workbook_set_vba_name(self->workbook, "ThisWorkbook"); + + STAILQ_FOREACH(sheet, self->workbook->sheets, list_pointers) { + if (sheet->is_chartsheet) + continue; + else + worksheet = sheet->u.worksheet; + + if (!worksheet->vba_codename) { + lxw_snprintf(codename, LXW_MAX_SHEETNAME_LENGTH, "Sheet%d", + worksheet->index + 1); + + worksheet_set_vba_name(worksheet, codename); + } + } } /* Prepare the worksheet VML elements such as comments. */ @@ -485,13 +518,15 @@ workbook_file(xls_resource_write_t *self) _add_chart_cache_data(self->workbook); /* Create a packager object to assemble sub-elements into a zip file. */ - packager = lxw_packager_new(self->workbook->filename, self->workbook->options.tmpdir, self->workbook->options.use_zip64); + packager = lxw_packager_new(self->workbook->filename, + self->workbook->options.tmpdir, + self->workbook->options.use_zip64); /* If the packager fails it is generally due to a zip permission error. */ if (packager == NULL) { fprintf(stderr, "[ERROR] workbook_close(): " - "Error creating '%s'. " - "Error = %s\n", self->workbook->filename, strerror(errno)); + "Error creating '%s'. " + "Error = %s\n", self->workbook->filename, strerror(errno)); error = LXW_ERROR_CREATING_XLSX_FILE; goto mem_error; @@ -506,15 +541,15 @@ workbook_file(xls_resource_write_t *self) /* Error and non-error conditions fall through to the cleanup code. */ if (error == LXW_ERROR_CREATING_TMPFILE) { fprintf(stderr, "[ERROR] workbook_close(): " - "Error creating tmpfile(s) to assemble '%s'. " - "Error = %s\n", self->workbook->filename, strerror(errno)); + "Error creating tmpfile(s) to assemble '%s'. " + "Error = %s\n", self->workbook->filename, strerror(errno)); } /* If LXW_ERROR_ZIP_FILE_OPERATION then errno is set by zlib. */ if (error == LXW_ERROR_ZIP_FILE_OPERATION) { fprintf(stderr, "[ERROR] workbook_close(): " - "Zlib error while creating xlsx file '%s'. " - "Error = %s\n", self->workbook->filename, strerror(errno)); + "Zlib error while creating xlsx file '%s'. " + "Error = %s\n", self->workbook->filename, strerror(errno)); } /* If LXW_ERROR_ZIP_PARAMETER_ERROR then errno is set by zip. */ @@ -548,11 +583,11 @@ workbook_file(xls_resource_write_t *self) if (error == LXW_ERROR_ZIP_CLOSE) { fprintf(stderr, "[ERROR] workbook_close(): " - "Zlib error closing xlsx file '%s'.\n", self->workbook->filename); + "Zlib error closing xlsx file '%s'.\n", self->workbook->filename); } mem_error: - lxw_packager_free(packager); + lxw_packager_free(packager); return error; }