c# 可枚举类 - 与 VBA 兼容

标签 c# .net c#-to-vb.net

谁能指导我如何编写 C# 可枚举类的代码,以便 Excel VBA 中的“for each”结构正常工作?我用一个名为 People 的测试类对此进行了尝试,该类实现了 IEnumerable 并包含一个 Person 对象数组。 “foreach”构造在 C# 中运行良好,但在 VBA 中我只能以老式方式循环。

这段 VBA 代码工作得很好:

Dim P As Person
Dim PP As New People

For i = 0 To PP.Count - 1
    Set P = PP(i)
    Debug.Print P.firstName + " " + P.lastName
Next i

但这在运行时失败了(“对象不支持这个属性或方法”):

For Each P In PP
    Debug.Print P.firstName + " " + P.lastName
Next P

这是 C# 代码(已编译的 COM 在 VS 2008 中可见,用于 Excel VBA - Office 2010):

using System;
using System.Collections;
using System.Runtime.InteropServices;

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }
    public string firstName;
    public string lastName;
}

public class People : IEnumerable
{
    private Person[] _people;                           // array of people
    public Int32 Count() { return _people.Length; }     // method to return array size

    // indexer method to enable People[i] construct, or in VBA: People(i)
    public Person this[Int32 PersonNo] { get { return _people[PersonNo]; } }

    // constructor - hardcode to initialize w 3 people (for testing)
    public People()
    {
        _people = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
            new Person("Sue", "Rabon"),
        };
    }

    // test method just to make sure the c# foreach construct works ok
    public void Test() 
    { 
        foreach (Person P in this) System.Diagnostics.Debug.WriteLine(P.firstName + " " + P.lastName); 
    }

    //implementation of basic GetEnumerator
    IEnumerator IEnumerable.GetEnumerator()
    {
        return (IEnumerator)GetEnumerator();
    }

    //implementation of People GetEnumerator
    public PeopleEnum GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

// People Enumerator class definition
public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    int position = -1;

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public Person Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}

最佳答案

尝试将 [DispId(-4)] 添加到您的 GetEnumerator() 方法中。这将其标记为 DISPID_NEWENUM 成员。为了让 VBA 使用 For Each 处理集合,它需要实现 _newEnum通过 COM。

这可以通过实现枚举器并为其赋予适当的 DispId 来完成。尽管有 other mechanisms,这通常是通过实现具有此指定的自定义接口(interface)来完成的。可用。

关于c# 可枚举类 - 与 VBA 兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4796613/

相关文章:

c# - 等距,仅在屏幕图 block 上绘制

c# - 使用 Ninject 2 将参数传递给 WCF ServiceHost 类型

c# - 使用 lambda 表达式替换正则表达式匹配

c# - 在带参数的函数上使用 PInvoke 时出现 AccessViolationException

.net - ProvidersHelper.InstantiateProviders 的替代方案

c# - 从 C# 到 VB 中的 where 继承

.net - 什么是 dnu 包装?

c# - 为什么加载System.Data 4.0.99.99会成功?

.net - Vb.NET 索引属性

vb.net - 需要将 C# 转换为 VB.NET