Functie geschikt maken voor meerdere formulier

Status
Niet open voor verdere reacties.

Matjes

Gebruiker
Lid geworden
21 jun 2016
Berichten
76
Hallo,

Onderstaande functie wil ik geschikt maken zodat ik voor verschillende subformulieren kan aanroepen en een nieuwe record kan toevoegen. De functie staat in een algemene module en wordt aangeroepen vanaf een commandbar.

De vetgedrukte teksten moeten dus variabel worden. Iemand een suggestie hoe ik dit voor elkaar kan maken?

Code:
Public Function InsertNew(lngID As Long)

Debug.Print "lngID: " & lngID

   Dim frm As Form_[U][/U][B]fsubPrjObj[/B]
   Forms("frmTree").sfmGeneric.SourceObject = "[B]fsubPrjObj[/B]"
   
   Set frm = Forms("frmTree").sfmGeneric.Form
      
   frm.[B]txtPrjVeldID[/B].DefaultValue = lngID
   frm.Recordset.AddNew


   Set frm = Nothing
   
End Function
 
Je hebt een paar variabelen die kunnen variëren, dus die moet je allemaal als parameter meegeven met de functie. Dan krijg je iets als:
Code:
Public Function InsertNew(frm As Form, fld As String, lngID As Long)
    
    frm(fld).DefaultValue = lngID
    DoCmd.GoToRecord , , acNewRec
   
End Function
 
Hi Octafish,

Bedankt voor de eerste aanzet. Ik krijg het alleen nog niet voor elkaar. Hij geeft een compilatiefout op:

Code:
Dim frm As Form_fsub

Dit is één van de codes welke de functie aanroept:

Code:
Set cmdButton = cmdBar.Controls.Add(msoControlButton)
            With cmdButton
               .Caption = "Toevoegen Objecttype"
               .Style = msoButtonIconAndCaption
               .OnAction = "=InsertNew('txtPrjVeldID', 'fsubPrjObj', " & lngID & ", '" & strField & "')"
               .Picture = getImageList.ListImages("Objecttype").Picture
            End With


en dit is de functie om een nieuw record in te voegen:

Code:
Public Function InsertNew(fld As String, fsub As String, lngID As Long, strField As String)
  
   [B]Dim frm As Form_fsub[/B]
   Set frm = Forms("frmTree").sfmGeneric.Form
   frm(fld).DefaultValue = lngID
   frm.Recordset.AddNew


   Set frm = Nothing


End Function

Zoals gezegd krijg ik de frm niet gedimensioneerd op deze manier. Idee wat er verkeerd gaat?
 
Oh ja.... Een formulier bestaat maar als één soort object: Form. Wat je ook doet, als je een variabele declareert die een formulier moet voorstellen, dan is dat dus altijd een Form object. Een Form_fsub bestaat niet. Of je moet daar zelf een klasse voor gemaakt hebben, dat kan natuurlijk ook.
Wel grappig: ik heb honderden databases gemaakt (werkende, ook dat nog ;) ) en nog nooit een knop op deze manier hoeven toe te voegen....
 
Hi OctaFish, duidelijk verhaal dat zo niet wil. Maar hoe dan wel?

Ik zou de achtergrond van de knop(pen) even toelichten:

Op een hoofdformulier heb ik een TreeView Object met nodes van verschillende soorten. Als er met de rechtermuisknop op een node wordt geklikt dan wordt er middels een "Select Case" bepaald wat voor soort node het is en daar wordt dan een knop voor gemaakt om een nieuw record toe te voegen:

Code:
Public Sub RightClickNode(nodX As MSComctlLib.Node)
Dim lngID As Long
Dim strField As String

lngID = CLng(Mid(nodX.Key, InStr(nodX.Key, conKeySeparator) + 1))
   
   Dim cmdBar As CommandBar
   Set cmdBar = CommandBars.Add(, msoBarPopup, False, True)
   
   Dim cmdButton As CommandBarButton
   
   
   strField = Left(nodX.Key, InStr(nodX.Key, conKeySeparator) - 1)
   
   
   Select Case strField
         
      Case "PrjID"
         Set cmdButton = cmdBar.Controls.Add(msoControlButton)
            With cmdButton
               .Caption = "Toevoegen Veld"
               .Style = msoButtonIconAndCaption
               '.OnAction = "=InsertNew('txtPrjVeldID', 'fsubPrjObj', " & lngID & ", '" & strField & "')"
               .Picture = getImageList.ListImages("bay").Picture
            End With
        
      Case "enzovoort"
         
      Case "enzovoort"
         
      Case "enzovoort"
      
      Case "enzovoort"
      
      Case "enzovoort"
        
   End Select

   Bar.ShowPopup
    
   
