views:

329

answers:

1

I am having an issue using a .NET/ComVisible assembly in Excel/VBA. I defined several parameters as "object" in .NET so they will be translated to Variant in VBA since optional parameters in VBA need to use Variant types.

The problem is when I try to use the object in Excel/VBA, I get a "Run-time error '424': Object required". I think I am missing attributes in the C# interface that would add a 'propput' method instead of the 'propputref' method that would allow values in Variants, but I haven't found any answers on the Internet just similar questions. I see System.Reflection.BindingFlags, but that only seems to work for compile-time and runtime code and not for interface definition.

The underlying data type is double and I need it to be null or a double through COM/VBA. I have no issues with the string parameters, just the variant/double.

Here is the C# interface:

[ComVisible(true)]
[Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ISampleParameters
{
    object GrossObservedValue { get; set; }
    string TableName { get; set; }
    // Rest of parameters removed for simplicity
}

Here is the C# object:

[ComVisible(true)]
[Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
[ClassInterface(ClassInterfaceType.None)]
public class SampleParameters : ISampleParameters
{
    private double? grossObservedValue;
    private string tableName;

    public object GrossObservedValue
    {
        get
        {
            return grossObservedValue;
        }
        set
        {
            try
            {
                if (value == null)
                    grossObservedValue = null;
                else
                    grossObservedValue = Convert.ToDouble(value);
            }
            catch
            {
                throw;
            }
        }
    }
}

Here is the VBA usage:

Dim Parameters As New SampleParameters
Parameters.GrossObservedValue = 1.23
' Causes: Run-time error '424': Object required

Here is the Type Library IDL from OleView:

[
  odl,
  uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX),
  version(1.0),
  dual,
  oleautomation,
  custom(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, TempNamespace.ISampleParameters)    
]
interface ISampleParameters : IDispatch {
    [id(0x60020000), propget]
    HRESULT GrossObservedValue([out, retval] VARIANT* pRetVal);
    [id(0x60020000), propputref]
    HRESULT GrossObservedValue([in] VARIANT pRetVal);
    [id(0x60020001), propget]
    HRESULT TableName([out, retval] BSTR* pRetVal);
    [id(0x60020001), propput]
    HRESULT TableName([in] BSTR pRetVal);
};

It seems the only solution is to manually generate the IDL and then import it back into .NET as in this thread using VB.NET with VB6. Is that the only solution? This article on The Essentials for Using COM in Managed Code was also very good, but did not cover defining interfaces in .NET/C#.

A: 

This error is often caused by incorrect registration of COM component.

What method of registration have you used for your component?

elder_george
I used 'regasm /tlb' to register. However since the assembly output and resulting TLB has 'propputref' instead of 'propput' in the GrossObservedValue setter with the VARIANT parameters, I believe it is most likely compile-time not registration related.
Ryan
propputref could be used because passing 16-byte variant is suboptimal. To clarify: does access to property TableName from VB works correctly?To check, whether your hypothesis is right, you can unregister TLB, build your own TLB from correct IDL and register it manually. If this will solve your problem, then maybe you could use this TLB further, passing it with your assembly e.g. as embedded resource.
elder_george