{"id":13937205,"url":"https://github.com/reubano/csv2ofx","last_synced_at":"2025-04-12T23:36:08.357Z","repository":{"id":4875428,"uuid":"6030562","full_name":"reubano/csv2ofx","owner":"reubano","description":"A Python library and command line tool for converting csv to ofx and qif files","archived":false,"fork":false,"pushed_at":"2024-05-04T22:35:30.000Z","size":4598,"stargazers_count":199,"open_issues_count":26,"forks_count":113,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-10-30T06:57:28.814Z","etag":null,"topics":["cli","csv","data","featured","finance","library","ofx","qif"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reubano.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-10-01T13:53:08.000Z","updated_at":"2024-10-16T08:50:54.000Z","dependencies_parsed_at":"2024-02-01T06:27:45.751Z","dependency_job_id":"ad9b0d3c-54a1-4c4a-9747-1b57adb758cd","html_url":"https://github.com/reubano/csv2ofx","commit_stats":{"total_commits":570,"total_committers":28,"mean_commits":"20.357142857142858","dds":"0.10526315789473684","last_synced_commit":"04b78efaee519a33eccb095c9b4a5a034de4a290"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fcsv2ofx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fcsv2ofx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fcsv2ofx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reubano%2Fcsv2ofx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reubano","download_url":"https://codeload.github.com/reubano/csv2ofx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247112744,"owners_count":20885606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","csv","data","featured","finance","library","ofx","qif"],"created_at":"2024-08-07T23:03:23.099Z","updated_at":"2025-04-04T03:05:20.669Z","avatar_url":"https://github.com/reubano.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# csv2ofx\n\n[![travis](https://img.shields.io/travis/reubano/csv2ofx/master.svg)](https://app.travis-ci.com/github/reubano/csv2ofx)\n[![versions](https://img.shields.io/pypi/pyversions/csv2ofx.svg)](https://pypi.python.org/pypi/csv2ofx)\n[![pypi](https://img.shields.io/pypi/v/csv2ofx.svg)](https://pypi.python.org/pypi/csv2ofx)\n\n## INTRODUCTION\n\n[csv2ofx](http://github.com/reubano/csv2ofx) is a [Python library](#library-examples) and [command line interface program](#cli-examples) that converts CSV files to OFX and QIF files for importing into GnuCash or similar financial accounting programs. csv2ofx has built in support for importing csv files from mint, yoodlee, and xero.\n\n## Requirements\n\ncsv2ofx has been tested and is known to work on Python 3.7, 3.8, and 3.9; and PyPy3.7.\n\n## INSTALLATION\n\n(You are using a [virtualenv](http://www.virtualenv.org/en/latest/index.html), right?)\n\n  sudo pip install csv2ofx\n\n## Usage\n\ncsv2ofx is intended to be used either directly from Python or from the command line.\n\n### Library Examples\n\n*normal OFX usage*\n\n```python\nimport itertools as it\n\nfrom meza.io import read_csv, IterStringIO\nfrom csv2ofx import utils\nfrom csv2ofx.ofx import OFX\nfrom csv2ofx.mappings.default import mapping\n\nofx = OFX(mapping)\nrecords = read_csv('path/to/file.csv', has_header=True)\ngroups = ofx.gen_groups(records)\ntrxns = ofx.gen_trxns(groups)\ncleaned_trxns = ofx.clean_trxns(trxns)\ndata = utils.gen_data(cleaned_trxns)\ncontent = it.chain([ofx.header(), ofx.gen_body(data), ofx.footer()])\n\nfor line in IterStringIO(content):\n    print(line)\n```\n\n*normal QIF usage*\n\n```python\nimport itertools as it\n\nfrom tabutils.io import read_csv, IterStringIO\nfrom csv2ofx import utils\nfrom csv2ofx.qif import QIF\nfrom csv2ofx.mappings.default import mapping\n\nqif = QIF(mapping)\nrecords = read_csv('path/to/file.csv', has_header=True)\ngroups = qif.gen_groups(records)\ntrxns = qif.gen_trxns(groups)\ncleaned_trxns = qif.clean_trxns(trxns)\ndata = utils.gen_data(cleaned_trxns)\ncontent = it.chain([qif.gen_body(data), qif.footer()])\n\nfor line in IterStringIO(content):\n    print(line)\n```\n\n### CLI Examples\n\n*show help*\n\n  csv2ofx -h\n\n```bash\nusage: csv2ofx [options] \u003csource\u003e \u003cdest\u003e\n\ndescription: csv2ofx converts a csv file to ofx and qif\n\npositional arguments:\n  source                the source csv file (default: stdin)\n  dest                  the output file (default: stdout)\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -a TYPE, --account TYPE\n                        default account type 'CHECKING' for OFX and 'Bank' for QIF.\n  -e DATE, --end DATE   end date (default: today)\n  -B BALANCE, --ending-balance BALANCE\n                        ending balance (default: None)\n  -l LANGUAGE, --language LANGUAGE\n                        the language (default: ENG)\n  -s DATE, --start DATE\n                        the start date\n  -y, --dayfirst        interpret the first value in ambiguous dates (e.g. 01/05/09) as the day\n  -m MAPPING_NAME, --mapping MAPPING_NAME\n                        the account mapping (default: default)\n  -x FILE_PATH, --custom FILE_PATH\n                        path to a custom mapping file\n  -c FIELD_NAME, --collapse FIELD_NAME\n                        field used to combine transactions within a split for double entry statements\n  -C ROWS, --chunksize ROWS\n                        number of rows to process at a time (default: 2 ** 14)\n  -r ROWS, --first-row ROWS\n                        the first row to process (zero based)\n  -R ROWS, --last-row ROWS\n                        the last row to process (zero based, negative values count from the end)\n  -O COLS, --first-col COLS\n                        the first column to process (zero based)\n  -L, --list-mappings   list the available mappings\n  -V, --version         show version and exit\n  -q, --qif             enables 'QIF' output instead of 'OFX'\n  -M, --ms-money        enables MS Money compatible 'OFX' output\n  -o, --overwrite       overwrite destination file if it exists\n  -D DATE, --server-date DATE\n                        OFX server date (default: source file mtime)\n  -E ENCODING, --encoding ENCODING\n                        File encoding (default: utf-8)\n  -d, --debug           display the options and arguments passed to the parser\n  -v, --verbose         verbose output\n```\n\n*normal usage*\n\n\tcsv2ofx file.csv file.ofx\n\n*print output to stdout*\n\n\tcsv2ofx ~/Downloads/transactions.csv\n\n*read input from stdin*\n\n\tcat file.csv | csv2ofx\n\n*qif output*\n\n\tcsv2ofx -q file.csv\n\n*specify date range from one year ago to yesterday with qif output*\n\n\tcsv2ofx -s '-1 year' -e yesterday -q file.csv\n\n*use yoodlee settings*\n\n\tcsv2ofx -m yoodlee file.csv\n\n\n#### Special cases\n\nSome banks, like *UBS Switzerland*, may provide CSV exports that are not\nreadily tractable by csv2ofx because of extra header or trailing lines,\nredundant or unwanted columns. These input files can be preprocessed with the\nshipped `utilz/csvtrim` shell script. F.i., with mapping `ubs-ch-fr`:\n\n    csvtrim untrimmed.csv | csv2ofx -m ubs-ch-fr\n\n\n## CUSTOMIZATION\n\n### Code modification\n\nIf you would like to import csv files with field names different from the default, you can modify the mapping file or create your own. New mappings must be placed in the `csv2ofx/mappings` folder (otherwise you must use the ). The mapping object consists of a dictionary whose keys are OFX/QIF attributes and whose values are functions which should return the corresponding value from a record (csv row). The mapping function will take in a record, e.g.,\n\n```python\n{'Account': 'savings 2', 'Date': '1/3/15', 'Amount': 5000}\n```\n\nThe most basic mapping function just returns a specific field or value, e.g.,\n\n```python\nfrom operator import itemgetter\n\nmapping = {\n    'bank': 'BetterBank',\n    'account': itemgetter('Account'),\n    'date': itemgetter('Date'),\n    'amount': itemgetter('Amount')}\n```\n\nBut more complex parsing is also possible, e.g.,\n\n```python\nmapping = {\n    'account': lambda r: r['Details'].split(':')[0],\n    'date': lambda r: '%s/%s/%s' % (r['Month'], r['Day'], r['Year']),\n    'amount': lambda r: r['Amount'] * 2,\n    'first_row': 1,\n    'last_row': 10,\n    'filter': lambda r: r['Amount'] \u003e 10,\n}\n```\n\n### Required field attributes\n\nattribute | description | default field | example\n----------|-------------|---------------------|--------\n`account`|transaction account|Account|BetterBank Checking\n`date`|transaction date|Date|itemgetter('Transaction Date')\n`amount`|transaction amount|Amount|itemgetter('Transaction Amount')\n\n### Optional field attributes\n\nattribute | description | default field | default value | example\n----------|-------------|---------------|---------------|--------\n`desc`|transaction description|Reference|n/a|shell station\n`payee`|transaction payee|Description|n/a|Shell\n`notes`|transaction notes|Notes|n/a|for gas\n`check_num`|the check or transaction number|Row|n/a|2\n`id`|transaction id|`check_num`|Num|n/a|531\n`bank`|the bank name|n/a|`account`|Bank\n`account`|transaction account type|n/a|checking|savings\n`account_id`|transaction account id|n/a|hash of `account`|bb_checking\n`type`|transaction type (either debit or credit)|n/a|CREDIT if amount \u003e 0 else DEBIT|debit\n`balance`|account balance|n/a|n/a|$23.00\n`class`|transaction class|n/a|n/a|travel\n\n### Optional value attributes\n\nattribute | description | default value | example\n----------|-------------|---------------|--------\n`has_header`|does the csv file have a header row|True\n`custom_header`|header row to use (e.g. if not provided in csv)|None|[\"Account\",\"Date\",\"Amount\"]\n`is_split`|does the csv file contain split (double entry) transactions|False\n`currency`|the currency ISO code|USD|GBP\n`delimiter`|the csv field delimiter|,|;\n`date_fmt`|custom QIF date output format|%m/%d/%y|%m/%d/%Y\n`dayfirst`|interpret the first value in ambiguous dates (e.g. 01/05/09) as the day (ignored if `parse_fmt` is present)|False|True\n`parse_fmt`|transaction date parsing format||%m/%d/%Y\n`first_row`|the first row to process (zero based)|0|2\n`last_row`|the last row to process (zero based, negative values count from the end)|inf|-2\n`first_col`|the first column to process (zero based)|0|2\n`filter`|keep transactions for which function returns true||lambda tr: tr['amount'] \u003e 10\n\n## Scripts\n\ncsv2ofx comes with a built in task manager `manage.py`.\n\n### Setup\n\n  pip install -r dev-requirements.txt\n\n### Examples\n\n*Run python linter and nose tests*\n\n```bash\nmanage lint\nmanage test\n```\n\n## Contributing\n\nPlease mimic the coding style/conventions used in this repo. If you add new classes or functions, please add the appropriate doc blocks with examples. Also, make sure the python linter and nose tests pass.\n\nReady to contribute? Here's how:\n\n1. Fork and clone.\n\n```bash\ngit clone git@github.com:\u003cyour_username\u003e/csv2ofx.git\ncd csv2ofx\n```\n\n2. Setup a new [virtualenv](http://www.virtualenv.org/en/latest/index.html)\n\n```bash\nmkvirtualenv -i pkutils csv2ofx\nactivate csv2ofx\npython setup.py develop\npip install -r dev-requirements.txt\n```\n\n3. Create a branch for local development\n\n```bash\ngit checkout -b name-of-your-bugfix-or-feature\n```\n\n4. Make your changes, run linter and tests (see above), and submit a pull request through the GitHub website.\n\n### Adding Mappings\n\nHow to contribute a mapping:\n\n1. Add the mapping in `csv2ofx/mappings/`\n2. Add a simple example CSV file in `data/test/`.\n3. Add the OFX or QIF file that results from the mapping and example CSV file in `data/converted/`.\n4. Add a `csv2ofx` call for your mapping to the tests in `tests/test.py`, in `PRE_TESTS`. If you added an OFX (not QIF) converted file, pay attention to the `-e` (end date) and `-D` (server date) arguments in the test- otherwise tests may pass on your workstation and fail on the build server.\n5. Ensure your test succeeds (see above).\n\n## License\n\ncsv2ofx is distributed under the [MIT License](http://opensource.org/licenses/MIT), the same as [meza](https://github.com/reubano/meza).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freubano%2Fcsv2ofx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freubano%2Fcsv2ofx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freubano%2Fcsv2ofx/lists"}