Convert Cha-Ching CSV files to Quicken QIF files

From Stack Overflow
Jump to: navigation, search
#include <stdio.h>
#include <string.h>

int lineCounter = 0;

int die(const char *message) {
	fprintf(stderr, "%s\n", message);
	return 1;
}

// For numbers like "$1,000.00", trim out that extra comma, as it kills the comma-delimited parsing
void trimLargeNumbers(char *s, const char *prefix) {
	char *a, *b, *c;
	c = strstr(s, prefix);
	if (c) {
		a = c+2;
		b = c+3;
		do {
			*a = *b;
			a++;
			b++;
		} while (*a);
	}
}

void convert(FILE *in, FILE *out) {
	char line[256], *payee, *amount, *date, *c;
	fprintf(out, "!Type:Bank\n");
	fgets(line, sizeof(line) - 1, in); // Read the header line to get it out of the way
	while (fgets(line, sizeof(line) - 1, in) != NULL) {
		lineCounter++;
		line[sizeof(line) - 1] = 0;
		trimLargeNumbers(line, "$1,"); // Mmmm... copy & paste
		trimLargeNumbers(line, "$2,");
		trimLargeNumbers(line, "$3,");
		trimLargeNumbers(line, "$4,"); // No income/expenses larger than $4,999 in these accounts (for now!)
		for (c = line; *c; c++) // Trim off line endings and other control characters
			if (*c < ' ')
				*c = 0;
		if ((amount = strrchr(line, ',')) == NULL) {
			fprintf(stderr, "Could not find amount comma in line %d: %s\n", lineCounter, line);
			continue;
		}
		*amount = 0;
		amount++;
		if ((date = strrchr(line, ',')) == NULL) {
			fprintf(stderr, "Could not find date comma in line %d: %s\n", lineCounter, line);
			continue;
		}
		*date = 0;
		date++;
		payee = &line[0];
		if (*payee == '"') {
			payee++;
			c = strrchr(payee, '"');
			*c = 0;
		}
		// If amount is in quotes, strip 'em
		if (*amount == '"') {
			amount++;
			for (c = amount; *c; c++)
				if (*c == '"')
					*c = 0;
		}
		// Convert date to positive value (without $) or negative value (without $ or parens)
		amount++;
		if (*amount == '$') {
			*amount = '-';
			for (c = amount; *c; c++)
				if (*c == ')')
					*c = 0;
		}
		fprintf(out, "P%s\nD%s\nU%s\n^\n", payee, date, amount);
	}
}

int main(int argc, char **argv) {
	FILE *in, *out;
	if (argc != 3) {
		fprintf(stderr, "Converts Cha-Ching CSV files to Quicken QIF format\n"
			"Usage: %s inputfilename outputfilename\n"
			"NOTE: if you get a lot of \"Could not find amount comma\" errors, then convert your CSV to UTF-8\n",
			argv[0]);
		return 1;
	}
	if ((in = fopen(argv[1], "r")) == 0)
		return die("Unable to open input file");
	if ((out = fopen(argv[2], "w")) == 0)
		return die("Unable to open output file");
	convert(in, out);
	fclose(in);
	fclose(out);
}
Personal tools