Как предоставить класс C# модулю VBA в надстройке уровня документа?
это гипотетическая ситуация.
Я хотел бы узнать, можно ли предоставить класс C# VBA в надстройке уровня документа.
вот SSCCE:
в VS PRO 2012 я начал новый проект,Выбранный Офис - > Книга Excel 2010. (убедитесь, что вы выбрали .Net framework ver 4)
я добавил DateTimePicker
управление Лист1.
Я могу установить/получить .Value
собственность от DateTimePicker
управление в решении C# без проблем.
во время отладки: в VBA .Value
недвижимость не разоблачили. (пробовал .OLEFormat.Object.Value
)
не все свойства могут быть подвержены VBA, потому что элемент управления ActiveX DateTimePicker
обернут MSForms
таким образом, Excel распознает его (совместимость).
I необходимо иметь возможность захватить фактическое значение обернутого элемента управления из VBA, но я не уверен, как это сделать (возможно это или нет)...
Я знаю, что сам элемент управления поддерживает мероприятия, но это не тот путь, который я хочу взять. Я хочу иметь возможность захватить статическое / текущее значение с элемента управления.
это то, что я хотел бы иметь возможность сделать:
добавить класс в мой C# решение
разоблачить его, поэтому он воссоздается из VBA, как
Dim obj as new MyExposedClass
- есть
MyExposedClass
хранить ссылку наDateTimePicker
как он отображается в C# (все свойства доступны) тогда я могу определить функцию
GetValue(string controlName)
который возвращает значение из C# POV
я нашел данное решение + (этот один) это, кажется, работает с приложения-уровень надстройка, но она не работает с документ-уровень надстройки.
когда я отлаживаю свое решение и открываю браузер объектов VBA, я вижу, что ссылки автоматически добавляются в Microsoft Visual Studio 2008 Tools for Office Execution Engine 9.0 Type Library
но я не думаю, что могу добавить к этому дополнительный класс...
когда я открываю ссылки в VBE, в проект не добавляются дополнительные ссылки, но в / debug папка моего решения есть ExcelWorkbook1.dll
так как же это, что даже прилагается к решению?
Итак, мой вопрос:
как я могу предоставить класс в надстройке уровня документа для Excel с помощью C# для расширения диапазона свойств, доступных по умолчанию в элементах управления .Net?
обновление:
это самое близкое, что я получил до сих пор, но это позволяет вам выставлять только хост-элемент, такой как рабочий лист, книга, Диаграмма и т. д. Это позволяет вызовите методы, хотя я собираюсь исследовать это дальше и вернуться с некоторой обратной связью
вызывающий код в настройках уровня документа из VBA
как: предоставить код VBA в проекте Visual C#
Пошаговое Руководство: вызов кода из VBA в проекте Visual C#
1 ответов
вам нужно будет создать открытый интерфейс, чтобы предоставить класс VBA, это работает для меня как надстройка уровня документа.
-
откройте новую книгу Excel и скопируйте следующее В модуль
Sub CallVSTOMethod() Dim dt As Date Dim VSTOSheet1 As DocLevelAddin.Sheet1 Set VSTOSheet1 = GetManagedClass(Sheet1) dt = VSTOSheet1.GetDatePickerVal End Sub
сохранить Excel как " TestProj.файл xlsm" и "закрыть".
- откройте VS, новый проект, книгу Excel 20xx и назовите проект "DocLevelAddin"
- в Мастере выберите Копировать существующий документ и выберите недавно созданная книга " TestProj.файл xlsm"
-
в Excel Sheet1 добавьте элемент управления DateTimePicker на лист из WIHIN VS, дважды щелкните, чтобы создать событие ValueChanged и обновить код в Sheet1.cs читать
private DateTime dtVal; private void dateTimePicker1_ValueChanged(object sender, EventArgs e) { dtVal = dateTimePicker1.Value; }
-
все еще в Sheet1.cs, добавьте открытый метод для возврата dtVal
public DateTime GetDatePickerVal() { return dtVal; }
-
также добавьте следующее В Лист1.cs
protected override object GetAutomationObject() { return this; }
-
над открытым частичным классом Sheet1 в Лист1.cs добавьте следующее
[System.Runtime.InteropServices.ComVisible(true)] [System.Runtime.InteropServices.ClassInterface( System.Runtime.InteropServices.ClassInterfaceType.None)]
теперь вам нужно создать открытый интерфейс для метода. В Лист1.cs щелкните правой кнопкой мыши выберите рефакторинг, извлеките интерфейс и проверьте общедоступный метод GetDatePickerVal
-
сделать интерфейс общедоступным и COM видимым
[System.Runtime.InteropServices.ComVisible(true)] public interface ISheet1 { DateTime GetDatePickerVal(); }
дважды щелкните Лист1.cs, поэтому лист Excel виден. Выберите любую ячейку, чтобы открыть окно Свойства и их изменение ReferenceAssemblyFromVbaProject = true
в Excel вам может потребоваться перейти к настройкам Центра доверия и добавить папку VS Solution и вложенные папки в качестве надежного местоположения
запустите проект, и код в модуле Excel вернет dateTimepicker через открытый GetDatePickerVal метод.
Лист1.cs:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
namespace DocLevelAddin
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(
System.Runtime.InteropServices.ClassInterfaceType.None)]
public partial class Sheet1 : DocLevelAddin.ISheet1
{
private void Sheet1_Startup(object sender, System.EventArgs e)
{
}
private void Sheet1_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.dateTimePicker1.ValueChanged += new System.EventHandler(this.dateTimePicker1_ValueChanged);
this.Startup += new System.EventHandler(this.Sheet1_Startup);
this.Shutdown += new System.EventHandler(this.Sheet1_Shutdown);
}
#endregion
private DateTime dtVal;
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
dtVal = dateTimePicker1.Value;
}
public DateTime GetDatePickerVal()
{
return dtVal;
}
protected override object GetAutomationObject()
{
return this;
}
}
}
ISheet1.cs:
using System;
namespace DocLevelAddin
{
[System.Runtime.InteropServices.ComVisible(true)]
public interface ISheet1
{
DateTime GetDatePickerVal();
}
}