2

I have an embedded button in an excel sheet that calls a VBA script. In this script I am reading the current directory, parsing, and using that to generate values to pass string[] args to an external C# executable. I have gone through many iterations of this and it does call the executable, but it appears that the parameters being passed are null(empty) when the C# .exe runs. I am able to use this C# .exe in other programs and pass the arguments, but this VBA script isn't working as expected. I also know that it is passing the correct # of parameters as I don't get an out of bounds exception from the C# .exe. I am currently converting all these arguments into strings in an attempt to troubleshoot this, but that most likely isn't necessary. VBA Code attached:

Sub ButtonSG1b7_Click()

Dim FileLocation
Dim ProgramName
Dim length

FileLocation = ActiveWorkbook.FullName
length = Len(FileLocation) - 5
ProgramName = Left(FileLocation, length)
ProgramName = Right(ProgramName, 10)
length = Len(FileLocation) - 15
FileLocation = Left(FileLocation, length)
length = Len(FileLocation) - 2
FileLocation = Right(FileLocation, length)

MsgBox "File Location : " & FileLocation & "    Program Name: " & ProgramName

Dim str0 As String
Dim str1 As String
Dim str2 As String
Dim str3 As String
Dim str4 As String
Dim str5 As String
Dim str6 As String

str0 = "H:\StageGate\Administration\Scripts\GetLatestFileOpen.exe "
str1 = "H:"
str2 = FileLocation
str3 = "Common"
str4 = "\Market Feasibility "
str5 = ProgramName
str6 = ".xlsx"


MsgBox str0 & str1 & str2 & str3 & str4 & str5 & str6
Shell (str0 & str1 & str2 & str3 & str4 & str5 & str6)

End Sub

Edit (adding prelim C# code involving Solidworks EPDM library that takes the arguments, turns it into a list, and uses the list to provide a string filepath to Get Latest on a folder in an EPDM vault and then open the updated local copy of the file.) :

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using EPDM.Interop.epdm;

class Program
{
static void Main(string[] args)
{

    IEdmFolder5 ppoRetParentFolder;
    List<string> filePath = new List<string>(args);

    if (filePath.Any())
    {
        filePath.RemoveAt(0);  //really need to just stop having the script call passing this argument.
    }


    if (Directory.Exists(@"C:\StageGate")) {
        filePath.Insert(0,"C:");
    }
    else if (Directory.Exists(@"H:\StageGate"))
    {
        filePath.Insert(0,"H:");
    }
    else
    {
        MessageBox.Show("StageGate not found.");
    }

    string newFilePath = string.Join("", filePath.ToArray());
    filePath.RemoveAt(5);
    filePath.RemoveAt(4);
    filePath.RemoveAt(3);
    string folderPathstr = string.Join("", filePath.ToArray());
    //MessageBox.Show(folderPathstr);

    //Have to create vault object to work with BatchGet
    EdmVault5 vault = new EdmVault5();
    //Replace My_Vault with your vault name
    vault.LoginAuto("StageGate", 0);
    //Set the 2 here equal to how many folders you want to get (not counting subfolders)
    EdmSelItem[] folderArray = new EdmSelItem[1];
    IEdmBatchGet bg = (IEdmBatchGet)vault.CreateUtility(EdmUtility.EdmUtil_BatchGet);

    //Create and array element for eachf older you want to get, replace folder locations with your folders
    folderArray[0].mlDocID = 0;
    folderArray[0].mlProjID = vault.GetFolderFromPath(folderPathstr).ID;
    //fa[1].mlDocID = 0;
    //fa[1].mlProjID = vault.GetFolderFromPath("C:\\My_Vault\\FolderPath").ID;

    bg.AddSelection(vault, folderArray);
    bg.CreateTree(0, (int)EdmGetCmdFlags.Egcf_IncludeAutoCacheFiles);  //Egcf_IncludeAutoCacheFiles will get latest version of file
    bg.GetFiles(0, null);

    if (File.Exists(newFilePath))
    {

        Process process = Process.Start(newFilePath); //can't just open the file.  Need to create new windows process to have the file open in the default application(process)
        //File.Open(newPath, FileMode.Open);
    }
    else
    {
        MessageBox.Show("File not found.");
    } 
3
  • 1
    Since the second parameter has a space in it, have you tried using ' on either side of the string to specify it as a single argument instead of two (or more depending on spaces)? Commented Apr 24, 2015 at 19:58
  • I need the script to pass 6 arguments as that is what the C# program would expect. Specifying it as a single argument causes the C# exe to throw a System.OutofRange exception. I had to write the script this way as the EPDM vault being used doesn't include a way for me to format my arguments into one string, so I am passing the 6 needed variables. Commented Apr 24, 2015 at 21:21
  • 1
    Regardless, anything with a space in it needs to be escaped. For example, the \Market Feasability will be interpreted as two arguments, not one. Commented Apr 24, 2015 at 21:24

1 Answer 1

3

After reading your C# code, I see your code expects at least 6 arguments

This VBA code escapes any spaces that might appear in your path and passes them as command-line arguments:

Sub ButtonSG1b7_Click()

Dim FileLocation
Dim ProgramName
Dim length

FileLocation = ActiveWorkbook.FullName
length = Len(FileLocation) - 5
ProgramName = Left(FileLocation, length)
ProgramName = Right(ProgramName, 10)
length = Len(FileLocation) - 15
FileLocation = Left(FileLocation, length)
length = Len(FileLocation) - 2
FileLocation = Right(FileLocation, length)

MsgBox "File Location : " & FileLocation & "    Program Name: " & ProgramName

Dim args(0 To 6) As String
Dim cmdln As String, i as Integer

args(0) = "H:\StageGate\Administration\Scripts\GetLatestFileOpen.exe"
args(1) = "H:"
args(2) = FileLocation
args(3) = "Common"
args(4) = "\Market Feasibility "
args(5) = ProgramName
args(6) = ".xlsx"

cmdln=arg(0)
For i = 1 To 6
cmdln=cmdln & " """ & args(i) & """"
Next i
MsgBox "VBA Code Writes: " & cmdln
Shell (cmdln)

End Sub

Now your c# code should read those parameters:

class Program
{
static void Main(string[] args)
{
Console.WriteLine("C# Code Reads: "+String.Join(" ", args));
}
}

If the 2 proccesses return the same command-line string, then any exceptions you may encounter in the following lines are not related to the VBA-C# communications

Sign up to request clarification or add additional context in comments.

3 Comments

This causes it to give me a System.ArgumentOutOfRange error now instead of the null error. I will edit the original post to include the C# code.
that's a huge step forward :-)
If this answer was helpful, please accept the answer or at least vote up

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.