Zoomer Quicken -> desktop Quicken : answer here !

Rob Miller (rmiller@bsm.biochemistry.ucl.ac.uk)
Thu, 9 May 1996 18:16:41 +0100 (BST)

---2144850386-1467443836-831662201=:18407
Content-Type: TEXT/PLAIN; charset=US-ASCII

This is C source code for a program to convert output
from the `print' menu command in Zoomer Pocket Quicken (tm)
to QIF (Quicken Interchange Format) so you can load it
into desktop Quicken (tm). See the comments for details.
I decided that the ESCape characters in the code are
likely to get messed up in e-mail, so I have also
attached a gzipped copy.

So far as I can tell this doesn't violate any copyrights,
as Intuit has published QIF and the printer output is
simple ASCII that anyone can read.

NO WARRANTIES WHATSOEVER ---- USE AT YOUR OWN RISK

Remember, you get what you pay for. For example, this
won't import the `memo' fields, as they're not in the
printer output.

Restrictions: do not distribute without source code,
as I expect others may have to tweak it to make it
work for their own situations.

My employer has nothing to do with this.

If you like it or find it useful, drop me a line
by e-mail. I'm sorry, but the HP Omnigo I've looked
at doesn't appear to support printing :-(.

rob.

/*****************************************************************
*
* Qconvert.c
*
*
* Copyright 1996 Robert T. Miller.
* NO WARRANTIES EXPRESSED OR IMPLIED.
*
* Please see the note about the escape character immediately after
* this header.
*
* This software may be freely copied and distributed so long as
* the following restrictions are met:
* (1) Copyright (c) information may not be deleted from any part
* of the source code, although subsequent authors may copyright
* their own additions.
* (2) All distributions must include the source code, whether
* or not they include an executable version.
*
* This program converts data captured from the serial port of
* a Casio Zoomer (tm) pda when a Quicken (tm) transaction list
* is printed (file menu -> print when the transaction list is
* displayed). Select the Canon BJ-10e (tm) printer and make sure
* `IBM Code Page 437' is set under the Quicken (tm) print options
* (this was the default on my Zoomer), as well as the `text only'
* option. The Windows 95 (tm) `Hyperterminal' program is sufficient
* to capture the data coming into the serial port, though any terminal
* program should do and certainly you will need a null modem cable to
* connect your Zoomer to your PC.
*
* Save the captured data to a file such as `check.log'.
* The command line `Qconvert check.log' will create a file called
* check.qif for importation into desktop Quicken(tm) (assuming
* there is no problem reading the file :-).
*
* I developed this for use in the UK, so my Zoomer date format is
* day-month-year and my desktop Quicken(tm) calls the checking
* account a `Current' account. As I am releasing it, this software
* sets the `locale' variable to `UK'; the result is that the month
* and day fields for each transaction from the Zoomer will be swapped
* and the account name `Checking' is changed to `Current'. To change
* this behavior, change the initialization value for `locale'
* before compiling or use the `-s' switch (for uS) on the command
* line.
*
* You'll probably want to backup any data you have before you
* start importing QIF files so you can see how the import stuff works.
* Under my (UK) Quicken Release 5 (tm) I leave `special handling for
* transfers' enabled in all cases.
*
* You may run into some problems converting the files due to
* differences between my system and yours, or you may wish to use
* a different printer data format. To assist in these situations, use
* the -v (verbose) switch to display transaction data as it is read,
* and the -l (logfile) switch to generate a copy of the input file
* (with a .inp extension) with newlines separating each record. The
* potential need to modify the way the input data is handled is the
* reason I require that this program not be distributed in any form
* that does not include the source code.
*
* This is free software, with no warranties whatsoever. If you
* want more functionality (such as the ability to include the `memo'
* fields from your transactions, which is not included in the `print'
* output), I suggest you look into a commercial product from Intuit (tm).
*
* This source code has been successfully compiled and tested under
* Windows 95 using Visual C++ v2.0, and was originally developed under
* Linux (kernel 1.3.86) using gcc v2.7.0.
*
* Information describing QIF files is contained in your Quicken(tm)
* documentation; the Canon BJ-10e (tm) output was the closest I found to
* generating straight ASCII data for the transaction printout (I'd be
* happy to hear if anyone knows of a better choice). All in all, these
* two facts make this program pretty trivial, but I hope others find it
* to be of some use. Drop me a line if you like it.
*
* rob miller April 1996
*
* rmiller@bsm.bioc.ucl.ac.uk (e-mail *may* be forwarded after I leave)
*
**************************************************************************/
/*******
******** ATTENTION !!!!!
********
This is an `escape' character:

There are 5 more in this file. If you got this file via e-mail or
ASCII ftp, they may have been messed up in the transfer. Each line
that should have one is commented with the word ESC.
********
********
*******/

#include <stdio.h>

#ifdef WIN32
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#endif

#define FALSE 0
#define TRUE ~FALSE

#define MAXLINE 255
#define MAXFIELD 128
#define QSRCMAX 32
#define QMAXDATE 10

#define BAL_OFST 17
#define DAT_OFST 15
#define TYP_OFST 16
#define PDE_OFST 16
#define CAT_OFST 17
#define AMT_OFST 17

#define d(x) ((double) (x))

#define UK 1
#define USA 0

/** change this to compile in the locale spec rather than cmd line option */
int locale=UK;

int
getline(FILE *f,char *linebuf) {
int i=0,c;

while ((i < MAXLINE) &&
((c = fgetc(f)) != EOF) &&
(c != '\r') /* EOL terminator */
) if (c != '\0') linebuf[i++] = (char) c;

linebuf[i] = '\0';

return(i);
}

void
writeline(FILE *f,char *linebuf,int lc) {
int i=0;

while (i < lc) fputc((int) linebuf[i++],f);
fputc((int) '\n',f);
}

void
noCommaD(char *in,char *out) {
int i,j;

for (i=0,j=0;i<QSRCMAX;i++)
if ((isdigit(in[i])) || (in[i]=='.') || (in[i] == '-') || (in[i] == '\0'))
out[j++]=in[i];
}

FILE *QIFout;

char Qdate[QMAXDATE];
char Qsource[QSRCMAX];
char Qtype[MAXFIELD];
char QreportDate[MAXFIELD];
char QpayDesc[MAXFIELD];
char Qcategory[MAXFIELD];
double Qamount;
double Qbalance;

#define EXPENSE 0
#define INCOME 1

void
logTransaction() {
int ttype,i;
char temp[2];

if (Qdate[0] == '\0') {
printf("error: logTransaction() called with stale data\n");
return;
}

if ((!(strcmp("Balance",Qtype))) &&
(!(strcmp("Trimmed Balance",QpayDesc)))
) {
Qdate[0] = '\0';
Qtype[0] = '\0';
QpayDesc[0] = '\0';
Qcategory[0] = '\0';
return;
}

for (i=0;i<QMAXDATE;i++) if (Qdate[i] == '-') Qdate[i]='/';

if (locale == UK) {

temp[0] = Qdate[3]; /* Date Swap !!!! */
temp[1] = Qdate[4];
Qdate[3] = Qdate[0];
Qdate[4] = Qdate[1];
Qdate[0] = temp[0];
Qdate[1] = temp[1];

if (!(strcmp("Checking",Qcategory))) /* UK calls it this */
sprintf(Qcategory,"%s\0","Current");
}

fprintf(QIFout,"D%s\n",Qdate);

if (((Qtype[0] == '>') && (Qtype[1] == '>')) ||
(!(strcmp("Deposit",QpayDesc))) ||
(!(strcmp("Deposit",Qtype)))
)
ttype = INCOME;
else {
Qamount *= d(-1.0);
ttype = EXPENSE;
}

fprintf(QIFout,"T%-8.2lf\n",Qamount);

if (((!(strcmp("Receipt",Qtype))) && (!(strcmp("Cash",Qcategory)))) ||
((!(strcmp(">>Receipt",Qtype))) && (!(strcmp("Current",Qcategory))))
) fprintf(QIFout,"NATM\n");
else if (Qtype[0] != '\0') fprintf(QIFout,"N%s\n",Qtype);

if (QpayDesc[0] != '\0') fprintf(QIFout,"P%s\n",QpayDesc);
if (Qcategory[0] != '\0')
if ((ttype == INCOME) || (!(strcmp("Cash",Qcategory))))
fprintf(QIFout,"L[%s]\n",Qcategory);
else fprintf(QIFout,"L%s\n",Qcategory);

fprintf(QIFout,"^\n");

Qdate[0] = '\0';
Qtype[0] = '\0';
QpayDesc[0] = '\0';
Qcategory[0] = '\0';
}

void
main(int argc, char **argv) {
FILE *f,*out;
int i,lc;
int verbose=FALSE, logfile=FALSE;
int transaction=FALSE;

char lbuf[MAXLINE];
char temp[QSRCMAX];

Qdate[0] = '\0';
Qtype[0] = '\0';
QpayDesc[0] = '\0';
Qcategory[0] = '\0';

f = (FILE *) NULL;

while (--argc > 0) {
*argv++;

if (**argv == '-') {

switch ((*argv)[1]) {
case 'v':
verbose = TRUE;
break;
case 'l':
logfile = TRUE;
break;

case 'k':
locale = UK;
break;
case 's':
locale = USA;
break;

default:
printf("option %c not recognized\n", (*argv)[1]);
exit(0);
break;
}

} else {

char ofname[32];

if ((f = fopen(*argv,"r")) == (FILE *) NULL) {
printf("unable to open %s for reading\n",*argv);
exit(0);
}

sprintf(ofname,"%s\0",*argv);
for (i=0;i<6,ofname[i] != '.';i++);
sprintf(&(ofname[i]),".inp\0");

if (logfile)
if ((out = fopen(ofname,"w")) == (FILE *) NULL) {
printf("unable to open logfile %s for writing\n",ofname);
exit(0);
}

sprintf(ofname,"%s\0",*argv);
for (i=0;i<6,ofname[i] != '.';i++);
sprintf(&(ofname[i]),".qif\0");

if ((QIFout = fopen(ofname,"w")) == (FILE *) NULL) {
printf("unable to open QIF file %s for writing\n",ofname);
exit(0);
}
}

}

if (f == (FILE *) NULL) {
printf("\n Qconvert - convert Zoomer(tm) Quicken(tm) `print' output to QIF file\n");
printf("\n Copyright (c) 1996 Robert T. Miller. NO WARRANTIES EXPRESSED OR IMPLIED.\n");
printf("\n command format: Qconvert [options] <input_file>\n");
printf("\n where options are\n");
printf(" -v verbose : display transaction data as recognized\n");
printf(" -l logfile : write identified lines of input file to <input_file>.inp\n");
if (locale == UK) {
printf(" -k UK locale : swap month/day, call `Checking' `Current' (default)\n");
printf(" -s US locale : no UK changes\n");
} else {
printf(" -k UK locale : swap month/day, call `Checking' `Current' \n");
printf(" -s US locale : no UK changes (default)\n");
}
printf("\n <input_file> is a file of data captured (e.g. by a terminal program) from the\n");
printf(" Zoomer(tm) serial port after selecting `print' (file menu) when the desired\n");
printf(" transaction list is displayed. Set your printer type to Canon BJ-10e(tm),\n");
printf(" Quicken(tm) print options `text only' and `IBM(tm) Code Page 437'. \n");
printf("\n This software may not be distributed separate from its source code.\n");

exit(0);
}

while (lc = getline(f,lbuf)) {
if (logfile) writeline(out,lbuf,lc);
switch(lbuf[1]) {
case '[' :
switch(lbuf[2]) {
case 'K' : break;
default :
printf("[ not handled : :%s:\n",lbuf);
break;
}
break;
case 'd' :
switch(lbuf[2]) {
case '' : /* case ESC */
if (isdigit(lbuf[DAT_OFST])) {
if (transaction) logTransaction();
transaction=TRUE;
sscanf(&(lbuf[DAT_OFST]),"%s\n",Qdate);
if (verbose) printf("\n date = %s\n",Qdate);
} else if (lbuf[DAT_OFST] == 'R') {
sscanf(&(lbuf[DAT_OFST]),"Register Listing for %sJ\214",Qsource);
/* that was %sESCJ\214 */
for (i=0;i<QSRCMAX;i++) if (!(isprint(Qsource[i]))) Qsource[i]='\0';
if (!transaction) {
if (!(strcmp("Checking",Qsource)))
fprintf(QIFout,"!Type:Bank \n");
else
fprintf(QIFout,"!Type:%s \n",Qsource);
printf("Processing register listing for %s report date %s\n",Qsource,QreportDate);
}
if (verbose) printf(" source = %s\n",Qsource);
} else if (isalpha(lbuf[DAT_OFST])) {
strcpy(QreportDate,&(lbuf[DAT_OFST]));
if (verbose) printf("\n report date = %s\n",QreportDate);
}; /* could also be 'Date' info label */
break;
case 'p' :
if (lbuf[TYP_OFST] != '') { /* lbuf[TYP_OFST] != ESC */
sscanf(&(lbuf[TYP_OFST]),"%s\n",Qtype);
if (verbose) printf(" type = %s\n",Qtype);
} /* could also be 'Type' info label */
break;
case '' : break;
case '\367' :
if (lbuf[PDE_OFST] != '') { /* lbuf[PDE_OFST] != ESC */
strcpy(QpayDesc,&(lbuf[PDE_OFST]));
if (verbose) printf(" payee/description = %s\n",QpayDesc);
} /* could also be 'Payee/Description' info label */
break;
case 'e' : break;
default :
switch (lbuf[3]) {
case '' :
if ((isdigit(lbuf[BAL_OFST])) || (lbuf[BAL_OFST] == '-')) {
noCommaD(&(lbuf[BAL_OFST]),temp);
sscanf(temp,"%lf",&Qbalance);
if (verbose) printf(" balance = %12.2lf\n",Qbalance);
} /* could also be 'Page' or 'Balance' labels */
break;
case '' :
if (isdigit(lbuf[AMT_OFST])) {
noCommaD(&(lbuf[AMT_OFST]),temp);
sscanf(temp,"%lf",&Qamount);
switch (lbuf[2]) {
case '\241' : if (verbose) printf(" amount (n >= 1000) = ");
break;
case '\272' : if (verbose) printf(" amount (100 <= n < 1000.00) = ");
break;
case '\306' : if (verbose) printf(" amount (10.00 <= n < 100.00) = ");
break;
case '\321' : if (verbose) printf(" amount (n < 10.00) = ");
break;
default : if (verbose) printf(" amount = ");
break;
}

if (verbose) printf("%12.2lf\n",Qamount);
}
break;
case '' :
if (lbuf[CAT_OFST] != '') { /* lbuf[CAT_OFST] != ESC */
sscanf(&(lbuf[CAT_OFST]),"%s\n",Qcategory);
if (verbose) printf(" category = %s\n",Qcategory);
if (lbuf[2] != '\341') if (verbose) printf("*** category not \341\n");
} /* could also be 'Category' info label */
break;

default :
printf("d not handled - :%s:\n",lbuf);
break;
}
} /* end of switch(lbuf[2]) */
break;
case 'J' : break; /* last balance ? */
default :
printf(" line not handled - :%s:\n",&(lbuf[0]));
break;
} /* end of switch(lbuf[1]) */

} /* end of while(getline) */

if (Qdate[0] != '\0') logTransaction();
fclose(f);
if (logfile) fclose(out);
fclose(QIFout);
}

---2144850386-1467443836-831662201=:18407
Content-Type: APPLICATION/octet-stream; name="qconvert.c.gz"
Content-Transfer-Encoding: BASE64
Content-ID: <Pine.SGI.3.91.960509181641.18407B@bsmir09>
Content-Description: gzipped C source code

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
ndiMsL4xjkZU57FPQehn2OrcpGRkjHBBuY3yUjDK4kBSo0E7CZVSOyolcZhM
M4hwoUK1wI0gm+TIglJQfIs46QDGGWozQodARg0OAhW9SulIN5oYkbg0p2PM
cNYHD/ph+oYxb0RRUlQ54V0qsfjDfs9bz+0mWf9wrfPzPm51Px7DI/qBfdWy
SQHr4JXazbbr7ewOFqTvWufc51Hf872Kfg5GSiQILpsgYJiV9TCgNUFujAXq
SMVPuT8qJx21UaOCows2lSaMLwqAiYlzUyiRe59yMLe4LU53ujXnyYQGxvaY
gIscOJdxHsaUDf2zg26t6vwfz1uo3Z9NjnpdlGGcdUdvWjgW4WYGfh4cb285
BEGJ2xEicOcgbIfzY1jzr5tjivGfZYp1Avkjd9Ln3f7RWR827fP56ec+wD95
uKb6sP/L0eC4D1vff++OvRv0jw6ht/WDHfx0dnqAL4CENkP4fLh/3ofeZs3w
7f7R3z6+OzuH3is7hkR6rF7k/C8neuylHTs57C+MHdi5Nb/9D/WYHQy9r7iF
8MKsuqbijU9+/fLze4Be/XS2j4YhKNc9KBXPzCRgAxTVfAJ1XIApZ8QbV8Ry
MNb7IrXDBPQ27V4V+d7n97stfm4NZUlk3rvBUR+eRh2CPjyloesq8uF3xAjR
xXubnWCXAANUoHBFz4vhtXGOD0+etNZwLIA9iJBn4EW+D4/2oP/xnX4J+BIH
2l/ytg/w/Cm+OjKbzxJDBCVc8ynLGbpNpNOCXMTPnl0ia4/Ew30NSg/1O3pD
5DyK6azKUy/2d1t3tCq0brM4bE3zuJSrNe2wcYKGwk11SVsiiDD9B6h8Wjal
60Q+TXBft7+kbR52BUmzA2r2Dz21fpxqQTD3O6t3fmVlqFJ4ZPtfUZz4tUb4
Lq7nk2jA5vLiIsRqWuKiaAs0+z/+Aervvb12t+08wx4aamNhhCztt1SGRjEu
fkV19vg1id5SBsNiiu9QKhb3E+1LL0x4IZ0aVf3DhZbTDlPiuDAxa0dzSVuN
Q2K08G4iZoeYjRdfBEg+zPKZ+0YFFHwSY9r71c/XIhG4A9hl1Wxo9X856R83
8s7g+ODjhz6Fn3IRttfndWn2areUpEgnJoYsDe4lJhdbl+wq8oSyymZtVZ4J
qrhH3rrM8wxrygJ/dSahkjfu2BJ1gvMlXfeV7ArT9De6Q6/lPfIw+wbjibf+
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
---2144850386-1467443836-831662201=:18407--