【问题标题】:Getting list of hyperlinks from an Excel worksheet with Perl Win32::OLE使用 Perl Win32::OLE 从 Excel 工作表中获取超链接列表
【发布时间】:2012-05-25 14:44:57
【问题描述】:

我想更改 Excel 电子表格中一堆超链接的路径。在 Google 搜索后,我发现了一个solutions 问题,即添加 超链接到电子表格,但没有更改 它们。 Microsoft 展示了如何使用 VBA here 完成一些事情。

由于我想编辑文档中的每个超链接,我不知道如何解决的关键步骤是:

  1. 在 Perl 中获取超链接对象列表

  2. 一一提取他们的地址并

  3. 运行正则表达式来改变路径

  4. 将更新后的路径存储在超链接中->对象并重复

我是使用 OLE 的新手,在 (1) 上遇到了麻烦。到目前为止,这是我尝试过的:

#!perl
use strict;
use warnings;
use 5.014;
use OLE;
use Win32::OLE::Const "Microsoft Excel";

my $file_name = 'C:\path\to\spreadsheet.xlsx';
my $excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;});
$excel->{Visible} = 1;
my $workbook = $excel->Workbooks->Open($file_name);
my $sheet = $workbook->Worksheets('Sheet 1');
foreach my $link (in $sheet->Hyperlinks ) {
say $link->Address;
}

但这会给代码带来错误:

Win32::OLE(0.1709): GetOleEnumObject() 不是 C:/Dwimperl/perl/vendor/lib/Win32/OLE/Lite.pm 第 167 行的 Win32::OLE::Enum 对象。 无法在 script.pl 第 14 行调用没有包或对象引用的方法“超链接”。

它选择了正确的工作表,所以我不确定它为什么抱怨对象引用。我尝试了几种变体(在超链接周围添加 {},删除“in”,尝试将其存储为列表、哈希以及对哈希的引用)谁能给我一些指示?谢谢!

【问题讨论】:

  • “Sheet”和“1”之间应该有空格吗?默认情况下,Excel 将其工作表命名为“Sheet1”,没有空格。
  • 你的代码真的是foreach my $link (in $sheet->Hyperlinks )吗?我想不会,因为它会编译为 $sheet->in->Hyperlinks 并且工作表没有方法 in
  • @Borodin "in(COLLECTION)如果 COLLECTION 是 OLE 集合对象,则在 $COLLECTION 中返回集合所有成员的列表。这是一个Win32::OLE::Enum-All($COLLECTION) 的快捷方式。它最常用于foreach 循环"。我认为 OP 必须使用 in( $sheet->Hyperlinks ),但我发现 in 很不稳定。或者,换一种说法,当我使用 in 时遇到问题,我总是能够通过使用显式构造的 Win32::OLE::Enum 迭代器来避免这些问题。
  • 啊,我明白了。谢谢思南。所以它是一个 function 并且需要从 OP 的问题没有显示的Win32::OLE 导出。
  • @Borodin 正确,你说得比我冗长的引述和漫无边际的评论要简洁得多;-)

标签: perl excel hyperlink ole


【解决方案1】:

首先,您应该设置$Win32::OLE::Warn=3,这样您的脚本就会在出现问题时发出嘶嘶声。其次,我知道您不能在旧版本的 Excel 中按名称选择工作表,尽管我不知道最新版本中的情况如何。最后,我想你会发现使用Win32::OLE::Enum 会更容易。

这是一个例子:

#!/usr/bin/env perl

use 5.014;
use warnings; use strict;

use Carp qw( croak );
use Path::Class;
use Try::Tiny;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';
use Win32::OLE::Enum;
$Win32::OLE::Warn = 3;

my $book_file = file($ENV{TEMP}, 'test.xls');
say $book_file;

my $excel = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;});
$excel->{Visible} = 1;

my $book = $excel->Workbooks->Open("$book_file");
my $sheet = get_sheet($book, 'Sheet with Hyperlinks');
my $links = $sheet->Hyperlinks;
my $it = Win32::OLE::Enum->new($links);

while (defined(my $link = $it->Next)) {
    my $address = $link->{Address};
    say $address;
    if ($address =~ s/example/not.example/) {
        $link->{Address} = $address;
        $link->{TextToDisplay} = "Changed to $address";
    }
}

$book->Save;
$book->Close;
$excel->Quit;

sub get_sheet {
    my ($book, $wanted_sheet) = @_;

    my $sheets = $book->Worksheets;
    my $it = Win32::OLE::Enum->new($sheets);

    while (defined(my $sheet = $it->Next)) {
        my $name = $sheet->{Name};
        say $name;
        if ($name eq $wanted_sheet) {
            return $sheet;
        }
    }

    croak "Could not find '$wanted_sheet'";
}

工作簿确实包含一个名为 "Sheet with Hyperlinks" 的工作表。该表中的单元格A1 包含http://example.com,而A2 包含http://stackoverflow.com

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    相关资源
    最近更新 更多