Multidesk.be » Forums » Programmeren algemeen » VBA: Array dimensioneren adhv gebruikersinput

  • Pagina
  • [1]
  • 2
0 gasten lezen dit onderwerp.
^ Onderwerp geschreven door StOosh op zaterdag 12 januari 2013 om 18:04:35.
StOosh's avatar
Multiviteit: 1526
Ik probeer een array te dimensioneren aan de hand van gebruikersinput. Door eerst te vragen hoeveel gegevens de gebruiker wil ingeven. Zodat ik een Array op maat kan dimensioneren.

Met mijn geschreven code lukt dit echter niet omdat VBA een constante verwacht als dimensie. Hoe kan ik dit wel doen?

CODE
  1. Option Explicit
  2. Option Base 1
  3.  
  4. Sub ArrayVariabele()        'Array maken met een dimensie gedefinieerd door een variabele
  5.     Dim IntN As Integer
  6.     Dim IntM As Integer
  7.    
  8.     Call ArraySize(IntN)  'Vragen hoe groot de array moet zijn
  9.    
  10.     Const Size = IntN         'De constante definieren om de arraysize vast te kunnen leggen
  11.    
  12.     Dim IntArray(Size) As Integer   'array definieren
  13.    
  14.     Call ArrayFill(IntArray, IntM, Size)   'array random invullen
  15.    
  16.     Call ArrayToWorksheet(IntArray, IntM, Size)   'array schrijven in werkblad
  17.    
  18.    
  19. End Sub
  20.  
  21.  
  22. Sub ArraySize(ByRef Size As Integer)
  23.     Size = InputBox("Hoe groot moet de array zijn? (1-25) ")
  24. End Sub
  25.  
  26.  
  27. Sub ArrayFill(IntArray() As Integer, ByVal M As Integer, L)
  28.     For M = 1 To L Step 1
  29.         Randomize
  30.         IntArray(M) = 100 * Rnd()
  31.     Next M
  32. End Sub
  33.  
  34.  
  35. Sub ArrayToWorksheet(IntArray() As Integer, ByVal M As Integer, L)
  36.     For M = 1 To L Step 1
  37.         Cells(1, M).Value = IntArray(M)
  38.     Next M
  39. End Sub
  40.  
  41.  
^ Reactie #1 geschreven door DTC op zondag 13 januari 2013 om 02:57:01.
DTC's avatar
Multiviteit: 87
Je kan ReDim gebruiken om de size van je array dynamisch te definiëren.

CODE
  1. Dim IntArray() As Integer
  2. ReDim IntArray(Size) 'array definieren


en in jouw geval zou zelfs onmiddellijk ReDim gebruiken ook moeten werken:

CODE
  1. ReDim IntArray(Size) As Integer 'array definieren
^ Reactie #2 geschreven door StOosh op zondag 13 januari 2013 om 09:13:42.
StOosh's avatar
Multiviteit: 1526
Nee dat werkt niet bij mij. :/

CODE
  1. Sub ArrayVariabele()        'Array maken met een dimensie gedefinieerd door een variabele
  2.     Dim IntN As Integer
  3.     Dim IntM As Integer
  4.     Dim Size As Integer
  5.    
  6.    
  7.     Size = ArraySize(IntN)  'Vragen hoe groot de array moet zijn via een functie en constante maken
  8.    
  9.     ReDim IntArray(Size)   'array definieren
  10.    
  11.     Call ArrayFill(IntArray(), IntM, Size)   'array random invullen
  12.    
  13.     Call ArrayToWorksheet(IntArray(), IntM, Size)   'array schrijven in werkblad
  14.  


Geeft dan een fout bij de call ArrayFill. "Type mismatch: array or user-defined type expected"
^ Reactie #3 geschreven door thekid op zondag 13 januari 2013 om 10:27:37.
thekid's avatar
Multiviteit: 5273
Moderator
Stoosh, constante maken? constant is net gedefineerd om constant te zijn, over het ganse programma en kan niet veranderd worden

je kan wel een globale variable maken :)

in uw bovenstaand voorbeeld ontbreekt je array declaratie, 1st dim'en en dan redim'n :)

in je eerste voorbeeld zou ik ook de Randomize functie geen M aantal keer zich laten herhalen (1x is genoeg om vanaf dan een nieuwe random generator te hebben)

moet je overigens werken met een array? je kan ook direct het rnd generator nr toewijzen aan de cell?

volgens de logica van je programma schrijf je ook Size aantal keer dezelfde row neer (dus steeds dezelfde random value per row/kolom)?

Zit er ook een reden in waarom je uw for values meegeeft in de functie variabele? De size kan ik verstaan, maar de For iterator totaal niet :)
Deze tekst werd het laatst bewerkt voor 51.3 % door thekid op zondag 13 januari 2013 om 10:41:03.
"Human beings make life so interesting. Do you know, that in a universe so full of wonders, they have managed to invent boredom." - Death in Hogfather
^ Reactie #4 geschreven door DTC op zondag 13 januari 2013 om 11:33:11.
DTC's avatar
Multiviteit: 87
Je hebt As Integer niet gebruikt. Als je onmiddellijk ReDim wilt gebruikt moet je ook het type meegeven. Anders weet de compiler niet wat voor soort variabele je declareert.

CODE
  1. ReDim IntArray(Size)


moet dus dit zijn:

CODE
  1. ReDim IntArray(Size) As Integer


Op deze methode is die eerste Dim niet meer nodig.
Belangrijk: Dit werkt enkel voor lokale variabelen.
Deze tekst werd het laatst bewerkt voor 0.13 % door DTC op zondag 13 januari 2013 om 11:38:35.
^ Reactie #5 geschreven door StOosh op zondag 13 januari 2013 om 11:34:31.
StOosh's avatar
Multiviteit: 1526
Ik weet dat een constante bedoeld is om constant te zijn, maar ik wil de array op de exacte grootte van de in te geven data door de gebruiker dimensioneren. Daarom wil ik de gebruiker die constante in het begin zelf laten bepalen.
Ik dacht dat globale variabelen niet aangeraden waren (ivm veiligheid enzo..)

Ik heb gezien dat ik die declaratie ben vergeten, dat is nu aangepast, ook heb ik bij de arrays in de paramaters bij het oproepen van de subroutines hun haakjes gegeven om aan te duiden dat het wel degelijk arrays zijn. (of dit noodzakelijk is voor de werking weet ik niet, maar in de cursus wordt een array zo doorgegeven in de voorbeelden).

Ik heb tevens de randomize functie buiten de For geplaatst. Het is inderdaad logisch dat dit niet elke keer hoeft herhaalt te worden. :)

Waarom ik niet onmiddelijk een 'rnd generator toewijzen aan de cell' : Ik heb opzettelijk het programma onderverdeelt in drie grote subroutines om vaardigheid met die subroutines op te bouwen. Er wordt van ons verwacht dat we een programma een beetje logisch opdelen in blokken zodat we leren duidelijkheid te scheppen in de spaghetti... Maar inderdaad, het maakt de code misschien iets minder efficient als je dat bedoelt. :)

Ik vul die kolom random in om de gebruikersinput stap over te slaan. (Anders moet ik telkens opnieuw die gegevens invoeren met een inputbox :p) En nu is dat voor mij geautomatiseerd naar een honderdtal dat door de rnd-functie wordt ingevuld.

Die for-iterator heeft inderdaad geen enkele zin, das wat ondoordacht zodat ik maar eéénmal moest dimensioneren om me dat werk te besparen. Maar uiteindelijk blijkt dat toch een nul-operatie omdat ik ze telkens moet typen als variabelen die ik meeneem. :p
Ik had die ook gebruikt om die byref en byval te leren. Door het te gebruiken leer je dat sneller dan door gewoon een keer te lezen in een stukje code ;)

Opmerking: deze code heeft niet echt een nut. Het is gewoon een algemeen dingetje dat ik bedacht heb om uit te zoeken hoe ik die arraydimensie door de gebruiker kan laten definieren. :)

Dit is wat ik aangepast heb:

CODE
  1.  
  2. Option Explicit
  3. Option Base 1
  4.  
  5. Sub ArrayVariabele()        'Array maken met een dimensie gedefinieerd door een variabele
  6.     Dim IntN As Integer
  7.     Dim Size As Integer
  8.     Dim IntArray() As Integer
  9.    
  10.    
  11.     Size = ArraySize(IntN)  'Vragen hoe groot de array moet zijn via een functie en constante maken
  12.    
  13.     ReDim IntArray(Size) As Integer   'array definieren
  14.    
  15.     Call ArrayFill(IntArray(), Size)   'array random invullen
  16.    
  17.     Call ArrayToWorksheet(IntArray(), Size)   'array schrijven in werkblad
  18. End Sub
  19.  
  20.  
  21. Function ArraySize(ByRef Size As Integer)
  22.     Size = InputBox("Hoe groot moet de array zijn? (1-25) ")
  23. End Function
  24.  
  25. 'array automatisch invullen door computer, zodat ik het zelf niet moet doen.
  26. Sub ArrayFill(IntArray() As Integer, Size)
  27.     Dim M As Integer
  28.    
  29.     Randomize
  30.     For M = 1 To Size Step 1
  31.         IntArray(M) = 100 * Rnd()
  32.     Next M
  33. End Sub
  34.  
  35.  
  36. Sub ArrayToWorksheet(IntArray() As Integer, Size)
  37.     Dim M As Integer
  38.    
  39.     For M = 1 To Size Step 1
  40.         Cells(1, M).Value = IntArray(M)
  41.     Next M
  42. End Sub
  43.  
  44.  
  45.  



Als ik dit nu uitvoer, wordt ArraySize uitgevoerd. Maar de Redim geeft volgende fout: 'subscript out of range'
Deze tekst werd het laatst bewerkt voor 1.68 % door StOosh op zondag 13 januari 2013 om 11:39:06.
^ Reactie #6 geschreven door StOosh op zondag 13 januari 2013 om 11:52:12.
StOosh's avatar
Multiviteit: 1526
DTC, ik heb dit aangepast in de code. De eerste foutmelding is weg, maar nu geeft hij als fout 'subscript out of range'

Ik had geprobeerd om op de functie ArraySize een Cint te gebruiken zodat ik zeker ben dat er een integer in Size geplaatst wordt, maar dat veranderd niets.

CODE
  1. Size = CInt(ArraySize(IntN))
^ Reactie #7 geschreven door thekid op zondag 13 januari 2013 om 11:55:31.
thekid's avatar
Multiviteit: 5273
Moderator
een function, moet een return value hebben :)

CODE
  1. Function ArraySize()
  2.     ArraySize = CInt(InputBox("Hoe groot moet de array zijn? (1-25) "))
  3. End Function

bij vbscript is de return value enkel de functienaam toewijzen met de gewenste waarde

hier heb je nog een byref nodig
CODE
  1. Sub ArrayFill(ByRef IntArray() As Integer, ByVal Size as Integer)
  2.     Dim M As Integer
  3.    
  4.     Randomize
  5.     For M = 1 To Size Step 1
  6.         IntArray(M) = 100 * Rnd()
  7.     Next M
  8. End Sub


en blijf ik bij de opmerking, dat iedere rij dezelfde array van random getallen zal toegewezen krijgen :)
Deze tekst werd het laatst bewerkt voor 18.67 % door thekid op zondag 13 januari 2013 om 11:58:05.
"Human beings make life so interesting. Do you know, that in a universe so full of wonders, they have managed to invent boredom." - Death in Hogfather
^ Reactie #8 geschreven door DTC op zondag 13 januari 2013 om 12:03:19.
DTC's avatar
Multiviteit: 87
Die Dim IntArray() As Integer kan je weg laten.

Of te wel doe je:

CODE
  1.  
  2. Dim IntArray() As Integer
  3. ReDim IntArray(Size)
  4.  


of dit:

CODE
  1. ReDim IntArray(Size) As Integer
^ Reactie #9 geschreven door DTC op zondag 13 januari 2013 om 12:04:34.
DTC's avatar
Multiviteit: 87
Dus volledig:

CODE
  1.  
  2. Option Explicit
  3. Option Base 1
  4.  
  5. Sub ArrayVariabele()        'Array maken met een dimensie gedefinieerd door een variabele
  6.     Dim Size As Integer
  7.     Dim IntArray() As Integer
  8.      
  9.     Size = ArraySize()  'Vragen hoe groot de array moet zijn via een functie en constante maken
  10.    
  11.     ReDim IntArray(Size) As Integer   'array definieren
  12.    
  13.     Call ArrayFill(IntArray(), Size)   'array random invullen
  14.    
  15.     Call ArrayToWorksheet(IntArray(), Size)   'array schrijven in werkblad
  16. End Sub
  17.  
  18. Function ArraySize() As Integer
  19.     ArraySize = InputBox("Hoe groot moet de array zijn? (1-25) ")
  20. End Function
  21.  
  22. 'array automatisch invullen door computer, zodat ik het zelf niet moet doen.
  23. Sub ArrayFill(IntArray() As Integer, Size)
  24.     Dim M As Integer
  25.    
  26.     For M = 1 To Size Step 1
  27.         Randomize
  28.         IntArray(M) = 100 * Rnd()
  29.     Next M
  30. End Sub
  31.  
  32.  
  33. Sub ArrayToWorksheet(IntArray() As Integer, Size)
  34.     Dim M As Integer
  35.    
  36.     For M = 1 To Size Step 1
  37.         Cells(1, M).Value = IntArray(M)
  38.     Next M
  39. End Sub


Maar zoals TheKid zegt er klopt inderdaad iets niet met die Random.

*Edit
Ik heb je random functie aangepast en Randomize mee in de For-Loop geplaatst.
Deze tekst werd het laatst bewerkt voor 1.71 % door DTC op zondag 13 januari 2013 om 12:10:50.
^ Reactie #10 geschreven door thekid op zondag 13 januari 2013 om 12:10:36.
thekid's avatar
Multiviteit: 5273
Moderator
ps: je vergeet ook de byref bij de ArrayFill DTC ;)

voor verschillende random lijnen:
- of je werkt met een multidimensionele array
- je roept bij het invullen van het blad voor iedere loop de arrayfill functie op
- je werkt met een size * size grootte array (waar je dan manueel je row/kolom kunt uithalen)

DTC, randomize initialiseert de random generator. Die moet je in theorie maar 1x oproepen :)
Deze tekst werd het laatst bewerkt voor 77.83 % door thekid op zondag 13 januari 2013 om 12:14:26.
"Human beings make life so interesting. Do you know, that in a universe so full of wonders, they have managed to invent boredom." - Death in Hogfather
^ Reactie #11 geschreven door DTC op zondag 13 januari 2013 om 12:18:50.
DTC's avatar
Multiviteit: 87
Thx, wist ik niet van die randomize . Ik gebruik eerder:

CODE
  1. Random random = new Random();
  2. int randomNumber = random.Next(...);


Maar ja dat is dan ook voor .net bedoelt :P.
Deze tekst werd het laatst bewerkt voor 3.58 % door DTC op zondag 13 januari 2013 om 12:19:10.
^ Reactie #12 geschreven door DTC op zondag 13 januari 2013 om 12:29:18.
DTC's avatar
Multiviteit: 87
Zo hopelijk is dit correct nu ;):

CODE
  1.  
  2. Option Explicit
  3. Option Base 1
  4.  
  5. Sub ArrayVariabele()        'Array maken met een dimensie gedefinieerd door een variabele
  6.     Dim Size As Integer
  7.      
  8.     Size = ArraySize()  'Vragen hoe groot de array moet zijn via een functie en constante maken
  9.    
  10.     ReDim IntArray(Size) As Integer   'array definieren
  11.    
  12.     Call ArrayFill(IntArray(), Size)   'array random invullen
  13.    
  14.     Call ArrayToWorksheet(IntArray(), Size)   'array schrijven in werkblad
  15. End Sub
  16.  
  17. Function ArraySize() As Integer
  18.     ArraySize = InputBox("Hoe groot moet de array zijn? (1-25) ")
  19. End Function
  20.  
  21. 'array automatisch invullen door computer, zodat ik het zelf niet moet doen.
  22. Sub ArrayFill(ByRef IntArray() As Integer, Size)
  23.     Dim M As Integer
  24.    
  25.     For M = 1 To Size Step 1
  26.         IntArray(M) = 100 * Rnd()
  27.     Next M
  28. End Sub
  29.  
  30.  
  31. Sub ArrayToWorksheet(IntArray() As Integer, Size)
  32.     Dim M As Integer
  33.    
  34.     For M = 1 To Size Step 1
  35.         Cells(1, M).Value = IntArray(M)
  36.     Next M
  37. End Sub
  38.  


Bij mij werkt het in ieder geval.
^ Reactie #13 geschreven door StOosh op zondag 13 januari 2013 om 12:33:07.
StOosh's avatar
Multiviteit: 1526
Inderdaad, in die functie had ik een fout gemaakt met die terugkeerwaarde. Nu werkt het.

Dixit

en blijf ik bij de opmerking, dat iedere rij dezelfde array van random getallen zal toegewezen krijgen

Eerlijk waar, ik begrijp gewoon niet wat je bedoelt. :s

Dankjewel DTC, ik heb bij de Redim de 'As Integer' weggelaten :)
^ Reactie #14 geschreven door thekid op zondag 13 januari 2013 om 12:35:35.
thekid's avatar
Multiviteit: 5273
Moderator
Bijna, de randomize functie zit er nu niet meer in (en zal dus iedere keer in hetzelfde werkblad, dezelfde random values oproepen)

@Stoosh:
achnee,

ik zag het mis :D

ik dacht eerst dat je ook rijen invulde :)
Deze tekst werd het laatst bewerkt voor 25.29 % door thekid op zondag 13 januari 2013 om 12:40:27.
"Human beings make life so interesting. Do you know, that in a universe so full of wonders, they have managed to invent boredom." - Death in Hogfather
^ Reactie #15 geschreven door DTC op zondag 13 januari 2013 om 12:44:03.
DTC's avatar
Multiviteit: 87
Ben ook niet echt mee met wat je bedoelt.
Ik heb de code uitgetest en ik krijg telkens andere getallen zelfs zonder die randomize.
^ Reactie #16 geschreven door thekid op zondag 13 januari 2013 om 12:48:41.
thekid's avatar
Multiviteit: 5273
Moderator
Ja, heb mij al aangepast, ik zag het eerst verkeerd, was pas bij de laatste controle dat ik het anders zag :)

voor de randomize:
http://ns7.webmasters.com/caspdoc/html/vbscript_randomize_statement.htm

alhoewel de note en de remarks zich wat lijken tegen te spreken :d
"Human beings make life so interesting. Do you know, that in a universe so full of wonders, they have managed to invent boredom." - Death in Hogfather
^ Reactie #17 geschreven door StOosh op zondag 13 januari 2013 om 12:50:37.
StOosh's avatar
Multiviteit: 1526
Ik denk dat je je die array fout voorstelt. (Hoewel dat me sterk lijkt met jouw ervaring ;) )

Die array is ééndimensionaal en het aantal elementen dat in die array kan worden opgeslagen wordt via de ArraySize door de gebruiker ingegeven.
Vervolgens worden door ArrayFill in die arrayplaatsen data ingegeven door de gebruiker. (In dit geval laat ik ieder arrayelement random invullen door de computer).

Wanneer ik nu die array ga schrijven naar mijn werkblad, neem ik via de For lus ieder element van die array apart en schrijf die naar een aangrenzende cell aan het vorige weggeschreven arrayelement. (In dit geval gebeurt dit horizontaal)

Ik krijg dus Size plaatsen in de array die ik kan invullen. Deze krijgen elk een andere waarde (100 * random getal tussen 0 en 1 ) en die worden elk op het werkblad in horizontaal aangrenzende cellen geplaatst.
Het resultaat is een horizontale rij met waarden.

*edit: opgelost dus :)

@DTC: Microsoft VBA Help zegt het volgende:

Dixit

The Rnd function returns a value less than 1 but greater than or equal to zero.

The value of number determines how Rnd generates a random number:

For any given initial seed, the same number sequence is generated because each successive call to the Rnd function uses the previous number as a seed for the next number in the sequence.

Before calling Rnd, use the Randomize statement without an argument to initialize the random-number generator with a seed based on the system timer.

To produce random integers in a given range, use this formula:
Int((upperbound - lowerbound + 1) * Rnd + lowerbound)

Deze tekst werd het laatst bewerkt voor 27.93 % door StOosh op zondag 13 januari 2013 om 12:55:13.
^ Reactie #18 geschreven door thekid op zondag 13 januari 2013 om 12:53:00.
thekid's avatar
Multiviteit: 5273
Moderator
Ja inderdaad, ik had het miszien :)

was nog vroeg toen ik er deze morgen na keek, nu na 3 koffies was het al wat beter :D

je kan eens als volgende een driehoek van pascal creeer met een variabel aantal rijen :) is steeds een goeie oefening :D
"Human beings make life so interesting. Do you know, that in a universe so full of wonders, they have managed to invent boredom." - Death in Hogfather
^ Reactie #19 geschreven door StOosh op zondag 13 januari 2013 om 12:59:31.
StOosh's avatar
Multiviteit: 1526
Bedankt voor de hulp allebei. :)

Wat betreft arrays wordt van ons niet verwacht meer te kennen dan ééndimensionale arrays.
Maar het lijkt me wel een leuke uitdaging om die driehoek van Pascal eens te proberen.
  • Pagina
  • [1]
  • 2

Snel-antwoordformulier
Toon uitgebreid antwoordformulier Bericht nalezen Bericht plaatsen