浏览代码

Adjust the head and data operation

viest 7 年之前
父节点
当前提交
74be6e7c7c
共有 10 个文件被更改,包括 485 次插入80 次删除
  1. 5 1
      config.m4
  2. 58 55
      kernel/excel.c
  3. 19 2
      kernel/excel.h
  4. 0 7
      kernel/excel.loT
  5. 12 0
      kernel/exception.c
  6. 12 0
      kernel/exception.h
  7. 352 0
      kernel/write.c
  8. 19 0
      kernel/write.h
  9. 3 1
      php_vtiful.h
  10. 5 14
      vtiful.c

+ 5 - 1
config.m4

@@ -17,7 +17,7 @@ if test "$PHP_VTIFUL" != "no"; then
             [
                 PHP_ADD_LIBRARY_WITH_PATH(xlsxwriter, $i/$PHP_LIBDIR, VTIFUL_SHARED_LIBADD)
                 AC_DEFINE([VTIFUL_XLSX_WRITER], [1], [Have libxlsxwriter support])
-                vtiful_sources="$vtiful_sources kernel/excel.c "
+                vtiful_sources="$vtiful_sources kernel/excel.c kernel/write.c"
             ],[
                 AC_MSG_ERROR([Wrong libxlsxwriter version or library not found])
             ],[
@@ -34,6 +34,10 @@ if test "$PHP_VTIFUL" != "no"; then
         AC_MSG_ERROR([libxlsxwriter library not found])
     fi
 
+    if test -z "$PHP_DEBUG"; then
+        AC_ARG_ENABLE(debug, [--enable-debug compile with debugging system], [PHP_DEBUG=$enableval],[PHP_DEBUG=no] )
+    fi
+
     PHP_SUBST(VTIFUL_SHARED_LIBADD)
 
     PHP_NEW_EXTENSION(vtiful, $vtiful_sources, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)

+ 58 - 55
kernel/excel.c

@@ -1,3 +1,15 @@
+/*
+  +----------------------------------------------------------------------+
+  | Vtiful Extension                                                     |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2017-2017 The Viest                                    |
+  +----------------------------------------------------------------------+
+  | http://www.vtiful.com                                                |
+  +----------------------------------------------------------------------+
+  | Author: viest <[email protected]>                                 |
+  +----------------------------------------------------------------------+
+*/
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -8,17 +20,10 @@
 
 #include "php.h"
 
-#include "xlsxwriter.h"
 #include "php_vtiful.h"
 #include "excel.h"
 #include "exception.h"
-
-#include "ext/standard/php_var.h"
-
-typedef struct {
-    lxw_workbook *workbook;
-    lxw_worksheet *worksheet;
-} excel_resource_t;
+#include "write.h"
 
 zend_class_entry *vtiful_excel_ce;
 
@@ -108,7 +113,9 @@ PHP_METHOD(vtiful_excel, fileName)
  */
 PHP_METHOD(vtiful_excel, header)
 {
-    zval *header;
+    zval rv, res_handle, *attr_handle, *header, *header_value;
+    zend_long header_l_key;
+    excel_resource_t *res;
 
     ZEND_PARSE_PARAMETERS_START(1, 1)
             Z_PARAM_ARRAY(header)
@@ -116,7 +123,18 @@ PHP_METHOD(vtiful_excel, header)
 
     ZVAL_COPY(return_value, getThis());
 
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HEADER), header);
+    attr_handle = zend_read_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), 0, &rv TSRMLS_DC);
+    if((res = (excel_resource_t *)zend_fetch_resource(Z_RES_P(attr_handle), VTIFUL_RESOURCE_NAME, le_vtiful)) == NULL) {
+        zend_throw_exception(vtiful_exception_ce, "Excel resources resolution fail", 210);
+    }
+
+    ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(header), header_l_key, header_value) {
+         type_writer(header_value, 0, header_l_key, res);
+         zval_ptr_dtor(header_value);
+    } ZEND_HASH_FOREACH_END();
+
+    ZVAL_RES(&res_handle, zend_register_resource(res, le_vtiful));
+    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
 }
 /* }}} */
 
@@ -124,7 +142,9 @@ PHP_METHOD(vtiful_excel, header)
  */
 PHP_METHOD(vtiful_excel, data)
 {
-    zval *data;
+    zval rv, *data, *attr_handle, res_handle, *data_r_value, *data_l_value;
+    zend_long data_r_key, data_l_key;
+    excel_resource_t *res;
 
     ZEND_PARSE_PARAMETERS_START(1, 1)
             Z_PARAM_ARRAY(data)
@@ -132,7 +152,22 @@ PHP_METHOD(vtiful_excel, data)
 
     ZVAL_COPY(return_value, getThis());
 
-    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_DATA), data);
+    attr_handle = zend_read_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), 0, &rv TSRMLS_DC);
+    if((res = (excel_resource_t *)zend_fetch_resource(Z_RES_P(attr_handle), VTIFUL_RESOURCE_NAME, le_vtiful)) == NULL) {
+        zend_throw_exception(vtiful_exception_ce, "Excel resources resolution fail", 210);
+    }
+
+    ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data), data_r_key, data_r_value) {
+        if(Z_TYPE_P(data_r_value) == IS_ARRAY) {
+            ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data_r_value), data_l_key, data_l_value) {
+                type_writer(data_l_value, data_r_key+1, data_l_key, res);
+                zval_ptr_dtor(data_l_value);
+            } ZEND_HASH_FOREACH_END();
+        }
+    } ZEND_HASH_FOREACH_END();
+
+    ZVAL_RES(&res_handle, zend_register_resource(res, le_vtiful));
+    zend_update_property(vtiful_excel_ce, return_value, ZEND_STRL(V_EXCEL_HANDLE), &res_handle);
 }
 /* }}} */
 
@@ -140,42 +175,20 @@ PHP_METHOD(vtiful_excel, data)
  */
 PHP_METHOD(vtiful_excel, output)
 {
-    zval rv1, rv2, rv3;
-    zval *file_name, *header, *data, *value, *data_r_value, *data_l_value;
-    zend_long header_l_key, data_r_key, data_l_key;
+    zval rv, *handle, null_handle;
     excel_resource_t *res;
 
-    file_name = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_FIL), 0, &rv1 TSRMLS_DC);
-    header    = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_HEADER), 0, &rv2 TSRMLS_DC);
-    data      = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_DATA), 0, &rv3 TSRMLS_DC);
+    handle = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_HANDLE), 0, &rv TSRMLS_DC);
 
-    res = malloc(sizeof(excel_resource_t));
-
-    res->workbook  = workbook_new(ZSTR_VAL(zval_get_string(file_name)));
-    res->worksheet = workbook_add_worksheet(res->workbook, NULL);
-
-    zval_ptr_dtor(file_name);
+    if((res = (excel_resource_t *)zend_fetch_resource(Z_RES_P(handle), VTIFUL_RESOURCE_NAME, le_vtiful)) == NULL) {
+        zend_throw_exception(vtiful_exception_ce, "Excel resources resolution fail", 210);
+    }
 
-    ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(header), header_l_key, value) {
-        worksheet_write_string(res->worksheet, 0, header_l_key, ZSTR_VAL(zval_get_string(value)), NULL);
-        zval_ptr_dtor(value);
-    } ZEND_HASH_FOREACH_END();
+    workbook_file(res, handle);
 
-    ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data), data_r_key, data_r_value) {
-        ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data_r_value), data_l_key, data_l_value) {
-            switch (Z_TYPE_P(data_l_value)) {
-                case IS_STRING:
-                    worksheet_write_string(res->worksheet, data_r_key+1, data_l_key, ZSTR_VAL(zval_get_string(data_l_value)), NULL);
-                    zval_ptr_dtor(data_l_value);
-                    break;
-                case IS_LONG:
-                    worksheet_write_number(res->worksheet, data_r_key+1, data_l_key, zval_get_long(data_l_value), NULL);
-                    break;
-            }
-        } ZEND_HASH_FOREACH_END();
-    } ZEND_HASH_FOREACH_END();
+    ZVAL_NULL(&null_handle);
 
