Basic working spreadsheet import dialog (sort of)
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 5 Jan 2013 19:35:23 +0000 (20:35 +0100)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 16 Feb 2013 14:02:40 +0000 (15:02 +0100)
src/ui/gui/automake.mk
src/ui/gui/page-file.c
src/ui/gui/page-formats.c
src/ui/gui/page-sheet-spec.c [new file with mode: 0644]
src/ui/gui/text-data-import-dialog.c
src/ui/gui/text-data-import-dialog.h
src/ui/gui/text-data-import.ui

index 955d8391c64f7c01f6c221c91b06f75b6d20706d..eba09d003662e4f3bdc85de132da4fb69e757923 100644 (file)
@@ -310,6 +310,7 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/page-first-line.c \
        src/ui/gui/page-formats.c \
        src/ui/gui/page-separators.c \
+       src/ui/gui/page-sheet-spec.c \
        src/ui/gui/text-data-import-dialog.c \
        src/ui/gui/text-data-import-dialog.h \
        src/ui/gui/transpose-dialog.c \
index ff135f677f7afcdfa44f121755a5bb3dbead140c..e4cb781559b7cdc8a39307a5e4c8eb11102ba85b 100644 (file)
@@ -29,6 +29,8 @@
 #include "data/data-in.h"
 #include "data/data-out.h"
 #include "data/format-guesser.h"
+#include "data/gnumeric-reader.h"
+#include "data/spreadsheet-reader.h"
 #include "data/value-labels.h"
 #include "language/data-io/data-parser.h"
 #include "language/lexer/lexer.h"
@@ -74,75 +76,92 @@ bool
 init_file (struct import_assistant *ia, GtkWindow *parent_window)
 {
   struct file *file = &ia->file;
-  enum { MAX_PREVIEW_LINES = 1000 }; /* Max number of lines to read. */
-  enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
-  struct line_reader *reader;
-  struct string input;
-
   file->file_name = choose_file (parent_window, &file->encoding);
   if (file->file_name == NULL)
     return false;
 
-  reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
-  if (reader == NULL)
-    {
-      msg (ME, _("Could not open `%s': %s"),
-           file->file_name, strerror (errno));
-      return false;
-    }
-
-  ds_init_empty (&input);
-  file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
-  for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
-    {
-      ds_clear (&input);
-      if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
-          || ds_length (&input) > MAX_LINE_LEN)
-        {
-          if (line_reader_eof (reader))
-            break;
-          else if (line_reader_error (reader))
-            msg (ME, _("Error reading `%s': %s"),
-                 file->file_name, strerror (line_reader_error (reader)));
-          else
-            msg (ME, _("Failed to read `%s', because it contains a line "
-                       "over %d bytes long and therefore appears not to be "
-                       "a text file."),
-                 file->file_name, MAX_LINE_LEN);
-          line_reader_close (reader);
-          destroy_file (ia);
-          ds_destroy (&input);
-          return false;
-        }
-
-      ds_init_cstr (&file->lines[file->line_cnt],
-                    recode_string ("UTF-8", line_reader_get_encoding (reader),
-                                   ds_cstr (&input), ds_length (&input)));
-    }
-  ds_destroy (&input);
-
-  if (file->line_cnt == 0)
-    {
-      msg (ME, _("`%s' is empty."), file->file_name);
-      line_reader_close (reader);
-      destroy_file (ia);
-      return false;
-    }
-
-  /* Estimate the number of lines in the file. */
-  if (file->line_cnt < MAX_PREVIEW_LINES)
-    file->total_lines = file->line_cnt;
-  else
-    {
-      struct stat s;
-      off_t position = line_reader_tell (reader);
-      if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
-        file->total_lines = (double) file->line_cnt / position * s.st_size;
-      else
-        file->total_lines = 0;
-    }
-
-  line_reader_close (reader);
+  struct dictionary *dict = NULL;
+  struct spreadsheet_read_info sri;
+
+  sri.sheet_name = NULL;
+  sri.file_name = file->file_name;
+  sri.cell_range = NULL;
+  sri.sheet_index = 1;
+  sri.read_names = true;
+  sri.asw = 0;
+
+  struct casereader *creader = gnumeric_open_reader (&sri, &dict);
+  printf ("%s:%d %s\n", __FILE__, __LINE__, sri.file_name);
+  ia->file.type = FTYPE_SPREADSHEET;
+
+  if (creader == NULL)
+  {
+    enum { MAX_PREVIEW_LINES = 1000 }; /* Max number of lines to read. */
+    enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
+
+    struct string input;
+    struct line_reader *reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
+    if (reader == NULL)
+      {
+       msg (ME, _("Could not open `%s': %s"),
+            file->file_name, strerror (errno));
+       return false;
+      }
+
+    ds_init_empty (&input);
+    file->lines = xnmalloc (MAX_PREVIEW_LINES, sizeof *file->lines);
+    for (; file->line_cnt < MAX_PREVIEW_LINES; file->line_cnt++)
+      {
+       ds_clear (&input);
+       if (!line_reader_read (reader, &input, MAX_LINE_LEN + 1)
+           || ds_length (&input) > MAX_LINE_LEN)
+         {
+           if (line_reader_eof (reader))
+             break;
+           else if (line_reader_error (reader))
+             msg (ME, _("Error reading `%s': %s"),
+                  file->file_name, strerror (line_reader_error (reader)));
+           else
+             msg (ME, _("Failed to read `%s', because it contains a line "
+                        "over %d bytes long and therefore appears not to be "
+                        "a text file."),
+                  file->file_name, MAX_LINE_LEN);
+           line_reader_close (reader);
+           destroy_file (ia);
+           ds_destroy (&input);
+           return false;
+         }
+
+       ds_init_cstr (&file->lines[file->line_cnt],
+                     recode_string ("UTF-8", line_reader_get_encoding (reader),
+                                    ds_cstr (&input), ds_length (&input)));
+      }
+    ds_destroy (&input);
+
+    if (file->line_cnt == 0)
+      {
+       msg (ME, _("`%s' is empty."), file->file_name);
+       line_reader_close (reader);
+       destroy_file (ia);
+       return false;
+      }
+
+    /* Estimate the number of lines in the file. */
+    if (file->line_cnt < MAX_PREVIEW_LINES)
+      file->total_lines = file->line_cnt;
+    else
+      {
+       struct stat s;
+       off_t position = line_reader_tell (reader);
+       if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
+         file->total_lines = (double) file->line_cnt / position * s.st_size;
+       else
+         file->total_lines = 0;
+      }
+
+    line_reader_close (reader);
+    ia->file.type = FTYPE_TEXT;
+  }
 
   return true;
 }
index ee9b540bdc703d1c07bcb116ca3bebec6b0e7127..c79551fb04415071ffabd26455ea183d3f0c17c9 100644 (file)
@@ -104,7 +104,7 @@ prepare_formats_page (struct import_assistant *ia)
   GtkBin *vars_scroller;
   GtkWidget *old_var_sheet;
   PsppireVarSheet *var_sheet;
-  struct separators_page *s = &ia->separators;
+  struct separators_page *seps = &ia->separators;
   struct formats_page *p = &ia->formats;
   struct fmt_guesser *fg;
   unsigned long int number = 0;
@@ -114,7 +114,8 @@ prepare_formats_page (struct import_assistant *ia)
 
   dict = dict_create (get_default_encoding ());
   fg = fmt_guesser_create ();
-  for (column_idx = 0; column_idx < s->column_cnt; column_idx++)
+  printf ("%s:%d Column count %d\n", __FILE__, __LINE__, seps->column_cnt);
+  for (column_idx = 0; column_idx < seps->column_cnt; column_idx++)
     {
       struct variable *modified_var;
 
@@ -122,7 +123,7 @@ prepare_formats_page (struct import_assistant *ia)
                       ? p->modified_vars[column_idx] : NULL);
       if (modified_var == NULL)
         {
-          struct column *column = &s->columns[column_idx];
+          struct column *column = &seps->columns[column_idx];
           struct variable *var;
           struct fmt_spec format;
           char *name;
diff --git a/src/ui/gui/page-sheet-spec.c b/src/ui/gui/page-sheet-spec.c
new file mode 100644 (file)
index 0000000..4905a78
--- /dev/null
@@ -0,0 +1,85 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2013  Free Software Foundation
+
+   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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "ui/gui/text-data-import-dialog.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <gtk-contrib/psppire-sheet.h>
+#include <gtk/gtk.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "data/data-in.h"
+#include "data/data-out.h"
+#include "data/format-guesser.h"
+#include "data/value-labels.h"
+#include "language/data-io/data-parser.h"
+#include "language/lexer/lexer.h"
+#include "libpspp/assertion.h"
+#include "libpspp/i18n.h"
+#include "libpspp/line-reader.h"
+#include "libpspp/message.h"
+#include "ui/gui/checkbox-treeview.h"
+#include "ui/gui/dialog-common.h"
+#include "ui/gui/executor.h"
+#include "ui/gui/helper.h"
+#include "ui/gui/builder-wrapper.h"
+#include "ui/gui/psppire-data-window.h"
+#include "ui/gui/psppire-dialog.h"
+#include "ui/gui/psppire-encoding-selector.h"
+#include "ui/gui/psppire-empty-list-store.h"
+#include "ui/gui/psppire-var-sheet.h"
+#include "ui/gui/psppire-var-store.h"
+#include "ui/gui/psppire-scanf.h"
+#include "ui/syntax-gen.h"
+
+#include "gl/error.h"
+#include "gl/intprops.h"
+#include "gl/xalloc.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
+
+struct import_assistant;
+
+
+\f
+/* The "sheet-spec" page of the assistant. */
+
+
+/* Initializes IA's sheet_spec substructure. */
+void
+init_sheet_spec_page (struct import_assistant *ia)
+{
+  GtkBuilder *builder = ia->asst.builder;
+  struct sheet_spec_page *p = &ia->sheet_spec;
+
+  p->page = add_page_to_assistant (ia, get_widget_assert (builder, "Sheet"),
+                                   GTK_ASSISTANT_PAGE_INTRO);
+
+}
+
+/* Resets IA's sheet_spec page to its initial state. */
+void
+reset_sheet_spec_page (struct import_assistant *ia)
+{
+}
+
index bb7ce56e489666874262e745b87b5f4d4458185f..00e82a7035fac41d9e47f6cae37fcb9dbd10e14f 100644 (file)
@@ -79,10 +79,20 @@ text_data_import_assistant (PsppireDataWindow *dw)
       return;
     }
 
