adbeentjes | zondag 20 december 2009 @ 14:33 | |
Om maar meteen te beginnen, het volgende probleem: Ik moet een algoritme (in Excel VBA) schrijven dat berekent hoeveel wisselgeld een kassier moet teruggeven aan een klant. Niet enkel het totaal terug te geven bedrag moet worden afgedrukt, maar het wisselgeld moet worden opgesplitst in de verschillende coupures (bijv. ¤634,33 = 1x500 + 0x200+ 1x100 +0x50 + 1x20 + 2x5+ 2x2+ 0x1+ 0x0,50 + 1x0,20 + 1x0,10 + 0x0,05 + 1x0.02+1x0,01) Ervan uitgaande: terug te geven bedrag kleiner is dan 1000 euro. Al wat uurtjes 'gespeeld' met VBA, maar helaas zonder resultaat. Wie helpt? Ad | ||
GlowMouse | zondag 20 december 2009 @ 14:33 | |
wat voor code heb je nu? | ||
adbeentjes | zondag 20 december 2009 @ 14:35 | |
quote:Iets en niets, heb wat getikt, maar kreeg een foutmelding, vandaag de post. | ||
HenryHill | zondag 20 december 2009 @ 14:39 | |
quote:Hoe ben je tot bovenstaande uitwerking gekomen? Was dit een gegeven voorbeeld of heb je dit zelf uitgewerkt? Immers, als je niet weet hoe je het probleem handmatig moet oplossen, dan hoef je al helemaal niet te proberen dit uit te leggen aan een computer ![]() | ||
adbeentjes | zondag 20 december 2009 @ 14:42 | |
quote:Zelf 'uitgewerkt' dat is de zogenaamde bottum-up techniek, in delen oplossen van een 'groot' probleem. De vraag zelf snap ik wel, maar hoe dat te vertalen in Excel... | ||
adbeentjes | zondag 20 december 2009 @ 14:44 | |
Idee Klant moet betalen, bijv. ¤80. Hij 'betaalt' met briefje van ¤100 Verschilfunctie 100-80=20 retour door kassier. 20 is 1x20 ivm rond getal... | ||
HenryHill | zondag 20 december 2009 @ 14:48 | |
quote:Ok, en nu als iemand met een briefje van 100 voor 64 euro wil afrekenen. Welke coupures krijgt de klant dan terug? | ||
Thorír | zondag 20 december 2009 @ 14:48 | |
Ken VB niet, dus hier wat pseudocode:
| ||
HenryHill | zondag 20 december 2009 @ 14:49 | |
quote:Lekker, vriend. In plaats dat je TS zelf na laat denken over zijn huiswerk | ||
adbeentjes | zondag 20 december 2009 @ 14:50 | |
quote:Ik kan wel wat aflezen, maar ik ken dat programma niet, en voor een beginner is het zowat onmogelijk om dit te begrijpen,,, heeft u dit ook 'gemaakt' met tabellen? Sequentie, iteratie etc.? | ||
adbeentjes | zondag 20 december 2009 @ 14:51 | |
quote:Op dezelfde wijze; 100-64=36 euro retour door kassier 36 euro = 1x20 1x10 1x5 1x1 euro.. | ||
Basp1 | zondag 20 december 2009 @ 14:52 | |
quote:Dan moet je bij de print [i] iets van row en en nog wat invoegen in die code | ||
adbeentjes | zondag 20 december 2009 @ 14:52 | |
quote:Ik snap het probleem wel, en hoe je het moet oplossen, maar ik snap niet hoe dit in kaart te brengen in Excel VBA, ik moet een algoritme schrijven, waarschijnlijk moet Excel dan 'het spelletje spelen' van de kassier, | ||
HenryHill | zondag 20 december 2009 @ 14:56 | |
quote:Ok, ben je met me eens dat de truc is om van het retourbedrag (in dit geval 36 euro) net zolang biljetten van 20 euro uit te betalen totdat je retourbedrag onder de 20 euro komt. Vervolgens ga je biljetten van 10 euro uitbetalen totdat het retourbedrag minder dan 10 euro is, etc. Toch? | ||
adbeentjes | zondag 20 december 2009 @ 14:59 | |
quote:Zeer zeker mee eens... steeds weer volgens hetzelfde stramien. | ||
HenryHill | zondag 20 december 2009 @ 15:00 | |
quote:Ok, hoe had je dit voorgesteld in Excel? Ik kan me voorstellen dat je twee cellen gebruikt, 1 voor het invullen van het te betalen bedrag en 1 voor hoeveel de klant geeft. Als uitvoer heb je dan een kolom met met onder elkaar de waardes van de coupures (500, 200, 100, etc.). De uitvoer van je programma komt dan in de kolom naast de coupures te staan. Om de coupures uit te laten rekenen moet je op een knop drukken, deze start jouw VBA-code. Zoiets? | ||
adbeentjes | zondag 20 december 2009 @ 15:03 | |
quote:Hier loop ik vast, ik weet niet hoé. Voorheen was het een code schrijven net als hierboven, in excel vba, .. | ||
HenryHill | zondag 20 december 2009 @ 15:05 | |
quote:Heb je in de vorige opdrachten wel eens cellen uit een Excel werkblad moeten lezen? Of pas je gewoon je programmacode aan als je met andere bedragen wilt werken? | ||
adbeentjes | zondag 20 december 2009 @ 15:07 | |
quote:Altijd gewoon via "Marco opnemen" uiteindelijk kan je dan als het ware zelf de 'code' achterhalen via VBA. Ik heb nu een kolom A1: te betalen A2: klant geeft Kan ik ook dit probleem oplossen via "Macro opnemen"? | ||
HenryHill | zondag 20 december 2009 @ 15:10 | |
quote:Ok, maar werd de invoer (in dit geval de bedragen) voor de vorige opdrachten ingelezen vanuit een werkblad, of werd de invoer ook in code gespecificeerd? quote:Ja hoor, doe maar zoals je 't gewend bent ![]() | ||
adbeentjes | zondag 20 december 2009 @ 15:12 | |
quote: Geen idee hoe dus... dit is een 'apart' geval, opdrachten komen ook van een apart stencil. Ik heb gewoon de code voor VBA nodig, dus dat er ook schermpje verschijnt van"U betaalt, en u geeft" etc. Alleen weet ik niet hoe ik dat voor mekaar krijg, of iemand me daarbij wilt helpen. Het probleem zelf snap ik wel. | ||
HenryHill | zondag 20 december 2009 @ 15:16 | |
quote:In welke versie van Excel werk je? (2003 of 2007, Nederlands of Engels?) | ||
adbeentjes | zondag 20 december 2009 @ 15:17 | |
quote:Ik gebruik voor VBA 2003 (ivm uitleg boek), heb ook 2007. Beide NL. | ||
HenryHill | zondag 20 december 2009 @ 15:23 | |
Ik heb zelf alleen 2007 tot m'n beschikking, dus het is misschien het handigst als je deze gebruikt. Probeer eens het volgende: 1. Ga naar het lint "Ontwikkelaars". Als je deze niet ziet, zoek dan in de Help (F1) het onderwerp "Macro's maken met Microsoft Visual Basic" en volg de daar omschreven stappen om VBA beschikbaar te maken. 2. Op het lint Ontwikkelaars, klik op "Invoegen" (binnen het onderdeel Besturingselementen) en selecteer de knop (linksboven). 3. Door met de muis te slepen, bepaal de plaats en afmeting van de knop. Op het moment dat je de muisknop loslaat, krijg je het scherm "Macro toewijzen aan object" te zien. Vul als macronaam "BepaalBedrag" in, en druk op de knop Nieuw. Je komt nu in de VBA editor terecht, in de subroutine BepaalBedrag:
| ||
adbeentjes | zondag 20 december 2009 @ 15:26 | |
quote:Tot hier GELUKT!, Doe nu ook in 2007. Ik kan nu een blokje, knopje 'tekenen', nietwaar>? | ||
HenryHill | zondag 20 december 2009 @ 15:27 | |
quote:Correct, zie boven ![]() | ||
adbeentjes | zondag 20 december 2009 @ 15:30 | |
quote:Gelukt, tot laatste stap, Sub BepaalBedrag() End Sub ![]() | ||
HenryHill | zondag 20 december 2009 @ 15:31 | |
Ok, vul nu als code het volgende in, gewoon om het geheel even te testen:
Probeer deze subroutine uit door twee getallen in de cellen A1 en A2 te zetten, en op de knop te drukken. De som moet dan in cel A3 weggeschreven worden. Werkt dit? | ||
adbeentjes | zondag 20 december 2009 @ 15:33 | |
Het volgende: 30 bij A1 ingevuld 20 Bij A2 ingevuld > Knop drukken 50 verschijnt in A3 | ||
Deetch | zondag 20 december 2009 @ 15:35 | |
Volgende keer dit soort vragen in: [EXCEL] Het grote Excel vragen topic, #17 Dit is em dacht ik, zelf nog even naar wens finetunen.
| ||
adbeentjes | zondag 20 december 2009 @ 15:37 | |
@Ditch: Daar snap ik al helemaal niets van, bovendien veeeeeeeels te lang. Ik wil het begrijpen... | ||
HenryHill | zondag 20 december 2009 @ 15:38 | |
quote:Very nice. Dan gaan we nu het werkblad opzetten voor de opdracht. Ik stel voor: A1 bevat de tekst "Te betalen" B1 wordt gebruikt om het te betalen bedrag in te zetten A2 bevat de tekst "Klant geeft" B2 wordt gebruikt om het gegeven bedrag in te zetten B3 bevat de knop die onze subroutine BepaalBedrag aanroept De cellen D1 t/m D14 bevatten de waarden van de coupures (500, 200, ... 0,01). De cellen E1 t/m E14 gaan het resultaat bevatten van onze code, nl. de aantallen coupures die moeten worden teruggegeven. | ||
adbeentjes | zondag 20 december 2009 @ 15:46 | |
quote:Done; Alleen heb ik 15 coupures: 500 200 100 50 20 10 5 2 1 0,5 0,2 0,1 0,05 0,02 0,01 | ||
HenryHill | zondag 20 december 2009 @ 15:48 | |
quote:Ok, prima, dan houd ik dezelfde coupures aan als jij. Gooi de inhoud van BepaalBedrag maar weg, en gebruik de volgende code (zelf aanvullen!)
| ||
adbeentjes | zondag 20 december 2009 @ 15:54 | |
1 2 3 4 5 Dim bedragTeBetalen, bedragGegeven, bedragRetour As Double Rem 1. Lees de 2 invoervelden en bepaal het bedrag retour bedragTeBetalen = Range("B1").Value Rem ...? wat zijn de REM voor instructies, soort formules? misschien klopt dit: Rem...? Rem 2. bedragGegeven ---> zie cel B2 Rem 3. bedragRetour = bedragGegeven - bedragTeBetalen ... zoiets? | ||
HenryHill | zondag 20 december 2009 @ 15:59 | |
quote:"Rem" is een afkorting van "Remark", een opmerking dus. Het vertelt de VBA interpreter dat hij de rest van de regel kan negeren. Het wordt gebruikt om in je code uit te leggen wat je aan het doen bent ![]() quote:Je moet de REM's alleen gebruiken bij commentaarregels, niet bij je code. Enne, " ---> zie cel B2": als je kijkt naar die ene regel die ik je cadeau heb gedaan, dan zie je hoe het moet ![]() Je derde regel is trouwens correct. | ||
adbeentjes | zondag 20 december 2009 @ 16:07 | |
Zo dus: Rem 1. Lees de 2 invoervelden en bepaal het bedrag retour. bedragTeBetalen = Range("B1").Value Rem 2. Lees getal wat ingevoerd is bij invoerveld KlantGeeft. bedragGegeven = Range("B2").Value Rem 3. bedragRetour = bedragGegeven - bedragTeBetalen ???? Weet niet of alles precies getikt is zoals Excel het wilt. ???? | ||
HenryHill | zondag 20 december 2009 @ 16:12 | |
quote:Ja, je moet alleen nog die "Rem 3." weghalen, dan klopt het. quote:Als je het fout doet, dan krijg je het meteen te horen van excel hoor. Ok, plak nu onderstaande code er maar bij (onder de regels die je nu hebt)
Als het goed is, krijg je nu 15 nullen onder elkaar als je de knop indrukt. | ||
adbeentjes | zondag 20 december 2009 @ 16:16 | |
Nee, Krijg een foutmelding. heb tot nu toe: Dim bedragTeBetalen, bedragGegeven, bedragRetour As Double Rem 1. Lees de 2 invoervelden en bepaal het bedrag retour. bedragTeBetalen = Range("B1").Value Rem 2. Lees getal wat ingevoerd is bij invoerveld KlantGeeft. bedragGegeven = Range("B2").Value bedragRetour = bedragGegeven - bedragTeBetalen Rem Loop nu over alle beschikbare coupures heen... Dim coupureIndex, coupureAantal As Integer Dim coupure As Double For coupureIndex = 1 To 15 Rem Lees het bedrag voor deze coupure in coupure = Range("D" & coupureIndex).Value Rem (Logica moet hierzo komen). coupureAantal = 0 Rem Schrijf het resultaat weg Range("E" & coupureIndex).Value = coupureAantal Next COMPILEERFOUT, B1 | ||
HenryHill | zondag 20 december 2009 @ 16:32 | |
quote:Hmm, vreemd, ik heb net jouw tekst in mijn ding geplakt en dan werkt het. Voor de zekerheid: je hebt dit tussen
staan? | ||
adbeentjes | zondag 20 december 2009 @ 16:34 | |
quote: Dat had ik dus niet, dacht dat alles weg moest, nu heb ik het er wel bij staan, en hij doet het: er verschijnen allemaal 0-en ![]() | ||
HenryHill | zondag 20 december 2009 @ 16:36 | |
quote:Ah, gelukkig maar ![]() Snap je ook wat de code doet, of zijn er dingen tot nu toe niet helemaal duidelijk? | ||
adbeentjes | zondag 20 december 2009 @ 16:39 | |
quote:Ik snap wel zo'n beetje wat de code doet. Uiteindleijk moet er een waarde staan ipv de 0 (of weer 0) als uitgerekend is hoeveel de klant terug moet krijgen, zoals het voorbeeld. | ||
HenryHill | zondag 20 december 2009 @ 16:42 | |
quote:Precies. Maar heb je bijvoorbeeld de constructie "For index = 1 to 15" / "Next" wel eens gezien? En snap je wat er gebeurt bij "D" & coupureIndex ? | ||
adbeentjes | zondag 20 december 2009 @ 16:50 | |
Snap niet alle functies, Ik weet wel dat we nog het een en ander moeten toevoegen, als ik bijv. Te betalen: 120 Klant geeft: 200 invul, en daarna op de knop druk, gebeurt er nog niets, blijven nullen staan, het verschil moet nu dus berekend worden, en dan nog verdelen onder de cor. | ||
HenryHill | zondag 20 december 2009 @ 16:56 | |
quote:Vooruit dan maar, 't is ook al een heel middagvullend programma geworden ;) Op de plek waar "Rem (Logica komt hier)." staat, plaats de volgende code:
N.B. Die "while" / "wend" constructie is een mogelijke oplossing. Een andere manier om op het maximum aantal coupures te komen is om het overgebleven bedrag te delen door de grootte van de coupure, en het resultaat naar beneden af te ronden. Probeer het eens uit, zou ik zeggen. | ||
adbeentjes | zondag 20 december 2009 @ 17:00 | |
Heb tot nu toe, zie hieronder, alleen doet 'ie het nog niet'. Sub BepaalBedrag() Dim bedragTeBetalen, bedragGegeven, bedragRetour As Double Rem 1. Lees de 2 invoervelden en bepaal het bedrag retour. bedragTeBetalen = Range("B1").Value Rem 2. Lees getal wat ingevoerd is bij invoerveld KlantGeeft. bedragGegeven = Range("B2").Value bedragRetour = bedragGegeven - bedragTeBetalen Rem Loop nu over alle beschikbare coupures heen... Dim coupureIndex, coupureAantal As Integer Dim coupure As Double For coupureIndex = 1 To 15 Rem Lees het bedrag voor deze coupure in coupure = Range("D" & coupureIndex).Value Rem Bepaal het maximaal aantal coupures dat we kunnen uitgeven zonder bedragRetour te overschrijden. coupureAantal = 0 While ((coupureAantal + 1) * coupure) <= bedragRetour coupureAantal = coupureAantal + 1 Wend Rem Trek het bedrag wat dit aantal coupures voorstelt af van het bedrag dat we nog uit moeten keren. bedragRetour = bedragRetour - (coupureAantal * coupure) coupureAantal = 0 Rem Schrijf het resultaat weg Range("E" & coupureIndex).Value = coupureAantal Next End Sub | ||
HenryHill | zondag 20 december 2009 @ 17:02 | |
quote:Lol, je moet de vetgedrukte regel weghalen. Anders is het logisch dat 'ie elke keer '0' wegschrijft... | ||
adbeentjes | zondag 20 december 2009 @ 17:06 | |
ff testen | ||
adbeentjes | zondag 20 december 2009 @ 17:10 | |
HOEZEE! HIJ WERKT! HenryHill --------> Super!Bedankt! ![]() | ||
HenryHill | zondag 20 december 2009 @ 17:13 | |
Haha, graag gedaan hoor ![]() Voor de volledigheid, dit is het resultaat:
| ||
SuperRembo | zondag 20 december 2009 @ 18:55 | |
't kan trouwens makkerlijk zonder VBA, gewoon met een paar formuletjes... | ||
Deetch | maandag 21 december 2009 @ 10:28 | |
Interessant maar hij klopt niet. Te betalen = 126.38 Ontvangen = 215.48 verschil = 89.10 macro zegt dat je 89.09 terug moet geven?
| ||
Deetch | maandag 21 december 2009 @ 11:01 | |
Deze werk wel. uitleg staat in de regels achter '
oh ja het informatie tekentje ![]() ![]() | ||
Basp1 | maandag 21 december 2009 @ 11:07 | |
quote:Zou het niet nog mooier zijn als je ipv de 0 to 14 loop even de lengte van de array bepaald en dan de for loop tot de lengte van de array laat lopen, dan kan de gebruiker in het geval van hyperinflatie ook nog makkelijk de briefjes van 1000, 2000, 5000 en 10.000 euro invoegen zonder dat deze de for while loop moet veranderen. ![]() | ||
ralfie | maandag 21 december 2009 @ 12:33 | |
zonder vba veeel makkelijker http://spreadsheets.google.com/ccc?key=0AqF4qrW2Q0b1dGx4UHBVR0tPRkRZUWxRdlcwOEY4Snc&hl=en Enige gekke is dat de rest() / mod() of hoe je het ook wil noemen met de decimalen een kleine afwijking heeft, waardoor je het terug te betalen bedrag met 0.1 cent moet verhogen anders geeft ie een cent te weinig terug... Is zowel in google als in excel, dus... | ||
Deetch | maandag 21 december 2009 @ 15:45 | |
dubbel | ||
Deetch | maandag 21 december 2009 @ 15:47 | |
quote:Vandaar ook het afronden elke keer naar 2 decimalen. Opdracht van TS was om een algoritme te schrijven. quote:vervang "For i = 1 To 14" door "For i = 1 To Ubound(myArray)" | ||
HenryHill | maandag 21 december 2009 @ 18:25 | |
quote:Dat is geen oplossing, dat is een workaround (en ik vermoed dat, naarmate het aantal iteraties van je algoritme toeneemt, je nog wel meer dan 1 cent kwijt zult raken) ![]() Het probleem is dat, voor getallen kleiner dan 1, floating point datatypes (waaronder Double) eigenlijk alleen combinaties van negatieve machten van 2 exact kunnen opslaan (getallen als 0.5, 0.75, 0.125, etc.). Voor alle andere gevallen wordt een benadering gebruikt, wat een kleine afrondingsfout tot gevolg heeft. Des te vaker je het resultaat van de vorige berekening gebruikt als input voor de volgende, des te groter wordt je afrondingsfout. Aangezien VBA niet voorziet in een Decimal of Money datatype (die dit probleem niet hebben), is de beste oplossing om gewoon alle getallen 100 keer zo groot te maken (en dus in centen te gaan rekenen). Zo vermijdt je ten alle tijden dat je een getal kleiner dan 1 ergens moet opslaan. |