Ошибка проектирования интерфейса
ИМХО, похоже на ошибку дизайна интерфейса. Дизайнеры должны были также экспортировать метод GroupItemsCount
, который клиентский код мог бы проверить, прежде чем пытаться вызвать GroupItems
.
Ошибки погребения
Мне также не нравится использовать On Error Resume Next
(здесь и далее OERN), и в каждой команде разработчиков стараются убедить коллег в том, чтобы они поставили DLL
, написанный на .NET (либо на C #, либо на VB.NET), который скрывает все эти ошибки, генерируемые этими методами. .
Метод Excel отсутствует в рабочем листе
Итак, в Excel у нас есть коллекция Worksheets для каждой книги, но дизайнеры забывают экспортировать метод Exists. Нужно вызвать [Worksheets]Item
, но если лист не существует, то Item выдает ошибку. Написание собственного метода [Worksheet] Exists в .NET DLL означает, что можно скрыть ошибку и избежать VBA OERN.
SupportsGroupItems
В вашей ситуации я бы порекомендовал изобрести собственную функцию SupportsGroupItems
, которая сама имеет обработчик ошибок, но она будет скрыта от просмотра VBA (поэтому ошибки будут скрыты). Он будет размещен в .NET DLL.
Управление
Я понимаю, что многие менеджеры предпочитают чистое решение VBA, и управление может быть напугано до ада DLL, но если вы считаете, что оно одноразовое, их следует убедить. Это будет всего лишь несколько строк кода.
Развертывание
Следующая проблема для решения DLL - это развертывание, не все развертывание выполняется за одно полное развертывание, поэтому вам нужно написать код, чтобы использовать преимущества библиотеки DLL, если она установлена, и откат на VBA, если она не установлена. Вы можете найти в реестре код для определения установки DLL.
Код взаимодействия COM
Если вы прочитали это далеко и уверены, что хотите, чтобы ваш собственный dll хоронил любые ошибки, тогда вам нужен пример кода. Это сообщение в блоге содержит пример кода. Ключом к тому, чтобы сделать .NET DLL вызываемой из VBA, является пометка ComVisible (true) в Assembly.cs и вкладка сборки свойств проекта, чтобы убедиться, что установлен следующий флажок «Регистрация для взаимодействия COM».
Затем обеспечьте разделение интерфейса и класса. Знаешь что? Позвольте мне написать код здесь. Итак, это пример C #, в котором избегает первичной сборки взаимодействия Word с помощью ключевого слова dynamic
.
using System;
using System.Runtime.InteropServices; // No Word PIA required
namespace SupportsGroupItemsByDynamicLib
{
public interface ISupportsGroupItemsByDynamic
{
bool SupportsGroupItemsByDynamic(object shp);
}
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(ISupportsGroupItemsByDynamic))]
public class CSupportsGroupItemsByDynamic : ISupportsGroupItemsByDynamic
{
bool ISupportsGroupItemsByDynamic.SupportsGroupItemsByDynamic(object shp)
{
bool bSupportsGroupItems = false;
try
{
dynamic dynaShape = shp;
dynamic grpShps = dynaShape.GroupItems;
bSupportsGroupItems = true; // it worked
}
catch (Exception)
{
// bury the error
}
return bSupportsGroupItems;
}
}
}
Вот пример кода VBA, вызывающего .NET Dll
Sub TestByDynamic()
Dim oGroupItemsByDynamic As SupportsGroupItemsByDynamic.CSupportsGroupItemsByDynamic
Set oGroupItemsByDynamic = New SupportsGroupItemsByDynamic.CSupportsGroupItemsByDynamic
Dim shp As Shape
For Each shp In ActiveDocument.Shapes
If oGroupItemsByDynamic.SupportsGroupItemsByDynamic(shp) Then
Debug.Print shp.Name + " is a group! and has " & shp.GroupItems.Count & " items"
Else
Debug.Print shp.Name + " is not a group!"
End If
Next
End Sub
Все вышеперечисленное делает OERN в VBA привлекательным.