quick-etl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,126 @@
1
+ = QuickETL = Quicken Extract Transform and Load
2
+
3
+ Version: 0.1.0
4
+ Date: 2008-02-10
5
+
6
+ ---
7
+
8
+ QuickETL = Quicken Extract Transform and Load
9
+ QuickETL - Copyright 2008 by Chris Joakim.
10
+ QuickETL is available under GNU General Public License (GPL) license.
11
+
12
+ QuickETL is used to parse your Quicken *.qif files into csv format, then
13
+ load this csv data into a sqlite database, where it can be subsequently
14
+ queried and used for reporting.
15
+
16
+ QuickETL functionality is invoked from a command line with the Ruby Rake program.
17
+ File 'rakefile.rb' is included in the gem file.
18
+
19
+ Future versions of QuickETL will add a User Interface for running queries
20
+ and generating reports.
21
+
22
+
23
+ = General
24
+
25
+ Author:: Chris Joakim <chris@joakim-systems.com>
26
+ Requires:: Ruby 1.8.4 or later
27
+ License:: Copyright 2008 by Chris Joakim.
28
+ GNU General Public License (GPL) license.
29
+ See http://www.gnu.org/copyleft/gpl.html
30
+
31
+
32
+ = License
33
+
34
+ QuickETL is available under GNU General Public License (GPL) license.
35
+
36
+
37
+ = Download
38
+
39
+ The latest version of QuickETL can be found at http://rubyforge.org/projects/quick-etl/
40
+
41
+
42
+ = Installation
43
+
44
+ Please perform the following steps to install QuickETL.
45
+
46
+ 1. Create a directory on your computer which will be considered the "home" directory
47
+ for QuickETL. This directory will contain your Quicken *.qif files, as well as
48
+ the following files:
49
+ - QuickenData.qif (YOUR qif file, created by using the Quicken File -> Export... function)
50
+ - rakefile.rb (The Ruby Rake "rakefile"; your interface to QuickETL functionality)
51
+ - quick-etl.properties (required but unused in this release)
52
+ - quick-etl.csv (csv file created by parsing your *.qif file).
53
+ - quick-etl.db (sqlite database file).
54
+ - quick-etl.load (generated file used to load the csv file)
55
+
56
+ 2. Create the environment variable QUICK_ETL_HOME, and set its value to the directory name
57
+ you chose in step 1. This environment variable MUST be set for QuickETL to function properly.
58
+
59
+ Restart your shell program after setting this environment variable.
60
+
61
+ 3. Verify that you have the sqlite3 program installed on your computer.
62
+ See http://www.sqlite.org/ for sqlite3 installation and usage instructions.
63
+
64
+ For Max OS/X 10.4+ users, the sqlite3 is already installed with the OS.
65
+
66
+ 4. QuickETL is packaged and installed as a ruby 'gem'. Download the latest gem to
67
+ your computer, then run the following command from your download directory.
68
+
69
+ gem install quick-etl-1.0.0.gem
70
+
71
+ 5. Unpack the 'quick-etl-0.1.0.gem' file in your download directory with the following command:
72
+
73
+ gem unpack quick-etl-0.1.0.gem
74
+
75
+ Then copy the 'rakefile.rb' and 'quick-etl.properties' files, that were unpacked from the gem,
76
+ to your QUICK_ETL_HOME directory.
77
+
78
+
79
+ = Usage
80
+
81
+ 1. Use your Quicken program to export its data to the QUICK_ETL_HOME directory.
82
+ Specify output file 'QuickenData.qif'.
83
+
84
+ 2. Open a shell window in your QUICK_ETL_HOME directory.
85
+
86
+ Execute command 'rake -T' to see the list of functions available.
87
+
88
+ Execute command 'rake parse' to parse the qif file into csv format.
89
+
90
+ Execute command 'rake load' to load the csv file data into sqlite3 database 'quick-etl.db'.
91
+
92
+ Execute command 'rake parse_and_load' to run both the parsing and loading function.
93
+
94
+ Execute command 'rake show_ddl' to see the structure of the database table and its column names.
95
+
96
+ 3. Use the sqlite3 CLP (Command Line Program) to query the database.
97
+ From the QUICK_ETL_HOME directory, execute command 'sqlite3 quick-etl.db'.
98
+
99
+ You can then enter and execute queries like the following:
100
+
101
+ sqlite> select * from transactions;
102
+ sqlite> select * from transactions where tran_date == '2008-02-05';
103
+
104
+ Note: A User Interface will be created for QuickETL its next release.
105
+
106
+
107
+ = Road Map / TODO List
108
+
109
+ 1. Develop a UI for the quick-etl.db sqlite database.
110
+
111
+ 2. Develop reporting functionality.
112
+
113
+ 3. Support the "merging" of multiple *qif files into one database.
114
+
115
+
116
+ = Support
117
+
118
+ Please see http://rubyforge.org/projects/quick-etl/ to submit a request or report
119
+ a bug, on the Tracker page.
120
+
121
+
122
+ = Warranty
123
+
124
+ This software is provided "as is" and without any express or implied warranties,
125
+ including, without limitation, the implied warranties of merchantibility and
126
+ fitness for a particular purpose.
@@ -0,0 +1,231 @@
1
+
2
+ http://www.intuit.com/quicken/technical-support/quicken/old-faqs/dosfaqs/60006.html
3
+
4
+ Q: What is the Quicken interchange format (QIF)?
5
+
6
+ A: The Quicken interchange format (QIF) is a specially formatted text (ASCII)
7
+ file that lets you to move Quicken transactions:
8
+
9
+ From one Quicken account register into another Quicken account register, or
10
+ To/From another application that supports the QIF format.
11
+ Note: For Quicken to translate data from a text file into the Quicken register
12
+ as transactions, the text file must be in the QIF format.
13
+
14
+
15
+ Required File Formatting:
16
+
17
+
18
+ Each transaction must end with a symbol, indicating the end of entry.
19
+ Each item in the transaction must display on a separate line.
20
+ When Quicken exports an account register or list, it adds a line to the top
21
+ of the file that identifies the type of account or list. Listed below are
22
+ the header lines Quicken adds to the exported files:
23
+
24
+ Header Type of data
25
+ !Type:Bank Bank account transactions
26
+ !Type:Cash Cash account transactions
27
+ !Type:CCard Credit card account transactions
28
+ !Type:Invst Investment account transactions
29
+ !Type:Oth A Asset account transactions
30
+ !Type:Oth L Liability account transactions
31
+ !Account Account list or which account follows
32
+ !Type:Cat Category list
33
+ !Type:Class Class list
34
+ !Type:Memorized Memorized transaction list
35
+
36
+
37
+ You can force Quicken to import all transfers, regardless of whether
38
+ Ignore Transfers is selected when the file is imported. You must add a
39
+ line to the file being imported into a Quicken account. Use a text editor
40
+ or word processor to put the following line right after the header line
41
+ at the top of the file:
42
+
43
+ !Option:AllXfr
44
+
45
+ Items for Non-Investment Accounts
46
+
47
+ Each item in a bank, cash, credit card, other liability, or other asset
48
+ account must begin with a letter that indicates the field in the Quicken
49
+ register. The non-split items can be in any sequence:
50
+
51
+ Field Indicator Explanation
52
+ D Date
53
+ T Amount
54
+ C Cleared status
55
+ N Num (check or reference number)
56
+ P Payee
57
+ M Memo
58
+ A Address (up to five lines; the sixth line is an optional message)
59
+ L Category (Category/Subcategory/Transfer/Class)
60
+ S Category in split (Category/Transfer/Class)
61
+ E Memo in split
62
+ $ Dollar amount of split
63
+ ^ End of the entry
64
+
65
+ Note: Repeat the S, E, and $ lines as many times as needed for additional
66
+ items in a split. If an item is omitted from the transaction in the QIF
67
+ file, Quicken treats it as a blank item.
68
+
69
+ Items for Investment Accounts
70
+
71
+ Field Indicator Explanation
72
+ D Date
73
+ N Action
74
+ Y Security
75
+ I Price
76
+ Q Quantity (number of shares or split ratio)
77
+ T Transaction amount
78
+ C Cleared status
79
+ P Text in the first line for transfers and reminders
80
+ M Memo
81
+ O Commission
82
+ L Account for the transfer
83
+ $ Amount transferred
84
+ ^ End of the entry
85
+
86
+ Items for Account Information
87
+
88
+ The account header !Account is used in two places-at the start of an account
89
+ list and the start of a list of transactions to specify to which account they
90
+ belong.
91
+
92
+ Field Indicator Explanation
93
+ N Name
94
+ T Type of account
95
+ D Description
96
+ L Credit limit (only for credit card accounts)
97
+ / Statement balance date
98
+ $ Statement balance amount
99
+ ^ End of entry
100
+
101
+ Items for a Category List
102
+
103
+ Field Indicator Explanation
104
+ N Category name:subcategory name
105
+ D Description
106
+ T Tax related if included, not tax related if omitted
107
+ I Income category
108
+ E Expense category
109
+ (if category type is unspecified, quicken assumes expense type)
110
+ B Budget amount (only in a Budget Amounts QIF file)
111
+ R Tax schedule information
112
+ ^ End of entry
113
+
114
+ Items for a Class List
115
+
116
+ Field Indicator Explanation
117
+ N Class name
118
+ D Description
119
+ ^ End of entry
120
+
121
+ Items for a Memorized Transaction List
122
+
123
+ Immediately preceding the ^ character, each entry must end with one of the
124
+ following file indicators to specify the transaction type.
125
+
126
+ KC
127
+ KD
128
+ KP
129
+ KI
130
+ KE
131
+ With that exception, memorized transaction entries have the same format as
132
+ regular transaction entries (non-investment accounts). However, the Date
133
+ or Num field is included. All items are optional, but if an amortization
134
+ record is included, all seven amortization lines must also be included.
135
+
136
+ Field Indicator Explanation
137
+ KC Check transaction
138
+ KD Deposit transaction
139
+ KP Payment transaction
140
+ KI Investment transaction
141
+ KE Electronic payee transaction
142
+ T Amount
143
+ C Cleared status
144
+ P Payee
145
+ M Memo
146
+ A Address
147
+ L Category or Transfer/Class
148
+ S Category/class in split
149
+ E Memo in split
150
+ $ Dollar amount of split
151
+ 1 Amortization: First payment date
152
+ 2 Amortization: Total years for loan
153
+ 3 Amortization: Number of payments already made
154
+ 4 Amortization: Number of periods per year
155
+ 5 Amortization: Interest rate
156
+ 6 Amortization: Current loan balance
157
+ 7 Amortization: Original loan amount
158
+ ^ End of entry
159
+
160
+ Examples of QIF files
161
+
162
+ Normal Transactions Example
163
+
164
+ Transaction Item Comment (not in file)
165
+ !Type:Bank Header
166
+ D6/ 1/94 Date
167
+ T-1,000.00 Amount
168
+ N1005 Check number
169
+ PBank Of Mortgage Payee
170
+ L[linda] Category
171
+ S[linda] First category in split
172
+ $-253.64 First amount in split
173
+ SMort Int Second category in split
174
+ $-746.36 Second amount in split
175
+ ^ End of the transaction
176
+ D6/ 2/94 Date
177
+ T75.00 Amount
178
+ PDeposit Payee
179
+ ^ End of the transaction
180
+ D6/ 3/94 Date
181
+ T-10.00 Amount
182
+ PJoBob Biggs Payee
183
+ MJ.B. gets bucks Memo
184
+ LEntertain Category
185
+ A1010 Rodeo Dr. Address (line 1)
186
+ AWaco, Tx Address (line 2)
187
+ A80505 Address (line 3)
188
+ A Address (line 4)
189
+ A Address (line 5)
190
+ A Address (line 6)
191
+ ^ End of the transaction
192
+
193
+ Investment Example
194
+
195
+ Transaction Item Comment (not in file)
196
+ !Type:Invst Header line
197
+ D8/25/93 Date
198
+ NShrsIn Action (optional)
199
+ Yibm4 Security
200
+ I11.260 Price
201
+ Q88.81 Quantity
202
+ CX Cleared Status
203
+ T1,000.00 Amount
204
+ MOpening Balance Memo
205
+ ^ End of the transaction
206
+ D8/25/93 Date
207
+ NBuyX Action
208
+ Yibm4 Security
209
+ I11.030 Price
210
+ Q9.066 Quantity
211
+ T100.00 Amount
212
+ MEst. price as of 8/25/93 Memo
213
+ L[CHECKING] Account for transfer
214
+ $100.00 Amount transferred
215
+ ^ End of the transaction
216
+
217
+ Memorized List Example
218
+
219
+ Transaction Item Comment (not in file)
220
+ !Type:Memorized Header line
221
+ T-50.00 Amount
222
+ PJoe Hayes Payee
223
+ MRent Memo
224
+ KC Check transaction
225
+ ^ End of the transaction
226
+ T-25.00 Amount
227
+ T-25.00 Company Payee
228
+ LTelephone Category
229
+ KP Payment transaction
230
+ ^ End of the transaction
231
+
@@ -0,0 +1,28 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ This is the main ruby file for this project. It contains require statements
10
+ for all of the necessary ruby standard libraries, and quick_etl custom files.
11
+
12
+ =end
13
+
14
+ # System libraries and gems:
15
+ require 'rubygems'
16
+ require 'rbconfig'
17
+ require 'date'
18
+ require 'time'
19
+ require 'sqlite3'
20
+
21
+ # Custom libraries:
22
+ require 'quick_etl_kernel'
23
+ require 'quick_etl_object'
24
+ require 'quick_etl_dbo'
25
+ require 'quick_etl_money'
26
+ require 'quick_etl_qif_date'
27
+ require 'quick_etl_qif_file_reader'
28
+ require 'quick_etl_qif_transaction'
@@ -0,0 +1,88 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ This class is used to interface with the sqlite3 database.
10
+
11
+ =end
12
+
13
+ module QuickETL
14
+
15
+ class DBO < QuickETLObject
16
+
17
+ attr_accessor :db , :db_filename
18
+
19
+ def initialize()
20
+ @db_filename = "#{home_dir}/#{QuickETL::DATABASE_FILE}"
21
+ end
22
+
23
+ def open_database
24
+ @db = SQLite3::Database.new(@db_filename)
25
+ end
26
+
27
+ def show_ddl
28
+ puts "\nThe following DDL (SQL) is used to create database #{@db_filename}"
29
+ puts ""
30
+ puts drop_transactions_ddl
31
+ puts create_transactions_ddl
32
+ puts ""
33
+ end
34
+
35
+ def drop_and_create_database
36
+ open_database
37
+ puts @db.execute(drop_transactions_ddl);
38
+ puts @db.execute(create_transactions_ddl);
39
+ puts "\nDatabase has been created - #{@db_filename}"
40
+ puts "Database schema is shown below:"
41
+ puts ""
42
+ puts `sqlite3 #{@db_filename} VACUUM`
43
+ puts `sqlite3 #{@db_filename} .schema`
44
+ puts ""
45
+ end
46
+
47
+ def drop_transactions_ddl
48
+ "drop table if exists transactions;"
49
+ end
50
+
51
+ def create_transactions_ddl
52
+ s = "create table transactions ( \n"
53
+ s << " id INTEGER PRIMARY KEY, \n"
54
+ s << " account_owner TEXT, \n"
55
+ s << " account_name TEXT, \n"
56
+ s << " account_type TEXT, \n"
57
+ s << " tran_date TEXT, \n"
58
+ s << " cleared_status TEXT, \n"
59
+ s << " item_number INTEGER, \n"
60
+ s << " amount REAL, \n"
61
+ s << " payee TEXT, \n"
62
+ s << " category TEXT, \n"
63
+ s << " memo TEXT, \n"
64
+ s << " line_number INTEGER \n"
65
+ s << ");"
66
+ s
67
+ end
68
+
69
+ def load_database
70
+ command_file = "#{home_dir}/#{LOAD_COMMAND_FILE}"
71
+ lines = Array.new
72
+ lines << ".import #{home_dir}/quick-etl.csv transactions"
73
+ write_lines(command_file, lines)
74
+ puts `sqlite3 #{@db_filename} < #{command_file}`
75
+ end
76
+
77
+ def query_all_transactions
78
+ command_file = "#{home_dir}/#{QUERY_ALL_FILE}"
79
+ results_file = "#{home_dir}/output.txt"
80
+ lines = Array.new
81
+ lines << "select * from transactions;"
82
+ write_lines(command_file, lines)
83
+ puts `sqlite3 #{@db_filename} < #{command_file} > #{results_file}`
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,295 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ This is the core module for this project, and is included in base class
10
+ QuickETLObject.
11
+
12
+ =end
13
+
14
+ module QuickETL
15
+
16
+ DATABASE_FILE = 'quick-etl.db'
17
+ PROPERTIES_FILE = 'quick-etl.properties'
18
+ LOAD_COMMAND_FILE = 'quick-etl.load'
19
+ QUERY_ALL_FILE = 'query_all.sql'
20
+ DEFAULT_QIF_FILE = 'QuickenData.qif'
21
+ DAY_NAMES = %w(Sun Mon Tue Wed Thu Fri Sat)
22
+ QUICK_ETL_HOME = 'QUICK_ETL_HOME'
23
+ QUICK_ETL_DEV_HOME = 'QUICK_ETL_DEV_HOME'
24
+
25
+ @@properties = Hash.new
26
+ @@debug = false
27
+
28
+ module QuickETLKernel
29
+
30
+ def project_name
31
+ 'QuickETL'
32
+ end
33
+
34
+ def project_version_number
35
+ '0.1.0'
36
+ end
37
+
38
+ def project_date
39
+ '2008/02/10'
40
+ end
41
+
42
+ def project_author
43
+ 'Chris Joakim'
44
+ end
45
+
46
+ def project_year
47
+ project_date[0...4] # start, length
48
+ end
49
+
50
+ def project_copyright
51
+ "Copyright (C) #{project_year} #{project_author}"
52
+ end
53
+
54
+ def project_embedded_comment
55
+ "#{project_name} #{project_version_number}"
56
+ end
57
+
58
+ def project_license
59
+ 'GNU General Public License (GPL). See http://www.gnu.org/copyleft/gpl.html'
60
+ end
61
+
62
+ def display_general_info
63
+ puts ""
64
+ puts "This is '#{project_name}'. "
65
+ puts "#{project_copyright} "
66
+ puts "#{project_license} "
67
+ puts ""
68
+ puts "QuickETL home pages: "
69
+ puts " -- http://rubyforge.org/projects/quick-etl/ "
70
+ puts " -- http://www.joakim-systems.com/ "
71
+ puts ""
72
+ puts "QuickETL uses the SQLite3 database; see the following URLs: "
73
+ puts " -- http://www.sqlite.org/"
74
+ puts " -- http://sqlite-ruby.rubyforge.org/ "
75
+ puts " -- http://sqlite-ruby.rubyforge.org/sqlite3/faq.html "
76
+ puts ""
77
+ puts "Enter 'rake help' for QuickETL usage instructions. "
78
+ puts "Enter 'rake -T' for the list of available QuickETL rake commands. "
79
+ puts ""
80
+
81
+ home = home_dir
82
+ if (home_dir)
83
+ puts "Your QuickETL home directory is currently set to: #{home_dir}"
84
+ else
85
+ puts "Warning: You have not yet set your 'QUICK_ETL_HOME' environment variable."
86
+ end
87
+ puts ""
88
+ end
89
+
90
+ def display_usage_instructions
91
+ puts "usage"
92
+ puts ""
93
+ end
94
+
95
+ def home_dir
96
+ is_dev = ENV['dev']
97
+ if ((is_dev) && (is_dev == 'y'))
98
+ ENV[QUICK_ETL_DEV_HOME]
99
+ else
100
+ ENV[QUICK_ETL_HOME]
101
+ end
102
+ end
103
+
104
+ def command_line_arg(name, default)
105
+ value = default
106
+ if name
107
+ value = ENV[name]
108
+ value = default if value == nil
109
+ end
110
+ value
111
+ end
112
+
113
+ def command_line_boolean_arg(name, default)
114
+ v = command_line_arg(name, "#{default}")
115
+ return true if ((v.downcase == 'true') || (v.downcase == 't'))
116
+ return true if ((v.downcase == 'yes') || (v.downcase == 'y'))
117
+ false
118
+ end
119
+
120
+ def command_line_array_arg(name, default)
121
+ s = command_line_arg(name, nil)
122
+ return default if s == nil
123
+ return s.split(',')
124
+ end
125
+
126
+ def get_property(name, default='')
127
+ if @@properties.has_key? "#{name}"
128
+ return @@properties["#{name}"]
129
+ end
130
+ default
131
+ end
132
+
133
+ def get_array_property(name, default=Array.new)
134
+ s = get_property(name)
135
+ if s
136
+ return s.split(',')
137
+ end
138
+ default
139
+ end
140
+
141
+ def startup
142
+ load_properties("#{home_dir}/#{QuickETL::PROPERTIES_FILE}")
143
+ end
144
+
145
+ def load_properties(properties_filename)
146
+ props = Hash.new
147
+ if File.exist? properties_filename
148
+ File.open(properties_filename, 'r') do | properties_file |
149
+ properties_file.read.each_line do |line|
150
+ line.strip!
151
+ if (line[0] != ?# and line[0] != ?=)
152
+ i = line.index('=')
153
+ if (i)
154
+ props[line[0..i - 1].strip] = line[i + 1..-1].strip
155
+ else
156
+ props[line] = ''
157
+ end
158
+ end
159
+ end
160
+ puts "properties file read - #{properties_filename} , entry count=#{props.size}" if true
161
+ end
162
+ else
163
+ puts "properties file does not exist - #{properties_filename}" if false
164
+ end
165
+ @@properties = props
166
+ end
167
+
168
+ def parse_qif_files
169
+ qif_file = command_line_arg('qif', QuickETL::DEFAULT_QIF_FILE)
170
+ qif_dir = get_property('qif_dir', home_dir)
171
+ qif_path = "#{qif_dir}/#{qif_file}"
172
+ owner = command_line_arg('owner', 'owner')
173
+ reader = QuickETL::QifFileReader.new(owner, qif_path)
174
+ array = Array.new
175
+ reader.transactions.each_with_index { | tran, idx|
176
+ array << "#{idx+1}#{tran.to_s}"
177
+ }
178
+ write_lines("#{home_dir}/quick-etl.csv", array)
179
+ end
180
+
181
+ def read_lines(filename, strip=false)
182
+ array = IO.readlines(filename)
183
+ array = strip_lines(array) if strip
184
+ array
185
+ end
186
+
187
+ def write_file(out_name, content)
188
+ out = File.new out_name, "w+"
189
+ out.write content
190
+ out.flush
191
+ out.close
192
+ puts "file written: #{out_name}"
193
+ end
194
+
195
+ def write_lines(out_name, lines)
196
+ s = ''
197
+ lines.each { | line | s << "#{line}\n" }
198
+ write_file(out_name, s)
199
+ end
200
+
201
+ def read_as_ascii_lines(filename, delim=10, strip=false)
202
+ array = Array.new
203
+ file = File.new(filename)
204
+ currLine = ''
205
+ bytesRead = 0
206
+ linesRead = 0
207
+
208
+ file.each_byte { |b|
209
+ bytesRead = bytesRead + 1
210
+ if (b == delim) # delim is 13 for quicken, 10 for address book xml
211
+ array << currLine
212
+ currLine = ''
213
+ linesRead = linesRead + 1
214
+ else
215
+ if (b < 127)
216
+ currLine << "#{b.chr}"
217
+ end
218
+ end
219
+ }
220
+ if currLine.size > 0
221
+ array << currLine
222
+ end
223
+ if strip
224
+ array = strip_lines(array)
225
+ end
226
+ array
227
+ end
228
+
229
+ def strip_lines(array)
230
+ newArray = Array.new
231
+ if (array != nil)
232
+ array.each { |line| line.strip! ; newArray << line }
233
+ end
234
+ newArray
235
+ end
236
+
237
+ def line_value(s)
238
+ if ((s == nil) || (s.size < 1))
239
+ s
240
+ else
241
+ s[1, s.size]
242
+ end
243
+ end
244
+
245
+ def tokenize(string, delim=nil, strip=false)
246
+ if string
247
+ tokens = string.split(delim)
248
+ if strip
249
+ tokens.each { |tok| tok.strip! }
250
+ end
251
+ tokens
252
+ else
253
+ Array.new
254
+ end
255
+ end
256
+
257
+ def default_delimiter
258
+ '|'
259
+ end
260
+
261
+ def usage_instructions
262
+ s = <<HERE
263
+
264
+ 1. Use your Quicken program to export its data to the QUICK_ETL_HOME directory.
265
+ Specify output file 'QuickenData.qif'.
266
+
267
+ 2. Open a shell window in your QUICK_ETL_HOME directory.
268
+
269
+ Execute command 'rake -T' to see the list of functions available.
270
+
271
+ Execute command 'rake parse' to parse the qif file into csv format.
272
+
273
+ Execute command 'rake load' to load the csv file data into sqlite3 database 'quick-etl.db'.
274
+
275
+ Execute command 'rake parse_and_load' to run both the parsing and loading function.
276
+
277
+ Execute command 'rake show_ddl' to see the structure of the database table and its column names.
278
+
279
+ 3. Use the sqlite3 CLP (Command Line Program) to query the database.
280
+ From the QUICK_ETL_HOME directory, execute command 'sqlite3 quick-etl.db'.
281
+
282
+ You can then enter and execute queries like the following:
283
+
284
+ sqlite> select * from transactions;
285
+ sqlite> select * from transactions where tran_date == '2008-02-05';
286
+
287
+ Note: A User Interface will be created for QuickETL its next release.
288
+
289
+ HERE
290
+ s
291
+ end
292
+
293
+ end
294
+
295
+ end
@@ -0,0 +1,48 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ Instances of this class represent a monetary amount from within a Quicken qif file,
10
+ such as 'T-38.09' (i.e. - $38.09 US Dollars).
11
+
12
+ =end
13
+
14
+ module QuickETL
15
+
16
+ class Money < QuickETLObject
17
+
18
+ attr_accessor :string_value, :numeric_value
19
+
20
+ def initialize(s='0.00')
21
+ s ? @string_value = s : @string_value = '0.00'
22
+ @string_value.strip!
23
+ @numeric_value = numeric(@string_value).to_f
24
+ end
25
+
26
+ def to_s
27
+ "#{@numeric_value}"
28
+ end
29
+
30
+ private
31
+
32
+ def numeric(s)
33
+ n = ''
34
+ if s
35
+ s.each_byte { | b |
36
+ if ((b == 44) || (b == 32))
37
+ # bypass commas (44) and spaces (32)
38
+ else
39
+ n << "#{b.chr}"
40
+ end
41
+ }
42
+ end
43
+ n
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,20 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ This is the abstract superclass of several QuickETL classes.
10
+ It includes module QuickETLKernel.
11
+
12
+ =end
13
+
14
+ module QuickETL
15
+
16
+ class QuickETLObject
17
+ include QuickETL::QuickETLKernel
18
+ end
19
+
20
+ end
@@ -0,0 +1,44 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ Instances of this class represent a date from within a Quicken qif file,
10
+ such as 'D5/24/94'.
11
+
12
+ =end
13
+
14
+ module QuickETL
15
+
16
+ class QifDate < QuickETLObject
17
+
18
+ attr_accessor :raw_line, :ccyymmdd, :year, :year_mm, :yy, :mm, :dd
19
+
20
+ def initialize(raw_line)
21
+ @raw_line = raw_line
22
+ @y, @m, @d = 0, 0, 0
23
+ @cc, @yy, @mm, @dd = '00', '00', '00', '00'
24
+
25
+ if @raw_line
26
+ tokens = @raw_line.split('/')
27
+ if (tokens && tokens.size > 2)
28
+ m = tokens[0].to_i
29
+ d = tokens[1].to_i
30
+ y = tokens[2].to_i
31
+ @yy = tokens[2]
32
+ y < 50 ? @cc = "20" : @cc = "19"
33
+ m < 10 ? @mm = "0#{m}" : @mm = "#{m}"
34
+ d < 10 ? @dd = "0#{d}" : @dd = "#{d}"
35
+ end
36
+ end
37
+ @ccyymmdd = "#{@cc}#{@yy}-#{@mm}-#{@dd}"
38
+ @year = "#{@cc}#{@yy}"
39
+ @year_mm = "#{@cc}#{@yy}-#{@mm}"
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,90 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ Instances of this class are used to read and parse a Quicken qif file.
10
+
11
+ =end
12
+
13
+ module QuickETL
14
+
15
+ class QifFileReader < QuickETLObject
16
+
17
+ attr_accessor :filename, :transactions, :debug
18
+
19
+ def initialize(owner, filename, debug=false)
20
+ @owner = owner
21
+ @filename = filename
22
+ @debug = debug
23
+ @transactions = Array.new
24
+ read
25
+ end
26
+
27
+ def read
28
+ @lines = read_as_ascii_lines(@filename, 13, false)
29
+ in_tran_zone = false
30
+ in_acct_header = false
31
+ @acct_name = ''
32
+ @acct_type = ''
33
+ line_num = 0
34
+ tran = QifTran.new(@owner, @acct_name, @acct_type, 0)
35
+ start_token = '!Type:Class'
36
+
37
+ @lines.each { | line |
38
+ line_num = line_num + 1
39
+
40
+ if (line == start_token)
41
+ in_tran_zone = true
42
+ next
43
+ end
44
+
45
+ if (line.match(/^!Account/))
46
+ in_acct_header = true
47
+ next
48
+ end
49
+
50
+ if in_acct_header
51
+ if (line.match(/^N/))
52
+ @acct_name = (line_value(line))
53
+ tran.acct_name = @acct_name
54
+ elsif (line.match(/^T/))
55
+ @acct_type = (line_value(line))
56
+ tran.acct_type = @acct_type
57
+ elsif (line == '^')
58
+ in_acct_header = false
59
+ end
60
+ next
61
+ end
62
+
63
+ if in_tran_zone
64
+ if (line == '^')
65
+ add_transaction(tran)
66
+ tran = QifTran.new(@owner, @acct_name, @acct_type, line_num)
67
+ else
68
+ tran.add_line(line)
69
+ end
70
+ end
71
+ }
72
+ end
73
+
74
+ def add_transaction(t)
75
+ t.parse
76
+ if t.valid
77
+ @transactions.push(t)
78
+ else
79
+ puts "invalid trans"
80
+ end
81
+ end
82
+
83
+ public
84
+
85
+ def to_s
86
+ "QifFileReader #{@filename} #{@lines.size} #{@transactions.size}"
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,91 @@
1
+ =begin rdoc
2
+
3
+ QuickETL = Quicken Extract Transform and Load
4
+ QuickETL - Copyright 2008 by Chris Joakim.
5
+ QuickETL is available under GNU General Public License (GPL) license.
6
+
7
+ -
8
+
9
+ Instances of this class represent one transaction within a Quicken qif file.
10
+
11
+ =end
12
+
13
+ module QuickETL
14
+
15
+ class QifTran < QuickETLObject
16
+
17
+ attr_accessor :raw_lines, :acct_owner, :acct_name, :acct_type, :date, :amount
18
+ attr_accessor :valid, :balance, :cleared, :category, :number, :payee, :memo
19
+
20
+ def initialize(anOwner, aName, aType, line_num, delim='|')
21
+ @acct_owner = "#{anOwner}"
22
+ @acct_name = "#{aName}"
23
+ @acct_type = "#{aType}"
24
+ @line_num = line_num
25
+ @delim = delim
26
+ @valid = false
27
+ @cleared = ' '
28
+ @number = ' '
29
+ @memo = ' '
30
+ @raw_lines = Array.new
31
+ @splits = Array.new
32
+ end
33
+
34
+ public
35
+
36
+ def add_line(line)
37
+ @raw_lines.push(line)
38
+ end
39
+
40
+ =begin
41
+ Field Indicator Explanations:
42
+ D Date
43
+ T Amount
44
+ C Cleared status
45
+ N Num (check or reference number)
46
+ P Payee
47
+ M Memo
48
+ A Address (up to five lines; the sixth line is an optional message) NOT IMPLEMENTED IN QUICK-ETL
49
+ L Category (Category/Subcategory/Transfer/Class)
50
+ S Category in split (Category/Transfer/Class)
51
+ E Memo in split
52
+ $ Dollar amount of split
53
+ ^ End of the entry
54
+ =end
55
+
56
+ def parse
57
+ @raw_lines.each { | line |
58
+ if (line.match(/^D/))
59
+ @date = QifDate.new(line_value(line))
60
+ elsif (line.match(/^T/))
61
+ s = line_value(line)
62
+ @amount = Money.new(s)
63
+ elsif (line.match(/^P/))
64
+ @payee = line_value(line)
65
+ elsif (line.match(/^C/))
66
+ @cleared = line_value(line)
67
+ elsif (line.match(/^N/))
68
+ @number = line_value(line)
69
+ elsif (line.match(/^M/))
70
+ @memo = line_value(line)
71
+ elsif (line.match(/^L/))
72
+ @category = line_value(line)
73
+ elsif (line.match(/^S/))
74
+ @split_category = line_value(line)
75
+ elsif (line.match(/^E/))
76
+ @split_memo = line_value(line)
77
+ elsif (line.match(/^$/))
78
+ @split_amount = Money.new(line_value(line))
79
+ end
80
+ }
81
+ if (@date && @amount && @payee)
82
+ @valid = true
83
+ end
84
+ end
85
+
86
+ def to_s
87
+ "#{@delim}#{@acct_owner}#{@delim}#{@acct_name}#{@delim}#{@acct_type}#{@delim}#{@date.ccyymmdd}#{@delim}#{@cleared}#{@delim}#{@number}#{@delim}#{@amount.to_s}#{@delim}#{@payee}#{@delim}#{@category}#{@delim}#{@memo}#{@delim}#{@line_num}"
88
+ end
89
+ end
90
+
91
+ end
@@ -0,0 +1,3 @@
1
+ qif_files=c
2
+ qif_file_c=QuickenData.qif
3
+ qif_file_t=TQuickenData.qif
@@ -0,0 +1,79 @@
1
+ =begin
2
+
3
+ Ruby Rakefile for Quick-ETL.
4
+
5
+ Quick-ETL - Copyright 2008 by Chris Joakim.
6
+ Quick-ETL is available under GNU General Public License (GPL) license.
7
+
8
+ http://sqlite-ruby.rubyforge.org/
9
+ http://sqlite-ruby.rubyforge.org/sqlite3/faq.html
10
+ =end
11
+
12
+ require 'rubygems'
13
+ require 'rake'
14
+ require 'rbconfig'
15
+ require 'date'
16
+ require 'time'
17
+ require 'sqlite3'
18
+
19
+ # The following prefixes /lib to the active ruby load path
20
+ #$:.unshift File.join(File.dirname(__FILE__), "", "lib")
21
+ require 'quick_etl.rb'
22
+
23
+ desc "Display information about this open-source project."
24
+ task :default do
25
+ obj = QuickETL::QuickETLObject.new
26
+ obj.display_general_info
27
+ end
28
+
29
+ desc "Display QuickETL usage instructions."
30
+ task :help do
31
+ obj = QuickETL::QuickETLObject.new
32
+ puts obj.usage_instructions
33
+ end
34
+
35
+ desc "Show the DDL (SQL) used to create the sqlite3 'quick-etl.db' database."
36
+ task :show_ddl do
37
+ dbo = QuickETL::DBO.new
38
+ dbo.show_ddl
39
+ end
40
+
41
+ desc "Drop and (re)create the sqlite3 'quick-etl.db' database."
42
+ task :drop_create_db do
43
+ startup
44
+ dbo = QuickETL::DBO.new
45
+ dbo.drop_and_create_database
46
+ end
47
+
48
+ desc "Parse *qif files into csv per properties file."
49
+ task :parse do
50
+ startup
51
+ obj = QuickETL::QuickETLObject.new
52
+ obj.parse_qif_files
53
+ end
54
+
55
+ desc "Parse *qif files into csv per properties file."
56
+ task :load do
57
+ startup
58
+ dbo = QuickETL::DBO.new
59
+ dbo.drop_and_create_database
60
+ dbo.load_database
61
+ end
62
+
63
+ desc "Parse *qif files into csv per properties file."
64
+ task :parse_and_load do
65
+ startup
66
+
67
+ obj = QuickETL::QuickETLObject.new
68
+ obj.parse_qif_files
69
+
70
+ dbo = QuickETL::DBO.new
71
+ dbo.drop_and_create_database
72
+ dbo.load_database
73
+ end
74
+
75
+ # -----------------------------------------------------------------------------
76
+
77
+ def startup
78
+ QuickETL::QuickETLObject.new.startup
79
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: quick-etl
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2008-02-10 00:00:00 -05:00
8
+ summary: Quicken Extract Transform and Load
9
+ require_paths:
10
+ - lib
11
+ email: chris@joakim-systems.com
12
+ homepage: http://rubyforge.org/projects/quick-etl/
13
+ rubyforge_project: quick-etl
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.4
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Chris Joakim
31
+ files:
32
+ - doc/qifFormatDoc.txt
33
+ - lib/quick_etl.rb
34
+ - lib/quick_etl_dbo.rb
35
+ - lib/quick_etl_kernel.rb
36
+ - lib/quick_etl_money.rb
37
+ - lib/quick_etl_object.rb
38
+ - lib/quick_etl_qif_date.rb
39
+ - lib/quick_etl_qif_file_reader.rb
40
+ - lib/quick_etl_qif_transaction.rb
41
+ - README
42
+ - rakefile.rb
43
+ - quick-etl.properties
44
+ test_files: []
45
+
46
+ rdoc_options: []
47
+
48
+ extra_rdoc_files:
49
+ - README
50
+ - rakefile.rb
51
+ - quick-etl.properties
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ requirements: []
57
+
58
+ dependencies: []
59
+