-    workbook_close(res->workbook);
+    zend_update_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_HANDLE), &null_handle);
 }
 /* }}} */
 
@@ -184,19 +197,11 @@ PHP_METHOD(vtiful_excel, output)
 PHP_METHOD(vtiful_excel, getHandle)
 {
     zval rv;
-    zval *file_name;
-    excel_resource_t *res;
-
-    file_name = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_FIL), 0, &rv TSRMLS_DC);
-
-    res = malloc(sizeof(excel_resource_t));
-
-    res->workbook  = workbook_new(ZSTR_VAL(zval_get_string(file_name)));
-    res->worksheet = workbook_add_worksheet(res->workbook, NULL);
+    zval *handle;
 
-    zval_ptr_dtor(file_name);
+    handle = zend_read_property(vtiful_excel_ce, getThis(), ZEND_STRL(V_EXCEL_HANDLE), 0, &rv TSRMLS_DC);
 
-    RETURN_RES(zend_register_resource(res, le_vtiful));
+    ZVAL_COPY(return_value, handle);
 }
 /* }}} */
 
@@ -219,8 +224,6 @@ VTIFUL_STARTUP_FUNCTION(excel) {
 
     zend_declare_property_null(vtiful_excel_ce, ZEND_STRL(V_EXCEL_COF), ZEND_ACC_PRIVATE);
     zend_declare_property_null(vtiful_excel_ce, ZEND_STRL(V_EXCEL_FIL), ZEND_ACC_PRIVATE);
-    zend_declare_property_null(vtiful_excel_ce, ZEND_STRL(V_EXCEL_DATA), ZEND_ACC_PRIVATE);
-    zend_declare_property_null(vtiful_excel_ce, ZEND_STRL(V_EXCEL_HEADER), ZEND_ACC_PRIVATE);
     zend_declare_property_null(vtiful_excel_ce, ZEND_STRL(V_EXCEL_HANDLE), ZEND_ACC_PRIVATE);
 
     return SUCCESS;

+ 19 - 2
kernel/excel.h

@@ -1,11 +1,28 @@
+/*
+  +----------------------------------------------------------------------+
+  | Vtiful Extension                                                     |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2017-2017 The Viest                                    |
+  +----------------------------------------------------------------------+
+  | http://www.vtiful.com                                                |
+  +----------------------------------------------------------------------+
+  | Author: viest <[email protected]>                                 |
+  +----------------------------------------------------------------------+
+*/
+
 #ifndef VTIFUL_EXCEL_H
 #define VTIFUL_EXCEL_H
 
-#define V_EXCEL_HEADER "header"
+#include "xlsxwriter.h"
+
+typedef struct {
+    lxw_workbook *workbook;
+    lxw_worksheet *worksheet;
+} excel_resource_t;
+
 #define V_EXCEL_HANDLE "handle"
 #define V_EXCEL_FIL "fileName"
 #define V_EXCEL_COF "config"
-#define V_EXCEL_DATA "data"
 #define V_EXCEL_PAT "path"
 
 extern zend_class_entry *vtiful_excel_ce;

+ 0 - 7
kernel/excel.loT

@@ -1,7 +0,0 @@
-# kernel/excel.lo - a libtool object file
-# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.492 2008/01/30 06:40:56)
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# Name of the PIC object.

+ 12 - 0
kernel/exception.c

@@ -1,3 +1,15 @@
+/*
+  +----------------------------------------------------------------------+
+  | Vtiful Extension                                                     |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2017-2017 The Viest                                    |
+  +----------------------------------------------------------------------+
+  | http://www.vtiful.com                                                |
+  +----------------------------------------------------------------------+
+  | Author: viest <[email protected]>                                 |
+  +----------------------------------------------------------------------+
+*/
+
 #include <php.h>
 #include "zend_exceptions.h"
 #include "php_vtiful.h"

+ 12 - 0
kernel/exception.h

@@ -1,3 +1,15 @@
+/*
+  +----------------------------------------------------------------------+
+  | Vtiful Extension                                                     |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2017-2017 The Viest                                    |
+  +----------------------------------------------------------------------+
+  | http://www.vtiful.com                                                |
+  +----------------------------------------------------------------------+
+  | Author: viest <[email protected]>                                 |
+  +----------------------------------------------------------------------+
+*/
+
 #ifndef VTIFUL_EXCEL_EXCEPTION_H
 #define VTIFUL_EXCEL_EXCEPTION_H
 

+ 352 - 0
kernel/write.c

@@ -0,0 +1,352 @@
+/*
+  +----------------------------------------------------------------------+
+  | Vtiful Extension                                                     |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2017-2017 The Viest                                    |
+  +----------------------------------------------------------------------+
+  | http://www.vtiful.com                                                |
+  +----------------------------------------------------------------------+
+  | Author: viest <[email protected]>                                 |
+  +----------------------------------------------------------------------+
+*/
+
+#include "php.h"
+#include "excel.h"
+#include "write.h"
+#include "xlsxwriter.h"
+#include "xlsxwriter/packager.h"
+
+STATIC void _prepare_defined_names(lxw_workbook *self);
+STATIC void _prepare_drawings(lxw_workbook *self);
+STATIC void _add_chart_cache_data(lxw_workbook *self);
+
+/*
+ * According to the zval type written to the file
+ */
+void type_writer(zval *value, zend_long row, zend_long columns, excel_resource_t *res)
+{
+    switch (Z_TYPE_P(value)) {
+        case IS_STRING:
+            worksheet_write_string(res->worksheet, row, columns, ZSTR_VAL(zval_get_string(value)), NULL);
+            break;
+        case IS_LONG:
+            worksheet_write_number(res->worksheet, row, columns, zval_get_long(value), NULL);
+            break;
+        case IS_DOUBLE:
+            worksheet_write_string(res->worksheet, row, columns, ZSTR_VAL(zval_get_string(value)), NULL);
+            break;
+    }
+}
+
+/*
+ * Call finalization code and close file.
+ */
+lxw_error
+workbook_file(excel_resource_t *self, zval *handle)
+{
+    lxw_worksheet *worksheet = NULL;
+    lxw_packager *packager = NULL;
+    lxw_error error = LXW_NO_ERROR;
+
+    /* Add a default worksheet if non have been added. */
+    if (!self->workbook->num_sheets)
+        workbook_add_worksheet(self, NULL);
+
+    /* 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;
+    }
+
+    /* Set the active sheet. */
+    STAILQ_FOREACH(worksheet, self->workbook->worksheets, list_pointers) {
+        if (worksheet->index == self->workbook->active_sheet)
+            worksheet->active = 1;
+    }
+
+    /* Set the defined names for the worksheets such as Print Titles. */
+    _prepare_defined_names(self->workbook);
+
+    /* Prepare the drawings, charts and images. */
+    _prepare_drawings(self->workbook);
+
+    /* Add cached data to charts. */
+    _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);
+
+    /* 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 = LXW_ERROR_CREATING_XLSX_FILE;
+        goto mem_error;
+    }
+
+    /* Set the workbook object in the packager. */
+    packager->workbook = self->workbook;
+
+    /* Assemble all the sub-files in the xlsx package. */
+    error = lxw_create_package(packager);
+
+    /* 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));
+    }
+
+    /* 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));
+    }
+
+    /* The next 2 error conditions don't set errno. */
+    if (error == LXW_ERROR_ZIP_FILE_ADD) {
+        fprintf(stderr, "[ERROR] workbook_close(): "
+                        "Zlib error adding file to xlsx file '%s'.\n",
+                self->workbook->filename);
+    }
+
+    if (error == LXW_ERROR_ZIP_CLOSE) {
+        fprintf(stderr, "[ERROR] workbook_close(): "
+                "Zlib error closing xlsx file '%s'.\n", self->workbook->filename);
+    }
+
+    mem_error:
+    if (handle) {
+        zend_list_close(Z_RES_P(handle));
+    }
+    return error;
+}
+
+void _php_vtiful_excel_close(zend_resource *rsrc TSRMLS_DC)
+{
+    //Here to PHP for gc
+}
+
+/*
+ * Iterate through the worksheets and store any defined names used for print
+ * ranges or repeat rows/columns.
+ */
+STATIC void
+_prepare_defined_names(lxw_workbook *self)
+{
+    lxw_worksheet *worksheet;
+    char app_name[LXW_DEFINED_NAME_LENGTH];
+    char range[LXW_DEFINED_NAME_LENGTH];
+    char area[LXW_MAX_CELL_RANGE_LENGTH];
+    char first_col[8];
+    char last_col[8];
+
+    STAILQ_FOREACH(worksheet, self->worksheets, list_pointers) {
+
+        /*
+         * Check for autofilter settings and store them.
+         */
+        if (worksheet->autofilter.in_use) {
+
+            lxw_snprintf(app_name, LXW_DEFINED_NAME_LENGTH,
+                         "%s!_FilterDatabase", worksheet->quoted_name);
+
+            lxw_rowcol_to_range_abs(area,
+                                    worksheet->autofilter.first_row,
+                                    worksheet->autofilter.first_col,
+                                    worksheet->autofilter.last_row,
+                                    worksheet->autofilter.last_col);
+
+            lxw_snprintf(range, LXW_DEFINED_NAME_LENGTH, "%s!%s",
+                         worksheet->quoted_name, area);
+
+            /* Autofilters are the only defined name to set the hidden flag. */
+            _store_defined_name(self, "_xlnm._FilterDatabase", app_name,
+                                range, worksheet->index, LXW_TRUE);
+        }
+
+        /*
+         * Check for Print Area settings and store them.
+         */
+        if (worksheet->print_area.in_use) {
+
+            lxw_snprintf(app_name, LXW_DEFINED_NAME_LENGTH,
+                         "%s!Print_Area", worksheet->quoted_name);
+
+            /* Check for print area that is the max row range. */
+            if (worksheet->print_area.first_row == 0
+                && worksheet->print_area.last_row == LXW_ROW_MAX - 1) {
+
+                lxw_col_to_name(first_col,
+                                worksheet->print_area.first_col, LXW_FALSE);
+
+                lxw_col_to_name(last_col,
+                                worksheet->print_area.last_col, LXW_FALSE);
+
+                lxw_snprintf(area, LXW_MAX_CELL_RANGE_LENGTH - 1, "$%s:$%s",
+                             first_col, last_col);
+
+            }
+                /* Check for print area that is the max column range. */
+            else if (worksheet->print_area.first_col == 0
+                     && worksheet->print_area.last_col == LXW_COL_MAX - 1) {
+
+                lxw_snprintf(area, LXW_MAX_CELL_RANGE_LENGTH - 1, "$%d:$%d",
+                             worksheet->print_area.first_row + 1,
+                             worksheet->print_area.last_row + 1);
+
+            }
+            else {
+                lxw_rowcol_to_range_abs(area,
+                                        worksheet->print_area.first_row,
+                                        worksheet->print_area.first_col,
+                                        worksheet->print_area.last_row,
+                                        worksheet->print_area.last_col);
+            }
+
+            lxw_snprintf(range, LXW_DEFINED_NAME_LENGTH, "%s!%s",
+                         worksheet->quoted_name, area);
+
+            _store_defined_name(self, "_xlnm.Print_Area", app_name,
+                                range, worksheet->index, LXW_FALSE);
+        }
+
+        /*
+         * Check for repeat rows/cols. aka, Print Titles and store them.
+         */
+        if (worksheet->repeat_rows.in_use || worksheet->repeat_cols.in_use) {
+            if (worksheet->repeat_rows.in_use
+                && worksheet->repeat_cols.in_use) {
+                lxw_snprintf(app_name, LXW_DEFINED_NAME_LENGTH,
+                             "%s!Print_Titles", worksheet->quoted_name);
+
+                lxw_col_to_name(first_col,
+                                worksheet->repeat_cols.first_col, LXW_FALSE);
+
+                lxw_col_to_name(last_col,
+                                worksheet->repeat_cols.last_col, LXW_FALSE);
+
+                lxw_snprintf(range, LXW_DEFINED_NAME_LENGTH,
+                             "%s!$%s:$%s,%s!$%d:$%d",
+                             worksheet->quoted_name, first_col,
+                             last_col, worksheet->quoted_name,
+                             worksheet->repeat_rows.first_row + 1,
+                             worksheet->repeat_rows.last_row + 1);
+
+                _store_defined_name(self, "_xlnm.Print_Titles", app_name,
+                                    range, worksheet->index, LXW_FALSE);
+            }
+            else if (worksheet->repeat_rows.in_use) {
+
+                lxw_snprintf(app_name, LXW_DEFINED_NAME_LENGTH,
+                             "%s!Print_Titles", worksheet->quoted_name);
+
+                lxw_snprintf(range, LXW_DEFINED_NAME_LENGTH,
+                             "%s!$%d:$%d", worksheet->quoted_name,
+                             worksheet->repeat_rows.first_row + 1,
+                             worksheet->repeat_rows.last_row + 1);
+
+                _store_defined_name(self, "_xlnm.Print_Titles", app_name,
+                                    range, worksheet->index, LXW_FALSE);
+            }
+            else if (worksheet->repeat_cols.in_use) {
+                lxw_snprintf(app_name, LXW_DEFINED_NAME_LENGTH,
+                             "%s!Print_Titles", worksheet->quoted_name);
+
+                lxw_col_to_name(first_col,
+                                worksheet->repeat_cols.first_col, LXW_FALSE);
+
+                lxw_col_to_name(last_col,
+                                worksheet->repeat_cols.last_col, LXW_FALSE);
+
+                lxw_snprintf(range, LXW_DEFINED_NAME_LENGTH,
+                             "%s!$%s:$%s", worksheet->quoted_name,
+                             first_col, last_col);
+
+                _store_defined_name(self, "_xlnm.Print_Titles", app_name,
+                                    range, worksheet->index, LXW_FALSE);
+            }
+        }
+    }
+}
+
+/*
+ * Iterate through the worksheets and set up any chart or image drawings.
+ */
+STATIC void
+_prepare_drawings(lxw_workbook *self)
+{
+    lxw_worksheet *worksheet;
+    lxw_image_options *image_options;
+    uint16_t chart_ref_id = 0;
+    uint16_t image_ref_id = 0;
+    uint16_t drawing_id = 0;
+
+    STAILQ_FOREACH(worksheet, self->worksheets, list_pointers) {
+
+        if (STAILQ_EMPTY(worksheet->image_data)
+            && STAILQ_EMPTY(worksheet->chart_data))
+            continue;
+
+        drawing_id++;
+
+        STAILQ_FOREACH(image_options, worksheet->chart_data, list_pointers) {
+            chart_ref_id++;
+            lxw_worksheet_prepare_chart(worksheet, chart_ref_id, drawing_id,
+                                        image_options);
+            if (image_options->chart)
+                STAILQ_INSERT_TAIL(self->ordered_charts, image_options->chart,
+                                   ordered_list_pointers);
+        }
+
+        STAILQ_FOREACH(image_options, worksheet->image_data, list_pointers) {
+
+            if (image_options->image_type == LXW_IMAGE_PNG)
+                self->has_png = LXW_TRUE;
+
+            if (image_options->image_type == LXW_IMAGE_JPEG)
+                self->has_jpeg = LXW_TRUE;
+
+            if (image_options->image_type == LXW_IMAGE_BMP)
+                self->has_bmp = LXW_TRUE;
+
+            image_ref_id++;
+
+            lxw_worksheet_prepare_image(worksheet, image_ref_id, drawing_id,
+                                        image_options);
+        }
+    }
+
+    self->drawing_count = drawing_id;
+}
+
+/*
+ * Add "cached" data to charts to provide the numCache and strCache data for
+ * series and title/axis ranges.
+ */
+STATIC void
+_add_chart_cache_data(lxw_workbook *self)
+{
+    lxw_chart *chart;
+    lxw_chart_series *series;
+
+    STAILQ_FOREACH(chart, self->ordered_charts, ordered_list_pointers) {
+
+        _populate_range(self, chart->title.range);
+        _populate_range(self, chart->x_axis->title.range);
+        _populate_range(self, chart->y_axis->title.range);
+
+        if (STAILQ_EMPTY(chart->series_list))
+            continue;
+
+        STAILQ_FOREACH(series, chart->series_list, list_pointers) {
+            _populate_range(self, series->categories);
+            _populate_range(self, series->values);
+            _populate_range(self, series->title.range);
+        }
+    }
+}

