Foutmelding bij kopiëren VBA

Status
Niet open voor verdere reacties.

RDIE

Gebruiker
Lid geworden
25 aug 2013
Berichten
80
Hoi,
In mijn database heb ik o.a. een tabel met artikelen.
Invoeren van een nieuw artikelnr. gebeurt via een formulier. Voor het gemak bij het invoeren van veel artikelnrs heb ik een stukje code gemaakt dat als volgt werkt:
Het aantal records wordt geteld en in het label AantalRecords gezet.
In het veld [CatNR] wordt de hoofdcategorie getikt, bijvoorbeeld 85. Dan wordt in het veld [SubCatNR] het subcategorienr getikt, bijvoorbeeld 8545. Daarna zoekt access in de tabel naar het hoogste nr dat begint met 858545, hoogt dat op met 1 en geeft dat nr aan in het label [VrstlArt] Daarmee wordt dan in die (sub)categorie het eerstvolgende vrije artikelnr weergegeven. wat dan gebruikt kan worden voor het nieuw op te voeren artikelnr.
Werkte perfect en ik was er zeer content mee.

Het hele verhaal heb ik inclusief tabel, formulier en bijbehorende rapporten in een nieuwe database moeten importeren waarna ik steeds een foutmelding krijg "compileer fout, een door de gebruiker gedefinieerd gegevenstype is niet gedefinieerd" en in de code stopt meteen bij "Dim db As Database"

Mijn logische conclusie is dat het met het importeren te maken heeft maar andere stukjes code, zoals een knopje met messagebox eronder of een knop die een rapport opent blijven wel keurig werken.
Wat gaat hier fout? Wederom bij voorbaat mijn hartelijke dank.
de code heb ik hieronder gezet: (hopelijk doe ik het goed met de "codetags")

Code:
[I]'Deze procedure opent de tabel ARTIKELEN, gaat naar de laatste record en terug naar de eerste record
'telt het aantal record
'zet dat aantal in de variabele AantalRecords
'die waarde wordt getoond in het label Aantal Records
'de gebeurtenis vindt plaats bij het verlaten van het veld Artikelcode[/I]

Private Sub Artikelcode_Exit(Cancel As Integer)
Dim db As Database
Dim rec As Recordset
Dim AantalRecords As Integer
    Set db = CurrentDb()
    Set rec = db.OpenRecordset("tbl_Artikelen")
        rec.MoveFirst
        rec.MoveLast
        AantalRecords = rec.RecordCount
        rec.MoveFirst
        lblAantalRecords.Caption = AantalRecords
        rec.Close
End Sub
Private Sub CatNr_Exit(Cancel As Integer)
    Dim Cat As Long
    Dim Multipl As Double
    Dim extra As Integer
    extra = 100
    Cat = Me.CatNr
    Multipl = 10000000 * CLng(Cat)
    Multipl = 10& * Multipl
    lblCatNr.Caption = Multipl
End Sub



Code:
[I]deze routine zorgt ervoor dat in de labels de categorienrs en de subcategorienummers geplaatst worden in de vorm van gehele getallen
'omdat het om zulke grote getallen gaat zijn de variabelen gedimd als double en is er met de variabel extra1 een trucje uitgehaald. Deze is op 100 / 1000 gezet
'en wordt dan als het ware aan het CatNr en/of SubCatNr "geplakt". Daarmee voorkom je een overloop fout wat een fout is van te grote getallen proberen te plaatsen
'ten laatste wordt een voorlopig max artikelnummer voor die Categorie / Subcategorie aangemaakt met het optellen van 9999 Daarmee kunnen we straks wellicht
'zoeken naar het bestaande maximale artikelnummer. Deze variabel (VrlArt) wordt in het label VoorlArt (Voorlopig Artikelnummer) bewaard.
'Zodra het veld CatNR wordt ge-enterd vindt de gebeurtenis plaats[/I]

Private Sub SubCatNr_Exit(Cancel As Integer)
        Dim Cat As Long
        Dim Multipl As Double
        Dim extra As Integer
        extra = 100
        Cat = Me.CatNr
        Multipl = 10000000 * CLng(Cat)
        Multipl = 10& * Multipl
        lblCatNr.Caption = Multipl
            Dim SubCat As Long
            Dim Multipl1 As Double
            Dim extra1 As Integer
            extra1 = 10000
            SubCat = Me.SubCatNr
            Multipl1 = SubCat * extra1
            lblSubCatNr.Caption = Multipl1
            lblBasisNr.Caption = Multipl + Multipl1
                    Dim Multipl2 As Double
                    Dim VrlArt As Double
                    Multipl2 = 9999
                    VrlArt = Multipl + Multipl1 + Multipl2
                    lblVoorlArt.Caption = VrlArt
                        Dim VrstlArt As Double
                        VrstlArt = DMax("[Artikelcode]", "tbl_Artikelen", "[Artikelcode] < " & VrlArt)
                        VrstlArt = VrstlArt + 1
                        lblVrstArt.Caption = VrstlArt
        End Sub
 
Laatst bewerkt:
Het plaatsen van de codetags is niet goed gegaan. Wil je dat eerst even doen? Dat is een stuk prettiger lezen.
 
Was ik al bang voor, maar het is toch:
Code:
 "en dan hier de code"  [CODE]
of is het: [" en dan hier de code"] ??
 
Die laatste moet beginnen met [/
 
Ongelooflijk ingewikkelde manier om een nieuw artikelnummer te genereren. Ik zou hem zelf niet bedacht kunnen hebben :). Ook niet nodig hebben trouwens, want het kan echt een stuk simpeler. Kun je een voorbeeldje posten, dan kan ik er eens naar kijken. Kun jij ondertussen in de menubalk op zoekmaak de CODE knop. Want dat is de makkelijkste manier om een stuk geselecteerde tekst naar code om te zetten :).
 
Beste Octafish,
Ik zal eens proberen een voorbeeldje te posten.
Van de andere kant, ik geloof het direct dat het een stuk simpeler kan. Hoe zou jij dit kort en krachtig aanpakken?
 
Laten we om te beginnen eens kijken naar de manier waarop je de artikelnummers opbouwt. Daar zit m.i. niet zo'n geweldige logica in.
In het veld [CatNR] wordt de hoofdcategorie getikt, bijvoorbeeld 85. Dan wordt in het veld [SubCatNR] het subcategorienr getikt, bijvoorbeeld 8545. Daarna zoekt access in de tabel naar het hoogste nr dat begint met 858545, hoogt dat op met 1 en geeft dat nr aan in het label [VrstlArt] Daarmee wordt dan in die (sub)categorie het eerstvolgende vrije artikelnr weergegeven. wat dan gebruikt kan worden voor het nieuw op te voeren artikelnr.
Je kiest dus Categorie 85, en ziet dan een lijst met beschikbare subcategorieën. Laten we er voor het gemak even van uit gaan dat je max 99 categorieën hebt en max 99 subcategorieën per categorie. Zodat je voor een Catnr 2 posities hebt, en voor een subcat ook 2 posities. Daarmee is de categorie al prima te bepalen: een artikelnummer kan dan met 4 cijfers perfect aan een subcategorie worden gehangen. Waarom gebruik jij er 6? Waarin verschilt 858545 van 8545? Een subcategorie met als nummer 8545 kan toch nooit aan een andere categorie hangen dan 85? Kortom: in mijn optiek kun je net zo goed volstaan met de startcode 8545 voor een artikel.

In het voorbeeldje dat ik nu ga geven, ga ik dus uit van een artikelnummer dat bestaat uit 2 cijfers voor de categorie, 2 cijfers voor de subcategorie en 3 cijfers voor het artikelnummer. Dat artikelnummer moet automatisch worden bepaald op het moment dat je een nieuw artikel toevoegt. En daarvoor heb je in Access een prima plek: de eigenschap <Standaardwaarde>. Die koppel ik op een formulier dus aan een functie Volgnummer, als volgt:
Code:
=Volgnummer("Artikelcode";"tbl_Artikelen")

En de functie ziet er dan zo uit:
Code:
Function VolgNummer(Veld As String, Tabel As String) As String
Dim strSQL As String, sWaarde As String, sNum As String
Dim iNum As Integer

    If InStr(1, Veld, " ") > 0 And Left(Veld, 1) <> "[" Then Veld = "[" & Veld & "]"
    If InStr(1, Tabel, " ") > 0 And Left(Tabel, 1) <> "[" Then Tabel = "[" & Tabel & "]"
    strSQL = "SELECT TOP 1 " & Veld & " FROM " & Tabel & " WHERE (" & Veld & " Is Not Null AND Left(" & Veld & ",4) = " & Me.SubCatNr & ") ORDER BY " & Veld & " DESC"
    With CurrentDb.OpenRecordset(strSQL)
        If Not .BOF And Not .EOF Then sWaarde = .Fields(0).Value
        .Close
    End With
    If sWaarde & "" = "" Then GoTo GeenNummer
    
    sNum = Left(sWaarde, 4)
    iNum = CLng(Right(sWaarde, 3)) + 1
    VolgNummer = sNum & Right("000" & iNum, 3)
    Exit Function
    
GeenNummer:
    VolgNummer = Me.SubCatNr & "001"

End Function

En dat werkt dus heel simpel als volgt: de query die je in de functie opent haalt uit de tabel met artikelen het hoogste bestaande artikelnummer op gebaseerd op het subcategorienummer. Dat nummer bestaat uit 7 cijfers: 4 voor de subcategorie (waarmee dus ook de categorie bepaald is) en 3 voor het artikelnummer zelf. De query filtert op Subcatnr, sorteert de lijst aflopend op [Artikelcode] en pakt van die lijst de TOP 1, oftwel: één record, namelijk de eerste uit de lijst. Dat moet dus ook de hoogste zijn, omdat de lijst aflopend is gesorteerd.
Nu heb je dus ofwel de hoogste, ofwel niks (kan natuurlijk ook, als je nog nooit een artikel hebt toegevoegd voor die subcategorie. In het laatse geval moet je met nr 1 beginnen, in het eerste geval moet je het subcategorie nummer uit de querywaarde trekken. Omdat dat subcatnr altijd 4 cijfers bevat, kun je dat met Left (veld,4) doen. De laatste cijfers zijn dan dus automatisch het artikelnummer, en dat getal verhoog je met de waarde 1. En het hele zooitje voeg je weer samen en geef je terug aan de functie. Simpel, en werkt altijd perfect.
 
Daar ga ik eens mee aan de slag. Zover alvast mijn dank weer
 
Hallo, het duurde even voordat ik er mee verder kon maar inmiddels heb ik de artikeltabel aangepast (dus bijvoorbeeld: artnr 858545001 is geworden 8545001)
Maar het koppelen van de functie op het formulier dat doe ik toch door op het formulier het veld [Artikelcode] in de eigenschap <standaardwaarde> te voorzien van
Code:
=Volgnummer("Artikelcode";"tbl_Artikelen")
?
Zodra het veld SUBCatNR is gevuld moet dan toch het eerstvolgende vrije artikelnr worden weergegeven in het veld [Artikelcode] op het formulier?
Ik krijg dan namelijk in het veld [Artikelcode] op het formulier een foutmelding: #Fout te zien.
Of zit ik nu helemaal in de verkeerde richting te redeneren.
 
De functie Standaardwaarde laat een waarde zien zodra je een nieuw record aanmaakt. Als er op dat moment geen subcategorie bekend is (en dat zal niet bij een nieuw record) dan gaat de Standaardwaarde niet werken. In dat geval kun je de functie Volgnummer beter triggeren aan de keuzelijst subcategorie.
 
Excuus, maar ik kom er niet uit.
Hoe laat ik de functie triggeren door het veld SubCarNr?
Ik blijf steeds maar #Fout zien in het veld Artikelnr
Moet ik de functie niet op één of andere manier aan een gebeurtenis "hangen"?

En wat betekent het stukje nu eigenlijk precies
Code:
 If InStr(1, Veld, " ") > 0 And Left(Veld, 1) <> "[" Then Veld = "[" & Veld & "]"
    If InStr(1, Tabel, " ") > 0 And Left(Tabel, 1) <> "[" Then Tabel = "[" & Tabel & "]"


Bij voorbaat dank voor de moeite
 
Laatst bewerkt:
Hoi,
Ik heb er nu een knop aan het formulier toegevoegd met de code:
Code:
Private Sub Knop156_Click()
Me.Artikelcode.Value = VolgNummer
End Sub

Bij klikken zou dan de functie uitgevoerd moeten worden. (tja, ik probeer ook maar wat)

Krijg nu de foutmelding: compileerfout, het argument is niet optioneel

Wat gaat hier niet fout en hoe los ik het op?

Bij voorbaat dank voor de hulp.
 
Diezelfde code kun je dus óók aan de gebeurtenis <Bij klikken> van de keuzelijst hangen. En dan doet hij precies hetzelfde, en heb je geen extra knop nodig. Dus waarom die gebeurtenis niet gebruikt?
Het antwoord op je andere vraag krijg je uiteraard ook nog :). Ik zal de code even uitleggen, dan weet je ook gelijk waarom hij nu een foutmelding geeft. Nog even de functie dus:
De functie gebruikt 2 parameters als input: een tabelnaam en een veldnaam. Eigenlijk is dat niet helemaal correct, want je hebt nog een derde parameter wil je de functie helemaal jofel gebruiken. Want hij is eigenlijk opgezet om in een aparte module te gebruiken zodat je hem ook in queries etc. kunt toepassen. Zoals hij nu is geschreven werkt de functie alleen op het formulier waar de keuzelijst op staat. Hieronder dus de aangepaste algemene versie. Die vereist dus wel dat je drie parameters meegeeft. In bericht #7 gaf ik een voorbeeldje op basis van 2 parameters. In jouw laatste bericht, waarin je de functie aanroept zonder parameters, krijg je uiteraard een foutmelding. Want de functie krijgt geen parameters mee, en kan dus niet goed werken. Kijk maar eens naar de code in genoemde berichten :).

Code:
Function VolgNummer(Veld As String, Tabel As String, SubCat As String) As String
Dim strSQL As String, sWaarde As String, sNum As String, iNum As Integer

    If InStr(1, Veld, " ") > 0 And Left(Veld, 1) <> "[" Then Veld = "[" & Veld & "]"
    If InStr(1, Tabel, " ") > 0 And Left(Tabel, 1) <> "[" Then Tabel = "[" & Tabel & "]"
    strSQL = "SELECT TOP 1 " & Veld & " FROM " & Tabel & " WHERE (" & Veld & " Is Not Null AND Left(" & Veld & ",4) = " & SubCat & ") ORDER BY " & Veld & " DESC"
    With CurrentDb.OpenRecordset(strSQL)
        If Not .BOF And Not .EOF Then sWaarde = .Fields(0).Value
        .Close
    End With
    If sWaarde & "" = "" Then GoTo GeenNummer
    sNum = Left(sWaarde, 4)
    iNum = CLng(Right(sWaarde, 3)) + 1
    VolgNummer = sNum & Right("000" & iNum, 3)
    Exit Function
    
GeenNummer:
    VolgNummer = SubCat & "001"

End Function
En de aanroep wordt dan zo:
Code:
Private Sub SubCarNr_Click()
     Me.Artikelcode.Value = Volgnummer("Artikelcode","tbl_Artikelen", Me.SubCarNr)
End Sub
Op de Click van de keuzelijst roep je dus de functie aan, die het Volgnummer baseert op het veld [Artikelcode] uit de tabel [tbl_Artikelen] op basis van de gekozen waarde uit de keuzelijst <SubCarNr>.

Dan nog deze twee regels:
Code:
    If InStr(1, Veld, " ") > 0 And Left(Veld, 1) <> "[" Then Veld = "[" & Veld & "]"
    If InStr(1, Tabel, " ") > 0 And Left(Tabel, 1) <> "[" Then Tabel = "[" & Tabel & "]"
Die hebben een simpele verklaring. In een veldnaam (in een functie althans) mogen geen spaties zitten, want dan werkt de functie niet meer. Daarom doe ik met Instr een check op spaties in zowel veldnaam als tabelnaam. Zit er een spatie in, dan levert de functie Instr een waarde op die groter is dan 0. In dat geval moeten er [] om de veldnaam en tabelnaam worden gezet. Maar dat hoeft uiteraard niet als die haken er al staan; dat zou weer een andere fout opleveren. Vandaar een extra check die controleert of het eerste teken in de veldnaam en tabelnaam niet een "[" is. Dus: als er een spatie in de naam zit, en het eerste teken is niet gelijk aan [, dan worden er haken om veldnaam en tabelnaam gezet.
Hopelijk is het zo weer wat duidelijker :).
 
Laatst bewerkt:
Hallo Octafisch,
In elk geval bedankt voor je uitleg.
Echter, ik Krijg het niet werkend. Op de puntkomma achter "Artikelcode" krijg ik een foutmelding "verwacht lijstscheidingsteken of )" Maak ik er een komma van dan geen foutmelding maar wellicht maakt dat weer dat het hele verhaal niet werkt?
Mijn dank voor je geduld.
 
In queries gebruik je e puntkomma, in VBA een komma. De aanpassing wad dus terecht :).
 
Ik krijg nu de melding: er is een dubbelzinnige naam gevonden: Volgnummer
* de expressie geeft niet de naam van een macro, de naam van een door de gebruiker gedefinieerde functie of een [Gebeurtenisprocedure] als resultaat

mysterie miserie
 
Dan heb je de functie twee keer geplakt. Of nog een andere variant ergens staan. Één van de twee hernoemen, en het werkt weer.
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan