Я изучаю возможность создания надстройки автоматизации для Excel в качестве альтернативы Excel ДНК.Ссылка на статью Адама Тиби (http://www.adamtibi.net/07-2012/using-c-sharp-net-user-defined-functions-udf-in-excel),) Мне удалось заставить библиотеку классов работать с некоторыми проблемами. Самая большая проблема заключается в том, что формула работает, но не отображается в списке формул Excel. Кроме того, яхотел бы иметь intellisense для параметров UDF, а также хотел бы знать, есть ли какой-нибудь способ получения ссылок на ячейки, из которых была отправлена формула.
С точки зрения настройки я выбрал«Сделать сборку COM видимой» и «Зарегистрироваться для взаимодействия COM».
По кодам у меня есть следующие классы.
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace AutoExcel
{
public abstract class UdfBase
{
[ComRegisterFunction]
public static void ComRegisterFunction(Type type)
{
Registry.ClassesRoot.CreateSubKey(
GetClsIdSubKeyName(type, "Programmable"));
// Solves an intermittent issue where Excel
// reports that it cannot find mscoree.dll
// Register the full path to mscoree.dll.
var key = Registry.ClassesRoot.OpenSubKey(GetClsIdSubKeyName(type, "InprocServer32"), true);
if (key == null)
{
return;
}
key.SetValue("", $"{Environment.SystemDirectory}\\mscoree.dll", RegistryValueKind.String);
}
[ComUnregisterFunction]
public static void ComUnregisterFunction(Type type)
{
// Adds the "Programmable" registry key under CLSID
Registry.ClassesRoot.DeleteSubKey(GetClsIdSubKeyName(type, "Programmable"));
}
private static string GetClsIdSubKeyName(Type type, String subKeyName)
{
return $"CLSID\\{{{type.GUID.ToString().ToUpper()}}}\\{subKeyName}";
}
// Hiding these methods from Excel
[ComVisible(false)]
public override string ToString()
{
return base.ToString();
}
[ComVisible(false)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[ComVisible(false)]
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
и
using System.Runtime.InteropServices;
namespace AVstoAddIn
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("3CA06A95-F1A6-4C36-9E56-501BDC7AFDCF")]
public class UdfTest : UdfBase
{
public double AddNumbers(double a, double b)
{
return a + b;
}
public double SubtractNumbers(double a, double b)
{
return a - b;
}
}
}
Когда я пытаюсь взять надстройку Excel VSTO и применить те же методы, я могу заставить ее собрать все то же самое, кроме выбора «Зарегистрироваться для взаимодействия COM».
Моя среда разработки - Windows 10, Excelдля Office 365, 64-разрядная версия Visual Studio Professional 2017 версии 15.9.7. Моя надстройка Excel должна будет поддерживать 2010, 2013, 2016 2019 и Office 365.
Я хотел бы, чтобы функция появилась в списке функций, а также создала категорию, в которой она должна отображаться, но не знаю как.
Любая помощь будет принята с благодарностью.
Edit 1
Я понял, как определить диапазон, из которого вызывается UDF.Интересно, что приложение не сохраняется даже при попытке сохранить его в статическом классе / переменной / свойстве.Я устанавливал приложение в ThisAddIn.cs в методе ThisAddIn_Startup, но приложение было пустым, когда я пытался получить к нему доступ в методе COM Automation.
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace AVstoAddIn
{
public static class ExcelApplication
{
static Excel.Application application;
public static Excel.Application XlApplication
{
get => application ?? (Excel.Application) Marshal.GetActiveObject("Excel.Application");
set { application = Globals.ThisAddIn.Application ?? (Excel.Application) Marshal.GetActiveObject("Excel.Application"); }
}
}
}
В упомянутом выше классе COM Automationссылки могут быть найдены следующим образом:
public class UdfTest : UdfBase
{
public double AddNumbers(double a, double b)
{
Excel.Application excelApp = ExcelApplication.XlApplication;
Excel.Range target = (Excel.Range)excelApp.get_Caller(Type.Missing);
string cellAddress = target.get_Address(Missing.Value, Missing.Value, Excel.XlReferenceStyle.xlA1, Missing.Value, Missing.Value);
return a + b;
}
}
На данный момент у меня следующие вопросы: 1. Как заставить UDF показывать, когда пользователь начинает печатать.2. Как заставить intellisense работать с параметрами UDF.3. Как сохранить приложение.