velden vanuit meerdere rijen samenvoegen in één veld middels query

Status
Niet open voor verdere reacties.

MJJBROEKHUI

Gebruiker
Lid geworden
6 jun 2001
Berichten
175
Goedemorgen,

Zou jullie mij willen helpen met het volgende?
Ik heb de volgende tabel met records. Deze tabel heeft drie kolommen.

Bedrijf;Naamemail
Bedrijf A;Pietje Puk;pietjepuk@bedrijfa.nl
Bedrijf A;Klaasje Vaak;klaasjevaak@bedrijfa.nl
Bedrijf B;Kees Kist;keeskist@bedrijfb.nl
Bedrijf B;Jan de Nul;jandenul@bedrijfb.nl

Ik wil middels een query de volgende gegevens krijgen in twee kolommen

Bedrijf;email
Bedrijf A;pietjepuk@bedrijfa.nl;klaasjevaak@bedrijfa.nl
Bedrijf B;keeskist@bedrijfb.nl;jandenul@bedrijfb.nl

Alle emailadressen van één bedrijf moeten in één veld samengevoegd worden.

Kunnen jullie mij hierbij helpen, hoe ik dat moet doen?
Alvast dank voor jullie hulp!

grt,
Marco
 
Je wilt dat met een query doen? Dat zal niet gaan. Misschien nog wel als je maar twee adressen hebt, dan kun je misschien in een query met twee DLookup functies i.c.m. DMax en Dmin de eerste en laatste persoon opzoeken, maar heb je er meer, dan werkt dat al niet meer want je krijgt er nooit meer dan 2 uit.
Je zult dus een functie moeten maken. De vraag is natuurlijk: waarom wil je dit? Want queries maak je met een bepaald doel, en email adressen wil je alleen in één string hebben als je gaat mailen. En dan is dat een prima moment om de adressen samen te voegen lijkt mij. Samenvoegen om het samenvoegen lijkt mijmeren beetje onzin.

Maar met een functie die m.b.v. een recordset door alle adressen loopt en die in één string zet om dat dan in een tijdelijke tabel op te slaan, kun je het resultaat in ieder geval wel maken.
 
Beste OctaFish,

Dank je wel voor jouw reactie. De reden dat ik dit wil is dat ik via Word een mailing uitstuur via mail & merge. Ik wil namelijk per bedrijf een mailing uitsturen naar alle medewerkers van dit bedrijf. De mailing is niet informatie en maar een verzoek (een factuur dus) om een bedrag aan mij over te maken. Als ik iedere medewerker individueel mail, betalen zij mij wellicht allemaal. Het moet voor de ontvangen duidelijk uit de email blijken, welke collega's nog meer deze email ontvangen hebben. Ik wil dus maar één regel per bedrijf en niet meerdere regels.

Je geeft aan dat dit niet kan via een query. In het verleden heb ik dit wel gedaan, maar deze database ligt mijn oude werkgever. Ik zal hem contacten of ik de code mag inzien. Ik zal de oplossing op het forum zetten, zodat we dit issue kunnen sluiten.

Mocht iemand anders ondertussen wel een oplossing hebben, houd ik mij natuurlijk wel aanbevolen. Ik heb niet zo'n zin om mijn oude werkgever hiervoor te bellen...

Dank!
 
Je kunt het niet via een query, want je hebt de data niet in één record staan. Je kunt er wellicht een kruistabel query van maken, en groeperen op Bedrijf met email als kolomkop. Dan heb je in ieder geval één record per bedrijf met alle email adressen er achter. In een vervolgquery kun je dan de emailvelden samenvoegen. En uiteraard de oplossing die ik al gaf (en die je vorige bedrijf vermoed ik ook heeft gebruikt) namelijk een (tijdelijke) tabel maken met alle email adressen in één veld. Is ook niet zo moeilijk, en de code daarvoor heb ik al een paar keer op het forum gezet.
Maar als je hem niet kan vinden, dan zet ik de routine wel weer online :).
 
Nou ja, ik ben een langslaper :).
Code:
Function EmailSamenvoegen()
Dim qd As DAO.QueryDef
Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset
Dim strSQL As String, sB As String
Dim varResult As String
Dim bAdd As Boolean, iAdd As Integer
Dim tdf As DAO.TableDef
Dim fld As DAO.Field

    On Error Resume Next
    CurrentDb.TableDefs.Delete "tblEmail"
    Set tdf = CurrentDb.CreateTableDef("tblEmail")
    With tdf
        'AutoNummer: Long met Unieke ID
        Set fld = .CreateField("BedrijfID", dbLong)
        fld.Attributes = dbAutoIncrField + dbFixedField
        .Fields.Append fld
        'Tekst veld: maximum 30 karakters; verplicht veld.
        Set fld = .CreateField("Bedrijf", dbText, 30)
        fld.Required = True
        .Fields.Append fld
        'Memo veld voor email adressen
        .Fields.Append .CreateField("Email", dbMemo)
        'Ja/Nee veldje. Altijd handig bij mailings
        .Fields.Append .CreateField("Gemaild", dbBoolean)
        'Valuta veld.
        .Fields.Append .CreateField("Bedrag", dbCurrency)
    End With
    CurrentDb.TableDefs.Append tdf
    
    strSQL = "SELECT Bedrijfsnaam, EmailNaam FROM tblBedrijven ORDER BY Bedrijfsnaam, EmailNaam"
    Set rs1 = CurrentDb.OpenRecordset(strSQL)
    Set rs2 = CurrentDb.OpenRecordset("tblEmail")
    With rs1
        .MoveLast
        .MoveFirst
        Do While Not .EOF
            If Not .Fields("[In regie bij]").Value = sB And bAdd = True Then
                rs2.AddNew
                rs2!Bedrijf = sB
                rs2!email.Value = varResult
                rs2.Update
                sB = .Fields("Bedrijf").Value
                varResult = !EmailNaam
                bAdd = False
            ElseIf Not .Fields("[In regie bij]").Value = sB And bAdd = False Then
                sB = .Fields("Bedrijf").Value
                varResult = !EmailNaam.Value
            Else
                If Not varResult = vbNullString Then varResult = varResult & "; "
                varResult = varResult & !EmailNaam.Value
                bAdd = True
            End If
            .MoveNext
        Loop
        rs1.Close
        rs2.Close
    End With

End Function
 
Goedemorgen ;-)

Dank je wel!. Echter, met functies en dergelijke ben ik niet echt bedreven. Ik zou eerlijk niet weten wat ik nu moet doen. Ik heb wel een tblBedrijven aangemaakt met de betreffende velden. Ook kan ik uit de code opmaken dat er tblEmail wordt gecreeerd, maar dan houd het echt bij mij op.

Mag ik je vragen of dit voor wil doen obv bijgaande database met de tabel die ik zojuist aangemaakt heb?

Dat zou erg fijn zijn!! Hopelijk vraag ik niet te veel.

Bekijk bijlage Database2.zip
 
Ach, wat is teveel? :)
Ik zal er vanavond even naar kijken.
 
Toevallig wel :). Ik heb gelijk maar een paar foutjes aan beide kanten weggehaald, waarvan de mijne trouwens het ergst waren, want er zaten nogal wat fouten in de code. Maar omdat-ie het nog niet deed, was dat natuurlijk niet erg :). Jouw fout was een (in mijn ogen) vervelende: je had van het email veld een hyperlink veld gemaakt. Nooit doen: altijd een tekstveld gebruiken. Zo is het onbruikbaar om mee te mailen.

Kijk maar eens wat er is veranderd.
 

Bijlagen

  • Database2.zip
    38,2 KB · Weergaven: 54
super en dank je wel!

Als ik had geweten dat ik deze functie met een knop moest starten, had ik het zelf ook geprobeerd. Of dit tot succes geleid had, durf ik niet te garanderen!
 
Ik weet wel zeker van niet, want er zat a) een stevige fout in de code (verkeerde veldnaam) en b) liep hij niet zoals hij zou moeten lopen. Nu wel :).
 
Voor de liefhebbers: ik heb er een algemene procedure van gemaakt, waarbij je zelf de tabel kunt opgeven die je wilt gebruiken, en meer dan één veld in de output kan zetten. Daarbij gelden de volgende voorwaarden:

1. Tabelnaam is verplicht
2. Veldnamen zijn verplicht; hierbij is een minimum van 2 velden verplicht (één groepeerveld, één verzamelveld)
2. Eerste veld is altijd het groepeerveld
3. Veldnamen moeten gescheiden zijn door een vast scheidingsteken. Dat kun je zelf opgeven bij het invoeren.

Hier de functie:
Code:
Function VeldenSamenvoegen(Tabel As String, Velden As String, Optional Delim As String) As Boolean
Dim qd As DAO.QueryDef
Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset
Dim strSQL As String, sB1 As String, sB2 As String, sDelim As String
Dim sV As Variant, arrResult() As Variant
Dim varResult As String
Dim bAdd As Boolean, iAdd As Integer, i As Integer
Dim tdf As DAO.TableDef
Dim fld As DAO.Field

    On Error Resume Next
    '-------------------------------------------------------------------------------------------------------
    'Veldnamen uitsplitsen in een matrix om de tabel aan te kunnen maken.
    'Delimiter komt ofwel uit de procedure, ofwel is een vast teken.
    '-------------------------------------------------------------------------------------------------------
    If Delim = vbNullString Then sdelimn = "|" Else: sDelim = Delim
    If InStr(1, Velden, sDelim) = 0 Then
        MsgBox "Er is maar één veld ingevuld; hiermee kan niet worden samengevoegd.", vbOKOnly + vbCritical
        Exit Function
    Else
        sV = Split(Velden, sDelim)
        ReDim arrResult(UBound(sV))
    End If
    
    '-------------------------------------------------------------------------------------------------------
    'Tijdelijke tabel aanmaken met de gevraagde velden
    '-------------------------------------------------------------------------------------------------------
    CurrentDb.TableDefs.Delete "tmpSamenvoegen"
    On Error GoTo Hell
    Set tdf = CurrentDb.CreateTableDef("tmpSamenvoegen")
    With tdf
        '---------------------------------------------------------------------------------------------------
        'AutoNummer: Long met Unieke ID
        '---------------------------------------------------------------------------------------------------
        Set fld = .CreateField("KeyID", dbLong)
        fld.Attributes = dbAutoIncrField + dbFixedField
        .Fields.Append fld
        For i = LBound(sV) To UBound(sV)
            '-----------------------------------------------------------------------------------------------
            'Tekstveld: maximum 100 karakters; verplicht veld. Dit is het groepeerveld.
            '-----------------------------------------------------------------------------------------------
            If i = LBound(sV) Then
                Set fld = .CreateField(sV(i), dbText, 100)
                fld.Required = True
                .Fields.Append fld
            Else
                '-------------------------------------------------------------------------------------------
                'Memoveld voor overige velden. Gebruik dit als er teveel records zijn.
                '-------------------------------------------------------------------------------------------
                .Fields.Append .CreateField(sV(i), dbMemo)
                '-------------------------------------------------------------------------------------------
                'tekstveld voor overige velden. Gebruik dit als er weinig records zijn
                '-------------------------------------------------------------------------------------------
                '.Fields.Append .CreateField(sV(i), dbText, 255)
            End If
        Next i
        '---------------------------------------------------------------------------------------------------
        'Ja/Nee veldje. Altijd handig bij mailings.
        '---------------------------------------------------------------------------------------------------
        .Fields.Append .CreateField("Gemaild", dbBoolean)
        '---------------------------------------------------------------------------------------------------
        'Valuta veld. Je zal maar geld willen hebben.
        '---------------------------------------------------------------------------------------------------
        .Fields.Append .CreateField("Bedrag", dbCurrency)
    End With
    CurrentDb.TableDefs.Append tdf
    
    '-------------------------------------------------------------------------------------------------------
    'Query string opbouwen om de gegevens uit te lezen.
    'Hierbij is het éérste veld altijd het groepeerveld.
    '-------------------------------------------------------------------------------------------------------
    strSQL = "SELECT "
    For i = LBound(sV) To UBound(sV)
        strSQL = strSQL & sV(i)
        If Not i = UBound(sV) Then strSQL = strSQL & ", "
    Next i
    strSQL = strSQL & " FROM " & Tabel & " ORDER BY " & sV(LBound(sV)) & ", " & sV(LBound(sV) + 1)
    
    '-------------------------------------------------------------------------------------------------------
    'Recordsets openen; tijdelijke tabel en query
    '-------------------------------------------------------------------------------------------------------
    Set rs1 = CurrentDb.OpenRecordset(strSQL)
    Set rs2 = CurrentDb.OpenRecordset("tmpSamenvoegen")
    
    With rs1
        .MoveLast
        .MoveFirst
        '---------------------------------------------------------------------------------------------------
        'Door query lopen en de eerste waarden toewijzen aan de matrix variabele
        '---------------------------------------------------------------------------------------------------
        sB1 = .Fields(0).Value
        arrResult(LBound(arrResult)) = .Fields(0).Value
        sB2 = sB1
        Do While Not .EOF
            '-----------------------------------------------------------------------------------------------
            'Door de overige records lopen en de waarden toewijzen aan de matrix variabele
            '-----------------------------------------------------------------------------------------------
            Do Until sB1 <> sB2
                For i = LBound(sV) + 1 To UBound(sV)
                    If Not Nz(.Fields(i), "") = "" Then
                        If Not arrResult(i) = vbNullString Then arrResult(i) = arrResult(i) & "; "
                        arrResult(i) = arrResult(i) & .Fields(i).Value
                    End If
                Next i
                .MoveNext
                If Not .EOF Then
                    sB2 = .Fields(0).Value
                Else
                    sB2 = ""
                    Exit Do
                End If
            Loop
            '-----------------------------------------------------------------------------------------------
            'De ingelezen waarden in de tijdelijke tabel wegschrijven
            '-----------------------------------------------------------------------------------------------
            rs2.AddNew
            For i = LBound(arrResult) To UBound(arrResult)
                rs2.Fields(i + 1).Value = arrResult(i)
                arrResult(i) = Null
            Next i
            rs2.Update
            If Not .EOF Then
                sB1 = .Fields(0).Value
            Else
                sB1 = ""
                Exit Do
            End If
            arrResult(LBound(arrResult)) = .Fields(0).Value
        Loop
        '---------------------------------------------------------------------------------------------------
        'Recordsets sluiten
        '---------------------------------------------------------------------------------------------------
        rs1.Close
        rs2.Close
    End With
    VeldenSamenvoegen = True
    Exit Function
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Hell:
    VeldenSamenvoegen = False
End Function

En zo gebruik je hem op een formulier (achter een knop bijvoorbeeld)
Code:
Private Sub cmdEmail_Click()
Dim sTabel As String, sVelden As String, sDelim As String

    sTabel = InputBox("Typ de naam van de tabel:", "Tabel kiezen", "Klanten")
    sDelim = InputBox("Typ een scheidingsteken, bijvoorbeeld '|'", "Scheidingsteken typen", "|")
    sVelden = InputBox("Typ de veldnamen." & vbLf & "Veldnamen moet je scheiden met een delimiter (" & sDelim & ")", "Velden kiezen", "Plaatsnaam|Achternaam|Emailadres")
     
    If VeldenSamenvoegen(sTabel, sVelden, sDelim) = True Then
        MsgBox "Klaar, samenvoegen met meerdere velden is gelukt!", vbOKOnly
    Else
        MsgBox "Niet helemaal gelukt, vrees ik... :(", vbOKOnly
    End If
End Sub

't Is een hoop code, maar hij is erg flexibel :).

IK maak ook nog een voorbeeldje waarbij je m.b.v. keuzelijsten uit de tabellen kan kiezen, en vervolgens per tabel uit de gewenste velden. Is uiteraard nog wat gebruiksvriendelijker. Deze techniek staat ook beschreven in de Access cursus, als je niet kan wachten :).
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan