]>
Dogcows Code - chaz/homebank/blob - src/hb-import-csv.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "hb-import.h"
26 /****************************************************************************/
28 /****************************************************************************/
37 /* our global datas */
38 extern struct HomeBank
*GLOBALS
;
39 extern struct Preferences
*PREFS
;
42 static gint csvtype
[7] = {
54 static gchar
*hb_csv_strndup (gchar
*str
, gsize n
)
61 new_str
= g_new (gchar
, n
+ 1);
69 strncpy (new_str
, str
, n
);
73 twoquote
= strstr(new_str
, "\"\"");
75 strcpy (twoquote
, twoquote
+1);
77 //todo: replace & < > ' " ??
87 static gchar
*hb_csv_find_delimiter(gchar
*string
, gchar delimiter
)
90 gboolean enclosed
= FALSE
;
94 if( (*s
== delimiter
) && (enclosed
== FALSE
) )
109 static gboolean
hb_csv_row_valid(gchar
**str_array
, guint nbcolumns
, gint
*csvtype
)
111 gboolean valid
= TRUE
;
116 gchar
*type
[5] = { "string", "date", "int", "double" };
120 DB( g_print("\n** hb_string_csv_valid: init %d\n", valid
) );
122 DB( g_print(" -> length %d, nbcolumns %d\n", g_strv_length( str_array
), nbcolumns
) );
124 if( g_strv_length( str_array
) != nbcolumns
)
130 for(i
=0;i
<nbcolumns
;i
++)
133 lasttype
= csvtype
[i
];
138 DB( g_print(" -> fail on column %d, type: %s\n", i
, type
[lasttype
]) );
142 DB( g_print(" -> control column %d, type: %d, valid: %d '%s'\n", i
, lasttype
, valid
, str_array
[i
]) );
147 valid
= hb_string_isdate(str_array
[i
]);
150 valid
= hb_string_isprint(str_array
[i
]);
153 valid
= hb_string_isdigit(str_array
[i
]);
157 //todo: use strtod (to take care or . or ,)
158 g_ascii_strtod(str_array
[i
], NULL
);
159 //todo : see this errno
162 DB( g_print("errno: %d\n", errno
) );
171 DB( g_print(" --> return %d\n", valid
) );
177 static gchar
**hb_csv_row_get(gchar
*string
, gchar delimiter
, gint max_tokens
)
179 GSList
*string_list
= NULL
, *slist
;
180 gchar
**str_array
, *s
;
184 g_return_val_if_fail (string
!= NULL
, NULL
);
185 g_return_val_if_fail (delimiter
!= '\0', NULL
);
188 max_tokens
= G_MAXINT
;
191 s
= hb_csv_find_delimiter (remainder
, delimiter
);
194 while (--max_tokens
&& s
&& *s
!= '\0')
199 string_list
= g_slist_prepend (string_list
, hb_csv_strndup (remainder
, len
));
200 DB( g_print(" stored=[%s]\n", (gchar
*)string_list
->data
) );
204 s
= hb_csv_find_delimiter (remainder
, delimiter
);
213 string_list
= g_slist_prepend (string_list
, hb_csv_strndup (remainder
, len
));
214 DB( g_print(" stored=[%s]\n", (gchar
*)string_list
->data
) );
217 str_array
= g_new (gchar
*, n
+ 1);
219 str_array
[n
--] = NULL
;
220 for (slist
= string_list
; slist
; slist
= slist
->next
)
221 str_array
[n
--] = slist
->data
;
223 g_slist_free (string_list
);
229 static gchar
hb_csv_get_separator(void)
231 static const gchar sep
[] = PRF_DTEX_CSVSEP_BUFFER
;
232 return sep
[PREFS
->dtex_csvsep
];
236 gboolean
hb_csv_test_line(gchar
*rawline
)
240 gboolean isvalid
= FALSE
;
242 hb_string_strip_crlf(rawline
);
243 sep
= hb_csv_get_separator();
244 str_array
= hb_csv_row_get(rawline
, sep
, 8);
245 isvalid
= hb_csv_row_valid(str_array
, 8, csvtype
);
247 g_strfreev (str_array
);
253 GList
*homebank_csv_import(ImportContext
*ictx
, GenFile
*genfile
)
256 //GList *list = NULL;
258 DB( g_print("\n[import] homebank csv\n") );
260 io
= g_io_channel_new_file(genfile
->filepath
, "r", NULL
);
274 newacc
= hb_import_gen_acc_get_next(ictx
, FILETYPE_CSV_HB
, NULL
, NULL
);
276 if( genfile
->encoding
!= NULL
)
278 g_io_channel_set_encoding(io
, genfile
->encoding
, NULL
);
283 io_stat
= g_io_channel_read_line(io
, &tmpstr
, &length
, NULL
, &err
);
284 if( io_stat
== G_IO_STATUS_EOF
)
286 if( io_stat
== G_IO_STATUS_ERROR
)
288 DB (g_print(" + ERROR %s\n",err
->message
));
291 if( io_stat
== G_IO_STATUS_NORMAL
)
293 if( *tmpstr
!= '\0' )
299 sep
= hb_csv_get_separator();
301 hb_string_strip_crlf(tmpstr
);
302 str_array
= hb_csv_row_get(tmpstr
, sep
, 8);
304 // 0:date; 1:paymode; 2:info; 3:payee, 4:wording; 5:amount; 6:category; 7:tags
305 isvalid
= hb_csv_row_valid(str_array
, 8, csvtype
);
307 DB( g_print("\n (row-%04d) ->|%s|<-\n", count
, tmpstr
) );
308 DB( g_print(" valid %d, '%s'\n", isvalid
, tmpstr
) );
312 g_warning ("csv parse: line %d, invalid column count or data", count
);
314 //todo log line in error to report user
318 GenTxn
*newope
= da_gen_txn_malloc();;
320 DB( g_print(" adding txn\n" ) );
322 /* convert to generic transaction */
323 newope
->date
= g_strdup(str_array
[0]);
324 newope
->paymode
= atoi(str_array
[1]);
325 //todo: reinforce controls here
326 // csv file are standalone, so no way to link a target txn
327 //added 5.1.8 forbid to import 5=internal xfer
328 if(newope
->paymode
== PAYMODE_INTXFER
)
329 newope
->paymode
= PAYMODE_XFER
;
330 newope
->rawinfo
= g_strdup(str_array
[2]);
331 newope
->rawpayee
= g_strdup(g_strstrip(str_array
[3]));
332 newope
->rawmemo
= g_strdup(str_array
[4]);
333 newope
->amount
= hb_qif_parser_get_amount(str_array
[5]);
334 newope
->category
= g_strdup(g_strstrip(str_array
[6]));
335 newope
->tags
= g_strdup(str_array
[7]);
336 newope
->account
= g_strdup(newacc
->name
);
338 /* todo: move this eval date valid */
339 //guint32 juliantmp = hb_date_get_julian(str_array[0], ictx->datefmt);
340 ///if( juliantmp == 0 )
341 // ictx->cnt_err_date++;
344 DB( g_print(" storing %s : %s : %s :%s : %s : %s : %s : %s\n",
345 str_array[0], str_array[1], str_array[2],
346 str_array[3], str_array[4], str_array[5],
347 str_array[6], str_array[7]
351 da_gen_txn_append(ictx
, newope
);
353 g_strfreev (str_array
);
360 g_io_channel_unref (io
);
363 ui_dialog_msg_infoerror(data->window, error > 0 ? GTK_MESSAGE_ERROR : GTK_MESSAGE_INFO,
364 _("Transaction CSV import result"),
365 _("%d transactions inserted\n%d errors in the file"),
371 return ictx
->gen_lst_txn
;
This page took 0.051499 seconds and 5 git commands to generate.