Perl: Win32::OLE and Microsoft Outlook - Iterating

2019-02-17 22:27发布

问题:

I'm an intern and very new to this...

My boss gets an email with two attachments every Monday which he has to turn into wiki code and put it on our internal website. The process takes roughly 20 minutes every Monday due to the amount of information to transfer. I've been asked to stream line this process.

I have code which will parse the file and break it up into components, and I have code to grab all the attachments out of his inbox.

The issue I am facing is that my script starts at the oldest email. This isn't a huge issue, but it causes the script to run much longer than needed.

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

my $OL = Win32::OLE->GetActiveObject('Outlook.Application') || Win32::OLE->new('Outlook.Application', 'Quit');
my $NameSpace = $OL->GetNameSpace("MAPI");
my $Folder = $NameSpace->GetDefaultFolder(olFolderInbox);
my $dir = cwd . "\\";
$dir =~ s/\//\\/g;
my $atch1, $file1, $atch2, $file2;

print ref($Folder->{Items}) . "\n";

foreach my $msg (in $Folder->{Items}){
    #print $msg->{CreationTime} . "\n";
    foreach my $atch (in $msg->{Attachments}){
        if($atch->{FileName} =~ m/.xls$/i){
            if($atch->{FileName} =~ /Name of attachment1/i){
                $atch1 = $atch;
                $file1 = $dir . "file1.xls";
            }
            if($atch->{FileName} =~ /Name of attachment2/i){
                $atch2 = $atch;
                $file2 = $dir . "file2.xls";
            }
       }
   }
}

if($atch1 && $atch2){
    print $file1 . "\n" . $file2 . "\n";
    $atch1->SaveAsFile($file1);
    $atch2->SaveAsFile($file2);
}

The way this is set up right now, since it was oldest to newest, is intended to find the files and then just replace them if it finds a newer one (Though I removed that functionality). Realistically I could just find the newest ones and stop.

I have no idea how to reverse $Folder->{Items}. I don't even understand what it is. When I do ref($Folder->{Items} it says it is a Win32::OLE, which hasn't helped me much since the documentation for Win32::OLE seems to just show it could be any number of things.

Any ideas how I can get to the newer emails first? (Reversing $Folder->{Items}? Something other than Foreach? Dumping $folder->{Items} into another object that can be reversed? Just skip thousands of emails until the date is within the last 2 weeks? (I don't like that one though))

Thanks.

回答1:

You imported the in subroutine from the package Win32::OLE. It is probably some awful "syntactical sugar". And deeply unperlish. I suppose it returns some sort of list from the Win32::OLE object $Folder. So try this:

foreach my $msg (reverse $Folder->{items}->in)

or

foreach my $msg (reverse in($Folder->{items}))

Also, be sure to use strict and use warnings in every script to ensure high quality code. If you can be sure that a modern perl will be used, you can also use v5.10 and enjoy the say function – it behaves like print, but automatically appends a newline to your output.



回答2:

Try something like this

foreach my $msg (reverse @{$Folder->{items}})

don't use "in" in perl