+ 19 - 0
kernel/write.h

@@ -0,0 +1,19 @@
+/*
+  +----------------------------------------------------------------------+
+  | Vtiful Extension                                                     |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2017-2017 The Viest                                    |
+  +----------------------------------------------------------------------+
+  | http://www.vtiful.com                                                |
+  +----------------------------------------------------------------------+
+  | Author: viest <[email protected]>                                 |
+  +----------------------------------------------------------------------+
+*/
+
+#ifndef VTIFUL_EXCEL_WRITE_H
+#define VTIFUL_EXCEL_WRITE_H
+
+void type_writer(zval *value, zend_long row, zend_long columns, excel_resource_t *res);
+lxw_error workbook_file(excel_resource_t *self, zval *handle);
+
+#endif

+ 3 - 1
php_vtiful.h

@@ -30,13 +30,15 @@ extern zend_module_entry vtiful_module_entry;
 #include "TSRM.h"
 #endif
 
+#define VTIFUL_RESOURCE_NAME "vtiful"
+
 extern int le_vtiful;
 
 #define VTIFUL_STARTUP_MODULE(module) ZEND_MODULE_STARTUP_N(vtiful_##module)(INIT_FUNC_ARGS_PASSTHRU)
 #define VTIFUL_STARTUP_FUNCTION(module) ZEND_MINIT_FUNCTION(vtiful_##module)
 #define VTIFUL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(vtiful, v)
 
-static void _php_vtiful_excel_close(zend_resource *rsrc TSRMLS_DC);
+void _php_vtiful_excel_close(zend_resource *rsrc TSRMLS_DC);
 
 #if defined(ZTS) && defined(COMPILE_DL_VTIFUL)
 ZEND_TSRMLS_CACHE_EXTERN();

+ 5 - 14
vtiful.c

@@ -33,7 +33,7 @@ PHP_MINIT_FUNCTION(vtiful)
     VTIFUL_STARTUP_MODULE(vtiful_exception);
 	VTIFUL_STARTUP_MODULE(excel);
 
-	le_vtiful = zend_register_list_destructors_ex(_php_vtiful_excel_close, NULL, "vtiful", module_number);
+	le_vtiful = zend_register_list_destructors_ex(_php_vtiful_excel_close, NULL, VTIFUL_RESOURCE_NAME, module_number);
 
 	return SUCCESS;
 }
@@ -94,21 +94,12 @@ PHP_MINFO_FUNCTION(vtiful)
  *
  * List destructor for FSS handles
  */
-static void _php_vtiful_excel_close(zend_resource *rsrc TSRMLS_DC)
-{
-//	int i;
-//	fss_resource_t * res = (fss_resource_t *)rsrc->ptr;
-//	/* Destroy the replace strings */
-//	for (i = 0; i < res->replace_size; i++) {
-//		if (res->replace[i]) {
-//			zval_ptr_dtor(res->replace[i]);
-//		}
-//	}
-//	/* Destroy the kwset structure */
-//	kwsfree(res->set);
+//static void _php_vtiful_excel_close(zend_resource *rsrc TSRMLS_DC)
+//{
+//	excel_resource_t * res = (excel_resource_t *)rsrc->ptr;
 //	/* Destroy the resource structure itself */
 //	efree(res);
-}
+//}
 /* }}} */