From 9e1268d9347f9375865a5f52becb9d52f23eb3ad Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 10:40:42 +0100 Subject: [PATCH 01/10] Bug 798600 - CSV import of multi-split security transactions fails to load capital gain - part 1 Transactions with capital gains processing can have splits in transaction currency with a zero amount and a non-zero value. To properly import those, prefer the value column even if transaction currency equals account commodity. Previous (wrong) assumption was that in case of a same-currency split, the amount would always be the value. --- gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp index 3c1496bcde..354d2b6c89 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp @@ -758,15 +758,15 @@ void GncPreSplit::create_split (std::shared_ptr 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) From 003f379d88785af7cb181ac197bf058d52641b45 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 11:43:46 +0100 Subject: [PATCH 02/10] Bug 798600 - CSV import of multi-split security transactions fails to load capital gain - part 2 Update csv transaction export format to include split values. In the csv importer the 'GnuCash Export Format' option will now include values. For compatibility with filex exported from older gnucash versions the previous preset is still available under the name 'GnuCash Export Format (4.x and older)'. --- .../csv-exp/csv-transactions-export.c | 33 ++++++++++++++++- .../csv-imp/gnc-imp-settings-csv-tx.cpp | 37 +++++++++++++++++++ .../csv-imp/gnc-imp-settings-csv.cpp | 6 +++ .../csv-imp/gnc-imp-settings-csv.hpp | 1 + 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index f709dc4433..ab177ab7e6 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -351,6 +351,28 @@ add_amount (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvEx return result; } +// Value with Symbol or not +static gchar* +add_value (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvExportInfo *info) +{ + const gchar *amt; + gchar *conv; + gchar *result; + + Transaction *trans = xaccSplitGetParent(split); + gnc_commodity *tcurr = xaccTransGetCurrency (trans); + GNCPrintAmountInfo pai = gnc_commodity_print_info (tcurr, symbol); + if (t_void) + amt = xaccPrintAmount (xaccSplitVoidFormerValue (split), pai); + else + amt = xaccPrintAmount (xaccSplitGetValue (split), pai); + conv = csv_txn_test_field_string (info, amt); + result = g_strconcat (so_far, conv, info->mid_sep, NULL); + g_free (conv); + g_free (so_far); + return result; +} + // Share Price / Conversion factor static gchar* add_rate (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info) @@ -413,6 +435,8 @@ make_simple_trans_line (Account *acc, Transaction *trans, Split *split, CsvExpor 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_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; } @@ -426,6 +450,8 @@ make_split_part (gchar* exp_line, Split *split, gboolean t_void, CsvExportInfo * 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); @@ -614,8 +640,10 @@ void csv_transactions_export (CsvExportInfo *info) _("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->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 @@ -627,6 +655,7 @@ void csv_transactions_export (CsvExportInfo *info) 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); } diff --git a/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp index a2e503704a..151ce91166 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp @@ -90,6 +90,8 @@ static std::shared_ptr 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 create_int_gnc_exp_preset(void) return preset; } +static std::shared_ptr create_int_gnc_exp_4_preset(void) +{ + auto preset = std::make_shared(); + 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) diff --git a/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp b/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp index 7bd8e44324..ae5e6f396f 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp +++ b/gnucash/import-export/csv-imp/gnc-imp-settings-csv.cpp @@ -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 * diff --git a/gnucash/import-export/csv-imp/gnc-imp-settings-csv.hpp b/gnucash/import-export/csv-imp/gnc-imp-settings-csv.hpp index bb344ce39c..92a277ba8f 100644 --- a/gnucash/import-export/csv-imp/gnc-imp-settings-csv.hpp +++ b/gnucash/import-export/csv-imp/gnc-imp-settings-csv.hpp @@ -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. From c6a93903b3495a124e7d8515fb7effb34db79fa8 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 12:45:56 +0100 Subject: [PATCH 03/10] CsvTransExport - generic code cleanup - declare variables on use - more concise tests and loops --- .../csv-exp/csv-transactions-export.c | 92 +++++++------------ 1 file changed, 34 insertions(+), 58 deletions(-) diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index ab177ab7e6..13d7b5a07a 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "gnc-commodity.h" #include "gnc-ui-util.h" @@ -422,7 +423,7 @@ 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); @@ -459,7 +460,7 @@ make_split_part (gchar* exp_line, Split *split, gboolean t_void, CsvExportInfo * } static gchar* -make_complex_trans_line (Account *acc, Transaction *trans, Split *split, CsvExportInfo *info) +make_complex_trans_line (Transaction *trans, Split *split, CsvExportInfo *info) { gchar *exp_line = g_strdup(""); exp_line = add_date (exp_line, trans, info); @@ -493,21 +494,18 @@ 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; // 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); @@ -515,83 +513,61 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) } /* Run the query */ - for (splits = qof_query_run (info->query); splits; splits = splits->next) + 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 (info->trans_list, trans)) continue; // Look for blank split - if (xaccSplitGetAccount (split) == NULL) + Account *split_acc = xaccSplitGetAccount (split); + if (!split_acc) 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; - g_free (line); - } - - cnt++; - node = node->next; + // Write complex Split Line. + line = make_complex_split_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 } + if (info->export_type == XML_EXPORT_TRANS) qof_query_destroy (info->query); - g_list_free (splits); } From 9df059e9a5f60d0cf99a937940e88977c7b0e4c8 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 14:52:59 +0100 Subject: [PATCH 04/10] CsvTransExport - omit trading splits unless exporting from a trading account --- .../import-export/csv-exp/csv-transactions-export.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index 13d7b5a07a..ed8345bdd9 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -494,6 +494,7 @@ make_complex_split_line (Transaction *trans, Split *split, CsvExportInfo *info) static void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) { + bool is_trading_acct = acc && (xaccAccountGetType (acc) == ACCT_TYPE_TRADING); // Setup the query for normal transaction export if (info->export_type == XML_EXPORT_TRANS) @@ -527,6 +528,11 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) if (!split_acc) continue; + // Only export trading splits when exporting a trading account + if (!is_trading_acct && + (xaccAccountGetType (split_acc) == ACCT_TYPE_TRADING)) + continue; + if (info->simple_layout) { // Write line in simple layout, equivalent to a single line register view @@ -555,6 +561,11 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) if (split == t_split) continue; + // 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; // Write complex Split Line. line = make_complex_split_line (trans, t_split, info); From be0579dc0cde794ffef05316011c399d105d8f22 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 16:40:48 +0100 Subject: [PATCH 05/10] CsvTransExport - more generic code cleanup - declare variables on use - more concise tests and loops - drop unused includes - gboolean->bool --- .../csv-exp/assistant-csv-export.h | 1 + .../csv-exp/csv-transactions-export.c | 340 +++++++----------- 2 files changed, 135 insertions(+), 206 deletions(-) diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.h b/gnucash/import-export/csv-exp/assistant-csv-export.h index b0cf99cbe7..9cb1f9af0f 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.h +++ b/gnucash/import-export/csv-exp/assistant-csv-export.h @@ -30,6 +30,7 @@ #include "Account.h" #include "Query.h" +#include typedef enum { diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index ed8345bdd9..75ea0beed5 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -26,8 +26,6 @@ */ #include "config.h" -#include -#include #include #include @@ -57,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); } @@ -85,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 @@ -131,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; @@ -146,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); @@ -164,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); @@ -187,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; @@ -203,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; @@ -219,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; @@ -235,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; } @@ -255,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; @@ -269,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); @@ -304,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; @@ -320,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; @@ -335,18 +284,15 @@ 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; @@ -354,21 +300,18 @@ add_amount (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvEx // Value with Symbol or not static gchar* -add_value (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvExportInfo *info) +add_value (gchar *so_far, Split *split, bool t_void, bool symbol, CsvExportInfo *info) { - const gchar *amt; - gchar *conv; - gchar *result; - 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); - 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; @@ -376,20 +319,16 @@ add_value (gchar *so_far, Split *split, gboolean t_void, gboolean symbol, CsvExp // 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; @@ -397,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, @@ -413,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; @@ -425,34 +361,34 @@ add_price (gchar *so_far, Split *split, gboolean t_void, CsvExportInfo *info) static gchar* 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_value (exp_line, split, t_void, TRUE, info); - exp_line = add_value (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) +make_split_part (gchar* exp_line, Split *split, bool 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_value (exp_line, split, t_void, TRUE, info); - exp_line = add_value (exp_line, split, t_void, FALSE, 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); @@ -510,7 +446,7 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) 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 */ @@ -589,15 +525,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) @@ -612,71 +543,68 @@ 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, _("Value With Sym"), info->mid_sep, _("Value 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, _("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); + 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 + { + 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 */ - if (!write_line_to_file (fh, header)) - { - info->failed = TRUE; - g_free (header); - return; - } - g_free (header); + /* Write header line */ + info->failed = !write_line_to_file (fh, header); + g_free (header); + if (info->failed) + return; - if (info->export_type == XML_EXPORT_TRANS) + if (info->export_type == XML_EXPORT_TRANS) + { + /* Go through list of accounts */ + for (GList *ptr = info->csva.account_list; ptr; ptr = g_list_next(ptr)) { - /* 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); + Account *acc = ptr->data; + DEBUG("Account being processed is : %s", xaccAccountGetName (acc)); + account_splits (info, acc, fh); } - else - account_splits (info, info->account, fh); - - g_list_free (info->trans_list); // free trans_list + g_list_free (info->csva.account_list); } else - info->failed = TRUE; - if (fh) - fclose (fh); + account_splits (info, info->account, fh); + + g_list_free (info->trans_list); // free trans_list + + fclose (fh); LEAVE(""); } From aa0a68fd1c67c0e0aed21e2193ecf35107745dcc Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 16:47:18 +0100 Subject: [PATCH 06/10] CsvTransExp - repeat transaction details on every line in multi-line mode The GnuCash Csv Importer can deal with both cases, but there has been user feedback that the format with only the first line displaying transaction details is confusing and/or not readily usable in external tools. --- .../csv-exp/csv-transactions-export.c | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index 75ea0beed5..2244a259c3 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -379,8 +379,20 @@ make_simple_trans_line (Transaction *trans, Split *split, CsvExportInfo *info) } static gchar* -make_split_part (gchar* exp_line, Split *split, bool t_void, 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); + exp_line = add_number (exp_line, trans, info); + exp_line = add_description (exp_line, trans, info); + 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); + bool t_void = xaccTransGetVoidStatus (trans); + + //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); @@ -392,32 +404,8 @@ make_split_part (gchar* exp_line, Split *split, bool t_void, CsvExportInfo *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 (Transaction *trans, Split *split, CsvExportInfo *info) -{ - gchar *exp_line = g_strdup(""); - exp_line = add_date (exp_line, trans, info); - exp_line = add_guid (exp_line, trans, info); - exp_line = add_number (exp_line, trans, info); - exp_line = add_description (exp_line, trans, info); - 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); -} - -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); + return exp_line; } @@ -504,7 +492,7 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) continue; // Write complex Split Line. - line = make_complex_split_line (trans, t_split, info); + line = make_complex_trans_line (trans, t_split, info); info->failed = !write_line_to_file (fh, line); g_free (line); if (info->failed) From 545f27c5500a4bb3e1068c629c3ed89251ce9704 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 16:52:13 +0100 Subject: [PATCH 07/10] CsvTransExp - limit scope of variable to actual use --- gnucash/import-export/csv-exp/assistant-csv-export.c | 1 - gnucash/import-export/csv-exp/assistant-csv-export.h | 1 - gnucash/import-export/csv-exp/csv-transactions-export.c | 8 ++++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.c b/gnucash/import-export/csv-exp/assistant-csv-export.c index 72c4d565e9..0e42719ad7 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.c +++ b/gnucash/import-export/csv-exp/assistant-csv-export.c @@ -303,7 +303,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); diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.h b/gnucash/import-export/csv-exp/assistant-csv-export.h index 9cb1f9af0f..bb52e4423a 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.h +++ b/gnucash/import-export/csv-exp/assistant-csv-export.h @@ -72,7 +72,6 @@ typedef struct CsvExportType export_type; CsvExportDate csvd; CsvExportAcc csva; - GList *trans_list; Query *query; Account *account; diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index 2244a259c3..82d998235b 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -438,13 +438,14 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) } /* Run the query */ + GList *trans_list = NULL; for (GList *splits = qof_query_run (info->query); splits; splits = splits->next) { Split *split = splits->data; // Look for trans already exported in trans_list Transaction *trans = xaccSplitGetParent (split); - if (g_list_find (info->trans_list, trans)) + if (g_list_find (trans_list, trans)) continue; // Look for blank split @@ -498,11 +499,12 @@ void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) 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 (trans_list); } @@ -590,8 +592,6 @@ void csv_transactions_export (CsvExportInfo *info) else account_splits (info, info->account, fh); - g_list_free (info->trans_list); // free trans_list - fclose (fh); LEAVE(""); } From 1d971c157887e81afc2720edec8f90a0e6cfa6ff Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 17:24:11 +0100 Subject: [PATCH 08/10] CsvTransExp - remove redundant counter num_accounts Simply use length of account list instead --- .../csv-exp/assistant-csv-export.c | 27 ++++++++++--------- .../csv-exp/assistant-csv-export.h | 1 - .../csv-exp/csv-transactions-export.c | 16 ++++------- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.c b/gnucash/import-export/csv-exp/assistant-csv-export.c index 0e42719ad7..d2f11b44de 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.c +++ b/gnucash/import-export/csv-exp/assistant-csv-export.c @@ -378,7 +378,7 @@ show_acct_type_accounts (CsvExportInfo *info) * * update the account tree *******************************************************/ -static int +static void update_accounts_tree (CsvExportInfo *info) { GncTreeViewAccount *tree; @@ -396,8 +396,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; } @@ -410,22 +408,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); } @@ -692,7 +690,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); @@ -730,7 +728,9 @@ csv_export_assistant_finish_page_prepare (GtkAssistant *assistant, if ((info->export_type == XML_EXPORT_REGISTER) && (info->account == NULL)) 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); @@ -802,6 +802,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); } @@ -1013,7 +1014,7 @@ gnc_file_csv_export_internal (CsvExportType export_type, Query *q, Account *acc) 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, diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.h b/gnucash/import-export/csv-exp/assistant-csv-export.h index bb52e4423a..7079b49284 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.h +++ b/gnucash/import-export/csv-exp/assistant-csv-export.h @@ -62,7 +62,6 @@ typedef struct GtkWidget *select_button; GtkWidget *num_acct_label; GList *account_list; - int num_accounts; GNCAccountType account_type; } CsvExportAcc; diff --git a/gnucash/import-export/csv-exp/csv-transactions-export.c b/gnucash/import-export/csv-exp/csv-transactions-export.c index 82d998235b..20dde3dcb6 100644 --- a/gnucash/import-export/csv-exp/csv-transactions-export.c +++ b/gnucash/import-export/csv-exp/csv-transactions-export.c @@ -578,19 +578,13 @@ void csv_transactions_export (CsvExportInfo *info) if (info->failed) return; - if (info->export_type == XML_EXPORT_TRANS) + /* Go through list of accounts */ + for (GList *ptr = info->csva.account_list; ptr; ptr = g_list_next(ptr)) { - /* 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); - } - g_list_free (info->csva.account_list); + Account *acc = ptr->data; + DEBUG("Account being processed is : %s", xaccAccountGetName (acc)); + account_splits (info, acc, fh); } - else - account_splits (info, info->account, fh); fclose (fh); LEAVE(""); From dae07fba993c21b55607404a99d890e91c96b1dc Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 17:32:52 +0100 Subject: [PATCH 09/10] CsvTransExp - treat single account as list of accounts with one element That allows to remove another tracking variable. --- .../import-export/csv-exp/assistant-csv-export.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.c b/gnucash/import-export/csv-exp/assistant-csv-export.c index d2f11b44de..1082445a7c 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.c +++ b/gnucash/import-export/csv-exp/assistant-csv-export.c @@ -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."); @@ -669,8 +669,9 @@ csv_export_assistant_start_page_prepare (GtkAssistant *assistant, { 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)); + if ((info->export_type == XML_EXPORT_REGISTER) && + (g_list_length (info->csva.account_list) == 0)) + 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)); @@ -725,7 +726,8 @@ 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), @@ -880,7 +882,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,8 +1015,6 @@ 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.account_list = g_list_prepend(info->csva.account_list, acc); csv_export_assistant_create (info); From 6993fed22974d2465b8507c40b728bb526a7da0b Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 14 Feb 2023 17:58:05 +0100 Subject: [PATCH 10/10] CsvTransExp - fix info message to match state of simple format button --- .../csv-exp/assistant-csv-export.c | 32 ++++++++----------- .../csv-exp/assistant-csv-export.h | 1 - 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.c b/gnucash/import-export/csv-exp/assistant-csv-export.c index 1082445a7c..d71b17a443 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.c +++ b/gnucash/import-export/csv-exp/assistant-csv-export.c @@ -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); } /******************************************************* @@ -659,25 +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) && - (g_list_length (info->csva.account_list) == 0)) - 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); diff --git a/gnucash/import-export/csv-exp/assistant-csv-export.h b/gnucash/import-export/csv-exp/assistant-csv-export.h index 7079b49284..a2cf8f299c 100644 --- a/gnucash/import-export/csv-exp/assistant-csv-export.h +++ b/gnucash/import-export/csv-exp/assistant-csv-export.h @@ -73,7 +73,6 @@ typedef struct CsvExportAcc csva; Query *query; - Account *account; GtkWidget *start_page; GtkWidget *account_page;