3

I am getting the following message when trying to return a new object to VBA from my Visual Foxpro COM server. "Run-time error '-2147417851 (80010105)':

Method 'ReturnObject' of object 'Itestclass' failed"

If I remove the "Dim ... As" line the error goes away but then I lose intellisense for the COM object.

This is the VBA code:

Sub Test()

'' Removing the following line gets rid of the error but loses intellisense for the COM object
Dim objTest As testcom.TestClass

Set objTest = CreateObject("TestCOM.TestClass")
Set objNew = objTest.ReturnObject   '' This is the line that causes the error

End Sub

I have created a link to the TestCOM type library in Tools > References

Here is the Visual Foxpro (VFP) code: The COM server is being built as an out of process EXE. If I build it as an inprocess .DLL then the VBA code causes Excel to crash.

DEFINE CLASS ObjectToReturn AS SESSION OLEPUBLIC

ENDDEFINE

DEFINE CLASS TestClass AS SESSION OLEPUBLIC

FUNCTION ReturnObject

    RETURN CREATEOBJECT("ObjectToReturn")

ENDFUNC

ENDDEFINE

I have tried changing the RETURN CREATEOBJECT("ObjectToReturn") to RETURN CREATEOBJECT("CUSTOM") but the problem persists.

Please advise how I can get rid of this error without losing the intellisense for the COM object in VBA. Thanks

Caltor
  • 2,538
  • 1
  • 27
  • 55
  • That's RPC_E_SERVERFAULT, your COM server threw an exception. Why is unguessable. – Hans Passant Oct 11 '11 at 16:26
  • @hans-passant thanks for the extra info. Based on the symptoms I'm 'guessing' it's something to do with early vs late binding and the type library but beyond that I'm lost. – Caltor Oct 11 '11 at 21:25
  • I can't imagine I am the only person who has ever wanted to return an object to VBA from VFP without losing intellisense i.e. early-binding – Caltor Oct 13 '11 at 14:47
  • You just asked the question 10 years too late. – Hans Passant Oct 13 '11 at 14:48
  • haha I guess all that knowledge disappeared in a puff of .net – Caltor Oct 13 '11 at 16:05
  • Can you give me a little more clarification of what the "ObjectToReturn" is... Is it another VFP Class with exposed properties, methods, etc??? – DRapp Oct 14 '11 at 12:56
  • @DRapp ObjectToReturn is another VFP class (defined in the sample code above) with the keyword OLEPUBLIC to make it visible to COM clients. Although for the purpose of illustration the class above is empty, in the real world application it will have a load of public properties and probably no other properties or methods. It will actually be called PurchaseOrderLine and there will be a Collection or array of them. – Caltor Oct 14 '11 at 23:41

1 Answers1

0

I don't know why you are going through such difficulties... This should be able to help you... You can define your class as OlePublic and set some properties on it like the samples at the top. You can set these properties anywhere through the other functions that are not HIDDEN.

If you need to are trying to get at certain elements OF some other "object", try creating an instance of the object and stick it into a property on the OlePublic class... see my method

DoSomethingElse

which does a simple scatter NAME call to the "SomeObject" property of the class. Even though you are not explicitly returning it, it should be visible from within your creation of it from VB...

DEFINE CLASS VFPClassForVB as Session  OLEPublic
  cTmpFiles  = ""
  cCOMUser  = ""
  SomeObject  = ""

  FUNCTION Init()
    */ Who is user...  always ignore the machine....
    This.cCOMUser  = SUBSTR( SYS(0), AT( "#", SYS(0)) +1 )
    This.cTmpFiles  = "somepath\"

    */ Unattended mode... any "MODAL" type dialog will throw error / exception
    SYS(2335, 0 )

    */ ALWAYS HAVE EXCLUSIVE OFF FOR COM!!!
    SET EXCLUSIVE OFF

    */ ALWAYS HIDE DELETED RECORDS!!!
    SET DELETED ON
  ENDFUNC 

  */ Error handler at the CLASS level will always be invoked
  */ instead of explicit ON ERROR or TRY/CATCH handlers...
  FUNCTION xError(nError, cMethod, nLine)
    lcMsg  = "User: " + SYS(0) + "  Tmp:" + SYS(2023);
        + "  Method: " + cMethod + "  Error: " + STR( nError,5);
        + "  Line: " + STR( nLine, 6 )
    STRTOFILE( lcMsg, This.cTmpFiles + "COMLog.txt" )

    */ NOW, throw the COM Error...
    COMReturnError( cMethod + '  Error:' + str(nError,5);
        + '  Line:' + str(nline,6);
        + '  Msg:' + message(), _VFP.ServerName )
  RETURN 


  HIDDEN FUNCTION SomeOtherFunction( lcWhat String,;
                     lnThing as Integer ) as String

    */ Do something
    RETURN 1
  ENDFUNC 

  */ Another completely visible function direct form VB
  FUNCTION DoSomethingElse( SomeParameter as String ) as String
    USE SomeTable
    */ Now, this object should be visible as a direct property in VB
    SCATTER MEMO NAME This.SomeObject
  ENDFUNC 

ENDDEFINE 

Your VB side, even from your sample...

Sub Test()
Set objTest = CreateObject("MySampleProject.VFPClassForVB")
objTest.DoSomethingElse( "I dont care" )
dim Something as objTest.SomeObject.ColumnFromTable  
End Sub

You can create as many OlePublic classes in your in-code class libraries that you want to expose and just create those instances as needed. Let me know if this helps you get closer and we'll try to keep working it out.

I've tried all sorts of samples, but looking at what you have of the object where both are VFP OleObject entries, each is exposed, and can be created individually. You don't need to create one to create the other.

Is there some reason SPECIFIC you are trying to create one object from another? You can have one object expose a bunch of methods and properties to perform whatever you need from VFP.

If you want to have multiple object classes exposed, and under a central control, you can always create your primary object for communication and have IT create an instance of each "other" class on it. Then, expose methods on your main class to handle the communications between them to act out whatever it is you need.

DRapp
  • 47,638
  • 12
  • 72
  • 142
  • thanks for the advice but I think you might slightly misunderstand the problem. I am unable to get any objects to pass between the VFP COM server and the VBA (MS Excel 2007) program. I have now tried creating the object within VFP or VBA but I can't pass it either direction :( – Caltor Oct 16 '11 at 22:56
  • I've expanded answer and added questions on your needs. – DRapp Oct 17 '11 at 02:47
  • I am writing the VFP COM server but a third party client will be writing the VBA code. I am therefore trying to make it as simple as possible for him to create the 'child' objects which is the specific reason I am trting to create one object from another. I see from your code that you can create a public property to hold the new object that will be accessible from the VBA client; but how about multiple objects? As the main class 'TestClass' will have multiple children I actually need the public property to be a collection but in this scenario the VBA client is unable to pass the object. – Caltor Oct 17 '11 at 09:09
  • You can't explicitly return that type of object. I would just create one master object that is exposed, then from that, have all your functions within it ACT ON/AGAINST the child object that IT creates. This way, you can still offer whatever functionality OF the child object, but called from the primary OlePublic that is created. – DRapp Oct 17 '11 at 11:04
  • You could create a collection in the VFP code to hold the set of objects you're creating. That collection can be accessed through a property of the VFP object you're actually creating in the VBA code. – Tamar E. Granor Oct 17 '11 at 20:40
  • I have found that this is definitely a generic problem with returning COM objects when using early-binding. I have rewritten the client code in VFP using early-binding and I get the same error. The workarounds I am currently working on are based around either creating and populating the COM object in the client code before passing it to the COM server or creating the COM objects in the COM server and then accessing them through an array or collection as per the suggestion from Tamar. – Caltor Oct 21 '11 at 09:47