Co-ordinate conversion - vb6

I am making a simple coordinate converter with the help of eye4software. Following link provides the required Visual Basic 6 codes for the converter.
http://www.eye4software.com/products/gpstoolkit/source/vb/datumtransformation/
I have followed said process according to the given details in the link.
Private Sub Form1_Load()
Private objProjection As GpsProjection
Private objDatumSrc As GpsDatumParameters
Private objDatumDst As GpsDatumParameters
Set objProjection = CreateObject("Eye4Software.GpsProjection")
Set objDatumSrc = CreateObject("Eye4Software.GpsDatumParameters")
Set objDatumDst = CreateObject("Eye4Software.GpsDatumParameters")
End Sub
Option Explicit
Private objProjection As GpsProjection
Private objDatumSrc As GpsDatumParameters
Private objDatumDst As GpsDatumParameters
Private Sub CommandTranslate_Click()
' Set Source Datum ( WGS84 )
' The ID for WGS84 is 4326, see 'http://www.eye4software.com/resources/datums' for a full list of supported datums
' To convert from another datum, just change the code below (EPSG code)
objDatumSrc.LoadFromId (4326)
' Set Destination Datum ( NAD27 )
' The ID for NAD27 is 4267, see 'http://www.eye4software.com/resources/datums' for a full list of supported datums
' To convert to another datum, just change the code below (EPSG code)
objDatumDst.LoadFromId (4267)
' Set Source coordinates
objProjection.Latitude = CDbl(Textlat1.Text)
objProjection.Longitude = CDbl(Textlon1.Text)
' Perform the datum transformation
objProjection.TransformDatum objDatumSrc, objDatumDst
' Display the result
Textlat2.Text = objProjection.Latitude
Textlon2.Text = objProjection.Longitude
End Sub
But i am getting a run time error for this code (objDatumSrc.LoadFromId (4326)) saying object required. Since i'm a beginner i was unable to solve this. please help me.

You have two objDatumSrc variables.
One is a private variable inside Form_Load - you are initialising that one.
The other one is a module-level one and you are not initialising that one.
Delete the Private variable declarations inside Form_Load

To me, it looks like you aren't understanding scope, but the real problem is a non-instantiated variable. Your declaration of objDatumSrc in the form load event will not be able to be seen in the rest of the form because The variables you are declaring outside of a method are not being instantiated.
Replace your current code with this...
Option Explicit
Private objProjection As New GpsProjection
Private objDatumSrc As New GpsDatumParameters
Private objDatumDst As New GpsDatumParameters
Private Sub CommandTranslate_Click()
' Set Source Datum ( WGS84 )
' The ID for WGS84 is 4326, see 'http://www.eye4software.com/resources/datums' for a full list of supported datums
' To convert from another datum, just change the code below (EPSG code)
objDatumSrc.LoadFromId (4326)
' Set Destination Datum ( NAD27 )
' The ID for NAD27 is 4267, see 'http://www.eye4software.com/resources/datums' for a full list of supported datums
' To convert to another datum, just change the code below (EPSG code)
objDatumDst.LoadFromId (4267)
' Set Source coordinates
objProjection.Latitude = CDbl(Textlat1.Text)
objProjection.Longitude = CDbl(Textlon1.Text)
' Perform the datum transformation
objProjection.TransformDatum objDatumSrc, objDatumDst
' Display the result
Textlat2.Text = objProjection.Latitude
Textlon2.Text = objProjection.Longitude
End Sub

The code here so obviously shouldn't compile, it is obvious that you are not showing your real code. For instance, what is your error handling? If you have done something like On Error Resume Next, then if the following lines raise errors, then the errors won't be reported.
Set objProjection = CreateObject("Eye4Software.GpsProjection")
Set objDatumSrc = CreateObject("Eye4Software.GpsDatumParameters")
Set objDatumDst = CreateObject("Eye4Software.GpsDatumParameters")
Since they would be set to Nothing, if you tried to execute methods and properties on objProjection, objDatumSrc, and objDatumDst, they would raise the error "object required".
And since this is likely not the code you have tried to run, can you verify that all the Program Ids e.g. "Eye4Software.GpsProject" are correct? In fact - have you registered these components? And why can't you instantiate these objects using the slightly cleaner notation, e.g.
Set objProjection = New Eye4Software.GpsProjection
?

Try either:
Call objDatumSrc.LoadFromId(4326)
or
objDatumSrc.LoadFromId 4326
VB gets a little funky doing method calls with parameters. If it's not in the expected format, some results may vary.

Related

How to fix an import from AD

I'm not a developer, i'm trying to understand why my IT ticketing software is unable to import people from the windows AD. It was working ok a month ago. I have no access to the windows AD but they said "no changes or upgrades" recently made
I have isolated problem is related to the AD "manager" field, meaning, my ticketing software has an option not to try to import the manager field(or whatever it is) and it will work fine
Here is the code that performs the import
Option Explicit On ' Change to Off instead of On to disable the need to declare variables with Dim. (NOT recommended)
Option Strict Off ' Change to Off instead of On to cast variables automatically. (NOT recommended)
Option Compare Binary ' Change to Text instead of Binary to let string "A" equal to "a".
Imports System
Imports System.Data
Imports System.Collections
This is a transformation script class. Please take notice of the following rules:
' - You are not allowed to change the name of the class (must be "TransformationScript")
' - You are not allowed to change the namespace the class is in (the class "TransformationScript" must not be in a namespace).
' - You are not allowed to change the name of the method (must be "Transform")
' - You are not allowed to change the parameters of the "Transform" method
' This method is called by the transformation logic. The dt parameter contains the data table with the data to transform.
' Any additional arguments are passed in the additionalArguments list.
Public Class TransformationScript
Public Sub Transform (ByVal dt As System.Data.DataTable, ByVal additionalArguments As SortedList)
For Each row As DataRow In dt.Rows
Dim strValue As String
If Not String.IsNullorEmpty(row.Item("manager").ToString)
strValue = row.Item("manager").ToString
Dim strArray() As String
Dim strManager As String
Dim strManagerDisplayName As String
split the AD manager object on "OU" and the results to array
strArray = strValue.Split("OU")
get string array position "0" that contains the manager name
strManager = strArray(0)
clean up the Manager display and remove the "CN=" and "\" and the last ","
strManagerDisplayName = strManager.Replace("CN=","")
strManagerDisplayName = strManagerDisplayName.Replace("\","")
strManagerDisplayName = strManagerDisplayName.Remove(strManagerDisplayName.Length-1)
return the Manager Display Name
row.Item("manager") = strManagerDisplayName
End If
Next
End Sub
End Class
I want to understand what the code is trying to do and possible root causes of what could be causing the issue
Thanks in advance

How to create description object model at runtime in uft/qtp?

thank you for taking a look on this question. Just wondering if there is a best approach to create description object model at runtime. My code fails
Object doesn't support this property or method: 'Browser(...).page(...).WebButton'
FunctionCreateDescObjAt_RunTime(StrBrowserNme,StrBrwsrTitle,StrObject,StrPgeNme,StrPgtitle,StrObjectName,index)`
'create a description object for Browser & Page`
Set WebBrwsrDesc= Description.Create
WebBrwsrDesc("application version").value= "Internet Explorer.*"
If StrBrowser<>"" Then
WebBrwsrDesc("name").value=StrBrowserNme
WebBrwsrDesc("title").value=StrBrwsrTitle
End If
Set WebPageDesc= Description.Create
WebPageDesc("name").value=StrPgeNme
WebPageDesc("title").value=StrPgtitle
' 'Based on the type of object, execute the condition`
Select Case StrObject`
Case "WebButton"
Set WebBtnDes= Description.Create
WebBtnDes("html tag").value="INPUT"
WebBtnDes("name").value=StrObjectName
WebBtnDes("micclass").value="button"
WebBtnDes("index").value=index
'Browser("title:=.*","name:=.*").page("title:=.*","name:=.*").WebButton(WebBtnDes).fnWebButtonClick
Browser(WebBrwsrDesc).page(WebPageDesc).WebButton(WebBtnDes).click
end select
End Function
I am making a call from action
CreateDescObjAt_RunTime "Account Login","Your Store", "WebButton", "", "Account Login", "Login", "" And this is failing. However if I un comment this line & comment problem line, it works
Browser("title:=.*","name:=.*").page("title:=.*","name:=.*").WebButton(WebBtnDes).fnWebButtonClick
Could you please help me with the right approach? thanks
If you want to set a generic browser and page you can simply use a statement similar to the line you have commented:
Dim objPage : Set objPage = Browser("class:=browser").Page("title:=.*")
The line above will create a page object that you can work with.
Check the parameters being passed to your function to make sure you are correctly identifying your browser and page.
For the part of your actual object, which you want to create at runtime, you need to create a Description object, then look for the ChildObjects of your main object (in this case, your page) and store it to a collection. After that you can check whether or not your object is found. So your Select Case part would be something like this:
Select Case StrObject
Case "WebButton"
' This is just a description of your object, not your actual object
Dim descButton : Set descButton = Description.Create
descButton("html tag").value="INPUT"
descButton("name").value=StrObjectName
descButton("micclass").value="button"
descButton("index").value=index
' In the following statement you are looking for all child objects
' of your page that matches with your description, and storing it
' into the collButton collection
Dim collButton : Set collButton = Browser("class:=browser").Page("title:=.*").ChildObjects(descButton)
If collButton.count > 0 Then ' Now you are checking if any object was found
' There are many ways to get the button object that you want.
' Here I'm just assuming you want the first one, but you could iterate
' into the collection to make sure you have the right one
Dim objButton : Set objButton = collButton(0) ' I'm getting the first item, which is in index 0 of your collection
objButton(0).Click ' This object already have the whole Browser().Page().WebButton() identified, so no need to use it
Else
MsgBox "No WebButton found. Please check your Description object"
End If
' Your other cases...
End Select
MicClass of a Webbutton Can't be button. It should be WebButton
' You are using following
WebBtnDes("micclass").value="button"
It Should be : WebButton
'Anyway Describing Description Object
Set ObjButton=Description.Create
ObjButton("MiCClass").value="WebButton"
ObjButton("name").value=strButtonName
ObjButton("htmlid").value=strHtmlId
Set ObjButton= Browser().page().ChildObject(ObjButton)

Run-time error '91' when adding data to a record set

I want to insert some information into a database in VB6, but I get runtime error '91'.
My code:
Private sub btn_click()
Fname = txtFname.text
Adodc1.Recordset.AddNew
Adodc1.Recordset.Fields("Fname") = Fname
Adodc1.Recordset.Update
End sub
The debuger shows error on: Adodc.Recordset.AddNew
You haven't posted the rest of the code as to where the Adhoc1 variable is created etc...
This post suggests that the RecordSet has not been initialized prior to working with it, but it's hard to be more specific without the code.
Runtime error '91' is Object variable or With block variable not set, which is a slightly confusing way to say that your variable contains Nothing.
You either forgot to initialise the Adodc1 properly, or, and this is more likely, you need to initialise Adodc1.RecordSet to something useful (like a Set Adodc1.RecordSet = New RecordSet or related) before you can use it.
By the way you posted the code, I believe that you will populate a Recordset to insert into the database. Try as follows:
sub btn_click()
dim Adodc1 as adodb.recordset
set Adodc1 = new adodb.recordset
Fname = txtFname.text
Rs.Fields.Append "Fname", adVarChar, 20 'adVarChar = text, followed by the amount of characters
Adodc1.open()
Adodc1.Recordset.AddNew
Adodc1.Recordset.Fields("Fname") = Fname
Adodc1.Recordset.Update
End sub

ArcPad - VBscript - Autopopulate attributes

I am using the following script to grab parcel and address information from one layer to fill the attribute table of a newly created feature.
There is no returned error, but the problem I am having is that there seems to be the wrong information stuck in the memory of recordselect function. No matter where I place a point it gives the same parcel # and address. Or maybe it isn’t actually be performing the IF function properly.
Sub Address
Dim rsCurrentXY
Set rsCurrentXY = Map.Layers("Violations").records
rsCurrentXY.movelast
Dim objXYShape
Set objXYShape = rsCurrentXY.Fields.Shape
Dim pControls
Set pControls= Application.Map.selectionlayer.Forms("EDITFORM").Pages(“PAGE1”).Controls
Dim rsGrid
' Find corresponding map page to the valve point
Set rsGrid = Map.Layers("ACPA_parcels").records
rsGrid.movefirst
Do While Not rsGrid.eof
If rsGrid.fields.shape.Ispointin(objXYShape) Then
pControls("txtAddress").value = rsGrid.Fields("ADD1").Value
Exit Do
End If
rsGrid.Movenext
Loop
' Clean Up
Set rsCurrentXY = Nothing
Set objXYShape = Nothing
Set rsGrid = Nothing
End Sub
(I have another subroutine called "PIN" that would do the exact same thing.)
I have them called when their respective edit boxes in the custom form are activated by the inspector.
Thanks for the help,
Robert
Accessing the EDITFORM via Application.Map.selectionlayer.Forms("EDITFORM") will be problematic. Whenever working with controls on an EDITFORM you should using ThisEvent.Object to discover all your objects. For example, if your event handler is Page_OnLoad then ThisEvent.Object will refer to your current page. You should have code like this:
Dim pPage1
Set pPage1 = ThisEvent.Object
Dim pControls
Set pControls = pPage1.Controls

Self Inspection of VB6 UDTs

I have a feeling the answer to this is going to be "not possible", but I'll give it a shot...
I am in the unenviable position of modifying a legacy VB6 app with some enhancements. Converting to a smarter language isn't an option.
The app relies on a large collection of user defined types to move data around. I would like to define a common function that can take a reference to any of these types and extract the data contained.
In pseudo code, here's what I'm looking for:
Public Sub PrintUDT ( vData As Variant )
for each vDataMember in vData
print vDataMember.Name & ": " & vDataMember.value
next vDataMember
End Sub
It seems like this info needs to be available to COM somewhere... Any VB6 gurus out there care to take a shot?
Thanks,
Dan
Contrary to what others have said, it IS possible to get run-time type information for UDT's in VB6 (although it is not a built-in language feature). Microsoft's TypeLib Information Object Library (tlbinf32.dll) allows you to programmatically inspect COM type information at run-time. You should already have this component if you have Visual Studio installed: to add it to an existing VB6 project, go to Project->References and check the entry labeled "TypeLib Information." Note that you will have to distribute and register tlbinf32.dll in your application's setup program.
You can inspect UDT instances using the TypeLib Information component at run-time, as long as your UDT's are declared Public and are defined within a Public class. This is necessary in order to make VB6 generate COM-compatible type information for your UDT's (which can then be enumerated with various classes in the TypeLib Information component). The easiest way to meet this requirement would be to put all your UDT's into a public UserTypes class that will be compiled into an ActiveX DLL or ActiveX EXE.
Summary of a working example
This example contains three parts:
Part 1: Creating an ActiveX DLL project that will contain all the public UDT declarations
Part 2: Creating an example PrintUDT method to demonstrate how you can enumerate the fields of a UDT instance
Part 3: Creating a custom iterator class that allows you easily iterate through the fields of any public UDT and get field names and values.
The working example
Part 1: The ActiveX DLL
As I already mentioned, you need to make your UDT's public-accessible in order to enumerate them using the TypeLib Information component. The only way to accomplish this is to put your UDT's into a public class inside an ActiveX DLL or ActiveX EXE project. Other projects in your application that need to access your UDT's will then reference this new component.
To follow along with this example, start by creating a new ActiveX DLL project and name it UDTLibrary.
Next, rename the Class1 class module (this is added by default by the IDE) to UserTypes and add two user-defined types to the class, Person and Animal:
' UserTypes.cls '
Option Explicit
Public Type Person
FirstName As String
LastName As String
BirthDate As Date
End Type
Public Type Animal
Genus As String
Species As String
NumberOfLegs As Long
End Type
Listing 1: UserTypes.cls acts as a container for our UDT's
Next, change the Instancing property for the UserTypes class to "2-PublicNotCreatable". There is no reason for anyone to instantiate the UserTypes class directly, because it's simply acting as a public container for our UDT's.
Finally, make sure the Project Startup Object (under Project->Properties) is set to to "(None)" and compile the project. You should now have a new file called UDTLibrary.dll.
Part 2: Enumerating UDT Type Information
Now it's time to demonstrate how we can use TypeLib Object Library to implement a PrintUDT method.
First, start by creating a new Standard EXE project and call it whatever you like. Add a reference to the file UDTLibrary.dll that was created in Part 1. Since I just want to demonstrate how this works, we will use the Immediate window to test the code we will write.
Create a new Module, name it UDTUtils and add the following code to it:
'UDTUtils.bas'
Option Explicit
Public Sub PrintUDT(ByVal someUDT As Variant)
' Make sure we have a UDT and not something else... '
If VarType(someUDT) <> vbUserDefinedType Then
Err.Raise 5, , "Parameter passed to PrintUDT is not an instance of a user-defined type."
End If
' Get the type information for the UDT '
' (in COM parlance, a VB6 UDT is also known as VT_RECORD, Record, or struct...) '
Dim ri As RecordInfo
Set ri = TLI.TypeInfoFromRecordVariant(someUDT)
'If something went wrong, ri will be Nothing'
If ri Is Nothing Then
Err.Raise 5, , "Error retrieving RecordInfo for type '" & TypeName(someUDT) & "'"
Else
' Iterate through each field (member) of the UDT '
' and print the out the field name and value '
Dim member As MemberInfo
For Each member In ri.Members
'TLI.RecordField allows us to get/set UDT fields: '
' '
' * to get a fied: myVar = TLI.RecordField(someUDT, fieldName) '
' * to set a field TLI.RecordField(someUDT, fieldName) = newValue '
' '
Dim memberVal As Variant
memberVal = TLI.RecordField(someUDT, member.Name)
Debug.Print member.Name & " : " & memberVal
Next
End If
End Sub
Public Sub TestPrintUDT()
'Create a person instance and print it out...'
Dim p As Person
p.FirstName = "John"
p.LastName = "Doe"
p.BirthDate = #1/1/1950#
PrintUDT p
'Create an animal instance and print it out...'
Dim a As Animal
a.Genus = "Canus"
a.Species = "Familiaris"
a.NumberOfLegs = 4
PrintUDT a
End Sub
Listing 2: An example PrintUDT method and a simple test method
Part 3: Making it Object-Oriented
The above examples provide a "quick and dirty" demonstration of how to use the TypeLib Information Object Library to enumerate the fields of a UDT. In a real-world scenario, I would probably create a UDTMemberIterator class that would allow you to more easily iterate through the fields of UDT, along with a utility function in a module that creates a UDTMemberIterator for a given UDT instance. This would allow you to do something like the following in your code, which is much closer to the pseudo-code you posted in your question:
Dim member As UDTMember 'UDTMember wraps a TLI.MemberInfo instance'
For Each member In UDTMemberIteratorFor(someUDT)
Debug.Print member.Name & " : " & member.Value
Next
It's actually not too hard to do this, and we can re-use most of the code from the PrintUDT routine created in Part 2.
First, create a new ActiveX project and name it UDTTypeInformation or something similar.
Next, make sure that the Startup Object for the new project is set to "(None)".
The first thing to do is to create a simple wrapper class that will hide the details of the TLI.MemberInfo class from calling code and make it easy to get a UDT's field's name and value. I called this class UDTMember. The Instancing property for this class should be PublicNotCreatable.
'UDTMember.cls'
Option Explicit
Private m_value As Variant
Private m_name As String
Public Property Get Value() As Variant
Value = m_value
End Property
'Declared Friend because calling code should not be able to modify the value'
Friend Property Let Value(rhs As Variant)
m_value = rhs
End Property
Public Property Get Name() As String
Name = m_name
End Property
'Declared Friend because calling code should not be able to modify the value'
Friend Property Let Name(ByVal rhs As String)
m_name = rhs
End Property
Listing 3: The UDTMember wrapper class
Now we need to create an iterator class, UDTMemberIterator, that will allow us to use VB's For Each...In syntax to iterate the fields of a UDT instance. The Instancing property for this class should be set to PublicNotCreatable (we will define a utility method later that will create instances on behalf of calling code).
EDIT: (2/15/09) I've cleaned the code up a bit more.
'UDTMemberIterator.cls'
Option Explicit
Private m_members As Collection ' Collection of UDTMember objects '
' Meant to be called only by Utils.UDTMemberIteratorFor '
' '
' Sets up the iterator by reading the type info for '
' the passed-in UDT instance and wrapping the fields in '
' UDTMember objects '
Friend Sub Initialize(ByVal someUDT As Variant)
Set m_members = GetWrappedMembersForUDT(someUDT)
End Sub
Public Function Count() As Long
Count = m_members.Count
End Function
' This is the default method for this class [See Tools->Procedure Attributes] '
' '
Public Function Item(Index As Variant) As UDTMember
Set Item = GetWrappedUDTMember(m_members.Item(Index))
End Function
' This function returns the enumerator for this '
' collection in order to support For...Each syntax. '
' Its procedure ID is (-4) and marked "Hidden" [See Tools->Procedure Attributes] '
' '
Public Function NewEnum() As stdole.IUnknown
Set NewEnum = m_members.[_NewEnum]
End Function
' Returns a collection of UDTMember objects, where each element '
' holds the name and current value of one field from the passed-in UDT '
' '
Private Function GetWrappedMembersForUDT(ByVal someUDT As Variant) As Collection
Dim collWrappedMembers As New Collection
Dim ri As RecordInfo
Dim member As MemberInfo
Dim memberVal As Variant
Dim wrappedMember As UDTMember
' Try to get type information for the UDT... '
If VarType(someUDT) <> vbUserDefinedType Then
Fail "Parameter passed to GetWrappedMembersForUDT is not an instance of a user-defined type."
End If
Set ri = tli.TypeInfoFromRecordVariant(someUDT)
If ri Is Nothing Then
Fail "Error retrieving RecordInfo for type '" & TypeName(someUDT) & "'"
End If
' Wrap each UDT member in a UDTMember object... '
For Each member In ri.Members
Set wrappedMember = CreateWrappedUDTMember(someUDT, member)
collWrappedMembers.Add wrappedMember, member.Name
Next
Set GetWrappedMembersForUDT = collWrappedMembers
End Function
' Creates a UDTMember instance from a UDT instance and a MemberInfo object '
' '
Private Function CreateWrappedUDTMember(ByVal someUDT As Variant, ByVal member As MemberInfo) As UDTMember
Dim wrappedMember As UDTMember
Set wrappedMember = New UDTMember
With wrappedMember
.Name = member.Name
.Value = tli.RecordField(someUDT, member.Name)
End With
Set CreateWrappedUDTMember = wrappedMember
End Function
' Just a convenience method
'
Private Function Fail(ByVal message As String)
Err.Raise 5, TypeName(Me), message
End Function
Listing 4: The UDTMemberIterator class.
Note that in order to make this class iterable so that For Each can be used with it, you will have to set certain Procedure Attributes on the Item and _NewEnum methods (as noted in the code comments). You can change the Procedure Attributes from the Tools Menu (Tools->Procedure Attributes).
Finally, we need a utility function (UDTMemberIteratorFor in the very first code example in this section) that will create a UDTMemberIterator for a UDT instance, which we can then iterate with For Each. Create a new module called Utils and add the following code:
'Utils.bas'
Option Explicit
' Returns a UDTMemberIterator for the given UDT '
' '
' Example Usage: '
' '
' Dim member As UDTMember '
' '
' For Each member In UDTMemberIteratorFor(someUDT) '
' Debug.Print member.Name & ":" & member.Value '
' Next '
Public Function UDTMemberIteratorFor(ByVal udt As Variant) As UDTMemberIterator
Dim iterator As New UDTMemberIterator
iterator.Initialize udt
Set UDTMemberIteratorFor = iterator
End Function
Listing 5: The UDTMemberIteratorFor utility function.
Finally, compile the project and create a new project to test it out.
In your test projet, add a reference to the newly-created UDTTypeInformation.dll and the UDTLibrary.dll created in Part 1 and try out the following code in a new module:
'Module1.bas'
Option Explicit
Public Sub TestUDTMemberIterator()
Dim member As UDTMember
Dim p As Person
p.FirstName = "John"
p.LastName = "Doe"
p.BirthDate = #1/1/1950#
For Each member In UDTMemberIteratorFor(p)
Debug.Print member.Name & " : " & member.Value
Next
Dim a As Animal
a.Genus = "Canus"
a.Species = "Canine"
a.NumberOfLegs = 4
For Each member In UDTMemberIteratorFor(a)
Debug.Print member.Name & " : " & member.Value
Next
End Sub
Listing 6: Testing out the UDTMemberIterator class.
If you change all your Types to Classes. You have options. The big pitfall of changing from a type to a class is that you have to use the new keyworld. Every time there a declaration of a type variable add new.
Then you can use the variant keyword or CallByName. VB6 doesn't have anytype of reflection but you can make lists of valid fields and test to see if they are present for example
The Class Test has the following
Public Key As String
Public Data As String
You can then do the following
Private Sub Command1_Click()
Dim T As New Test 'This is NOT A MISTAKE read on as to why I did this.
T.Key = "Key"
T.Data = "One"
DoTest T
End Sub
Private Sub DoTest(V As Variant)
On Error Resume Next
Print V.Key
Print V.Data
Print V.DoesNotExist
If Err.Number = 438 Then Print "Does Not Exist"
Print CallByName(V, "Key", VbGet)
Print CallByName(V, "Data", VbGet)
Print CallByName(V, "DoesNotExist", VbGet)
If Err.Number = 438 Then Print "Does Not Exist"
End Sub
If you attempt to use a field that doesn't exist then error 438 will be raised. CallByName allows you to use strings to call the field and methods of a class.
What VB6 does when you declare Dim as New is quite interesting and will greatly minimize bugs in this conversion. You see this
Dim T as New Test
is not treated exactly the same as
Dim T as Test
Set T = new Test
For example this will work
Dim T as New Test
T.Key = "A Key"
Set T = Nothing
T.Key = "A New Key"
This will give a error
Dim T as Test
Set T = New Test
T.Key = "A Key"
Set T = Nothing
T.Key = "A New Key"
The reason for this is that in the first example VB6 flags T so that anytime a member is accessed it check whether the T is nothing. If it is it will automatically create a new instance of the Test Class and then assign the variable.
In the second example VB doesn't add this behavior.
In most project we rigorously make sure we go Dim T as Test, Set T = New Test. But in your case since you want to convert Types into Classes with the least amount of side effects using Dim T as New Test is the way to go. This is because the Dim as New cause the variable to mimic the way types works more closely.
#Dan,
It looks like your trying to use RTTI of a UDT. I don't think you can really get that information without knowing about the UDT before run-time.
To get you started try:
Understanding UDTs
Because of not having this reflection capability. I would create my own RTTI to my UDTs.
To give you a baseline. Try this:
Type test
RTTI as String
a as Long
b as Long
c as Long
d as Integer
end type
You can write a utility that will open every source file and add The RTTI with the name of the type to the UDT. Probably would be better to put all the UDTs in a common file.
The RTTI would be something like this:
"String:Long:Long:Long:Integer"
Using the memory of the UDT you can extract the values.

Resources