Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do I determine if a control is a control array?

0 views
Skip to first unread message

ben_h...@hotmail.com

unread,
Aug 26, 1999, 3:00:00 AM8/26/99
to
I have a method that I want to use for many forms. On some of those
forms I have control arrays and on others I do not. The method I
execute should loop through all controls and do some special stuff to
those controls that are NOT part of a control array.

I have sample code below that does work. However, in my case most of
my controls are NOT control arrays, so this code is very slow because
it assumes the exception, which we all know is not efficient.

Is there ANY WAY to check for a ControlArray?? Does VB have anything
like a "IsControlArray" method or something similiar??

The code I have that works is below, but I would really appreciate
something that works much more efficiently (and reads a little clearer)!

- Ben Hadden
ben_h...@hotmail.com


Dim Index as Integer

For Each Control in Form.Controls

'This will raise error if it is not a control array.
'this error is handled in error handling and Index set to -1.
Index = Control.Index

'Index of 0 or greater means we have a control array, so skip code.
'Index of -1 assumes we do not have control array, so run code.
If Index < 0 then
<<Code that we run when we know we do NOT have a control array>>
End If

Next Control

Err_Handling:
Select Case Err.Number
Case 343
Index = -1
Resume Next
Case Else
'Do Error Handling
End Select


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

Richard Nettleingham

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
Hi Ben,

Perhaps this would help:

Use the Count property of the controls collection, if you for example have
a textbox named txtinput use txtinput.count

Regards
/Richard


ben_h...@hotmail.com skrev i meddelandet <7q4gte$dvi$1...@nnrp1.deja.com>...

Douglas Marquardt

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
Hi Ben:

>I have sample code below that does work. However, in my case most of
>my controls are NOT control arrays, so this code is very slow because
>it assumes the exception, which we all know is not efficient.


I doubt very much that you would notice the performance difference (if any).


>Is there ANY WAY to check for a ControlArray

IMO, checking for the Index property is just as good as any other.

Doug.


Douglas Marquardt

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
Hi Richard:

> Use the Count property of the controls collection, if you for example have
>a textbox named txtinput use txtinput.count


Count property only works on Indexed controls -- controls that don't have an
Index property do not support the count property.

Doug.


Douglas Marquardt

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
Hi Timothy:

>> Is there ANY WAY to check for a ControlArray?? Does VB have anything
>> like a "IsControlArray" method or something similiar??

>..he he.. /\/\/\/\/\/\/\/\/\/\ .......IsArray( )
> | | | | | | | | | | |


AFIK, this does not work on controls, only on variables. Could you post
some working code that demonstrates using this on controls?


Doug.


Timothy A. Kessler

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
Doug,

(note: it is not essential to loop through
every control like this example...duh)

Anyway....here ya go.....
put some controls that are arrays and
controls that are not on a form. Then
place one textbox ....call it textbox1
with no index (for this example to work)
set Text1.multiline = true
Then run this code.

Option Explicit
Private Const IsNotControlArray = 343

Private Sub Form_Load()
Dim x As Control

On Error GoTo ERRORTRAP:

For Each x In Controls
If x.Index >= 0 Then
Text1.Text = Text1.Text _
& x.Name & "(" & x.Index & ") is an array." & vbCrLf
Else
NotArray:
Text1.Text = Text1.Text _
& x.Name & " " & "is NOT an array." & vbCrLf
End If
Next

Exit Sub

ERRORTRAP:
Select Case Err
Case IsNotControlArray
Resume NotArray:
Case Else
MsgBox Str$(Err.Number) & " - " & Err.Description
End Select
End Sub


Rick Rothstein

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
That only works if you use the actual control name (Label1 in your example)
in the TypeName function. However, if you try and reference the control via
a passed argument into a function call or via a variable while looping
through the Controls collection, you lose the ability to use TypeName to
test this way. I find this surprising but accepted it quite a while ago when
I made this identical argument in response to a similar post 6 or so months
ago.

Rick

Bill McCarthy <bil...@gsat.edu.au> wrote in message
news:um9VgHK8#GA.263@cppssbbsa03...
> Actually you can try the "TypeOf IS" statement or the typename function.
> eg.
>
> If TypeName(Label1) = "Object" Then
> Debug.Print "is a control array"
> End If
>
>
>
> Eg If
> Timothy Kessler <Tak...@RocketMail.Com> wrote in message
> news:01bee91f$55fc2b00$9a98...@kih.net...

V. Korol

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
For looping in Controls yes, but if you assign control to variant variable
you can pass it as function argument and TypeOf as well as TypeName will be
work.
e.g.
Dim cmb
Dim c
Set cmb = cmbArray
' cmbArray is any control. Function check If it is control array, and add
new control to to array.
AddControl cmbArray, "myControl"

Public Function AddControl(cntr As Variant, Caption As String)
Dim cnt As Long
If TypeName(cntr) = "Object" Then
cnt = cntr.UBound + 1
Load cntr(cnt)
cntr(cnt).Top = cntr(cnt - 1).Top + cntr(cnt).Height
cntr(cnt).Caption = Caption
cntr(cnt).Visible = True
Else
AddControl = 0
End If
End Function

Rick Rothstein пишет в сообщении <#yUJwhK8#GA...@cppssbbsa02.microsoft.com>
...

Rick Rothstein

unread,
Aug 27, 1999, 3:00:00 AM8/27/99
to
This is in response to both V. Korol and Bill McCarthy:

Perhaps I wasn't as clear as I could have been in my post. IF you use the
Control's Name *directly*, or set a variable to that Control Name and then
use it, then yes TypeName will distinguish between a Control Array and a
Non-Control Array. The problem is if you know the Name you are passing, then
you (as the programmer) already know if it is a Control Array or not -- no
knowledge was gained. In practical use, the user gives focus to a control
and the question is - is it part of a Control Array or not? This TypeName
can't distinguish for you.

The easiest way to see this is to put a Control Array of components on a
form along with a Non-Control-Array component and run through the form's
Controls collection. If you run through all the components, TypeName does
not see the Control Array -- only the individual elements of the Control
Array.

The challenge if you are still skeptical is this:

Given the following

For Each ControlItem in Controls
If ???(ControlItem.???) = "Object" Then
Debug.Print "Control Array"
Else
Debug.Print "Nope"
End If
Next

tell me what function (TypeName or other) and what Property you would put in
for the ???'s in order to have "Control Array" printed out (given that a
Control Array of components exists on the Form).

The point is -- if you don't use the actual Control Name either directly or
through a proxy variable, then you can't tell me if a component is part of a
Control Array or not UNLESS you use an On Error routine.

Rick

Rick Rothstein <fnr...@aosi.com> wrote in message
news:#yUJwhK8#GA...@cppssbbsa02.microsoft.com...


> That only works if you use the actual control name (Label1 in your
example)
> in the TypeName function. However, if you try and reference the control
via
> a passed argument into a function call or via a variable while looping
> through the Controls collection, you lose the ability to use TypeName to
> test this way. I find this surprising but accepted it quite a while ago
when
> I made this identical argument in response to a similar post 6 or so
months
> ago.
>
> Rick
>
> Bill McCarthy <bil...@gsat.edu.au> wrote in message
> news:um9VgHK8#GA.263@cppssbbsa03...
> > Actually you can try the "TypeOf IS" statement or the typename
function.
> > eg.
> >
> > If TypeName(Label1) = "Object" Then
> > Debug.Print "is a control array"
> > End If
> >
> >
> >

Bill McCarthy

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to

Bill McCarthy

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
Well this works for me

Dim cntlCntrl As Control
For Each cntlCntrl In Controls
Debug.Print TypeName(Controls(cntlCntrl.Name))
Next

Rick Rothstein <fnr...@aosi.com> wrote in message
news:#yUJwhK8#GA...@cppssbbsa02.microsoft.com...
> That only works if you use the actual control name (Label1 in your
example)
> in the TypeName function. However, if you try and reference the control
via
> a passed argument into a function call or via a variable while looping
> through the Controls collection, you lose the ability to use TypeName to
> test this way. I find this surprising but accepted it quite a while ago
when
> I made this identical argument in response to a similar post 6 or so
months
> ago.
>
> Rick
>
> Bill McCarthy <bil...@gsat.edu.au> wrote in message
> news:um9VgHK8#GA.263@cppssbbsa03...

Bill McCarthy

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to

Rick Rothstein <fnr...@aosi.com> wrote in message
news:eQaILfQ8#GA.254@cppssbbsa04...

> This is in response to both V. Korol and Bill McCarthy:
>
> Perhaps I wasn't as clear as I could have been in my post. IF you use the
> Control's Name *directly*, or set a variable to that Control Name and then
> use it, then yes TypeName will distinguish between a Control Array and a
> Non-Control Array. The problem is if you know the Name you are passing,
then
> you (as the programmer) already know if it is a Control Array or not -- no
> knowledge was gained. In practical use, the user gives focus to a control
> and the question is - is it part of a Control Array or not? This TypeName
> can't distinguish for you.

Well if you , as the programmer can identify the control purely by it's
name, just use it's .Name property.
In practice though, this would probably require an extensive Select Case
statement or a dictionary to work it out. By way do that if the Control
collection can tell you. As per my previous post Control(cntlThingy.Name)
returns a refernce to the control on which you can use TypeName.


> The easiest way to see this is to put a Control Array of components on a
> form along with a Non-Control-Array component and run through the form's
> Controls collection. If you run through all the components, TypeName does
> not see the Control Array -- only the individual elements of the Control
> Array.
>
> The challenge if you are still skeptical is this:
>
> Given the following
>
> For Each ControlItem in Controls
> If ???(ControlItem.???) = "Object" Then
> Debug.Print "Control Array"
> Else
> Debug.Print "Nope"
> End If
> Next
>
> tell me what function (TypeName or other) and what Property you would put
in
> for the ???'s in order to have "Control Array" printed out (given that a
> Control Array of components exists on the Form).
>


For Each ControlItem in Controls

If TypeName(Controls(ControlItem.Name)) = "Object" Then

V. Korol

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
Well, Bill make more than I: I cannot find (Controls(Control.Name)).
Vlad

Bill McCarthy пишет в сообщении ...

Rick Rothstein

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
I'm afraid I've still not made myself clear. The idea and question behind
the original post is you are writing a routine, a function, a whatever and
through some action by the user, that function is being "handed" one of the
controls on the Form and that function is being asked to determine if it is
part of a Control Array or not. You will find that VB sees only the control
in isolation and there is *no* property that you can specify (including
Name) which will let it see if it is a member of a Control Array -- it only
sees the control as a control. I actually formulated my challenge
incorrectly. I repeated it here:

For Each ControlItem in Controls

If ??? Then


Debug.Print "Control Array"
Else
Debug.Print "Nope"
End If
Next

Tell me what logical expression to put in place of the ??? so that the If
statement evaluates as true (and the words "Control Array" are printed in
the Immediate Window). Don't make a guess and post that -- try it out inside
of VB. You will be surprised to find that no expression can be found. (Yes,
some elaborate Select-Case structure could be created, but let's assume your
Form has a thousand controls on it and you don't fell like trying that
approach.)

That's my challenge. Post back a logical expression (using the ControlItem
variable) that I can paste into my VB that prints "Control Array" in this
general case. (And remember, we are trying to rule out the use of an
On-Error trap to accomplish this.)

Rick

P.S. -- I'm not familiar with Control(cntlThingy.Name); is this supposed to
be a Collection you have created within your program? If so, remember, I
proposed that there are a thousand controls on your Form so manually forming
a Collection (via typing) is out. We are looking for a "general" solution,
not one based on knowing the facts before hand -- this is an event driven
world and the user is in control, not the programmer. I believe these
conditions would force you to find a solution in keeping with the intent of
the original post.


Bill McCarthy <bil...@gsat.edu.au> wrote in message

news:uMfaYuQ8#GA.224@cppssbbsa03...

Bill McCarthy

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
Rick are you saying that the code I pasted in my last post does not work ??
Are we both talking about VB6SP3 ??

Try it again, and see what you get:

For Each ControlItem In Controls


If TypeName(Controls(ControlItem.Name)) = "Object" Then
Debug.Print "Control Array"
Else
Debug.Print "Nope"
End If
Next


P.S. That bit about Control(cntlThingy.Name) was a typo, (actually the
whole sentence/paragraph was full of typos), it should have read
Controls(cntlThingy.Name).

Note: when you do a for each iteration you are referencing each and every
control, hence you get the control type. But when you call on the control
from the Controls collection, eg: Controls(cntlThingy.Name) you are
returning a reference to the control or the control array. That is, if it
was an array, you could reference the individual items such as by
Controls(cntlThingy.Name)(i)


Rick Rothstein <fnr...@aosi.com> wrote in message

news:OI6BTfR8#GA.229@cppssbbsa05...

David Youngblood

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
Try this Rick. Yes I know, it doesn't meet one of the criteria you laid of
not using an error handler, but it does do the job, and you should be using
error handling anyway.

Private Sub Command1_Click()
Dim c As Control
For Each c In Controls
If IsControlArray(c) Then
Debug.Print c.Name & " is a control array."
Else
Debug.Print "Nope " & c.Name & " is not."
End If
Next
End Sub

Public Function IsControlArray(c As Control) As Boolean
On Error Resume Next
IsControlArray = Len(TypeName(c.Index))
End Function

David

Rick Rothstein wrote in message ...

David Youngblood

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
It works in vb5sp3, forget my solution.

David

Bill McCarthy wrote in message ...

Bob Butler

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
Rick Rothstein <fnr...@aosi.com> wrote in message
news:OI6BTfR8#GA.229@cppssbbsa05...
> I'm afraid I've still not made myself clear. The idea and question behind
> the original post is you are writing a routine, a function, a whatever and
> through some action by the user, that function is being "handed" one of
the
> controls on the Form and that function is being asked to determine if it
is
> part of a Control Array or not.
<cut>

> (And remember, we are trying to rule out the use of an
> On-Error trap to accomplish this.)
<cut>
I do not believe you can check without using an error trap. Given a single
control reference the only difference between one that is part of a control
array and one that belongs to an array is the existence of the Index
property. There is no intrinsic VB function that will check the property
without triggering an error if it does not exist. While it's probably
possible to query the control's interface and see if the Index property
exists without triggering an error the easiest solution by far is to use an
error trap. I've never understood why people feel that it is an inferior
technique --- it works, it's reliable and it's easy to understand.

Private Sub cmdCheck_Click()
Dim ControlItem As Control
For Each ControlItem In Me.Controls
If IsInControlArray(ControlItem) Then
Debug.Print ControlItem.Name & " is index " & CStr(ControlItem.Index)
Else
Debug.Print ControlItem.Name & " is not an Array member"


End If
Next
End Sub

Private Function IsInControlArray(ByVal ControlItem As Control)
Dim x As Long
On Error Resume Next
x = ControlItem.Index
If Err.Number = 0 Then IsInControlArray = True
End Function


Bob Butler

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
David Youngblood <d...@flash.net> wrote in message
news:OtaFbDT8#GA.263@cppssbbsa04...

> It works in vb5sp3, forget my solution.
>
> David
>
> Bill McCarthy wrote in message ...
> >Rick are you saying that the code I pasted in my last post does not work
??
> >Are we both talking about VB6SP3 ??
> >
> >Try it again, and see what you get:
> >
> > For Each ControlItem In Controls
> > If TypeName(Controls(ControlItem.Name)) = "Object" Then
> > Debug.Print "Control Array"
> > Else
> > Debug.Print "Nope"
> > End If
> > Next
<cut>

VERY interesting.... I learn something new every day...

Rick Rothstein

unread,
Aug 28, 1999, 3:00:00 AM8/28/99
to
My apologies (maybe I got thrown by the typo), but . . .

YOUR SOLUTION WORKS PERFECTLY.

Thank you. That's what I love about these news groups, there is always
someone out there who can provide an answer to a question. For some reason,
this particular question has always presented a blind spot to me. I thought
I looked into, and I thought didn't find a solution in, the Controls
collection back when I first ran into this particular problem. Obviously, I
missed it then and never thought to look at it again. Thanks again.

Rick

Bill McCarthy <bil...@gsat.edu.au> wrote in message

news:uba8BzS8#GA.227@cppssbbsa05...

Bill McCarthy

unread,
Aug 29, 1999, 3:00:00 AM8/29/99
to
Thanks Rick,

Glad you got it.
It seems that with VB we all have to say OOPs sooner or later, you can
.Count on it. :-)

Rick Rothstein <fnr...@aosi.com> wrote in message

news:e8ycIYW8#GA.197@cppssbbsa04...

<SNIP>

ben_h...@hotmail.com

unread,
Aug 30, 1999, 3:00:00 AM8/30/99
to
This just gives me a different error:

438 - "Object doesn't support this property or method."

Thanks but no good.
Anyone else?
- Ben

"Richard Nettleingham" wrote:
>
> Hi Ben,
>
> Perhaps this would help:
>

> Use the Count property of the controls collection, if you for
example have
> a textbox named txtinput use txtinput.count
>

> Regards
> /Richard

Rick Rothstein

unread,
Aug 30, 1999, 3:00:00 AM8/30/99
to
This function is based on the sub-thread located under your post and the
routine provided in response to my "challenge" to Bill McCarthy:

Function IsControlArray(ControlIn) As Boolean
If TypeName(Controls(ControlIn.Name)) = "Object" Then
IsControlArray = True
Else
IsControlArray = False
End If
End Function

The loop you want to do is:

For Each Cntrl In Controls
If IsControlArray(Cntrl) = False Then
'It is NOT a control array so do your thing
End If
Next

Rick

<ben_h...@hotmail.com> wrote in message
news:7q4gte$dvi$1...@nnrp1.deja.com...


> I have a method that I want to use for many forms. On some of those
> forms I have control arrays and on others I do not. The method I
> execute should loop through all controls and do some special stuff to
> those controls that are NOT part of a control array.
>

> I have sample code below that does work. However, in my case most of
> my controls are NOT control arrays, so this code is very slow because
> it assumes the exception, which we all know is not efficient.
>

> Is there ANY WAY to check for a ControlArray?? Does VB have anything
> like a "IsControlArray" method or something similiar??
>

> The code I have that works is below, but I would really appreciate
> something that works much more efficiently (and reads a little clearer)!
>
> - Ben Hadden
> ben_h...@hotmail.com
>
>
> Dim Index as Integer
>
> For Each Control in Form.Controls
>
> 'This will raise error if it is not a control array.
> 'this error is handled in error handling and Index set to -1.
> Index = Control.Index
>
> 'Index of 0 or greater means we have a control array, so skip code.
> 'Index of -1 assumes we do not have control array, so run code.
> If Index < 0 then

> <<Code that we run when we know we do NOT have a control array>>
> End If
>


> Next Control
>
> Err_Handling:
> Select Case Err.Number
> Case 343
> Index = -1
> Resume Next
> Case Else
> 'Do Error Handling
> End Select
>
>

ben_h...@hotmail.com

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to
Just an FYI:

I ran two tests. The only difference was to take out the line where
I'm accessing the Index property. Instead I just hardcoded the number
to -1. My screen opened in half of the time (8 sec. vs. 4 sec.).

0 new messages