# since the order of the columns is significant, we # use an array to hold information about each column. my @COL_INFO = ( { name => 'foo_id', hide => 1 }, { name => 'foo', id => 'foo_id', width => 400, gen => \&gen_foo, title => 'Foo' }, { name => 'bar', width => 200, align => 'right', title => 'Barque' } ); #### # now we can derive whichever other hashes or arrays # we might want from the above data. having a list # of column names is always handy: my @COL_NAMES = map $_->{name}, @COL_INFO; # and we might want to look up columns by name: my %COL_BY_NAME; @COL_BY_NAME{ @COL_NAMES } = @COL_INFO; # and to find the index of a column name: my %COL_INDEX; @COL_INDEX{ @COL_NAMES } = 0 .. $#COL_INFO; #### # ------------------------------------------------------- # the information is centralized for other uses, such as # printing headers: print ""; foreach my $info ( @COL_INFO ) { # skip hidden fields next if $info->{hide}; # build up opening tag my $header = "{width} ) { $header .= qq| width="$width"|; } $header .= ">"; print( $header . escapeHTML( $info->{title} ) . "\n" ); } print "\n"; # ------------------------------------------------------- # then for each row: while ( my $cur = $sth->fetch() ) { # if necessary, you can construct a hash using # whatever keys you want, not just db column names: my %row; @row{ @COL_NAMES } = @$cur; # or maybe just pick out one value my $foo_id = $cur->[ $COL_INDEX{foo_id} ]; # formatting the output is now easier, too: print qq|\n|; foreach my $info ( @COL_INFO ) { my $cell = "{align}; $cell .= ">"; if ( my $gen = $info->{gen} ) { $cell .= $gen->( $cur ); } else { my $ix = $COL_INDEX{ $info->{name} }; $cell .= escapeHTML( $cur->[$ix] ); } $cell .= "\n"; print $cell; } print "\n"; }