如何将参数从 excel 中的 VBA 脚本作为参数传递给外部可执行文件 (C#)?
How do you pass parameters from a VBA script in excel to an external executable (C#) as arguments?
我在 excel sheet 中有一个嵌入式按钮调用 VBA 脚本。在此脚本中,我正在读取当前目录、解析并使用它来生成值以将 string[] args 传递给外部 C# 可执行文件。我已经经历了多次迭代,它确实调用了可执行文件,但是当 C# .exe 运行时,传递的参数似乎为 null(空)。我可以在其他程序中使用此 C# .exe 并传递参数,但此 VBA 脚本未按预期工作。我也知道它传递了正确的参数数量,因为我没有从 C# .exe 中得到越界异常。我目前正在将所有这些参数转换为字符串以尝试对此进行故障排除,但这很可能是不必要的。 VBA 附上代码:
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
编辑(添加涉及 Solidworks EPDM 库的初步 C# 代码,该代码接受参数,将其转换为列表,并使用该列表提供字符串文件路径以获取 EPDM 库中文件夹的最新版本,然后打开更新的文件的本地副本。):
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.");
}
阅读您的 C# 代码后,我发现您的代码至少需要 6 个参数
此 VBA 代码转义可能出现在您的路径中的任何空格,并将它们作为命令行参数传递:
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
现在您的 C# 代码应该读取这些参数:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("C# Code Reads: "+String.Join(" ", args));
}
}
如果这 2 个过程 return 相同的命令行字符串,那么您在以下几行中可能遇到的任何异常都与 VBA-C# 通信无关
我在 excel sheet 中有一个嵌入式按钮调用 VBA 脚本。在此脚本中,我正在读取当前目录、解析并使用它来生成值以将 string[] args 传递给外部 C# 可执行文件。我已经经历了多次迭代,它确实调用了可执行文件,但是当 C# .exe 运行时,传递的参数似乎为 null(空)。我可以在其他程序中使用此 C# .exe 并传递参数,但此 VBA 脚本未按预期工作。我也知道它传递了正确的参数数量,因为我没有从 C# .exe 中得到越界异常。我目前正在将所有这些参数转换为字符串以尝试对此进行故障排除,但这很可能是不必要的。 VBA 附上代码:
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
编辑(添加涉及 Solidworks EPDM 库的初步 C# 代码,该代码接受参数,将其转换为列表,并使用该列表提供字符串文件路径以获取 EPDM 库中文件夹的最新版本,然后打开更新的文件的本地副本。):
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.");
}
阅读您的 C# 代码后,我发现您的代码至少需要 6 个参数
此 VBA 代码转义可能出现在您的路径中的任何空格,并将它们作为命令行参数传递:
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
现在您的 C# 代码应该读取这些参数:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("C# Code Reads: "+String.Join(" ", args));
}
}
如果这 2 个过程 return 相同的命令行字符串,那么您在以下几行中可能遇到的任何异常都与 VBA-C# 通信无关