/* PSPP - a program for statistical analysis.
Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include "libpspp/message.h"
#include "libpspp/misc.h"
#include "gl/minmax.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
#define N_(msgid) (msgid)
#if XLS_SUPPORT
struct casereader *
xls_open_reader (struct xls_read_info *xls, struct dictionary **dict)
{
msg (ME, _("Support for XLS files was not compiled into this installation of PSPP"));
return NULL;
}
#else
#include "data/xls-reader.h"
#include
#include
#include
#include
#include
#include "data/case.h"
#include "data/casereader-provider.h"
#include "data/dictionary.h"
#include "data/identifier.h"
#include "data/value.h"
#include "data/variable.h"
#include "libpspp/i18n.h"
#include "libpspp/str.h"
#include "gl/xalloc.h"
static void xls_file_casereader_destroy (struct casereader *, void *);
static struct ccase *xls_file_casereader_read (struct casereader *, void *);
void convert_xls_to_value(struct ccase *, const struct variable *, xlsCell *);
static const struct casereader_class xls_file_casereader_class =
{
xls_file_casereader_read,
xls_file_casereader_destroy,
NULL,
NULL,
};
struct xls_reader
{
int n_cases;
int first_case;
int last_case;
int next_case;
int n_var_specs;
struct caseproto *proto;
struct dictionary *dict;
xlsWorkBook* pWB;
xlsWorkSheet* pWS;
};
static void
xls_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
{
struct xls_reader *r = r_;
if (r == NULL)
return;
caseproto_unref(r->proto);
free(r);
}
struct casereader *
xls_open_reader (struct xls_read_info *xls, struct dictionary **dict)
{
struct xls_reader *r = NULL;
char charset[] = "UTF-8";
int i;
r = xzalloc (sizeof *r);
r->pWB = xls_open(xls->file_name, charset);
if (NULL == r->pWB)
{
msg (ME, _("Error opening `%s' for reading as a XLS file: %s."),
xls->file_name, strerror (errno));
return NULL;
}
r->pWS = xls_getWorkSheet(r->pWB, 0);
xls_parseWorkSheet(r->pWS);
r->n_cases = r->pWS->rows.lastrow;
r->n_var_specs = r->pWS->rows.lastcol;
r->first_case = 0;
r->last_case = r->n_cases;
r->next_case = 0;
/* Create the dictionary and populate it */
*dict = r->dict = dict_create ();
for (i = 0 ; i < r->n_var_specs ; ++i )
{
unsigned long int vstart = 0;
char *name;
name = dict_make_unique_var_name (r->dict, NULL, &vstart);
dict_create_var (r->dict, name, 255);
free (name);
}
r->proto = caseproto_ref (dict_get_proto (r->dict));
return casereader_create_sequential
(NULL,
r->proto,
r->n_cases,
&xls_file_casereader_class, r);
}
/* Reads and returns one case from READER's file. Returns a null
pointer on failure. */
static struct ccase *
xls_file_casereader_read (struct casereader *reader UNUSED, void *r_)
{
struct ccase *c;
int i;
struct xls_reader *r = r_;
c = case_create (r->proto);
case_set_missing (c);
if(r->next_case > r->last_case)
return NULL;
for ( i = 0 ; i < r->n_var_specs ; ++i )
{
const struct variable *var = dict_get_var (r->dict, i);
xlsCell *cell = xls_cell(r->pWS, r->next_case, i);
convert_xls_to_value (c, var, cell);
}
r->next_case++;
return c;
}
void
convert_xls_to_value(struct ccase *c, const struct variable *var, xlsCell *cell)
{
union value *v = case_data_rw (c, var);
int width = var_get_width(var);
char *tmp = malloc(width);
if (cell->id == 0x27e || cell->id == 0x0BD || cell->id == 0x203)
sprintf(tmp,"%.15g", cell->d);
/* Formula */
else if (cell->id == 0x06)
{
/* Numeric Formula */
if (cell->l == 0)
sprintf(tmp,"%.15g", cell->d);
else
{
/* Boolean Formula */
if (strcmp(cell->str,"bool"))
{
if(cell->d)
sprintf(tmp,"true");
else
sprintf(tmp,"false");
}
/* Error Formula */
else if (strcmp(cell->str,"error"))
sprintf(tmp,"*error*");
/* Probably a String Formula */
else
sprintf(tmp,"%s",cell->str);
}
}
/* String? */
else if (cell->str != NULL)
tmp = cell->str;
/*Empty Cell*/
else
sprintf(tmp, "%s", "");
value_copy_str_rpad(v, width, (const uint8_t *) tmp, ' ');
}
#endif /* XLS_SUPPORT */