【问题标题】:Generate Excel output using Win32::OLE in Perl在 Perl 中使用 Win32::OLE 生成 Excel 输出
【发布时间】:2014-02-13 22:22:06
【问题描述】:

我是 Perl 的初学者,并且尝试过使用 Perl 来了解它的方式和工作原理!我对数组、哈希和相关主题有基本的了解。我必须为一个主题开发一个脚本,我很不确定如何去做。我非常需要帮助,非常感谢任何可以解释“如何做”部分的人!

我有一个包含 3 个部分的代码,它对 3 个不同的组件执行三次相同的操作。基本思想是,它从一个 excel 文件中获取所有标记为“A”的组件,遍历该 excel 文件,将其相应的 RAM 和 ROM 值相加,并打印出没有重复条目的输出。第 2 部分和第 3 部分相同,但用于组件“B”和“C”。到目前为止,我能够在文本文件中打印出所有 3 个部分的输出。但现在我希望将 Excel 工作簿中的所有三个输出作为 3 个单独的工作表!

我不太确定该怎么做。任何想法都非常欢迎!

PS:如果我没有在论坛中输入正确的代码,请原谅我!这是我的第一篇文章!!

到目前为止,我的代码如下所示:

# This Test script was created to try out the possible methods to extract all the Names from the
# excel report without duplicate entries and find their corresponding RAM/ROM size sum

# -excel D:\Abc\Test.xlsx  -out D:\Abc\Output

sub usage($) 
{
   return shift(@_) . <<"END_USAGE";
   Usage: $0 -excel               Specify the file path.
                -out outputdirectory  Specify output directiory             
END_USAGE
}

use Getopt::Long;
use Win32::OLE;
use List::Util qw(sum);
use Data::Dumper qw(Dumper);

my $output_path = ();
my $excel_path = ();
my $no_rows = ();
my $lastCol = ();

GetOptions("excel=s"   =>   \$excel_path,
                 "out=s" =>   \$output_path,
           "h|help" =>   \$help,
          );

#help message
die usage("") if ($help);
system(cls);
print "\n*******************************************************************\n";
print "Component Overview \n";
print "*******************************************************************\n";
print "Please wait, Processing may take couple of minutes... \n";

##File handler for the script file.
$log_path = $output_path."\\log.txt";
$output_file_path = $output_path."\\TestExcel.xlsx";
open LogFile,">",$log_path or die "Cannot create the log file:$log_path !!!";
print LogFile "Start time :".localtime()."\n";

# Start Excel and make it visible
my $xlApp = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit');  
$xlApp->{Visible} = 0;

#Opening the work book
my $workBook = $xlApp->Workbooks->Open($excel_path);
#print "X: " . $workBook . " - " . $excel_path . "\n";
my $excelSheet = $workBook->Worksheets("Report");
$excelSheet->Activate();

print "Reading the file...\n";
&ReadExcel();

print LogFile "Completed time :".localtime()."\n";
print "\nCompleted.Please close this window...\n" ;
print "*******************************************************************\n";

# Sub routine to parse the cosipa file
sub ReadExcel()
{
my $row_index;
#Findings the number of valid rows
$no_rows = $excelSheet->UsedRange->Rows->{'Count'};
$lastCol = $excelSheet->UsedRange->Columns->{'Count'};
$row_index = findRowindex();
my @comp_array = ();

# Name => ResourceType => size
my $resultData = {};

for(my $index=($row_index+1);$index<=$no_rows;$index++)
                       {
                            my $X =  $excelSheet->Cells($index,6)->Value();
            my $Y =  $excelSheet->Cells($index,7)->Value();
            my $name = $excelSheet->Cells($index,9)->Value();
            my $resourceType = $excelSheet->Cells($index,3)->Value();
            my $size = $excelSheet->Cells($index,2)->Value();

            #Name Overview                              
            my $currNameTypeMap;

            if ( ! exists $resultNameData->{ $name } )          # ->: arrow operator is used to dereference reference to arrays or hashes.
                {
                    $resultNameData->{ $name } = {};
                }
            $currNameTypeMap = $resultNameData->{ $name };

            $currNameTypeMap->{ $resourceType } += $size;       

            # Y Overview
            my $currYTypeMap;

            if ( ! exists $resultYData->{ $Y } )            # ->: arrow operator is used to dereference reference to arrays or hashes.
                {
                    $resultYData->{ $cluster } = {};
                }
            $currYTypeMap = $resultYData->{ $Y };

            $currYTypeMap->{ $resourceType } += $size;  

            # X Overview
            my $currXTypeMap;

            if ( ! exists $resultXData->{ $X } )            # ->: arrow operator is used to dereference reference to arrays or hashes.
                {
                    $resultXData->{ $X } = {};
                }
            $currXTypeMap = $resultXData->{ $X };

            $currXTypeMap->{ $resourceType } += $size;      
        }   

    my @uniqNameArr = sort keys %$resultNameData;

    my @uniqYArr = sort keys %$resultYData;

    my @uniqXArr = sort keys %$resultXData;

            for my $currName ( @uniqNameArr )
            {
                print $currName . "\n". " RAM: " . $resultNameData->{ $currName }-> { "RAM" } . ", ROM: " . $resultNameData->{ $currName }-> { "ROM" } . "\n";
                #print Dumper %$resultData;
            }

            print "----------------------------------------------------------------------- \n";

            for my $currY ( @uniqYArr )
            {
                print $currY. "\n". " RAM: " . $resultYData->{ $currY }-> { "RAM" } . ", ROM: " . $resultYData->{ $currY }-> { "ROM" } . "\n";
            }

            print "------------------------------------------------------------------------ \n";

            for my $currX ( @uniqXArr )
            {
                print $currX . "\n". " RAM: " . $resultXData->{ $currX }-> { "RAM" } . ", ROM: " . $resultXData->{ $currX }-> { "ROM" } . "\n";
            }

}

#Sub routine to find the starting row index
sub findRowindex()
{
my $ret = ();
for(my $index=1;$index<$no_rows;$index++)
{
    if(defined($excelSheet->Cells($index,1)))
    {
        my $cel_value = $excelSheet->Cells($index,1)->Value();
        if($cel_value =~ m/^Name$/i)
        {
            $ret = $index;
            last;
        }
    }
}
return $ret;

}

#Trim function
sub trim {
(my $s = $_[0]) =~ s/^\s+|\s+$//g;
return $s;        

}

【问题讨论】:

    标签: perl


    【解决方案1】:

    解决方法:您可以使用 Excel::Writer::XLSX 创建 Excel 文件,它工作正常且非常强大。以下是将制表符分隔的文件转换为 Excel 的方法。

    阅读excel:电子表格::XLSX

    use Text::Iconv;
    my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
    
    
    use Spreadsheet::XLSX;
    my $excel = Spreadsheet::XLSX -> new ('test.xlsx', $converter);
    foreach my $sheet (@{$excel -> {Worksheet}}) {
            printf("Sheet: %s\n", $sheet->{Name});
            $sheet -> {MaxRow} ||= $sheet -> {MinRow};
             foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) {       
                    $sheet -> {MaxCol} ||= $sheet -> {MinCol};              
                    foreach my $col ($sheet -> {MinCol} ..  $sheet -> {MaxCol}) {     
                            my $cell = $sheet -> {Cells} [$row] [$col];
                            if ($cell) {
                                printf("( %s , %s ) => %s\n", $row, $col, $cell -> {Val});
                            }
    
                    }
            }
     }
    

    编写excel:Excel::Writer::XLSX

    my $workbook = Excel::Writer::XLSX->new( $xls_filename );
    my $worksheet = $workbook->add_worksheet('data');
    # Create a format for the headings
    my $header_format = $workbook->add_format();
    $header_format->set_bold(); 
    $header_format->set_size( 18 );
    $header_format->set_color( 'black' );
    $header_format->set_align( 'center' );
    my $row=0;
    while (my $line = <$fh>){
        chomp($line);       
        my @cols = split(/\t/,$line);
        for(my $col=0;$col<@cols;$col++){
            if ($row == 0 ){
                $worksheet->write_string( $row, $col, $cols[$col],$header_format );
            } else {
                $worksheet->write_string( $row, $col, $cols[$col] );
            }
        }
        $row++;
    }
    close($fh); 
    

    希望对你有帮助。

    问候,

    【讨论】:

    • 您好,感谢您的回复,非常感谢。有一个小问题。不幸的是,我不能使用电子表格或 Excel::Writer::XLSX,因为我被要求使用 Win32::OLE 编写脚本。希望使用 OLE 库的其他人将对此进行进一步的补充。所以我被这个困住了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多