Reproducable Hard Crash in Excel 2003 (and earlier versions) with the following VBA code.

D

David Battams

Hi,

I have a problem in some VBA code that causes a hard crash in Excel 2000 and
2003 (haven't tried Excel XP but I would assume the same result).
Fortunately I managed to reproduce the problem in a simple workbook, and the
code is that small that I can duplicate it here.

In a new workbook, add the following:


ThisWorkBook

Public Sub EntryPoint()

Dim data() As MY_DATA_TYPE

ReDim data(0)
data(0).val1 = "Test"
data(0).val2 = "Test 2"

MethodA data

End Sub

Private Sub MethodA(ByRef data() As MY_DATA_TYPE)

Dim form As UserForm1
Set form = New UserForm1
form.Test = data

End Sub


Module1

Public Type MY_DATA_TYPE
val1 As String
val2 As String
End Type


UserForm1

Private m_data() As MY_DATA_TYPE

Public Property Let Test(ByRef newValue() As MY_DATA_TYPE)
m_data = newValue
End Property

The code will crash when setting the Test property of UserForm1

This only seems to occur in this particular configuration of code. I can
pass the dyamic array through a number of methods without issue, but when I
assign the UserForm property is when it fails. It will also work fine if I
short circuit MethodB and set the UserForm property directly from the
EntryPoint method. Yet another way to get it to work is to make the dynamic
array a module level variable in ThisWorkBook and thus not have to pass it
between methods in ThisWorkbook.

I do have a work around so am not being held up by this, but I would be
appreciative if someone from Microsoft (or otherwise) could confirm this
behavior and advise whether it is a bug or known limitation. I couldn't find
anything in the KB about it.

Kind Regards,
Wayne.
 
R

Rob van Gelder

I treat Userforms as Class Modules without problems. It find it tider than
returning values via a Standard Module.
 
D

David Battams

There's no "treating" a UserForm class as an object module. It IS an object
module.

Try placing the public type declaration in UserForm1 and see what error
message you get....

KeepItCool - what do you mean what is the point? I presume hard crashes are
a feature in your code? :)
 
J

Jamie Collins

keepITcool wrote ...
ok i confirm it crashed in xlXP too :)

but what's the point?

the PROBLEM is that
you're treating a userform as a class module (first time i saw that :)

That isn't the problem! Userforms *should* be treated as classes. You
should read my posts more often ;-)

http://groups.google.com/[email protected]

AFAIK it's the user defined type that is the problem. I've seen it
before in this ng but don't have any answers other than workarounds
(which the OP already has).

Jamie.

--
 
D

David Battams

Hi Jamie,

I figured the user defined type is what set the cat amongst the pigeons, and
for some reason only the specific combination of passing by reference to a
local method, then to a UserForm class property setter (or in VB do you guys
call value type setters, letters? ;-)

When running my full application as an Excel Add-In I was getting the
following automation error:
Automation Error: The Object Invoked Has Disconnected from Its Clients

That makes me think there is something sinister going on in the background
somewhere, since the code itself should be pretty harmless.

Anyway, I've taken the route of a module level variable of the user defined
type, then passing that once only to the form class via its associated
property. Seems to work fine.

Cheers,
Wayne.
 
J

Jamie Collins

...
There's no "treating" a UserForm class as an object module. It IS an object
module.

I think Rob meant he uses a userform as he would a class e.g. add
public members to the userform rather than use public variables in a
standard module etc.
KeepItCool - what do you mean what is the point? I presume hard crashes are
a feature in your code? :)

I think KeepItCool meant he usually instantiates a userform with

Load UserForm1

(which is reasonable if you only need one instance) and wasn't waare
he could you could do the same with

Dim frm1 As UserForm1
Set frm1 = New UserForm1

David, untested but if you replace the struct (MY_DATA_TYPE) with a
complex object (a VB class) I think the problem would go away. That's
what I mean by the struct being the problem. But something tells me
you need the struct for an external app...?

Jamie.

--
 
D

David Battams

Hi Jamie,

My comment about the UserForm being an object module was that there is no
need to "pretend" its like an object module since it is one. Rob is using it
correctly It's just a special type of class module.

I might try the idea of using a class object in lieu of a type and let you
know how it goes. I am writing VBA code against a set of custom COM
components, but the data type I am having the problem with is used purely
within the VBA world, so I have the freedom to change it to a VBA class
instead. Good thinking and I'll let you know how it goes.

Cheers,
Wayne.
 
D

David Battams

Hi again Jamie,

Tried the VB object route - here's my 2 second class:

Class Module FailedPattern

Private m_patternLabel As String
Private m_reason As String

Public Property Get PatternLabel() As String
PatternLabel = m_patternLabel
End Property

Public Property Let PatternLabel(ByVal label As String)
m_patternLabel = label
End Property

Public Property Get Reason() As String
Reason = m_reason
End Property

Public Property Let Reason(ByVal reason As String)
m_reason = reason
End Property

to replace the following data type:

Public Type FAILED_PATTERN
patternLabel As String
reason As String
End Type

but just like the with the data type I still got the hard crash in Excel :-(

Something for Microsoft I guess......

Regards,
Wayne.
 
K

keepITcool

Wayne,

although my first remark wasn't well received.. let me try again :)

crash appears to be caused by invoking a property let procedure with
an argument defined as a dynamic ARRAY of userdefined type.
Regardless of what happens inside the procedure.. the moment it's passed
to the proc the crash occurs in oleaut32

Workaround:
dim it as a class, pass it as a variant


I've changed the class varariables to public for simplicity

'Class Module clsTest
Public patternLabel As String
Public reason As String

'Object module userform1
Private m_cls() As clsTest
Public Property Let TestVariant(newData)
m_cls = newData
End Property
Public Property Let TestTyped(newData As clsTest)
'note this 'ought' to be a Property SET
ReDim m_cls(0)
Set m_cls(0) = newData
End Property
Public Property Let TestArray(newData() As clsTest)
m_cls = newData
End Property
'code module1
Public Sub EntryPoint()
Dim data() As clsTest
ReDim data(0)
Set data(0) = New clsTest
data(0).patternLabel = "Test1"
data(0).reason = "Test2"
fillFORM data
End Sub

Private Sub fillFORM(data() As clsTest)
Dim form As UserForm1
Set form = New UserForm1
form.TestVariant = data
MsgBox "Variant successfull"

Let form.TestTyped = data(0)

MsgBox "Class successfull"

If vbOK = MsgBox("Fasten seatbelts", vbOKCancel) Then
form.TestArray = data
MsgBox "You wont see this one ...."
End If
End Sub




keepITcool

< email : keepitcool chello nl (with @ and .) >
< homepage: http://members.chello.nl/keepitcool >


David Battams said:
Hi again Jamie,

Tried the VB object route - here's my 2 second class:
...[snip]

but just like the with the data type I still got the hard crash in
Excel :-(

Something for Microsoft I guess......

Regards,
Wayne.




David Battams said:
Hi Jamie,

My comment about the UserForm being an object module was that there
is no need to "pretend" its like an object module since it is one.
Rob is using it correctly It's just a special type of class module.

I might try the idea of using a class object in lieu of a type and
let you know how it goes. I am writing VBA code against a set of
custom COM components, but the data type I am having the problem with
is used purely within the VBA world, so I have the freedom to change
it to a VBA class instead. Good thinking and I'll let you know how it
goes.

Cheers,
Wayne.
[..snip]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top