Collation in Access

Status
Niet open voor verdere reacties.

Visara

Gebruiker
Lid geworden
10 mrt 2019
Berichten
217
Goede avond,

Een gebruiker kan via een 'unbound textbox' de query resultaten filteren.
Access ziet hoofdletters en kleine letters hier als inwisselbaar, dat is prettig.
Dit schijnt 'collation' te heten...?

Mijn vraag:
Kan ik dit uitbreiden zodat bijv de volgende tekens ook als inwisselbaar worden gezien:
ë é e è & c ç & í ï i & n ñ etc etc
Is prettig voor de gebruiker, ik zal toch niet de eerste zijn met deze wens. Zoekmachines hebben dit denk ik ook ingebouwd.
Ik hoop dat ik iets aan kan vinken in Tools-References, maar ik vrees...

Met vriendelijke groet,
Vïsärá
 
Laatst bewerkt:
Kan ik dit uitbreiden zodat bijv de volgende tekens ook als inwisselbaar worden gezien:
Simpel antwoord: nee. Hoofd-kleine letters zijn verwant, dus die kun je eventueel 'vangen' met een speciale insteek in Access. Standaard gebruikt Access Compare Database, maar er zijn er nog twee:
PHP:
Option Compare Binary ' Vergelijkingsvorm: "AAA" is kleiner dan "aaa". '
Option Compare Text ' Vergelijkingsvorm: "AAA" is gelijk aan "aaa". '
Wil je dus onderscheid maken tussen hoofd- en kleine letters, dan kun je Compare Binary gebruiken op een formulier.

Collation is overigens niks anders dan een term voor sortering :).
 
Helaas.
Bedankt voor uw uitleg!

Wellicht in Office 2030, we wachten rustig af ;)
 
Jij geeft snel op :). Je kunt natuurlijk prima een functie gebruiken die de niet-gewenste karakters vervangt door de gewenste. Dus die functie vervangt alle "à,á,ä,â" door "a", etc. Zo'n functie is niet moeilijk te maken en te implementeren.
 
En omdat ik de beroerdste niet ben, hier twee voorbeelden van functies die je kan gebruiken.
Code:
Function StripAccent(theString As String)
Dim a As String * 1
Dim B As String * 1
Dim i As Integer

    Const AccChars = "ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðñòóôõöùúûüýÿ"
    Const RegChars = "SZszYAAAAAACEEEEIIIIDNOOOOOUUUUYaaaaaaceeeeiiiidnooooouuuuyy"
    
    For i = 1 To Len(AccChars)
        a = Mid(AccChars, i, 1)
        B = Mid(RegChars, i, 1)
        theString = Replace(theString, a, B)
    Next
    StripAccent = theString
End Function

Code:
Function VervangDiacriet(sWaarde As String) As String
Dim iLen As Integer, i As Integer
Dim sLetter As String, sTmp As String

    iLen = Len(sWaarde)
    For i = 1 To iLen
        sLetter = Mid(sWaarde, i, 1)
        Select Case sLetter
            Case "À", "Á", "Â", "Ã", "Ä", "Å", "Æ"
                sTmp = sTmp & "A"
            Case "à", "á", "â", "ã", "ä", "å", "æ"
                sTmp = sTmp & "a"
            Case "Ç"
                sTmp = sTmp & "C"
            Case "ç"
                sTmp = sTmp & "c"
            Case "È", "É", "Ê", "Ë"
                sTmp = sTmp & "E"
            Case "è", "é", "ê", "ë"
                sTmp = sTmp & "e"
            Case "Ñ"
                sTmp = sTmp & "N"
            Case "ñ"
                sTmp = sTmp & "n"
            Case "Ò", "Ó", "Ô", "Õ", "Ö", "Ø", "Œ"
                sTmp = sTmp & "O"
            Case "ò", "ó", "ô", "õ", "ö", "ø", "œ"
                sTmp = sTmp & "o"
            Case "Š"
                sTmp = sTmp & "S"
            Case "š"
                sTmp = sTmp & "s"
            Case "Ù", "Ú", "Û", "Ü"
                sTmp = sTmp & "U"
            Case "ù", "ú", "û", "ü"
                sTmp = sTmp & "u"
            Case "Ý", ""
                sTmp = sTmp & "Y"
            Case "ÿ"
                sTmp = sTmp & "y"
            Case Else
                sTmp = sTmp & sLetter
        End Select
        VervangDiacriet = sTmp
    Next
End Function
 
Ah, nice :)
Zoeken naar zo'n functie was de volgende stap, dat van Office 2030 was een geintje hoor.
Bedankt voor de mooie functies.

Je schreef "(...)Hoofd-kleine letters zijn verwant(...)". Ik dacht dat ze met een functie verwant gemáákt kunnen worden door de makers van bijv MS Office, maar dat ze dat op een basis-niveau niet zijn.
Daarom dacht ik dat er misschien een inactieve module aangevinkt kon worden in Referenties, want als ze met een ingebouwde functie hoofd- en kleine letters aan elkaar linken hebben ze misschien ook wat gemaakt voor wat ik wil.

Ik ga aan de slag met een functie, fijne avond!
 
Laatst bewerkt:
Nee, dat hebben ze niet. Sowieso zijn het allemaal aparte ASCII tekens, maar ‘normale’ letters kun je met de functies LCASE en UCASE omzetten. Dat is de verwantschap die ik bedoelde. Zo’n koppeling is er echter niet voor a-á etc.
 
Mag ik u nog een vervolgvraag stellen?
De kolom [omschrijving] is zichtbaar voor de gebruiker.
De kolom StripAccent([omschrijving]) is niet zichtbaar voor de gebruiker. Deze krijgt als criterium een verwijzing:
Like "*" & [Forms]![Formnaam]![txtOmschrijving] & "*"

Twee dingen:
Access maakt bij gebruik van functie StripAccent van alle '"bijzondere" letters hoofdletters. Dus cérène wordt cErEne. Dat is op zich niet erg, want de gebruiker ziet deze kolom niet.
Dit komt denk ik omdat Access hoofd- en kleine letters inwisselbaar vindt en als je dan naar de functie kijkt zie je dat de hoofdletters aan het begin staan en dan begrijp ik dat het zo werkt.

Een ander ding is wel jammer:
Ik wil graag dat de gebruiker niet "gestraft" wordt als hij in het zoekveld gebruik maakt van de bijzondere letters.
Ik dacht het als volgt op te kunnen lossen in de Query criteria:
Like "*" & StripAccent([Forms]![Formnaam]![txtOmschrijving]) & "*" Access geeft echter de foutmelding dat de formule te complex is.

Zo ziet de echte SQL WHERE code er uit:
Code:
WHERE ((([1039_Odin].eenheid) Like "*" & [Forms]![fOdin]![txtEenheid] & "*") AND
(([1039_Odin].inhoud) Like "*" & [Forms]![fOdin]![txtInhoud] & "*") AND
(([1039_Odin].kwaliteit) Like "*" & [Forms]![fOdin]![txtKwaliteit] & "*") AND
((StripAccent([omschrijving])) Like "*" & [COLOR="#FF0000"][B][Forms]![fOdin]![txtOmschrijving][/B][/COLOR] & "*") AND
((StripAccent([merk])) Like "*" & [COLOR="#FF0000"][B][Forms]![fOdin]![txtMerk][/B][/COLOR] & "*"))
Ik zou de functie StripAccent graag op de rode stukjes toe willen passen. Mijn pogingen tot dusver faalde, ik kreeg de foutmelding dat het te complex werd.
 
Omdat functies gebruiken in zoekargumenten de performantie van de queries serieus naar beneden haalt kan dit een geldige reden zijn om je database te denormaliseren: voeg een berekend veld aan je tabel toe waarin je het resultaat van de functie stripaccent in opslaat. Je kan dit veld eventueel onzichtbaar in je formulier opnemen. Dat scheelt de helft aan functies in je query.
Ik weet niet als je eigengemaakte functies kunt gebruiken bij een berekend veld in je tabel, anders moet je een gewoon tekstveld toevoegen dat je automatisch laat updaten afterinsert en afterupdate van het originele veld.
 
Hoi Noella,

Bedankt voor je reactie.
Begrijp ik goed dat je reactie alleen gaat over het GROENE?
Code:
WHERE ((([1039_Odin].eenheid) Like "*" & [Forms]![fOdin]![txtEenheid] & "*") AND
(([1039_Odin].inhoud) Like "*" & [Forms]![fOdin]![txtInhoud] & "*") AND
(([1039_Odin].kwaliteit) Like "*" & [Forms]![fOdin]![txtKwaliteit] & "*") AND
(([COLOR="#00FF00"][B]StripAccent([omschrijving][/B][/COLOR])) Like "*" & [Forms]![fOdin]![txtOmschrijving] & "*") AND
(([COLOR="#00FF00"][B]StripAccent([merk])[/B][/COLOR]) Like "*" & [Forms]![fOdin]![txtMerk] & "*"))
Je adviseert dus om Functie([Tabelveld]) niet in de query 'uit te laten rekenen', maar in een calculated field in de tabel?
Voor de zekerheid geef ik nog aan dat de database er geen problemen mee had om Functie([Tabelveld]) in de query uit te laten rekenen. Maar om traagheid te voorkomen dus beter direct in een calculated field in een tabel?
De tabel wordt door de gebruiker niet aangepast en veranderd niet tijdens de gebruikerssessie. Het is een productoverzichttabel. Maakt dat het gebruik van een calculated field met Functie([Tabelveld]) in de tabel zelf extra aantrekkelijk, omdat de tabel zelf tijdens de gebruikerssessie niet veranderd?
 
Een berekende waarde vergelijken met een andere berekende waarde is altijd heel zwaar voor de query engine, dat heeft niets te maken of de waarde aangepast kan worden of niet. Op de moment dat de query de waarde opvraagt is die wat hij is.
Als het veld in de tabel wordt berekend, hoeft dat niet meer in de query en maakt de query eenvoudiger en sneller. Dat neemt dan de helft van de complexiteit van je query weg zodat die waarschijnlijk uitvoerbaar wordt door Access. Als de tabel niet aanpasbaar is door de gebruiker is het nog sneller om het veld te berekenen en de berekende waarde op te slaan in de tabel in een apart tekstveld, dan kan je die zelfs indexeren. Je moet die dan alleen aanpassen als de originele waarde wordt aangepast.
Ik neem aan dat je formulier een zoekformulier is dat on the fly wordt ingevuld. Als de query dan nog 'to complex to perform' geeft kan je de zoekwaarde ook laten berekenen in een (verborgen) berekend veld op je formulier. Op deze manier hoef je in je query zelf geen berekeningen meer te maken. Ik vermoed dat Access het bij parsing van de query moeilijk heeft met de combinatie van de like met wildcards en de berekening.
 
Access maakt bij gebruik van functie StripAccent van alle '"bijzondere" letters hoofdletters. Dus cérène wordt cErEne.
Dit komt doordat je de verkeerde Compare in je module gebruikt. Zoals ik al heb uitgelegd, maakt Access daar verschil in. Je moest dus bovenin de module Compare Binary zetten, dan werkt de functie wél goed.
De rest van je verhaal (en het antwoord van noellla) moet ik nog eens goed doorlezen, maar volgens mij kan het een stuk simpeler. En zonder berekend veld in je tabel. Nergens voor nodig.
 
Dat is suf van me, u schreef het al.
Dank voor de herhaling
 
@Noella
Een direct Calculated Field in de tabel accepteert het systeem niet. Het systeem accepteert geen eigen functie in een calculated field, lijkt het.
Ik kan dit veld wel maken via een append query. De tabel komt sowieso op die manier tot stand, dus dat werkt prima.

Als ik dit Calculated Field in een query zet en het query criterium "door de functie haal" vindt Access het nog steeds te complex. Als ik de query direct open en in de popup voor de parameter handmatig iets invul doet hij het trouwens wel.
Maar als ik dit via het formulier doe, dan vind Access het te complex. Helaas...
Dit werkt dus niet:
Code:
Like "*" & FUNCTIE([Forms]![Formnaam]![UnboundTextfield]) & "*"

Bedankt voor jullie hulp!
 
Je hele query is mij veel te gecompliceerd. Zoals ik al schreef in #12: het kan vele malen simpeler.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan