Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
// Video explanation and instructions in Dutch
// The problem:
// The ING bank only allows CSV exports of your bank statements until 16 months in the past.
// PDF exports can be downloaded for previous months but do not convert well to CSV. Most
// bookkeeping software allows import of CSV's so you don't have to type everything manually.
// The solution:
// With this script you can copy the HTML table on containing the bank statements,
// and convert it to CSV format (for Acumulus on Works on the ING website in April
// 2015. Might break when ING makes changes to the HTML/CSS of their website.
// See video. Copy the HTML table to a file "ing_table_input.html" in the same directory as this
// script. Run the script. You can copy/paste the results into a CSV file and import
// that as "Acumulus Standard". I know the script could also generate the CSV directly (fputcsv)
// but I just did not have the need to code that as well.
// Copyright © 2015 David de Boer <>
// License:
// Everyone is permitted to copy and distribute verbatim or modified
// copies of this license document, and changing it is allowed as long
// as the name is changed.
// License: Do What You Want To Public License, Version 2,
// as published by Sam Hocevar. See for more details.
// Load the table source file
$file = file_get_contents('ing_table_input.html');
$file = preg_replace('/\<ng-include.*?\<\/ng-include>/', '', $file);
$file = preg_replace('/\<h3.*?\<\/h3>/', '', $file);
// date
$file = str_replace('<td class="l-w-20 ng-binding" ng-class="{\'h-bor-0\':row.lastOfBatch}">','<date>', $file);
$file = str_replace('</td><td class="l-w-50" ng-class="{\'h-bor-0\':row.lastOfBatch}">','</date>', $file);
$file = str_replace('<td class="l-w-20 ng-binding h-bor-0" ng-class="{\'h-bor-0\':row.lastOfBatch}">','<date>', $file);
$file = str_replace('</td><td class="l-w-50 h-bor-0" ng-class="{\'h-bor-0\':row.lastOfBatch}">','</date>', $file);
// account (tegenrekening)
$file = str_replace('<div class="h-float-left l-w-70 ng-binding ng-scope" ng-if="row.counterAccount">','<account>', $file);
$file = str_replace('</div><!-- end ngIf: row.counterAccount -->','</account>', $file);
$file = str_replace('<!-- ngIf: row.counterAccount --><!-- ngIf: row.counterAccount -->','<account></account>', $file);
// amount positive or negative
$file = str_replace('Af','<neg>-</neg>', $file);
$file = str_replace('Bij','<neg></neg>', $file);
// amount
$file = str_replace('<td class="l-w-20 h-text-right h-bold ng-binding" ng-class="{\'h-bor-0\':row.lastOfBatch}">','<td class="l-w-20 h-text-right h-bold ng-binding" ng-class="{\'h-bor-0\':row.lastOfBatch}"><amount>',$file);
$file = str_replace('<td class="l-w-20 h-text-right h-bold ng-binding h-bor-0" ng-class="{\'h-bor-0\':row.lastOfBatch}">','<td class="l-w-20 h-text-right h-bold ng-binding" ng-class="{\'h-bor-0\':row.lastOfBatch}"><amount>',$file);
$file = str_replace(' <i aria-hidden="true"','</amount><i aria-hidden="true"',$file);
// description - name
$file = str_replace('<div class="h-float-left l-w-70"><!-- ngRepeat: line in row.statementLines track by $index -->','<description>', $file);
$file = str_replace('<!-- end ngRepeat: line in row.statementLines track by $index --></div>','</description>', $file);
// Unified function to get content between custom tags
function get_tags($tagname,$file){
if (preg_match_all('/\<'. preg_quote($tagname) .'>.*?\<\/'. preg_quote($tagname) .'>/', $file, $matches, PREG_PATTERN_ORDER))
$matches = $matches[0];
return $matches;
// Get and move all data into arrays
$dates = get_tags('date',$file);
$accounts = get_tags('account',$file);
$negs = get_tags('neg',$file);
$amounts = get_tags('amount',$file);
$descriptions = get_tags('description',$file);
// Combine data-arrays into one general records-array
$records = array(
// Count total records for use in for
$count_all = count($dates, COUNT_RECURSIVE);
// For debugging
// echo $count_all . '<br/><br />';
// Get and output CSV records
echo '"' . $records[0][$i] .'";"YOUR IBAN NUMBER";"' . $records[1][$i] . '";"' . $records[2][$i] . str_replace('.','',$records[3][$i]) . '";"' . trim(preg_replace('~<.+?>~s', ' ', $records[4][$i])) .'";<br />';
// For debugging
// echo '<pre>';
// print_r($records);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.