Question

I wish to modify my code in such a way that the column widens to accommodate the data.

Below is an example of a broken row

+========+=========+===============+=============+=============+
| Record | Cluster | Current Build | Current Use | Environment |
+--------+---------+---------------+-------------+-------------+
| 3      | 1       | v44           | v44 Live (currently - new company cluster)| PROD        |
+--------+---------+---------------+-------------+-------------+

Here is the (kludgy) code I'm using

sub printData {
   if (@_) {
      # print the data grid top border
      printf ("%10s%10s%15s%14s%14s",'+'.('=' x 8).'+',('=' x 9).'+',('=' x 15).'+',('=' x 13).'+',('=' x 13).'+');
      print "\n";
      # print the data grid column titles
      printf ("%-9s%-10s%-16s%-14s%-15s",'| Record ','| Cluster ','| Current Build ','| Current Use ','| Environment |');
      print "\n";

      # print out each row of data
      foreach my $rows (@_) {

         # print the data grid demarcation border
         printf ("%10s%10s%15s%14s%14s",'+'.('-' x 8).'+',('-' x 9).'+',('-' x 15).'+',('-' x 13).'+',('-' x 13).'+');
         print "\n";

         # print each data cell
         printf ("%-9s",'| '.$rows->{'Record ID#'});
         printf ("%-10s",'| '.$rows->{'Cluster'});
         printf ("%-16s",'| '.$rows->{'Current Build'});
         printf ("%-14s",'| '.$rows->{'Current Use'});

            # calculate the length of the last column
            my $length = length($rows->{'Environment'});

            # calculate how many spaces to add to the last column
            # the title of this column uses 15 characters (including '|' and spaces)
            # we already used three of those spaces for 2 '|' characters  and 1 leading space
            # so 15 - 3 = 12 
            # then subtract the length of the return string from 12
            my $spaces = 12 - $length;

         # we print the last data cell plus the padding spaces calculated above
         printf ("%-15s",'| '.$rows->{'Environment'}.(' ' x $spaces).'|');
         print "\n";
      }

      # we print the bottom data grid border
      printf ("%10s%10s%15s%14s%14s",'+'.('=' x 8).'+',('=' x 9).'+',('=' x 15).'+',('=' x 13).'+',('=' x 13).'+');
      print "\n";
    }
   else {  
      if ($debug) {
         print "trouble with printData subroutine\n";
      }
      return 0;
    }
}
Was it helpful?

Solution

Text::Table will adjust column widths to fit the data.

OTHER TIPS

You have to pre-scan the data do get the max width of each field, then build your formatting strings.

Text::SimpleTable::AutoWidth is extremely straightforward, and less fiddly than Text::Table.

I'm not familiar with either of the modules already suggested, so if they don't work as you'd like then I'd do as Mouse Food suggested and pre-scan the data to get the maximum width in each column. These maximum widths would then be used in a format string when outputting. If possible it would probably be more efficient to obtain this maximum value while building the array, rather than iterating through it twice at the end.

The code below iterates through the entire array to find the maximum column lengths, but it should be easily adapted if you're calculating it as you go. Also, I've written this off the cuff and haven't tested it, but it should give you the idea.

my %maximums = {
    "Record ID#" => 0,
    "Cluster" => 0,
    "Current Build" => 0,
    "Current Use" => 0
};

# calculate the maximum length of the values in each column
foreach my $row (@_) {
    foreach my $col (keys %maximums) {
        my $col_length = length($row->{$col});
        $maximums{key} = $col_length if ($col_length > $maximums{$col});
    }
}

# Generate a format string using the maximum column widths.  Other format strings
# may be generated in this loop for the other parts of the table.  Alternatively
# you could probably transform the one string and replace the characters in it.
my $row_format = "|";
foreach my $col (keys %maximums) {
    $row_format .= " %-",$maximums{$key},"s |";
}
$row_format .= "\n";

# Print your headers and borders here, using the other format strings that you
# would calculate above (where $row_format is generated).

# Print each row in the table
foreach my $row (@_) {
    printf($row_format, $row->{"Record ID#"}, $row->{"Cluster"},
        $row->{"Current Build"}, $row->{"Current Use"});
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top