public static NonInvestmentAccount ParseNonInvestmentAccountFile(string filePath) { StreamReader sr; string line; NonInvestmentAccount account; NonInvestmentAccountTransaction transaction; Dictionary<string, object> context; const string QIF_HEADER = "!Type:Bank"; const string QIF_TX_TERM = "^"; const string QIF_CLRDIND = "*"; const string QIF_KEY_DATE = "D"; const string QIF_KEY_AMOUNT = "T"; const string QIF_KEY_CLEARED = "C"; const string QIF_KEY_NUMBER = "N"; const string QIF_KEY_PAYEE = "P"; const string QIF_KEY_MEMO = "M"; const string QIF_KEY_CATEGORY = "L"; account = new NonInvestmentAccount(); context = new Dictionary<string, object>(); using (sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 32, FileOptions.None), Encoding.ASCII)) { if ((line = sr.ReadLine() ?? "") != "") { if (line != QIF_HEADER && line != "!Type:CCard") throw new InvalidOperationException("Invalid QIF header: " + line); } while ((line = sr.ReadLine() ?? "") != "") { if (line == QIF_TX_TERM) { if (context.Count == 0) throw new InvalidOperationException("Invalid QIF transaction context"); transaction = new NonInvestmentAccountTransaction( context.ContainsKey(QIF_KEY_AMOUNT) ? (double?)context[QIF_KEY_AMOUNT] : null, context.ContainsKey(QIF_KEY_CATEGORY) ? (string)context[QIF_KEY_CATEGORY] : null, context.ContainsKey(QIF_KEY_CLEARED) ? (bool?)context[QIF_KEY_CLEARED] : null, context.ContainsKey(QIF_KEY_DATE) ? (DateTime?)context[QIF_KEY_DATE] : null, context.ContainsKey(QIF_KEY_MEMO) ? (string)context[QIF_KEY_MEMO] : null, context.ContainsKey(QIF_KEY_NUMBER) ? (string)context[QIF_KEY_NUMBER] : null, context.ContainsKey(QIF_KEY_PAYEE) ? (string)context[QIF_KEY_PAYEE] : null); account.PostTransaction(transaction); context.Clear(); continue; } else { string key; object value; if (line.Length < 2) throw new InvalidOperationException("Invalid QIF item length: " + line); key = line[0].ToString(); line = line.Substring(1); switch (key) { case QIF_KEY_AMOUNT: value = double.Parse(line); break; case QIF_KEY_CATEGORY: value = line.ToUpper(); break; case QIF_KEY_CLEARED: value = line == QIF_CLRDIND; break; case QIF_KEY_DATE: value = DateTime.Parse(line.Replace("'", "/")); break; case QIF_KEY_MEMO: value = line.ToUpper(); break; case QIF_KEY_NUMBER: value = line.ToUpper(); break; case QIF_KEY_PAYEE: value = line.ToUpper(); break; default: throw new InvalidOperationException("Invalid QIF item key: " + key); } context.Add(key, value); } } } return account; }
public static void FormatToTsvFile(NonInvestmentAccount account, string filePath) { StreamWriter swa, swp, swc; string line; Dictionary<string, object> payees, categories; if (account == null) throw new ArgumentNullException("account"); payees = new Dictionary<string, object>(); categories = new Dictionary<string, object>(); using (swa = new StreamWriter(new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 32, FileOptions.None), Encoding.ASCII)) { foreach (NonInvestmentAccountTransaction transaction in account.Transactions) { if (!payees.ContainsKey(transaction.Payee ?? "")) payees.Add(transaction.Payee ?? "", null); if (!categories.ContainsKey(transaction.Category ?? "")) categories.Add(transaction.Category ?? "", null); line = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\n", transaction.Number, transaction.Payee, transaction.Category, transaction.Date.Value.ToString("MM/dd/yyyy"), (transaction.Amount ?? 0).ToString("n"), transaction.Cleared ?? false, transaction.Memo); swa.Write(line); } using (swp = new StreamWriter(new FileStream(filePath + ".pay", FileMode.Create, FileAccess.Write, FileShare.None, 32, FileOptions.None), Encoding.ASCII)) { foreach (KeyValuePair<string, object> payee in payees) swp.WriteLine(payee.Key); } using (swc = new StreamWriter(new FileStream(filePath + ".cat", FileMode.Create, FileAccess.Write, FileShare.None, 32, FileOptions.None), Encoding.ASCII)) { foreach (KeyValuePair<string, object> category in categories) swc.WriteLine(category.Key); } } }