如何用Perl脚本读写.XLSM文件并实现单元格匹配写入?
Perl处理.xlsm文件的实操方案(RHEL 8.6)
.xlsm是带宏的压缩二进制Excel格式,不能用Perl原生的open()直接读取,得用专门处理Excel的Perl模块。下面是针对你需求的分步解决办法:
1. 安装必要模块
在RHEL 8.6上先安装系统依赖和Perl模块:
# 安装编译模块所需的系统依赖 sudo dnf install perl-ExtUtils-MakeMaker perl-CPAN libxml2-devel zlib-devel # 用cpanm安装Excel处理模块 cpanm Spreadsheet::XLSX Excel::Writer::XLSX
2. 完整代码示例
以下代码实现你要求的所有操作:读取xlsm文件、匹配数组字符串、在同行指定列写入内容、输出新的xlsm文件(注意:此方法会丢失原文件中的宏,需保留宏的话见文末说明)
use strict; use warnings; use Spreadsheet::XLSX; use Excel::Writer::XLSX; # 配置参数,根据你的需求修改 my $input_file = 'your_target.xlsm'; # 输入的xlsm文件路径 my $output_file = 'modified_result.xlsm'; # 修改后的输出文件路径 my @search_strings = ('张三', '项目A', '待处理'); # 需要匹配的字符串数组 my $write_column = 'F'; # 要写入内容的目标列(对应示例中的F列) my $write_content = '已匹配'; # 要写入的字符内容 # 列名转列索引(Excel模块用0起始索引) sub column_to_idx { my $col_name = shift; my $idx = 0; foreach my $c (split //, uc $col_name) { $idx = $idx * 26 + (ord($c) - ord('A') + 1); } return $idx - 1; } my $target_col_idx = column_to_idx($write_column); # 读取原xlsm文件 my $excel_reader = Spreadsheet::XLSX->new($input_file); # 创建新的xlsm输出文件 my $excel_writer = Excel::Writer::XLSX->new($output_file, { format => 'xlsm' }); # 遍历原文件的每个工作表 foreach my $old_sheet (@{$excel_reader->{Worksheet}}) { # 在新文件中创建同名工作表 my $new_sheet = $excel_writer->add_worksheet($old_sheet->{Name}); # 处理工作表的行列范围 $old_sheet->{MaxRow} ||= $old_sheet->{MinRow}; $old_sheet->{MaxCol} ||= $old_sheet->{MinCol}; # 遍历每一行 for my $row ($old_sheet->{MinRow} .. $old_sheet->{MaxRow}) { # 遍历每一列 for my $col ($old_sheet->{MinCol} .. $old_sheet->{MaxCol}) { # 获取原单元格内容 my $cell = $old_sheet->{Cells}[$row][$col]; my $cell_val = $cell ? $cell->{Val} : ''; # 将原内容写入新工作表对应位置 $new_sheet->write($row, $col, $cell_val); # 检查当前单元格是否匹配目标字符串 if (grep { $_ eq $cell_val } @search_strings) { # 在同行的目标列写入指定内容 $new_sheet->write($row, $target_col_idx, $write_content); } } } } # 关闭工作簿,完成写入 $excel_writer->close; print "处理完成,输出文件:$output_file\n";
3. 关键说明
- 宏的保留:上述模块处理后会丢失原文件中的宏,如果必须保留宏,可手动将xlsm文件解压(本质是zip压缩包),修改内部
xl/worksheets目录下的工作表XML文件,再重新打包,但操作复杂度较高,新手不推荐。 - 匹配逻辑:代码中是精确匹配字符串,若需要模糊匹配,可将
grep { $_ eq $cell_val }替换为grep { index($cell_val, $_) != -1 }。 - 列修改:若要更换写入列,直接修改
$write_column的值即可(如改为'G')。
内容的提问来源于stack exchange,提问作者PerlNoobie
相关产品推荐
相关产品推荐

