perl 工作簿:子例程中无法访问动态工作表

pxiryf3j  于 2023-03-03  发布在  Perl
关注(0)|答案(1)|浏览(129)

因此,我正在名为CreateWorkbook的子例程中创建工作簿,使用SQL查询动态添加工作表,并将工作表分配给%ws对象。导出时,工作簿包含所有选项卡。
但是,我在另一个子例程中访问这些工作表时遇到了问题。

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

use Data::Dumper;

my @lang_ids;
my @lang_types_ids;

sub run {
    my ($self, $app_id, $filepath, $args) = @_;
    my $workbook = CreateWorkbook($filepath, $app_id, $report_type, $lang_ids);
    return {};
}

这一个创建工作簿和工作表使用所有可用的语言,如:英语、西班牙语、德语等。单个工作表由正在传递的对象**%ws引用。如果我硬编码$ws{test},则可以正常工作。动态$ws{$final_name}添加具有正确名称的工作表,例如,$ws{spanish}**,并且在导出excel时,我可以看到所有单个选项卡。

sub CreateWorkbook {
    my ($filepath, $app_id, $report_type, $lang_ids) = @_;

    #print "Print filepath: $filepath    \n";
    my $sth;

    my $workbook_writer = Excel::Writer::XLSX->new($filepath);
    die "Problems creating new Excel file: $!" unless defined $workbook_writer;

    my %fmt;

    $fmt{fmt_normal} = $workbook_writer->add_format(num_format => '@');
    $fmt{fmt_normal}->set_size(11);

    my %ws;

    #this line works great and I'm able to access it in subroutine
    $ws{test} = $workbook_writer->add_worksheet('test');

    foreach my $lang_id (@lang_ids) {
        $sth = $app_id->_dbh->prepare(
            "SELECT name FROM languages where id = ?")
        || die("Problem preparing query");
        $sth->execute($lang_id) || die("Problem executing query");

        while ( my $name = $sth->fetchrow_array ) {
            $name=~s/ /_/g;
            my $final_name = lc $name;

            #line below adds worksheet to workbook but cannot be accessed in subroutine
            $ws{\$final_name} = $workbook_writer->add_worksheet($name);

        }
    }

    $workbook_writer->close() or die "Error closing file: $!";

    
    return {
        fmt                 => \%fmt,
        ws                  => \%ws,
        workbook_writer     => $workbook_writer,
    };

这里有个问题,访问**$ws{test}可以正常工作,但是我无法访问$ws{$final_name},即使我硬编码了$ws{spanish}**这样的值

sub add_data {
    my ($app_id, $workbook, $report_type, $lang_ids, $lang_types_ids) = @_;

    my %fmt = %{ $workbook->{fmt} };
    my %ws = %{ $workbook->{ws} };
    my %workbook_writer = %{ $workbook->{workbook_writer} };

    my $sth;
    my $sth2;

    foreach my $lang_id (@lang_ids) {
        $sth = $app_id->_dbh->prepare(
            "SELECT name FROM languages where id = ?")
        || die("Problem preparing query");
        $sth->execute($lang_id) || die("Problem executing query");

        while ( my $name = $sth->fetchrow_array ) {
            
            $name=~s/ /_/g;
            my $final_name = lc $name;

            #THIS WORKS FINE
            $ws{test}->write( 0, $languages, $name . " - " . $lang_id, $fmt{fmt_normal} );

            #ERROR: cannot call write method on undefined 
            $ws{\$final_name}->write( 0, $languages, $name . " - " . $lang_id, $fmt{fmt_normal} );
        }
    }

}

我花了太多的时间在上面。我检查了这些工作表是否被分配给了CreateWorkbook子例程中的对象变量,它们是,但是不能在子例程之外访问它们。
我真的很感激你的帮助。我想我传递错误或者没有解引用它。

mspsb9vt

mspsb9vt1#

这只是对Perl引用的误解;与练习册或工作表无关。
如果%ws是一个散列,$final_name是一个字符串,那么$ws{\$final_name} = ...创建一个如下所示的散列条目:$ws{'SCALAR(0x25f79c0)'} = ...
换句话说,散列键不是字符串,而是存储该键的内存位置。删除反斜杠,您将得到一个由$final_name的实际内容正确索引的散列条目

相关问题