Skip to content

Commit a0b6a0b

Browse files
committed
Add xlsxioread_sheet_next_cell_with_format() function which returns cell style number format (in addition to cell value).
1 parent b2b39b9 commit a0b6a0b

File tree

5 files changed

+187
-31
lines changed

5 files changed

+187
-31
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ IF(BUILD_SHARED)
8484
ENDIF()
8585

8686
FOREACH(LINKTYPE ${LINKTYPES})
87-
ADD_LIBRARY(xlsxio_read_${LINKTYPE} ${LINKTYPE} lib/xlsxio_read.c lib/xlsxio_read_sharedstrings.c)
87+
ADD_LIBRARY(xlsxio_read_${LINKTYPE} ${LINKTYPE} lib/xlsxio_read.c lib/xlsxio_read_sharedstrings.c lib/xlsxio_read_cellstyles.c)
8888
SET_TARGET_PROPERTIES(xlsxio_read_${LINKTYPE} PROPERTIES DEFINE_SYMBOL "BUILD_XLSXIO_DLL")
8989
SET_TARGET_PROPERTIES(xlsxio_read_${LINKTYPE} PROPERTIES COMPILE_DEFINITIONS "BUILD_XLSXIO;${ANYZIP_DEF}")
9090
SET_TARGET_PROPERTIES(xlsxio_read_${LINKTYPE} PROPERTIES OUTPUT_NAME xlsxio_read)
@@ -193,7 +193,7 @@ INSTALL(TARGETS ${ALLTARGETS}
193193
RUNTIME DESTINATION bin
194194
)
195195
INSTALL(DIRECTORY include/
196-
DESTINATION include
196+
DESTINATION include
197197
FILES_MATCHING PATTERN "xlsxio*.h"
198198
)
199199
IF(MINGW AND BUILD_SHARED)

include/xlsxio_read.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ DLL_EXPORT_XLSXIO int xlsxioread_sheet_next_row (xlsxioreadersheet sheethandle);
254254
*/
255255
DLL_EXPORT_XLSXIO XLSXIOCHAR* xlsxioread_sheet_next_cell (xlsxioreadersheet sheethandle);
256256

257+
DLL_EXPORT_XLSXIO XLSXIOCHAR* xlsxioread_sheet_next_cell_with_format (xlsxioreadersheet sheethandle, int* format);
258+
257259
/*! \brief get next cell from worksheet as a string
258260
* \param sheethandle read handle for worksheet object
259261
* \param pvalue pointer where string will be stored if data is available (caller must free the result)

lib/xlsxio_read.c

Lines changed: 118 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "xlsxio_private.h"
22
#include "xlsxio_read_sharedstrings.h"
3+
#include "xlsxio_read_cellstyles.h"
34
#include "xlsxio_read.h"
45
#include "xlsxio_version.h"
56
#include <stdlib.h>
@@ -181,7 +182,7 @@ int expat_process_zip_file (ZIPFILETYPE* zip, const XML_Char* filename, XML_Star
181182
#endif
182183
//return (status == XML_STATUS_ERROR != XML_ERROR_FINISHED ? 1 : 0);
183184
return 0;
184-
}
185+
}
185186

186187
XML_Parser expat_process_zip_file_suspendable (ZIPFILEENTRYTYPE* zipfile, XML_StartElementHandler start_handler, XML_EndElementHandler end_handler, XML_CharacterDataHandler data_handler, void* callbackdata)
187188
{
@@ -246,7 +247,7 @@ int XML_Char_icmp_ins (const XML_Char* value, const XML_Char* name)
246247
return -1;
247248
}
248249
#endif
249-
250+
250251
//get expat attribute by name, returns NULL if not found
251252
const XML_Char* get_expat_attr_by_name (const XML_Char** atts, const XML_Char* name)
252253
{
@@ -378,8 +379,8 @@ voidpf ZCALLBACK minizip_io_filehandle_open_file_fn (voidpf opaque, const char*
378379
return NULL;
379380
return &((struct minizip_io_filehandle_data*)opaque)->filehandle;
380381
}
381-
382-
uLong ZCALLBACK minizip_io_filehandle_read_file_fn (voidpf opaque, voidpf stream, void* buf, uLong size)
382+
383+
uLong ZCALLBACK minizip_io_filehandle_read_file_fn (voidpf opaque, voidpf stream, void* buf, uLong size)
383384
{
384385
IOSIZETYPE len;
385386
if (!opaque || !stream || !buf || size == 0)
@@ -389,32 +390,32 @@ uLong ZCALLBACK minizip_io_filehandle_read_file_fn (voidpf opaque, voidpf stream
389390
return len;
390391
}
391392

392-
/*
393-
uLong ZCALLBACK minizip_io_filehandle_write_file_fn (voidpf opaque, voidpf stream, const void* buf, uLong size)
393+
/*
394+
uLong ZCALLBACK minizip_io_filehandle_write_file_fn (voidpf opaque, voidpf stream, const void* buf, uLong size)
394395
{
395396
return 0;
396397
}
397398
*/
398-
399-
int ZCALLBACK minizip_io_filehandle_close_file_fn (voidpf opaque, voidpf stream)
399+
400+
int ZCALLBACK minizip_io_filehandle_close_file_fn (voidpf opaque, voidpf stream)
400401
{
401402
if (stream)
402403
close(*(int*)stream);
403404
free(opaque);
404405
return 0;
405406
}
406-
407-
int ZCALLBACK minizip_io_filehandle_testerror_file_fn (voidpf opaque, voidpf stream)
407+
408+
int ZCALLBACK minizip_io_filehandle_testerror_file_fn (voidpf opaque, voidpf stream)
408409
{
409410
return 0;
410411
}
411-
412-
long ZCALLBACK minizip_io_filehandle_tell_file_fn (voidpf opaque, voidpf stream)
412+
413+
long ZCALLBACK minizip_io_filehandle_tell_file_fn (voidpf opaque, voidpf stream)
413414
{
414415
return IOFN(lseek)(*(int*)stream, 0, SEEK_CUR);
415416
}
416-
417-
long ZCALLBACK minizip_io_filehandle_seek_file_fn (voidpf opaque, voidpf stream, uLong offset, int origin)
417+
418+
long ZCALLBACK minizip_io_filehandle_seek_file_fn (voidpf opaque, voidpf stream, uLong offset, int origin)
418419
{
419420
int whence;
420421
if (!opaque || !stream)
@@ -489,8 +490,8 @@ voidpf ZCALLBACK minizip_io_memory_open_file_fn (voidpf opaque, const char* file
489490
}
490491
return result;
491492
}
492-
493-
uLong ZCALLBACK minizip_io_memory_read_file_fn (voidpf opaque, voidpf stream, void* buf, uLong size)
493+
494+
uLong ZCALLBACK minizip_io_memory_read_file_fn (voidpf opaque, voidpf stream, void* buf, uLong size)
494495
{
495496
uLong len;
496497
if (!opaque || !stream || !buf || size == 0)
@@ -504,35 +505,35 @@ uLong ZCALLBACK minizip_io_memory_read_file_fn (voidpf opaque, voidpf stream, vo
504505
return len;
505506
}
506507

507-
/*
508-
uLong ZCALLBACK minizip_io_memory_write_file_fn (voidpf opaque, voidpf stream, const void* buf, uLong size)
508+
/*
509+
uLong ZCALLBACK minizip_io_memory_write_file_fn (voidpf opaque, voidpf stream, const void* buf, uLong size)
509510
{
510511
return 0;
511512
}
512513
*/
513-
514-
int ZCALLBACK minizip_io_memory_close_file_fn (voidpf opaque, voidpf stream)
514+
515+
int ZCALLBACK minizip_io_memory_close_file_fn (voidpf opaque, voidpf stream)
515516
{
516517
free(stream);
517518
if (opaque && ((struct minizip_io_memory_data*)opaque)->freedata)
518519
free(((struct minizip_io_memory_data*)opaque)->data);
519520
free(opaque);
520521
return 0;
521522
}
522-
523-
int ZCALLBACK minizip_io_memory_testerror_file_fn (voidpf opaque, voidpf stream)
523+
524+
int ZCALLBACK minizip_io_memory_testerror_file_fn (voidpf opaque, voidpf stream)
524525
{
525526
return 0;
526527
}
527-
528-
long ZCALLBACK minizip_io_memory_tell_file_fn (voidpf opaque, voidpf stream)
528+
529+
long ZCALLBACK minizip_io_memory_tell_file_fn (voidpf opaque, voidpf stream)
529530
{
530531
if (!opaque || !stream)
531532
return 0;
532533
return ((struct minizip_io_memory_handle*)stream)->pos;
533534
}
534-
535-
long ZCALLBACK minizip_io_memory_seek_file_fn (voidpf opaque, voidpf stream, uLong offset, int origin)
535+
536+
long ZCALLBACK minizip_io_memory_seek_file_fn (voidpf opaque, voidpf stream, uLong offset, int origin)
536537
{
537538
switch (origin) {
538539
case ZLIB_FILEFUNC_SEEK_CUR :
@@ -888,6 +889,9 @@ struct data_sheet_callback_data {
888889
XML_Char* celldata;
889890
size_t celldatalen;
890891
cell_string_type_enum cell_string_type;
892+
int cell_style_idx;
893+
int num_format;
894+
int* cell_style_formats;
891895
unsigned int flags;
892896
XML_Char* skiptag; //tag to skip
893897
size_t skiptagcount; //nesting level for current tag to skip
@@ -899,7 +903,7 @@ struct data_sheet_callback_data {
899903
void* callbackdata;
900904
};
901905

902-
void data_sheet_callback_data_initialize (struct data_sheet_callback_data* data, struct sharedstringlist* sharedstrings, unsigned int flags, xlsxioread_process_cell_callback_fn cell_callback, xlsxioread_process_row_callback_fn row_callback, void* callbackdata)
906+
void data_sheet_callback_data_initialize (struct data_sheet_callback_data* data, struct sharedstringlist* sharedstrings, unsigned int flags, xlsxioread_process_cell_callback_fn cell_callback, xlsxioread_process_row_callback_fn row_callback, void* callbackdata, int* cell_style_formats)
903907
{
904908
data->xmlparser = NULL;
905909
data->sharedstrings = sharedstrings;
@@ -909,6 +913,8 @@ void data_sheet_callback_data_initialize (struct data_sheet_callback_data* data,
909913
data->celldata = NULL;
910914
data->celldatalen = 0;
911915
data->cell_string_type = none;
916+
data->cell_style_idx = -1;
917+
data->cell_style_formats = cell_style_formats;
912918
data->flags = flags;
913919
data->skiptag = NULL;
914920
data->skiptagcount = 0;
@@ -925,6 +931,7 @@ void data_sheet_callback_data_cleanup (struct data_sheet_callback_data* data)
925931
sharedstringlist_destroy(data->sharedstrings);
926932
free(data->celldata);
927933
free(data->skiptag);
934+
free(data->cell_style_formats);
928935
}
929936

930937
void data_sheet_expat_callback_skip_tag_start (void* callbackdata, const XML_Char* name, const XML_Char** atts)
@@ -1122,6 +1129,13 @@ void data_sheet_expat_callback_find_cell_start (void* callbackdata, const XML_Ch
11221129
data->cell_string_type = shared_string;
11231130
else
11241131
data->cell_string_type = value_string;
1132+
1133+
const XML_Char* s = get_expat_attr_by_name(atts, X("s"));
1134+
if (s != NULL) {
1135+
sscanf(s, "%d", &data->cell_style_idx);
1136+
} else {
1137+
data->cell_style_idx = -1;
1138+
}
11251139
//prepare empty value data
11261140
free(data->celldata);
11271141
data->celldata = NULL;
@@ -1152,6 +1166,11 @@ void data_sheet_expat_callback_find_cell_end (void* callbackdata, const XML_Char
11521166
free(data->celldata);
11531167
data->celldata = NULL;
11541168
}
1169+
if (data->cell_style_idx > -1 && data->cell_style_idx < 256) {
1170+
data->num_format = data->cell_style_formats[data->cell_style_idx];
1171+
} else {
1172+
data->num_format = -1;
1173+
}
11551174
}
11561175
//reset data
11571176
data->colnr++;
@@ -1268,17 +1287,29 @@ DLL_EXPORT_XLSXIO int xlsxioread_process (xlsxioreader handle, const XLSXIOCHAR*
12681287
shared_strings_callback_data_cleanup(&sharedstringsdata);
12691288
}
12701289

1290+
// styles
1291+
int* cell_style_formats = NULL;
1292+
if (getrelscallbackdata.stylesfile && getrelscallbackdata.stylesfile[0]) {
1293+
cell_style_formats = malloc(256 * sizeof(int));
1294+
struct cell_styles_callback_data cell_styles_data;
1295+
cell_styles_callback_data_initialize(&cell_styles_data, cell_style_formats);
1296+
if (expat_process_zip_file(handle->zip, getrelscallbackdata.stylesfile, cell_styles_callback_find_start, NULL, NULL, &cell_styles_data, &cell_styles_data.xmlparser) != 0) {
1297+
free(cell_style_formats);
1298+
cell_style_formats = NULL;
1299+
}
1300+
}
1301+
12711302
//process sheet
12721303
if (!(flags & XLSXIOREAD_NO_CALLBACK)) {
12731304
//use callback mechanism
12741305
struct data_sheet_callback_data processcallbackdata;
1275-
data_sheet_callback_data_initialize(&processcallbackdata, sharedstrings, flags, cell_callback, row_callback, callbackdata);
1306+
data_sheet_callback_data_initialize(&processcallbackdata, sharedstrings, flags, cell_callback, row_callback, callbackdata, cell_style_formats);
12761307
expat_process_zip_file(handle->zip, getrelscallbackdata.sheetfile, data_sheet_expat_callback_find_worksheet_start, NULL, NULL, &processcallbackdata, &processcallbackdata.xmlparser);
12771308
data_sheet_callback_data_cleanup(&processcallbackdata);
12781309
} else {
12791310
//use simplified interface by suspending the XML parser when data is found
12801311
xlsxioreadersheet sheethandle = (xlsxioreadersheet)callbackdata;
1281-
data_sheet_callback_data_initialize(&sheethandle->processcallbackdata, sharedstrings, flags, NULL, NULL, sheethandle);
1312+
data_sheet_callback_data_initialize(&sheethandle->processcallbackdata, sharedstrings, flags, NULL, NULL, sheethandle, cell_style_formats);
12821313
if ((sheethandle->zipfile = XML_Char_openzip(sheethandle->handle->zip, getrelscallbackdata.sheetfile, 0)) == NULL) {
12831314
result = 1;
12841315
}
@@ -1488,6 +1519,64 @@ DLL_EXPORT_XLSXIO XLSXIOCHAR* xlsxioread_sheet_next_cell (xlsxioreadersheet shee
14881519
return result;
14891520
}
14901521

1522+
DLL_EXPORT_XLSXIO XLSXIOCHAR* xlsxioread_sheet_next_cell_with_format (xlsxioreadersheet sheethandle, int* format)
1523+
{
1524+
XML_Char* result;
1525+
if (!sheethandle)
1526+
return NULL;
1527+
//append empty column if needed
1528+
if (sheethandle->paddingcol) {
1529+
if (sheethandle->paddingcol > sheethandle->processcallbackdata.cols) {
1530+
//last empty column added, finish row
1531+
sheethandle->paddingcol = 0;
1532+
//when padding rows prepare for the next one
1533+
if (sheethandle->paddingrow) {
1534+
sheethandle->lastrownr++;
1535+
sheethandle->paddingrow++;
1536+
if (sheethandle->paddingrow + 1 < sheethandle->processcallbackdata.rownr) {
1537+
sheethandle->paddingcol = 1;
1538+
}
1539+
}
1540+
return NULL;
1541+
} else {
1542+
//add another empty column
1543+
sheethandle->paddingcol++;
1544+
return XML_Char_dup(X(""));
1545+
}
1546+
}
1547+
//get value
1548+
if (!sheethandle->processcallbackdata.celldata)
1549+
if (expat_process_zip_file_resume(sheethandle->zipfile, sheethandle->processcallbackdata.xmlparser) != XML_STATUS_SUSPENDED)
1550+
sheethandle->processcallbackdata.celldata = NULL;
1551+
//insert empty rows if needed
1552+
if (!(sheethandle->processcallbackdata.flags & XLSXIOREAD_SKIP_EMPTY_ROWS) && sheethandle->lastrownr + 1 < sheethandle->processcallbackdata.rownr) {
1553+
sheethandle->paddingrow = sheethandle->lastrownr + 1;
1554+
sheethandle->paddingcol = sheethandle->processcallbackdata.colnr*0 + 1;
1555+
return xlsxioread_sheet_next_cell_with_format(sheethandle, format);
1556+
}
1557+
//insert empty column before if needed
1558+
if (!(sheethandle->processcallbackdata.flags & XLSXIOREAD_SKIP_EMPTY_CELLS)) {
1559+
if (sheethandle->lastcolnr + 1 < sheethandle->processcallbackdata.colnr) {
1560+
sheethandle->lastcolnr++;
1561+
return XML_Char_dup(X(""));
1562+
}
1563+
}
1564+
result = sheethandle->processcallbackdata.celldata;
1565+
sheethandle->processcallbackdata.celldata = NULL;
1566+
//end of row
1567+
if (!result) {
1568+
sheethandle->lastrownr = sheethandle->processcallbackdata.rownr;
1569+
//insert empty column at end if row if needed
1570+
if (!result && !(sheethandle->processcallbackdata.flags & XLSXIOREAD_SKIP_EMPTY_CELLS) && sheethandle->processcallbackdata.colnr < sheethandle->processcallbackdata.cols) {
1571+
sheethandle->paddingcol = sheethandle->lastcolnr + 1;
1572+
return xlsxioread_sheet_next_cell_with_format(sheethandle, format);
1573+
}
1574+
}
1575+
sheethandle->lastcolnr = sheethandle->processcallbackdata.colnr;
1576+
*format = sheethandle->processcallbackdata.num_format;
1577+
return result;
1578+
}
1579+
14911580
DLL_EXPORT_XLSXIO int xlsxioread_sheet_next_cell_string (xlsxioreadersheet sheethandle, XLSXIOCHAR** pvalue)
14921581
{
14931582
XML_Char* result;

lib/xlsxio_read_cellstyles.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "xlsxio_private.h"
2+
#include "xlsxio_read_cellstyles.h"
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
7+
void cell_styles_callback_data_initialize (struct cell_styles_callback_data* data, int* cell_style_formats)
8+
{
9+
data->xmlparser = NULL;
10+
data->cell_style_formats = cell_style_formats;
11+
data->num_cell_style_formats = 0;
12+
}
13+
14+
void cell_styles_callback_find_start (void* callbackdata, const XML_Char* name, const XML_Char** atts)
15+
{
16+
struct cell_styles_callback_data* data = (struct cell_styles_callback_data*)callbackdata;
17+
if (XML_Char_icmp(name, X("cellXfs")) == 0) {
18+
XML_SetElementHandler(data->xmlparser, cell_styles_callback_xf_handler, NULL);
19+
}
20+
}
21+
22+
void cell_styles_callback_xf_handler (void* callbackdata, const XML_Char* name, const XML_Char** atts)
23+
{
24+
struct cell_styles_callback_data* data = (struct cell_styles_callback_data*)callbackdata;
25+
if (XML_Char_icmp(name, X("xf")) == 0) {
26+
const XML_Char* value = get_expat_attr_by_name(atts, X("numFmtId"));
27+
if (value != NULL) {
28+
sscanf(value, "%d", &data->cell_style_formats[data->num_cell_style_formats++]);
29+
}
30+
} else {
31+
XML_SetElementHandler(data->xmlparser, cell_styles_callback_find_start, NULL);
32+
}
33+
}

lib/xlsxio_read_cellstyles.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef INCLUDED_XLSXIO_READ_CELLSTYLES_H
2+
#define INCLUDED_XLSXIO_READ_CELLSTYLES_H
3+
4+
#include <stdint.h>
5+
#include <expat.h>
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
struct cell_styles_callback_data {
12+
XML_Parser xmlparser;
13+
int* cell_style_formats;
14+
int num_cell_style_formats;
15+
};
16+
17+
#ifdef ASSUME_NO_NAMESPACE
18+
#define XML_Char_icmp_ins XML_Char_icmp
19+
#else
20+
int XML_Char_icmp_ins (const XML_Char* value, const XML_Char* name);
21+
#endif
22+
23+
const XML_Char* get_expat_attr_by_name (const XML_Char** attrs, const XML_Char* name);
24+
void cell_styles_callback_data_initialize (struct cell_styles_callback_data* data, int* cell_style_formats);
25+
void cell_styles_callback_find_start (void* callbackdata, const XML_Char* name, const XML_Char** atts);
26+
void cell_styles_callback_xf_handler (void* callbackdata, const XML_Char* name, const XML_Char** atts);
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
#endif

0 commit comments

Comments
 (0)