Perl Excel::Writer::XLSX判断工作表存在避免add_worksheet报错
Perl Excel::Writer::XLSX 工作表存在性校验实现方案
Excel::Writer::XLSX的add_worksheet方法碰到重名工作表会直接抛出致命错误终止程序,不会返回假值,因此直接将调用语句放在if条件中无法走到else分支,可通过以下两种方案实现需求:
方案1:自行维护已创建工作表映射表(推荐)
所有工作表均由业务代码主动创建,自行维护已创建工作表的哈希映射是性能最高、逻辑最可控的方案,无需额外捕获异常。
注意模块对工作表重名的判定是大小写不敏感的,存储和判断时需要统一转为小写/大写匹配规则。
示例代码:
# 初始化已存在工作表的存储哈希,key为小写表名,value为工作表对象 my %sheet_map; my $target_sheet_name = $filters{$filter}{description}; my $sheet_key = lc($target_sheet_name); my $sheet; unless (exists $sheet_map{$sheet_key}) { # 表不存在,执行创建+初始化 $sheet = $workbook->add_worksheet($target_sheet_name); $sheet_map{$sheet_key} = $sheet; # 此处写入初始化逻辑:插入表头、设置单元格样式等 # $sheet->write_row(0, 0, \@header_list); # my $header_style = $workbook->add_format(bold => 1, bg_color => '#CCCCCC'); # ... } else { # 表已存在,直接复用已有对象,跳过初始化 $sheet = $sheet_map{$sheet_key}; }
方案2:捕获创建时抛出的异常
如果不想额外维护哈希表,可通过块级eval捕获add_worksheet抛出的异常,区分错误类型执行对应逻辑,注意不要无差别吞掉所有错误。
示例代码:
my $target_sheet_name = $filters{$filter}{description}; my $sheet; eval { $sheet = $workbook->add_worksheet($target_sheet_name); # 未触发异常说明创建成功,执行初始化 # 此处写入表头插入、样式设置等初始化逻辑 # $sheet->write_row(0, 0, \@header_list); 1; # 标记eval块执行成功 } or do { my $error = $@; # 判断是否为工作表重名错误 if ($error =~ /is already used/i) { # 遍历已有工作表,匹配大小写不敏感的目标表名 for my $exist_sheet ($workbook->sheets()) { if (lc($exist_sheet->get_name()) eq lc($target_sheet_name)) { $sheet = $exist_sheet; last; } } } else { # 其他错误(如表名含非法字符、长度超31位限制、工作簿已关闭等)直接抛出 die $error; } };
注意事项
- 不要使用旧版
eval { ... } if $@的异常捕获写法,避免$@变量被其他逻辑修改导致错误捕获失效,推荐使用上述eval { ...; 1 } or do { ... }的稳定写法。 - 所有表名匹配逻辑必须做大小写转换,否则会漏判
All Users和all users这类大小写不同但被模块判定为重名的场景。 - 异常捕获时必须校验错误类型,禁止直接吞掉所有异常,否则会导致其他类型的运行错误被静默忽略,提升问题排查难度。
内容的提问来源于stack exchange,提问作者olivierg
相关产品推荐
相关产品推荐

