msgbox voor leeg veld(en) ja/nee en dan verdergaan

  • Onderwerp starter Onderwerp starter scw
  • Startdatum Startdatum
Status
Niet open voor verdere reacties.

scw

Gebruiker
Lid geworden
5 jun 2009
Berichten
530
Goedendag,

Onderstaande code is een bestaande code voor een form, waarbij ik in dit form nu twee niet-verplicht in te vullen velden wil toevoegen. Echter, ik wil de gebruiker wel er op wijzen dat Veld 1 en/of Veld 2 leeg zijn. Hoe kan ik dit neerzetten, ik heb een poging gedaan hieronder, maar vooral het en/of aspect is bepaald lastig voor mij. En uiteindelijk als de gebruiker beide niet in wil vullen hoe kan ik dan weer verder gaan naar de resterende code (het opstellen van een e-mail)? doe ik dat met een Call functie van VBA ofzo? Ik ben benieuwd!


Code:
Private Sub Opslaan_Click()
On Error GoTo Err_Opslaan_Click

Dim objOutlook As Object
Dim objEmail As Object
Dim Con As Object
Dim Rs, Rsq, Rst, Rss, Rsv, Rsn, Rsp, Rsr As Object
Dim stSql As String
Dim StrmsgA As String
Dim StrmsgB As String
Dim StrmsgC As String


If Trim(Me!Datum & "") = "" Then
MsgBox "Vul de datum in.", vbInformation, "voorbeeldDB"
Me.Datum.SetFocus

ElseIf Nz(Me!Aanname, "0") = "0" Then
MsgBox "Voer een naam in voor de aanname.", vbInformation, "voorbeeldDB"
Me.Aanname.SetFocus

ElseIf Nz(Me!Betrokkene, "0") = "0" Then
MsgBox "Voer de naam van de betrokkene in.", vbInformation, "voorbeeldDB"
Me.Betrokkene.SetFocus

ElseIf Nz(Me!Groep, "0") = "0" Then
MsgBox "Geef een groep aan.", vbInformation, "voorbeeldDB"
Me.Groep.SetFocus

ElseIf Nz(Me!Vereniging, "0") = "0" Then
MsgBox "Vul de vereniging in.", vbInformation, "voorbeeldDB"
Me.Vereniging.SetFocus

ElseIf Nz(Me!Soort, "0") = "0" Then
MsgBox "Geef het soort aanmelding aan.", vbInformation, "voorbeeldDB"
Me.Soort.SetFocus

ElseIf Trim(Me!Omschrijving & "") = "" Then
MsgBox "Vul een omschrijving in.", vbInformation, "voorbeeldDB"
Me.Omschrijving.SetFocus

ElseIf Trim(Me!Maatregel & "") = "" Then
MsgBox "Vul een maatregel in.", vbInformation, "voorbeeldDB"
Me.Maatregel.SetFocus

ElseIf Trim(Me!Status & "") = "" Then
MsgBox "Geef de status van het verbeterpunt aan.", vbInformation, "voorbeeldDB"
Me.Kader71.SetFocus

ElseIf Nz(Me!Afhandeling, "0") = "0" Then
MsgBox "Voer een naam in voor de afhandeling.", vbInformation, "voorbeeldDB"
Me.Afhandeling.SetFocus

[COLOR="red"]

strmsgA = 'Veld 1 + Veld 2 zijn nog niet ingevuld wilt u deze invullen?'
strmsgB = 'Veld 1 is nog niet ingevuld wilt u deze invullen?'
strmsgC = 'Veld 2 is nog niet ingevuld wilt u deze invullen?'

