Alternatief voor dlookup

Status
Niet open voor verdere reacties.
Bedankt OctaFish, nog ff en alle problemen zijn verholpen.

Is het mogelijk als er in de kruistabel een veld niet voorkomt dat deze overgeslagen wordt op het rapport.

Op mijn rapport heb ik de velden V1 t/m V12.
Als ik als filter meegeef de periodes 3,4 en 8.
Dat op het rapport V1 en V2 geen controlsource, V3 en V4 wel de controlsource, V5 enz. enz. geen controlsource ingesteld wordt.

Ben al wat aan het knutselen geweest, maar zonder resultaat.

Code:
Private Sub Report_Open(Cancel As Integer)
 With CurrentDb.OpenRecordset("SELECT * FROM qryTest")
        On Error Resume Next
        While Not .EOF
            For i = 1 To 12
                If i = ??????? Then
                    Me("V" & i).ControlSource = .Fields(i + 1).Name
                Else
                    Me("V" & 1).ControlSource = ""
            Next i
            .MoveNext
        Wend
    End With
End Sub
 
Laatst bewerkt:
Ik zie in je oudere db's geen rapport waarop ik wat kan uitproberen; kun je een recente versie posten?
 
Alleen het maandrapport is correct, dus ik heb de code daarop aangepast. Het andere rapport kun je nu denk ik zelf wel?
 

Bijlagen

Bedankt OctaFish, ziet er netjes uit.
Misschien heb ik het niet helemaal duidelijk uitgelegd wat ik wilde.

Eigenlijk wil ik de layout van het rapport zo houden. (vaste laytout)
Dus 1 t/m 12 wil ik blijven zien op het rapport en totaal helemaal rechts.

Als ik periode 3 en periode 8 selecteer dat onder veld 1,2,4,5,6,7,9,10,11 geen bedragen staan, maar wel het label. Eigenlijk dat de controlsource niet ingesteld is.
En onder periode 3 en 8 netjes de bedragen staan.

Je krijgt dus leeg veld, leeg veld, bedragen, leeg veld enz. enz.

Als je er nog wil naar kijken heel graag, anders houdt het op.
 
Dat is een vrij simpele aanpassing. Volgens mij kun je die zelf wel maken :) Voorzetje: de techniek die ik gebruik heb je nog steeds nodig, om te bepalen welke velden gebruikt zijn. Die velden moet je met een loopje vergelijken met de 12 vaste velden die je hebt: komen ze overeen, dan moeten veld en label zichtbaar worden gemaakt, anders niet.
 
OctaFish, ik probeer de code een beetje begrijpen.
Heb zelf het een en ander geprobeerd door met msgbox de waardes uit te lezen.
Maar snap nog niet alles.

Wil jij eventueel het een en ander aanvullen, zodat ik het een beetje begrijp?
Code:
Private Sub Report_Open(Cancel As Integer)
Dim sVelden() As String
Dim i As Integer, j As Integer
Dim iTotaal As Double

With CurrentDb.OpenRecordset("SELECT * FROM qry_rptOmzetKlantMaandWeergave")
[COLOR="lime"]''Telt het aantal velden in de kruistabel[/COLOR]      
i = .Fields.Count 

[COLOR="lime"]''Eerste 3 velden zijn rijkoppen en vanaf  3 tot totaal aantal velden, de loop uitvoeren [/COLOR]
For i = 3 To i - 1

[COLOR="lime"]''Wat doe redim preserve?[/COLOR]            
ReDim Preserve sVelden(j)

[COLOR="lime"]''Snap die (j) en (i) niet helemaal wat de functie is[/COLOR]            
sVelden(j) = .Fields(i).Name
            j = j + 1

        Next i
    End With
    
    

    With CurrentDb.OpenRecordset("SELECT * FROM qry_rptOmzetKlantMaandWeergave")
        On Error Resume Next

[COLOR="lime"]'' Begin van de reeks tot einde van de reeks[/COLOR]      
For i = LBound(sVelden) To UBound(sVelden)

[COLOR="lime"]'' Die +1 is er zeker voor, omdat vba begint te tellen bij 0?
'' Je maakt de velden zichtbaar, maar hoe komt het dat de velden niet zichtbaar zijn?[/COLOR]
            Me("V" & i + 1).ControlSource = sVelden(i)
            Me("l" & i + 1).Caption = sVelden(i)
            Me("l" & i + 1).Visible = True

