Toevoegen van code via een macro.

Status
Niet open voor verdere reacties.

MDN111

Gebruiker
Lid geworden
13 aug 2007
Berichten
503
Hallo !

Op de website http://www.cpearson.com/Excel/VBE.aspx heb ik een interessant stukje code gevonden om programmatisch een procedure aan een module toe te voegen. Die topic heet “Adding A Procedure To A Module”.

Ik heb die code op drie plaatsen een beetje aangepast zodat ze een parameter kan ontvangen. Als ik die code test, dan werkt dat perfect. Tot hier alles OK.

De bedoeling die ik heb is de volgende: Er is een sheet met een variabel aantal command buttons. Die zijn programmatisch toegevoegd, zodat er geen event procedures in de code van de sheet staan. Ik wens nu een macro te hebben die voor alle command buttons, waarvan het woord “Button” in de naam zit, de gepaste code toevoegt bij de code van de betreffende sheet. Die macro heet AddCodeForTheButtons()

Als ik dat test, loop het volledig fout. Als de procedure AddProcedureToModule() eenmalig wordt aangeroepen werkt het zonder problemen, maar als ik ze aanroep vanuit een lus, dan gaat het fout. Er is een totale blokkage van Excel. Ter info: Het gaat over Excel 2002 met VBA 6.3.

Iemand inspiratie ?

Grtz,
MDN111
 

Bijlagen

  • Test.xls
    33 KB · Weergaven: 33
Laatst bewerkt:
Het lijkt me eenvoudiger déze code te gebruiken die in 3 regels exact hetzelfde doet, als de (onnodig gecompliceerde) code die je van internet plukte. (Verwijder wel eerst option Explicit uit alle modules).

Code:
Sub naardeknoppen()
  For Each oObj In ActiveSheet.OLEObjects
    If InStr(oObj.Name, "Button") > 0 Then ActiveWorkbook.VBProject.VBComponents("Sheet1").CodeModule.AddFromString "Private Sub " & oObj.Name & "_Click()" & vbCr & " MsgBox " & Chr(34) & oObj.Name & " is aangeklikt" & Chr(34) & vbCr & "End Sub"
  Next
End Sub
 
Laatst bewerkt:
Hallo SNB !

Dat is werkelijk een geweldig stukje code. Zoals steeds ligt de ware schoonheid in de eenvoud der dingen. Maar…., het is niet allemaal rozengeur en maneschijn.

Na het lezen van de code in je reactie ben ik vol enthousiasme in gang geschoten. Omdat ik in het bestandje Test.xls alleen het relevante had laten staan, heb ik nu je macro Naardeknoppen geïntegreerd in mijn VBA project. Dat bleek eerst perfect te werken, maar na een aanpassing, die ik niet echt ingrijpend vind, gaat het weer mis. Na een boel trial and error ben ik tot de volgende situatie gekomen:

Ik heb je macro Naardeknoppen iets aangepast. Als ik hem gebruik in Test1.xls dan werkt alles normaal. Als ik hem echter gebruik in B4Test.xls dat gaat het fout. Ik heb totaal geen idee wat er mis is. In beide gevallen wordt Naardeknoppen aangeroepen op het moment dat er een deel knoppen in de sheet staan. Alleen de methode om die knoppen toe te voegen is anders, maar dat mag toch geen invloed hebben? Ik zie het even niet meer zitten….

Groeten,
MDN111.
 

Bijlagen

  • Test1.zip
    54,4 KB · Weergaven: 19
Laatst bewerkt:
Dit is voldoende voor jouw module:

Code:
Sub start()
  ActiveSheet.Unprotect

  With Application.FileSearch
    .LookIn = ThisWorkbook.Path
    .Filename = "*.xls"
    Application.Caption = .Execute & " document(en) gevonden."
    For i = 1 To .FoundFiles.Count
      Sheet3.Cells(8 + i, 1) = Dir(.FoundFiles(i))
      With Sheet3
        For j = 1 To 3
          With .OLEObjects.Add("Forms.CommandButton.1", , , , , , , Sheet3.Columns(4).Left + Choose(j, 1, 50, 100), .Rows(8 + i).Top, 40, .Rows(8 + i).Height)
            .Name = Choose(j, "CopyButton", "OpenButton", "ClipButton") & (8 + i)
            With .Object
              .Caption = Choose(j, "Copy", "Open", "Clip")
              .Font.Size = 9
              .ForeColor = vbBlue
            End With
          End With
        Next
      End With
    Next
  End With

  NaarDeKnoppen
  ActiveSheet.Protect
End Sub

Code:
Sub CopyThisFile(ByVal nRow As Integer)
  MsgBox "CopyThisFile on Row " & nRow
End Sub

Code:
Sub OpenThisFile(ByVal nRow As Integer)
  MsgBox "OpenThisFile on Row " & nRow
End Sub

Code:
Sub ClipThisFile(ByVal nRow As Integer)
  MsgBox "ClipThisFile on Row " & nRow
End Sub

Code:
Sub NaarDeKnoppen()
  For Each oObj In Sheet3.OLEObjects
    If InStr("CopyButton*OpenButton*ClipButton", Left(oObj.Name, 10)) > 0 Then ActiveWorkbook.VBProject.VBComponents("Sheet3").CodeModule.AddFromString "Private Sub " & oObj.Name & "_Click()" & vbCr & Replace(oObj.Name, "Button", "ThisFile ") & vbCr & "End Sub"
  Next
End Sub
 
Hallo SNB !

Ja, dat is werkelijk een prachtig stukje code. Daar word ik gewoon stil van !

Je zal van mij even niet horen want dat moet ik zeker eens rustig gaan analyseren. Uiterst leerzaam. Ik ben er van overtuigd dat het zal werken. Zeer hartelijk bedankt !!!

Er ligt toch nog een vraagje op mijn lever. Het is natuurlijk plezant als men een kant en klare oplossing aangereikt krijgt, maar ik blijf toch met de vraag zitten waarom de ene code het wel doet en de andere niet. Niettegenstaande mijn code eerder amateuristisch uitvalt, zitten er toch geen echte fouten in (denk ik althans). Het is niet omdat een bepaalde code ingewikkelder geschreven is dat ze moet falen. Daarom is het een beetje vervelend als men de oorzaak niet kent.

Groeten,
MDN111.
 
Laatst bewerkt:
Als je jouw code stap voor stap vergelijkt met mijn suggestie (want dat heb ik ook met jouw code gedaan om een alternatief te kunnen maken) kom je er, denk ik, vanzelf achter.
2 belangrijke verschillen: ik gebruik zomin mogelijk variabelen; in de totale code 3 (i,j en oObj).
Het andere verschil is, dat als een code slechts eenmaal wordt gebruikt in een bepaald proces ik er geen aparte module of funktie van maak. Het doorgeven van argumenten is dan ook niet nodig.
Het leidt tot compactere code, die je weliswaar langzamer moet lezen om te begrijpen maar die van boven naar onder het gehele proces beslaat en daardoor gemakkelijker te volgen is (vind ik tenminste). Het opsporen van fouten is dan ook wat gemakkeljker.
Bovendien: met het real-time aanpassen van VBA-modules zitten we allang niet meer op nivo 2 van de beginnende VBA-gebruiker.
Tenslotte: de toevoeging van 3 knoppen in jouw toepassing lijkt me voldoende. Afhankelijk van de geselekteerde cel in kolom A kan de bewerking worden toegepast op het bestand dat in de aktieve cel staat aangeduid.
 
Laatst bewerkt:
Hallo SNB !

Ja, de gedachte om slechts drie knoppen op de sheet te zetten en te werken met de geselecteerde cellen was ook bij mij reeds opgekomen. Als ik nu de zaak laat draaien met behulp van jouw code en er worden bijvoorbeeld 20 bestanden gevonden, dan staan er 20 bestandsnamen op de sheet met in toaal 60 knoppen. Dat is misschien wel wat overdreven en het uitzicht van die sheet op zich is dan ook niet erg elegant. Bovendien hoeven de knoppen dan niet dynamisch toegevoegd te worden.

De reden waarom ik die denkpiste niet verder gevolgd heb, was omdat ik het zo een beetje als een nederlaag aanzag wegens het niet goedkomen met de dynamische knoppen.

Tot slot nog een vraagje om af te sluiten misschien. Je gebruikt niet alleen zo weinig mogelijk variabelen, maar degene die je wel gebruikt declareer je niet met het Dim-statement. Ook gebruik je het Option Explicit statement niet. Dat had je mij voordien als eens afgeraden.

Is er een bijzondere reden of voordeel om die beide zaken niet te gebruiken?

Nogmaals bedankt voor de raadgevingen en Grtz,
MDN111.
 
  • Het declareren van variabelen binnen een procedure heeft geen enkele invloed op de funktionaliteit van de macro
  • Het declareren van variabelen binnen een procedure heeft geen enkele invloed op de snelheid van de macro (extra-galactische toepassingen uitgezonderd)
  • De automatische interpretatie van variabelen als Variant-typen is nooit een bezwaar; zelf declareren is daarmee overbodig.
  • Het declareren van variabelen is alleen noodzakelijk als ze beschikbaar moeten zijn in verschillende modules van een projekt (Public). Het nalaten van declareren stimuleert je daardoor het aantal modules te beperken. Voorbeeld. met 1 Userform kun je met de voorziening Tabpages een onbeperkt aantal verschillende invoerschermen tevoorschijn toveren. Sommigen hebben daarvoor vele afzonderlijke userforms nodig.
  • Het beperken van het aantal te gebruiken modules en variabelen heeft op de snelheid van de macro meer merkbare invloed; als rudiment van de periode waarin de with...end with konstruktie nog niet bestond bestaat er in de code van sommigen (en vooral ook in de Microsoft-voorbeelden in Access -die volgens mij veelal uit de periode voor 1998 stammen-) een overdaad aan variabelen.
  • Hoe systematischer je variabelen gebruikt, hoe overbodiger declareren wordt.
  • Hoe minder tekst in een macro hoe leesbaarder ik hem vind en hoe eenvoudiger fouten te detecteren zijn.
Dat is een aantal van mijn overwegingen om alleen als het noodzakelijk is variabelen te declareren.
 
Laatst bewerkt:
Hier de visie van Stephen Bullen, John Green en Mike Bovey in hun klassieker "Professional Excel Development" (2005):

VBA Programming Best Practices
General VBA Best Practices
Use of Module Directives


Option Explicit: Always use the Option Explicit statement in every module. The importance of this practice cannot be overstated. Without Option Explicit, any typographical error you make results in VBA automatically creating a new Variant variable. This type of error is very insidious because it may not even cause an immediate runtime error. However, it will certainly cause your application to eventually return incorrect results. This type of bug may very well pass without notice until your application is distributed, and it will be difficult to debug under any circumstances. The Option Explicit statement forces you to explicitly declare all the variables you use. Option Explicit causes VBA to throw a compile-time error (initiated by selecting Debug > Compile from the VBE menu) whenever an unrecognized identifier name is encountered. This makes it very easy to discover and correct typographical errors. You can ensure that Option Explicit is automatically placed at the top of every module you create by choosing Tools > Options > Editor from the VBE menu and checking the Require Variable Declaration check box. This setting is strongly recommended

Code:
[B]Avoid the Variant Data Type[/B]

Avoid the use of the Variant data type whenever possible. Unfortunately, VBA is not a strongly typed programming language.
Therefore, you can simply declare variables without specifying their data type and VBA will create these variables as Variants. 
The main reasons not to use Variants are as follows:

 * Variants are very inefficient This is because internally, a Variant is a very complex structure designed to hold any data type 
in the VBA programming language. Variant values cannot be accessed and modified directly as can fundamental data types 
such as Long and Double. Instead, VBA must use a series of complex Windows API calls behind the scenes whenever it 
needs to perform any operation on a Variant.

 * Data stored in a variant can behave unexpectedly Because Variants are designed to hold any type of data, the data type 
that goes into a Variant is not necessarily the data type that will come out of it. When accessing the data in a Variant, VBA 
will attempt to coerce the data into whatever data type it thinks makes the most sense in the context of the operation. If you 
must use Variants, always explicitly cast them to the data type you want when using their values.

[B]Beware of Evil Type Coercion[/B]
Evil Type Coercion (ETC) is another symptom that results from VBA not being a strongly typed programming language. 
ETC occurs when VBA automatically converts one data type to another completely unrelated data type. The most frequent 
examples are Strings that hold numbers being converted to Integers and Booleans being converted to their String equivalents. 
Don't mix variables of different data types in your code without using the explicit casting functions (CStr, CLng, CDbl and so on) 
to tell VBA exactly how you want those variables to be treated.

Wigi
 
Laatst bewerkt:
Hallo !

Waartoe een vraag op www.helpmij.nl allemaal niet kan leiden. Ik zie daar een erg interessante discussie ontstaan. Voor alle duidelijkheid: ik voel mij zelf niet geroepen om mee te discussiëren met argumenten voor en tegen, want ik ben geen beroepsprogrammeur en het gaat hier wel boven mijn niveau. Ik schrijf macro’s om mijn eigen werk efficiënter te kunnen doen en soms ook wel voor collega’s. Meestal slaag ik er wel in om te bekomen wat ik wil en als het echt niet lukt ga ik op zoek. Onder andere op dit forum.

Het is bijzonder boeiend om te zien dat er zich iemand aandient met een totaal andere visie en die zwaar geschut (Professional Excel Development) in de strijd werpt (strijd is natuurlijk figuurlijk bedoeld). Wat ik ervan moet denken weet ik zelf (nog) niet. Toen ik op www.cpearson.com terecht kwam dacht ik ook het ultieme Excel-VBA-orakel gevonden te hebben, maar toch faalde de code die ik van die site plukte, terwijl de code van SNB het wel deed.

Persoonlijk denk ik dat ik zelf misschien wel ietwat overdrijf met het in stukken trekken van de code. Ik kan mij macro’s herinneren waarvan het hoofdproces slechts uit enkele lijnen bestaat met in hoofdzaak function calls naar andere Udf’s die dan op hun beurt weer andere Udf’s aanroepen. Misschien iets van het goede teveel. Zulke werkwijze brengt wel met zich mee dat men automatisch geneigd is om z’n variabelen te declareren om toch geen risico te lopen dat men variabelen met dezelfde naam in ’t leven roept met alle mogelijk gevolgen.

Nog even een vraagje: In verband met hetgeen ik bezig was om te programmeren, is bij mij de volgende gedachte opgekomen: Door het programmatisch toevoegen van knoppen en de code daarvoor, zijn we in feite bezig met code toe te voegen in de module waarvan de uitvoering op dat moment zelf bezig is. Ik ben niet op de hoogte van hoe het proces van interpreteren en compileren in elkaar zit, maar het zou mij niet verwonderen dat zoiets tot instabiele situaties leiden?

Grtz,
MDN111.
 
De enige beperking die ik daarbij ben tegengekomen is de beperking van de stapsgewijze uitvoering; de onderbrekingsmodus (bijv. voor foutdetectie), werkt dan niet.
Wil je meer weten klik dan op de link van mijn ondertekening.
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan