simple 2 dimensional array problem
|
|
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
|
|
|