[COLOR="lime"]''Wat doet de .Left bij totaal?[/COLOR] 
Me.lTotaal.Left = Me("l" & i + 2).Left
Me.Totaal.Left = Me("V" & i + 2).Left
        Next i
    End With

End Sub


In 1 van je vorige voorbeelden gebruik je ook deze code.
Ook hier is niet alles helemaal duidelijk van.

Code:
Private Sub Report_Open(Cancel As Integer)
    With CurrentDb.OpenRecordset("SELECT * FROM qBedragperjaar")
        For i = 1 To 7

[COLOR="lime"]''Wordt gebruikt zeker als er geen veld is, dat de loop doorgezet wordt[/COLOR]          On Error Resume Next

            Me("l" & i).Caption = .Fields(i + 1).Name
        Next i

[COLOR="lime"]''Wat doet While not .EOF? en .movenext?  
''Waarom gebruik je geen On error resume next net zoals hierboven?[/COLOR] 
       While Not .EOF
            For i = 1 To 7
                Me("v" & i).ControlSource = .Fields(i + 1).Name
                Me("t" & i).ControlSource = "=Sum([" & .Fields(i + 1).Name & "])"
            Next i
            .MoveNext
        Wend
    End With
End Sub
 
Laatst bewerkt:
De hele procedure ziet er zo uit:

Code:
    With CurrentDb.OpenRecordset("SELECT * FROM qry_rptOmzetKlantMaandWeergave")
        i = .Fields.Count
        For i = 3 To i - 1
            ReDim Preserve sVelden(j)
            sVelden(j) = .Fields(i).Name
            j = j + 1
        Next i
    End With
    
    With CurrentDb.OpenRecordset("SELECT * FROM qry_rptOmzetKlantMaandWeergave")
        On Error Resume Next
        For j = 1 To 12
            For i = LBound(sVelden) To UBound(sVelden)
                If Me("V" & j).Name = "V" & sVelden(i) Then
                    Me("V" & j).ControlSource = sVelden(i)
                    Me("l" & j).Caption = sVelden(i)
                    Me("l" & j).Visible = True
                End If
            Next i
        Next j
    End With

Misschien dat de code alle vragen al beantwoord ;)
 
Was niet de bedoeling van mij dat je gelijk de code zal geven.
Snap sommige dingen niet helemaal en wil het graag begrijpen.
Kan er zelf slecht tegen als ik het niet begrijp. :(

Dus hoop dat je om wat dingen een antwoord wil geven:
-Begint vba te tellen bij 0, omdat je overal +1 ziet staan?
-Wat doe redim preserve sVelden(j)?

-Bij dit stukje snap ik niet echt wat die .left functie doet?
Code:
Me.lTotaal.Left = Me("l" & i + 2).Left
Me.Totaal.Left = Me("V" & i + 2).Left

Wat doet While not .EOF? en .movenext? Dit komt vaak voor in codes.
 
Code op zich helpt natuurlijk niet altijd; het begrijpen er van is uiteraard veel belangrijker. Dus hier komt de uitleg!

1) Tellen doe je vanaf de beginwaarde die je opgeeft. Als je een numerieke variabele declareert, heeft die nog geen waarde. Hij heeft na het declareren dus de waarde 0. Wil je met een andere waarde beginnen, dan doe je dat door de variabele te vullen. Bijvoorbeeld door de startwaarde in een lus in te stellen. Dus als ik een lus maak als: For i = 12 To 20, begint de lus bij i=12. Daarnaast tel ik vaak in een lus op basis van een matrixvariabele, zoals sVelden(j) (ook en vraag van je). Deze variabele wordt gevuld op basis van wisselende gegevens, en je weet dus nooit hoeveel elementen er in zitten, of wat de startwaarde is. Dat herdefiniëren gebeurt hier:

Code:
     ReDim Preserve sVelden(j)
     sVelden(j) = .Fields(i).Name
     j = j + 1

Bij matrixvariabelen heb je twee opties voor de startwaarde: 0 of 1. Dat hangt een beetje van je module declaraties af. Standaard begint een variabele met de waarde 0. Dus als je de eerste waarde toevoegt aan sVelden, dan wordt die dus in sVelden(0) gezet. Wil je met de waarde 1 beginnen, dan zet je bovenin de module de regel Option Base 1. Dan zit de eerste waarde dus in sVelden(1). Soms is het een beetje onhandig dat de matrix bij 0 begint, zoals in jouw geval omdat jouw tekstvakken en labels met de waarde 1 beginnen. Als ik jouw module zou hebben gemaakt, dan was ik dus met Option Base 1 begonnen, zodat de posities van de variabelen overeenkomen met de namen van de tekstvelden: svelden(1) is dan identiek aan Me("V" & j). Nu moet je dus steeds een waarde optellen of aftrekken om de twee te matchen.

Het herdefiniëren van een matrix variabele doe je met de regel ReDim Preserve sVelden(j). Dim heb je uiteraard regelmatig gebruikt; met Redim doe je eigenlijk hetzelfde: het opnieuw definiëren van een variabele. Dat hoeft uiteraard nooit bij een enkele variabele; die is namelijk al gedefinieerd. Zou je alleen ReDim sVelden(j) doen, dan wordt de variabele ook opnieuw ingesteld, maar wordt hij ook helemaal geleegd. Dat is uiteraard niet de bedoeling; je wilt de eerder ingelezen waarden niet verwijderen. Vandaar de toevoeging van het woord Preserve. Dit zorgt er voor dat de eerdere waarden blijven bestaan.

Code:
     For i = LBound(sVelden) To UBound(sVelden)

Met LBound(sVelden) en UBound(sVelden) lees je de laagste en hoogste waarde van een matrix uit. Ongeacht dus of de laagste een 0 of een 1 is. Die wetenschap heb je dus wel nodig in sommige procedures om de gegevens juist uit te lezen. Overigens lees je met i = .Fields.Count wel het juiste aantal velden uit, met is .Fields(0) dus het eerste veld; wil je de namen van alle velden uitlezen, dan heb je dit weer nodig: For i = 3 To i - 1
Deze regel leest dus de veldnamen uit vanaf het vierde veld tot het laatste. In de lus gebruik je LBound om vanaf de eerste waarde te starten, en UBound om tot de laatste door te gaan. Die waarden zijn dus afhankelijk van de instelling Option Base 1, of het ontbreken daarvan.

De laatste code die je aanhaalt wordt gebruikt in de eerdere versie waarbij de kolommen die niet gebruikt worden ook niet worden getoond. Daarbij zie je alle gebruikte kolommen netjes naast elkaar. Wat mij persoonlijk dan mooi lijkt, is dat de Totaal kolom daar ook netjes op aansluit. Alleen: die staat helemaal rechts op het rapport. En die kun je natuurlijk niet zomaar op een willekeurige plek neerzetten. Vandaar deze code:

Code:
     Me.Totaal.Left = Me("V" & i + 2).Left

Hierbij wordt na het vullen van de kolommen gekeken wat de laatst ingevulde kolom is (waarde i) en wordt van die kolom de horizontale positie op het rapport uitgelezen. De kolom V(i+1) laat ik dan open, en de kolom Totaal kan dan op de positie van V(i+2) worden neergezet. De horizontale positie van een kolom lees je dus uit met Left.

Laatste vraag: Als je een recordset opent, dan wil je meestal die records uitlezen. Niet altijd; in het voorbeeld lees ik ook de veldnamen uit, en dat hoef je natuurlijk maar één keer te doen. Maar bij het uitlezen van gegevens, open je eerst een recordset en ga je naar het begin van die recordset: het eerste record. Dat doe je met .MoveFirst. Daarna lees je het eerste record uit, vul je variabelen of formulier/rapport, en dan wil je natuurlijk naar het volgende record, om dat uit te lezen: en daar heb je het commando .MoveNext voor nodig! En het laatste punt: je wilt de procedure uiteraard stoppen als je alle records hebt gehad. Vandaar dat je het uitlezen van een recordset doet met een eigen lus: Do While Not .EOF. EOF staat voor: End Of File. Net zo als BOF staat voor: Begin Of File.
 
Bedankt voor de duidelijke uitleg :thumb::thumb:.
Helemaal super!!!!
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan