Sfoglia il codice sorgente

Merge pull request #161 from viest/dev

Feat insert date and read data with type
viest 5 anni fa
parent
commit
7d136b2c01

+ 11 - 0
include/excel.h

@@ -18,6 +18,17 @@
 #define V_XLS_COF    "config"
 #define V_XLS_PAT    "path"
 
+#define V_XLS_CONST_READ_TYPE_INT      "TYPE_INT"
+#define V_XLS_CONST_READ_TYPE_DOUBLE   "TYPE_DOUBLE"
+#define V_XLS_CONST_READ_TYPE_STRING   "TYPE_STRING"
+#define V_XLS_CONST_READ_TYPE_DATETIME "TYPE_TIMESTAMP"
+
+#define READ_TYPE_EMPTY    0x00
+#define READ_TYPE_STRING   0x01
+#define READ_TYPE_INT      0x02
+#define READ_TYPE_DOUBLE   0x04
+#define READ_TYPE_DATETIME 0x08
+
 #define GET_CONFIG_PATH(dir_path_res, class_name, object)                                          \
     do {                                                                                           \
         zval rv;                                                                                   \

+ 1 - 2
include/read.h

@@ -17,10 +17,9 @@
 #define READ_ROW 0x01
 
 int sheet_read_row(xlsxioreadersheet sheet);
-char* sheet_read_column(xlsxioreadersheet sheet);
 xlsxioreader file_open(const char *directory, const char *file_name);
 void load_sheet_all_data(xlsxioreadersheet sheet_t, zval *zv_result_t);
 xlsxioreadersheet sheet_open(xlsxioreader file, const zend_string *zs_sheet_name_t);
-unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, unsigned int flag);
+unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, zval *zv_type, unsigned int flag);
 
 #endif //PHP_READ_INCLUDE_H

+ 8 - 0
include/xlswriter.h

@@ -109,6 +109,14 @@ static inline chart_object *php_vtiful_chart_fetch_object(zend_object *obj) {
 #define Z_CHART_P(zv)  php_vtiful_chart_fetch_object(Z_OBJ_P(zv));
 #define Z_FORMAT_P(zv) php_vtiful_format_fetch_object(Z_OBJ_P(zv));
 
+#define WORKBOOK_NOT_INITIALIZED(xls_object_t)                                                                       \
+    do {                                                                                                             \
+        if(obj->write_ptr.workbook == NULL) {                                                                        \
+            zend_throw_exception(vtiful_exception_ce, "Please create a file first, use the filename method", 130);   \
+            return;                                                                                                  \
+        }                                                                                                            \
+    } while(0);
+
 #define ROW(range) \
     lxw_name_to_row(range)
 

+ 96 - 11
kernel/excel.c

@@ -99,6 +99,14 @@ ZEND_BEGIN_ARG_INFO_EX(xls_insert_text_arginfo, 0, 0, 5)
                 ZEND_ARG_INFO(0, format_handle)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(xls_insert_date_arginfo, 0, 0, 5)
+                ZEND_ARG_INFO(0, row)
+                ZEND_ARG_INFO(0, column)
+                ZEND_ARG_INFO(0, timestamp)
+                ZEND_ARG_INFO(0, format)
+                ZEND_ARG_INFO(0, format_handle)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(xls_insert_url_arginfo, 0, 0, 4)
                 ZEND_ARG_INFO(0, row)
                 ZEND_ARG_INFO(0, column)
@@ -235,13 +243,9 @@ PHP_METHOD(vtiful_xls, addSheet)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
     SHEET_LINE_INIT(obj)
 
-    if(obj->write_ptr.workbook == NULL) {
-        zend_throw_exception(vtiful_exception_ce, "Please create a file first, use the filename method", 130);
-        return;
-    }
-
     if(zs_sheet_name != NULL) {
         sheet_name = ZSTR_VAL(zs_sheet_name);
     }
@@ -266,10 +270,7 @@ PHP_METHOD(vtiful_xls, checkoutSheet)
 
     xls_object *obj = Z_XLS_P(getThis());
 
-    if(obj->write_ptr.workbook == NULL) {
-        zend_throw_exception(vtiful_exception_ce, "Please create a file first, use the filename method", 130);
-        return;
-    }
+    WORKBOOK_NOT_INITIALIZED(obj);
 
     if ((sheet_t = workbook_get_worksheet_by_name(obj->write_ptr.workbook, ZSTR_VAL(zs_sheet_name))) == NULL) {
         zend_throw_exception(vtiful_exception_ce, "Sheet not fund", 140);
@@ -339,6 +340,8 @@ PHP_METHOD(vtiful_xls, header)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(header), header_l_key, header_value)
          type_writer(header_value, 0, header_l_key, &obj->write_ptr, NULL, NULL);
          zval_ptr_dtor(header_value);
@@ -360,6 +363,8 @@ PHP_METHOD(vtiful_xls, data)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(data), data_r_value)
         if(Z_TYPE_P(data_r_value) == IS_ARRAY) {
             SHEET_LINE_ADD(obj)
@@ -383,6 +388,8 @@ PHP_METHOD(vtiful_xls, output)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     workbook_file(&obj->write_ptr);
 
     ZVAL_COPY(return_value, file_path);
@@ -420,6 +427,8 @@ PHP_METHOD(vtiful_xls, insertText)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     SHEET_LINE_SET(obj, row);
 
     if (format_handle) {
@@ -427,7 +436,54 @@ PHP_METHOD(vtiful_xls, insertText)
     } else {
         type_writer(data, row, column, &obj->write_ptr, format, NULL);
     }
+}
+/* }}} */
+
+/** {{{ \Vtiful\Kernel\xls::insertDate(int $row, int $column, int $timestamp[, string $format, resource $formatHandle])
+ */
+PHP_METHOD(vtiful_xls, insertDate)
+{
+    zval *data = NULL, *format_handle = NULL;
+    zend_long row, column;
+    zend_string *format = NULL;
+
+    ZEND_PARSE_PARAMETERS_START(3, 5)
+            Z_PARAM_LONG(row)
+            Z_PARAM_LONG(column)
+            Z_PARAM_ZVAL(data)
+            Z_PARAM_OPTIONAL
+            Z_PARAM_STR(format)
+            Z_PARAM_RESOURCE(format_handle)
+    ZEND_PARSE_PARAMETERS_END();
+
+    ZVAL_COPY(return_value, getThis());
+
+    xls_object *obj = Z_XLS_P(getThis());
+
+    WORKBOOK_NOT_INITIALIZED(obj);
+    SHEET_LINE_SET(obj, row);
+
+    if (Z_TYPE_P(data) != IS_LONG) {
+        zend_throw_exception(vtiful_exception_ce, "timestamp is long", 160);
+        return;
+    }
+
+    // Default datetime format
+    if (format == NULL) {
+        format = zend_string_init(ZEND_STRL("yyyy-mm-dd hh:mm:ss"), 0);
+    }
+
+    zval _zv_double_time;
+    ZVAL_DOUBLE(&_zv_double_time, ((double)data->value.lval / 86400 + 25569));
+
+    if (format_handle) {
+        type_writer(&_zv_double_time, row, column, &obj->write_ptr, format, zval_get_format(format_handle));
+    } else {
+        type_writer(&_zv_double_time, row, column, &obj->write_ptr, format, NULL);
+    }
 
+    zend_string_release(format);
+    zval_ptr_dtor(&_zv_double_time);
 }
 /* }}} */
 
@@ -448,6 +504,8 @@ PHP_METHOD(vtiful_xls, insertChart)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     chart_writer(row, column, zval_get_chart(chart_resource), &obj->write_ptr);
 }
 /* }}} */
@@ -474,6 +532,8 @@ PHP_METHOD(vtiful_xls, insertUrl)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     if (argc == 4) {
         url_writer(row, column, &obj->write_ptr, url, zval_get_format(format_handle));
     }
@@ -505,6 +565,8 @@ PHP_METHOD(vtiful_xls, insertImage)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     image_writer(image, row, column, width, height,  &obj->write_ptr);
 }
 /* }}} */
@@ -526,6 +588,8 @@ PHP_METHOD(vtiful_xls, insertFormula)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     formula_writer(formula, row, column, &obj->write_ptr);
 }
 /* }}} */
@@ -544,6 +608,8 @@ PHP_METHOD(vtiful_xls, autoFilter)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     auto_filter(range, &obj->write_ptr);
 }
 /* }}} */
@@ -563,6 +629,8 @@ PHP_METHOD(vtiful_xls, mergeCells)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     merge_cells(range, data, &obj->write_ptr);
 }
 /* }}} */
@@ -588,6 +656,8 @@ PHP_METHOD(vtiful_xls, setColumn)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     if (argc == 3) {
         set_column(range, width, &obj->write_ptr, zval_get_format(format_handle));
     }
@@ -619,6 +689,8 @@ PHP_METHOD(vtiful_xls, setRow)
 
     xls_object *obj = Z_XLS_P(getThis());
 
+    WORKBOOK_NOT_INITIALIZED(obj);
+
     if (argc == 3) {
         set_row(range, height, &obj->write_ptr, zval_get_format(format_handle));
     }
@@ -693,13 +765,20 @@ PHP_METHOD(vtiful_xls, getSheetData)
  */
 PHP_METHOD(vtiful_xls, nextRow)
 {
-    xls_object *obj  = Z_XLS_P(getThis());
+    zval *zv_type = NULL;
+
+    ZEND_PARSE_PARAMETERS_START(0, 1)
+            Z_PARAM_OPTIONAL
+            Z_PARAM_ARRAY(zv_type)
+    ZEND_PARSE_PARAMETERS_END();
+
+    xls_object *obj = Z_XLS_P(getThis());
 
     if (!obj->read_ptr.sheet_t) {
         RETURN_FALSE;
     }
 
-    load_sheet_current_row_data(obj->read_ptr.sheet_t, return_value, READ_ROW);
+    load_sheet_current_row_data(obj->read_ptr.sheet_t, return_value, zv_type, READ_ROW);
 }
 /* }}} */
 
@@ -719,6 +798,7 @@ zend_function_entry xls_methods[] = {
         PHP_ME(vtiful_xls, getHandle,     NULL,                       ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, autoFilter,    xls_auto_filter_arginfo,    ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, insertText,    xls_insert_text_arginfo,    ZEND_ACC_PUBLIC)
+        PHP_ME(vtiful_xls, insertDate,    xls_insert_date_arginfo,    ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, insertChart,   xls_insert_chart_arginfo,   ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, insertUrl,     xls_insert_url_arginfo,     ZEND_ACC_PUBLIC)
         PHP_ME(vtiful_xls, insertImage,   xls_insert_image_arginfo,   ZEND_ACC_PUBLIC)
@@ -754,6 +834,11 @@ VTIFUL_STARTUP_FUNCTION(excel) {
     REGISTER_CLASS_PROPERTY_NULL(vtiful_xls_ce, V_XLS_COF, ZEND_ACC_PRIVATE);
     REGISTER_CLASS_PROPERTY_NULL(vtiful_xls_ce, V_XLS_FIL, ZEND_ACC_PRIVATE);
 
+    REGISTER_CLASS_CONST_LONG(vtiful_xls_ce, V_XLS_CONST_READ_TYPE_INT,      READ_TYPE_INT);
+    REGISTER_CLASS_CONST_LONG(vtiful_xls_ce, V_XLS_CONST_READ_TYPE_DOUBLE,   READ_TYPE_DOUBLE);
+    REGISTER_CLASS_CONST_LONG(vtiful_xls_ce, V_XLS_CONST_READ_TYPE_STRING,   READ_TYPE_STRING);
+    REGISTER_CLASS_CONST_LONG(vtiful_xls_ce, V_XLS_CONST_READ_TYPE_DATETIME, READ_TYPE_DATETIME);
+
     return SUCCESS;
 }
 /* }}} */

+ 44 - 10
kernel/read.c

@@ -49,16 +49,11 @@ int sheet_read_row(xlsxioreadersheet sheet)
 /* }}} */
 
 /* {{{ */
-char* sheet_read_column(xlsxioreadersheet sheet)
-{
-    return xlsxioread_sheet_next_cell(sheet);
-}
-/* }}} */
-
-/* {{{ */
-unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, unsigned int flag)
+unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_result_t, zval *zv_type_arr_t, unsigned int flag)
 {
+    zend_long _type = READ_TYPE_EMPTY;
     char *_string_value = NULL;
+    Bucket *_start = NULL, *_end = NULL;
 
     if (flag && !sheet_read_row(sheet_t)) {
         return XLSWRITER_FALSE;
@@ -68,8 +63,47 @@ unsigned int load_sheet_current_row_data(xlsxioreadersheet sheet_t, zval *zv_res
         array_init(zv_result_t);
     }
 
-    while ((_string_value = sheet_read_column(sheet_t)) != NULL)
+    if (zv_type_arr_t != NULL && Z_TYPE_P(zv_type_arr_t) == IS_ARRAY) {
+        _start = zv_type_arr_t->value.arr->arData;
+        _end   = _start + zv_type_arr_t->value.arr->nNumUsed;
+    }
+
+    while ((_string_value = xlsxioread_sheet_next_cell(sheet_t)) != NULL)
     {
+        if (_start != _end) {
+            zval *_zv_type = &_start->val;
+
+            if (Z_TYPE_P(_zv_type) == IS_LONG) {
+                _type = Z_LVAL_P(_zv_type);
+            }
+
+            _start++;
+        }
+
+        if (_type & READ_TYPE_DATETIME) {
+            double value = strtod(_string_value, NULL);
+
+            if (value != 0) {
+                value = (value - 25569) * 86400;
+            }
+
+            add_next_index_double(zv_result_t, value);
+            continue;
+        }
+
+        if (_type & READ_TYPE_DOUBLE) {
+            add_next_index_double(zv_result_t, strtod(_string_value, NULL));
+            continue;
+        }
+
+        if (_type & READ_TYPE_INT) {
+            zend_long _long_value;
+
+            sscanf(_string_value, "%" PRIi64, &_long_value);
+            add_next_index_long(zv_result_t, _long_value);
+            continue;
+        }
+
         add_next_index_stringl(zv_result_t, _string_value, strlen(_string_value));
     }
 
@@ -89,7 +123,7 @@ void load_sheet_all_data(xlsxioreadersheet sheet_t, zval *zv_result_t)
         zval _zv_tmp_row;
         ZVAL_NULL(&_zv_tmp_row);
 
-        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, READ_SKIP_ROW);
+        load_sheet_current_row_data(sheet_t, &_zv_tmp_row, NULL, READ_SKIP_ROW);
         add_next_index_zval(zv_result_t, &_zv_tmp_row);
     }
 }

+ 25 - 0
tests/insert_date_custom_format.phpt

@@ -0,0 +1,25 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php if (!extension_loaded("xlswriter")) print "skip"; ?>
+--FILE--
+<?php
+$config = [
+    'path' => './tests'
+];
+
+$fileObject = new \Vtiful\Kernel\Excel($config);
+$fileObject = $fileObject->fileName('tutorial.xlsx');
+
+$filePath = $fileObject->header(['date'])
+    ->insertDate(1, 0, time(), 'mmm d yyyy hh:mm AM/PM')
+    ->output();
+
+var_dump($filePath);
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+string(21) "./tests/tutorial.xlsx"

+ 25 - 0
tests/insert_date_default_format.phpt

@@ -0,0 +1,25 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php if (!extension_loaded("xlswriter")) print "skip"; ?>
+--FILE--
+<?php
+$config = [
+    'path' => './tests'
+];
+
+$fileObject = new \Vtiful\Kernel\Excel($config);
+$fileObject = $fileObject->fileName('tutorial.xlsx');
+
+$filePath = $fileObject->header(['date'])
+    ->insertDate(1, 0, time())
+    ->output();
+
+var_dump($filePath);
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+string(21) "./tests/tutorial.xlsx"

+ 49 - 0
tests/open_xlsx_next_row_with_data_type_date.phpt

@@ -0,0 +1,49 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php
+require __DIR__ . '/include/skipif.inc';
+skip_disable_reader();
+?>
+--FILE--
+<?php
+$config = [
+    'path' => './tests',
+];
+
+$fileObject = new \Vtiful\Kernel\Excel($config);
+$fileObject = $fileObject->fileName('tutorial.xlsx');
+
+$filePath = $fileObject->header(['date'])
+    ->insertDate(1, 0, 1568389354, 'mmm d yyyy hh:mm AM/PM')
+    ->output();
+
+$fileObject->openFile('tutorial.xlsx')
+    ->openSheet();
+
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING])); // Header
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_TIMESTAMP]));
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_TIMESTAMP]));
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_TIMESTAMP]));
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_TIMESTAMP]));
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_TIMESTAMP]));
+var_dump($fileObject->nextRow([\Vtiful\Kernel\Excel::TYPE_TIMESTAMP]));
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+array(1) {
+  [0]=>
+  string(4) "date"
+}
+array(1) {
+  [0]=>
+  float(1568389354)
+}
+NULL
+NULL
+NULL
+NULL
+NULL

+ 51 - 0
tests/open_xlsx_next_row_with_data_type_string.phpt

@@ -0,0 +1,51 @@
+--TEST--
+Check for vtiful presence
+--SKIPIF--
+<?php
+require __DIR__ . '/include/skipif.inc';
+skip_disable_reader();
+?>
+--FILE--
+<?php
+$config   = ['path' => './tests'];
+$excel    = new \Vtiful\Kernel\Excel($config);
+$filePath = $excel->fileName('tutorial.xlsx')
+    ->header(['Item', 'Cost'])
+    ->data([
+        ['Item_1', 'Cost_1'],
+    ])
+    ->output();
+
+$excel->openFile('tutorial.xlsx')
+    ->openSheet();
+
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+var_dump($excel->nextRow([\Vtiful\Kernel\Excel::TYPE_STRING, \Vtiful\Kernel\Excel::TYPE_STRING]));
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/tutorial.xlsx');
+?>
+--EXPECT--
+array(2) {
+  [0]=>
+  string(4) "Item"
+  [1]=>
+  string(4) "Cost"
+}
+array(2) {
+  [0]=>
+  string(6) "Item_1"
+  [1]=>
+  string(6) "Cost_1"
+}
+NULL
+NULL
+NULL
+NULL
+NULL