Satish Sajjanar
Satish Sajjanar

Reputation: 21

How to create a html table using perl

I'm new to perl and don't have much idea in using modules. I'm trying to create a ouput.html file through perl. Basically perl gives me some rows of data for several experiment in my work. I'm using these results and making a table using HTML::table. To make it a kind of dashboard. Below is my code. Since i dont have access to server to create a webpage. I'm trying to create a html file which can be opened with a web browser.

use strict;
use warnings;
use feature "say";
use HTML::Table;
my $table1= new HTML::Table(-cols       =>  9,
                            -align      =>  'centre',
                            -rules      =>  'rows',
                            -border     =>  "1",
                            -bgcolor    =>  '#A6DBF7',
                            -width      =>  '80%',
                            -spacing    =>  1,
                            -padding    =>  5,
                            -style      =>  'color:black',
                            -class      =>  'myclass',
                            -head       =>  ['Block Name','Owner','Handoff','Covg-SA','SA-Patterns','Covg-TFT','TFT-Patterns','Fullscan-SA','Fullscan-TFT']);
open my $HTML,'>' ,'output.html' or die $!;
print $HTML "$table1\n";

for my $i (0..50) {
sub_call()
}

sub sub_call{
...bla..bla
..bla...bla...
.bla....
my @row=('$block','$uid','$step',,'$compress_SA_cvg','$temp','$compress_TFT_cvg','$logic_patt','$fullscan_SA_cvg','$fullscan_TFT_cvg');.

my $table1= new HTML::Table(-cols       =>  9,
                            -align      =>  'centre',
                            -rules      =>  'rows',
                            -border     =>  "1",
                            -bgcolor    =>  '#DAF7A6',
                            -width      =>  '80%',
                            -spacing    =>  1,
                            -padding    =>  5,
                            -style      =>  'color:black',
                            -class      =>  'myclass',
                        );
$table1->addRow(@row);
open my $HTML,'>>' ,'output.html' or die $!;
print $HTML "$table1\n";
}

In the above code. I will be having a row of data in the array @row each time that 2nd block executes. which will be appended to the output.html . I have few requirements as below.

I have attached screenshot of the output that i have got. For security reasons i left variables values as it is. But when i get variable's values this table will be not aligned properly.

screenshot of output

Please suggest me what to use to meet above requirements.

Thanks in advance.

Upvotes: 0

Views: 4549

Answers (2)

simbabque
simbabque

Reputation: 54323

I disapprove of HTML::Table, as it has not seen any updates for more than 10 years and uses very outdated concepts. Please see below for more on that.


Your problem is that you make a new HTML::Table object every time you call your subroutine for a row of data, and you also use a different one for your table head. Essentially your code looks like this:

use strict;
use warnings;
use HTML::Table;
my $table_header = HTML::Table->new(
    -cols => 2,
    -head => [qw/ foo bar/],
);
print $table_header;

for ( 1, 2 ) {
    my $table_data = HTML::Table->new( -cols => 2, );
    $table_data->addRow( 1, 2 );
    print $table_data;
}

This code produces the following output.

<table>
<tbody>
<tr><th>foo</th><th>bar</th></tr>
</tbody>
</table>

<table>
<tbody>
<tr><td>1</td><td>2</td></tr>
</tbody>
</table>

<table>
<tbody>
<tr><td>1</td><td>2</td></tr>
</tbody>
</table>

As you can see, this has the same problem with the headers not being aligned. It happens because those are separate tables, and your browser renders each table on its own. If not otherwise told, it tries to find the best column size for each table. And that will make them not be aligned with each other. It's even possible that some of the rows of data end up not being aligned properly in relation to the ones above and below.

Instead, you need to make just one HTML::Table object and keep using it for the header as well as every row of data.

use strict;
use warnings;
use HTML::Table;
my $table = HTML::Table->new(
    -cols => 2,
    -head => [qw/ foo bar/],
);

for ( 1, 2 ) {
    $table->addRow( 1, 2 );
}

print $table;

Now the output will look like this

<table>
<tbody>
<tr><th>foo</th><th>bar</th></tr>
<tr><td>1</td><td>2</td></tr>
<tr><td>1</td><td>2</td></tr>
</tbody>
</table>

In your code, there is no need for the subroutine call to sub_call you can have that code directly in your loop. Get rid of the new HTML::Table object in there, and reuse the one from the heading. Keep in mind that lexical variables (declared with my) will only be valid in their current scope. That means if you declare a variable between { and } it is not visible outside that block.

To get your background colors different, take a look at the documentation regarding sections. Here's a quick mockup of how that could look like.

use strict;
use warnings;
use HTML::Table;
my $table = HTML::Table->new(
    -cols => 2,
);
$table->addSectionRow( 'thead', 0, qw/foo bar/ );
$table->setSectionStyle('thead', 0, 'background-color: red');
$table->setSectionRCellsHead('thead', 0, 1);

$table->setSectionStyle('tbody', 0, 'background-color: green');
for ( 1, 2 ) {
    $table->addSectionRow( 'tbody', 0, 1, 2 );
}

print $table;

That code will produce output like this

<table>
<thead style="background-color: red">
<tr><th>foo</th><th>bar</th></tr>
</thead>
<tbody style="background-color: green">
<tr><td>1</td><td>2</td></tr>
<tr><td>1</td><td>2</td></tr>
</tbody>
</table>

As you can see, this is really complicated for what it produces. As I said before in my comment, you are probably better off writing your own HTML. It's even better to use a templating system. Please the answer by Chris Turner for that.

Upvotes: 1

Chris Turner
Chris Turner

Reputation: 8142

As mentioned in the comments, the best way to create HTML using Perl is to use a template system. There are many possible options, but I'm demonstrating the principle using Template Toolkit

Here is the Perl code. It just creates the data and leaves the creating of the HTML to the template system.

#!/usr/bin/perl

use strict;
use Template;

my $template=Template->new({PRE_CHOMP => 1});

my @rows;

push @rows,["a","b","c","d","e"];
push @rows,["a","b","c","d","e"];
push @rows,["a","b","C","d","e"];
push @rows,["a","b","c","d","e"];

$template->process("table.tmpl",{rows => \@rows}) || die $template->error(); 

The template (table.tmpl) is as follows.

<html>
<head>
<title>My Table</title>
<style>
table { border-collapse: collapse; border: solid 1px black; }
th { border: solid 1px black; background: #A6DBF7; text-align: center; color: black; }
td { border: solid 1px black; background: #DAF7A6; text-align: center; color: black; }
</style>
</head>
<body>
<table>
<tr><th>Heading</th><th>Another</th><th>More</th><th>Heading!</th><th>Blah</th></tr>
[% FOREACH row IN rows %]
<tr>
<td>[% row.0 %]</td>
<td>[% row.1 %]</td>
<td style="background: [% IF row.2=='c'%]green[% ELSE %]red[%END %];">[% row.2 %]</td>
<td>[% row.3 %]</td>
<td>[% row.4 %]</td>
</tr>
[% END %]
</table>
</body>
</html>

As you can see, you can put some logic of how the output looks in the template - the background of the 3rd column is dependant on the value of the 3rd element in the row.

Upvotes: 1

Related Questions