MOD in Excel en VBA

Status
Niet open voor verdere reacties.

snb

Verenigingslid
Lid geworden
12 jun 2008
Berichten
19.728
Dag allen.

In VBA kun je met de modulo (Mod) niet het decimale deel van een getal krijgen.
Dat kan in Excel wel

PHP:
=MOD(12,345;1)

Dan ligt de verleiding op de loer om in VBA de Excel-funktie te gebruiken.

Daar zijn in principe 2 methodes voor:
- het gebruik van Evaluate (in 2 gedaanten)
- het gebruik van de worksheetfunction (in 3 gedaanten; zie onder)

Nu bljkt dat de Excelfunktie MOD niet met de Worksheetfunction te kunnen worden opgeroepen.
Heeft iemand daarvoor een verklaring ?

Hieronder de mogelijkheden die ik heb onderzocht.

Code:
Sub M_snb()
    MsgBox 12.345 Mod 1                            '  levert altijd 0
    MsgBox [mod(12.345,1)]                        '  het decimale resultaat
    MsgBox Evaluate("mod(12.345,1)")          '  het decimale resultaat
    
    MsgBox Application.Min(12.345, 1)          '  vlekkelings
    
    MsgBox Application.WorksheetFunction.mod(12.345, 1)   '  funktioneert niet
    MsgBox WorksheetFunction.mod(12.345, 1)                  '  funktioneert niet
    MsgBox Application.mod(12.345, 1)                             '  funktioneert niet
End Sub
 
In VBA (en de meeste andere programmeertalen) is modulorekening een operator en geen functie. Dat verklaart waarom je er geen worksheetfunction van kunt maken.

Dan het volgende issue: modulo met een decimaal. Modulo is wiskundig gezien eigenlijk helemaal niet gemaakt voor non-integer values. Wat VBA dus (eigenlijk best wel terecht) doet is het afronden naar beneden vóórdat de modulo gebeurt.
Voorbeelden: 9.5 mod 4 = 1, en 9 mod 4.5 = 1. Terwijl je eigenlijk 1.5 en 0 zou verwachten als je de Excelfunctie zou gebruiken. In beide gevallen doet VBA dus 9 mod 4, en dat is inderdaad 1.

De echte vraag is waarom de andere twee wél werken. Ook dat is verklaarbaar: de Excelfunctie MOD doet niet veel anders dan 'rest na deling' (daarom heet het in het Nederlands ook 'REST' ipv MOD). Je noemt het modulo, maar dat is het niet helemaal.
MOD(A,B) = A-floor(A/B)*B. In het geval van A=12.345 en B=1 krijgen we dus MOD(A,B)=12.345-floor(12.345/1)*1 = 12.345-12*1 = 0.345.

Je gebruikt in deze twee gevallen VBA om de Excel functie aan te roepen in plaats van de VBA operator. :)
 
Als ik in de bibliotheek van klasse Worksheetfunction kijk is Mod hier geen onderdeel van.
 
@Zig

Dank.

Duidelijk verhaal.
Taal is flexibeler dan de realiteit: homoniemen <> identieke verschijnselen.

@Sjon

Dank voor je reaktie.
Dat lijkt me echter niet echt een 'verklaring', maar een bevestiging van wat ik schreef.
Het ging mij meer om de achtergrond.

Mijn benadering in VBA wordt dus:

Code:
Sub M_snb()
   MsgBox 12.345 - Fix(12.345)
End Sub
 
Laatst bewerkt:
Mijn benadering in VBA wordt dus:

Code:
Sub M_snb()
   MsgBox 12.345 - Fix(12.345)
End Sub

Dat is niet zo triviaal en hangt af van wat je wil dat het gedrag wordt bij negatieve getallen. Je alternatief is Int() - of floor als worksheetfunction - maar dan krijg je dus andere uitkomsten bij negatieve getallen.

Concreet is de vraag of je in deze setting -6.46 beschouwt als -6-0.46 of als -7+0.54.
 
Nu blijkt dat de Excelfunktie MOD niet met de Worksheetfunction te kunnen worden opgeroepen.
Heeft iemand daarvoor een verklaring ?

lijkt mij dus een aardige verklaring :)
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan