}
-struct casereader *
-ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts,
- struct dictionary **dict)
+/* Try to find out how many sheets there are in the "workbook" */
+static int
+get_sheet_count (struct zip_reader *zreader)
{
- int ret = 0;
- xmlChar *type = NULL;
- unsigned long int vstart = 0;
- casenumber n_cases = CASENUMBER_MAX;
- int i;
- struct var_spec *var_spec = NULL;
- int n_var_specs = 0;
+ xmlTextReaderPtr mxtr;
+ struct zip_member *meta = NULL;
+ meta = zip_member_open (zreader, "meta.xml");
+
+ if ( meta == NULL)
+ return -1;
+
+ mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
+ (xmlInputCloseCallback) zip_member_finish,
+ meta, NULL, NULL, XML_PARSE_RECOVER);
+
+ while (1 == xmlTextReaderRead (mxtr))
+ {
+ xmlChar *name = xmlTextReaderName (mxtr);
+ if ( 0 == xmlStrcmp (name, _xml("meta:document-statistic")))
+ {
+ xmlChar *attr = xmlTextReaderGetAttribute (mxtr, _xml ("meta:table-count"));
+
+ if ( attr != NULL)
+ {
+ int s = _xmlchar_to_int (attr);
+ return s;
+ }
+ }
+ }
+ return -1;
+}
- struct ods_reader *r = xzalloc (sizeof *r);
+struct spreadsheet *ods_probe (const char *filename)
+{
+ struct ods_reader *r;
+ struct string errs;
+ xmlTextReaderPtr xtr ;
+ int sheet_count;
struct zip_member *content = NULL;
- struct zip_reader *zreader ;
- xmlChar *val_string = NULL;
- r->read_names = gri->read_names;
- ds_init_empty (&r->ods_errs);
+ struct zip_reader *zreader = NULL;
- zreader = zip_reader_create (gri->file_name, &r->ods_errs);
+ ds_init_empty (&errs);
- if ( NULL == zreader)
- {
- msg (ME, _("Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."),
- gri->file_name, ds_cstr (&r->ods_errs));
+ zreader = zip_reader_create (filename, &errs);
- goto error;
- }
+ if (zreader == NULL)
+ return NULL;
content = zip_member_open (zreader, "content.xml");
- if ( NULL == content)
- {
- msg (ME, _("Could not extract OpenDocument spreadsheet from file `%s': %s."),
- gri->file_name, ds_cstr (&r->ods_errs));
- goto error;
- }
+ if ( content == NULL)
+ goto error;
zip_member_ref (content);
- r->xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
+ sheet_count = get_sheet_count (zreader);
+
+ xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
(xmlInputCloseCallback) zip_member_finish,
content, NULL, NULL, XML_PARSE_RECOVER);
- if ( r->xtr == NULL)
- {
- goto error;
- }
+ if ( xtr == NULL)
+ goto error;
+
+ r = xzalloc (sizeof *r);
+ r->xtr = xtr;
+ r->spreadsheet.type = SPREADSHEET_ODS;
+ r->spreadsheet.sheets = sheet_count;
+
+ ds_destroy (&errs);
+
+ return &r->spreadsheet;
+
+ error:
+ zip_reader_destroy (zreader);
+ ds_destroy (&errs);
+ return NULL;
+}
+
+struct casereader *
+ods_make_reader (struct spreadsheet *spreadsheet,
+ const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts)
+{
+ intf ret = 0;
+ xmlChar *type = NULL;
+ unsigned long int vstart = 0;
+ casenumber n_cases = CASENUMBER_MAX;
+ int i;
+ struct var_spec *var_spec = NULL;
+ int n_var_specs = 0;
+
+ struct ods_reader *r = (struct ods_reader *) spreadsheet;
+ xmlChar *val_string = NULL;
+
+ assert (r);
+ r->read_names = gri->read_names;
+ ds_init_empty (&r->ods_errs);
if ( opts->cell_range )
{
}
/* Create the dictionary and populate it */
- *dict = r->dict = dict_create (
+ r->spreadsheet.dict = r->dict = dict_create (
CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr)));
for (i = 0 ; i < n_var_specs ; ++i )
convert_xml_to_value (r->first_case, var, &var_spec[i].firstval);
}
- zip_reader_destroy (zreader);
+ // zip_reader_destroy (zreader);
for ( i = 0 ; i < n_var_specs ; ++i )
{
error:
- zip_reader_destroy (zreader);
+ // zip_reader_destroy (zreader);
for ( i = 0 ; i < n_var_specs ; ++i )
{
free (var_spec);
- dict_destroy (r->dict);
+ dict_destroy (r->spreadsheet.dict);
+ r->spreadsheet.dict = NULL;
ods_file_casereader_destroy (NULL, r);
return r->first_case;
}
-
if ( r->state > STATE_INIT)
{
c = case_create (r->proto);
struct spreadsheet_read_options;
-struct casereader * ods_open_reader (const struct spreadsheet_read_info *,
- struct spreadsheet_read_options *,
- struct dictionary **);
+struct spreadsheet *ods_probe (const char *filename);
+
+struct casereader * ods_make_reader (struct spreadsheet *spreadsheet,
+ const struct spreadsheet_read_info *gri,
+ struct spreadsheet_read_options *opts);
#endif
enum spreadsheet_type
{
+ SPREADSHEET_NONE,
SPREADSHEET_GNUMERIC,
SPREADSHEET_ODS
};
}
else if (0 == strncasecmp (tok, "ODS", 3))
{
- reader = ods_open_reader (&sri, &opts, &dict);
+ struct spreadsheet *spreadsheet = ods_probe (sri.file_name);
+ reader = ods_make_reader (spreadsheet, &sri, &opts);
+ dict = spreadsheet->dict;
}
if (reader)
on_prepare (GtkAssistant *assistant, GtkWidget *page,
struct import_assistant *ia)
{
+ struct sheet_spec_page *ssp = &ia->sheet_spec;
+
int pn = gtk_assistant_get_current_page (assistant);
- if (pn == 1 && ia->file.type != FTYPE_TEXT)
+ if (pn == 1 && ssp->spreadsheet)
post_sheet_spec_page (ia);
if (gtk_assistant_get_page_type (assistant, page)
prepare_separators_page (ia);
else if (page == ia->formats.page)
prepare_formats_page (ia);
- else if (page == ia->sheet_spec.page)
- prepare_sheet_spec_page (ia);
+ else if (page == ia->sheet_spec.page && ssp->spreadsheet)
+ {
+ prepare_sheet_spec_page (ia);
+ }
struct ccase *c;
int col;
+
sepp->column_cnt = dict_get_var_cnt (ssp->dict);
sepp->columns = xcalloc (sepp->column_cnt, sizeof (*sepp->columns));
for (col = 0; col < sepp->column_cnt ; ++col)
}
file->line_cnt = rows;
- casereader_destroy (ssp->reader);
- ssp->reader = NULL;
}
sri.read_names = true;
sri.asw = -1;
- ssp->spreadsheet = gnumeric_probe (sri.file_name);
+ if (ssp->spreadsheet == NULL)
+ ssp->spreadsheet = gnumeric_probe (sri.file_name);
+
+ printf ("%s:%d %p %d\n", __FILE__, __LINE__, ssp->spreadsheet, ssp->spreadsheet->type);
+
+ if (ssp->spreadsheet == NULL)
+ ssp->spreadsheet = ods_probe (sri.file_name);
+
+ printf ("%s:%d %p %d\n", __FILE__, __LINE__, ssp->spreadsheet, ssp->spreadsheet->type);
if (ssp->spreadsheet)
{
- struct casereader *creader = NULL;
- struct dictionary *dict = NULL;
-
- if (ssp->spreadsheet->type == SPREADSHEET_GNUMERIC)
- {
- ia->file.type = FTYPE_GNUMERIC;
- }
- else if (ssp->spreadsheet->type == SPREADSHEET_ODS)
- {
- ia->file.type = FTYPE_ODS;
- }
- else
- {
- assert (0);
- }
-
- {
- struct sheet_spec_page *ssp = &ia->sheet_spec;
- ssp->dict = dict;
- ssp->reader = creader;
-
- update_assistant (ia);
- }
-
+
+ // update_assistant (ia);
}
else
{
+ printf ("%s:%d %p\n", __FILE__, __LINE__, ssp->spreadsheet);
+
struct string input;
struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
if (reader == NULL)
}
line_reader_close (reader);
- ia->file.type = FTYPE_TEXT;
}
return true;
ssp->sri.read_names = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (readnames_checkbox));
ssp->sri.asw = -1;
- switch (ia->file.type)
+ switch (ssp->spreadsheet->type)
{
- case FTYPE_ODS:
- creader = ods_open_reader (&ssp->sri, &ssp->opts, &dict);
+ case SPREADSHEET_ODS:
+ {
+ creader = ods_make_reader (ssp->spreadsheet, &ssp->sri, &ssp->opts);
+ dict = ssp->spreadsheet->dict;
+ }
break;
- case FTYPE_GNUMERIC:
+ case SPREADSHEET_GNUMERIC:
{
creader = gnumeric_make_reader (ssp->spreadsheet, &ssp->sri, &ssp->opts);
dict = ssp->spreadsheet->dict;
{
GtkWindow *parent_window = GTK_WINDOW (dw);
struct import_assistant *ia;
+ struct sheet_spec_page *ssp ;
ia = xzalloc (sizeof *ia);
if (!init_file (ia, parent_window))
}
init_assistant (ia, parent_window);
- if ( ia->file.type == FTYPE_TEXT)
+ ssp = &ia->sheet_spec;
+ if (ssp->spreadsheet == NULL)
{
init_intro_page (ia);
init_first_line_page (ia);
break;
}
- if ( ia->file.type == FTYPE_TEXT)
+ if (ssp->spreadsheet == NULL)
{
destroy_formats_page (ia);
destroy_separators_page (ia);
static char *
generate_syntax (const struct import_assistant *ia)
{
+ struct sheet_spec_page *ssp = &ia->sheet_spec;
+
struct string s = DS_EMPTY_INITIALIZER;
- switch (ia->file.type)
+ if (ssp->spreadsheet == NULL)
{
- case FTYPE_TEXT:
- {
- size_t var_cnt;
- size_t i;
- syntax_gen_pspp (&s,
- "GET DATA"
- "\n /TYPE=TXT"
- "\n /FILE=%sq\n",
- ia->file.file_name);
- if (ia->file.encoding && strcmp (ia->file.encoding, "Auto"))
- syntax_gen_pspp (&s, " /ENCODING=%sq\n", ia->file.encoding);
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
- ia->intro.n_cases_button)))
- ds_put_format (&s, " /IMPORTCASES=FIRST %d\n",
- gtk_spin_button_get_value_as_int (
- GTK_SPIN_BUTTON (ia->intro.n_cases_spin)));
- else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
- ia->intro.percent_button)))
- ds_put_format (&s, " /IMPORTCASES=PERCENT %d\n",
- gtk_spin_button_get_value_as_int (
- GTK_SPIN_BUTTON (ia->intro.percent_spin)));
- else
- ds_put_cstr (&s, " /IMPORTCASES=ALL\n");
- ds_put_cstr (&s,
- " /ARRANGEMENT=DELIMITED\n"
- " /DELCASE=LINE\n");
- if (ia->first_line.skip_lines > 0)
- ds_put_format (&s, " /FIRSTCASE=%d\n", ia->first_line.skip_lines + 1);
- ds_put_cstr (&s, " /DELIMITERS=\"");
- if (ds_find_byte (&ia->separators.separators, '\t') != SIZE_MAX)
- ds_put_cstr (&s, "\\t");
- if (ds_find_byte (&ia->separators.separators, '\\') != SIZE_MAX)
- ds_put_cstr (&s, "\\\\");
- for (i = 0; i < ds_length (&ia->separators.separators); i++)
- {
- char c = ds_at (&ia->separators.separators, i);
- if (c == '"')
- ds_put_cstr (&s, "\"\"");
- else if (c != '\t' && c != '\\')
- ds_put_byte (&s, c);
- }
- ds_put_cstr (&s, "\"\n");
- if (!ds_is_empty (&ia->separators.quotes))
- syntax_gen_pspp (&s, " /QUALIFIER=%sq\n", ds_cstr (&ia->separators.quotes));
- if (!ds_is_empty (&ia->separators.quotes) && ia->separators.escape)
- ds_put_cstr (&s, " /ESCAPE\n");
- ds_put_cstr (&s, " /VARIABLES=\n");
-
- var_cnt = dict_get_var_cnt (ia->formats.dict);
- for (i = 0; i < var_cnt; i++)
- {
- struct variable *var = dict_get_var (ia->formats.dict, i);
- char format_string[FMT_STRING_LEN_MAX + 1];
- fmt_to_string (var_get_print_format (var), format_string);
- ds_put_format (&s, " %s %s%s\n",
- var_get_name (var), format_string,
- i == var_cnt - 1 ? "." : "");
- }
-
- apply_dict (ia->formats.dict, &s);
- }
- break;
- case FTYPE_GNUMERIC:
- case FTYPE_ODS:
- {
- const struct sheet_spec_page *ssp = &ia->sheet_spec;
-
- syntax_gen_pspp (&s,
- "GET DATA"
- "\n /TYPE=%ss"
- "\n /FILE=%sq"
- "\n /SHEET=index %d"
- "\n /READNAMES=%ss",
- (ia->file.type == FTYPE_GNUMERIC) ? "GNM" : "ODS",
- ia->file.file_name,
- ssp->opts.sheet_index,
- ssp->sri.read_names ? "ON" : "OFF");
-
-
- if ( ssp->opts.cell_range)
- {
- syntax_gen_pspp (&s,
- "\n /CELLRANGE=RANGE %sq",
- ssp->opts.cell_range);
- }
- else
- {
- syntax_gen_pspp (&s,
- "\n /CELLRANGE=FULL");
- }
-
-
- syntax_gen_pspp (&s, ".");
-
- }
- break;
-
- default:
- g_assert_not_reached ();
+ size_t var_cnt;
+ size_t i;
+ syntax_gen_pspp (&s,
+ "GET DATA"
+ "\n /TYPE=TXT"
+ "\n /FILE=%sq\n",
+ ia->file.file_name);
+ if (ia->file.encoding && strcmp (ia->file.encoding, "Auto"))
+ syntax_gen_pspp (&s, " /ENCODING=%sq\n", ia->file.encoding);
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+ ia->intro.n_cases_button)))
+ ds_put_format (&s, " /IMPORTCASES=FIRST %d\n",
+ gtk_spin_button_get_value_as_int (
+ GTK_SPIN_BUTTON (ia->intro.n_cases_spin)));
+ else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+ ia->intro.percent_button)))
+ ds_put_format (&s, " /IMPORTCASES=PERCENT %d\n",
+ gtk_spin_button_get_value_as_int (
+ GTK_SPIN_BUTTON (ia->intro.percent_spin)));
+ else
+ ds_put_cstr (&s, " /IMPORTCASES=ALL\n");
+ ds_put_cstr (&s,
+ " /ARRANGEMENT=DELIMITED\n"
+ " /DELCASE=LINE\n");
+ if (ia->first_line.skip_lines > 0)
+ ds_put_format (&s, " /FIRSTCASE=%d\n", ia->first_line.skip_lines + 1);
+ ds_put_cstr (&s, " /DELIMITERS=\"");
+ if (ds_find_byte (&ia->separators.separators, '\t') != SIZE_MAX)
+ ds_put_cstr (&s, "\\t");
+ if (ds_find_byte (&ia->separators.separators, '\\') != SIZE_MAX)
+ ds_put_cstr (&s, "\\\\");
+ for (i = 0; i < ds_length (&ia->separators.separators); i++)
+ {
+ char c = ds_at (&ia->separators.separators, i);
+ if (c == '"')
+ ds_put_cstr (&s, "\"\"");
+ else if (c != '\t' && c != '\\')
+ ds_put_byte (&s, c);
+ }
+ ds_put_cstr (&s, "\"\n");
+ if (!ds_is_empty (&ia->separators.quotes))
+ syntax_gen_pspp (&s, " /QUALIFIER=%sq\n", ds_cstr (&ia->separators.quotes));
+ if (!ds_is_empty (&ia->separators.quotes) && ia->separators.escape)
+ ds_put_cstr (&s, " /ESCAPE\n");
+ ds_put_cstr (&s, " /VARIABLES=\n");
+
+ var_cnt = dict_get_var_cnt (ia->formats.dict);
+ for (i = 0; i < var_cnt; i++)
+ {
+ struct variable *var = dict_get_var (ia->formats.dict, i);
+ char format_string[FMT_STRING_LEN_MAX + 1];
+ fmt_to_string (var_get_print_format (var), format_string);
+ ds_put_format (&s, " %s %s%s\n",
+ var_get_name (var), format_string,
+ i == var_cnt - 1 ? "." : "");
+ }
+
+ apply_dict (ia->formats.dict, &s);
+ }
+ else
+ {
+ const struct sheet_spec_page *ssp = &ia->sheet_spec;
+
+ printf ("%s:%d %p %d\n", __FILE__, __LINE__, ssp->spreadsheet, ssp->spreadsheet->type);
+
+ syntax_gen_pspp (&s,
+ "GET DATA"
+ "\n /TYPE=%ss"
+ "\n /FILE=%sq"
+ "\n /SHEET=index %d"
+ "\n /READNAMES=%ss",
+ (ssp->spreadsheet->type == SPREADSHEET_GNUMERIC) ? "GNM" : "ODS",
+ ia->file.file_name,
+ ssp->opts.sheet_index,
+ ssp->sri.read_names ? "ON" : "OFF");
+
+
+ if ( ssp->opts.cell_range)
+ {
+ syntax_gen_pspp (&s,
+ "\n /CELLRANGE=RANGE %sq",
+ ssp->opts.cell_range);
+ }
+ else
+ {
+ syntax_gen_pspp (&s,
+ "\n /CELLRANGE=FULL");
+ }
+
+
+ syntax_gen_pspp (&s, ".");
}
-
return ds_cstr (&s);
}
#include "libpspp/str.h"
-enum file_type
- {
- FTYPE_TEXT,
- FTYPE_GNUMERIC,
- FTYPE_ODS
- };
-
/* The file to be imported. */
struct file
{
char *file_name; /* File name. */
- enum file_type type;
-
/* Relevant only for text files */
gchar *encoding; /* Encoding. */