2011-07-27 7 views
4

나는 Spreadsheet :: ParseExcel을 사용하여 Perl 프로그램을 가지고있다. 그러나 해결 방법을 찾을 수 없다는 두 가지 어려움이 있습니다.Perl에서 Spreadsheet :: ParseExcel 사용하기, 도움이 필요함

#!/usr/bin/perl 
use strict; 
use warnings; 
use Spreadsheet::ParseExcel; 
use WordNet::Similarity::lesk; 
use WordNet::QueryData; 

my $wn = WordNet::QueryData->new(); 
my $lesk = WordNet::Similarity::lesk->new($wn); 
my $parser = Spreadsheet::ParseExcel->new(); 
my $workbook = $parser->parse ('input.xls'); 

if (!defined $workbook) { 
    die $parser->error(), ".\n"; 
} 

WORKSHEET: 
for my $worksheet ($workbook->worksheets()) { 

    my $sheetname = $worksheet->get_name(); 
    my ($row_min, $row_max) = $worksheet->row_range(); 
    my ($col_min, $col_max) = $worksheet->col_range(); 
    my $target_col; 
    my $response_col; 

# Skip worksheet if it doesn't contain data 
    if ($row_min > $row_max) { 
     warn "\tWorksheet $sheetname doesn't contain data. \n"; 
     next WORKSHEET; 
    } 

# Check for column headers 
    COLUMN: 
    for my $col ($col_min .. $col_max) { 

     my $cell = $worksheet->get_cell($row_min, $col); 
     next COLUMN unless $cell; 

     $target_col = $col if $cell->value() eq 'Target'; 
     $response_col = $col if $cell->value() eq 'Response'; 
    } 

    if (defined $target_col && defined $response_col) { 

     ROW: 
     for my $row ($row_min + 1 .. $row_max) { 
      my $target_cell = $worksheet->get_cell($row, $target_col); 
      my $response_cell = $worksheet->get_cell($row, $response_col); 
      if (defined $target_cell && defined $response_cell) { 
       my $target = $target_cell->value(); 
       my $response = $response_cell->value(); 

       my $value = $lesk->getRelatedness($target, $response); 

       print "Worksheet = $sheetname\n"; 
       print "Row   = $row\n"; 
       print "Target  = $target\n"; 
       print "Response = $response\n"; 
       print "Relatedness = $value\n";     

      } 
      else { 

       warn "\tWroksheet $sheetname, Row = $row doesn't contain target and response data.\n"; 
       next ROW; 
      } 
     }  
    } 
    else { 

     warn "\tWorksheet $sheetname: Didn't find Target and Response headings.\n"; 
     next WORKSHEET; 
    } 
} 

그래서, 내 두 가지 문제 : 모든

먼저, 때로는 프로그램이 오류를 반환 데이터가 비록 "파일을 찾을 수 없습니다 Excel 데이터를"다음과 같이 프로그램의 스크립트입니다 그곳에. 각 Excel 파일은 같은 방식으로 형식이 지정됩니다. '대상'과 '응답'이라고 표시된 A 및 B 열이 각각 한 장만 있으며 그 아래에 단어 목록이 있습니다. 그러나 항상이 오류를 반환하지는 않습니다. 그것은 하나의 엑셀 파일에 대해 작동하지만, 두 파일 모두 똑같은 방식으로 포맷되었지만 (다른 파일 형식에서도 똑같습니다) 두 번째 파일을 읽지 않는 이유는 첫 번째 파일과 동일하기 때문에 찾을 수 없습니다. 유일한 차이점은 Excel 매크로를 사용하여 두 번째 파일을 만들었습니다. 그러나 왜 그렇게 중요할까요? 파일 형식과 형식은 완전히 동일합니다.

두 번째로, '$ target'및 '$ response'변수는 'my $ value'표현식이 작동하려면 문자열로 형식화해야합니다. 문자열 형식으로 변환하려면 어떻게해야합니까? 각 변수에 할당 된 값은 Excel 스프레드 시트의 해당 셀에있는 단어입니다. 어떤 형식인지는 알지 못합니다. (그리고 Perl에서는 확인할 방법이 없습니다).

제안 사항?

+0

잘 형식화 된 변경 코드를 확인하십시오! – Zaid

답변

3

첫 번째 질문과 관련하여 "데이터 없음"오류는 파일 형식에 문제가 있음을 나타냅니다. xls 확장자를 가진 HTML 또는 CSV 파일과 같은 가상 Excel 파일에서이 오류를 보았습니다. 타사 응용 프로그램에서 생성 된 잘못된 파일에 대해서도이 오류를 보았습니다.

작동중인 파일과 작동하지 않는 파일의 덤프/xxd 덤프를 수행하고 전체 구조가 거의 같은지 확인하여 파일의 초기 확인을 수행 할 수 있습니다 (예 : 처음부터 비슷한 마법 번호가있는 경우 및 HTML이 아닙니다.)

Spreadsheet :: ParseExcel에서도 문제가 될 수 있습니다. 나는 그 모듈의 관리자이다. 당신이 좋아하는 경우에 문서의 전자 메일 주소에서 "좋은"파일과 "나쁜"파일을 보낼 수 있으며, 나는 그들을 살펴볼 것입니다.

+0

나는 그것들을 알아 내기 위해 헥스 덤프에 대해 충분히 알지 못합니다. 아마도 파일을 좋아하지 않는 이유를 알 수없는 한 .txt 파일이나 다른 것을 사용하는 것으로 전환 될 것입니다. 어쨌든, 고마워, 방금 이메일을 보냈습니다. – Billy

+3

이것에 대한 업데이트를 제공합니다.문제가있는 파일은 실제로 Excel 2007 xlsx 파일입니다. 스프레드 시트 :: XLSX 또는 스프레드 시트 :: 읽기로 읽어야합니다. Spreadsheet :: ParseExcel은 2007 이전 파일 형식 만 처리 할 수 ​​있습니다. – jmcnamara

0

"데이터가 없음"을 얻는다면 독점적 인 Excel 데이터 파일 형식과 좋은 Perl 라이브러리가 정보를 추출 할 수 없기 때문에 감사 할 수 있습니다.

특히 내가 설명한 데이터 레이아웃의 단순한 특성을 고려하면 CSV와 같이 쉽게 구문 분석 된 것으로 Excel 데이터를 내보내는 것이 좋습니다. Excel에서 일괄 처리를 처리하는 방법이있을 수 있지만 잘 모르겠습니다. 빠른 검색 결과는 tool to use OpenOffice to do batch conversion입니다.

Excel 데이터 파일이 정상적으로 재생되지 않는다고 받아들이면 나머지 질문에 대해서는 의의가 있습니다.

0

나는 그가 매주 보내는 XLS가 실제로 XLS 형식 또는 CSV ....인지 여부를 결정할 수 없으면이 코드를 작성했습니다. HTH!

sub testForXLS() 
{ 
my ($FileName) = @_; 
my $signature  = ''; 
my $XLSsignature = 'D0CF11E0A1B11AE10000'; 

open(FILE, "<$FileName")||die; 
read(FILE, $buffer, 10, 0); 
close(FILE); 

foreach (split(//, $buffer)) 
    { $signature .= sprintf("%02x", ord($_)); } 

$signature =~ tr/a-z/A-Z/; 

if ($signature eq $XLSsignature) 
{ return 1; } else { return 0; } 

}