PDA

View Full Version : Solved: Obj_Type Is Nothing, Is Empty...



kunguito
06-19-2008, 06:48 AM
I defined a Type:

Public Type MyType
'...
End Type


I declared an array of MyType:
Dim obj_MyType() As MyType

How could I find out if there's nothing inside?
I tried:
If obj_MyType Is Nothing

But it gives a Type error missmatch. I also tried with Is Empty And IsNull...

Oorang
06-19-2008, 11:34 AM
This is a great question. One to which I have never found a fully satisfying answer. Personally I would just include in your Type Definition a boolean Member Called "HasContent" then whenever I write data to it set it to true (it will be false by default). Then you can just test this member.


Option Explicit

Public Type Person
HasContent As Boolean
FirstName As String
LastName As String
End Type

Public Sub Example1()
Dim udtUsers(0 To 5) As Person
Dim udtUser As Person
Dim i As Long
udtUser.HasContent = True
udtUser.FirstName = "John"
udtUser.LastName = "Smith"
udtUsers(2) = udtUser
For i = 0 To 5
If udtUsers(i).HasContent Then
Debug.Print udtUsers(i).FirstName & " " & udtUsers(i).LastName
End If
Next
End Sub

Bob Phillips
06-19-2008, 11:37 AM
It yet again proves that UDTs are useless, and a waste of time.

Oorang
06-19-2008, 11:45 AM
XLD, I respectfully disagree with you. I agree that classes are way more powerful, but they are also more complex. To me the chief benefit of a UDT is that it gets people to use data in a structured way. Once they adapt to this approach they tend to segway into classes. IMO, vaving the intermediate step smooths out the learning curve.

UDTs can also be an expediant. Take for example, "rectangle". Do you really need a "rectangle" class? Sure it's more OOP, but c'mon:) If it's for production code, maybe I'd go that far. But if I am just doing something Q&D... No way am I taking the time to do that.

And finally, as long as VBA is using VB6 and not .Net you will still need to use the Win32 API. And if you think you can do that without UDTs... Well... Fahgedda bout it:)


Edit:
I ran across this at vb helper (http://www.vb-helper.com/howto_compare_udt.html), if you want to compare udts directly without a special HasContent member, here is how to do it:

Option Explicit

Public Type Person
FirstName As String
LastName As String
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As _
Any, pSrc As Any, ByVal ByteLen As Long)

Sub Test()
Dim udtEmpty As Person
Dim udtJohn As Person
udtJohn.FirstName = "John"
udtJohn.LastName = "Smith"
MsgBox MyTypesTheSame(udtJohn, udtEmpty)
End Sub

' Return True if these structures contain the same data.
Private Function MyTypesTheSame(a As Person, b As Person) As Boolean
Dim i As Integer
Dim a_bytes() As Byte
Dim b_bytes() As Byte
Dim different As Boolean

' Copy the data into arrays of bytes.
ReDim a_bytes(1 To Len(a))
ReDim b_bytes(1 To Len(b))

CopyMemory a_bytes(1), a, Len(a)
CopyMemory b_bytes(1), b, Len(b)

' Compare the bytes.
For i = 1 To Len(a)
If a_bytes(i) <> b_bytes(i) Then
MyTypesTheSame = False
Exit Function
End If
Next i

MyTypesTheSame = True
End Function

kunguito
06-19-2008, 12:07 PM
buffff!

The array is dynamic and it's very likely that often it will not be referenced. :doh:
So unless I build a super UDT containing the array and a boolean it won't do. Never mind, I'll code a class!

Oorang, you're right I used a UDT instead of a class because I needed something done fast.


You brought the discussion to an interesting point. At least for me. I'm an Industrial Engineer, so kind of a programming novice. I've got some C/C++ experience, VB and some other stuff. I would like to learn some other languages. Here is my dilema: Java/.Net/C#/Python (I find that one very cool).

Thanks for your replies!

Oorang
06-19-2008, 12:30 PM
That is holy-war material, but I'll give you my personal opinion.
The language you use depends on what you are coding. I kind of like C# myself, because I work with Microsoft products so much. But to be honest C# is a whole lot like Java (and vice-versa) so the transition between the two is about as easy as it's ever going to get from language to language. Not a Python guy so I don't have an opinion there. And as far as vb.Net... Well it's so different from VB6 (which is pretty much what you are using in VBA) that you might as learn C#. The problem with vb.Net (imho) is that while substantially incompatable with VB6, it still has many legacy quirks. This prevents its from fully embracing any one programming style and leads to some non-intuitive practices. So much so, that if were starting a project in .Net from scratch, I would do it in C# over VB.

But there are some "hard core" apps that I would never ever do in a .Net language. Then you are back to C/C++ (not that I know C++, but I would hire someone who did).

Bob Phillips
06-19-2008, 01:15 PM
XLD, I respectfully disagree with you. I agree that classes are way more powerful, but they are also more complex. To me the chief benefit of a UDT is that it gets people to use data in a structured way. Once they adapt to this approach they tend to segway into classes. IMO, vaving the intermediate step smooths out the learning curve.

They are, but you only code them once, and then re-use them And if you are any good, you think about them, so you make them flexible, extendible, and powerful - all words it is difficult to apply to UDTs.

UDTs are so limited as to make them more of an annoyance than an useful part of the toolkit IMO. I stopped using them years ago because they failed in so many situations.


UDTs can also be an expediant. Take for example, "rectangle". Do you really need a "rectangle" class? Sure it's more OOP, but c'mon:) If it's for production code, maybe I'd go that far. But if I am just doing something Q&D... No way am I taking the time to do that.

I would argue that if it is not for production, you would be unlikely to need UDTs. But more to the point, no you wouldn't create a rectangle class, you would create a polygon class. Far more useful.


And finally, as long as VBA is using VB6 and not .Net you will still need to use the Win32 API. And if you think you can do that without UDTs... Well... Fahgedda bout it:)

That is true, but that is not an argument for us to use them as well.

Oorang
06-19-2008, 01:47 PM
They are, but you only code them once, and then re-use them And if you are any good, you think about them, so you make them flexible, extendible, and powerful - all words it is difficult to apply to UDTs.
I totally agree, classes are a much better approach. And I tend to favor them over even standard modules. But I am not taking the stance that UDTs have more value than a class. They don't. I am taking the stance the UDTs have a value in some circumstances.

[quote=xld]I would argue that if it is not for production, you would be unlikely to need UDTs. But more to the point, no you wouldn't create a rectangle class, you would create a polygon class. Far more useful.
/[quote]
And that is my whole point. This, is why UDTs are useful.

If all I need is a Rectangle, and I come back two hours later and you are still coding up "One Shape Class to Rule Them All", I'm going to be like: "Dude, none of our forms, controls, screens, etc will be anything other than 4 sides of 2 equal values. If, in the future, we need need to add code for all of those octogonal forms we use, then build that shape class... And if you really feel the need, you can replace our rectacgle UDT with a wrapper that interacts with the shape class. But while we are still using rectangles.... Stop wasting time." (Well IRL, I wouldn't be quite that direct. But I'd be thinking it :))

The whole point of OOP is to keep code self-documenting, self-scoping, so it's easy to understand and maintain after the original developers have moved on. UDTs meet those goals in a very simplistic fashion. You can do more with a class, and when you need to do more, use one. But IMHO you should always use the simplest tool needed to accomplish the task.

I'd further point out than even fully OOP languages make use of data structures.

Bob Phillips
06-19-2008, 01:59 PM
Aaron,

I think my main argument is not coming across, I have wandered off of the point rather than being specific.

Your arguments re the value of UDTs are totally right. In concept, I agree that in concept UDTs are great, it is just that in VB/VBA they suffer from a garbage implementation. If they were robust, as useable as they should be, I would use them. They aren't and they they aren't, so I prefer not to suffer the pain (even after 2 houres <g>).

Oorang
06-19-2008, 02:06 PM
Ahh the time honored "It's a price I'm willing to pay argument" :)

Well so be it. I at least agree with the poor implementation point. I should not have to be manually copying memory around with an api call to test for emptyness. And you run into all sorts of weird scoping issues with them too.

You know what would be cool... A vbe add-in that converted UDTs to a Class. I already have one that converts public variables to properties, it should be a short leap, right?

Bob Phillips
06-19-2008, 02:13 PM
MZ Tools has a command to convert publics to properties, I wonder if Carlos would be interested in adding that?

Is it a short leap? Can you create a class module dynamically or do you envisage that would already be done.

I would think that the real value comes with a collection class as well as the UDT class, and that is quite a bit more tricky

Oorang
06-19-2008, 02:25 PM
Yes very easy. I just coded up a Q&D test run. Works fine. The real difficulty would be putting it into a COM Add-in. Haven't tried it yet in .Net. I have the tools though.

Getting it put in MZ-Tools would be fantastic. I love MZ-Tools. But I didn't think he was furthering the 3.0 version? (And as far as I know 6.0 won't work w/VBA.)

Bob Phillips
06-20-2008, 01:22 AM
Deployment is the issue with VS2008. It is supposed to be better in 2008, but it is still a minefield.

Oorang
06-20-2008, 05:43 AM
Hmmm I haven't acutally tried anything major off VS2008. The few programs I have written in .Net I used Sharp Develop or VS2003. And even then I built my installer using Advanced Installer (http://www.caphyon.com/) (which took less than an hour and worked like a dream). Are they issues that this will avoid, or is there some fresh new hell?

Bob Phillips
06-20-2008, 10:31 AM
No, I don;'t believe there are new issues, just that they haven't fully resolved all of the old issues yet. Did you look in on Excel User Group at the thread I mentioned?

Paul_Hossler
06-22-2008, 02:59 PM
Not getting in the way of the UDT vs. Class discussion, but:whistle:

1. Even tho you called it obj_MyType(), I think that it's still an array variable of MyType's, and not an object, so object-like tests (i.e. Is Nothing) probably won't work.

2. I've noticed a difference in behaviour if the array is declared outside the Sub vs. Inside. After the first run, it's Nothing, but for the second run, it remembers.

This is a little brute force, but at least you can tell that it's empty



Option Explicit
Public Type MyType
x As Long
y As Long
z As Long
End Type
'if outside the sub, re-runs do not reset it to nothing
'Dim arr_MyType() As MyType

Sub MySub()
Dim i As Long
Dim arr_MyType() As MyType
'before
i = -1
On Error Resume Next
i = UBound(arr_MyType)
On Error Resume Next

If i = -1 Then
MsgBox "Nothing"
Else
MsgBox "There are " & (i + 1) & " entries"
End If

'put in some data 0 - 1
ReDim arr_MyType(1)

With arr_MyType(0)
.x = 1
.y = 2
.z = 3
End With
With arr_MyType(1)
.x = 1
.y = 2
.z = 3
End With

'after
i = -1
On Error Resume Next
i = UBound(arr_MyType)
On Error Resume Next

If i = -1 Then
MsgBox "Nothing"
Else
MsgBox "There are " & (i + 1) & " entries"
End If

End Sub


Paul

Oorang
06-22-2008, 05:47 PM
:oops:

Yah I totally threadjacked... Sorry about that:)

Back to matter at hand. You are correct that you can test for an empty array using the standard methods. But the problem is, that it will only tell you that the array has (or has not) been dimensioned. I think what the OP was asking (assuming I understood correctly) was how to test if an element of an array was empty.


Option Explicit

Public Type MyType
x As Long
y As Long
z As Long
End Type

Public Sub Test()
Dim udtTest() As MyType
MsgBox IsDimmed(udtTest)
ReDim udtTest(0 To 10)
MsgBox IsDimmed(udtTest)
'It may be dimmed, but it's empty:)
End Sub

Public Function IsDimmed(ByRef testArray() As MyType) As Boolean
Dim udtTest As MyType
On Error Resume Next
udtTest = testArray(UBound(testArray))
IsDimmed = Not CBool(Err.Number)
End Function

Bob Phillips
06-23-2008, 06:01 AM
I know how to test an array for never having been loaded, ghaving been cleared out, but it doesn't work on an array of UDTs.

Oorang
06-23-2008, 08:31 AM
Hehe I am just making it worse... Sorry:) You can test an array of UDTs for not being dimmed (which is what I thought you were doing in you example and what I showed in my own example). And the usual methods of bound-checking of does work (at least I haven't found a breaking scenario yet).

But what I was trying to say was I think the OP was less worried about checking the entire array, and seeing if a specific element in said array was not used. (As in vbNullString if it were a string array).

Since an empty UDT will look different for each individual UDT, the most flexible way (IMO) to see if element in a UDT array is empty is to just be able to compare it to an Empty Variable of the same user defined type. To do that you need to be able to perform a comparison of two UDTs (the element to be tested, and the empty UDT). If the tested element is equivalant at the byte level to an empty version of the UDT (which is what I posted earler will check) then the element is empty.

But as far as I have noticed an array of UDTs performs no different than any other array.

/Me hopes he has not made it worse by explaining

:stars:

Paul_Hossler
06-23-2008, 05:11 PM
Well, I'm going to argue with anyone who has a post count > 10,000 :clap: :clap: or any one who has earned the VBAX Expert tag, :thumb .... but


The OP had

1.


If obj_MyType Is Nothing


instead of a specific element obj_MyType(1)

2. and prefaced the variable name with "obj_"

So I figured a there was a misunderstanding between a UDT and an object, and started with the KISS principle.

Paul