alokranjan has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

Can anyone please let me know how can I print the values of hash in tabular form in Pel CGI?

Below is my code, which is not showing the table:

print $cgi->header(), $cgi->start_html("Fruits and colors"), $cgi->table({-border=>1}, $cgi->Tr($cgi->th([" Fruit"," Color"])), for my $f (keys %tbl){ map { $cgi->Tr($cgi->td([$f,$tbl{$f}])) } sort keys %tbl } ), $cgi->end_html();
Any help/assistance would be highly appreciated.

Thanks

Alok

Replies are listed 'Best First'.
Re: Table in Perl CGI
by GrandFather (Saint) on Aug 02, 2015 at 09:54 UTC

    As a general thing mixing HTML and code is a Bad Thing because it makes it harder to maintain both the code and the HTML. Better is to use modules such as HTML::Template which lets you write most of the page as an ordinary HTML file and add a little magic to allow parts of the HTML to be provided by the script. Consider:

    #!/usr/bin/perl use strict; use warnings; use HTML::Template; my $htmlStr = <<HTML; Content-Type: text/html; charset=ISO-8859-1 <!DOCTYPE HTML> <html> <head> </head> <body> <table border=1> <TMPL_LOOP name=fruits> <tr> <td><TMPL_VAR name=fruit /></td> <td><TMPL_VAR name=color /></td> </tr> </TMPL_LOOP></table> </body> </html> HTML my %tbl = ( orange => 'orange', lime => 'lime', lemon => 'lemon', bannannanna => 'yellow' ); my @fruits = map {{fruit => $_, color => $tbl{$_}}} keys %tbl; my $template = HTML::Template->new(scalarref => \$htmlStr); $template->param(fruits => \@fruits); print $template->output();

    Prints:

    Content-Type: text/html; charset=ISO-8859-1 <!DOCTYPE HTML> <html> <head> </head> <body> <table border=1> <tr> <td>lime</td> <td>lime</td> </tr> <tr> <td>orange</td> <td>orange</td> </tr> <tr> <td>lemon</td> <td>lemon</td> </tr> <tr> <td>bannannanna</td> <td>yellow</td> </tr> </table> </body> </html>

    Usually an external file would be used instead of the here doc and string in the sample.

    Update: output fixed - thanks CountZero

    Premature optimization is the root of all job security
