【问题标题】:Perl: Dump data from a hash into excelPerl:将数据从哈希转储到 excel
【发布时间】:2016-08-04 17:43:03
【问题描述】:

我有一个带有键和值(数组)的散列。我想将它们转储到电子表格中,但难以安排它们。

%hash
key1 -> 富吧
key2-> 约翰·亚当·吉尔
key3-> 苹果香蕉芒果橙

代码:

use strict;
use warnings;
use Excel::Writer::XLSX;

my $pattern = "BEGIN_";
my $format;
my @keys = qw(key1 key2 key3);
foreach my $key(@keys){
     open my $fh, "<","filename.txt" or die $!;
      while ( <$fh> ) {
        if (/$pattern/) {
        push(@matching_lines, $_);
      }
    }
    $hash{$key} = [@matching_lines] ; 
   for (@matching_lines) { $_ = undef } ; #Emptying the array contents,to reuse it for for all the other keys
}

my $workbook = Excel::Writer::XLSX->new( 'c:\TEMP\filename.xlsx' ); 
 if (not defined $workbook)
{
    die "Failed to create spreadsheet: $!";
}
my $worksheet = $workbook->add_worksheet();

#  Add and define a format
$format = $workbook->add_format();
$format->set_bg_color( 'yellow' );

my $row = 1;
my $col = 0;

foreach my $k (keys %hash)
{
     $worksheet->write($row, $col, $k, $format); # title
     $worksheet->write_col($row+1, $col, $hash{$k}); #value
     $col++;
}
$workbook->close() or die "Error closing file: $!";   

电流输出


所需输出

【问题讨论】:

  • 您的示例中有一些拼写错误。缺少my,使用%hash%tools 没有意义。我修复了这些并运行它,这给了我正确的输出,但第 1 行和 A 列是空的。它从 B2 开始,但看起来完全正确。我认为您的 minimal reproducible example 可以作为您的真实代码执行其他操作。
  • @simbabque 感谢您指出错别字。我已经纠正了他们。我已经仔细检查了我的代码并再次运行,但输出仍然与上面提到的当前输出相同。不确定,我错过了什么
  • 您能否在循环中包含print $row . "\n"; 以验证$row 没有被递增?
  • @Mr.Llama 这给了我输出1 1 1$row 没有增加,这就是标题(key2key 3)打印正确的原因。但是为什么只有价值观才能获得空间。我尝试在 excel 之外打印哈希值,结果没有任何空格
  • 您能否将use Data::Dumper; 添加到脚本的开头并在foreach 循环之前包含print Dumper($hash);

标签: arrays excel perl hash


【解决方案1】:

编辑:现在您实际上已经更新了您的程序,以澄清问题在于您如何读取数据,以下内容没有实际意义。但它确实说明了另一种方法。

好的,这里的核心问题是您尝试做的是“翻转”哈希。您正在逐行打印,但您的哈希是按列组织的。

使用逗号分隔作为打印实际 excel 的快速代理:

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;

#initialise
my %hash = (
    key1 => [qw (  foo bar  )],
    key2 => [qw (  john adam gill  )],
    key3 => [qw (  apple banana mango orange )],
);

#print for debug
print Dumper \%hash;


#get header row. Sort it, because hashes are unordered.
#could instead:
#my @keys = qw ( key1 key2 key3 );
my @keys = sort keys %hash;
#print header row
print join ",", @keys, "\n";

#iterate until every element of the hash is gone
while ( map { @{ $hash{$_} } } @keys ) {
    #cycle the keys, shifting a value of the top of each array. 
    #replace any undefined values with ''. 
    print shift( @{ $hash{$_} } ) // '', "," for @keys;
    print "\n";
}

打印出来:

key1,key2,key3,
foo,john,apple,
bar,adam,banana,
,gill,mango,
,,orange,

如果您将其作为 csv 加载到 Excel 中,应该会得到您想要的结果。我很确定您可以在模块中使用类似的“写入行”。

所以这实际上似乎是你想要的:

#!/usr/env/perl
use strict;
use warnings;

use Excel::Writer::XLSX;

#initialise
my %hash = (
    key1 => [qw (  foo bar  )],
    key2 => [qw (  john adam gill  )],
    key3 => [qw (  apple banana mango orange )],
);


my $workbook = Excel::Writer::XLSX->new('c:\TEMP\filename.xlsx');
if ( not defined $workbook ) {
    die "Failed to create spreadsheet: $!";
}
my $worksheet = $workbook->add_worksheet();

#  Add and define a format
my $format = $workbook->add_format();
$format->set_bg_color('yellow');

my @keys = sort keys %hash;
my $row  = 0;
$worksheet->write_row( $row++, 0, \@keys, $format );
while ( map { @{ $hash{$_} } } @keys ) {
    my $col = 0;
    $worksheet->write( $row, $col++, shift( @{ $hash{$_} } ) // '' )
        for @keys;
    $row++;
}
$workbook->close() or die "Error closing file: $!";

【讨论】:

    【解决方案2】:

    您没有正确清空 @matching_lines 数组。这一行:

    for (@matching_lines) { $_ = undef } 
    

    将数组值设置为undef,但不会删除它们
    例如,如果 @matching_lines('foo', 'bar'),现在它变为 (undef, undef)。稍后添加bazqux 时,它变为(undef, undef, 'baz', 'qux')。当您将这些 undef 添加到工作表时,它们将变为空白单元格。

    要正确清空数组,请使用:

    @matching_lines = ();
    

    【讨论】:

    • 是的。工作完美。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 2015-04-01
    • 2014-08-10
    • 2013-07-09
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    相关资源
    最近更新 更多