'cleanup
   Set cmdBar = Nothing
   Set cmdButton = Nothing
 
End Sub



Dan is het de bedoeling dat de knop de gegevens bevat als input voor de onderstaande functie welke:

- de betreffende subformulier meegezonden als frm in de control subformuliercontrol plaatst;
- de vreemde sleutel meegezonden als lngID als default waarde in het meegezonden veld zet;
- toevoegen van een nieuw record in de recordset van het subformulier

Zoiets als dit dus:

Code:
Public Function InsertNew(fld As String, fsub As String, lngID As Long, strField As String)
  
   Dim frm As Form_fsub
   Set frm = Forms("frmTree").sfmGeneric.Form
   frm(fld).DefaultValue = lngID
   frm.Recordset.AddNew


   Set frm = Nothing


End Function


Uiteraard sta ik open voor andere mogelijkheden dus ik ben benieuwd hoe jij dit dan zou regelen. Als je mij nog even verder op weg kan helpen dan heel graag :thumb:
 
Oktafish,

Niet helemaal met je eens.
In feite is een formulier-module, zoals je ongetwijfeld weet, ook een klasse en kan inderdaad in een declaratie gebruikt worden.
Dus iets als

Dim frm as Form_fSub is heel wel mogelijk en ook
Dim frm as New Form_fSub

Daarna moet je natuurlijk niet een ander formulier in deze variabele zetten.

Jan
 
[@jgkdrt: je hebt in technische zin wel gelijk, en formulieren zijn uiteraard ook eigen klasseobjecten. Maar in het aangehaalde voorbeeld is het in mijn ogen een zinloze declaratie. Ik gebruik de constructie nog wel eens als je één formulier twee keer tegelijk wilt openen. In beginsel kan dat niet: als je een geopend formulier voor een tweede keer probeert te openen, ga je namelijk terug naar het eerste reeds geopende formulier. Door er een apart object voor te maken, kan het wel. Maar daar is hier geen sprake van.
 
Als er met de rechtermuisknop op een node wordt geklikt dan wordt er middels een "Select Case" bepaald wat voor soort node het is en daar wordt dan een knop voor gemaakt om een nieuw record toe te voegen
Kijk, dát snap ik dus niet: als je een knop nodig hebt om records toe te voegen, dan kan dat m.i. gewoon één knop zijn. Dat je daar dan steeds andere opdrachten aan hangt, maar dan verder niks uit. Het blijft (bij mij althans) gewoon één knop. Daar verander ik dan de tekst van, en/of de afbeelding, of de kleur, afhankelijk van de functie van de knop. Is de knop niet nodig, dan maak ik hem onzichtbaar. Of, als hij wel nodig is maar nog niet actief mag zijn, dan zet ik hem op disabled. Kortom: de inrichting van het formulier doe ik volledig in de design modus, met alle objecten dus gewoon waar ik ze hebben wil, en de functionaliteit regel ik wel met VBA. Maar ik zal dus nooit met VBA extra objecten toevoegen. Ach, verschil van aanpak moet kunnen :D.

Ik snap nog steeds niet precies wat de bedoeling is. Als je vanuit de knop een tweede formulier wilt openen, dan is dat toch simpel? Je opent het formulier, en geeft alle gegevens die je mee wilt nemen mee in de OpenArgs variabele. Dat is doorgaans een tekststring die dus één string bevat, en als je niks doet dus ook maar op één veld kan worden gezet (vaak overigens is dat al genoeg) maar met een simpel trucje kun je net zo veel velden vulden als je wilt.
Dan krijg je zoiets:

Code:
    sArgs = TempVars("varPersoonID").Value & "|" & TempVars("varDossierID").Value & "|" & TempVars("varMedID").Value
    DoCmd.OpenForm "fNieuwGesprek", DataMode:=acFormAdd, WindowMode:=acDialog, OpenArgs:=sArgs
Je opent dus een formulier waarbij je de OpenArgs variabele vult met een string met alle parameters die zijn gescheiden met een vast scheidingsteken. Op het formulier dat je opent draai je deze code bij de gebeurtenis Form_Load
Code:
    If Not IsNull(Me.OpenArgs) Then
        If InStr(1, Me.OpenArgs, "|") > 0 Then
            arr = Split(Me.OpenArgs, "|")
            With Me
                .persoon_ID_g.Value = arr(LBound(arr))
                .Dossier_ID_g = arr(LBound(arr) + 1)
                .medewerker_ID_g = arr(LBound(arr) + 2)
            End With
        End If
        Me.lblTitel.Caption = "Niewuw Gesprek"
    Else
        Me.lblTitel.Caption = "Gesprek bewerken"
    End If
 
Hi OctaFish en Jan,

Hartelijk dank voor jullie toelichting. Ik begrijp de verwarring omtrent de nut en noodzaak van de Case Select en de knoppen. Ik ben niet helemaal volledig geweest op dat punt. Het is namelijk zo dat als er met de rechtermuisknop op een node geklikt wordt er minimaal één of soms meerdere knoppen verschijnen, afhankelijk van het type node waar op geklikt wordt. Elke knop is dan een verschillend item wat toegevoegd kan worden aan de node. Bij elk soort item hoort een eigen subformulier welke in de subformuliercontrol van het hoofdformulier geplaatst moet worden.

Voor de volledigheid ziet de code van de knoppen er dan zo uit:

Code:
Public Sub RightClickNode(nodX As MSComctlLib.Node)
Dim lngID As Long
Dim strField As String

lngID = CLng(Mid(nodX.Key, InStr(nodX.Key, conKeySeparator) + 1))
   
   Dim cmdBar As CommandBar
   Set cmdBar = CommandBars.Add(, msoBarPopup, False, True)
   
   Dim cmdButton As CommandBarButton
   
   
   strField = Left(nodX.Key, InStr(nodX.Key, conKeySeparator) - 1)
   
   
   Select Case strField
         
      Case "PrjID"
         Set cmdButton = cmdBar.Controls.Add(msoControlButton)
            With cmdButton
               .Caption = "Toevoegen Veld"
               .Style = msoButtonIconAndCaption
               '.OnAction = "=InsertNew('txtPrjVeldID', 'fsubPrjObj', " & lngID & ", '" & strField & "')"
               .Picture = getImageList.ListImages("bay").Picture
            End With
         Set cmdButton = cmdBar.Controls.Add(msoControlButton)
            With cmdButton
               .Caption = "Toevoegen wat anders"
               .Style = msoButtonIconAndCaption
               '.OnAction = "=InsertNew('txtPrjVeldID', 'fsubWatandersj', " & lngID & ", '" & strField & "')"
               .Picture = getImageList.ListImages("bay").Picture
            End With
        
      Case "enzovoort"
               Knop 1
               Knop 2
               Knop 3
         
      Case "enzovoort"
              Knop 1     
      Case "enzovoort"
      
      Case "enzovoort"
      
      Case "enzovoort"
        
   End Select

   Bar.ShowPopup
    
   
'cleanup
   Set cmdBar = Nothing
   Set cmdButton = Nothing
 
End Sub


Omdat deze knoppen qua gebeurtenis (onaction) alleen een public function kunnen aansturen is het de bedoeling dat de onaction alle gegevens bevat om:

- de betreffende subformulier in de subformuliercontrol van het hoofdformulier te openen;
- de vreemde sleutel welke wordt meegezonden als default waarde in een veld zet;
- toevoegen van een nieuw record in de recordset van het betreffend subformulier

Zoiets als dit dus:

Code:
Public Function InsertNew(fld As String, fsub As String, lngID As Long, strField As String)
  
   Dim frm As Form_fsub
   Set frm = Forms("frmTree").sfmGeneric.Form
   frm(fld).DefaultValue = lngID
   frm.Recordset.AddNew


   Set frm = Nothing


End Function

Ik hoop dat ik het zo heb kunnen verduidelijken en dat jullie de code misschien willen wijzigen zodat het werkend wordt. Ik zie het even niet meer :rolleyes: (het is maar een hobby :d)
 
Laatst bewerkt:
Elke knop is dan een verschillend item wat toegevoegd kan worden aan de node.
Nu je meer vertelt (waar blijft trouwens een voorbeeldje, dan was de draad waarschijnlijk al klaar geweest ;) ) begrijp ik nóg minder van je aanpak. Althans: dit zou zo'n beetje de laatste werkwijze zijn die ik hier zou toepassen. Omdat het in mijn ogen dus ongelooflijk veel simpeler kan. En de gequoote zin ontsluit die werkwijze. In mijn ogen schreeuwt dit namelijk helemaal niet naar knoppen waar je vervolgens op moet klikken, maar om het vullen van één keuzelijst met de in de node aangeklikte keuze. Simpel, want die keuzelijst kun je naar behoeven vullen en leegmaken (eventueel de hoogte aanpassen) en een keuzelijst heeft een natuurlijke Click event die je voor de vervolgstap kunt gebruiken.
 