ElseIf Trim(Me!Veld1 & "") = "" AND Trim(Me!Veld2 & "")  Then
If MsgBox(strMsgA, vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
    Me.Veld1.SetFocus
    ElseIf
ElseIf Trim(Me!Veld2 & "") = "" Then
If MsgBox(strMsgB, vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
    Me.Veld1.SetFocus
    ElseIf
ElseIf Trim(Me!Veld2 & "") = "" Then
If MsgBox(strMsgB, vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
    Me.Veld2.SetFocus   
 ElseIf
'Vanaf hier naar onderstaande verzendprocedure... hoe zet ik dat neer?
        [/COLOR]
        
        Exit Sub

Else

Set Con = Application.CurrentProject.Connection

stSql = "SELECT [Naam] FROM tblMedewerkers "
stSql = stSql & "WHERE [MedewerkerID] = " & Me!Betrokkene
Set Rsq = CreateObject("ADODB.Recordset")
Rsq.Open stSql, Con, 1

stSql = "SELECT [Aanmeldingsoort] FROM tblAanmeldingSoorten "
stSql = stSql & "WHERE [AanmeldingsoortID] = " & Me!Soort
Set Rst = CreateObject("ADODB.Recordset")
Rst.Open stSql, Con, 1

stSql = "SELECT [Groep] FROM tblGroepen "
stSql = stSql & "WHERE [GroepID] = " & Me!Groep
Set Rss = CreateObject("ADODB.Recordset")
Rss.Open stSql, Con, 1

stSql = "SELECT [Verenigingnaam] FROM tblleden "
stSql = stSql & "WHERE [VerenigingID] = " & Me!Vereniging
Set Rsv = CreateObject("ADODB.Recordset")
Rsv.Open stSql, Con, 1

stSql = "SELECT [Status] FROM tblStatus "
stSql = stSql & "WHERE [StatusID] = " & Me!Status
Set Rsp = CreateObject("ADODB.Recordset")
Rsp.Open stSql, Con, 1

stSql = "SELECT [Naam] FROM tblMedewerkers "
stSql = stSql & "WHERE [MedewerkerID] = " & Me!Afhandeling
Set Rsn = CreateObject("ADODB.Recordset")
Rsn.Open stSql, Con, 1

stSql = "SELECT [E-mailadres] FROM tblMedewerkers "
stSql = stSql & "WHERE [MedewerkerID] = " & Me!Afhandeling
Set Rsr = CreateObject("ADODB.Recordset")
Rsr.Open stSql, Con, 1


Set objOutlook = CreateObject("Outlook.application")
Set objEmail = objOutlook.CreateItem(olMailItem)

With objEmail
If IsNull(Rsr![E-mailadres]) Then
MsgBox "Er is geen e-mailadres toegevoegd voor " & Rsn!Naam & ". Ga naar" & vbNewLine & "het scherm 'Instellingen' en klik daar op 'Medewerkers' om een e-mailadres toe te voegen.", vbExclamation, "voorbeeldDB"
.To = ""
Else
.To = Rsr![E-mailadres]
End If
.CC = DLookup("[E-mailadres]", "tblEmail")
.Subject = "Aanmelding " & LCase(Rst![Verenigingsoort])
.HTMLBody = "<script type=text/javascript>"
.Display
End With


DoCmd.RunCommand acCmdSaveRecord
DoCmd.Close acForm, "frmVereniginglidToevoegen"
End If
Exit Sub

Rs.Close
Rsq.Close
Rst.Close
Rss.Close
Rsv.Close
Rsp.Close
Rsn.Close
Rsr.Close

Set Con = Nothing
Set Cont = Nothing
Set Rs = Nothing
Set Rsq = Nothing
Set Rst = Nothing
Set Rss = Nothing
Set Rsv = Nothing
Set Rsp = Nothing
Set Rsn = Nothing
Set Rsr = Nothing

Exit Sub


Exit_Opslaan_Click:
    Exit Sub

Err_Opslaan_Click:
    MsgBox Err.Description
    Resume Exit_Opslaan_Click

End Sub
 
Als ik goed begrijp wat je bedoelt, zou dit moeten werken.
Het is wel AirCode, dus niet getest

Code:
    If IsNull([Field1]) Then
        Dim LResponse As Integer
            LResponse = MsgBox("Veld 1 is niet ingevuld, nu invullen ?" _
            , vbYesNo, "Continue")
    If LResponse = vbYes Then
        DoCmd.GotoControl "Field1"
    If LResponse = vbNo Then
          Exit sub
            End If
                End If
                   End if

Dus veld1 is niet ingevuld dan krijg je de vraag dat alsnog te doen en word de focus op het veld gezet. Is het antwoord nee dan gaat ie verder met de controle.
 
Laatst bewerkt:
Hoi JeroenMioch,

Dank voor je reactie. Nee, dat principe werkt wel. Het gaat juist om het principe drie keer te combineren:

dus eerst check veld 1 + veld 2 leeg= msgbox "allebei niet ingevuld", doorgaan ja/nee
anders check alleen veld 1 is leeg? = msgbox "veld 1 is niet ingevuld", doorgaan ja/nee
anders check alleen veld 2 is leeg? = msgbox "veld 2 is niet ingevuld", doorgaan ja/nee

Dat zou ik graag willen bereiken...
 
Ook dat zou niet al te moeilijk moeten zijn, Helaas zit ik niet meer achter mn werkstation en om te gaan coderen vanaf mn iphone... Hahaha
Ik zie Octafish online, hij schud die code zo uit zijn mouw haha.
Hopelijk kan hij je helpen en anders kijk ik morgen wel even als ik thuis ben.
 
Om te beginnen: de manier waarop je variabelen declareert vind ik een beetje vreemd.... Wat denk je dat je met deze regel bijvoorbeeld declareert?
Code:
Dim Rs, Rsq, Rst, Rss, Rsv, Rsn, Rsp, Rsr As Object
En dan die enorme constructie met de IF...ELSEIF...END IF, waarbij je elke keer een msgbox geefr, en de focus op het lege tekstveld zet. Als iemand 5 velden leeg laat, verplaatst de focus dus 5 keer, waarbij hij dus het laatste lege teksvak de focus geeft, niet de eerste. Dus die constructie is niet erg gebruiksvriendelijk, ook al omdat je een aantal keer een msgbox moet wegklikken, wat uiteraard tijd kost. Zelf zou ik alle checks 'verzamelen' in één msgbox, en de focus naar het eerste tekstvak verplaatsen. Dan moet je de ELSEIF er wel uitgooien, en er losse IF's van maken.

De twee losse tekstvakken kun je wel oplossen met een IF...ELSEIF. Je hebt namelijk maar een paar varianten, die je tegelijk kunt checken.

Code:
If Trim(Me.Veld1 & "") = "" And Trim(Me.Veld2 & "") Then
    If MsgBox("Veld 1 + Veld 2 zijn nog niet ingevuld wilt u deze invullen?", vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
        Me.Veld1.SetFocus
    End If
ElseIf Trim(Me.Veld1 & "") = "" And Trim(Me.Veld2 & "") <> "" Then
    If MsgBox("Veld 1 is nog niet ingevuld wilt u deze invullen?", vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
        Me.Veld1.SetFocus
    End If
ElseIf Trim(Me.Veld2 & "") = "" And Trim(Me.Veld1 & "") <> "" Then
    If MsgBox("Veld 2 is nog niet ingevuld wilt u deze invullen?", vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
        Me.Veld2.SetFocus
    End If
End If
 
Dank Octafish voor je opmerkingen.

Voor wat betreft de variabelen declaratie:
Dit gebruik ik in het stukje e-mail opmaak, wat ik er niet even tussenuit heb gehaald, omdat dat alleen maar ruis is voor deze vraag welke ergens anders over gaat.

Voor wat betreft de vele ElseIfs:
Dit onderschrijf ik volledig, maar het werkt echter naar behoren. 'wanneer iemand vijf velden niet invult'... dan moet diegene ook alle vijf velden invullen. Meestal gebeurt dat gewoon. Ik zie er geen gebruikersONvriendelijkheid in...

Voor wat betreft de twee losse tekstvakken:
Super! dat is wat ik zo ongeveer zocht.. nu ontvang ik alleen nog de melding 'Typen komen niet met elkaar overeen... bij het gebruik van de volgende code:

Code:
ElseIf Nz(Me!Afhandeling, "0") = "0" Then
MsgBox "Voer een naam in voor de afhandeling.", vbInformation, "voorbeeldDB"
Me.Afhandeling.SetFocus

ElseIf Trim(Me.Veld1 & "") = "" And Trim(Me.Veld2 & "") Then
    If MsgBox("Veld 1 + Veld 2 zijn nog niet ingevuld wilt u deze invullen?", vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
        Me.Veld1.SetFocus
    End If
ElseIf Trim(Me.Veld1 & "") = "" And Trim(Me.Veld2 & "") <> "" Then
    If MsgBox("Veld 1 is nog niet ingevuld wilt u deze invullen?", vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
        Me.Veld1.SetFocus
    End If
ElseIf Trim(Me.Veld2 & "") = "" And Trim(Me.Veld1 & "") <> "" Then
    If MsgBox("Veld 2 is nog niet ingevuld wilt u deze invullen?", vbQuestion + vbYesNo, "voorbeeldDB") = vbYes Then
        Me.Veld2.SetFocus
    End If
Else
 
Ik snap waar je de variabelen voor gebruikt; de vraag ging over de manier waarop je ze declareert.... Want dat gaat eigenlijk helemaal niet goed zo. Wat denk je bijvoorbeeld dat de variabele Rs is qua type?

Volgens mij heb ik je eigen code gepakt, en op de juiste manier aan elkaar geplakt. Als je een foutmelding krijgt, weet ik zo ook niet waar die vandaan komt. Er zit overigens wel een fout in deze regel:
Code:
ElseIf Nz(Me!Afhandeling, "0") = "0" Then
en ik vermoed dus dat je daar de foutmelding krijgt?
Code:
ElseIf Nz(Me.Afhandeling, 0) = 0 Then
zou moeten werken.

Wat betreft de vele msgboxen: als je gebruikers niet klagen, dan heb je mazzel :) Zelf zou ik alle lege velden verzamelen, en er één msgbox van maken, waarin je alle lege velden opsomt die ze moeten invullen. Vind ik veel overzichtelijker, en de gebruiker hoeft maar één msgbox te sluiten.
 
Goede punten:

eerst nog even over de variabelen, die moet ik dan aanpassen, maar:
- waarom werkt het wel naar behoren dan?
- waar zou ik hem naar moeten veranderen (excuus ik heb zeer weinig kennis van VBA en weet alleen maar van wat ik tegenkom)?

en zou je een voorbeeld kunnen geven hoe je dat aanpakt van een opsomming van lege velden in een msgbox, ik heb daar wel oren naar! het klinkt inderdaad als een mooie oplossing!
 
Bij het begin beginnen, maar dan!
Je declareert Con als object:
Code:
Dim Con As Object
Maar het is geen object, het is een Connectie. Declareer hem dan ook als connection:
Code:
Dim Con As DAO.Connection

Als je deze variabelen maakt:
Code:
Dim Rs, Rsq, Rst, Rss, Rsv, Rsn, Rsp, Rsr As Object
declareer je 7 variabelen (de eerste 7 namelijk) als Variant, en alleen de laatste (Rsr) als Object. Maar waarom maak je er een object van? Het zijn namelijk allemaar Recordsets, en die kun je dus veel beter als zodanig declareren. Dat ziet er dan zo uit:
Dim Rs As DAO.Recordset, Rsq As DAO.Recordset, Rst As DAO.Recordset, Rss As DAO.Recordset
Dim Rsv As DAO.Recordset, Rsn As DAO.Recordset, Rsp As DAO.Recordset, Rsr As DAO.Recordset
Je kunt best verschillende variabelen in één regel declareren, maar je moet voor elke variabele aangeven wat het is. Een recordset declareer je als Recordset, een getal als Integer (bijvoorbeeld).
Als je geen type vastlegt, maakt Acces er een Variant van. Dit is een type dat alles kan bevatten, dus ook een Recordset. Vandaar dat je code op zich wel werkt. Maar omdat je niet specifiek aangeeft wat de variabele moet zijn, kun je ook geen gebruik maken van de eigenschappen van het type. Bij een Recordset heb je bijvoorbeeld de eigenschap Field. Die kun je met een With ... End with gebruiken, door een punt te typen, en het gewenste type uit de lijst te selecteren. Dus niet alleen verklein je de geheugenruimte door de juiste variabelesoort te gebruiken, je maakt het vervolg een stuk makkelijker.

Een voorbeeldje van hoe je een variabele messagebox maakt:

Code:
Dim sMsg() As String, Tekst As String
Dim i As Integer

i = 0
ReDim sMsg(i, i)

If Trim(Me.Datum & "") = "" Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Datum"
    sMsg(i, 1) = "Het datumveld is leeg."
    i = i + 1
End If

If Nz(Me!Aanname, 0) = 0 Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Aanname"
    sMsg(i, 1) = "Voer een naam in voor de aanname."
    i = i + 1
End If

If Nz(Me!Betrokkene, 0) = 0 Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Betrokkene"
    sMsg(i, 1) = "Voer de naam van de betrokkene in."
    i = i + 1
End If

If Nz(Me!Groep, 0) = 0 Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Groep"
    sMsg(i, 1) = "Geef een groep aan."
    i = i + 1
End If

If Nz(Me!Vereniging, 0) = 0 Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Vereniging"
    sMsg(i, 1) = "Vul de vereniging in."
    i = i + 1
End If

If Nz(Me!Soort, 0) = 0 Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Vereniging"
    sMsg(i, 1) = "Geef het soort aanmelding aan."
    i = i + 1
End If

If Trim(Me!Omschrijving & "") = "" Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Omschrijving"
    sMsg(i, 1) = "Vul een omschrijving in."
    i = i + 1
End If

If Trim(Me!Maatregel & "") = "" Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Maatregel"
    sMsg(i, 1) = "Vul een maatregel in."
    i = i + 1
End If

If Trim(Me!Status & "") = "" Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Status"
    sMsg(i, 1) = "Geef de status van het verbeterpunt aan."
End If

If Nz(Me!Afhandeling, 0) = 0 Then
    ReDim Preserve sMsg(i, i)
    sMsg(i, 0) = "Afhandeling"
    sMsg(i, 1) = "Voer een naam in voor de afhandeling."
End If

If i > 0 Then
    If i = 1 Then
        Tekst = "Het volgende punt moet je nog even oplossen..."
    Else
        Tekst = "De volgende punten moet je nog even oplossen..."
    End If
    Tekst = Tekst & vbLf & vbLf
    For i = LBound(sMsg) To UBound(sMsg)
        Tekst = Tekst & i & " - " & sMsg(i, 1) & vbLf
    Next i
    MsgBox Tekst
    Me(sMsg(LBound(sMsg))).SetFocus
 
Laatst bewerkt:
Hoi Octafish,

Excuses voor de vertraging in reactie. Ik begrijp je punt(en) helemaal! Maar... zodra ik verander

1) Dim Con As DAO.Connection

2) Dim Rs As DAO.Recordset, Rsq As DAO.Recordset, Rst As DAO.Recordset, Rss As DAO.Recordset Dim Rsv As DAO.Recordset, Rsn As DAO.Recordset, Rsp As DAO.Recordset, Rsr As DAO.Recordset

Geeft die een compileerfout bij Rs.Open "kan de methode of het gegevenslid niet vinden". Moet ik hier zeker ook meteen iets aan veranderen??

Gr. scw
 
Je moet je bibliotheken goed laden; kijk in <Extra>, <Verwijzingen> of de DAO 3.6 bibliotheek geladen wordt als laatste bibliotheek. Ik krijg dezelfde problemen ook als ik eerst DAO laad, en als volgende ADO 2.8. Officieel mag het niet uitmaken, en er zijn ook helpers op het forum die zullen zeggen dat het niet uitmaakt, maar mijn ervaring is dat de bibliotheken beter werken als je eerst ADO laad, en daarna DAO. Gebruik je overigens geen ADO commando's dan kun je die bibliotheek beter niet laden; met DAO kun je doorgaans hetzelfde doen. Je hebt dus maar één variant nodig.
 
1) Dim Con As DAO.Connection
2) Dim Rs As DAO.Recordset
..
Geeft die een compileerfout bij Rs.Open

Hoewel DAO de eigenschap Connection kent (alleen met ODBC), maar samen met de methode Open, lijkt mij dit geen DAO.
 
nieuwe poging..

Goedendag,

Omdat ik het in juli niet direct zag, heb ik het even gelaten voor wat het was. Vandaag weer naar gekeken naar de kwestie... Ik begrijp waarom het nodig is om het zo neer te zetten volgens Octafish, absoluut. Maar vooralsnog werkt het niet en werkt het wél met het 'oude' Dim Con As Object. Ik heb dus ook geprobeerd om die 3.6 verwijzing als laatste te laden. Het helpt niet... :( Graag wil ik het wel goed programmeren... wat kan ik nog proberen?

Harry, wat bedoelde je precies te zeggen met:
Hoewel DAO de eigenschap Connection kent (alleen met ODBC), maar samen met de methode Open, lijkt mij dit geen DAO.

Wat is dat voor mij bedoeld of meer voor Octafish??
 
ADOBD kent de methode Connection, en ADO (zeg maar) niet. Je kunt zowel kiezen voor een ADO aanpak of een DAO procedure, maar natuurlijk niet tegelijkertijd door elkaar heen. Hoewel de experts tegenwoordig (geloof ik) nu liever met ADO werken, kun je nog steeds met DAO aan de slag. Voor normale (niet supergrote) databases zie ik ook niet zo heel veel snelheidsverschil, al zullen er ongetwijfeld argumenten zijn waarom je met de ene variant zou moeten werken, of de andere. Ik zit niet diep genoeg in die materie om daar een goed oordeel over te geven, dus ik gebruik beide varianten in verschillende db's. En ik heb dus niet echt een voorkeur.

Door Con als object te declareren, maak je gebruik van 'Late binding'. Declareer je als ADODB.Connection, dan maak je gebruik van 'Early binding'. Hier zijn wel duidelijke voor- en nadelen aan te geven: Early binding is sneller als Late binding, en je kunt met de punt simple methodes etc kiezen als je de code maakt. Late binding is dus wat langzamer, en je hebt de opbouwfunctie niet. Voordeel van Late binding (en nadeel van Early binding) is dat je geen bibliotheken hoeft te declareren. Je maakt overal een Object van, en je kunt aan de slag. Een declaratie als ADODB.Connection werkt alleen als je de juiste bibliotheek hebt geladen. En daar zit de crux: als een andere gebruiker dat niet heeft gedaan, dan werkt de code niet. Late binding is dus een prima optie als je een db bij andere gebruikers uit zet, en je kent hun configuratie niet.
Ook als de ene gebruiker nog Access 2003 gebruikt, en de ander 2010, kun je problemen krijgen, omdat de Office bibliotheken in beide versies een ander nummer hebben. En dat levert dan weer compatibiliteitsproblemen op.
Logisch dus dat je code werkt met Dim Con As Object, maar ik zou zeggen: maak hem ook werkend met Early binding, dan weet je zeker dat je code correct is.

Een goede tip die ik eens ergens gelezen heb: begin (en maak) je db met Early binding; je hebt dan volledige controle over de objecten, methodes etc. Als alles naar het zin is, kun je de binding omzetten naar Late binding. Je hebt dan de voordelen van het maken van Early binding, en de voordelen van Late binding bij het distributeren!
 
Duidelijk verhaal. Ik stuit nu op compatibiliteitsproblemen namelijk. Ik heb Outlook 2010 geïnstalleerd waar ik tegelijkertijd Access 2007 runtime gebruik. Nu werkt het niet meer...

Maar zodra ik de Dim Con As DAO.Connection toepas (zoals ik graag zou willen)

blijft die vastlopen bij die Rs.Open... wat ik ook doe: hij geeft "kan de methode of het gegevenslid niet vinden". :confused:
 
Ik zou 'm ombouwen naar ADODB.Connection, en alle declaraties dus naar ADO doen.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan