1

I have the following C# COM Object :

[ComVisible(true), GuidAttribute("FD87D0EA-1D00-4189-801A-987D5F8ABD2C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IRegistration
{
    string RegisterForm(string server, string database, string username, string password, string catalogId, string date, string AxyaContextFile);
    void RegisterFormAcknowledge(string server, string database, string username, string password, long formId, bool isPrinted, string message);
}

When I call the method RegisterFormAcknowledge from Word 200, I get the following compilation exception : function or interface marked as restricted or the function uses an automation type not supported

Here is the Word macro code

    Set printer = New MyCOMObject.Registration
    printer.RegisterFormAcknowledge "test", "test", "test", "test", 12345, False, "CatalogWordTemplate Not Found"

Does anyone has an idea why ? Long type are not supported by VB6 ? The first method RegisterForm is working well.

Kara
  • 6,115
  • 16
  • 50
  • 57
Raphaël
  • 427
  • 5
  • 14
  • public void RegisterFormAcknowledge(string server, string database, string username, string password, long formId, bool isPrinted, string message) – Raphaël Mar 06 '14 at 14:53
  • I just changed the parameter "long formId" into "int formId" and it works. Does anyone knows why ? – Raphaël Mar 06 '14 at 14:54
  • 2
    Yes, `long` is a signed **64-bit** integer, which is not automation-compatible. On the other hand, `int` is a signed **32-bit** integer, which is automation-compatible. – acelent Mar 06 '14 at 14:57
  • Then, if I want to pass a value bigger than int.Max, I should pass it by string, and parse it in the C# code ? – Raphaël Mar 06 '14 at 15:00
  • 1
    It depends. If it's not signed, you can use `uint` and the limit is roughly the double of `Int32.MaxValue`, i.e. `UInt32.MaxValue`. – acelent Mar 06 '14 at 15:04
  • If I want to pass the value 372,036,854,775,807 I must pass it as string ? Or is it another DataType more appropriated ? – Raphaël Mar 06 '14 at 15:10
  • For that value, you can use a `double`, as it can represent faithfully integers up to 53 bits. For larger integers, yes, you'll have to use `string`. Or an array of bytes, but if this is not "hot" code, it's more trouble without reason. – acelent Mar 06 '14 at 15:19
  • I should probably write an answer. – acelent Mar 06 '14 at 15:23

2 Answers2

4
  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

That's a mistake, VB6 and VBA require a dispatch interface. Boilerplate is to use ComInterfaceType.InterfaceIsAutoDual so that the client code can use both early and late-binding. You almost surely need to fix the [ClassInterface] attribute on the class that implements this interface as well, given that you could actually make calls, use ClassInterfaceType.None

Using long as an argument type isn't going to fly, it is not a type supported in VB6. VB1 started life as a 16-bit tool so Integer is 16-bits and Long is 32-bits. No type for 64-bit integrals. Use int if a VB6 Long was intended. If not then you'll need to consider Double, gets you up to 15 digits, or String.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • +1 for picking up on the attribute. I love reading [your answers](http://stackoverflow.com/questions/17615044/early-binding-of-a-c-sharp-com-library-in-vba) –  Mar 06 '14 at 15:16
  • Not to muck the waters up, but 64bit versions of Office do have a `LongLong` type which *is* a 64 bit integer. – RubberDuck Mar 23 '15 at 20:37
2

C#'s long is a signed 64-bit integer, which is not automation-compatible. On the other hand, C#'s int is a signed 32-bit integer, which is automation-compatible.

You asked about large integers, such as 372036854775807.

This one in particular needs 49 bits to represent. C#'s double is a standard double float, which can represent integers that require up to 53 bits.

There's also C#'s decimal, which maps to e.g. VBA's Decimal (inside a VARIANT). If you wish, you can marshal it as e.g. VBA's Currency, a signed 64-bit integer, with the [MarshalAs(UnmanagedType.Currency)] attribute before the argument definition.

For larger values, you should probably be better off using a string. That is, if you can actually deal with them in VBA.

acelent
  • 7,965
  • 21
  • 39