G'day ibm1620,
"But I can't get over the feeling that there is a much simpler solution that's eluded me."
I knocked this off in my lunch break:
I expect there are many opportunities for improvement;
however, it's certainly simpler than the code you posted.
#!/usr/bin/env perl
use v5.36;
use autodie;
use constant {
DATE => 0,
AMOUNT => 1,
CATEGORY => 2,
DESCRIPTION => 3,
};
use Text::CSV;
my $csv_file = 'pm_11145274_tabulate_csv.csv';
# Dummy figures from 1st pass which you say you know how to do
my @max_widths = qw{10 6 15 55};
say 'Shrunk to fit 52-char-wide window';
tabulate($csv_file, \@max_widths, 52);
say 'Shrunk to fit 46-char-wide window';
tabulate($csv_file, \@max_widths, 46);
sub tabulate ($filename, $max_widths, $table_width) {
state $des_weight = 0.7;
my $table_available = $table_width - 4; # 4 pipe chars
my $data_fmt = '%8d|'; # date: YYYYMMDD
my $head_fmt = '%-8s|';
$table_available -= 8;
$data_fmt .= '%6.2f|'; # amount: | 12.34|
$head_fmt .= '%-6s|';
$table_available -= 6;
my $max_cat_des = $max_widths->[CATEGORY] + $max_widths->[DESCRIPT
+ION];
my $cat_width = int($table_available * ($max_widths->[CATEGORY] /
+$max_cat_des));
my $des_width = int($table_available * ($max_widths->[DESCRIPTION]
+ / $max_cat_des));
$des_width = int($des_width * $des_weight);
$cat_width += $table_available - ($cat_width + $des_width);
$data_fmt .= "%-${cat_width}.${cat_width}s|%-${des_width}.${des_wi
+dth}s|\n";
$head_fmt .= "%-${cat_width}s|%-${des_width}s|\n";
my $csv = Text::CSV::->new();
{
open my $fh, '<', $filename;
my $head_row = $csv->getline($fh);
printf $head_fmt, @$head_row;
while (my $data_row = $csv->getline($fh)) {
printf $data_fmt, $data_row->[DATE] =~ y/-//dr,
$data_row->@[AMOUNT, CATEGORY, DESCRIPTION];
}
}
return;
}
I used this for input.
You may need some code adjustments depending on what your real input looks like.
$ cat pm_11145274_tabulate_csv.csv
Date,Amount,Category,Description
2022-06-23,123.45,Software & Tech,BACKBLAZE HTTPSWWW.BACKCA
2022-06-24,63.45,Internet,RECURRING PAYMENT AUTHORIZED ON 06/11 SPECTR
+UM TX
2022-06-24,69.34,Phone,RECURRING PAYMENT AUTHORIZED ON 06/02 VZWRLSS*A
+POCC VISE
I reduced the YYYY-MM-DD date to YYYYMMDD to free up a couple of extra characters and aligned the amounts.
Fiddle with the arithmetic to get exactly what you want: adjusting $des_weight may be all that you need.
Here's the output:
$ ./pm_11145274_tabulate_csv.pl
Shrunk to fit 52-char-wide window
Date |Amount|Category |Description |
20220623|123.45|Software & Tech |BACKBLAZE HTTPSWWW|
20220624| 63.45|Internet |RECURRING PAYMENT |
20220624| 69.34|Phone |RECURRING PAYMENT |
Shrunk to fit 46-char-wide window
Date |Amount|Category |Description |
20220623|123.45|Software & Te|BACKBLAZE HTTPS|
20220624| 63.45|Internet |RECURRING PAYME|
20220624| 69.34|Phone |RECURRING PAYME|