Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / General 2 / July 2006



Tip: Looking for answers? Try searching our database.

simple 2 dimensional array problem

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Johnno - 25 Jul 2006 14:29 GMT
I am having trouble working out how to make a two dimensional array work
correctly. I have tried the code below, but keep getting a Type Mismatch. If
I simply assign simple variables to the Drive and Caption items, the code
works fine and I get the results I expect. Can someone please tell me where
the code is wrong? The Dim statements and the procedure are in a module,
while the command button is on a form.
Johnno.

Dim ItemSet As Object
Dim Item As Object
Dim CDInfo() As String
Dim NumDrives As Integer

Public Sub FindCDAtts(CDInfo(), NumDrives)
x = 0
Set ItemSet = GetObject("WinMgmts:").InstancesOf("Win32_CDRomDrive")
For Each Item In ItemSet
   x = x + 1
   ReDim Preserve CDInfo(1 To x, 2)
   CDInfo(x, 1) = Item.Drive
   CDInfo(x, 2) = Item.Caption
  ' info = info & Item.scsiport & ","
  ' info = info & Item.scsitargetid & ","
  ' info = info & Item.scsilogicalunit
  ' CDInfo(x, 2) = info
Next
Set ItemSet = Nothing
Set Item = Nothing
End Sub

Private Sub Command1_Click()
Call FindCDAtts(CDInfo(), NumDrives)
For x = 1 To NumDrives
MsgBox " Drive is " & CDInfo(x, 1) & ", and caption is " & CDInfo(x, 2)
Next x
End Sub
Steve Gerrard - 25 Jul 2006 15:05 GMT
>I am having trouble working out how to make a two dimensional array work
>correctly. I have tried the code below, but keep getting a Type Mismatch. If I
[quoted text clipped - 32 lines]
> Next x
> End Sub

The code as posted doesn't compile. There are various things not to like, but
the critical items are:
1. If you are going to pass an array of strings (i.e. CDInfo), the parameter
should be declared as such in FindCDAtts. However, since it is a public
variable, there is no need to pass it at all.
2. Redim Preserve can only change the size of the last array dimension.
3. If you don't assign something to NumDrives, you won't get any message box
results.

Here is a version of your code with the changes needed to make it work:

Dim ItemSet As Object
Dim Item As Object
Dim CDInfo() As String
Dim NumDrives As Integer
Dim x As Integer

Public Sub FindCDAtts()
x = 0
Set ItemSet = GetObject("WinMgmts:").InstancesOf("Win32_CDRomDrive")
For Each Item In ItemSet
   x = x + 1
   ReDim Preserve CDInfo(2, 1 To x)
   CDInfo(1, x) = Item.Drive
   CDInfo(2, x) = Item.Caption
Next
NumDrives = x
Set ItemSet = Nothing
Set Item = Nothing
End Sub

Private Sub Command1_Click()
Call FindCDAtts
For x = 1 To NumDrives
MsgBox " Drive is " & CDInfo(1, x) & ", and caption is " & CDInfo(2, x)
Next x
End Sub
Randy Birch - 25 Jul 2006 23:40 GMT
In addition to Steve's comments, you can only redimension the last member of
an array. ReDim Preserve CDInfo(1 To x, 2) would have to be ReDim Preserve
CDInfo(2, 1 To x).  Not too that by specifying 2 as the first element, in
the absence of an Option Base statement or explicit lower bound declaration,
you are creating an array with three elements (0, 1, and 2).

Signature

Randy Birch
MS MVP Visual Basic
http://vbnet.mvps.org/

Please reply to the newsgroups so all can participate.

I am having trouble working out how to make a two dimensional array work
correctly. I have tried the code below, but keep getting a Type Mismatch. If
I simply assign simple variables to the Drive and Caption items, the code
works fine and I get the results I expect. Can someone please tell me where
the code is wrong? The Dim statements and the procedure are in a module,
while the command button is on a form.
Johnno.

Dim ItemSet As Object
Dim Item As Object
Dim CDInfo() As String
Dim NumDrives As Integer

Public Sub FindCDAtts(CDInfo(), NumDrives)
x = 0
Set ItemSet = GetObject("WinMgmts:").InstancesOf("Win32_CDRomDrive")
For Each Item In ItemSet
   x = x + 1
   ReDim Preserve CDInfo(1 To x, 2)
   CDInfo(x, 1) = Item.Drive
   CDInfo(x, 2) = Item.Caption
  ' info = info & Item.scsiport & ","
  ' info = info & Item.scsitargetid & ","
  ' info = info & Item.scsilogicalunit
  ' CDInfo(x, 2) = info
Next
Set ItemSet = Nothing
Set Item = Nothing
End Sub

Private Sub Command1_Click()
Call FindCDAtts(CDInfo(), NumDrives)
For x = 1 To NumDrives
MsgBox " Drive is " & CDInfo(x, 1) & ", and caption is " & CDInfo(x, 2)
Next x
End Sub
Johnno - 26 Jul 2006 04:58 GMT
Thanks for your help gentlemen. I now understand what you explained.
However, after trying Steves code, I couldn't get it to work. I believe it
is simply because the Dim statements and the procedure are in a module,
while the command button is on a form. I apologise if I didn't make that
clear before. When I placed all the code on a form, things worked perfectly.
So my new question is this - if the procedure in a module is public,  why is
the variable that is contained in it not then available to a command button
on a form?
Johnno.

> In addition to Steve's comments, you can only redimension the last member
> of
[quoted text clipped - 42 lines]
> Next x
> End Sub
J French - 26 Jul 2006 07:53 GMT
>Thanks for your help gentlemen. I now understand what you explained.
>However, after trying Steves code, I couldn't get it to work. I believe it
[quoted text clipped - 4 lines]
>the variable that is contained in it not then available to a command button
>on a form?

Short answer - because exposing variables within procedures would be
sheer madness.

Technical answer - because (usually) the variables are created on the
stack, they do not exist until the procedure is called

The variables within a procedure are called 'local variables'

Making a Procedure 'Public' means that it can be seen by code in other
Modules
Johnno - 27 Jul 2006 06:19 GMT
>>Thanks for your help gentlemen. I now understand what you explained.
>>However, after trying Steves code, I couldn't get it to work. I believe it
[quoted text clipped - 18 lines]
> Making a Procedure 'Public' means that it can be seen by code in other
> Modules

I did it again. I neglected to make myself clear. Sorry. I should have asked
how to make the variables available, given I am using a module in this case.
I have tried to pass the variable names, and am doing something wrong,
because I cannot make it work. I am fully aware that there are easier and
less cumbersome ways to achieve what I am trying; however if someone could
help me with this it would help clear up some of the confusion I obviously
have with declaration of multi dimensional variables. Would someone mind
posting the code changes needed to work this? I would appreciate it.
Johnno.
Mike Williams - 27 Jul 2006 07:07 GMT
> I did it again. I neglected to make myself clear. Sorry. I should
> have asked how to make the variables available . . .

As J French and others have already said you really should write your code
in a different way so as to avoid as much as possible using publicly
available variables. Such variables are "open to abuse" in that their
contents can be inadvertently changed by routines elsewhere in your project
that really have no need to "see" that variable at all. As they used to say
in the Army, "Information should be given out strictly on a 'need to know'
basis"! If a variable exposes its contents to every routine in your
application then you are inviting trouble as your program increases in size
and complexity.

Anyway, having said that, the reason your code as it stands is not working
is because your FindCDAtts routine is Public but your other variables in
that module are not. You have declared NumDrives (and the other three module
variables) in the declarations section of your module using the Dim
statement. Variables declared in  such a way are available to all procedures
*within the same module*. So, your FindCDAtts routine (and any other
routines you may have in the same code module) can "see" the NumDrives
variable (and can read and write to it) but routines outside that code
module cannot "see" it. So, your FindCDAtts routine is capable of setting
the value of NumDrives to (say) a value of 3 but your Command1 Click routine
in Form1 cannot "see" the NumDrives variable at all, and so it has no way of
finding out what value it contains. Does that make sense to you?

If you want all routines in all modules in your project (including your
Command1 Click routine in Form1) to be able to "see" the NumDrives variable
then you must declare it as Public:

Public NumDrives as Integer

As I've said, and as J French and others have said, using Public variables
in this way is not considered good practice, especially as there are other
ways of returning information from your FindCDAtts routine which avoid the
need for Public variables. However, the decision is of course up to you.

Mike
Johnno - 27 Jul 2006 09:23 GMT
Thanks Mike. Your post makes perfect sense. I now have a far better grasp of
things, and of course realise that my problem was not so much with the multi
dimensional variables, as with the scope of variables in general. As a
result of these posts,  I now have no intention of using the code in a
module, but the exercise taught me some valuable stuff. Cheers to all.
Johnno.

>> I did it again. I neglected to make myself clear. Sorry. I should
>> have asked how to make the variables available . . .
[quoted text clipped - 35 lines]
>
> Mike
J French - 27 Jul 2006 10:47 GMT
>Thanks Mike. Your post makes perfect sense. I now have a far better grasp of
>things, and of course realise that my problem was not so much with the multi
>dimensional variables, as with the scope of variables in general. As a
>result of these posts,  I now have no intention of using the code in a
>module, but the exercise taught me some valuable stuff. Cheers to all.
>Johnno.

Nice one !

It is always good to see someone seeing the light.

The next thing is to look into UserControls for getting graphical
fiddling out of the Form's code
- don't bother about OCXing them, just make them part of the project

After that, getting code out of .BAS modules and into Classes is very
interesting, it allows one to 'hide' code from the rest of the App

That 'Need to know' stuff Mike told you about, makes code a lot
tidier, robust and easier to maintain.

Here is a tip for Common (module level) variables
- sometimes you need them

Private Type TCMN
    UserName As String
    DataPath As String
    etc
End Type

Private cmn As TCMN

After that you get:   cmn.UserName

It makes it /very/ clear which variables a Module level
... and which are not
Johnno - 28 Jul 2006 03:59 GMT
Thanks for all the help. I'll no doubt be back soon with another head
scratcher!
Johnno.

>>Thanks Mike. Your post makes perfect sense. I now have a far better grasp
>>of
[quoted text clipped - 34 lines]
> It makes it /very/ clear which variables a Module level
> ... and which are not
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.