Skip to content

Commit 452ecf9

Browse files
authored
Merge pull request #229 from viest/dev
Feat: sheet writer exception and custom csv delimiter
2 parents 77a1d16 + 712b4fc commit 452ecf9

File tree

8 files changed

+222
-25
lines changed

8 files changed

+222
-25
lines changed

include/csv.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
#ifndef PHP_EXT_XLS_WRITER_CSV_H
1414
#define PHP_EXT_XLS_WRITER_CSV_H
1515

16-
unsigned int xlsx_to_csv(zval *stream_resource, xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache);
16+
unsigned int xlsx_to_csv(
17+
zval *stream_resource,
18+
const char *delimiter_str, int delimiter_str_len,
19+
const char *enclosure_str, int enclosure_str_len,
20+
const char *escape_str, int escape_str_len,
21+
xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
22+
);
1723

1824
#endif // PHP_EXT_XLS_WRITER_CSV_H

include/xlswriter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ static inline chart_object *php_vtiful_chart_fetch_object(zend_object *obj) {
141141
} \
142142
} while(0);
143143

144+
#define WORKSHEET_WRITER_EXCEPTION(error) \
145+
do { \
146+
if(error > LXW_NO_ERROR) { \
147+
zend_throw_exception(vtiful_exception_ce, "Worksheet write exception", error); \
148+
return; \
149+
} \
150+
} while(0)
151+
144152
#define FCALL_TWO_ARGS(bucket) \
145153
ZVAL_COPY_VALUE(&args[0], &bucket->val); \
146154
if (bucket->key) { \

kernel/csv.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@
1515
#include "ext/standard/file.h"
1616

1717
/* {{{ */
18-
unsigned int xlsx_to_csv(zval *stream_resource, xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache)
18+
unsigned int xlsx_to_csv(
19+
zval *stream_resource,
20+
const char *delimiter_str, int delimiter_str_len,
21+
const char *enclosure_str, int enclosure_str_len,
22+
const char *escape_str, int escape_str_len,
23+
xlsxioreadersheet sheet_t, zval *zv_type_arr_t, unsigned int flag, zend_fcall_info *fci, zend_fcall_info_cache *fci_cache
24+
)
1925
{
20-
zval *_zv_type_arr_t = NULL;
21-
php_stream *_stream_t;
22-
2326
ssize_t ret = 0;
24-
char delimiter = ',';
25-
char enclosure = '"';
26-
int escape_char = (unsigned char) '\\';
27+
zval *_zv_type_arr_t = NULL;
28+
php_stream *_stream_t = NULL;
29+
char delimiter = ',', enclosure = '"', escape_char = '\\';
2730

2831
ZEND_ASSERT(Z_TYPE_P(stream_resource) == IS_RESOURCE);
2932

@@ -32,6 +35,42 @@ unsigned int xlsx_to_csv(zval *stream_resource, xlsxioreadersheet sheet_t, zval
3235
return XLSWRITER_FALSE;
3336
}
3437

38+
if (delimiter_str != NULL) {
39+
if (delimiter_str_len < 1) {
40+
zend_throw_exception(vtiful_exception_ce, "delimiter must be a character", 190);
41+
return XLSWRITER_FALSE;
42+
} else if (delimiter_str_len > 1) {
43+
zend_throw_exception(vtiful_exception_ce, "delimiter must be a single character", 191);
44+
return XLSWRITER_FALSE;
45+
}
46+
47+
delimiter = *delimiter_str;
48+
}
49+
50+
if (enclosure_str != NULL) {
51+
if (enclosure_str_len < 1) {
52+
zend_throw_exception(vtiful_exception_ce, "enclosure must be a character", 192);
53+
return XLSWRITER_FALSE;
54+
} else if (enclosure_str_len > 1) {
55+
zend_throw_exception(vtiful_exception_ce, "enclosure must be a single character", 193);
56+
return XLSWRITER_FALSE;
57+
}
58+
59+
enclosure = *enclosure_str;
60+
}
61+
62+
if (escape_str != NULL) {
63+
if (escape_str_len < 1) {
64+
zend_throw_exception(vtiful_exception_ce, "escape must be a character", 194);
65+
return XLSWRITER_FALSE;
66+
} else if (escape_str_len > 1) {
67+
zend_throw_exception(vtiful_exception_ce, "escape must be a single character", 195);
68+
return XLSWRITER_FALSE;
69+
}
70+
71+
escape_char = *escape_str;
72+
}
73+
3574
if (Z_TYPE_P(zv_type_arr_t) == IS_ARRAY) {
3675
_zv_type_arr_t = zv_type_arr_t;
3776
}

kernel/excel.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,17 @@ ZEND_END_ARG_INFO()
176176

177177
ZEND_BEGIN_ARG_INFO_EX(xls_put_csv_arginfo, 0, 0, 1)
178178
ZEND_ARG_INFO(0, fp)
179+
ZEND_ARG_INFO(0, delimiter_str)
180+
ZEND_ARG_INFO(0, enclosure_str)
181+
ZEND_ARG_INFO(0, escape_str)
179182
ZEND_END_ARG_INFO()
180183

181184
ZEND_BEGIN_ARG_INFO_EX(xls_put_csv_callback_arginfo, 0, 0, 2)
182185
ZEND_ARG_INFO(0, callback)
183186
ZEND_ARG_INFO(0, fp)
187+
ZEND_ARG_INFO(0, delimiter_str)
188+
ZEND_ARG_INFO(0, enclosure_str)
189+
ZEND_ARG_INFO(0, escape_str)
184190
ZEND_END_ARG_INFO()
185191

186192
ZEND_BEGIN_ARG_INFO_EX(xls_set_type_arginfo, 0, 0, 1)
@@ -991,10 +997,16 @@ PHP_METHOD(vtiful_xls, setType)
991997
*/
992998
PHP_METHOD(vtiful_xls, putCSV)
993999
{
994-
zval *fp = NULL, *zv_type = NULL;;
1000+
zval *fp = NULL, *zv_type = NULL;
1001+
char *delimiter_str = NULL, *enclosure_str = NULL, *escape_str = NULL;
1002+
size_t delimiter_str_len = 0, enclosure_str_len = 0, escape_str_len = 0;
9951003

996-
ZEND_PARSE_PARAMETERS_START(1, 1)
1004+
ZEND_PARSE_PARAMETERS_START(1, 4)
9971005
Z_PARAM_RESOURCE(fp)
1006+
Z_PARAM_OPTIONAL
1007+
Z_PARAM_STRING(delimiter_str, delimiter_str_len)
1008+
Z_PARAM_STRING(enclosure_str, enclosure_str_len)
1009+
Z_PARAM_STRING(escape_str,escape_str_len)
9981010
ZEND_PARSE_PARAMETERS_END();
9991011

10001012
xls_object *obj = Z_XLS_P(getThis());
@@ -1005,7 +1017,10 @@ PHP_METHOD(vtiful_xls, putCSV)
10051017

10061018
zv_type = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
10071019

1008-
if (xlsx_to_csv(fp, obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, NULL, NULL) == XLSWRITER_TRUE) {
1020+
if (xlsx_to_csv(
1021+
fp, delimiter_str, delimiter_str_len, enclosure_str, enclosure_str_len, escape_str, escape_str_len,
1022+
obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, NULL, NULL
1023+
) == XLSWRITER_TRUE) {
10091024
RETURN_TRUE;
10101025
}
10111026

@@ -1018,12 +1033,18 @@ PHP_METHOD(vtiful_xls, putCSV)
10181033
PHP_METHOD(vtiful_xls, putCSVCallback)
10191034
{
10201035
zval *fp = NULL, *zv_type = NULL;
1021-
zend_fcall_info fci = empty_fcall_info;
1036+
zend_fcall_info fci = empty_fcall_info;
10221037
zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
1038+
char *delimiter_str = NULL, *enclosure_str = NULL, *escape_str = NULL;
1039+
size_t delimiter_str_len = 0, enclosure_str_len = 0, escape_str_len = 0;
10231040

1024-
ZEND_PARSE_PARAMETERS_START(2, 2)
1041+
ZEND_PARSE_PARAMETERS_START(2, 5)
10251042
Z_PARAM_FUNC(fci, fci_cache)
10261043
Z_PARAM_RESOURCE(fp)
1044+
Z_PARAM_OPTIONAL
1045+
Z_PARAM_STRING(delimiter_str, delimiter_str_len)
1046+
Z_PARAM_STRING(enclosure_str, enclosure_str_len)
1047+
Z_PARAM_STRING(escape_str,escape_str_len)
10271048
ZEND_PARSE_PARAMETERS_END();
10281049

10291050
xls_object *obj = Z_XLS_P(getThis());
@@ -1034,7 +1055,10 @@ PHP_METHOD(vtiful_xls, putCSVCallback)
10341055

10351056
zv_type = zend_read_property(vtiful_xls_ce, getThis(), ZEND_STRL(V_XLS_TYPE), 0, NULL);
10361057

1037-
if (xlsx_to_csv(fp, obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, &fci, &fci_cache) == XLSWRITER_TRUE) {
1058+
if (xlsx_to_csv(
1059+
fp, delimiter_str, delimiter_str_len, enclosure_str, enclosure_str_len, escape_str, escape_str_len,
1060+
obj->read_ptr.sheet_t, zv_type, READ_SKIP_ROW, &fci, &fci_cache
1061+
) == XLSWRITER_TRUE) {
10381062
RETURN_TRUE;
10391063
}
10401064

kernel/write.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ void type_writer(zval *value, zend_long row, zend_long columns, xls_resource_wri
2626

2727
if (value_type == IS_STRING) {
2828
zend_string *_zs_value = zval_get_string(value);
29-
worksheet_write_string(res->worksheet, lxw_row, lxw_col, ZSTR_VAL(_zs_value), format_handle);
29+
30+
int error = worksheet_write_string(res->worksheet, lxw_row, lxw_col, ZSTR_VAL(_zs_value), format_handle);
31+
3032
zend_string_release(_zs_value);
33+
WORKSHEET_WRITER_EXCEPTION(error);
3134
return;
3235
}
3336

@@ -36,13 +39,12 @@ void type_writer(zval *value, zend_long row, zend_long columns, xls_resource_wri
3639
value_format = workbook_add_format(res->workbook);
3740

3841
format_set_num_format(value_format, ZSTR_VAL(format));
39-
40-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), value_format);
42+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), value_format));
4143
return;
4244
}
4345

4446
if (format == NULL && format_handle != NULL) {
45-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), format_handle);
47+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), format_handle));
4648
return;
4749
}
4850

@@ -52,25 +54,24 @@ void type_writer(zval *value, zend_long row, zend_long columns, xls_resource_wri
5254
format_copy(value_format, format_handle);
5355
format_set_num_format(value_format, ZSTR_VAL(format));
5456

55-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), value_format);
57+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), value_format));
5658
return;
5759
}
5860

59-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), NULL);
61+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, (double)zval_get_long(value), NULL));
6062
}
6163

6264
if (value_type == IS_DOUBLE) {
6365
if (format != NULL && format_handle == NULL) {
6466
value_format = workbook_add_format(res->workbook);
65-
6667
format_set_num_format(value_format, ZSTR_VAL(format));
6768

68-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, zval_get_double(value), value_format);
69+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, zval_get_double(value), value_format));
6970
return;
7071
}
7172

7273
if (format == NULL && format_handle != NULL) {
73-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, zval_get_double(value), format_handle);
74+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, zval_get_double(value), format_handle));
7475
return;
7576
}
7677

@@ -80,11 +81,11 @@ void type_writer(zval *value, zend_long row, zend_long columns, xls_resource_wri
8081
format_copy(value_format, format_handle);
8182
format_set_num_format(value_format, ZSTR_VAL(format));
8283

83-
worksheet_write_number(res->worksheet, lxw_row, lxw_col, zval_get_double(value), value_format);
84+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, lxw_row, lxw_col, zval_get_double(value), value_format));
8485
return;
8586
}
8687

87-
worksheet_write_number(res->worksheet, (lxw_row_t)row, (lxw_col_t)columns, zval_get_double(value), NULL);
88+
WORKSHEET_WRITER_EXCEPTION(worksheet_write_number(res->worksheet, (lxw_row_t)row, (lxw_col_t)columns, zval_get_double(value), NULL));
8889
return;
8990
}
9091
}

package.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
<file md5sum="39f7c511d9019c6815bcf7fd0f7e8224" name="tests/chart_style.phpt" role="test" />
182182
<file md5sum="bfdf9e054f8efd971a65d00eca465f2f" name="tests/chart_title.phpt" role="test" />
183183
<file md5sum="9badb50b14bd81536bafcfefcb5677d6" name="tests/column_index_from_string.phpt" role="test" />
184+
<file name="tests/const_memory_index_out_range.phpt" role="test" />
184185
<file name="tests/default_format.phpt" role="test" />
185186
<file name="tests/fix-207.phpt" role="test" />
186187
<file md5sum="df2a6af4ced4ea7660a1691d18e75e8c" name="tests/format_align.phpt" role="test" />
@@ -223,6 +224,8 @@
223224
<file md5sum="5811dd930d7b0f916c662139ff1053d4" name="tests/string_from_column_index.phpt" role="test" />
224225
<file md5sum="42b26f050d9291509d6f583ef43ebde9" name="tests/xlsx_to_csv.phpt" role="test" />
225226
<file name="tests/xlsx_to_csv_callback.phpt" role="test" />
227+
<file name="tests/xlsx_to_csv_callback_custom_delimiter.phpt" role="test" />
228+
<file name="tests/xlsx_to_csv_custom_delimiter.phpt" role="test" />
226229
<file md5sum="a9af7f4ca385ba41b008b50ac67f8e96" name="tests/zoom.phpt" role="test" />
227230
<file md5sum="f4a2d1a28ad1bf782502d698de0b1907" name="tests/include/skipif.inc" role="test" />
228231
<file md5sum="bb4256831dfd81f951bd6f4afbe1719f" name="CREDITS" role="doc" />
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
--TEST--
2+
Check for vtiful presence
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/include/skipif.inc';
6+
skip_disable_reader();
7+
?>
8+
--FILE--
9+
<?php
10+
$config = ['path' => './tests'];
11+
$excel = new \Vtiful\Kernel\Excel($config);
12+
$filePath = $excel->fileName('tutorial.xlsx', 'TestSheet1')
13+
->header(['Item', 'Cost'])
14+
->data([
15+
['Item_1', 'Cost_1', 10, 10.9999995],
16+
])
17+
->output();
18+
19+
$fp = fopen('./tests/file.csv', 'w');
20+
21+
$csvResult = $excel->openFile('tutorial.xlsx')
22+
->openSheet()
23+
->putCSVCallback(function($row){
24+
return $row;
25+
}, $fp, ';');
26+
27+
var_dump($csvResult);
28+
29+
if (($csvHandler = fopen('./tests/file.csv', 'r')) === FALSE) {
30+
die('csv file open failure');
31+
}
32+
33+
while (($data = fgetcsv($csvHandler, 1000, ';')) !== FALSE) {
34+
var_dump($data);
35+
}
36+
?>
37+
--CLEAN--
38+
<?php
39+
@unlink(__DIR__ . '/tutorial.xlsx');
40+
@unlink(__DIR__ . '/file.csv');
41+
?>
42+
--EXPECT--
43+
bool(true)
44+
array(2) {
45+
[0]=>
46+
string(4) "Item"
47+
[1]=>
48+
string(4) "Cost"
49+
}
50+
array(4) {
51+
[0]=>
52+
string(6) "Item_1"
53+
[1]=>
54+
string(6) "Cost_1"
55+
[2]=>
56+
string(2) "10"
57+
[3]=>
58+
string(10) "10.9999995"
59+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
Check for vtiful presence
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/include/skipif.inc';
6+
skip_disable_reader();
7+
?>
8+
--FILE--
9+
<?php
10+
$config = ['path' => './tests'];
11+
$excel = new \Vtiful\Kernel\Excel($config);
12+
$filePath = $excel->fileName('tutorial.xlsx', 'TestSheet1')
13+
->header(['Item', 'Cost'])
14+
->data([
15+
['Item_1', 'Cost_1', 10, 10.9999995],
16+
])
17+
->output();
18+
19+
$fp = fopen('./tests/file.csv', 'w');
20+
21+
$csvResult = $excel->openFile('tutorial.xlsx')
22+
->openSheet()
23+
->putCSV($fp, ';');
24+
25+
var_dump($csvResult);
26+
27+
if (($csvHandler = fopen('./tests/file.csv', 'r')) === FALSE) {
28+
die('csv file open failure');
29+
}
30+
31+
while (($data = fgetcsv($csvHandler, 1000, ';')) !== FALSE) {
32+
var_dump($data);
33+
}
34+
?>
35+
--CLEAN--
36+
<?php
37+
@unlink(__DIR__ . '/tutorial.xlsx');
38+
@unlink(__DIR__ . '/file.csv');
39+
?>
40+
--EXPECT--
41+
bool(true)
42+
array(2) {
43+
[0]=>
44+
string(4) "Item"
45+
[1]=>
46+
string(4) "Cost"
47+
}
48+
array(4) {
49+
[0]=>
50+
string(6) "Item_1"
51+
[1]=>
52+
string(6) "Cost_1"
53+
[2]=>
54+
string(2) "10"
55+
[3]=>
56+
string(10) "10.9999995"
57+
}

0 commit comments

Comments
 (0)