1 /*******************************************************************************
2 * Copyright (c) 2013-2021, Andrés Martinelli <andmarti@gmail.com> *
3 * All rights reserved. *
4 * *
5 * This file is a part of SC-IM *
6 * *
7 * SC-IM is a spreadsheet program that is based on SC. The original authors *
8 * of SC are James Gosling and Mark Weiser, and mods were later added by *
9 * Chuck Martin. *
10 * *
11 * Redistribution and use in source and binary forms, with or without *
12 * modification, are permitted provided that the following conditions are met: *
13 * 1. Redistributions of source code must retain the above copyright *
14 * notice, this list of conditions and the following disclaimer. *
15 * 2. Redistributions in binary form must reproduce the above copyright *
16 * notice, this list of conditions and the following disclaimer in the *
17 * documentation and/or other materials provided with the distribution. *
18 * 3. All advertising materials mentioning features or use of this software *
19 * must display the following acknowledgement: *
20 * This product includes software developed by Andrés Martinelli *
21 * <andmarti@gmail.com>. *
22 * 4. Neither the name of the Andrés Martinelli nor the *
23 * names of other contributors may be used to endorse or promote products *
24 * derived from this software without specific prior written permission. *
25 * *
26 * THIS SOFTWARE IS PROVIDED BY ANDRES MARTINELLI ''AS IS'' AND ANY *
27 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
29 * DISCLAIMED. IN NO EVENT SHALL ANDRES MARTINELLI BE LIABLE FOR ANY *
30 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;*
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
36 *******************************************************************************/
37
38 /**
39 * \file TODO <filename>
40 * \author Andrés Martinelli <andmarti@gmail.com>
41 * \date 2017-07-18
42 * \brief TODO Write a tbrief file description.
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include "sc.h"
50 #include "cmds.h"
51 #include "color.h"
52 #include "macros.h"
53 #include "xls.h"
54 #include "utils/string.h"
55
56 /*
57 * xls.h is part of libxls. make sure its installed and headers are in path.
58 * build must be done with '-lxlsreader'
59 */
60 #ifdef XLS
61 #include <xls.h>
62 #endif
63
64 /**
65 * \brief TODO <brief function description>
66 *
67 * \details This function loads an excel file into tbl. As SC-IM still
68 * does not handle multiple sheets, if excel file has multiple sheets,
69 * only the first one is read.
70 *
71 * \return -1 on error
72 */
73
open_xls(char * fname,char * encoding)74 int open_xls(char * fname, char * encoding) {
75 #ifdef XLS
76
77 // Set date format reading LOCALE
78 char fmt[15] = "%d/%m/%Y";
79
80 #ifdef USELOCALE
81 #include <locale.h>
82 #include <langinfo.h>
83 char * loc = NULL;
84 char * f = NULL;
85 loc = setlocale(LC_TIME, "");
86
87 if (loc != NULL) {
88 f = nl_langinfo(D_FMT);
89 strcpy(fmt, f);
90 }
91 #endif
92
93 // Read XLS file
94 xlsWorkBook * pWB;
95 xlsWorkSheet * pWS;
96 WORD r, c;
97 pWB = xls_open(fname, encoding);
98
99 wchar_t line_interp[FBUFLEN] = L"";
100 struct ent * n;
101
102 if (pWB == NULL) {
103 sc_error("Error loading %s", fname);
104 return -1;
105 }
106
107 pWS = xls_getWorkSheet(pWB, 0); //only the first sheet
108 if (pWS == NULL) return -1;
109 xls_parseWorkSheet(pWS);
110
111 for (r = 0; r <= pWS->rows.lastrow; r++) { // rows
112 for (c = 0; c <= pWS->rows.lastcol; c++) { // cols
113 xlsCell * cell = xls_cell(pWS, r, c);
114 if ((! cell) || (cell->isHidden)) continue;
115
116 // TODO enable rowspan ?
117 //if (cell->rowspan > 1) continue;
118
119 struct st_xf_data * xf = &pWB->xfs.xf[cell->xf];
120
121 //sc_debug("%d %d fmt:%d id:%x %d %d", r, c, xf->format, cell->id, cell->d, cell->l);
122
123 // these are dates
124 if (((xf->format >= 14 && xf->format <= 22) ||
125 (xf->format >= 165 && xf->format <= 180) ||
126 xf->format == 278 || xf->format == 185 || xf->format == 196 || xf->format
127 == 217 || xf->format == 326 )
128 && cell->id != 0x06
129 //&& cell->id != 0x27e
130 && cell->id != 0x0BD
131 && cell->id != 0x203 ) {
132
133 swprintf(line_interp, FBUFLEN, L"let %s%d=%.15g", coltoa(c), r, (cell->d - 25569) * 86400);
134 send_to_interp(line_interp);
135 n = lookat(r, c);
136 n->format = 0;
137 char * s = scxmalloc((unsigned)(strlen(fmt) + 2));
138 sprintf(s, "%c", 'd');
139 strcat(s, "%d/%m/%Y");
140 n->format = s;
141 continue;
142
143 // display the value of the cell (either numeric or string)
144 } else if (cell->id == 0x27e || cell->id == 0x0BD || cell->id == 0x203) {
145 swprintf(line_interp, FBUFLEN, L"let %s%d=%.15g", coltoa(c), r, cell->d);
146
147 } else if (cell->id == 0x06) { // formula
148 if (cell->l == 0) { // its a number
149 swprintf(line_interp, FBUFLEN, L"let %s%d=%.15g", coltoa(c), r, cell->d);
150 } else {
151 if (!strcmp((char *) cell->str, "bool")) { // its boolean, and test cell->d
152 swprintf(line_interp, FBUFLEN, L"label %s%d=\"%s\"", coltoa(c), r, (int) cell->d ? "true" : "false");
153 } else if (! strcmp((char *) cell->str, "error")) { // formula is in error
154 swprintf(line_interp, FBUFLEN, L"label %s%d=\"%s\"", coltoa(c), r, "error"); //FIXME
155 } else {
156 swprintf(line_interp, FBUFLEN, L"label %s%d=\"%s\"", coltoa(c), r, (char *) cell->str);
157 }
158 }
159
160 } else if (cell->str != NULL) {
161 int pad_pos;
162 if ((pad_pos = str_in_str((char *) cell->str, "\n")) != -1) ((char *) cell->str)[pad_pos] = '\0'; // For spanning
163 // clean_carrier((char *) cell->str); // For spanning
164 swprintf(line_interp, FBUFLEN, L"label %s%d=\"%s\"", coltoa(c), r, (char *) cell->str);
165 } else {
166 swprintf(line_interp, FBUFLEN, L"label %s%d=\"%s\"", coltoa(c), r, "");
167 }
168 send_to_interp(line_interp);
169 }
170 }
171 xls_close_WS(pWS);
172 xls_close_WB(pWB);
173 auto_justify(0, maxcols, DEFWIDTH);
174 return 0;
175 #else
176 return -1;
177 #endif
178 }
179