Как открыть текстовый файл с разделителями табуляции в Excel с помощью Perl и OLE?

Первоначально я пытался открыть файл XML с помощью Excel. Но поскольку это занимает много времени, я сам разобрал XML в текстовый файл с разделителями табуляции. Я думал, что нашел правильный синтаксис в Интернете. Я попробовал код ниже, используя значения, которые я записал с помощью макроса Excel. У меня есть файл с разделителями табуляции из 18 столбцов. Ошибка возникает в последней строке приведенного ниже кода при вызове метода «Рабочие листы».

Сообщение об ошибке: Невозможно вызвать метод "Worksheets" без ссылки на пакет или объект в строке 70 файла ./PostProcessingDev.pl.

use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';
Win32::OLE->Option(Warn => 3);

use strict;

my $Excel;
my $Sheet;
my $Workbook;


$Excel = CreateObject OLE "Excel.Application";

$Workbook =  $Excel->Workbooks->OpenText({Filename =>"$inSelf->{'TXT'}",
  Origin => xlMSDOS,
  StartRow => 1,
  DataType => xlDelimited, 
  TextQualifier => xlDoubleQuote, 
  ConsecutiveDelimiter => "False", 
  Tab => "True",
  Semicolon => "False",
  Comma => "False",
  Space => "False",
  Other => "False",
  FieldInfo => [[1, xlTextFormat],
    [2, xlTextFormat],
    [3, xlTextFormat],
    [4, xlTextFormat],
    [5, xlTextFormat],
    [6, xlTextFormat],
    [7, xlTextFormat],
    [8, xlTextFormat],
    [9, xlTextFormat],
    [10, xlTextFormat],
    [11, xlTextFormat],
    [12, xlTextFormat],
    [13, xlTextFormat],
    [14, xlTextFormat],
    [15, xlTextFormat],
    [16, xlTextFormat],
    [17, xlTextFormat],
    [18, xlTextFormat]],
  TrailingMinusNumbers => "True"});

$Sheet = $Workbook->Worksheets(1);

person user617474    schedule 15.02.2011    source источник


Ответы (3)


Вам действительно нужно анализировать TSV с помощью Excel? Если в ваших файлах нет ничего особенного, вы можете использовать что-то вроде этого:

my $file = 'some tsv file';
{
    open my $in,"<",$file  or die "$file: $!";
    while(<$in>) {
        chomp;
        my @cols = split /\t/;
        # do something with columns in @cols array
    }
}

Если Excel нужен по непонятной мне причине, проблема в том, что метод OpenText возвращает True/False, а не объект Workbook. Это работает:

use strict;

use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';
use Data::Dump;     # for dd

Win32::OLE->Option(Warn => 3);

my $Excel = Win32::OLE->new("Excel.Application");
$Excel->Workbooks->OpenText({
    Filename             => 'enter the full path to file',
    Origin               => xlMSDOS,
    StartRow             => 1,
    DataType             => xlDelimited,
    TextQualifier        => xlDoubleQuote,
    Tab                  => "True",
    TrailingMinusNumbers => "True"
});

my $Sheet = $Excel->ActiveWorkbook->Worksheets(1);
my $Data = $Sheet->UsedRange()->{Value};

dd $Data;    # arrayref (rows) of arrayrefs (columns)
person bvr    schedule 15.02.2011
comment
Вы не должны анализировать файлы xSV с помощью разделения/регулярных выражений. То же, что и CSV, используйте соответствующий модуль (текст: CSV_CS) - person DVK; 15.02.2011
comment
Спасибо за быстрый ответ. Нет, я не использую Excel в качестве парсера. Парсинговую часть я написал сам, так как не могу ни использовать, ни установить нужные модули. Я делаю все внутри массивов Pearl. TSV, а также файл Excel являются выходными данными. Поскольку запись Excel Cell by Cell медленнее (десятки тысяч строк) по сравнению с открытием TSV, я просто хочу открыть TSV и сохранить его как Excel. Попробовав свой код в 4-строчном текстовом файле, он застрял внутри метода OpenText. Как я могу увидеть, что происходит? Можно ли отлаживать методы OLE? - person user617474; 15.02.2011
comment
Я не правильно понял, что вы хотите. Если вы записываете CSV с расширением .CSV, Excel связывается и может открыть его напрямую. Для отладки OLE это немного сложно, но вы можете поставить $Excel->{Visible} = 1; после инициализации, и вы можете видеть, что происходит в Excel. - person bvr; 15.02.2011
comment
@DVK Если вы знаете, какие у вас данные, почему бы не разделить? Преимущество TSV заключается в том, что символ табуляции редко встречается в данных, подобных базе данных. Естественно, он не должен запускаться в производство для обработки произвольных данных. - person bvr; 15.02.2011
comment
@bvr - Поверьте мне, в первый раз, когда ваш скрипт дает сбой из-за того, что данные содержат дурацкие вещи (а они будут), вы начнете жалеть, что не изобрели велосипед заново (плохо) - person DVK; 15.02.2011
comment
@DVK Слишком поздно - многие из моих сценариев потерпели неудачу из-за творчества пользователя, будь то с использованием синтаксического анализатора или ручных решений. Но я принимаю вашу точку зрения - синтаксический анализатор, безусловно, подходит, по крайней мере, он намного лучше протестирован, чем мой код. - person bvr; 15.02.2011

попробуйте использовать Text::CSV . он поддерживает определяемые пользователем разделители. См. описание модуля.

person Беров    schedule 15.02.2011

Спасибо вообще за ваши ответы. Это решило мою проблему. Все, что я хотел сделать с помощью метода OpenText, — это преобразовать файл TSV в Excel, поскольку это формат результата, который мне нужен. Поскольку я не мог найти решение в Интернете, прежде чем предоставить полный код:

use Win32::OLE;
use Win32::OLE::Const 'Microsoft Excel';
use strict;

Win32::OLE->Option(Warn => 3);

my $FileName = "Complete Path of TSV File";

my $Excel = Win32::OLE->new("Excel.Application");

# Open Tab separated Text file in Excel, all 18 columns are "Text" formated
$Excel->Workbooks->OpenText({
  Filename      => $FileName,
  Origin        => xlMSDOS,
  StartRow      => 1,
  DataType      => xlDelimited,
  TextQualifier => xlDoubleQuote,
  Tab           => "True",
  FieldInfo     => [[1, xlTextFormat],
    [2, xlTextFormat],
    [3, xlTextFormat],
    [4, xlTextFormat],
    [5, xlTextFormat],
    [6, xlTextFormat],
    [7, xlTextFormat],
    [8, xlTextFormat],
    [9, xlTextFormat],
    [10, xlTextFormat],
    [11, xlTextFormat],
    [12, xlTextFormat],
    [13, xlTextFormat],
    [14, xlTextFormat],
    [15, xlTextFormat],
    [16, xlTextFormat],
    [17, xlTextFormat],
    [18, xlTextFormat]],
  TrailingMinusNumbers => "True"
});

my $Sheet = $Excel->ActiveWorkbook->Worksheets(1);
$Sheet->Activate;

my $Workbook = $Excel->ActiveWorkbook;

# Replace the "*.txt" file extension by "*.xls" for Excel
$FileName =~ s/txt$/xls/;

# Turn off the "This file already exists" message.
$Excel->{DisplayAlerts} = 0;
# Save file as Excel 2000-2003 Workbook (command for Excel 2007)
$Workbook->SaveAs({Filename => $FileName, FileFormat => xlExcel8});
$Excel->Quit; 
person user617474    schedule 16.02.2011