Проблемы с разбором файла Excel 2010 .xlsx с помощью Win32::OLE в Perl

У меня есть файл excel (.xlsx), подключенный к «источнику данных» с файлом .iqy. Я использовал Perl, чтобы открыть файл Excel и обновить данные. Изначально мой код работал. Однако мне нужно было изменить файл .iqy, с которым была связана моя электронная таблица, и это, похоже, сломало мой Perl-скрипт (несмотря на то, что на самом деле ничего не изменилось внутри самого скрипта). Теперь он терпит неудачу, когда я звоню

my $LastRow = $Sheet->UsedRange->Find({What=>"*",
    SearchDirection=>xlPrevious,
    SearchOrder=>xlByRows})->{Row};

и вывод cmd гласит: «Невозможно использовать неопределенное значение в качестве ссылки HASH в строке 20 sharing.pl». Я пытался отладить это, но я недостаточно знаю о внутренностях модуля Win32::OLE, чтобы знать, как даже поймать, где или почему проблема возникает в отладчике. Исходный код моего скрипта:

#!/usr/bin/perl
use Win32::OLE;
use Win32::OLE qw(in with);
use Win32::OLE::Variant;
use Win32::OLE::Const 'Microsoft Excel';

$Excel = Win32::OLE->GetActiveObject('Excel.Application') ||
       Win32::OLE->new('Excel.Application');
$Excel->{'Visible'} = 0;        #0 is hidden, 1 is visible
$Excel->{DisplayAlerts}=0;  #0 is hide alerts

# Open File and Worksheet
my $Book = $Excel->Workbooks->Open ('C:\shareP\sp.xlsx'); # open Excel file
$Sheet = $Book->Worksheets(1);

# Refresh Data (ActiveWorkbook.RefreshAll)
$Book->RefreshAll();

# Find Last Column and Row
my $LastRow = $Sheet->UsedRange->Find({What=>"*",
    SearchDirection=>xlPrevious,
    SearchOrder=>xlByRows})->{Row};

my $LastCol = $Sheet->UsedRange->Find({What=>"*", 
              SearchDirection=>xlPrevious,
              SearchOrder=>xlByColumns})->{Column};
####### EDIT: I initially didn't post this portion because it stops
#       before reaching it unless I make $LastCol and $LastRow constants
my @hasher;
my $c = "a";
for (my $cn=1; $cn <= $LastCol; $cn++){
    for (my $r=2; $r <= $LastRow; $r++){
# stops here with same error if I make $LastCol and $LastRow constants
        $hasher[$r-2]{ $Sheet->Range($c.'1')->{Value} } = $Sheet->Range($c.$r)->{Value};
    }
$c++;
}
####### end of EDIT
# Save as Excel
$Book->Save();  
$Book->Close();
$Excel->Quit();  

Заранее спасибо за любой совет. Я действительно застрял на этом.


person user1226409    schedule 22.02.2012    source источник


Ответы (3)


Я считаю, что ваша функция поиска сейчас не возвращает значение. У меня есть два возможных объяснения.

1) Возможно, ваши новые исходные данные больше не содержат символов "*"

2) Функция поиска запоминает некоторые атрибуты между использованиями, а именно LookIn, LookAt и SearchOrder. Для достижения наилучших результатов вы всегда должны устанавливать эти 3 атрибута при поиске, чтобы убедиться, что вы получаете желаемую функциональность.

Мой совет — попробовать выполнить поиск вручную на электронной таблице и посмотреть, сработает ли он. Я не думаю, что ваша ошибка связана с OLE-частью сценария.

person Pynner    schedule 22.02.2012
comment
Найти * работает в электронной таблице, если выполняется вручную. У меня также было больше кода ниже этого, до save() и close(), который я удалил, так как он все равно остановился, не дойдя до него. Я попытался сделать переменные $LastRow и $LastCol постоянными, но затем код остановился дальше с той же ошибкой. (посмотрите, что я добавил в пост, извините, что сначала пропустил это). Однако, если я запускаю код дважды с $LastRow и $LastCol в качестве констант, он работает при втором запуске... единственная разница, которую я вижу, заключается в том, что во втором запуске Excel все еще открыт с первого запуска, поскольку он не t достичь близко(). - person user1226409; 22.02.2012
comment
учитывая вашу дополнительную информацию... Я собираюсь предположить, что проблема как-то связана с тем, что $Sheet пуст. Попробуйте обратиться к рабочему листу по текстовому имени, а не по номеру, и посмотрите, поможет ли это. - person Pynner; 23.02.2012

Я решил проблему, добавив короткую паузу в код. Сценарий Perl продвигался вперед до того, как лист Excel мог завершить обновление. Спасибо за помощь.

person user1226409    schedule 16.03.2012

Я думаю, это потому, что одна из ваших электронных таблиц пуста. Лучший способ получить общее количество столбцов и строк:

my $Tot_Rows= $Sheet->UsedRange->Rows->{'Count'}; 

my $Tot_Cols= $Sheet->UsedRange->Columns->{'Count'}; 
person kaidong    schedule 21.01.2016