mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
more improvements to the quicken file parsing code
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@166 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
a065747f21
commit
19e97d3486
@ -49,6 +49,8 @@ actionBox (Widget parent)
|
|||||||
AddPopBoxMenuItem (popGUI, "STCG");
|
AddPopBoxMenuItem (popGUI, "STCG");
|
||||||
AddPopBoxMenuItem (popGUI, "Dist");
|
AddPopBoxMenuItem (popGUI, "Dist");
|
||||||
AddPopBoxMenuItem (popGUI, "Split");
|
AddPopBoxMenuItem (popGUI, "Split");
|
||||||
|
AddPopBoxMenuItem (popGUI, "Deposit");
|
||||||
|
AddPopBoxMenuItem (popGUI, "Withdraw");
|
||||||
|
|
||||||
return popGUI;
|
return popGUI;
|
||||||
}
|
}
|
||||||
|
223
src/QIFIO.c
223
src/QIFIO.c
@ -220,7 +220,7 @@ void xaccParseQIFDate (Date * dat, char * str)
|
|||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
* xaccParseQIFAmount *
|
* xaccParseQIFAmount *
|
||||||
* parses dollar ammount of the form DDD.CC *
|
* parses dollar ammount of the form DDD,DDD,DDD.CC *
|
||||||
* *
|
* *
|
||||||
* Args: str -- pointer to string rep of sum *
|
* Args: str -- pointer to string rep of sum *
|
||||||
* Return: int -- in pennies *
|
* Return: int -- in pennies *
|
||||||
@ -229,9 +229,9 @@ void xaccParseQIFDate (Date * dat, char * str)
|
|||||||
double xaccParseQIFAmount (char * str)
|
double xaccParseQIFAmount (char * str)
|
||||||
{
|
{
|
||||||
char * tok;
|
char * tok;
|
||||||
double dollars = 0;
|
double dollars = 0.0;
|
||||||
|
|
||||||
if (!str) return 0;
|
if (!str) return 0.0;
|
||||||
|
|
||||||
tok = strchr (str, ',');
|
tok = strchr (str, ',');
|
||||||
if (tok) {
|
if (tok) {
|
||||||
@ -249,19 +249,105 @@ double xaccParseQIFAmount (char * str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tok = strchr (str, '.');
|
tok = strchr (str, '.');
|
||||||
if (!tok) return 0;
|
if (tok) {
|
||||||
*tok = 0x0;
|
*tok = 0x0;
|
||||||
dollars += ((double) (atoi (str)));
|
dollars += ((double) (atoi (str)));
|
||||||
|
|
||||||
str = tok+sizeof(char);
|
str = tok+sizeof(char);
|
||||||
|
|
||||||
tok = strchr (str, '\r');
|
tok = strchr (str, '\r');
|
||||||
if (!tok) return dollars;
|
if (!tok) return dollars;
|
||||||
*tok = 0x0;
|
*tok = 0x0;
|
||||||
dollars += 0.01 * ((double) atoi (str));
|
dollars += 0.01 * ((double) atoi (str));
|
||||||
|
return dollars;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tok = strchr (str, '\r');
|
||||||
|
if (tok) {
|
||||||
|
*tok = 0x0;
|
||||||
|
dollars += ((double) (atoi (str)));
|
||||||
|
return dollars;
|
||||||
|
} else {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dollars;
|
return dollars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
Account *
|
||||||
|
xaccGetXferQIFAccount (Account *acc, char *qifline)
|
||||||
|
{
|
||||||
|
Account *xfer_acc;
|
||||||
|
AccountGroup *rootgrp;
|
||||||
|
char * tmp;
|
||||||
|
|
||||||
|
/* remove square brackets from name, remove carriage return ... */
|
||||||
|
qifline = &qifline[1];
|
||||||
|
if ('[' == qifline[0]) {
|
||||||
|
qifline = &qifline[1];
|
||||||
|
tmp = strchr (qifline, ']');
|
||||||
|
if (tmp) *tmp = 0x0;
|
||||||
|
}
|
||||||
|
tmp = strchr (qifline, '\r');
|
||||||
|
if(tmp) *tmp = 0x0;
|
||||||
|
tmp = strchr (qifline, '\n');
|
||||||
|
if(tmp) *tmp = 0x0;
|
||||||
|
|
||||||
|
/* see if the account exists */
|
||||||
|
rootgrp = xaccGetRootGroupOfAcct (acc);
|
||||||
|
xfer_acc = xaccGetAccountFromName (rootgrp, qifline);
|
||||||
|
|
||||||
|
/* if not, create it */
|
||||||
|
if (!xfer_acc) {
|
||||||
|
xfer_acc = mallocAccount ();
|
||||||
|
xfer_acc->accountName = XtNewString (qifline);
|
||||||
|
xfer_acc->type = BANK;
|
||||||
|
insertAccount (rootgrp, xfer_acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xfer_acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
Account *
|
||||||
|
xaccGetSecurityQIFAccount (Account *acc, char *qifline)
|
||||||
|
{
|
||||||
|
Account *xfer_acc;
|
||||||
|
AccountGroup *rootgrp;
|
||||||
|
char * tmp;
|
||||||
|
|
||||||
|
/* remove square brackets from name, remove carriage return ... */
|
||||||
|
qifline = &qifline[1];
|
||||||
|
if ('[' == qifline[0]) {
|
||||||
|
qifline = &qifline[1];
|
||||||
|
tmp = strchr (qifline, ']');
|
||||||
|
if (tmp) *tmp = 0x0;
|
||||||
|
}
|
||||||
|
tmp = strchr (qifline, '\r');
|
||||||
|
if(tmp) *tmp = 0x0;
|
||||||
|
tmp = strchr (qifline, '\n');
|
||||||
|
if(tmp) *tmp = 0x0;
|
||||||
|
|
||||||
|
/* see if the account exists */
|
||||||
|
rootgrp = xaccGetRootGroupOfAcct (acc);
|
||||||
|
xfer_acc = xaccGetAccountFromName (rootgrp, qifline);
|
||||||
|
|
||||||
|
/* if not, create it */
|
||||||
|
if (!xfer_acc) {
|
||||||
|
xfer_acc = mallocAccount ();
|
||||||
|
xfer_acc->accountName = XtNewString (qifline);
|
||||||
|
xfer_acc->type = STOCK;
|
||||||
|
xaccInsertSubAccount (acc, xfer_acc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xfer_acc;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
* xaccReadQIFTransaction *
|
* xaccReadQIFTransaction *
|
||||||
* reads in transaction *
|
* reads in transaction *
|
||||||
@ -274,11 +360,20 @@ double xaccParseQIFAmount (char * str)
|
|||||||
* Return: first new line after end of transaction *
|
* Return: first new line after end of transaction *
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
|
#define XACC_ACTION(q,x) \
|
||||||
|
if (!strncmp (&qifline[1], q, strlen(q))) { \
|
||||||
|
trans->action = XtNewString(x); \
|
||||||
|
} else
|
||||||
|
|
||||||
|
|
||||||
char * xaccReadQIFTransaction (int fd, Account *acc)
|
char * xaccReadQIFTransaction (int fd, Account *acc)
|
||||||
{
|
{
|
||||||
Transaction *trans;
|
Transaction *trans;
|
||||||
char * qifline;
|
char * qifline;
|
||||||
int isneg = 0;
|
int isneg = 0;
|
||||||
|
int got_quantity = 0;
|
||||||
|
int do_security = 0;
|
||||||
|
Account *sub_acc = 0x0;
|
||||||
|
|
||||||
if (!acc) return NULL;
|
if (!acc) return NULL;
|
||||||
trans = (Transaction *)_malloc(sizeof(Transaction));
|
trans = (Transaction *)_malloc(sizeof(Transaction));
|
||||||
@ -313,70 +408,103 @@ char * xaccReadQIFTransaction (int fd, Account *acc)
|
|||||||
|
|
||||||
/* scan for transaction date, description, type */
|
/* scan for transaction date, description, type */
|
||||||
while (qifline) {
|
while (qifline) {
|
||||||
if ('M' == qifline [0]) { /* M == memo field */
|
/* M == memo field */
|
||||||
|
if ('M' == qifline [0]) {
|
||||||
XACC_PREP_STRING (trans->memo);
|
XACC_PREP_STRING (trans->memo);
|
||||||
} else
|
} else
|
||||||
if ('P' == qifline [0]) { /* P == Payee, for Bank accounts */
|
|
||||||
|
/* P == Payee, for Bank accounts */
|
||||||
|
if ('P' == qifline [0]) {
|
||||||
XACC_PREP_STRING (trans->description);
|
XACC_PREP_STRING (trans->description);
|
||||||
} else
|
} else
|
||||||
if ('Y' == qifline [0]) { /* Y == Name of Security */
|
|
||||||
|
/* Y == Name of Security */
|
||||||
|
if ('Y' == qifline [0]) {
|
||||||
XACC_PREP_STRING (trans->description);
|
XACC_PREP_STRING (trans->description);
|
||||||
|
|
||||||
|
if (do_security) {
|
||||||
|
/* locate or create the sub-account account */
|
||||||
|
sub_acc = xaccGetSecurityQIFAccount (acc, qifline);
|
||||||
|
|
||||||
|
/* now, insert the transaction into the
|
||||||
|
* main (not sub) account as a debit. The
|
||||||
|
* main account will be debited, the
|
||||||
|
* subaccount credited */
|
||||||
|
trans->debit = (struct _account *) acc;
|
||||||
|
insertTransaction (acc, trans);
|
||||||
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
|
|
||||||
/* N == check numbers for Banks, but Action for portfolios */
|
/* N == check numbers for Banks, but Action for portfolios */
|
||||||
if ('N' == qifline [0]) {
|
if ('N' == qifline [0]) {
|
||||||
XACC_PREP_STRING (trans->num);
|
|
||||||
if (!strncmp (qifline, "NSell", 5)) isneg = 1;
|
if (!strncmp (qifline, "NSell", 5)) isneg = 1;
|
||||||
|
if (!strncmp (qifline, "NSell", 5)) do_security = 1;
|
||||||
|
if (!strncmp (qifline, "NBuy", 4)) do_security = 1;
|
||||||
|
|
||||||
|
/* if a recognized action, convert to our cannonical names */
|
||||||
|
XACC_ACTION ("Buy", "Buy")
|
||||||
|
XACC_ACTION ("Sell", "Sell")
|
||||||
|
XACC_ACTION ("Div", "Div")
|
||||||
|
XACC_ACTION ("CGLong", "LTCG")
|
||||||
|
XACC_ACTION ("CGShort", "STCG")
|
||||||
|
XACC_ACTION ("IntInc", "Int")
|
||||||
|
XACC_ACTION ("DEP", "Deposit")
|
||||||
|
XACC_ACTION ("XIn", "Deposit")
|
||||||
|
XACC_ACTION ("XOut", "Withdraw")
|
||||||
|
{
|
||||||
|
XACC_PREP_STRING (trans->num);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
|
|
||||||
if ('D' == qifline [0]) { /* D == date */
|
if ('D' == qifline [0]) { /* D == date */
|
||||||
xaccParseQIFDate (&(trans->date), &qifline[1]);
|
xaccParseQIFDate (&(trans->date), &qifline[1]);
|
||||||
} else
|
} else
|
||||||
if ('T' == qifline [0]) { /* T == total */
|
if ('T' == qifline [0]) { /* T == total */
|
||||||
trans -> damount = xaccParseQIFAmount (&qifline[1]); /* amount is double */
|
|
||||||
|
/* ignore T for stock transactions, since T is a dollar amount */
|
||||||
|
if (0 == got_quantity) {
|
||||||
|
trans -> damount = xaccParseQIFAmount (&qifline[1]);
|
||||||
if (isneg) trans -> damount = - (trans->damount);
|
if (isneg) trans -> damount = - (trans->damount);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
if ('I' == qifline [0]) { /* I == share price */
|
if ('I' == qifline [0]) { /* I == share price */
|
||||||
trans -> share_price = xaccParseQIFAmount (&qifline[1]); /* amount is double */
|
trans -> share_price = xaccParseQIFAmount (&qifline[1]);
|
||||||
} else
|
} else
|
||||||
if ('Q' == qifline [0]) { /* Q == number of shares */
|
if ('Q' == qifline [0]) { /* Q == number of shares */
|
||||||
/* hack alert */
|
trans -> damount = xaccParseQIFAmount (&qifline[1]);
|
||||||
|
if (isneg) trans -> damount = - (trans->damount);
|
||||||
|
got_quantity = 1;
|
||||||
} else
|
} else
|
||||||
if ('L' == qifline [0]) { /* L == name of acount from which transfer occured */
|
if ('L' == qifline [0]) { /* L == name of acount from which transfer occured */
|
||||||
Account *xfer_acc;
|
Account *xfer_acc;
|
||||||
AccountGroup *rootgrp;
|
|
||||||
char * tmp;
|
|
||||||
|
|
||||||
/* remove square brackets from name, remove carriage return ... */
|
/* locate the transfer account */
|
||||||
qifline = &qifline[1];
|
xfer_acc = xaccGetXferQIFAccount (acc, qifline);
|
||||||
if ('[' == qifline[0]) {
|
|
||||||
qifline = &qifline[1];
|
|
||||||
tmp = strchr (qifline, ']');
|
|
||||||
if (tmp) *tmp = 0x0;
|
|
||||||
}
|
|
||||||
tmp = strchr (qifline, '\r');
|
|
||||||
if(tmp) *tmp = 0x0;
|
|
||||||
tmp = strchr (qifline, '\n');
|
|
||||||
if(tmp) *tmp = 0x0;
|
|
||||||
|
|
||||||
/* see if the account exists */
|
|
||||||
rootgrp = xaccGetRootGroupOfAcct (acc);
|
|
||||||
xfer_acc = xaccGetAccountFromName (rootgrp, qifline);
|
|
||||||
|
|
||||||
/* if not, create it */
|
|
||||||
if (!xfer_acc) {
|
|
||||||
xfer_acc = mallocAccount ();
|
|
||||||
xfer_acc->accountName = XtNewString (qifline);
|
|
||||||
xfer_acc->type = BANK;
|
|
||||||
insertAccount (rootgrp, xfer_acc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now, insert the transaction into the transfer account */
|
/* now, insert the transaction into the transfer account */
|
||||||
trans->debit = (struct _account *) xfer_acc;
|
trans->debit = (struct _account *) xfer_acc;
|
||||||
insertTransaction (xfer_acc, trans);
|
insertTransaction (xfer_acc, trans);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
if ('$' == qifline [0]) { /* $ == dollar amount -- always preceeded by 'L' */
|
|
||||||
/* hack alert */
|
/* $ == dollar amount -- always preceeded by 'L' */
|
||||||
|
if ('$' == qifline [0]) {
|
||||||
|
/* Currently, it appears that the $ amount is a redundant
|
||||||
|
* number that we can safely ignore. If we wanted to get
|
||||||
|
* fancy, we could use it to double-check the above work,
|
||||||
|
* since it appears to always appear the last entry in the
|
||||||
|
* transaction. */
|
||||||
|
double got, wanted;
|
||||||
|
wanted = xaccParseQIFAmount (&qifline[1]);
|
||||||
|
got = (trans->damount) * (trans->share_price);
|
||||||
|
if (isneg) got = -got;
|
||||||
|
if (wanted != got) {
|
||||||
|
printf ("QIF Parse Error: wanted %f got %f \n", wanted, got);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
|
|
||||||
if ('O' == qifline [0]) { /* O == round-off error ??? */
|
if ('O' == qifline [0]) { /* O == round-off error ??? */
|
||||||
/* hack alert */
|
/* hack alert */
|
||||||
} else
|
} else
|
||||||
@ -393,6 +521,7 @@ char * xaccReadQIFTransaction (int fd, Account *acc)
|
|||||||
xaccRemoveTransaction ((Account *) trans->debit, trans);
|
xaccRemoveTransaction ((Account *) trans->debit, trans);
|
||||||
xaccRemoveTransaction ((Account *) trans->credit, trans);
|
xaccRemoveTransaction ((Account *) trans->credit, trans);
|
||||||
freeTransaction (trans);
|
freeTransaction (trans);
|
||||||
|
return qifline;
|
||||||
}
|
}
|
||||||
|
|
||||||
XACC_PREP_NULL_STRING (trans->num);
|
XACC_PREP_NULL_STRING (trans->num);
|
||||||
@ -400,6 +529,10 @@ char * xaccReadQIFTransaction (int fd, Account *acc)
|
|||||||
XACC_PREP_NULL_STRING (trans->description);
|
XACC_PREP_NULL_STRING (trans->description);
|
||||||
XACC_PREP_NULL_STRING (trans->action);
|
XACC_PREP_NULL_STRING (trans->action);
|
||||||
|
|
||||||
|
/* if a transaction (e.g. security) belongs
|
||||||
|
* in a subaccount, hnalde it now */
|
||||||
|
if (sub_acc) acc = sub_acc;
|
||||||
|
|
||||||
trans->credit = (struct _account *) acc;
|
trans->credit = (struct _account *) acc;
|
||||||
insertTransaction( acc, trans );
|
insertTransaction( acc, trans );
|
||||||
|
|
||||||
@ -484,6 +617,18 @@ xaccReadQIFData( char *datafile )
|
|||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
|
|
||||||
|
if (!strcmp (qifline, "!Type:Invst\r\n")) {
|
||||||
|
Account *acc = mallocAccount();
|
||||||
|
DEBUG ("got Invst\n");
|
||||||
|
|
||||||
|
acc->type = BANK;
|
||||||
|
acc->accountName = XtNewString ("Quicken Investment Account");
|
||||||
|
|
||||||
|
insertAccount( grp, acc );
|
||||||
|
qifline = xaccReadQIFTransList (fd, acc);
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
|
||||||
if (!strcmp (qifline, "!Option:AutoSwitch\r\n")) {
|
if (!strcmp (qifline, "!Option:AutoSwitch\r\n")) {
|
||||||
DEBUG ("got autoswitch on\n");
|
DEBUG ("got autoswitch on\n");
|
||||||
skip = 1;
|
skip = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user