I don't really think you can do this. You would need to access
$workbook->VBProject->VBComponents
but then the typical way to pass create a macro on the fly is to call the VBComponents collection's AddFile, AddFromTemplate or Import method which all require paths to files that Excel will read itself. It's not like it's an extension of Perl and will accept an open file stream as well.
Of course, you can always write the machinery to take a in-script string, dump it out to a temporary file and send that file name to Excel. However, since Microsoft has greatly stepped up its paranoia, I wonder how many security hurdles you will need to clear to get Excel to run a macro from a temp file directory.
After you get this loaded it's simply a matter of $xl->run( 'Bookname!Macro' ). But I think the protections against attacks are bound to hinder your doing this.
Update:
Yeah, I just tried something along these lines and got "Programmatic access to Visual Basic Project is not trusted". Like I said, expect a lot of hurdles, if not complete failure.
However, you can work around that with this advice.
Actually, it turns out I was wrong, the code below allows you to add behavior to a code module.
my $prj = $wb->VBProject;
my $mod = $prj->VBComponents->Item( 'ThisWorkbook' )->CodeModule;
$mod->addFromString( <<"END_VB" );
Public Sub Doodad
MsgBox( "I am Doodad! Hear me roar!" )
End Sub
END_VB
However when I did this:
$excel->Run( $wb->Name . '!Doodad' );
I got this:
Cannot run the macro 'Book1!Doodad'. The macro may not be available in this
workbook or all macros may be disabled.
$excel->Run('Macro1')without specifying Book1