Merge branch 'CsvTransImpExp'

This commit is contained in:
Geert Janssens 2023-02-14 18:21:24 +01:00
commit a982b60f17
7 changed files with 283 additions and 318 deletions

View File

@ -95,7 +95,7 @@ static const gchar *start_trans_common_string = N_(
"Select the settings you require for the file and then click \"Next\" "
"to proceed or \"Cancel\" to abort the export.\n");
static const gchar *start_trans__multi_string = N_(
static const gchar *start_trans_multi_string = N_(
"There will be multiple rows for each transaction with each row "
"representing one split.");
@ -262,10 +262,16 @@ csv_export_simple_cb (GtkToggleButton *button, gpointer user_data)
{
CsvExportInfo *info = user_data;
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(button)))
info->simple_layout = TRUE;
info->simple_layout = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(button));
gchar *msg = NULL;
if (info->simple_layout)
msg = g_strdup_printf (_(start_trans_common_string), _(start_trans_simple_string));
else
info->simple_layout = FALSE;
msg = g_strdup_printf (_(start_trans_common_string), _(start_trans_multi_string));
gtk_label_set_text (GTK_LABEL(info->start_label), msg);
g_free (msg);
}
/*******************************************************
@ -303,7 +309,6 @@ load_settings (CsvExportInfo *info)
info->separator_str = ",";
info->file_name = NULL;
info->starting_dir = NULL;
info->trans_list = NULL;
/* The default directory for the user to select files. */
info->starting_dir = gnc_get_default_directory (GNC_PREFS_GROUP);
@ -379,7 +384,7 @@ show_acct_type_accounts (CsvExportInfo *info)
*
* update the account tree
*******************************************************/
static int
static void
update_accounts_tree (CsvExportInfo *info)
{
GncTreeViewAccount *tree;
@ -397,8 +402,6 @@ update_accounts_tree (CsvExportInfo *info)
string = g_strdup_printf ("%d", num_accounts);
gtk_label_set_text (GTK_LABEL (label), string);
g_free (string);
return num_accounts;
}
@ -411,22 +414,22 @@ static void
csv_export_account_changed_cb (GtkTreeSelection *selection,
gpointer user_data)
{
CsvExportInfo *info = user_data;
GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
GncTreeViewAccount *view;
g_return_if_fail(GTK_IS_TREE_SELECTION(selection));
info->csva.num_accounts = update_accounts_tree (info);
CsvExportInfo *info = user_data;
GncTreeViewAccount *view = GNC_TREE_VIEW_ACCOUNT(info->csva.account_treeview);
info->csva.account_list = gnc_tree_view_account_get_selected_accounts (view);
/* Enable the "Next" Assistant Button if we have accounts */
if (info->csva.num_accounts > 0)
GtkAssistant *assistant = GTK_ASSISTANT(info->assistant);
if (g_list_length (info->csva.account_list) > 0)
gtk_assistant_set_page_complete (assistant, info->account_page, TRUE);
else
gtk_assistant_set_page_complete (assistant, info->account_page, FALSE);
view = GNC_TREE_VIEW_ACCOUNT(info->csva.account_treeview);
info->csva.account_list = gnc_tree_view_account_get_selected_accounts (view);
update_accounts_tree (info);
}
@ -662,24 +665,15 @@ csv_export_assistant_start_page_prepare (GtkAssistant *assistant,
gpointer user_data)
{
CsvExportInfo *info = user_data;
gchar *msg = NULL;
/* Set Start page text */
if (info->export_type == XML_EXPORT_TREE)
gtk_label_set_text (GTK_LABEL(info->start_label), gettext (start_tree_string));
msg = g_strdup (_(start_tree_string));
else
{
gchar *label_string = NULL;
/* General Journal and search registers are always multi-line exported */
if ((info->export_type == XML_EXPORT_REGISTER) && (info->account == NULL))
label_string = g_strdup_printf (_(start_trans_common_string), _(start_trans__multi_string));
else
label_string = g_strdup_printf (_(start_trans_common_string), _(start_trans_simple_string));
msg = g_strdup_printf (_(start_trans_common_string), _(start_trans_multi_string));
gtk_label_set_text (GTK_LABEL(info->start_label), label_string);
g_free (label_string);
}
gtk_label_set_text (GTK_LABEL(info->start_label), msg);
g_free (msg);
/* Enable the Assistant Buttons */
gtk_assistant_set_page_complete (assistant, info->start_page, TRUE);
@ -693,7 +687,7 @@ csv_export_assistant_account_page_prepare (GtkAssistant *assistant,
CsvExportInfo *info = user_data;
/* Enable the "Next" Assistant Button if we have accounts */
if (info->csva.num_accounts > 0)
if (g_list_length(info->csva.account_list) > 0)
gtk_assistant_set_page_complete (assistant, info->account_page, TRUE);
else
gtk_assistant_set_page_complete (assistant, info->account_page, FALSE);
@ -728,10 +722,13 @@ csv_export_assistant_finish_page_prepare (GtkAssistant *assistant,
text = g_strdup_printf (gettext (finish_tree_string), info->file_name);
else
{
if ((info->export_type == XML_EXPORT_REGISTER) && (info->account == NULL))
if ((info->export_type == XML_EXPORT_REGISTER) &&
(g_list_length (info->csva.account_list) == 0))
text = g_strdup_printf (gettext (finish_trans_search_gl_string), info->file_name);
else
text = g_strdup_printf (gettext (finish_trans_string), info->file_name, info->csva.num_accounts);
text = g_strdup_printf (gettext (finish_trans_string),
info->file_name,
g_list_length (info->csva.account_list));
}
gtk_label_set_text (GTK_LABEL(info->finish_label), text);
g_free (text);
@ -803,6 +800,7 @@ csv_export_assistant_destroy_cb (GtkWidget *object, gpointer user_data)
{
CsvExportInfo *info = user_data;
gnc_unregister_gui_component_by_data (ASSISTANT_CSV_EXPORT_CM_CLASS, info);
g_list_free (info->csva.account_list);
g_free (info);
}
@ -880,7 +878,8 @@ csv_export_assistant_create (CsvExportInfo *info)
GtkWidget *chkbox = GTK_WIDGET(gtk_builder_get_object(builder, "simple_layout"));
// Don't provide simple export layout for search registers and General Journal
if ((info->export_type == XML_EXPORT_TREE) || (info->account == NULL))
if ((info->export_type == XML_EXPORT_TREE) ||
(g_list_length (info->csva.account_list) == 0))
gtk_widget_destroy (chkbox);
gtk_assistant_remove_page (GTK_ASSISTANT(info->assistant), 1); //remove accounts page
}
@ -1012,9 +1011,7 @@ gnc_file_csv_export_internal (CsvExportType export_type, Query *q, Account *acc)
if (q)
info->query = q;
if (acc)
info->account = acc;
if ((export_type == XML_EXPORT_REGISTER) && acc)
info->csva.num_accounts = 1;
info->csva.account_list = g_list_prepend(info->csva.account_list, acc);
csv_export_assistant_create (info);
gnc_register_gui_component (ASSISTANT_CSV_EXPORT_CM_CLASS,

View File

@ -30,6 +30,7 @@
#include "Account.h"
#include "Query.h"
#include <gtk/gtk.h>
typedef enum
{
@ -61,7 +62,6 @@ typedef struct
GtkWidget *select_button;
GtkWidget *num_acct_label;
GList *account_list;
int num_accounts;
GNCAccountType account_type;
} CsvExportAcc;
@ -71,10 +71,8 @@ typedef struct
CsvExportType export_type;
CsvExportDate csvd;
CsvExportAcc csva;
GList *trans_list;
Query *query;
Account *account;
GtkWidget *start_page;
GtkWidget *account_page;

View File

@ -26,9 +26,8 @@
*/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <stdbool.h>
#include "gnc-commodity.h"
#include "gnc-ui-util.h"
@ -56,23 +55,19 @@ static QofLogModule log_module = GNC_MOD_ASSISTANT;
/*******************************************************
* write_line_to_file
*
* write a text string to a file pointer, return TRUE if
* write a text string to a file pointer, return true if
* successful.
*******************************************************/
static
gboolean write_line_to_file (FILE *fh, char * line)
bool write_line_to_file (FILE *fh, char * line)
{
int len, written;
DEBUG("Account String: %s", line);
/* Write account line */
len = strlen (line);
written = fwrite (line, 1, len, fh);
int len = strlen (line);
int written = fwrite (line, 1, len, fh);
if (written != len)
return FALSE;
else
return TRUE;
return (written == len);
}
@ -84,25 +79,18 @@ gboolean write_line_to_file (FILE *fh, char * line)
static
gchar *csv_txn_test_field_string (CsvExportInfo *info, const gchar *string_in)
{
gboolean need_quote = FALSE;
gchar **parts;
gchar *string_parts;
gchar *string_out;
/* Check for " and then "" them */
parts = g_strsplit (string_in, "\"", -1);
string_parts = g_strjoinv ("\"\"", parts);
gchar **parts = g_strsplit (string_in, "\"", -1);
gchar *string_parts = g_strjoinv ("\"\"", parts);
g_strfreev (parts);
/* Check for separator string and \n and " in field,
if so quote field if not already quoted */
if (g_strrstr (string_parts, info->separator_str) != NULL)
need_quote = TRUE;
if (g_strrstr (string_parts, "\n") != NULL)
need_quote = TRUE;
if (g_strrstr (string_parts, "\"") != NULL)
need_quote = TRUE;
bool need_quote = !g_strrstr (string_parts, info->separator_str) ||
!g_strrstr (string_parts, "\n") ||
!g_strrstr (string_parts, "\"");
gchar *string_out;
if (!info->use_quotes && need_quote)
string_out = g_strconcat ("\"", string_parts, "\"", NULL);
else
@ -130,11 +118,8 @@ add_date (gchar *so_far, Transaction *trans, CsvExportInfo *info)
static gchar*
add_guid (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
gchar *result;
gchar *guid;
guid = guid_to_string (xaccTransGetGUID (trans));
result = g_strconcat (so_far, guid, info->mid_sep, NULL);
gchar *guid = guid_to_string (xaccTransGetGUID (trans));
gchar *result = g_strconcat (so_far, guid, info->mid_sep, NULL);
g_free (guid);
g_free (so_far);
return result;
@ -145,7 +130,6 @@ static gchar*
add_reconcile_date (gchar *so_far, Split *split, CsvExportInfo *info)
{
gchar *result;
if (xaccSplitGetReconcile (split) == YREC)
{
time64 t = xaccSplitGetDateReconciled (split);
@ -163,19 +147,16 @@ add_reconcile_date (gchar *so_far, Split *split, CsvExportInfo *info)
// Account Name short or Long
static gchar*
add_account_name (gchar *so_far, Split *split, gboolean full, CsvExportInfo *info)
add_account_name (gchar *so_far, Split *split, bool full, CsvExportInfo *info)
{
gchar *name = NULL;
gchar *conv;
gchar *result;
Account *account = xaccSplitGetAccount (split);
Account *account = xaccSplitGetAccount (split);
gchar *name = NULL;
if (full)
name = gnc_account_get_full_name (account);
else
name = g_strdup (xaccAccountGetName (account));
conv = csv_txn_test_field_string (info, name);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
gchar *conv = csv_txn_test_field_string (info, name);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (name);
g_free (conv);
g_free (so_far);
@ -186,13 +167,10 @@ add_account_name (gchar *so_far, Split *split, gboolean full, CsvExportInfo *inf
static gchar*
add_number (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
const gchar *num;
gchar *conv;
gchar *result;
num = xaccTransGetNum (trans) ? xaccTransGetNum (trans) : "" ;
conv = csv_txn_test_field_string (info, num);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
const gchar *num = xaccTransGetNum (trans);
num = num ? num : "";
gchar *conv = csv_txn_test_field_string (info, num);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -202,13 +180,10 @@ add_number (gchar *so_far, Transaction *trans, CsvExportInfo *info)
static gchar*
add_description (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
const gchar *desc;
gchar *conv;
gchar *result;
desc = xaccTransGetDescription (trans) ? xaccTransGetDescription (trans) : "" ;
conv = csv_txn_test_field_string (info, desc);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
const gchar *desc = xaccTransGetDescription (trans);
desc = desc ? desc : "";
gchar *conv = csv_txn_test_field_string (info, desc);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -218,13 +193,10 @@ add_description (gchar *so_far, Transaction *trans, CsvExportInfo *info)
static gchar*
add_notes (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
const gchar *notes;
gchar *conv;
gchar *result;
notes = xaccTransGetNotes (trans) ? xaccTransGetNotes (trans) : "" ;
conv = csv_txn_test_field_string (info, notes);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
const gchar *notes = xaccTransGetNotes (trans);
notes = notes ? notes : "" ;
gchar *conv = csv_txn_test_field_string (info, notes);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -234,18 +206,11 @@ add_notes (gchar *so_far, Transaction *trans, CsvExportInfo *info)
static gchar*
add_void_reason (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
gchar *result;
if (xaccTransGetVoidStatus (trans))
{
const gchar *void_reason = xaccTransGetVoidReason (trans);
gchar *conv = csv_txn_test_field_string (info, void_reason);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
}
else
result = g_strconcat (so_far, info->mid_sep, NULL);
const gchar *void_reason = xaccTransGetVoidReason (trans);
void_reason = void_reason ? void_reason : "";
gchar *conv = csv_txn_test_field_string (info, void_reason);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
}
@ -254,13 +219,10 @@ add_void_reason (gchar *so_far, Transaction *trans, CsvExportInfo *info)
static gchar*
add_memo (gchar *so_far, Split *split, CsvExportInfo *info)
{
const gchar *memo;
gchar *conv;
gchar *result;
memo = xaccSplitGetMemo (split) ? xaccSplitGetMemo (split) : "" ;
conv = csv_txn_test_field_string (info, memo);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
const gchar *memo = xaccSplitGetMemo (split);
memo = memo ? memo : "";
gchar *conv = csv_txn_test_field_string (info, memo);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -268,19 +230,16 @@ add_memo (gchar *so_far, Split *split, CsvExportInfo *info)
// Full Category Path or Not
static gchar*
add_category (gchar *so_far, Split *split, gboolean full, CsvExportInfo *info)
add_category (gchar *so_far, Split *split, bool full, CsvExportInfo *info)
{
gchar *cat;
gchar *conv;
gchar *result;
gchar *cat;
if (full)
cat = xaccSplitGetCorrAccountFullName (split);
else
cat = g_strdup(xaccSplitGetCorrAccountName (split));
conv = csv_txn_test_field_string (info, cat);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
gchar *conv = csv_txn_test_field_string (info, cat);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (cat);
g_free (conv);
g_free (so_far);
@ -303,13 +262,9 @@ add_action (gchar *so_far, Split *split, CsvExportInfo *info)
static gchar*
add_reconcile (gchar *so_far, Split *split, CsvExportInfo *info)
{
const gchar *recon;
gchar *conv;
gchar *result;
recon = gnc_get_reconcile_str (xaccSplitGetReconcile (split));
conv = csv_txn_test_field_string (info, recon);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
const gchar *recon = gnc_get_reconcile_str (xaccSplitGetReconcile (split));
gchar *conv = csv_txn_test_field_string (info, recon);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -319,14 +274,9 @@ add_reconcile (gchar *so_far, Split *split, CsvExportInfo *info)
static gchar*
add_commodity (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
const gchar *comm_m;
gchar *conv;
gchar *result;
comm_m = gnc_commodity_get_unique_name (xaccTransGetCurrency (trans));
conv = csv_txn_test_field_string (info, comm_m);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
const gchar *comm_m = gnc_commodity_get_unique_name (xaccTransGetCurrency (trans));
gchar *conv = csv_txn_test_field_string (info, comm_m);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -334,18 +284,34 @@ add_commodity (gchar *so_far, Transaction *trans, CsvExportInfo *info)
// Amount with Symbol or not
static gchar*
add_amount (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvExportInfo *info)
add_amount (gchar *so_far, Split *split, bool t_void, bool symbol, CsvExportInfo *info)
{
const gchar *amt;
gchar *conv;
gchar *result;
if (t_void)
amt = xaccPrintAmount (xaccSplitVoidFormerAmount (split), gnc_split_amount_print_info (split, symbol));
else
amt = xaccPrintAmount (xaccSplitGetAmount (split), gnc_split_amount_print_info (split, symbol));
conv = csv_txn_test_field_string (info, amt);
result = g_strconcat (so_far, conv, info->mid_sep, NULL);
gchar *conv = csv_txn_test_field_string (info, amt);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
}
// Value with Symbol or not
static gchar*
add_value (gchar *so_far, Split *split, bool t_void, bool symbol, CsvExportInfo *info)
{
Transaction *trans = xaccSplitGetParent(split);
gnc_commodity *tcurr = xaccTransGetCurrency (trans);
GNCPrintAmountInfo pai = gnc_commodity_print_info (tcurr, symbol);
const gchar *amt;
if (t_void)
amt = xaccPrintAmount (xaccSplitVoidFormerValue (split), pai);
else
amt = xaccPrintAmount (xaccSplitGetValue (split), pai);
gchar *conv = csv_txn_test_field_string (info, amt);
gchar *result = g_strconcat (so_far, conv, info->mid_sep, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -353,20 +319,16 @@ add_amount (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvEx
// Share Price / Conversion factor
static gchar*
add_rate (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info)
add_rate (gchar *so_far, Split *split, bool t_void, CsvExportInfo *info)
{
const gchar *amt;
gnc_commodity *curr = xaccAccountGetCommodity (xaccSplitGetAccount (split));
gchar *conv;
gchar *result;
const gchar *amt;
if (t_void)
amt = xaccPrintAmount (gnc_numeric_zero(), gnc_default_price_print_info (curr));
else
amt = xaccPrintAmount (xaccSplitGetSharePrice (split), gnc_default_price_print_info (curr));
conv = csv_txn_test_field_string (info, amt);
result = g_strconcat (so_far, conv, info->end_sep, EOLSTR, NULL);
gchar *conv = csv_txn_test_field_string (info, amt);
gchar *result = g_strconcat (so_far, conv, info->end_sep, EOLSTR, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -374,13 +336,10 @@ add_rate (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info)
// Share Price / Conversion factor
static gchar*
add_price (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info)
add_price (gchar *so_far, Split *split, bool t_void, CsvExportInfo *info)
{
const gchar *string_amount;
gnc_commodity *curr = xaccAccountGetCommodity (xaccSplitGetAccount (split));
gchar *conv;
gchar *result;
const gchar *string_amount;
if (t_void)
{
gnc_numeric cf = gnc_numeric_div (xaccSplitVoidFormerValue (split), xaccSplitVoidFormerAmount (split), GNC_DENOM_AUTO,
@ -390,8 +349,8 @@ add_price (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info)
else
string_amount = xaccPrintAmount (xaccSplitGetSharePrice (split), gnc_default_price_print_info (curr));
conv = csv_txn_test_field_string (info, string_amount);
result = g_strconcat (so_far, conv, info->end_sep, EOLSTR, NULL);
gchar *conv = csv_txn_test_field_string (info, string_amount);
gchar *result = g_strconcat (so_far, conv, info->end_sep, EOLSTR, NULL);
g_free (conv);
g_free (so_far);
return result;
@ -400,41 +359,29 @@ add_price (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info)
/******************************************************************************/
static gchar*
make_simple_trans_line (Account *acc, Transaction *trans, Split *split, CsvExportInfo *info)
make_simple_trans_line (Transaction *trans, Split *split, CsvExportInfo *info)
{
gboolean t_void = xaccTransGetVoidStatus (trans);
bool t_void = xaccTransGetVoidStatus (trans);
gchar *exp_line = g_strdup("");
exp_line = add_date (exp_line, trans, info);
exp_line = add_account_name (exp_line, split, TRUE, info);
exp_line = add_account_name (exp_line, split, true, info);
exp_line = add_number (exp_line, trans, info);
exp_line = add_description (exp_line, trans, info);
exp_line = add_category (exp_line, split, TRUE, info);
exp_line = add_category (exp_line, split, true, info);
exp_line = add_reconcile (exp_line, split, info);
exp_line = add_amount (exp_line, split, t_void, TRUE, info);
exp_line = add_amount (exp_line, split, t_void, FALSE, info);
exp_line = add_amount (exp_line, split, t_void, true, info);
exp_line = add_amount (exp_line, split, t_void, false, info);
exp_line = add_value (exp_line, split, t_void, true, info);
exp_line = add_value (exp_line, split, t_void, false, info);
exp_line = add_rate (exp_line, split, t_void, info);
return exp_line;
}
static gchar*
make_split_part (gchar* exp_line, Split *split, gboolean t_void, CsvExportInfo *info)
{
exp_line = add_action (exp_line, split, info);
exp_line = add_memo (exp_line, split, info);
exp_line = add_account_name (exp_line, split, TRUE, info);
exp_line = add_account_name (exp_line, split, FALSE, info);
exp_line = add_amount (exp_line, split, t_void, TRUE, info);
exp_line = add_amount (exp_line, split, t_void, FALSE, info);
exp_line = add_reconcile (exp_line, split, info);
exp_line = add_reconcile_date (exp_line, split, info);
exp_line = add_price (exp_line, split, t_void, info);
return exp_line;
}
static gchar*
make_complex_trans_line (Account *acc, Transaction *trans, Split *split, CsvExportInfo *info)
make_complex_trans_line (Transaction *trans, Split *split, CsvExportInfo *info)
{
// Transaction fields
gchar *exp_line = g_strdup("");
exp_line = add_date (exp_line, trans, info);
exp_line = add_guid (exp_line, trans, info);
@ -443,18 +390,22 @@ make_complex_trans_line (Account *acc, Transaction *trans, Split *split, CsvExpo
exp_line = add_notes (exp_line, trans, info);
exp_line = add_commodity (exp_line, trans, info);
exp_line = add_void_reason (exp_line, trans, info);
return make_split_part (exp_line, split, xaccTransGetVoidStatus (trans), info);
}
bool t_void = xaccTransGetVoidStatus (trans);
static gchar*
make_complex_split_line (Transaction *trans, Split *split, CsvExportInfo *info)
{
/* Pure split lines don't have any transaction information,
* so start with empty fields for all transaction columns.
*/
gchar *result = g_strconcat (info->end_sep, info->mid_sep, info->mid_sep, info->mid_sep,
info->mid_sep, info->mid_sep, info->mid_sep, info->mid_sep, NULL);
return make_split_part (result, split, xaccTransGetVoidStatus (trans), info);
//Split fields
exp_line = add_action (exp_line, split, info);
exp_line = add_memo (exp_line, split, info);
exp_line = add_account_name (exp_line, split, true, info);
exp_line = add_account_name (exp_line, split, false, info);
exp_line = add_amount (exp_line, split, t_void, true, info);
exp_line = add_amount (exp_line, split, t_void, false, info);
exp_line = add_value (exp_line, split, t_void, true, info);
exp_line = add_value (exp_line, split, t_void, false, info);
exp_line = add_reconcile (exp_line, split, info);
exp_line = add_reconcile_date (exp_line, split, info);
exp_line = add_price (exp_line, split, t_void, info);
return exp_line;
}
@ -467,105 +418,93 @@ make_complex_split_line (Transaction *trans, Split *split, CsvExportInfo *info)
static
void account_splits (CsvExportInfo *info, Account *acc, FILE *fh )
{
GSList *p1, *p2;
GList *splits;
QofBook *book;
bool is_trading_acct = acc && (xaccAccountGetType (acc) == ACCT_TYPE_TRADING);
// Setup the query for normal transaction export
if (info->export_type == XML_EXPORT_TRANS)
{
info->query = qof_query_create_for (GNC_ID_SPLIT);
book = gnc_get_current_book();
QofBook *book = gnc_get_current_book();
qof_query_set_book (info->query, book);
/* Sort by transaction date */
p1 = g_slist_prepend (NULL, TRANS_DATE_POSTED);
GSList *p1 = g_slist_prepend (NULL, TRANS_DATE_POSTED);
p1 = g_slist_prepend (p1, SPLIT_TRANS);
p2 = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
GSList *p2 = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
qof_query_set_sort_order (info->query, p1, p2, NULL);
xaccQueryAddSingleAccountMatch (info->query, acc, QOF_QUERY_AND);
xaccQueryAddDateMatchTT (info->query, TRUE, info->csvd.start_time, TRUE, info->csvd.end_time, QOF_QUERY_AND);
xaccQueryAddDateMatchTT (info->query, true, info->csvd.start_time, true, info->csvd.end_time, QOF_QUERY_AND);
}
/* Run the query */
for (splits = qof_query_run (info->query); splits; splits = splits->next)
GList *trans_list = NULL;
for (GList *splits = qof_query_run (info->query); splits; splits = splits->next)
{
Split *split;
Transaction *trans;
SplitList *s_list;
GList *node;
Split *t_split;
int nSplits;
int cnt;
gchar *line;
split = splits->data;
trans = xaccSplitGetParent (split);
nSplits = xaccTransCountSplits (trans);
s_list = xaccTransGetSplitList (trans);
Split *split = splits->data;
// Look for trans already exported in trans_list
if (g_list_find (info->trans_list, trans) != NULL)
Transaction *trans = xaccSplitGetParent (split);
if (g_list_find (trans_list, trans))
continue;
// Look for blank split
if (xaccSplitGetAccount (split) == NULL)
Account *split_acc = xaccSplitGetAccount (split);
if (!split_acc)
continue;
// Only export trading splits when exporting a trading account
if (!is_trading_acct &&
(xaccAccountGetType (split_acc) == ACCT_TYPE_TRADING))
continue;
// This will be a simple layout equivalent to a single line register view.
if (info->simple_layout)
{
line = make_simple_trans_line (acc, trans, split, info);
/* Write to file */
if (!write_line_to_file (fh, line))
{
info->failed = TRUE;
break;
}
// Write line in simple layout, equivalent to a single line register view
gchar *line = make_simple_trans_line (trans, split, info);
info->failed = !write_line_to_file (fh, line);
g_free (line);
if (info->failed)
break;
continue;
}
// Complex Transaction Line.
line = make_complex_trans_line (acc, trans, split, info);
/* Write to file */
if (!write_line_to_file (fh, line))
{
info->failed = TRUE;
break;
}
// Write complex Transaction Line.
gchar *line = make_complex_trans_line (trans, split, info);
info->failed = !write_line_to_file (fh, line);
g_free (line);
if (info->failed)
break;
/* Loop through the list of splits for the Transaction */
node = s_list;
cnt = 0;
while ((cnt < nSplits) && (info->failed == FALSE))
for (GList *node = xaccTransGetSplitList (trans); node; node = node->next)
{
t_split = node->data;
Split *t_split = node->data;
// base split is already written on the trans_line
if (split != t_split)
{
// Complex Split Line.
line = make_complex_split_line (trans, t_split, info);
if (split == t_split)
continue;
if (!write_line_to_file (fh, line))
info->failed = TRUE;
// Only export trading splits if exporting a trading account
Account *tsplit_acc = xaccSplitGetAccount (t_split);
if (!is_trading_acct &&
(xaccAccountGetType (tsplit_acc) == ACCT_TYPE_TRADING))
continue;
g_free (line);
}
cnt++;
node = node->next;
// Write complex Split Line.
line = make_complex_trans_line (trans, t_split, info);
info->failed = !write_line_to_file (fh, line);
g_free (line);
if (info->failed)
break;
}
info->trans_list = g_list_prepend (info->trans_list, trans); // add trans to trans_list
trans_list = g_list_prepend (trans_list, trans);
}
if (info->export_type == XML_EXPORT_TRANS)
qof_query_destroy (info->query);
g_list_free (splits);
g_list_free (trans_list);
}
@ -576,15 +515,10 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh )
*******************************************************/
void csv_transactions_export (CsvExportInfo *info)
{
FILE *fh;
Account *acc;
GList *ptr;
gboolean num_action = qof_book_use_split_action_for_num_field (gnc_get_current_book());
ENTER("");
DEBUG("File name is : %s", info->file_name);
info->failed = FALSE;
info->failed = false;
/* Set up separators */
if (info->use_quotes)
@ -599,68 +533,60 @@ void csv_transactions_export (CsvExportInfo *info)
}
/* Open File for writing */
fh = g_fopen (info->file_name, "w" );
if (fh != NULL)
FILE *fh = g_fopen (info->file_name, "w" );
if (!fh)
{
gchar *header;
int i;
info->failed = true;
return;
}
/* Header string */
if (info->simple_layout)
{
header = g_strconcat (info->end_sep,
/* Translators: The following symbols will build the *
* header line of exported CSV files: */
_("Date"), info->mid_sep, _("Account Name"),
info->mid_sep, (num_action ? _("Transaction Number") : _("Number")),
info->mid_sep, _("Description"), info->mid_sep, _("Full Category Path"),
info->mid_sep, _("Reconcile"), info->mid_sep, _("Amount With Sym"),
info->mid_sep, _("Amount Num."), info->mid_sep, _("Rate/Price"),
info->end_sep, EOLSTR, NULL);
}
else
{
header = g_strconcat (info->end_sep, _("Date"), info->mid_sep, _("Transaction ID"),
info->mid_sep, (num_action ? _("Transaction Number") : _("Number")),
info->mid_sep, _("Description"), info->mid_sep, _("Notes"),
info->mid_sep, _("Commodity/Currency"), info->mid_sep, _("Void Reason"),
info->mid_sep, (num_action ? _("Number/Action") : _("Action")), info->mid_sep, _("Memo"),
info->mid_sep, _("Full Account Name"), info->mid_sep, _("Account Name"),
info->mid_sep, _("Amount With Sym"), info->mid_sep, _("Amount Num."),
info->mid_sep, _("Reconcile"), info->mid_sep, _("Reconcile Date"), info->mid_sep, _("Rate/Price"),
info->end_sep, EOLSTR, NULL);
}
DEBUG("Header String: %s", header);
/* Write header line */
if (!write_line_to_file (fh, header))
{
info->failed = TRUE;
g_free (header);
return;
}
g_free (header);
if (info->export_type == XML_EXPORT_TRANS)
{
/* Go through list of accounts */
for (ptr = info->csva.account_list, i = 0; ptr; ptr = g_list_next(ptr), i++)
{
acc = ptr->data;
DEBUG("Account being processed is : %s", xaccAccountGetName (acc));
account_splits (info, acc, fh);
}
g_list_free (info->csva.account_list);
}
else
account_splits (info, info->account, fh);
g_list_free (info->trans_list); // free trans_list
gchar *header;
bool num_action = qof_book_use_split_action_for_num_field (gnc_get_current_book());
/* Header string */
if (info->simple_layout)
{
header = g_strconcat (info->end_sep,
/* Translators: The following symbols will build the *
* header line of exported CSV files: */
_("Date"), info->mid_sep, _("Account Name"),
info->mid_sep, (num_action ? _("Transaction Number") : _("Number")),
info->mid_sep, _("Description"), info->mid_sep, _("Full Category Path"),
info->mid_sep, _("Reconcile"),
info->mid_sep, _("Amount With Sym"), info->mid_sep, _("Amount Num."),
info->mid_sep, _("Value With Sym"), info->mid_sep, _("Value Num."),
info->mid_sep, _("Rate/Price"),
info->end_sep, EOLSTR, NULL);
}
else
info->failed = TRUE;
if (fh)
fclose (fh);
{
header = g_strconcat (info->end_sep, _("Date"), info->mid_sep, _("Transaction ID"),
info->mid_sep, (num_action ? _("Transaction Number") : _("Number")),
info->mid_sep, _("Description"), info->mid_sep, _("Notes"),
info->mid_sep, _("Commodity/Currency"), info->mid_sep, _("Void Reason"),
info->mid_sep, (num_action ? _("Number/Action") : _("Action")), info->mid_sep, _("Memo"),
info->mid_sep, _("Full Account Name"), info->mid_sep, _("Account Name"),
info->mid_sep, _("Amount With Sym"), info->mid_sep, _("Amount Num."),
info->mid_sep, _("Value With Sym"), info->mid_sep, _("Value Num."),
info->mid_sep, _("Reconcile"), info->mid_sep, _("Reconcile Date"), info->mid_sep, _("Rate/Price"),
info->end_sep, EOLSTR, NULL);
}
DEBUG("Header String: %s", header);
/* Write header line */
info->failed = !write_line_to_file (fh, header);
g_free (header);
if (info->failed)
return;
/* Go through list of accounts */
for (GList *ptr = info->csva.account_list; ptr; ptr = g_list_next(ptr))
{
Account *acc = ptr->data;
DEBUG("Account being processed is : %s", xaccAccountGetName (acc));
account_splits (info, acc, fh);
}
fclose (fh);
LEAVE("");
}

View File

@ -758,15 +758,15 @@ void GncPreSplit::create_split (std::shared_ptr<DraftTransaction> draft_trans)
auto value = GncNumeric();
auto trans_curr = xaccTransGetCurrency(draft_trans->trans);
auto acct_comm = xaccAccountGetCommodity(account);
if (gnc_commodity_equiv(trans_curr, acct_comm))
value = amount;
else if (m_value || m_value_neg)
if (m_value || m_value_neg)
{
if (m_value)
value += *m_value;
if (m_value_neg)
value -= *m_value_neg;
}
else if (gnc_commodity_equiv(trans_curr, acct_comm))
value = amount;
else if (tamount)
value = -*tamount;
else if (m_price)

View File

@ -90,6 +90,8 @@ static std::shared_ptr<CsvTransImpSettings> create_int_gnc_exp_preset(void)
GncTransPropType::NONE,
GncTransPropType::NONE,
GncTransPropType::AMOUNT,
GncTransPropType::NONE,
GncTransPropType::VALUE,
GncTransPropType::REC_STATE,
GncTransPropType::REC_DATE,
GncTransPropType::PRICE
@ -97,6 +99,40 @@ static std::shared_ptr<CsvTransImpSettings> create_int_gnc_exp_preset(void)
return preset;
}
static std::shared_ptr<CsvTransImpSettings> create_int_gnc_exp_4_preset(void)
{
auto preset = std::make_shared<CsvTransImpSettings>();
preset->m_name = get_gnc_exp_4();
preset->m_skip_start_lines = 1;
preset->m_multi_split = true;
/* FIXME date and currency format should still be aligned with export format!
* That's currently hard to do, because the export uses whatever the user
* had set as global preference.
* preset->date_active = 0;
* preset->currency_active = 0;
*/
preset->m_column_types = {
GncTransPropType::DATE,
GncTransPropType::UNIQUE_ID,
GncTransPropType::NUM,
GncTransPropType::DESCRIPTION,
GncTransPropType::NOTES,
GncTransPropType::COMMODITY,
GncTransPropType::VOID_REASON,
GncTransPropType::ACTION,
GncTransPropType::MEMO,
GncTransPropType::ACCOUNT,
GncTransPropType::NONE,
GncTransPropType::NONE,
GncTransPropType::AMOUNT,
GncTransPropType::REC_STATE,
GncTransPropType::REC_DATE,
GncTransPropType::PRICE
};
return preset;
}
/**************************************************
* find
*
@ -134,6 +170,7 @@ const preset_vec_trans& get_import_presets_trans (void)
/* Start with the internally generated ones */
presets_trans.push_back(create_int_no_preset());
presets_trans.push_back(create_int_gnc_exp_preset());
presets_trans.push_back(create_int_gnc_exp_4_preset());
/* Then add all the ones we found in the state file */
for (auto preset_name : preset_names)

View File

@ -45,6 +45,7 @@
const std::string csv_group_prefix{"CSV-"};
const std::string no_settings{N_("No Settings")};
const std::string gnc_exp{N_("GnuCash Export Format")};
const std::string gnc_exp_4{N_("GnuCash Export Format (4.x and older)")};
#define CSV_NAME "Name"
#define CSV_FORMAT "CsvFormat"
@ -107,6 +108,11 @@ std::string get_gnc_exp (void)
return gnc_exp;
}
std::string get_gnc_exp_4 (void)
{
return gnc_exp_4;
}
/**************************************************
* load_common
*

View File

@ -90,6 +90,7 @@ protected:
std::string get_no_settings (void);
std::string get_gnc_exp (void);
std::string get_gnc_exp_4 (void);
/** Check whether name can be used as a preset name.
* The names of the internal presets are considered reserved.