1
votes

Inside the AutoExec macro of Word, I would like to handle some features. For this, I need a Id, given by a command line parameter while starting WinWord.exe.

Example: "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /MyParam:5

I need this 5

How can I get this?

1
I found that with one simple google too ;-} - freeflow
@Tim Williams: Thanks a lot. This is the answer. - Tahtu

1 Answers

0
votes

VBA, natively, doesn't provide this kind of information. It's necessary to leverage the Windows API to get the command line arguments.

The following code demonstrates how to use the GetCommandLineA and lstrcpynA APIs to extract get the full command line. This is then parsed to pick up each individual argument.

Declare Function GetCommandLineA Lib "kernel32" () As Long
Declare Function lstrcpynA Lib "kernel32" ( _
   ByVal pDestination As String, ByVal pSource As Long, _
   ByVal iMaxLength As Integer) As Long

Function GetCmdLineInfo() As String

   ' Pointer to the command line
   ' Which will be passed as pSource to lstrcpynA
   Dim ptrCmdLine As Long
   ' Will hold the command line after the call to lstrcpynA
   ' Pointer to the destination; before being passed...
   ' must first be initialized with enough characters to hold that string
   Dim strCmdLine As String

   ' Get the pointer to the command line string
   ptrCmdLine = GetCommandLineA

   ' Fill the string with enough zeros to make sure there are enough
   ' characters available for the command string (which will replace the content).
   ' 300 is an arbitrary number, more might be necessary.
   strCmdLine = String$(300, vbNullChar)

   ' Copy from the pointer to a VBA-style string
   lstrcpynA strCmdLine, pCmdLine, Len(strCmdLine)

   ' Remove the extra vbNullChar characters at the end of the command line
   strCmdLine = left(strCmdLine, InStr(1, strCmdLine, _
      vbNullChar) - 1)

   GetCmdLineInfo = strCmdLine
End Function

Function GetCmdLineArgs(strCmdLine As String) As String
    Dim lExePos As Long, lSpaceAfterExe As Long
    Dim strArgString As String

    'Get the end of the path to the exe file...
    lExePos = InStr(LCase(strCmdLine), ".exe")
    strArgString = Mid(strCmdLine, lExePos + 4)

    'Move beyond any quote characters and spaces after '.exe'
    'The first argument may be the path to a file or
    'an argument beginning with a forward slash, so get it all.
    lSpaceAfterExe = InStr(strArgString, " ")
    If lSpaceAfterExe > 0 Then
        strArgString = Mid(strArgString, lSpaceAfterExe + 1)
    Else
        strArgString = "No args"
    End If
    GetCmdLineArgs = Trim(strArgString)
End Function

Sub TestCmdLineargs()
    Dim strCmdLine As String
    Dim strCmdArgs

    strCmdLine = GetCmdLineInfo
    strCmdArgs = GetCmdLineArgs(strCmdLine)
    'Debug.Print Len(strCmdLine), strCmdLine, strCmdArgs

   'Extract the individual args to an array
    Dim strArgChar As String
    Dim lFirstArgPos As Long, lNextArgPos As Long
    Dim argsList() As String
    Dim strArgString As String
    Dim argsCounter As Long

    strArgChar = " /"
    argsCounter = 0

    lFirstArgPos = InStr(strCmdArgs, strArgChar)
    'If the first argument is a file path, store that in the array
    If left(strCmdArgs, 1) <> "/" Then
        ReDim Preserve argsList(argsCounter)
        strArgString = Trim(left(strCmdArgs, lFirstArgPos - 2))
        argsList(argsCounter) = strArgString
        argsCounter = argsCounter + 1
    End If

    'Get the rest of the args, that start with a /
    Do While lFirstArgPos > 0
        ReDim Preserve argsList(argsCounter)
        strArgString = Mid(strCmdArgs, lFirstArgPos + 1)
        lNextArgPos = InStr(lFirstArgPos + 2, strCmdArgs, strArgChar)

        'If lNextArgPos is not greater than 0, then there are no more args
        If lNextArgPos <= 0 Then
            argsList(argsCounter) = strArgString
            Exit Do
        Else
            strArgString = Mid(strCmdArgs, lFirstArgPos + 1, lNextArgPos - lFirstArgPos)
            argsList(argsCounter) = strArgString
            argsCounter = argsCounter + 1
            lFirstArgPos = lNextArgPos
        End If
    Loop

    Dim i As Long

    For i = LBound(argsList) To UBound(argsList)
        Debug.Print argsList(i)
    Next
End Sub