Last active
April 11, 2017 04:14
-
-
Save cookieguru/d26f737b04d463abbc597d14d6e40fe4 to your computer and use it in GitHub Desktop.
Interactive command line utility to convert a QIF (Quicken export) file to CSV or display on screen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//First check the current directory for any QIF files | |
//If one is found, use that name by default | |
foreach(scandir('.') as $file) { | |
if(strtolower(substr($file, -4)) == '.qif') { | |
$filename = $file; | |
break; | |
} | |
} | |
/** | |
* Prompts for user input | |
* @param string $msg Hint text for the user | |
* @return string The user's input | |
*/ | |
function prompt($msg) { | |
if(function_exists('readline')) { | |
return readline("$msg: "); | |
} | |
echo "$msg: "; | |
return stream_get_line(STDIN, 1024, PHP_EOL); | |
} | |
//Prompt the user for the file to read, specifying the default name if a file was found | |
$prompt_filename = prompt('Filename' . (isset($filename) ? " [$filename]" : null)); | |
if(empty($prompt_filename)) { | |
if(!isset($filename)) { | |
echo "No file to open\n"; | |
exit(-1); | |
} | |
} else { | |
$filename = $prompt_filename; | |
} | |
//Prompt user for the destination and a filename that won't clobber unless told to do so | |
$destination = prompt('Output [C]SV or [s]creen? [c]'); | |
if(strtolower($destination) != 's') { | |
$destination = 'c'; | |
$output_filename = substr($filename, 0, -3) . 'csv'; | |
$prompt_outfile = prompt("Output filename [$output_filename]"); | |
if(!empty($prompt_outfile)) { | |
$output_filename = $prompt_outfile; | |
} | |
while(file_exists($output_filename) || empty($output_filename)) { | |
$prompt_overwrite = prompt("$output_filename exists; overwrite [y/n]? [n]"); | |
if(strtolower($prompt_overwrite) == 'y' && !empty($output_filename)) { | |
break; | |
} else { | |
$output_filename = prompt("Output filename"); | |
} | |
} | |
} | |
try { | |
$lines = new SplFileObject($filename); | |
$lines->setFlags(SplFileObject::DROP_NEW_LINE); | |
} catch(\RuntimeException $e) { | |
echo "Cannot open $filename\n"; | |
exit(-1); | |
} | |
//Read data in to a 3D array | |
$data = []; | |
$row = 0; | |
foreach($lines as $line) { | |
$code = substr($line, 0, 1); | |
if($code == '!') { | |
continue; | |
} | |
if($code == '^') { | |
$row++; | |
continue; | |
} | |
$value = substr($line, 1); | |
if($code == 'D') { | |
$value = str_replace("'", '/20', $value); | |
} | |
if($code == 'T') { | |
$value = str_replace(",", NULL, $value); | |
} | |
$data[$row][$code] = $value; | |
} | |
//Calculate maximum column widths and remove rows without data | |
$maxlength = array_fill_keys(['a', 'D', 'N', 'P', 'T'], 1); | |
$account = 'Unknown'; | |
foreach($data as $row => $values) { | |
if(!isset($values['P'])) { | |
unset($data[$row]); | |
$account = $values['N']; | |
continue; | |
} | |
foreach(['D', 'N', 'P', 'T'] as $code) { | |
if(!isset($values[$code])) { | |
$data[$row][$code] = null; | |
} | |
$maxlength[$code] = max($maxlength[$code], strlen($data[$row][$code]) + 1); | |
} | |
$data[$row]['a'] = $account; | |
$maxlength['a'] = max($maxlength['a'], strlen($data[$row]['a']) + 1); | |
} | |
//Output data | |
if($destination == 'c') { | |
$bytes = 0; | |
$file = new SplFileObject($output_filename, 'w+'); | |
foreach($data as $values) { | |
if(!isset($values['P'])) { | |
continue; | |
} | |
$bytes += $file->fputcsv([$values['a'], $values['D'], $values['N'], $values['P'], $values['T']]); | |
} | |
echo "Wrote $bytes bytes to $output_filename\n"; | |
} else { | |
foreach($data as $values) { | |
echo str_pad($values['a'], $maxlength['a']); | |
echo str_pad($values['D'], $maxlength['D']); | |
echo str_pad($values['N'], $maxlength['N']); | |
echo str_pad($values['P'], $maxlength['P']); | |
echo str_pad($values['T'], $maxlength['T'], ' ', STR_PAD_LEFT); | |
echo "\n"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment