1

I am trying to create a table using CGI.pm. The table would contain results from querying a database. The array final contains record numbers on which the queries will be executed. The results for each record should be in a separate row. The result of each query on the record should form a column in the row. Using some code I found here, I wrote the following (which may not be he best way of doing it):

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use DBI;

...

my @rows;
my $rec;

foreach my $el (@final) {
              @rows = ();
    foreach my $query (@queries) {
        my $query_handle = $connxn->prepare($query);
        $query_handle->execute($el);
        $query_handle->bind_columns(undef, \$rec);
        while($query_handle->fetch()) {
            push(@rows,td($rec));
        }   
    }
    print $q->table({-border=>undef,-width=>'25%'},
        Tr(\@rows)
       );
}

When I run this, I get a blank page and an error "Undefined subroutine &main::td" in the error log. Why do I get this error and I how do I get rid of it? Is there any other way to create a table the table I want using CGI.pm? Any help would be appreciated. Thanks!

EDIT: Using Sinan's suggestion, I modified my code as follows:

#!/usr/bin/perl 
use strict; 
use warnings; 
use DBI;  
use Carp; 
use HTML::Template;

...  
my @rows; 
my $rec;  
foreach my $el (@final) {     
    foreach my $query (@queries) {         
        my $query_handle = $connxn->prepare($query);         
        $query_handle->execute($el);         
        $query_handle->bind_columns(undef, \$rec);         
        while($query_handle->fetch()) {             
            push(@rows, { CELLS => [ map { CELL => $_ }, $rec ] });         
        }        
    } 
}

my $tmpl = HTML::Template->new(filehandle => \*DATA);
$tmpl->param(ROWS => \@rows); 
print $tmpl->output;

__DATA__ 
<table> 
<TMPL_LOOP ROWS> 
<tr> 
<TMPL_LOOP CELLS> 
<td><TMPL_VAR CELL></td> 
</TMPL_LOOP>
</tr> 
</TMPL_LOOP>
</table>

But now I am getting the result of each query in a separate row, instead of the same one (see original question above). I can't seem to fix it on my own. Any ideas?

EDIT2: Though I am accepting Sinan's answer, meanwhile I developed my own solution (in case anyone is interested):

my @rows;
my @rows1;
foreach my $el (@final) {
    @rows = ();
    foreach my $query1 (@queries) {
        my $query_handle = $connxn->prepare($query1);
        $query_handle->execute($el);
        $query_handle->bind_columns(undef, \$rec);
        while($query_handle->fetch()) {
            push(@rows, $rec);              
        }                       
    }
    push(@rows1, { CELLS => [ map { CELL => $_ }, @rows ] }); 
}

2 Answers 2

3

I know you think you want to use CGI.pm to generate the tables, but you shouldn't. The code will be ugly and it will hurt.

Instead, separate presentation from logic. Avoid the HTML generation functions of CGI.pm. Use a simple templating module such as HTML::Template. Customize the HTML to your heart's content without messing with your code.

Given the update to your question, I think what you need is this:

foreach my $el (@final) {
    my @cells;
    foreach my $query (@queries) {         
        my $query_handle = $connxn->prepare($query);         
        $query_handle->execute($el);         
        $query_handle->bind_columns(undef, \$rec);
        while($query_handle->fetch()) {
            push @cells, { CELL => $rec };
        }        
    } 
    push @rows, { CELLS => \@cells };
}
Sign up to request clarification or add additional context in comments.

6 Comments

I understand what you mean, but I cannot figure out how to use it in my case. Should I store my results in some data structure that I pass to this function? Please help me on this.
I am not sure if you have seen my update, but I think it answers your question.
I simply copy-pasted your commands, and the first one gives me an error Not enough arguments for map, near "} @". Also says syntax error near "} @. I am not sure why this is happening.
I forgot a comma. Assuming $rec is an array ref to a row retrieved from the database, that should work.
Right, but each query here retrieves only a single element of the database (usually a string), not a whole row. I fixed this by removing the @ in front of $rec. But now there is another problem. Pease see my edited question.
|
2

Try using "use CGI qw(:standard);" instead of "use CGI;". Otherwise the Namespace of the CGI-Module is not imported.

The other way is using "push(@rows,CGI->td($rec))" instead of "td()".

This is also applicable on the tr(\@rows)

Here's the full working code:

#!/usr/bin/perl
use strict;
use warnings;
use CGI qw(:standard);
use DBI;

...

my @rows;
my $rec;

foreach my $el (@final) {
    foreach my $query (@queries) {
        my $query_handle = $connxn->prepare($query);
        $query_handle->execute($el);
        $query_handle->bind_columns(undef, \$rec);
        while($query_handle->fetch()) {
            push(@rows,td($rec));
        }   
    }
    print table({-border=>undef,-width=>'25%'},
        tr(\@rows)
       );
}

5 Comments

Thanks, now at least I can see the tables! But using push(@rows,td($rec)); still gives me each result in a new line, instead of a new row. How do I fix that?
Lines == Rows ! Or do you mean columns ?
Oops, I meant each result in a new line, instead of a new column. Sorry
Remove the "\" in Front of @rows -- but Sinan is right: You should use plain HTML, which is divided from the logic. It's more clean... Anyway, if you still want to use CGI, this should work
+1 Thanks again. It works now, but yeah Sinan's suggestion seems to be better

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.