Re: Table in Perl CGI
by CountZero (Bishop) on Aug 02, 2015 at 12:30 UTC
    HTML::HashTable is a quite old module, but it does exactly what you want. It even takes care of nested data-structures.

    use Modern::Perl qw/2015/; use CGI; use HTML::HashTable; my %fruits = ( apple => { 'granny smith' => 'green', 'pink lady' => 'red', 'golden delicious' => 'yellow' }, melon => 'yellow', strawberry => 'red', blueberry => 'blue', durian => 'light yellow' ); my $cgi = CGI->new(); print $cgi->header(), $cgi->start_html("Fruits and colors"), tablify( { DATA => \%fruits, } ), $cgi->end_html();
    Output:
    Content-Type: text/html; charset=ISO-8859-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-U +S"> <head> <title>Fruits and colors</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1 +" /> </head> <body> <table border=1> <tr> <td>apple</td> <td> <table border=1> <tr> <td>golden delicious</td> <td>yellow</td> </tr> <tr> <td>granny smith</td> <td>green</td> </tr> <tr> <td>pink lady</td> <td>red</td> </tr> </table> </td> </tr> <tr> <td>blueberry</td> <td>blue</td> </tr> <tr> <td>durian</td> <td>light yellow</td> </tr> <tr> <td>melon</td> <td>yellow</td> </tr> <tr> <td>strawberry</td> <td>red</td> </tr> </table> </body> </html>

    apple
    golden delicious yellow
    granny smith green
    pink lady red
    blueberry blue
    durian light yellow
    melon yellow
    strawberry red

    Update: Added missing closing </table> tag. Thank you beech

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: Table in Perl CGI
by 1nickt (Canon) on Aug 02, 2015 at 15:57 UTC

    What‽ No love for jeffa's new Spreadsheet::HTML

    #!/usr/bin/perl -w use strict; use Spreadsheet::HTML; my %hash = ( kumquat => 'orange', pomegranate => 'red', cherimoya => 'green', ling +onberry => 'purple' ); my $data = [ [sort keys %hash], [sort { $a cmp $b } values %hash] ]; my $generator = Spreadsheet::HTML->new( data => $data, matrix => 1, # no <th> indent => ' ' ); print $generator->portrait; __END__

    Output:

    <table> <tr> <td>cherimoya</td> <td>kumquat</td> <td>lingonberry</td> <td>pomegranate</td> </tr> <tr> <td>green</td> <td>orange</td> <td>purple</td> <td>red</td> </tr> </table>

    Now if there was just a way to make a callback sub that would color the table cells with the fruit colors ...

    #!/usr/bin/perl -w use strict; use Spreadsheet::HTML; my %hash = ( kumquat => 'orange', pomegranate => 'red', cherimoya => 'green', lin +gonberry => 'purple' ); my ($fruits, $colors) = ( [sort keys %hash], [sort { $a cmp $b } value +s %hash] ); my $data = [ $fruits, $colors ]; my $generator = Spreadsheet::HTML->new( data => $data, indent => ' ', th => { style => { background => $colors } }, td => [ sub { my $c = shift; $c =~ s!(.*)!<font color="$1">$1</f +ont>!; return $c } ], ); print $generator->portrait; __END__

    Output:

    <table> <tr> <th style="background: green">cherimoya</th> <th style="background: orange">kumquat</th> <th style="background: purple">lingonberry</th> <th style="background: red">pomegranate</th> </tr> <tr> <td><font color="green">green</font></td> <td><font color="orange">orange</font></td> <td><font color="purple">purple</font></td> <td><font color="red">red</font></td> </tr> </table>

    Yep, I know this is deprecated HTML; just playing :-)

    The way forward always starts with a minimal test.

      Thank you for checking out my module, this really is an honor. :) You can simplify a few things, for what it is worth:

      use strict; use warnings; use Spreadsheet::HTML qw( portrait ); my %hash = ( kumquat => 'orange', pomegranate => 'red', cherimoya => 'green', lingonberry => 'purple' ); my @data = ( [sort keys %hash], [map $hash{$_}, sort keys %hash] ); print portrait( data => \@data, indent => ' ', th => { style => { background => $data[1] } }, td => { style => { background => $data[1] } }, ); __DATA__ <table> <tr> <th style="background: green">cherimoya</th> <th style="background: orange">kumquat</th> <th style="background: purple">lingonberry</th> <th style="background: red">pomegranate</th> </tr> <tr> <td style="background: green">green</td> <td style="background: orange">orange</td> <td style="background: purple">purple</td> <td style="background: red">red</td> </tr> </table>

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      

        It's working nicely ... I wrote the post above after simply testing it out in response to the OP; I'm using it now to build some nightly reports. I particularly like how easy it is to pass attributes to the tag builder. You're right about simplifying, I haven't needed to use a callback at all (but it's nice to know it's built-in for when it's needed).

        The way forward always starts with a minimal test.
      Many thanks for the suggestion.

      Can you please let me know if I can use "if" condition with the value of my hash and then decide the color of the cell in the table?

      Thanks
      Alok
Re: Table in Perl CGI
by pme (Monsignor) on Aug 02, 2015 at 09:27 UTC
    Hi Alok,

    This is one of the ways.

    #!/usr/bin/perl use strict; use warnings; use CGI; my $cgi = CGI->new; my %tbl = ( one => 1, two => 2, three => 3, four => 4, ); print $cgi->header(), $cgi->start_html("Fruits and colors"), $cgi->table({-border=>1}), $cgi->Tr($cgi->th([" Fruit"," Color"])); foreach my $key (sort keys %tbl) { print $cgi->Tr($cgi->td([$key, $tbl{$key}])); } print $cgi->end_table(); print $cgi->end_html();
Re: Table in Perl CGI
by i5513 (Pilgrim) on Aug 02, 2015 at 09:41 UTC
    Hello,

    Cgi module has been deprecated removed from core, so I think it is better to learn about Template toolkit, see how to use hash on TT

    See next code to see how to work with your example:
    #!/usr/bin/perl -w use strict; use Template; # Define hash my %fruits= ( "naranja" => "naranja" , "limón" => "amarillo" ); # Simulate a file (this content should be separated normally, on a fil +e) my $html = << 'EOT'; <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>fruits and colors</title> </head> <body> <table border="1"> <tr> <th>Fruit</th> <th>Color</th> </tr> [%# The end string "-%" will remove empty lines from source code -%] [% FOREACH fruit IN fruits.keys -%] <tr> <td> [% fruit -%] </td> <td> [% fruits.$fruit -%] </td> </tr> [% END -%] </table> </body> </html> EOT # Create the template var: my $template=Template->new(); # Process the template, telling that fruits var inside the template is + %fruits on perl code # and that $html has the template text: $template -> process (\$html,{ fruits => \%fruits }) || die $template- +>error(); # Read man Template to know more about this module
    Regards,
    Updated after read Re^2: Table in Perl CGI
    Updated with an example after read Re^2: Table in Perl CGI, i think it is better to know about TT before than after.

      I upvoted the parent for the generally good advice, but was sorely tempted to downvote for the intial, erroneous (though not quite FUD) statment. See also GrandFather's far more detailed (and nuanced) discussion at Re: Table in Perl CGI.

      http://search.cpan.org/dist/perl-5.20.0/pod/perldelta.pod#Module_removals

      Module removals
      
      The following modules will be removed from the core distribution in a future release, and will at that time need to be installed from CPAN. Distributions on CPAN which require these modules will need to list them as prerequisites.
      
      The core versions of these modules will now issue "deprecated"-category warnings to alert you to this fact. To silence these deprecation warnings, install the modules in question from CPAN.
      
      Note that the planned removal of these modules from core does not reflect a judgement about the quality of the code and should not be taken as a suggestion that their use be halted. Their disinclusion from core primarily hinges on their necessity to bootstrapping a fully functional, CPAN-capable Perl installation, not on concerns over their design.
      
      CGI and its associated CGI:: packages
      ....

      The 5.22 perldelta contains a much abbreviated announcement, simply stating that CGI.pm has been removed from core.

      Some individuals chose to use the word "deprecated" but in fact are expressing personal opinion rather than a concensus. The key phrase is "removed from core;" but not "officialy deprecated" as your statement might lead a reader to believe. Some CGI methods are outdated.

      Not only is CGI not deprecated, but Template would be a terrible choice for the OP and his problem. It is not for beginners learning their first perl to HTML script.

      (I am a regular user and proponent of TT2, BTW).

      The way forward always starts with a minimal test.