如何使用Perl将CSV转换为HTML表格?

时间:2008-10-14 06:04:34

标签: html perl html-table

在我的代码中,我希望以表格形式查看CSV中的所有数据,但它只显示最后一行。第1行和第2行怎么样?这是数据:

1,HF6,08-Oct-08,34:22:13,df,jhj,fh,fh,ffgh,gh,g,rt,ffgsaf,asdf,dd,yoawa,DWP,tester,Pattern
2,hf35,08-Oct-08,34:12:13,dg,jh,fh,fgh,fgh,gh,gfh,re,fsaf,asdf,dd,yokogawa,DWP,DWP,Pattern
3,hf35,08-Oct-08,31:22:03,dg,jh,fh,fgh,gh,gh,gh,rte,ffgsaf,asdf,dfffd,yokogawa,DWP,DWP,ghh

以下是代码:

#! /usr/bin/perl
print "Content-type:text/html\r\n\r\n";
use CGI qw(:standard);
use strict;
use warnings;

my $line;
my $file;
my ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$f10,$f11,$f12,$f13,$f14,$f15,$f16,$f17,$f18,$f19);

$file='MyFile.txt';
open(F,$file)||die("Could not open $file");
while ($line=<F>)
{

($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$f10,$f11,$f12,$f13,$f14,$f15,$f16,$f17,$f18,$f19)= split ',',$line;

}

close(F);

print "<HTML>";
print "<head>";
print "<body bgcolor='#4682B4'>";
print "<title>FUSION SHIFT REPORT</title>";
print "<div align='left'>";
print "<TABLE CELLPADDING='1' CELLSPACING='1' BORDER='1' bordercolor=black width='100%'>";
print "<TR>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>RECORD No.</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>TESTER No.</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>DATE</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>TIME</td>";
print "<td width='11%'bgcolor='#00ff00'><font size='2'>DEVICE NAME</td>";
print "<td bgcolor='#00ff00'><font size='2'>TEST PROGRAM</td>";
print "<td bgcolor='#00ff00'><font size='2'>DEVICE FAMILY</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>SMSLOT</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>DIE LOT</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>LOADBOARD</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>TESTER </td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>SERIAL NUMBER</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>TESTER CONFIG</td>";
print "<td width='11%'bgcolor='#00ff00'><font size='2'>SMSLOT</td>";
print "<td bgcolor='#00ff00'><font size='2'>PACKAGE</td>";
print "<td bgcolor='#00ff00'><font size='2'>SOCKET</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 1</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 2</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 3</td>";
print "</tr>";
print "<TR>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f1</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f2</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f3</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f4</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f5</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f6</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f7</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f8</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f9</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f10</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f11</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f12</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f13</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f14</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f15</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f16</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f17</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f18</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f19</TD>";
print "</tr>";

print "</TABLE>";

print "</body>";
print "<html>";

7 个答案:

答案 0 :(得分:14)

您需要在while循环中输出内的表行,因为这是您在读取行的位置。

所以更改代码以便

  • 输出表格标题
  • 逐行输出表行
  • 读取文件
  • 输出表格页脚

如果稍微简化一下,这就是你的循环看起来......

while ($line=<F>)
{  
    print "<tr>";
    my @cells= split ',',$line;
    foreach my $cell (@cells)
    {
       print "<td>$cell</td>";
    }
    print "</tr>";
}

答案 1 :(得分:7)

HTML :: Template会让您的生活更轻松。这是我的缩减模板。

#!/usr/local/bin/perl

use strict;
use warnings;

use HTML::Template;

my @table;
while (my $line = <DATA>){
    chomp $line;
    my @row = map{{cell => $_}} split(/,/, $line);
    push @table, {row => \@row};
}

my $tmpl = HTML::Template->new(scalarref => \get_tmpl());
$tmpl->param(table => \@table);
print $tmpl->output;

sub get_tmpl{
    return <<TMPL
<html>
<TMPL_LOOP table>
<tr>
<TMPL_LOOP row>
<td><TMPL_VAR cell></td></TMPL_LOOP>
</tr></TMPL_LOOP>
</html>
TMPL
}

__DATA__
1,HF6,08-Oct-08,34:22:13,df,jhj,fh,fh,ffgh,gh,g,rt,ffgsaf,asdf,dd,yoawa,DWP,tester,Pattern
2,hf35,08-Oct-08,34:12:13,dg,jh,fh,fgh,fgh,gh,gfh,re,fsaf,asdf,dd,yokogawa,DWP,DWP,Pattern
3,hf35,08-Oct-08,31:22:03,dg,jh,fh,fgh,gh,gh,gh,rte,ffgsaf,asdf,dfffd,yokogawa,DWP,DWP,ghh

答案 2 :(得分:6)

$f1,$f2,$f3,$f4

任何时候你都会看到类似闹铃的代码应该消失。使用数组。

答案 3 :(得分:5)

请允许我用一个较小的例子进行演示。