+  printf ("%s:%d %s\n", __FILE__, __LINE__, ia->file.file_name);
+
   init_assistant (ia, parent_window);
-  init_intro_page (ia);
-  init_first_line_page (ia);
-  init_separators_page (ia);
+  if ( ia->file.type == FTYPE_TEXT)
+    {
+      init_intro_page (ia);
+      init_first_line_page (ia);
+      init_separators_page (ia);
+    }
+  else
+    {
+      init_sheet_spec_page (ia);
+    }
+
   init_formats_page (ia);
 
   gtk_widget_show_all (GTK_WIDGET (ia->asst.assistant));
@@ -103,8 +113,12 @@ text_data_import_assistant (PsppireDataWindow *dw)
       break;
     }
 
-  destroy_formats_page (ia);
-  destroy_separators_page (ia);
+  if ( ia->file.type == FTYPE_TEXT)
+    {
+      destroy_formats_page (ia);
+      destroy_separators_page (ia);
+    }
+
   destroy_assistant (ia);
   destroy_file (ia);
   free (ia);
@@ -199,65 +213,77 @@ static char *
 generate_syntax (const struct import_assistant *ia)
 {
   struct string s = DS_EMPTY_INITIALIZER;
-  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)));
+  if (ia->file.type == 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);
+  }
   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 ? "." : "");
+      syntax_gen_pspp (&s,
+                      "GET DATA\n"
+                      "  /TYPE=GNM\n"
+                      "  /FILE=%sq\n",
+                      ia->file.file_name);
     }
 
-  apply_dict (ia->formats.dict, &s);
 
   return ds_cstr (&s);
 }
index 0966365d42dbbbb5ef2b7d7516f9220b74c9d81a..b23130d7f425174be4185108b5d6322ce520f9fb 100644 (file)
 
 #include "libpspp/str.h"
 
+enum file_type
+  {
+    FTYPE_TEXT,
+    FTYPE_SPREADSHEET
+  };
+
 /* The file to be imported. */
 struct file
   {
     char *file_name;        /* File name. */
+
+    enum file_type type;
+
+    /* Relevant only for text files */
+
     gchar *encoding;        /* Encoding. */
     unsigned long int total_lines; /* Number of lines in file. */
     bool total_is_exact;    /* Is total_lines exact (or an estimate)? */
@@ -50,6 +61,14 @@ struct assistant
     GtkCellRenderer *fixed_renderer;
   };
 
+
+/* The sheet_spec page of the assistant (only relevant for spreadsheet imports). */
+struct sheet_spec_page
+  {
+    GtkWidget *page;
+  };
+
+
 /* The introduction page of the assistant. */
 struct intro_page
   {
@@ -113,6 +132,7 @@ struct import_assistant
     struct file file;
     struct assistant asst;
     struct intro_page intro;
+    struct sheet_spec_page sheet_spec;
     struct first_line_page first_line;
     struct separators_page separators;
     struct formats_page formats;
index d8a33d118a39beec98546e09147e42308a6b5ae6..adc73e860d225ba7cea084dac6572f803337367c 100644 (file)
@@ -666,4 +666,124 @@ The selected file contains N lines of text.  Only the first M of these will be s
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkWindow" id="Sheet">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">Importing Textual Data</property>
+    <child>
+      <object class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="intro-label1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="label" translatable="yes">Enter below the sheet number and the cell range which you wish to import.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkAlignment" id="alignment4">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="xscale">0</property>
+            <child>
+              <object class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment7">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkTable" id="table3">
+                        <property name="visible">True</property>
+                        <property name="n_rows">2</property>
+                        <property name="n_columns">2</property>
+                        <child>
+                          <object class="GtkEntry" id="cell-range-entry">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">&#x25CF;</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="sheet-entry">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">&#x25CF;</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="cell-range-label">
+                            <property name="visible">True</property>
+                            <property name="xalign">1</property>
+                            <property name="label" translatable="yes">_Cells: </property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">cell-range-entry</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="sheet-label">
+                            <property name="visible">True</property>
+                            <property name="xalign">1</property>
+                            <property name="label" translatable="yes">_Sheet Index: </property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">sheet-entry</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Cells to Import&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
 </interface>