Dirk said:
Hi list,
I have the following piece of code to open an existing Project file
and
print out the number of tasks.
the error is "Can't locate object method "item" via package "test"....
could someone maybe post examples on how to interact with the Project
2000 Object Model and Perl.
Well, I have the following snippet of code that I wrote a while back to
do some testing to take an MS Project .mpp and write to an Excel .xls
file and save the Excel file. I can't run it right now to test it
because my copy of Project has expired. It wasn't commented so I don't
know exactly what it did, but I'll add some comments now. The Excel
write is bogus. I stubbed it out, but I'll leave it in here:
#!/usr/bin/perl
$|++;
## Pragmas.
use strict;
use warnings qw( all );
## Use statements.
use Data:
umper;
use My::Utils qw( :Time
isplay );
## The main routine I use in My::Utils is:
##
## sub puts { for (@_) { print "$_\n" } }
use Win32::OLE;
use Win32::OLE::Variant;
use Win32::OLE::NLS qw( :LOCALE
ATE :TIME );
## Get .MPP filename from command line and open as app container.
my $mpp = shift;
my $app = Win32::OLE->GetObject( $mpp ) || die "open $mpp ($!)";
## Create rl hash (don't remember why I named it that now), get
## timestamp (code in My::Utils, but easy to see what it does here
## and create Now() d/t variant that MS expects.
my $rl = {};
my( $yr, $mon, $day, $hr, $min ) = Timestamp();
my $now = Variant( VT_DATE, "$mon/$day/$yr $hr:$min" );
## Run through all the task in the project.
for (1..$app->Tasks->Count()) {
## Grab current task.
my $task = $app->Tasks($_);
## We were only interested in tasks that started with NNX
## where NN was some number and X some letter.
if ($task->{Name} =~ /^(\d\d)(\w)/) {
## Create hash-to index.
my $index = "$1$2";
## If already hashed then rollup the numbers for the
## same indexed task, otherwise, hash it first time.
unless (exists $rl->{$index}) {
## Hash first time hit on index.
$rl->{$index} = {};
my $t = $rl->{$index};
$t->{StartTime} = Variant( VT_DATE, "01/01/2200" );
$t->{FinishTime} = Variant( VT_DATE, "01/01/1900" );
$t->{StartTimes} = [];
$t->{FinishTimes} = [];
$t->{Row} = ord( $2 ) - 64;
$t->{Col} = int $1;
}
## Roll up numbers (keeping times in array for listing
## later.)
my $startTime = Variant( VT_DATE, $task->{Start} );
my $finishTime = Variant( VT_DATE, $task->{Finish} );
my $t = $rl->{$index};
$t->{Name} = $task->{Name};
$t->{StartTime} = $startTime if ($startTime < $t->{StartTime});
$t->{FinishTime} = $finishTime if ($finishTime > $t->{FinishTime});
push( @{$t->{StartTimes}}, $task->{Start} );
push( @{$t->{FinishTimes}}, $task->{Finish} );
$t->{Resources} += $task->{Resources}->Count();
$t->{PercentComplete} = $task->{PercentComplete};
}
}
## Show what we have to stdout (dump results).
for my $index (sort keys %{$rl}) {
## Grab task.
my $task = $rl->{$index};
## Compute various outputs for Excel output.
if ($task->{FinishTime} < $now && $task->{PercentComplete} < 100) {
$task->{Code} = 'Red';
} elsif ($task->{StartTime} <= $now && $task->{PercentComplete} == 0) {
$task->{Code} = 'Yellow';
} elsif ($task->{StartTime} > $now) {
$task->{Code} = 'White';
} elsif ($task->{PercentComplete} == 100) {
$task->{Code} = 'Gray';
} else {
$task->{Code} = 'Green';
}
puts(
"*" x 79,
$task->{Name},
" Start Date...: " . $task->{StartTime}->Date( DATE_SHORTDATE ),
" End Date.....: " . $task->{FinishTime}->Date( DATE_SHORTDATE ),
" Start Dates..:",
);
for (@{$task->{StartTimes}}) { puts( " $_" ) }
puts( " End Dates....: " );
for (@{$task->{FinishTimes}}) { puts( " $_" ) }
puts(
" Resources....: " . $task->{Resources},
" Percentage...: " . $task->{PercentComplete},
" Code.........: " . $task->{Code},
" Row..........: " . $task->{Row},
" Column.......: " . $task->{Col},
""
);
}
## Write rolled up numbers to Excel spreadsheet.
##
## Get Excel spreadsheet name from command line and
## open app container.
my $xls = shift;
## This was commented out because I think it didn't work? Leaving
## it here so you can see it just in case.
##
## $app2 = Win32::OLE->GetActiveObject( 'Excel.Application' ) ||
## Win32::OLE->new( 'Excel.Application', 'Quit' ) || die
"handle $xls ($!)";
my $app2 = Win32::OLE->new( 'Excel.Application' ) || die "excel";
my $book = $app2->Workbooks->Open( $xls ) || die "open $xls ($!)";
my $sheet = $book->ActiveSheet();
## Bugus write. The intention was to run through the tasks in the
## hash I built and write it back out to Excel. I later did this in
## VBScript because my place of employment wanted this done in VB and
## not Perl.
$sheet->Cells( 1, 1 )->{Value} = "Dude!";
## Close Excel down.
$book->Save();
$book->Close();
## I see the .MPP app was never closed... Bad me. Since this is just
## a sample, I'll leave it alone. This worked as I recall.
__END__
Sure. I know I have had haphazard errors with the exact same text you
asked about when trying to run through the Tasks in a Project container.
I got those errors both in Perl and VBScript. I played it off to my
using an eval version of Project but later when I moved my VB code to
production on an IIS server (web front end), I got similar errors. When
I reboot the server it's on, the errors go away. So now it's easy to
play it off to the Windows environment being the load of garbage that it
is...
Honestly, I've seen the same errors before and there seems to
be no logical explanation for it. It just adds more fuel to the raging
fire that I have burning regarding Windows. I absolutely abhor the
environment because it's a load of garbage.
I know you didn't ask for the soapbox, so I'll get off of it. As I
said, I eventually coded all this using VBScript (using .wsf in XML
format -- very nice, I will have to say that for it), and you are
welcome to that code too if you want. In fact, I have it available on
the Web. Speak and I can give you the URL for the VB code if it helps
at all.
Dirk
use Win32::OLE;
use Win32::OLE::Variant;
use strict;
my $app = Win32::OLE->GetObject("test.mpp")
or die "Couldn't open project";
my $project = $app->{Projects}->Item(1);
I don't think that line above is right.
print $project->{Tasks}->Count();
Hope the example helps.
Chris