将.XLSX电子表格转换为CSV的代码无法正常工作

时间:2015-09-18 15:25:16

标签: excel perl csv

我有一个包含许多列和行的Excel电子表格。我想将其转换为CSV,但只包含CSV中的某些列。

这是我的代码:

#!/usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseXLSX;
use Excel::Writer::XLSX;

my $excel = Spreadsheet::ParseXLSX -> new();
my $workbook = $excel->parse('headers.xlsx');
my $worksheet = $workbook->worksheet(0);
my $destination = 'csv.txt';
my $csv;
my ($row_min, $row_max) = $worksheet->row_range();
my ($col_min, $col_max) = $worksheet->col_range();

for my $row ( $row_min .. $row_max ) {
    for my $col ( $col_min .. $col_max ) {

        # my $cell = $worksheet>{Cells}[$row][$col];
        my $cell = $worksheet->get_cell( $row, $col );
        if ($cell) {
            if ($col eq ( 'A' || 'S' || 'T' || 'AA' || 'AX' || 'BC' || 'D' || 'AN' || 'AV' )) {
                if ($col == $col_max) {
                    $csv .= $cell->Value . "\n";
                    } else {
                    $csv .= $cell->Value . ",";
                }
            }
        }
    }
}

open (my $fh, '>', $destination) or die '$! error trying to write';
print $fh $csv;
close ($fh);

运行时我没有收到任何错误或警告,这对确定问题没有帮助。

任何人都可以识别出任何错误吗?

2 个答案:

答案 0 :(得分:2)

首先,$ col是数字,所以你不应该对字符串列名进行测试。

其次,你需要例如。

<interactive>:5:52:
    Could not deduce (Num (a -> a)) arising from a use of ‘+’
    from the context (Ord a, Num a)

如你所知,它只是测试$ col eq&#39; A&#39; (因为这是所有||&#39;)的结果。

答案 1 :(得分:1)

你的考试

$col eq ( 'A' || 'S' || 'T' || 'AA' || 'AX' || 'BC' || 'D' || 'AN' || 'AV' )

找到第一个 true 的文本字符串,即A,并将其与$col进行比较,这根本不是您想要的。你必须写

$col eq 'A' || $col eq 'S' || $col eq 'T' || $col eq 'AA' || $col eq 'AX' || $col eq 'BC' || $col eq 'D' || $col eq 'AN' || $col eq 'AV'

除了模块没有像那样处理列标签,所以你需要将它们转换为数字

我写过这个,应该有效。它首先构建一个哈希,它将每个列标签与前100列的数字相关联。然后我使用该哈希将您的标签列表转换为列号列表,并对其进行迭代。 (如果你感兴趣,它会产生[1, 4, 19, 20, 27, 40, 48, 50, 55]。)它比迭代所有列并忽略你不想要的那些更加整洁

它没有经过测试,因为我没有要测试的数据文件,但它确实编译了

如果代码包含 false 值,则我不能确定跳过单元格的代码。这将跳过空单元格和包含数字零的单元格,这将导致CSV文件中的列未对齐。我的代码部分是@csv_row = grep $_, @csv_row,如果您同意我的话,您可能想要删除它

#!/usr/bin/perl

use strict;
use warnings;

use Spreadsheet::ParseXLSX;

my ($source, $dest) = qw/ headers.xlsx headers.csv /;

my $excel = Spreadsheet::ParseXLSX->new;
my $workbook = $excel->parse($source);
my $worksheet = $workbook->worksheet(0);
my ($row_min, $row_max) = $worksheet->row_range;

my %col_numbers;
for ( my ($n, $name) = (1, 'A'); $n <= 100; ++$n, ++$name ) {
    $col_numbers{$name} = $n;
}

my @cols = sort { $a <=> $b }
        map $col_numbers{$_}, qw/ A  S  T  AA  AX  BC  D  AN  AV /;

open my $fh, '>', $dest
        or die qq{Unable to open "$dest" for output: $!};

for my $row ( $row_min .. $row_max ) {
    my @csv_row = map $worksheet->get_cell($row, $_)->unformatted, @cols;
    print $fh join(',', @csv_row), "\n";
}

close $fh;