2015-04-29 2 views
2

J'ai besoin d'extraire des données tabulaires à partir d'un fichier MS-Word. Le code auquel je me suis référé ne récupère que les première et dernière lignes, mais je dois aller chercher la table entière.Récupérer des données tabulaires à partir d'un fichier MS-Word

Plus tard, les données récupérées doivent être vérifiées si le même nom de fichier existe dans le dossier.

Je ne suis même pas capable de comprendre le déroulement du code, étant donné que je suis nouveau dans le module Win32::OLE.

J'ai fait référence à une question similaire concernant l'extraction de données sur ce site, mais je n'ai pas pu l'obtenir.

S'il vous plaît laissez-moi savoir comment procéder.

#!/usr/bin/perl 

use strict; 
use warnings; 

use File::Spec::Functions qw(catfile); 
use Win32::OLE qw(in); 
use Win32::OLE::Const 'Microsoft Word'; 

$Win32::OLE::Warn = 3; 

my $word = get_word(); 
$word->{DisplayAlerts} = wdAlertsNone; 
$word->{Visible}  = 1; 

my $doc = $word->{Documents}->Open('D:\A.doc'); 
my $tables = $word->ActiveDocument->{'Tables'}; 

for my $table (in $tables) { 
    my $tableText = $table->ConvertToText({ Separator => wdSeparateByTabs }); 
    print "Table: " . $tableText->Text() . "\n"; 
} 

$doc->Close(0); 

sub get_word { 
    my $word; 
    eval { $word = Win32::OLE->GetActiveObject('Word.Application'); }; 
    die "[email protected]\n" if [email protected]; 
    unless (defined $word) { 
    $word = Win32::OLE->new('Word.Application', sub { $_[0]->Quit }) 
     or die "Oops, cannot start Word: ", Win32::OLE->LastError, "\n"; 
    } 
    return $word; 
} 

MISE À JOUR: A.doc

Article No.  Count No  Committee 
A0029  A0029 16   E01.07 
B0028  B0028 34   E04.09 
C0036  C0036 17   E09.00 
D0033  D0033 15   E08.07 

sortie CMD

D:\Word>A.pl 
D0033 D0033 15  E08.07No      Committee 
+0

Vous devez consulter le [Word Developer Reference] (https://msdn.microsoft.com/en-us/library/office/ff841702% 28v = office.14% 29.aspx) qui liste toutes les classes disponibles avec leurs propriétés et méthodes. Mais je ne vois pas pourquoi votre code devrait aller chercher seulement les première et dernière lignes. La méthode 'Table.ConvertToText' renvoie un objet' Range', qui correspond essentiellement aux positions de début et de fin de la table. Et la propriété 'Range.Text' est juste le texte entre ces deux positions, donc peu de choses peuvent mal se passer. Regardez-vous cela sur une console? – Borodin

+0

Etes-vous capable de publier votre document Word afin que nous puissions l'essayer nous-mêmes? – Borodin

+0

@Borodin: Je le vois sur la console (cmd) et je lance le programme en tant que D: \> A.pl J'ai essayé le code dans divers fichiers doc qui a plusieurs lignes ainsi que seulement sur deux rangs, mais je reçois la même sortie .. – flora

Répondre

1

Le problème est causé par le fait que les lignes de la table se terminent par CR caractères dans le texte retourné par la méthode ConvertToText:

C:\...\Temp> perl word-table.pl A.doc | xxd 
00000000: 4172 7469 636c 6509 4e6f 2e09 436f 756e Article.No..Coun 
00000010: 7420 4e6f 0943 6f6d 6d69 7474 6565 0d41 t No.Committee.A 
00000020: 3030 3239 0941 3030 3239 0931 3609 4530 0029.A0029.16.E0 
00000030: 312e 3037 0d42 3030 3238 0942 3030 3238 1.07.B0028.B0028 
00000040: 0933 3409 4530 342e 3039 0d43 3030 3336 .34.E04.09.C0036 
00000050: 0943 3030 3336 0931 3709 4530 392e 3030 .C0036.17.E09.00 
00000060: 0d44 3030 3333 0944 3030 3333 0931 3509 .D0033.D0033.15. 
00000070: 4530 382e 3037 0d0d 0a     E08.07...

Pour résoudre, remplacer les retours chariot avec des sauts de ligne:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Carp qw(croak); 
use Cwd qw(abs_path); 
use Path::Class; 
use Win32::OLE qw(in); 
use Win32::OLE::Const 'Microsoft Word'; 

$Win32::OLE::Warn = 3; 

run(\@ARGV); 

sub run { 
    my $argv = shift; 
    my $word = get_word(); 

    $word->{DisplayAlerts} = wdAlertsNone; 
    $word->{Visible}  = 1; 

    for my $word_file (@$argv) { 
     print_tables($word, $word_file); 
    } 

    return; 
} 

sub print_tables { 
    my $word = shift; 
    my $word_file = file(abs_path(shift)); 

    my $doc = $word->{Documents}->Open("$word_file"); 
    my $tables = $word->ActiveDocument->{Tables}; 

    for my $table (in $tables) { 
     my $text = $table->ConvertToText(wdSeparateByTabs)->Text; 
     $text =~ s/\r/\n/g; 
     print $text, "\n"; 
    } 

    $doc->Close(0); 
    return; 
} 

sub get_word { 
    my $word; 
    eval { $word = Win32::OLE->GetActiveObject('Word.Application'); 1 } 
     or die "[email protected]\n"; 
    $word and return $word; 
    $word = Win32::OLE->new('Word.Application', sub { $_[0]->Quit }) 
     or die "Oops, cannot start Word: ", Win32::OLE->LastError, "\n"; 
    return $word; 
} 
+0

@flora Est-ce que ma réponse a résolu votre problème? –