views:

279

answers:

3

I want to run a Perl script at the click of a button inside an Excel spreadsheet.

As the button is assigned to execute a VB macro, the macro should effectively execute the program.

As my first ever VB script, this is what I came up with, which throws up an irritating Run-time error '424': Object required error.

Sub RunPerlScript()
    System.Diagnostics.process.Start ("perlscript.pl")
End Sub

How can I get this script to do what I want it to do?

+2  A: 

I didn't write this snippet, but it would seem to be a good answer to your question.

From the article "How to execute a perl script from VBA":

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub RunPerl()
    MsgBox ("Start of macro")
    Dim oWsc As Object
    Set oWsc = CreateObject("WScript.Shell")
    Dim oExec As Object
    Set oExec = oWsc.Exec("perl C:\temp\myperl.pl StartParam")
    While oExec.Status <> 1 ' Wait for process
        Sleep 1000
    Wend
    MsgBox ("STDOUT" + oExec.StdOut.ReadAll())
    MsgBox ("STDERR" + oExec.StdErr.ReadAll())
    Set oWsc = Nothing
    MsgBox ("End of macro")
End Sub

You might need to install ActivePerl first

Colin Pickard
I don't understand what you mean by "through an ActiveX Control". Hopefully my answer does what you want anyway.
Colin Pickard
Looks good, but need to test it. I have Strawberry running on my system... will let you know how it goes.
Zaid
codeape says you can't have objects in VBA macros. I have a hunch he's correct...
Zaid
@Zaid No, he said "You cannot use .NET classes", you were trying to use `System.Diagnostics.process.Start` which is a .NET class. His solution, using `Shell` is simpler, and will work, but you will not be notified when the process has completed, not will you be able to access the output. If you don't need this things then use `Shell`; otherwise use the solution I linked to.
Colin Pickard
@Colin: I'm all ears here. Could you explain what the first line does?
Zaid
heh, that will teach me to copy and paste. the linked article doesn't explain it. Looks like it's declaring an external function, probably the sleep function it uses later on. I might have to go find a copy of Excel to try this out on.
Colin Pickard
The first line declares a Windows API function to be called from the VBA. BTW you are missing `)` at the end of the line. `Sleep` sleeps the current thread for a period specified in milliseconds. It's being used to sleep Excel for 1 second in between each check to see whether the Perl script has finished. I would observe that is quite a long time to lock up Excel and have it not respond to user input - I'd suggest 50 or 100 milliseconds would be fine. +1 anyway for a synchronous solution that lets you access STDOUT. You definitely need to install ActivePerl to run Perl scripts.
MarkJ
@MarkJ corrected, thank you.
Colin Pickard
+3  A: 

You cannot use .NET classes in a VBA macro.

Use the VBA Shell function.

Shell "p:\ath\to\perlscript.pl"

The documentation:

Shell Function

Runs an executable program and returns a Variant (Double) representing the program's task ID if successful, otherwise it returns zero.

Syntax

Shell(pathname[,windowstyle])

The Shell function syntax has these named arguments:

Part Description pathname Required; Variant (String). Name of the program to execute and any required arguments or command-line switches; may include directory or folder and drive. On the Macintosh, you can use the MacID function to specify an application's signature instead of its name. The following example uses the signature for Microsoft Word: Shell MacID("MSWD") windowstyle Optional. Variant (Integer) corresponding to the style of the window in which the program is to be run. If windowstyle is omitted, the program is started minimized with focus. On the Macintosh (System 7.0 or later), windowstyle only determines whether or not the application gets the focus when it is run.

The windowstyle named argument has these values:

Constant Value Description vbHide 0 Window is hidden and focus is passed to the hidden window. The vbHide constant is not applicable on Macintosh platforms. vbNormalFocus 1 Window has focus and is restored to its original size and position. vbMinimizedFocus 2 Window is displayed as an icon with focus. vbMaximizedFocus 3 Window is maximized with focus. vbNormalNoFocus 4 Window is restored to its most recent size and position. The currently active window remains active. vbMinimizedNoFocus 6 Window is displayed as an icon. The currently active window remains active.

codeape
Looks like this is what I am after. Unfortunately, I'll have to install ActivePerl for the script to launch, but `Shell` is definitely the way to go for me...
Zaid
A: 

ActiveState's PDK has PerlCtrl which lets you package a perl script as an ActiveX control. It gathers up your script and all dependencies into a tidy DLL.

daotoad