English 中文(简体)
Perl - 代码增强
原标题:Perl - Code Enhancement
  • 时间:2012-05-24 20:19:47
  •  标签:
  • perl

我刚刚开始在Perl编译代码, 并想知道下面的代码是否能更有效率, 或者可以用更少的线条完成。

我对Win32::OLE 模块和 rel="nofolpol"\\code>Text:CSV 模块,但从我读到现在的模块来看,这似乎是前进的道路。

这个问题基本上是一个新问题,问一个老人:“嘿,我如何成为更好的珀尔探长?”

代码的目的是从Excel工作手册中特定页目中指定的范围内获取数据,并将这些范围内的内容写成CSV文件。

此外,我知道我需要执行一般检查,比如在将我的 < code>$cellValue 添加到阵列和这样的阵列之前要先确定它的定义,但我正在寻找更多的整体结构。 比如有办法将整个行同时放入一个阵列,或者将整个阵列放入一个阵列,或者在一个阵列或引用中,或者这种性质的东西,从而平整环形吗?

谢谢 谢谢

use strict;
use warnings;
use Spreadsheet::XLSX;

my $excel = Spreadsheet::XLSX -> new ( C:scott.xlsm ,);
my @sheets = qw(Fund_Data GL_Data);

foreach my $sheet (@sheets) {

    my $worksheet = $excel->Worksheet($sheet);
    my $cell = $worksheet->get_cell(25,0);

    if ($cell) { # make sure cell value isn t blank
        my $myFile = "C:/$sheet.csv";
        open NEWFILE, ">$myFile" or die $!;

        # write all cells from Range("A25:[MaxColumn][MaxRow]") to a csv file
        my $maxCol = $worksheet->{MaxCol};
        my $maxRow = $worksheet->{MaxRow};
        my @arrRows;
        my $rowString;

        # loop through each row and column in defined range and string together each row and write to file
        foreach my $row (24 .. $maxRow) {

            foreach my $col (0 .. $maxCol) {

                my $cellValue = $worksheet->{Cells} [$row] [$col]->Value();

                if ($rowString) {
                    $rowString = $rowString . "," . $cellValue;
                } else {
                    $rowString = $cellValue;
                }
            }

            print NEWFILE "$rowString
";
            undef $rowString;
        }
    }
}
最佳回答

Mark s 是一个极好的建议。另一个小的改进是将“做一堆嵌套逻辑if $cell ,改为“不做任何事情,除非$cell - 这样你就有略微容易读懂的代码(删除1个额外的缩进/删除块;如果$cell是空的,不必担心会发生什么。

# OLD
foreach my $sheet (@sheets) {
    my $worksheet = $excel->Worksheet($sheet);
    my $cell = $worksheet->get_cell(25,0);

    if ($cell) { # make sure cell value isn t blank
        # All your logic in the if
    }
}

# NEW
foreach my $sheet (@sheets) {
    my $worksheet = $excel->Worksheet($sheet);
    next unless $worksheet->get_cell(25,0); # You don t use $cell, so dropped

    # All your logic that used to be in the if
}

如您指出的, Text::CSV 将是一个值得考虑的好东西,取决于您的数据是否需要根据 CSV 标准引用(例如包含空格、逗号、引号等)。如果需要引用的话,不要重新发明方向盘,使用 Text::CSV 来打印。

# At the start of the script:
use Text::CSV;
my $csv = Text::CSV->new ( { } ); # Add error handler!

    # In the loop, when the file handle $fh is opened
    foreach my $row (24 .. $maxRow) {
        my $cols = [ map { $worksheet->{Cells}[$row][$_] } 0 .. $maxCol) ];
        my $status = $csv->print ($fh, $cols);
        # Error handling
    }
问题回答

没有理由有这个内环 :

print NEWFILE join(",", map { $worksheet->{Cells}[$row][$_] } 0 .. $maxCol), "
";

另外,请确保您的索引正确无误。 我对电子表格不熟悉 :: XLSX, 所以确定最大 col & amp; 行与您的代码其余部分一样是零基数。 如果它们不正确, 那么您会想要在 < code> 0. $maxCol-1 < / code > 上插入 。

我建议不要使用硬编码文件名... 特别是在这样的小项目中, 习惯于通过 GetOpt:Long 传递文件名。 如果您对所有的小项目都这样做, 它会更容易记住当它涉及到一个更大的项目时, 是否正确。

您的代码结构合理且可读, 您预见到循环语句的问题, 您使用警告和严格, 您通常使用图书馆的方式很正确 。

正如其他人所说的那样,你的守则是清楚和结构完善的。 但我认为,如果稍稍改进一下,就会有所改进。

兹考虑以下各点:

  • 使用词汇文件手表和三个参数形式的 open( open my $newfiles, & gt;, $myFile )

  • 在散列值或数组值(或它们中的 selps )而不是其键或索引上进行迭接,除非您真的需要环形的键

  • 如果数据子结构是循环的焦点, 则在循环中提取数据子结构的指针( my $rows = $Workingshall- gt;{Cells/code>)

  • 点显示您正在在哪里使用环环将一个列表转换成另一个列表, 并使用 map 代替

我希望我没有像你们提议的那样,通过使用Text::CSV 来撰写解决方案,略微跳过枪。幸运的话,这对你很有启发性。

use strict;
use warnings;

use Spreadsheet::XLSX;
use Text::CSV;

my $csv = Text::CSV->new;

my $excel = Spreadsheet::XLSX->new( C:scott.xlsm ,);

foreach my $sheet (qw/ Fund_Data  GL_Data /) {

  my $worksheet = $excel->Worksheet($sheet);
  next unless $worksheet->get_cell(25,0);

  my $myFile = "C:\$sheet.csv";
  open my $newfile,  > , $myFile or die $!;

  my $rows = $worksheet->{Cells};

  # Write all cells from row 25 onwards to the CSV file

  foreach my $row (@{$rows}[24..$#{$rows}]) {
    my @values = map $_ ? $_->Value :   , @$row;
    $csv->print($newfile, @values);
    print $newfile "
";
  }
}




相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...