diff --git configure.ac configure.ac
index 247b1d9..1d67936 100644
--- configure.ac
+++ configure.ac
@@ -1130,6 +1130,7 @@ then
     EFENCE_LIBS="")
   AC_SUBST(EFENCE_LIBS)

+
   ### ----------------------------------------------------------------------
   ## For now, we just presume you're using the GNOME version.  The other
   ## UI's haven't been carried over during the automake transition.  At
@@ -1495,6 +1496,11 @@ AC_CONFIG_FILES(
   src/business/business-gnome/ui/Makefile
   src/business/business-ledger/Makefile

+          src/plugins/Makefile
+          src/plugins/bi_import/Makefile
+          src/plugins/bi_import/glade/Makefile
+          src/plugins/bi_import/ui/Makefile
+
   dnl # non-makefiles
   dnl # Please read doc/build-system before adding *anything* here

diff --git src/Makefile.am src/Makefile.am
index 1505a46..682dc31 100644
--- src/Makefile.am
+++ src/Makefile.am
@@ -9,6 +9,7 @@ NONGUI_SUBDIRS = \
   engine \
   backend \
   scm \
+  plugins \
   quotes

 GUI_SUBDIRS_1 = \
diff --git src/plugins/Makefile.am src/plugins/Makefile.am
new file mode 100644
index 0000000..b599da2
--- /dev/null
+++ src/plugins/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS=bi_import
diff --git src/plugins/bi_import/Makefile.am src/plugins/bi_import/Makefile.am
new file mode 100644
index 0000000..ecee766
--- /dev/null
+++ src/plugins/bi_import/Makefile.am
@@ -0,0 +1,43 @@
+SUBDIRS = ui glade .
+
+pkglib_LTLIBRARIES = libgncmod-bi_import.la
+
+libgncmod_bi_import_la_SOURCES = \
+  gnc-plugin-bi_import.c \
+  gncmod-bi_import.c \
+  gui.c \
+  helpers.c \
+  bi_import.c
+
+noinst_HEADERS = \
+  gnc-plugin-bi_import.h \
+  gui.h \
+  helpers.h \
+  bi_import.h
+
+libgncmod_bi_import_la_LDFLAGS = -avoid-version
+
+libgncmod_bi_import_la_LIBADD = \
+  ${top_builddir}/src/gnc-module/libgnc-module.la \
+  ${GNOME_LIBS} \
+  ${GLADE_LIBS} \
+  ${QOF_LIBS} \
+  ${GLIB_LIBS}
+
+AM_CFLAGS = \
+  -I${top_srcdir}/src \
+  -I${top_srcdir}/src/gnome \
+  -I${top_srcdir}/src/register/ledger-core \
+  -I${top_srcdir}/src/register/register-gnome \
+  -I${top_srcdir}/src/register/register-core \
+  -I${top_srcdir}/src/gnome-utils \
+  -I${top_srcdir}/src/app-utils \
+  -I${top_srcdir}/src/engine \
+  -I${top_srcdir}/src/core-utils \
+  -I${top_srcdir}/src/gnc-module \
+  ${GNOME_CFLAGS} \
+  ${GLADE_CFLAGS} \
+  ${QOF_CFLAGS} \
+  ${GLIB_CFLAGS}
+
+INCLUDES = -DG_LOG_DOMAIN=\"gnc.plugin.bi_import\"
diff --git src/plugins/bi_import/bi_import.c src/plugins/bi_import/bi_import.c
new file mode 100644
index 0000000..12be243
--- /dev/null
+++ src/plugins/bi_import/bi_import.c
@@ -0,0 +1,575 @@
+/*
+ * bi_import.c --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+/**
+ * @internal
+ * @file gui.c
+ * @brief core import functions for invoice import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held@gmx.de>
+ * @author Mike Evans <mikee@saxicola.co.uk>
+ * @todo Make this work for bis.  Could be just add a column for type and test.
+ * @todo Create an option to import a pre-formed regex when it is present
+ * to enable the use of custom output csv formats.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <regex.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "gnc-ui.h"
+#include "gnc-ui-util.h"
+#include "gnc-gui-query.h"
+#include "gncAddress.h"
+#include "gncVendorP.h"
+#include "gncVendor.h"
+#include "gncEntry.h"
+//#include "Account.h"
+#include "gnc-exp-parser.h"
+
+// query
+#include "QueryCore.h"
+#include "QueryNew.h"
+#include "GNCId.h"
+#include "gncIDSearch.h"
+#include "bi_import.h"
+#include "helpers.h"
+
+
+
+
+
+//#ifdef HAVE_GLIB_2_14
+// glib >= 2.14.0
+// perl regular expressions are available
+
+// this helper macro takes a regexp match and fills the model
+#define FILL_IN_HELPER(match_name,column) \
+            temp = g_match_info_fetch_named (match_info, match_name); \
+            if (temp) \
+            { \
+				g_strstrip( temp ); \
+                gtk_list_store_set (store, &iter, column, temp, -1); \
+                g_free (temp); \
+            }
+bi_import_result
+gnc_bi_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows, bi_import_stats *stats)
+{
+    // some statistics
+	bi_import_stats stats_fallback;
+    FILE *f;
+
+    // regexp
+    char *line;
+    gchar *line_utf8, *temp;
+    GMatchInfo *match_info;
+    GError *err;
+    GRegex *regexpat;
+
+	// model
+	GtkTreeIter iter;
+
+    f = g_fopen( filename, "rt" );
+    if (!f)
+    {
+        //gnc_error_dialog( 0, _("File %s cannot be opened."), filename );
+        return  RESULT_OPEN_FAILED;
+    }
+
+	// set up statistics
+	if (!stats)
+		stats = &stats_fallback;
+
+    // compile the regular expression and check for errors
+    err = NULL;
+    regexpat = g_regex_new (parser_regexp, G_REGEX_EXTENDED | G_REGEX_OPTIMIZE, 0, &err);
+    if (err != NULL)
+    {
+        GtkWidget *dialog;
+        gchar *errmsg;
+
+        errmsg = g_strdup_printf (_("Error in regular expression '%s':\n%s"),
+                    parser_regexp, err->message);
+        g_error_free (err); err = NULL;
+
+        dialog = gtk_message_dialog_new (NULL,
+                       GTK_DIALOG_MODAL,
+                       GTK_MESSAGE_ERROR,
+                       GTK_BUTTONS_OK,
+                       "%s", errmsg);
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy(dialog);
+        g_free (errmsg); errmsg = 0;
+
+        fclose (f);
+        return  RESULT_ERROR_IN_REGEXP;
+    }
+
+    // start the import
+    stats->n_imported = 0;
+    stats->n_ignored = 0;
+	stats->ignored_lines = g_string_new (NULL);
+    #define buffer_size 1000
+    line = g_malloc0 (buffer_size);
+    while (!feof (f) && ((max_rows==0) || (stats->n_imported+stats->n_ignored<max_rows)))
+    {
+        int l;
+        // read one line
+        if (!fgets (line, buffer_size, f))
+            break; // eof
+        // now strip the '\n' from the end of the line
+        l = strlen (line);
+        if ((l > 0) && (line[l-1] == '\n'))
+            line[l-1] = 0;
+
+        // convert line from locale into utf8
+        line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL);
+
+        // parse the line
+        match_info = NULL; // it seems, that in contrast to documentation, match_info is not alsways set -> g_match_info_free will segfault
+        if (g_regex_match (regexpat, line_utf8, 0, &match_info))
+        {
+            // match found
+            stats->n_imported++;
+
+            // fill in the values
+			gtk_list_store_append (store, &iter);
+			FILL_IN_HELPER (_("id"), ID);
+			FILL_IN_HELPER ("date_opened", DATE_OPENED);
+			FILL_IN_HELPER ("owner_id", OWNER_ID);
+			FILL_IN_HELPER ("biing_id", BILLING_ID);
+			FILL_IN_HELPER ("notes", NOTES);
+
+			FILL_IN_HELPER ("date", DATE);
+			FILL_IN_HELPER ("desc", DESC);
+			FILL_IN_HELPER ("action", ACTION);
+			FILL_IN_HELPER ("account", ACCOUNT);
+			FILL_IN_HELPER ("quantity", QUANTITY);
+			FILL_IN_HELPER ("price", PRICE);
+			FILL_IN_HELPER ("disc_type", DISC_TYPE);
+			FILL_IN_HELPER ("disc_how", DISC_HOW);
+			FILL_IN_HELPER ("discount", DISCOUNT);
+			FILL_IN_HELPER ("taxable", TAXABLE);
+			FILL_IN_HELPER ("taxincluded", TAXINCLUDED);
+			FILL_IN_HELPER ("tax_table", TAX_TABLE);
+
+			FILL_IN_HELPER ("date_posted", DATE_POSTED);
+			FILL_IN_HELPER ("due_date", DUE_DATE);
+			FILL_IN_HELPER ("account_posted", ACCOUNT_POSTED);
+			FILL_IN_HELPER ("memo_posted", MEMO_POSTED);
+			FILL_IN_HELPER ("accu_splits", ACCU_SPLITS);
+		} else {
+            // ignore line
+            stats->n_ignored++;
+			g_string_append (stats->ignored_lines, line_utf8);
+			g_string_append_c (stats->ignored_lines, '\n');
+        }
+
+        g_match_info_free (match_info); match_info = 0;
+        g_free (line_utf8); line_utf8 = 0;
+    }
+    g_free (line); line = 0;
+
+    g_regex_unref (regexpat); regexpat = 0;
+    fclose (f);
+
+	if (stats == &stats_fallback)
+		// stats are not requested -> free the string
+		g_string_free (stats->ignored_lines, TRUE);
+
+	return  RESULT_OK;
+}
+
+
+//! \brief try to fix some common errors in the csv representation of invoices
+//! * corrects the date format
+//! * corrects ambigous values in multi line invoices
+//! * ensures customer exists
+//! * if quantity is unset, set to 1
+//! * if price is unset, delete row
+void
+gnc_bi_import_fix_bis (GtkListStore *store, guint *fixed, guint *deleted, GString *info)
+{
+	GtkTreeIter iter;
+	gboolean valid, row_deleted, row_fixed;
+	gchar *id, *date_opened, *date_posted, *owner_id, *date, *quantity, *price;
+	GString *prev_id, *prev_date_opened, *prev_date_posted, *prev_owner_id, *prev_date; // needed to fix multi line invoices
+	guint dummy;
+
+	// allow the call to this function with only GtkListeStore* specified
+	if (!fixed)
+		fixed = &dummy;
+	if (!deleted)
+		deleted = &dummy;
+
+	*fixed = 0;
+	*deleted = 0;
+
+	// init strings
+	prev_id = g_string_new("");
+	prev_date_opened = g_string_new("");
+	prev_date_posted = g_string_new("");
+	prev_owner_id = g_string_new("");
+	prev_date = g_string_new("");
+
+	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
+	while (valid) {
+		row_deleted = FALSE;
+		row_fixed = FALSE;
+
+		// Walk through the list, reading each row
+		gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
+		                     ID, &id,
+		                     DATE_OPENED, &date_opened,
+		                     DATE_POSTED, &date_posted,
+		                     OWNER_ID, &owner_id,
+		                     DATE, &date,
+		                     QUANTITY, &quantity,
+		                     PRICE, &price,
+		                    -1);
+
+		if (strlen(price) == 0) {
+			// invalid row (no price given)
+			// no fix possible -> delete row
+			gtk_list_store_remove (store, &iter);
+			row_deleted = TRUE;
+			g_string_append_printf( info, _("ROW DELETED PRICE_NOT_SET: id=%s\n"), id );
+		} else {
+			if (strlen(id) == 0) {
+				// no invoice id specified
+				if (prev_id->len == 0) {
+					// cannot fix -> delete row
+					gtk_list_store_remove (store, &iter);
+					row_deleted = TRUE;
+					g_string_append_printf( info, _("ROW DELETED ID_NOT_SET\n") );
+				} else {
+					// this is a fixable multi line invoice
+					gtk_list_store_set (store, &iter,  ID, prev_id->str, -1);
+					row_fixed = TRUE;
+				}
+			} else {
+				// remember invoice id (to be able to fix multi line invoices)
+				g_string_assign( prev_id, id );
+				// new invoice => reset all other fixable entries
+				g_string_assign( prev_date_opened, "" );
+				g_string_assign( prev_date_posted, "" );
+				g_string_assign( prev_owner_id, "" );
+				g_string_assign( prev_date, "" );
+			}
+		}
+
+		if (!row_deleted) {
+			// the row is valid (price and id are valid)
+
+			if (strlen(date_opened) == 0) {
+				if (prev_date_opened->len == 0) {
+					// fix this by using the current date (why is this so complicated?)
+					gchar temp[20]; GDate *date; time_t secs; struct tm now;
+					time (&secs);
+					localtime_r (&secs, &now);
+					date = g_date_new_dmy( now.tm_mday, now.tm_mon+1, now.tm_year+1900 );
+					g_date_strftime( temp, 20, "%x", date ); // create a locale specific date string
+					g_string_assign( prev_date_opened, temp );
+					g_date_free( date );
+				}
+				// fix this by using the previous date_opened value (multi line invoice)
+				gtk_list_store_set (store, &iter,  DATE_OPENED, prev_date_opened->str, -1);
+				row_fixed = TRUE;
+			} else {
+				// remember date_opened (to be able to fix multi line invoices)
+				g_string_assign( prev_date_opened, date_opened );
+			}
+
+			// date_opened is valid
+
+			if (strlen(date_posted) == 0) {
+				if (prev_date_posted->len == 0) {
+					// this invoice will have to get posted manually
+				} else {
+					// multi line invoice => fix it
+					gtk_list_store_set (store, &iter,  DATE_POSTED, prev_date_posted->str, -1);
+					row_fixed = TRUE;
+				}
+			} else {
+				// remember date_opened (to be able to fix multi line invoices)
+				g_string_assign( prev_date_posted, date_posted );
+			}
+
+			// date_posted is valid
+
+			if (strlen(quantity) == 0) {
+				// quantity is unset => set to 1
+				gtk_list_store_set (store, &iter,  QUANTITY, "1", -1);
+				row_fixed = TRUE;
+			}
+
+			// quantity is valid
+
+			if (strlen(owner_id) == 0) {
+				if (prev_owner_id->len == 0) {
+					// no customer given and not fixable => delete row
+					gtk_list_store_remove (store, &iter);
+					row_deleted = TRUE;
+					g_string_append_printf( info, _("ROW DELETED VENDOR_NOT_SET: id=%s\n"), id );
+				} else {
+					gtk_list_store_set (store, &iter,  owner_id, prev_owner_id->str, -1);
+					row_fixed = TRUE;
+				}
+			} else {
+				// remember owner_id
+				g_string_assign( prev_owner_id, owner_id );
+			}
+			// now check, if customer exists
+			if (!gnc_search_vendor_on_id ( gnc_get_current_book(), prev_owner_id->str)) {
+				// customer not found => delete row
+				gtk_list_store_remove (store, &iter);
+				row_deleted = TRUE;
+				g_string_append_printf( info, _("ROW DELETED VENDOR_DOES_NOT_EXIST: id=%s\n"), id );
+			}
+
+			// owner_id is valid
+		}
+
+		g_free (id); g_free (date_opened); g_free (date_posted); g_free (owner_id); g_free (date); g_free (quantity); g_free (price);
+		if (row_deleted) {
+			(*deleted)++;
+			// reset all remembered values
+			g_string_assign( prev_id, "" );
+			g_string_assign( prev_date_opened, "" );
+			g_string_assign( prev_date_posted, "" );
+			g_string_assign( prev_owner_id, "" );
+			g_string_assign( prev_date, "" );
+		}
+		else if (row_fixed)
+			(*fixed)++;
+		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
+    }
+
+	// deallocate strings
+	g_string_free(prev_id,TRUE); g_string_free(prev_date_opened,TRUE); g_string_free(prev_date_posted,TRUE);
+	g_string_free(prev_owner_id,TRUE); g_string_free(prev_date,TRUE);
+
+	if (info && (info->len > 0))
+		g_string_prepend( info, _("These rows were deleted:\n\n") );
+}
+
+
+/***********************************************************************
+ * @todo Maybe invoice checking should be done in gnc_bi_import_fix_bis (...)
+ * rather than in here?  But that is more concerned with ensuring the csv is consistent.
+ * @param GtkListStore *store
+ * @param guint *n_invoices_created
+ * @param guint *n_invoices_updated
+ * @return void
+ ***********************************************************************/
+void
+gnc_bi_import_create_bis (GtkListStore *store, QofBook *book, guint *n_invoices_created, guint *n_invoices_updated,	gchar *type)
+{
+	gboolean valid;
+	GtkTreeIter iter;
+	gchar *id,*date_opened,*owner_id,*biing_id,*notes;
+	gchar *date,*desc,*action,*account,*quantity,*price,*disc_type,*disc_how,*discount,*taxable,*taxincluded,*tax_table;
+	gchar *date_posted,*due_date,*account_posted,*memo_posted,*accumulatesplits;
+	guint dummy;
+	GncInvoice *invoice;
+	GncOrder * order;
+	GncEntry *entry;
+	gint day,month,year;
+	gnc_numeric n;
+	GncOwner *owner;
+	Account *acc;
+	gint update;
+	GtkWidget *dialog;
+//	time_t now;
+	Timespec today;
+
+
+	// these arguments are needed
+	g_return_if_fail (store && book);
+
+	// allow to call this function without statistics
+	if (!n_invoices_created)
+		n_invoices_created = &dummy;
+	if (!n_invoices_updated)
+		n_invoices_updated = &dummy;
+	*n_invoices_created = 0;
+	*n_invoices_updated = 0;
+
+	invoice = NULL;
+	order = NULL;
+	update = 1;
+
+	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
+	while (valid) {
+		// Walk through the list, reading each row
+		gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
+		                     ID, &id,
+		                     DATE_OPENED, &date_opened,
+		                     DATE_POSTED, &date_posted,       // if autoposting requested
+		                     DUE_DATE, &due_date,             // if autoposting requested
+		                     ACCOUNT_POSTED, &account_posted, // if autoposting requested
+		                     MEMO_POSTED, &memo_posted,       // if autoposting requested
+		                     ACCU_SPLITS, &accumulatesplits,  // if autoposting requested
+		                     OWNER_ID, &owner_id,
+		                     BILLING_ID, &biing_id,
+		                     NOTES, &notes,
+
+		                     DATE, &date,
+		                     DESC, &desc,
+		                     ACTION, &action,
+		                     ACCOUNT, &account,
+		                     QUANTITY, &quantity,
+		                     PRICE, &price,
+		                     DISC_TYPE, &disc_type,
+		                     DISC_HOW, &disc_how,
+		                     DISCOUNT, &discount,
+		                     TAXABLE, &taxable,
+		                     TAXINCLUDED, &taxincluded,
+		                     TAX_TABLE, &tax_table,
+		                    -1);
+
+
+			if (g_ascii_strcasecmp(type,"BILL")) invoice = gnc_search_bill_on_id (book, id);
+			else if (g_ascii_strcasecmp(type,"INVOICE")) invoice = gnc_search_invoice_on_id (book, id);
+
+			if (!invoice )
+			{
+			// new invoice
+			invoice = gncInvoiceCreate( book );
+			gncInvoiceSetID( invoice, id );
+			owner = gncOwnerCreate();
+			if (g_ascii_strcasecmp(type,"BILL") == 0)gncOwnerInitVendor(owner, gnc_search_vendor_on_id(book,owner_id) );
+			else if (g_ascii_strcasecmp(type,"INVOICE") == 0)	gncOwnerInitCustomer(owner, gnc_search_customer_on_id(book,owner_id) );
+			gncInvoiceSetOwner( invoice, owner );
+			gncInvoiceSetCurrency( invoice, gncOwnerGetCurrency(owner)); // Set the invoice currency based on the owner
+			qof_scan_date( date_opened, &day, &month, &year );
+			gncInvoiceSetDateOpened( invoice, gnc_dmy2timespec(day,month,year) );
+			gncInvoiceSetBillingID( invoice, biing_id );
+			gncInvoiceSetNotes( invoice, notes );
+			gncInvoiceSetActive( invoice, TRUE );
+			//if (g_ascii_strcasecmp(type,"INVOICE"))gncInvoiceSetBillTo( invoice, billto );
+			(*n_invoices_created)++;
+			update = -8;
+		}
+// I'm not happy with this next part.  I want to warn the user that an existing bilvoice exists, but not every time.
+// But an import can contain many lines referring to the same invoice, which is presumably delberate but we don't want to
+// append to an existing invoice.  Although the removal of line items is trivial.  Posted invoices are NEVER updated.
+		else // if invoice exists
+		{
+		if (gncInvoiceIsPosted(invoice )) // Is it already posted?
+			{
+				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
+				continue; // If already posted then never import
+			}
+			if(update != -8)// Pop up a dialog to ask if updates are the expected action
+			{
+				dialog = gtk_message_dialog_new (NULL,
+                       GTK_DIALOG_MODAL,
+                       GTK_MESSAGE_ERROR,
+                       GTK_BUTTONS_YES_NO,
+                       "%s", _("Are you sure you have bills/invoices to update?"));
+					update = gtk_dialog_run (GTK_DIALOG (dialog));
+					gtk_widget_destroy(dialog);
+					if(update == -9) // = NO.  -8 = YES.
+					{// Cleanup and leave
+						g_free (id); g_free (date_opened); g_free (owner_id); g_free (biing_id); g_free (notes);
+						g_free (date); g_free (desc); g_free (action); g_free (account); g_free (quantity); g_free (price); g_free (disc_type);
+						g_free (disc_how); g_free (discount); g_free (taxable); g_free (taxincluded); g_free (tax_table);
+						g_free (date_posted); g_free (due_date); g_free (account_posted); g_free (memo_posted); g_free (accumulatesplits);
+						return;
+					}
+				}
+		(*n_invoices_updated)++;
+		}
+
+
+		// add entry to invoice/bi
+		entry = gncEntryCreate( book );
+		qof_scan_date( date, &day, &month, &year );
+		gncEntrySetDate( entry, gnc_dmy2timespec(day,month,year) );
+		timespecFromTime_t( &today, time(NULL) ); // set today to the current date
+		gncEntrySetDateEntered( entry, today ); // This sets the wrong date on my system!
+		gncEntrySetDescription( entry, desc );
+		gncEntrySetAction( entry, action );
+
+		n = gnc_numeric_zero(); gnc_exp_parser_parse( quantity, &n, NULL );
+		gncEntrySetQuantity( entry, n );
+		acc = gnc_account_lookup_for_register( gnc_get_current_root_account(), account );
+		if (g_ascii_strcasecmp(type,"BILL") == 0)
+		{
+			gncEntrySetBillAccount( entry, acc );
+			n = gnc_numeric_zero(); gnc_exp_parser_parse( price, &n, NULL );
+			gncEntrySetBillPrice( entry, n );
+			gncEntrySetBillTaxable( entry, text2bool(taxable) );
+			gncEntrySetBillTaxIncluded( entry, text2bool(taxincluded) );
+			gncEntrySetBillTaxTable( entry, gncTaxTableLookupByName(book,tax_table) );
+			n = gnc_numeric_zero(); gnc_exp_parser_parse( discount, &n, NULL );
+			gncBillAddEntry( invoice, entry );
+		}
+		else if (g_ascii_strcasecmp(type,"INVOICE") == 0)
+		{
+			gncEntrySetNotes( entry, notes );
+			gncEntrySetInvAccount( entry, acc );
+			n = gnc_numeric_zero(); gnc_exp_parser_parse( price, &n, NULL );
+			gncEntrySetInvPrice( entry, n );
+			gncEntrySetInvTaxable( entry, text2bool(taxable) );
+			gncEntrySetInvTaxIncluded( entry, text2bool(taxincluded) );
+			gncEntrySetInvTaxTable( entry, gncTaxTableLookupByName(book,tax_table) );
+			n = gnc_numeric_zero(); gnc_exp_parser_parse( discount, &n, NULL );
+			gncEntrySetInvDiscount( entry, n );
+			gncEntrySetInvDiscountType( entry, text2disc_type( disc_type ) );
+			gncEntrySetInvDiscountHow( entry, text2disc_how( disc_how ) );
+			gncInvoiceAddEntry( invoice, entry );
+		}
+		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
+
+		// handle auto posting of invoices
+		{
+			gchar *new_id = NULL;
+			Transaction *tnx;
+			if (valid)
+				gtk_tree_model_get( GTK_TREE_MODEL(store), &iter,  ID, &new_id, -1 );
+			if (g_strcmp0( id, new_id ) != 0) {
+				// the next invoice id is different => try to autopost this invoice
+				if (qof_scan_date( date_posted, &day, &month, &year )) {
+					// autopost this invoice
+					Timespec d1,d2;
+					d1 = gnc_dmy2timespec(day,month,year);
+					qof_scan_date( due_date, &day, &month, &year ); // obtains the due date, or leaves it at date_posted
+					d2 = gnc_dmy2timespec(day,month,year);
+					acc = gnc_account_lookup_for_register( gnc_get_current_root_account(), account_posted );
+					tnx = gncInvoicePostToAccount( invoice, acc, &d1, &d2, memo_posted, text2bool(accumulatesplits) );
+				}
+			}
+			g_free( new_id );
+		}
+
+		// cleanup
+		g_free (id); g_free (date_opened); g_free (owner_id); g_free (biing_id); g_free (notes);
+		g_free (date); g_free (desc); g_free (action); g_free (account); g_free (quantity); g_free (price); g_free (disc_type);
+		g_free (disc_how); g_free (discount); g_free (taxable); g_free (taxincluded); g_free (tax_table);
+		g_free (date_posted); g_free (due_date); g_free (account_posted); g_free (memo_posted); g_free (accumulatesplits);
+	}
+}
diff --git src/plugins/bi_import/bi_import.h src/plugins/bi_import/bi_import.h
new file mode 100644
index 0000000..ec3705e
--- /dev/null
+++ src/plugins/bi_import/bi_import.h
@@ -0,0 +1,74 @@
+/*
+ * bi_import.h --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+/**
+ * @addtogroup Tools
+ * @{
+ * @file bi_import.h
+ * @brief core import functions for invoice import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held@gmx.de>
+ */
+
+#ifndef GNC_PLUGIN_bi_import_bi_import_H
+#define GNC_PLUGIN_bi_import_bi_import_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+// model
+enum bi_import_model_columns {
+	 ID, DATE_OPENED, OWNER_ID, BILLING_ID, NOTES, // invoice settings
+	 DATE, DESC, ACTION, ACCOUNT, QUANTITY, PRICE, DISC_TYPE, DISC_HOW, DISCOUNT, TAXABLE, TAXINCLUDED, TAX_TABLE, // entry settings
+	 DATE_POSTED, DUE_DATE, ACCOUNT_POSTED, MEMO_POSTED, ACCU_SPLITS, // autopost settings
+	 N_COLUMNS
+};
+
+enum _bi_import_result {
+	 RESULT_OK,
+	 RESULT_OPEN_FAILED,
+	 RESULT_ERROR_IN_REGEXP,
+};
+typedef enum _bi_import_result bi_import_result;
+
+struct _bi_import_stats {
+	int n_imported, n_ignored;
+	GString *ignored_lines;
+};
+typedef struct _bi_import_stats bi_import_stats;
+
+
+bi_import_result
+gnc_bi_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows, bi_import_stats *stats);
+
+void
+gnc_bi_import_fix_bis (GtkListStore *store, guint *fixed, guint *deleted, GString *info);
+
+void
+gnc_bi_import_create_bis (GtkListStore *store, QofBook *book, guint *n_invoices_created, guint *n_invoices_updated,	gchar *type);
+
+
+G_END_DECLS
+
+#endif /* GNC_PLUGIN_bi_import_bi_import_H */
+
+/** @} */
diff --git src/plugins/bi_import/glade/Makefile.am src/plugins/bi_import/glade/Makefile.am
new file mode 100644
index 0000000..242e770
--- /dev/null
+++ src/plugins/bi_import/glade/Makefile.am
@@ -0,0 +1,4 @@
+gladedir = $(GNC_GLADE_DIR)
+glade_DATA = bi_import.glade
+
+EXTRA_DIST = ${glade_DATA}
diff --git src/plugins/bi_import/glade/bi_import.glade src/plugins/bi_import/glade/bi_import.glade
new file mode 100644
index 0000000..85c34cd
--- /dev/null
+++ src/plugins/bi_import/glade/bi_import.glade
@@ -0,0 +1,370 @@
+<?xml version="1.0"?>
+<glade-interface>
+  <!-- interface-requires gtk+ 2.6 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <widget class="GtkDialog" id="bi_import Dialog">
+    <property name="visible">True</property>
+    <property name="title" translatable="yes">Import transactions from text file</property>
+    <property name="type_hint">dialog</property>
+    <signal name="destroy" handler="gnc_bi_import_gui_destroy_cb"/>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">8</property>
+        <child>
+          <widget class="GtkFrame" id="frame1">
+            <property name="visible">True</property>
+            <property name="border_width">3</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment1">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkEntry" id="entryFilename">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <signal name="changed" handler="gnc_bi_import_gui_filenameChanged_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkButton" id="buttonOpen">
+                        <property name="label">gtk-open</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_stock">True</property>
+                        <signal name="clicked" handler="gnc_bi_import_gui_buttonOpen_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="pack_type">end</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">1. Choose the file to import</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkFrame" id="frame4">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment4">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment5">
+                    <property name="visible">True</property>
+                    <child>
+                      <widget class="GtkHBox" id="hbox2">
+                        <property name="visible">True</property>
+                        <child>
+                          <widget class="GtkRadioButton" id="radiobuttonBill">
+                            <property name="label" translatable="yes">Bill</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="has_default">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="has_tooltip">True</property>
+                            <property name="tooltip" translatable="yes">Import bill CSV data</property>
+                            <property name="xalign">0.4699999988079071</property>
+                            <property name="active">True</property>
+                            <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="gnc_import_gui_type"/>
+                          </widget>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkRadioButton" id="radiobuttonInvoice">
+                            <property name="label" translatable="yes">Invoice</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="receives_default">False</property>
+                            <property name="has_tooltip">True</property>
+                            <property name="tooltip" translatable="yes">Import invoice CSV data</property>
+                            <property name="draw_indicator">True</property>
+                            <property name="group">radiobuttonBill</property>
+                            <signal name="toggled" handler="gnc_import_gui_type"/>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label4">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">2, Select import type</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkFrame" id="frame2">
+            <property name="visible">True</property>
+            <property name="border_width">3</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment2">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkVBox" id="vbox1">
+                    <property name="visible">True</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <widget class="GtkRadioButton" id="radiobutton1">
+                        <property name="label" translatable="yes">Semicolon separated</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <signal name="toggled" handler="gnc_bi_import_gui_option1_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkRadioButton" id="radiobutton2">
+                        <property name="label" translatable="yes">Comma separated</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="toggled" handler="gnc_bi_import_gui_option2_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkRadioButton" id="radiobutton3">
+                        <property name="label" translatable="yes">Semicolon separated with quotes</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="toggled" handler="gnc_bi_import_gui_option3_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkRadioButton" id="radiobutton4">
+                        <property name="label" translatable="yes">Comma separated with quotes</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="toggled" handler="gnc_bi_import_gui_option4_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkRadioButton" id="radiobutton5">
+                        <property name="label" translatable="yes">Custom regular expression</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="clicked" handler="gnc_bi_import_gui_option5_cb"/>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">3. Select import options</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkFrame" id="frame3">
+            <property name="visible">True</property>
+            <property name="border_width">3</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <widget class="GtkAlignment" id="alignment3">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <widget class="GtkScrolledWindow" id="scrolledwindow2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <widget class="GtkTreeView" id="treeview1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">4. Preview</property>
+                <property name="use_markup">True</property>
+              </widget>
+              <packing>
+                <property name="type">label_item</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <widget class="GtkButton" id="helpbutton">
+                <property name="label">gtk-help</property>
+                <property name="response_id">-11</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gnc_bi_import_gui_help_cb"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="cancelbutton">
+                <property name="label">gtk-cancel</property>
+                <property name="response_id">-6</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gnc_bi_import_gui_cancel_cb"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="okbutton">
+                <property name="label">gtk-ok</property>
+                <property name="response_id">-5</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gnc_bi_import_gui_ok_cb"/>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">5</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git src/plugins/bi_import/gnc-plugin-bi_import.c src/plugins/bi_import/gnc-plugin-bi_import.c
new file mode 100644
index 0000000..b54187e
--- /dev/null
+++ src/plugins/bi_import/gnc-plugin-bi_import.c
@@ -0,0 +1,115 @@
+/*
+ * gnc-plugin-bi_import.c --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+/**
+ * @internal
+ * @file gnc-plugin-bi_import.c
+ * @brief Plugin registration of the bi_import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held@gmx.de>
+ * @author Mike Evans <mikee@saxicola.co.uk>
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <glib/gi18n.h>
+
+#include "dialog-utils.h"
+
+#include "gnc-plugin-bi_import.h"
+#include "gui.h"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = G_LOG_DOMAIN;
+
+static void gnc_plugin_bi_import_class_init         (GncPluginbi_importClass *klass);
+static void gnc_plugin_bi_import_init               (GncPluginbi_import *plugin);
+static void gnc_plugin_bi_import_finalize           (GObject *object);
+
+/* Command callbacks */
+static void gnc_plugin_bi_import_cmd_test (GtkAction *action, GncMainWindowActionData *data);
+
+#define PLUGIN_ACTIONS_NAME "gnc-plugin-bi_import-actions"
+#define PLUGIN_UI_FILENAME  "gnc-plugin-bi_import-ui.xml"
+
+static GtkActionEntry gnc_plugin_actions [] = {
+    /* Menu Items */
+	{ "ImportMenuAction", NULL, N_("_Import"), NULL, NULL, NULL },
+    { "bi_importAction", NULL, N_("Import Bills & Invoices..."), NULL, N_("bi_import tooltip"),  G_CALLBACK(gnc_plugin_bi_import_cmd_test) },
+};
+static guint gnc_plugin_n_actions = G_N_ELEMENTS(gnc_plugin_actions);
+
+
+/************************************************************
+ *                   Object Implementation                  *
+ ************************************************************/
+
+G_DEFINE_TYPE(GncPluginbi_import, gnc_plugin_bi_import, GNC_TYPE_PLUGIN);
+
+GncPlugin *
+gnc_plugin_bi_import_new (void)
+{
+    return GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_bi_import, (gchar*) NULL));
+}
+
+static void
+gnc_plugin_bi_import_class_init (GncPluginbi_importClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GncPluginClass *plugin_class = GNC_PLUGIN_CLASS(klass);
+
+    object_class->finalize = gnc_plugin_bi_import_finalize;
+
+    /* plugin info */
+    plugin_class->plugin_name  = GNC_PLUGIN_bi_import_NAME;
+
+    /* widget addition/removal */
+    plugin_class->actions_name       = PLUGIN_ACTIONS_NAME;
+    plugin_class->actions            = gnc_plugin_actions;
+    plugin_class->n_actions          = gnc_plugin_n_actions;
+    plugin_class->ui_filename        = PLUGIN_UI_FILENAME;
+}
+
+static void
+gnc_plugin_bi_import_init (GncPluginbi_import *plugin)
+{
+}
+
+static void
+gnc_plugin_bi_import_finalize (GObject *object)
+{
+}
+
+/************************************************************
+ *                    Command Callbacks                     *
+ ************************************************************/
+
+static void
+gnc_plugin_bi_import_cmd_test (GtkAction *action, GncMainWindowActionData *data)
+{
+    ENTER ("action %p, main window data %p", action, data);
+    g_message ("bi_import");
+
+    gnc_plugin_bi_import_showGUI();
+
+    LEAVE (" ");
+}
diff --git src/plugins/bi_import/gnc-plugin-bi_import.h src/plugins/bi_import/gnc-plugin-bi_import.h
new file mode 100644
index 0000000..7e244af
--- /dev/null
+++ src/plugins/bi_import/gnc-plugin-bi_import.h
@@ -0,0 +1,78 @@
+/*
+ * gnc-plugin-bi_import.h --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+/**
+ * @addtogroup Tools
+ * @{
+ * @file gnc-plugin-bi_import.h
+ * @brief Plugin registration of the bi_import module
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held@gmx.de>
+ */
+
+#ifndef GNC_PLUGIN_bi_import_H
+#define GNC_PLUGIN_bi_import_H
+
+#include <glib.h>
+
+#include "gnc-plugin.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_PLUGIN_bi_import            (gnc_plugin_bi_import_get_type())
+#define GNC_PLUGIN_bi_import(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GNC_TYPE_PLUGIN_bi_import, GncPluginbi_import))
+#define GNC_PLUGIN_bi_import_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  GNC_TYPE_PLUGIN_bi_import, GncPluginbi_importClass))
+#define GNC_IS_PLUGIN_bi_import(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNC_TYPE_PLUGIN_bi_import))
+#define GNC_IS_PLUGIN_bi_import_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  GNC_TYPE_PLUGIN_bi_import))
+#define GNC_PLUGIN_bi_import_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  GNC_TYPE_PLUGIN_bi_import, GncPluginbi_importClass))
+
+#define GNC_PLUGIN_bi_import_NAME "gnc-plugin-bi_import"
+
+/* typedefs & structures */
+typedef struct {
+    GncPlugin gnc_plugin;
+} GncPluginbi_import;
+
+typedef struct {
+    GncPluginClass gnc_plugin;
+} GncPluginbi_importClass;
+
+/* function prototypes */
+/**
+ * @return The glib runtime type of an bi_import plugin page
+ **/
+GType gnc_plugin_bi_import_get_type (void);
+
+/**
+ * @return A new GncPluginbi_import object
+ */
+GncPlugin* gnc_plugin_bi_import_new (void);
+
+/**
+ * Create a new GncPluginbi_import object and register it.
+ */
+void gnc_plugin_bi_import_create_plugin (void);
+
+G_END_DECLS
+
+/** @} */
+
+#endif /* GNC_PLUGIN_bi_import_H */
diff --git src/plugins/bi_import/gncmod-bi_import.c src/plugins/bi_import/gncmod-bi_import.c
new file mode 100644
index 0000000..dbbf6b6
--- /dev/null
+++ src/plugins/bi_import/gncmod-bi_import.c
@@ -0,0 +1,100 @@
+/*********************************************************************
+ * gncmod-bi_import.c
+ * module definition/initialization for the bi_import GNOME UI module
+ *
+ * Copyright (c) 2009 Sebastian Held <sebastian.held@gmx.de>
+ * Copyright (c) 2001 Derek Atkins <warlord@MIT.EDU>
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ *
+ *********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gmodule.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <libguile.h>
+
+#include "gnc-hooks.h"
+#include "gnc-module.h"
+#include "gnc-module-api.h"
+
+#include "gnc-plugin-manager.h"
+#include "gnc-plugin-bi_import.h"
+
+GNC_MODULE_API_DECL(libgncmod_bi_import);
+
+/* version of the gnc module system interface we require */
+int libgncmod_bi_import_gnc_module_system_interface = 0;
+
+/* module versioning uses libtool semantics. */
+int libgncmod_bi_import_gnc_module_current  = 0;
+int libgncmod_bi_import_gnc_module_revision = 0;
+int libgncmod_bi_import_gnc_module_age      = 0;
+
+
+char *
+libgncmod_bi_import_gnc_module_path (void)
+{
+    return g_strdup("gnucash/plugins/bi_import");
+}
+
+char *
+libgncmod_bi_import_gnc_module_description (void)
+{
+    return g_strdup("The GnuCash bi_import plugin");
+}
+
+int
+libgncmod_bi_import_gnc_module_init (int refcount)
+{
+    if (!gnc_module_load ("gnucash/app-utils", 0)) {
+        return FALSE;
+    }
+    if (!gnc_module_load ("gnucash/gnome-utils", 0)) {
+        return FALSE;
+    }
+    if (!gnc_module_load ("gnucash/business-core", 0)) {
+        return FALSE;
+    }
+    if (!gnc_module_load ("gnucash/engine", 0)) {
+        return FALSE;
+    }
+
+    if (refcount == 0) {
+        /* this is the first time the module is loaded */
+
+        gnc_plugin_manager_add_plugin ( gnc_plugin_manager_get (),
+                   gnc_plugin_bi_import_new ());
+    }
+
+    return TRUE;
+}
+
+int
+libgncmod_bi_import_gnc_module_end (int refcount)
+{
+    if (refcount == 0) {
+        /* this is the last time the module is unloaded */
+    }
+
+    return TRUE;
+}
diff --git src/plugins/bi_import/gui.c src/plugins/bi_import/gui.c
new file mode 100644
index 0000000..274afd4
--- /dev/null
+++ src/plugins/bi_import/gui.c
@@ -0,0 +1,471 @@
+/*
+ * gui.c --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+/**
+ * @internal
+ * @file gui.c
+ * @brief GUI handling for bi import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held@gmx.de>
+ * @author Copyright (C) 2010	Mike Evans <mikee@saxicola.co.uk>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+
+#include "gnc-ui.h"
+#include "gnc-ui-util.h"
+#include "gnc-component-manager.h"
+#include "dialog-utils.h"
+#include "gnc-gui-query.h"
+#include "gnc-file.h"
+#include "gnc-gnome-utils.h"
+#include "bi_import.h"
+#include "gui.h"
+
+struct _bi_import_gui {
+	GtkWidget    *dialog;
+	GtkWidget    *tree_view;
+	GtkWidget    *entryFilename;
+	GtkListStore *store;
+	gint          component_id;
+	GString      *regexp;
+	QofBook      *book;
+	gchar	*type;
+};
+
+
+
+
+
+// callback routines
+void gnc_bi_import_gui_ok_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_cancel_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_help_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_destroy_cb (GtkWidget *widget, gpointer data);
+static void gnc_bi_import_gui_close_handler (gpointer user_data);
+void gnc_bi_import_gui_buttonOpen_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_filenameChanged_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_option1_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_option2_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_option3_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_option4_cb (GtkWidget *widget, gpointer data);
+void gnc_bi_import_gui_option5_cb (GtkWidget *widget, gpointer data);
+void gnc_import_gui_type(GtkWidget *widget, gpointer data);
+
+// utils
+static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
+static void gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg);
+
+
+BillImportGui *
+gnc_plugin_bi_import_showGUI(void)
+{
+	BillImportGui *gui;
+	GladeXML *xml;
+	GList *glist;
+	GtkTreeIter iter;
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+
+
+
+	// if window exists already, activate it
+	glist = gnc_find_gui_components ("dialog-bi_import_gui", NULL, NULL);
+	if (glist) {
+		// window found
+		gui = g_list_nth_data (glist,0);
+		g_list_free (glist);
+		gtk_window_present (GTK_WINDOW(gui->dialog));
+		return gui;
+	}
+
+	// create new window
+	gui = g_new0 (BillImportGui, 1);
+	gui->type = "BILL"; // Set default type to match gui.  really shouldn't be here TODO change me
+    xml = gnc_glade_xml_new ("bi_import.glade", "bi_import Dialog");
+	gui->dialog = glade_xml_get_widget (xml, "bi_import Dialog");
+    gui->tree_view = glade_xml_get_widget (xml, "treeview1");
+	gui->entryFilename = glade_xml_get_widget (xml, "entryFilename");
+
+	 gui->book = gnc_get_current_book();
+
+				gui->regexp = g_string_new ( "^(?<id>[^;]*);(?<date_opened>[^;]*);(?<owner_id>[^;]*);(?<billingid>[^;]*);?(?<notes>[^;]*);?(?<date>[^;]*);?(?<desc>[^;]*);?(?<action>[^;]*);?(?<account>[^;]*);?(?<quantity>[^;]*);?(?<price>[^;]*)(;?(?<disc_type>[^;]*)(;?(?<disc_how>[^;]*)(;?(?<discount>[^;]*)(;?(?<taxable>[^;]*)(;?(?<taxincluded>[^;]*)(;?(?<tax_table>[^;]*)(;(?<date_posted>[^;]*)(;(?<due_date>[^;]*)(;(?<account_posted>[^;]*)(;(?<memo_posted>[^;]*)(;(?<accu_splits>[^;]*))?)?)?)?)?)?)?)?)?)?)?");
+
+    // create model and bind to view
+    gui->store = gtk_list_store_new (N_COLUMNS,
+		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, // invoice settings
+		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, // entry settings
+		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); // autopost settings
+	gtk_tree_view_set_model( GTK_TREE_VIEW(gui->tree_view), GTK_TREE_MODEL(gui->store) );
+#define CREATE_COLUMN(description,column_id) \
+  renderer = gtk_cell_renderer_text_new (); \
+  column = gtk_tree_view_column_new_with_attributes (description, renderer, "text", column_id, NULL); \
+  gtk_tree_view_column_set_resizable (column, TRUE); \
+  gtk_tree_view_append_column (GTK_TREE_VIEW (gui->tree_view), column);
+	CREATE_COLUMN ("id", ID);
+	CREATE_COLUMN ("date__opened", DATE_OPENED);
+	CREATE_COLUMN ("owner__id", OWNER_ID);
+	CREATE_COLUMN ("billing_id", BILLING_ID);
+	CREATE_COLUMN ("notes", NOTES);
+
+	CREATE_COLUMN ("date", DATE);
+	CREATE_COLUMN ("desc", DESC);
+	CREATE_COLUMN ("action", ACTION);
+	CREATE_COLUMN ("account", ACCOUNT);
+	CREATE_COLUMN ("quantity", QUANTITY);
+	CREATE_COLUMN ("price", PRICE);
+	CREATE_COLUMN ("disc__type", DISC_TYPE);
+	CREATE_COLUMN ("disc__how", DISC_HOW);
+	CREATE_COLUMN ("discount", DISCOUNT);
+	CREATE_COLUMN ("taxable", TAXABLE);
+	CREATE_COLUMN ("taxincluded", TAXINCLUDED);
+	CREATE_COLUMN ("tax__table", TAX_TABLE);
+
+	CREATE_COLUMN ("date__posted", DATE_POSTED);
+	CREATE_COLUMN ("due__date", DUE_DATE);
+	CREATE_COLUMN ("account__posted", ACCOUNT_POSTED);
+	CREATE_COLUMN ("memo__posted", MEMO_POSTED);
+	CREATE_COLUMN ("accu__splits", ACCU_SPLITS);
+
+    gui->component_id = gnc_register_gui_component ("dialog-bi_import_gui",
+				  NULL,
+				  gnc_bi_import_gui_close_handler,
+				  gui);
+
+	/* Setup signals */
+	glade_xml_signal_autoconnect_full( xml, gnc_glade_autoconnect_full_func, gui );
+
+    gtk_widget_show_all ( gui->dialog );
+	return gui;
+}
+
+static gchar *
+gnc_plugin_bi_import_getFilename(void)
+{
+     // prepare file import dialog
+     gchar *filename;
+     GList *filters;
+     GtkFileFilter *filter;
+     filters = NULL;
+     filter = gtk_file_filter_new ();
+     gtk_file_filter_set_name (filter, "comma separated values (*.csv)");
+     gtk_file_filter_add_pattern (filter, "*.csv");
+     filters = g_list_append( filters, filter );
+     filter = gtk_file_filter_new ();
+     gtk_file_filter_set_name (filter, "text files (*.txt)");
+     gtk_file_filter_add_pattern (filter, "*.txt");
+     filters = g_list_append( filters, filter );
+     filename = gnc_file_dialog(_("Import Bills or Invoices from csv"), filters, NULL, GNC_FILE_DIALOG_IMPORT);
+
+     return filename;
+}
+
+void
+gnc_bi_import_gui_ok_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	gchar *filename = g_strdup( gtk_entry_get_text( GTK_ENTRY(gui->entryFilename) ) );
+	bi_import_stats stats;
+	bi_import_result res;
+	guint n_fixed, n_deleted, n_invoices_created, n_invoices_updated;
+	GString *info;
+
+	// import
+	info = g_string_new("");
+
+	gtk_list_store_clear (gui->store);
+	res = gnc_bi_import_read_file (filename, gui->regexp->str, gui->store, 0, &stats);
+	if (res == RESULT_OK) {
+		gnc_bi_import_fix_bis (gui->store, &n_fixed, &n_deleted, info);
+		if (info->len > 0)
+			gnc_info_dialog (gui->dialog, "%s", info->str);
+		g_string_free( info, TRUE );
+		gnc_bi_import_create_bis (gui->store, gui->book, &n_invoices_created, &n_invoices_updated, gui->type);
+    	gnc_info_dialog (gui->dialog, _("Import results:\n%i lines were ignored\n%i lines imported:\n   %u fixes\n   %u ignored (not fixable)\n\n   %u created\n   %u updated (based on id)"), stats.n_ignored, stats.n_imported, n_fixed, n_deleted, n_invoices_created, n_invoices_updated);
+
+		if (stats.n_ignored > 0)
+			gnc_info2_dialog (gui->dialog, _("These lines were ignored during import"), stats.ignored_lines->str);
+
+		g_string_free (stats.ignored_lines,TRUE);
+		gnc_close_gui_component (gui->component_id);
+	} else
+	if (res ==  RESULT_OPEN_FAILED) {
+		gnc_error_dialog (gui->dialog, _("The input file can not be opened."));
+	} else
+	if (res ==  RESULT_ERROR_IN_REGEXP) {
+		//gnc_error_dialog (gui->dialog, "The regular expression is faulty:\n\n%s", stats.err->str);
+	}
+}
+
+void
+gnc_bi_import_gui_cancel_cb (GtkWidget *widget, gpointer data)
+{
+  BillImportGui *gui = data;
+
+  gnc_close_gui_component (gui->component_id);
+}
+
+void
+gnc_bi_import_gui_help_cb (GtkWidget *widget, gpointer data)
+{
+  gnc_gnome_help(HF_HELP, HL_USAGE);
+}
+
+static void
+gnc_bi_import_gui_close_handler (gpointer user_data)
+{
+  BillImportGui *gui = user_data;
+
+  gtk_widget_destroy (gui->dialog);
+  // gui has already been freed by this point.
+  // gui->dialog = NULL;
+}
+
+void
+gnc_bi_import_gui_destroy_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+
+	gnc_suspend_gui_refresh ();
+	gnc_unregister_gui_component (gui->component_id);
+	gnc_resume_gui_refresh ();
+
+	g_object_unref (gui->store);
+	g_string_free (gui->regexp, TRUE);
+	g_free (gui);
+}
+
+void gnc_bi_import_gui_buttonOpen_cb (GtkWidget *widget, gpointer data)
+{
+	gchar *filename;
+	BillImportGui *gui = data;
+
+	filename = gnc_plugin_bi_import_getFilename();
+	if (filename) {
+		printf("Setting filename"); // debug
+		gtk_entry_set_text( GTK_ENTRY(gui->entryFilename), filename );
+			printf("Set filename"); // debug
+		g_free( filename );
+	}
+}
+
+void gnc_bi_import_gui_filenameChanged_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	gchar *filename = g_strdup( gtk_entry_get_text( GTK_ENTRY(gui->entryFilename) ) );
+
+	// generate preview
+	gtk_list_store_clear (gui->store);
+	gnc_bi_import_read_file (filename, gui->regexp->str, gui->store, 10, NULL);
+
+	g_free( filename );
+}
+
+void gnc_bi_import_gui_option1_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+		return;
+	g_string_assign (gui->regexp, "^(?<id>[^!#+^;]*);(?<date_opened>[^;]*);(?<owner_id>[^;]*);(?<billingid>[^;]*);?(?<notes>[^;]*);?(?<date>[^;]*);?(?<desc>[^;]*);?(?<action>[^;]*);?(?<account>[^;]*);?(?<quantity>[^;]*);?(?<price>[^;]*);?(?<disc_type>[^;]*);?(?<disc_how>[^;]*);?(?<discount>[^;]*);?(?<taxable>[^;]*);?(?<taxincluded>[^;]*);?(?<tax_table>[^;]*);(?<date_posted>[^;]*);(?<due_date>[^;]*);(?<account_posted>[^;]*);(?<memo_posted>[^;]*);(?<accu_splits>[^;]*)");
+	gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+void gnc_bi_import_gui_option2_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+		return;
+	g_string_assign (gui->regexp, "^(?<id>[^!#+^,]*),(?<date_opened>[^,]*),(?<owner_id>[^,]*),(?<billingid>[^,]*),?(?<notes>[^,]*),?(?<date>[^,]*),?(?<desc>[^,]*),?(?<action>[^,]*),?(?<account>[^,]*),?(?<quantity>[^,]*),?(?<price>[^,]*),?(?<disc_type>[^,]*),?(?<disc_how>[^,]*),?(?<discount>[^,]*),?(?<taxable>[^,]*),?(?<taxincluded>[^,]*),?(?<tax_table>[^,]*),(?<date_posted>[^,]*),(?<due_date>[^,]*),(?<account_posted>[^,]*),(?<memo_posted>[^,]*),(?<accu_splits>[^,]*)");
+	gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+void gnc_bi_import_gui_option3_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+		return;
+	g_string_assign (gui->regexp, "^(?<id>[^!#+^;]*);(?<date_opened>[^;]*);(?<owner_id>[^;]*);(?<billingid>[^;]*);?(?<notes>[^;]*);?(?<date>[^;]*);?(?<desc>[^;]*);?(?<action>[^;]*);?(?<account>[^;]*);?(?<quantity>[^;]*);?(?<price>[^;]*);?(?<disc_type>[^;]*);?(?<disc_how>[^;]*);?(?<discount>[^;]*);?(?<taxable>[^;]*);?(?<taxincluded>[^;]*);?(?<tax_table>[^;]*);(?<date_posted>[^;]*);(?<due_date>[^;]*);(?<account_posted>[^;]*);(?<memo_posted>[^;]*);(?<accu_splits>[^;]*)");
+	gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+void gnc_bi_import_gui_option4_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+		return;
+	g_string_assign (gui->regexp, "^(?<id>[^!#+^;]*);(?<date_opened>[^;]*);(?<owner_id>[^;]*);(?<billingid>[^;]*);?(?<notes>[^;]*);?(?<date>[^;]*);?(?<desc>[^;]*);?(?<action>[^;]*);?(?<account>[^;]*);?(?<quantity>[^;]*);?(?<price>[^;]*);?(?<disc_type>[^;]*);?(?<disc_how>[^;]*);?(?<discount>[^;]*);?(?<taxable>[^;]*);?(?<taxincluded>[^;]*);?(?<tax_table>[^;]*);(?<date_posted>[^;]*);(?<due_date>[^;]*);(?<account_posted>[^;]*);(?<memo_posted>[^;]*);(?<accu_splits>[^;]*)");
+	gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+void gnc_bi_import_gui_option5_cb (GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	gchar *temp;
+	if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+		return;
+    temp = gnc_input_dialog (0, _("Adjust regular expression used for import"), _("This regular expression is used to parse the import file. Modify according to your needs.\n"), gui->regexp->str);
+    if (temp) {
+        g_string_assign (gui->regexp,temp);
+		g_free (temp);
+		gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+	}
+}
+/*****************************************************************
+ * Set whether we are importing a bi, invoice, Customer or Vendor
+ * ****************************************************************/
+
+void gnc_import_gui_type(GtkWidget *widget, gpointer data)
+{
+	BillImportGui *gui = data;
+	if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+		return;
+		if  (g_ascii_strcasecmp(widget->name,"radiobuttonInvoice") == 0)gui->type="INVOICE";
+		else if (g_ascii_strcasecmp(widget->name,"radiobuttonBill") == 0)gui->type="BILL";
+	//printf ("TYPE set to, %s\n",gui->type);
+
+}
+
+
+
+
+
+
+
+
+
+/********************************************************************\
+ * gnc_input_dialog                                                 *
+ *   simple convenience dialog to get a single value from the user  *
+ *   user may choose between "Ok" and "Cancel"                      *
+ *                                                                  *
+ * NOTE: This function does not return until the dialog is closed   *
+ *                                                                  *
+ * Args:   parent  - the parent window or NULL                      *
+ *         title   - the title of the dialog                        *
+ *         msg     - the message to display                         *
+ *         default_input - will be displayed as default input       *
+ * Return: the input (text) the user entered, if pressed "Ok"       *
+ *         NULL, if pressed "Cancel"                                *
+\********************************************************************/
+static gchar *
+gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
+{
+    GtkWidget *dialog, *label, *content_area;
+    gint result;
+    GtkWidget *view;
+    GtkTextBuffer *buffer;
+    gchar *user_input;
+    GtkTextIter start, end;
+
+    /* Create the widgets */
+    dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
+                GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                NULL);
+#ifdef HAVE_GTK_2_14
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+#else
+    content_area = GTK_DIALOG (dialog)->vbox;
+#endif
+
+    // add a label
+    label = gtk_label_new (msg);
+    gtk_container_add (GTK_CONTAINER (content_area), label);
+
+    // add a textview
+    view = gtk_text_view_new ();
+    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
+    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+    gtk_text_buffer_set_text (buffer, default_input, -1);
+    gtk_container_add (GTK_CONTAINER (content_area), view);
+
+    // run the dialog
+    gtk_widget_show_all (dialog);
+    result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+    if (result == GTK_RESPONSE_REJECT)
+        user_input = 0;
+    else {
+        gtk_text_buffer_get_start_iter (buffer, &start);
+        gtk_text_buffer_get_end_iter (buffer, &end);
+        user_input = gtk_text_buffer_get_text (buffer,
+                         &start, &end, FALSE);
+    }
+
+    gtk_widget_destroy (dialog);
+
+    return user_input;
+}
+
+/********************************************************************\
+ * gnc_info2_dialog                                                 *
+ *   displays an information dialog box (with scrollable text area) *
+ *                                                                  *
+ * NOTE: This function does not return until the dialog is closed   *
+ *                                                                  *
+ * Args:   parent  - the parent window or NULL                      *
+ *         title   - the title of the dialog                        *
+ *         msg     - the message to display                         *
+ * Return: none                                                     *
+\********************************************************************/
+static void
+gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg)
+{
+    GtkWidget *dialog, *scrolledwindow, *content_area;
+    gint result;
+    GtkWidget *view;
+    GtkTextBuffer *buffer;
+    gchar *user_input;
+    GtkTextIter start, end;
+	gint width,height;
+
+    /* Create the widgets */
+    dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
+                GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                NULL);
+#ifdef HAVE_GTK_2_14
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+#else
+    content_area = GTK_DIALOG (dialog)->vbox;
+#endif
+
+    // add a scroll area
+    scrolledwindow = gtk_scrolled_window_new (NULL,NULL);
+    gtk_container_add (GTK_CONTAINER (content_area), scrolledwindow);
+
+    // add a textview
+    view = gtk_text_view_new ();
+//    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
+	gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
+    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+    gtk_text_buffer_set_text (buffer, msg, -1);
+    gtk_container_add (GTK_CONTAINER (scrolledwindow), view);
+
+    // run the dialog
+	if (parent) {
+		gtk_window_get_size (GTK_WINDOW(parent), &width, &height);
+		gtk_window_set_default_size (GTK_WINDOW(dialog), width, height);
+	}
+    gtk_widget_show_all (dialog);
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_destroy (dialog);
+}
diff --git src/plugins/bi_import/gui.h src/plugins/bi_import/gui.h
new file mode 100644
index 0000000..e94c535
--- /dev/null
+++ src/plugins/bi_import/gui.h
@@ -0,0 +1,48 @@
+/*
+ * gui.h --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+/**
+ * @addtogroup Tools
+ * @{
+ * @file gui.h
+ * @brief GUI handling for bi import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held@gmx.de>
+ */
+
+#ifndef GNC_PLUGIN_bi_import_gui_H
+#define GNC_PLUGIN_bi_import_gui_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _bi_import_gui BillImportGui;
+
+/**
+ * File chooser
+ */
+BillImportGui *gnc_plugin_bi_import_showGUI(void);
+
+G_END_DECLS
+
+#endif /* GNC_PLUGIN_bi_import_gui_H */
+
+/** @} */
diff --git src/plugins/bi_import/helpers.c src/plugins/bi_import/helpers.c
new file mode 100644
index 0000000..9de7940
--- /dev/null
+++ src/plugins/bi_import/helpers.c
@@ -0,0 +1,80 @@
+/**
+ * helpers.c --
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "helpers.h"
+
+//! \brief helper function
+gboolean text2bool( const gchar *text )
+{
+	gboolean erg = FALSE;
+	gchar *temp;
+
+	if (!text)
+		return erg;
+
+	temp = g_strdup( text );
+	g_strstrip( temp );
+	if ((g_ascii_strcasecmp( temp, "yes" ) == 0) || (g_ascii_strcasecmp( temp, "true" ) == 0) ||
+	    (g_ascii_strcasecmp( temp, "1" ) == 0) || (g_ascii_strcasecmp( temp, "x" ) == 0))
+		erg = TRUE;
+	g_free( temp );
+	return erg;
+}
+
+//! \brief helper function
+GncAmountType text2disc_type( const gchar *text )
+{
+	GncAmountType type = GNC_AMT_TYPE_PERCENT;
+	gchar *temp;
+
+	if (!text)
+		return type;
+
+	temp = g_strdup( text );
+	g_strstrip( temp );
+	if ((strlen(temp) > 0) && (g_ascii_strcasecmp( temp, "%" ) != 0))
+		type = GNC_AMT_TYPE_VALUE;
+	g_free( temp );
+	return type;
+}
+
+//! \brief helper function
+GncDiscountHow text2disc_how( const gchar *text )
+{
+	GncDiscountHow how = GNC_DISC_PRETAX;
+	gchar *temp;
+
+	if (!text)
+		return how;
+
+	temp = g_strdup( text );
+	g_strstrip( temp );
+	if (g_ascii_strcasecmp( temp, "=" ) == 0)
+		how = GNC_DISC_SAMETIME;
+	else if (g_ascii_strcasecmp( temp, ">" ) == 0)
+		how = GNC_DISC_POSTTAX;
+	g_free( temp );
+	return how;
+}
diff --git src/plugins/bi_import/helpers.h src/plugins/bi_import/helpers.h
new file mode 100644
index 0000000..87dccb2
--- /dev/null
+++ src/plugins/bi_import/helpers.h
@@ -0,0 +1,32 @@
+/**
+ *
+ * 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 2 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu@gnu.org
+ *
+ *
+ */
+
+
+
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "gncEntry.h"
+
+gboolean text2bool( const gchar *text );
+GncAmountType text2disc_type( const gchar *text );
+GncDiscountHow text2disc_how( const gchar *text );
diff --git src/plugins/bi_import/regex.txt src/plugins/bi_import/regex.txt
new file mode 100644
index 0000000..3679664
--- /dev/null
+++ src/plugins/bi_import/regex.txt
@@ -0,0 +1 @@
+^[#]*(?<id>[^,]*),(?<date_opened>[^,]*),(?<customer_id>[^,]*),(?<billing_id>[^,]*),?(?<notes>[^,]*),?(?<date>[^,]*),?(?<desc>[^,]*),?(?<action>[^,]*),?(?<account>[^,]*),?(?<quantity>[^,]*),?(?<price>[^,]*),?(?<disc_type>[^,]*),?(?<disc_how>[^,]*),?(?<discount>[^,]*),?(?<taxable>[^,]*),?(?<taxincluded>[^,]*),?(?<tax_table>[^,]*),(?<date_posted>[^,]*),(?<due_date>[^,]*),(?<account_posted>[^,]*),(?<memo_posted>[^,]*),(?<accu_splits>[^,]*)
diff --git src/plugins/bi_import/ui/Makefile.am src/plugins/bi_import/ui/Makefile.am
new file mode 100644
index 0000000..b06854c
--- /dev/null
+++ src/plugins/bi_import/ui/Makefile.am
@@ -0,0 +1,5 @@
+uidir = $(GNC_UI_DIR)
+ui_DATA = \
+	gnc-plugin-bi_import-ui.xml
+
+EXTRA_DIST = $(ui_DATA)
diff --git src/plugins/bi_import/ui/gnc-plugin-bi_import-ui.xml src/plugins/bi_import/ui/gnc-plugin-bi_import-ui.xml
new file mode 100644
index 0000000..f92f6b3
--- /dev/null
+++ src/plugins/bi_import/ui/gnc-plugin-bi_import-ui.xml
@@ -0,0 +1,13 @@
+<ui>
+	<menubar>
+		<placeholder name="AdditionalMenusPlaceholder">
+			<menu name="Business" action="BusinessAction">
+				<placeholder name="BusinessPlaceholderBottom">
+					<menu name="ImportMenu" action="ImportMenuAction">
+						<menuitem name="bi_import" action="bi_importAction"/>
+					</menu>
+				</placeholder>
+			</menu>
+		</placeholder>
+	</menubar>
+</ui>