my $f;
while ($line = <F>) {
    $f = $line;
}
print $f;

上面的代码将读取文件F的每一行,将每一行分配给变量$f。每次分配新行时,前一行都会被覆盖。当它到达文件末尾时,它会打印出$f一次的值。

my $f;
while ($line = <F>) {
    $f = $line;
    print $f;
}

上面的代码在循环中有print,因此print将为输入的每一行运行。您将需要对代码进行类似的修改以获得您期望的输出。

答案 4 :(得分:3)

您只看到最后一行的原因是您在阅读完整个文件后运行了打印件,并在读取下一行时丢弃了每一行。

说实话,这段代码有各种各样的错误。我将提及一对,并在下面的代码片段中解决这些问题。

  1. 请勿自行解析CSV数据(拆分)。使用Text::CSV或 - 如果您需要更好的效果 - Text::CSV_XS
  2. 您的HTML无效。你没有关闭所有标签,特别是标题应该在头部,而不是正文。
  3. 您应该使用模板化模块将表格数据插入网页。示例:HTML::TemplateTemplate Toolkit
  4. 至少,使用函数来抽象出冗余代码。
  5. 更好的是,使用数据格式化也是数据的事实。这就是为什么它应该被视为原因。
  6. 如果您发现许多附加了数字的变量($f1$f2,...),您真的想要一个数组:@fields = split /,/, $line;

  7. use strict;
    use warnings;
    use CGI qw();
    use Text::CSV;
    
    my $cgi = CGI->new();
    print $cgi->header();
    
    my $file ='MyFile.txt';
    
    # should really use a templating module from CPAN,
    # but let's take it step by step.
    # Any of the following would fit nicely:
    # - Template.pm (Template Toolkit)
    # - HTML::Template, etc.
    my $startHtml = <<'HERE';
    <html>
    <head> <title>FUSION SHIFT REPORT</title> </head>
    <body bgcolor="#4682B4">
    <div align="left">
    <table cellpadding="1" cellspacing="1" border="1" bordercolor="black" width="100%">
    HERE
    my $endHtml = <<'HERE';
    
    </table>
    
    </body>
    <html>
    HERE
    
    my @columns = (
      { name => 'RECORD No.', width => 12 },
      { name => 'TESTER No.', width => 12 },
      { name => 'DATE', width => 12 },
      { name => 'TIME', width => 13 },
      { name => 'DEVICE NAME', width => 11 },
      { name => 'TEST PROGRAM' },
      { name => 'DEVICE FAMILY' },
      { name => 'SMSLOT', width => 13 },
      { name => 'DIE LOT', width => 13 },
      { name => 'LOADBOARD', width => 12 },
      { name => 'TESTER', width => 12 },
      { name => 'SERIAL NUMBER', width => 12 },
      { name => 'TESTER CONFIG', width => 13 },
      { name => 'SMSLOT', width => 11 },
      { name => 'PACKAGE' },
      { name => 'SOCKET' },
      { name => 'ROOT CAUSE 1', width => 13 },
      { name => 'ROOT CAUSE 2', width => 13 },
      { name => 'ROOT CAUSE 3', width => 13 },
    );
    
    
    my $csv = Text::CSV->new();
    open my $fh, '<', $file
      or die "Could not open file '$file': $!"; # should generate a HTML error here
    
    # print header
    print $startHtml;
    print_table_header(\@columns);
    
    while (defined(my $line = <$fh>)) {
      $csv->parse($line);
      # watch out: This may be "tainted" data!
      my @fields = $csv->fields();
      @fields = @fields[0..$#columns] if @fields > @columns;
      print_table_line(\@fields);
    }
    
    close $fh;
    
    print $endHtml;
    
    
    
    
    sub print_table_header {
      my $columns = shift;
      print "<tr>\n";
      foreach my $column (@$columns) {
        my $widthStr = (defined($column->{width}) ? ' width="'.$column->{width}.'"' : '');
        my $colName = $column->{name};
        print qq{<td$widthStr bgcolor="#00FF00"><font size="2">$colName</font></td>\n};
      }
      print "</tr>\n";
    }
    
    sub print_table_line {
      my $fields = shift;
      print "<tr>\n";
      foreach my $field (@$fields) {
        print qq{<td bgcolor=\"#ADD8E6\"><font size="2">$field</font></td>\n};
      }
      print "</tr>\n";
    }
    

答案 5 :(得分:0)

请关闭你的&lt; font&gt;标签。仅仅因为浏览器会处理它们的缺乏并不意味着它们没有价值。

答案 6 :(得分:0)

这不是最强大的解决方案,事实上,如果你在内部使用逗号,它会有一些非常令人讨厌的失败,但它为我做了这个工作:

(CSV数据位于名为$ content的变量中)

$content =~ s#\n#</td></tr><tr><td>#g;
$content =~ s#,#</td><td>#g;
$content = "<table><tr><td>$content</td></tr></table>";