Я работаю над проектом, который строит математические модели для пользователя, а затем может выводить их в различных форматах. Прямо сейчас я поддерживаю вывод в Python, Java, C ++. Это работает, я просто автоматически генерирую код и называю его день.
Однако был сделан новый запрос. Пользователь хочет иметь возможность использовать модели из Excel. Я немного искал и нашел http://richnewman.wordpress.com/2007/04/15/a-beginner%E2%80%99s-guide-to-calling-a-net-library-from-excel/
Так что это хорошее начало, но мне нужно сделать это программно. Модели хранятся в виде объектов в большей программе. Если пользователь выбирает экспорт в виде DLL для Excel, я взял бы некоторый шаблонный код и вставил методы, которые я хотел бы использовать.
Однако, похоже, мне нужно зарегистрировать код для COM Interop. Мой тестовый код создает DLL, я могу использовать его C # и получить доступ к его методам. Но попытка добавить ссылку в Excel 2000 (я знаю, я знаю, корпоративные отстой) VBA не работает. Кажется, что файл TLB не создается, поэтому загружать его нечего.
Если я возьму сгенерированный код, скомпилирую его как автономный, проверив make COM Visible и зарегистрируясь для полей взаимодействия, генерируется TLB, но Excel VBA выдает ошибку автоматизации.
Итак, актуальные вопросы.
1) Как я могу создать во время выполнения DLL, которая будет видимой и зарегистрированной для COM-взаимодействия?
2) Как заставить Excel хорошо играть с ним.
Простой пример кода DLL:
using System;
using System.Runtime.InteropServices;
namespace VSN
{
[ComVisibleAttribute(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class VSNFunctions
{
public VSNFunctions()
{
}
/// <summary>
/// Adds 2 variables together.
/// </summary>
/// <param name=\"v1\">First Param</param>
/// <param name=\"v2\">Second Param</param>
/// <returns>Sum of v1 and v2</returns>
public double Add2(double v1, double v2)
{
return v1 + v2;
}
public double Sub2(double v1, double v2)
{
return v1 - v2;
}
public double Mul2(double v1, double v2)
{
return v1 * v2;
}
public double div2(double v1, double v2)
{
return v1 / v2;
}
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type t)
{
Microsoft.Win32.Registry.ClassesRoot.CreateSubKey("CLSID\\{"+t.GUID.ToString().ToUpper() + "}\\Programmable");
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type t)
{
Microsoft.Win32.Registry.ClassesRoot.DeleteSubKey("CLSID\\{"+t.GUID.ToString().ToUpper() + "}\\Programmable");
}
}
}
Код для сборки DLL программно следует:
CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
String exeName = String.Format(@"{0}\{1}.dll", System.Environment.CurrentDirectory, "VSNTest");
MessageBox.Show(exeName);
parameters.OutputAssembly = exeName;
parameters.CompilerOptions = "/optimize";
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, DLLString);