Hi OctaFish,

Bedankt voor je advies. Een extra keuzelijst is voor mij niet echt een optie omdat dit een extra handeling voor de gebruiker is, namelijk rechtermuisklik op node en dan selecteren uit een keuzelijst. Om het te verduidelijken wat het principe moet worden heb ik onderstaand plaatje toegevoegd als voorbeeld (dit is niet uit de database maar ter illustratie):

TreeViewPopUp.jpg

Het principe is dus dat er verschillende soorten nodes zijn waaraan verschillende items toegevoegd kunnen worden. Laten we bijvoorbeeld zeggen: Toevoegen eis, toevoegen partij, toevoegen object etc. Dit worden dan ook weer nodes van de parent node. Welke items voor node 1 van toepassing zijn hoeft dus niet te gelden voor een child node van 1 of bijvoorbeeld node 2, etc. Vandaar de Select Case om uit te peilen op wat voor soort node er geklikt is. Hierop wordt dan een dynamische popup geopend met daarin één of meerdere items om toe te voegen aan de node. Hierop moet dan het betreffende subformulier van eis, partij, object etc. worden gekoppeld aan de subformformuliercontrol in het hoofdformulier waarook de TreeView in staat.

Ik hoop dat ik hiermee de gewenste functionaliteit heb kunnen verduidelijken. Ik hoop dat je een oplossing voor mij weet om eenvoudig het juiste subformulier mee te geven aan de functie InsertNew zodat deze gekoppeld kan worden aan de subformuliercontrol.
 
Bedankt voor je advies. Een extra keuzelijst is voor mij niet echt een optie omdat dit een extra handeling voor de gebruiker is, namelijk rechtermuisklik op node en dan selecteren uit een keuzelijst.
Hoezo? Nu kies je uit de node, en moet je op een knop klikken. Bij een keuzelijst kies je uit de node en moet je op een keuze in de lijst klikken. Ik kan tot drie tellen, maar ik kom nu niet verder dan twee klikken in beide gevallen...
Let wel: ik heb het niet voor niets over een keuzelijst, niet over een keuzelijst met invoervak. Dat mag natuurlijk ook, en zou in beginsel een extra klik opleveren. Al is het een kleine moeite om die keuzelijst met invoervak uit te klappen als je op een node hebt geklikt, in welk geval het aantal klikken ook niet verder komt dan twee.
En dat gezegd hebbende, stel ik mij toch voor dat mijn constructie zoveel makkelijker te bouwen en onderhouden is, dat ik me afvraag waarom je het al niet zo gebouwd hebt :).
 
Hoezo? Nu kies je uit de node, en moet je op een knop klikken. Bij een keuzelijst kies je uit de node en moet je op een keuze in de lijst klikken

Waarom zou ik een node uit een keuzelijst moeten kiezen terwijl het eenvoudiger is om op de node zelf te gaan staan in de TreeView? Dat is toch juist de kracht van een TreeView. Ik heb wel 1000 nodes in de TreeView, dat wil je niet uit een lijst kiezen :d

Vandaar rechtermuisknop op de node en dan de opties voor het toevoegen van een bepaald soort childnode.
 
Oh ik lees verkeerd excuses. Maar waar op het formulier zou de keuzelijst dan moeten komen en hoe ziet dit dan in hoofdlijnen eruit in code?
 
Die keuzelijst zet je op de plek waar je anders de knop(pen) neer zounzetten. Ik neem tenminste aan dat je daar op je formulier wel ruimte voor gereserveerd hebt.
 
Daar zit de spraakverwarring denk ik. De knoppen zitten in een popup menu van een ActiveX Control. Dus waar je met de rechtermuisknop op een node klikt.
 
CommandBarbuttons volgens Microsoft. Dus Commandobar knoppen. Ook te lezen in de gegeven code :)
 
Ik vind het al vreemder en vreemder.... hou het toch gewoon allemaal op een formulier, waarom zo ingewikkeld?
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan