Bericht 1 van 10NL Computer Forum ~ SQL & Programmeren Van | : | Hugo Kornelis | Datum | : | 12-10-2004 |
Aan | : | Allen | MsgID | : | 1463.1 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi allemaal,
In Access 97 probeer ik een formulier zodanig te dresseren dat bij overschakelen naar een ander formulier de huidige positie wordt "onthouden"; bij her-activeren van het betreffende formulier moeten dan eventuele wijzigingen in de recordbron zichtbaar worden, maar zo mogelijk (als het record niet verwijderd is) moet de "onthouden" positie worden hersteld. Ik heb daarvoor de volgende gebeurtenisprocedures gemaakt:
Private Sub Form_Activate()
Me.Requery
Me.RecordsetClone.FindLast "Sleutel <= '" & OudeSleutel & "'"
NieuweSleutel = Me.RecordsetClone!Sleutel
If NieuweSleutel <= OudeSleutel Then
DoCmd.FindRecord NieuweSleutel, , True
End If
End Sub
Private Sub Form_Deactivate()
OudeSleutel = Me.Sleutel
End Sub
Dit werkt prima, zolang de sleutels allemaal met een hoofdletter beginnen, of allemaal met een kleine letter. Maar niet als het gemengd is. Dan worden de sleutelwaardes in het formulier gesorteerd op ASCII-waarde (dus eerst alle hoofdletters alfabetisch, dan de kleine letters alfabetisch), maar de FindLast en en daaropvolgende vergelijking in de Activate procedure beschouwt kleine en grote letters als gelijk.
Is hier een oplossing voor?
Alvast bedankt!
Groetjes, Hugo
Bericht 2 van 10NL Computer Forum ~ SQL & Programmeren Van | : | John Kopmels (Sysop) | Datum | : | 12-10-2004 |
Aan | : | Hugo Kornelis | MsgID | : | 1463.2 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi Hugo
> In Access 97 probeer ik een formulier zodanig te dresseren dat bij
overschakelen naar ander form de huidige positie wordt "onthouden"
Code iets aangepast
Option Explicit
'
' maak Sleutel een Public (in een globale module)
' als j'm ook na het sluiten en opnieuw openen wil
'
Private Sleutel As String
------------------------------------------------------
Private Sub Form_Activate()
'
' haal nieuw waardes op bij activeren
Me.Requery
'
' ga terug naar vorige record pointer
With Me.RecordsetClone
.FindLast "au_id=" & Chr(34) & Sleutel & Chr(34)
If Not .NoMatch Then Me.Bookmark = .Bookmark
End With
'
End Sub
Private Sub Form_Deactivate()
'
' bewaar record pointer
Sleutel = Me.au_id
'
End Sub
> Dit werkt prima, zolang de sleutels allemaal met een hoofdletter
beginnen, of allemaal met een kleine letter. Maar niet als het gemengd is.
Dan worden de sleutelwaardes in het formulier gesorteerd op ASCII-waarde
(dus eerst alle hoofdletters alfabetisch, dan de kleine letters alfabetisch),
maar de FindLast en en daaropvolgende vergelijking in de Activate procedure
beschouwt kleine en grote letters als gelijk. Is hier een oplossing voor?
Zoals je al gemerkt hebt is Access is niet Case Sensitive maar er zijn
verschillende workarounds mogelijk, de makkelijkste lijkt me in de query
een verborgen kolom met daarin de Ascii waarde te maken en daarop te sorteren
SELECT dbo_authors.au_id,
dbo_authors.au_fname,
dbo_authors.au_lname
FROM dbo_authors
ORDER BY (Asc([au_lname]))
Andere mogelijkheden:
- In code met een rs werken en dan
StrComp of Option Compare Binary
- een String 2 Hex functie en daarop sorteren
Groetjes --John
Bericht 3 van 10NL Computer Forum ~ SQL & Programmeren Van | : | Hugo Kornelis | Datum | : | 13-10-2004 |
Aan | : | John Kopmels (Sysop) | MsgID | : | 1463.3 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi John,
> verschillende workarounds mogelijk
Bedankt voor de suggesties! Ik ga er morgen meteen mee aan de slag en laat je weten hoe het verder gaat.
Groetjes, Hugo
PS: Had je mijn andere bericht ook gezien? Bericht nummer #191140.
Bericht 4 van 10NL Computer Forum ~ SQL & Programmeren Van | : | John Kopmels (Sysop) | Datum | : | 13-10-2004 |
Aan | : | Hugo Kornelis | MsgID | : | 1463.4 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
>> PS: Had je mijn andere bericht ook gezien? Bericht nummer #191140. <<
Hoi Hugo,
Ja zelfs heel even naar gekeken :-)
Maar (meestal) begin van de week heel erg druk, maar kom er
later deze week nog op terug (als ik een goeie ingeving heb)
Groetjes --John
Bericht 5 van 10NL Computer Forum ~ SQL & Programmeren Van | : | John Kopmels (Sysop) | Datum | : | 13-10-2004 |
Aan | : | Hugo Kornelis | MsgID | : | 1463.5 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
>> Dan worden de sleutelwaardes in het formulier gesorteerd op ASCII-waarde
(dus eerst alle hoofdletters alfabetisch, dan de kleine letters alfabetisch) <<
PS ik hoop dat ik het goed begrepen heb en het hier niet goed staat
Access is by default niet case sensitive en sorteerd dus alles door elkaar
a 97
A 65
b 98
B 66
De oplossing sorteren op Asc(Veldnaam) sorteerd ze dus wel gegroepeerd
A 65
B 66
a 97
b 98
Een andere is nog, eerst naar UCASE omzetten
SELECT dbo_authors.au_id,
dbo_authors.au_fname,
dbo_authors.au_lname,
UCase([au_lname]) AS U
FROM dbo_authors
ORDER BY UCase([au_lname]);
Groetjes --John
Bericht 6 van 10NL Computer Forum ~ SQL & Programmeren Van | : | John Kopmels (Sysop) | Datum | : | 13-10-2004 |
Aan | : | Hugo Kornelis | MsgID | : | 1463.6 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi Hugo
> Ik heb daarvoor de volgende gebeurtenisprocedures gemaakt:
Ook nog even wat verder naar gekeken en het volgende voor je
gemaakt, als je nu het debug venster vertikaal ernaast schikt
en open houd dan zie je precies wat er gebeurt, de extra code
is nodig vanwege de requery en de volgorde van de events ...
' in een Globale module's declaratie sectie :
Public Sleutel As String
'------------------------------------------------------------
' In de Form klasse module's declaratie sectie :
Option Explicit
'
Private bOpen As Boolean
' ------------------------------------------------------------
' In de Form klasse module zelf :
Private Sub Form_Activate()
'
Debug.Print "Activate" & vbTab & Sleutel
'
If bOpen Then
Me.Requery
Debug.Print "Requery" & vbTab & Sleutel
End If
'
With Me.RecordsetClone
.FindLast "au_id=" & Chr(34) & Sleutel & Chr(34)
If Not .NoMatch Then
Me.Bookmark = .Bookmark
Debug.Print Sleutel & " gevonden"
Else
Debug.Print Sleutel & " niet gevonden"
End If
End With
'
bOpen = True
'
End Sub
Private Sub Form_Deactivate()
'
If bOpen Then Sleutel = Me.au_id
Debug.Print "De-Activate" & vbTab & Sleutel
'
End Sub
Private Sub Form_Load()
Debug.Print "Laad"
bOpen = False
End Sub
Private Sub Form_Close()
Debug.Print "Sluit"
End Sub
Private Sub Form_Open(Cancel As Integer)
Debug.Print "Open"
End Sub
Private Sub Form_Unload(Cancel As Integer)
Debug.Print "Ontlaad"
bOpen = False
Sleutel = Me.au_id
End Sub
Groetjes --John
Bericht 7 van 10NL Computer Forum ~ SQL & Programmeren Van | : | Hugo Kornelis | Datum | : | 14-10-2004 |
Aan | : | John Kopmels (Sysop) | MsgID | : | 1463.7 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi John,
> De oplossing sorteren op Asc(Veldnaam) sorteerd ze dus wel gegroepeerd
> A 65
> B 66
> a 97
> b 98
Helaas is het veld meer dan n teken lang. En ook de onderlinge sortering van AA, Ab en AC moet goed zijn.
> Een andere is nog, eerst naar UCASE omzetten
>
> SELECT dbo_authors.au_id,
> dbo_authors.au_fname,
> dbo_authors.au_lname,
> UCase([au_lname]) AS U
> FROM dbo_authors
> ORDER BY UCase([au_lname]);
Die vind ik leuk. Dat heeft namelijk als voordeel dat de volgorde op het scherm meteen ook wat logischer overkomt.
Wat is eigenlijk beter: deze query opgeven als recordbron voor het formulier, of deze query maken, opslaan in de database en dan de naam van die query opgeven als recordbron?
Bedankt voor deze goede tip!!
Groetjes, Hugo
Bericht 8 van 10NL Computer Forum ~ SQL & Programmeren Van | : | Hugo Kornelis | Datum | : | 14-10-2004 |
Aan | : | John Kopmels (Sysop) | MsgID | : | 1463.8 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi John,
> Ook nog even wat verder naar gekeken en het volgende voor je
> gemaakt
Geweldig! Ik heb hem niet zo gehouden als 'ie was (ik wil namelijk niet dat de oude positie ook bewaard wordt als het formulier gesloten en dan weer geopend wordt; daarentegen wil ik wel in het geval een record niet meer bestaat positioneren op het daar direct aan voroafgaande record). De code die ik nu gebruik is als volgt:
* In de recordbron heb ik een veld "Sleutel" toegevoegd waarin de UCase functie wordt gebruikt om de sleutel vand e tabel in uppercase te zetten; hier is de recordbron ook op gesorteerd.
In de declaraties van het formulier:
Option Explicit
Public OudeSleutel As String
En dan de volgende gebeurtenisprocedures:
Private Sub Form_Activate()
Me.Requery
With Me.RecordsetClone
.FindLast "Sleutel <= " & Chr(34) & OudeSleutel & Chr(34)
If Not .NoMatch Then Me.Bookmark = .Bookmark
End With
End Sub
Private Sub Form_Deactivate()
OudeSleutel = Me.Sleutel
End Sub
Private Sub Form_Open(Cancel As Integer)
If Me.Filter <> "" Then
Me.Koptekst.Caption = Me.Koptekst.Caption & " (selectie)"
Else
Me.Koptekst.Caption = Me.Koptekst.Caption & " (overzicht)"
End If
End Sub
Door in de activate te zoeken op Sleutel <= OudeSleutel vindt ik f de oude positie, f (als die niet meer bestaat) de positie daar onmiddelijk aan voorafgaand. Als de oude positie de eerste was (en nu dus verwijderd), dan geeft deze zoek-operatie het laatste record als resultaat, daarom wijzig ik Me.Bookmark alleen als er geen sprake is van een NoMatch. Goed truk overigens met die bookmark - die kende ik niet (vandaar dat ik in mijn code zo'n lelijke kludge had staan).
Omdat ik bij sluiten en daarna weer openen van het formulier NIET de oude positie wil vasthouden heb ik geen gebeurtenisprocedures meer nodig voor laden, onladen en sluiten en geen extra acties in de gebeurtenisprocedure voor openen. Ook de lokale variabele bOpen is niet nodig; OudeSleutel kan een globale variabele voor het formulier worden en hoeft niet in een globale module.
Het nadeel van deze methode is dat ik nu voor alle tabellen waar ik een formulier voor maak een query moet maken om het extra veld Sleutel en de juiste sortering toe te voegen. Het voordeel is echter dat ik de bovenstaande code zonder enige wijziging kan knippen en plakken in alle formulieren (tot nu toe moest ik steeds de naam van de sleutelvelden overal aanpassen, en dat vergeet je atlijd op ten minste n plaats). Bovendien werkt deze truc ook voor tabellen met composite key (dan komt in de query gewoon zoiets als SELECT UCase(Kol01) & UCase(Kol02) AS Sleutel, ...
Ontzettend bedankt, John! Zonder jouw hulp zou ik hier voorlopig nog niet uit zijn gekomen.
Groetjes, Hugo
Bericht 9 van 10NL Computer Forum ~ SQL & Programmeren Van | : | John Kopmels (Sysop) | Datum | : | 14-10-2004 |
Aan | : | Hugo Kornelis | MsgID | : | 1463.9 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi Hugo
> Wat is eigenlijk beter: deze query opgeven als recordbron voor het formulier, of deze
query maken, opslaan in de database en dan de naam van die query opgeven als recordbron?
Een opgeslagen query is altijd sneller, deze wordt de eerst keer dat hij runt gecompileerd
net als in sql server wordt het beste executie plan bepaalt, oa mbv de Rushmore technology
Er is zelfs een ongedocumenteerde truc om het showplan uit te lezen, je daarvoor wel de
registry tweaken, voor Access97 is dat (als de Debug subsleutel er nog niet is dan maken)
SOFTWARE\MICROSOFT\JET\3.5\Engines\Debug
In deze sleutel in hoofdletters een nieuwe string waarde aanmaken : JETSHOWPLAN en de waarde
instellen op ON (of OFF als j'm weer uit wil zetten, let op: het bestand kan groot worden)
Onder Windows XP wordt in de data folder (systeeminstelling) een bestandje
showplan.out gemaakt, oudere versies in de zelfde map als de database zelf
Verschil is pas meetbaar bij complexe queries of qeuries die vaak gerunt
worden, vaak hou je de query in een form of in code vanwege portability.
Groetjes --John
Bericht 10 van 10NL Computer Forum ~ SQL & Programmeren Van | : | Hugo Kornelis | Datum | : | 14-10-2004 |
Aan | : | John Kopmels (Sysop) | MsgID | : | 1463.10 |
Onderwerp | : | Access: CasE-seNSiTivE | Forum | : | ws-nlcomputer |
Hoi John,
> > Wat is eigenlijk beter: deze query opgeven als recordbron voor het
> formulier, of deze
> query maken, opslaan in de database en dan de naam van die query opgeven
> als recordbron?
>
> Een opgeslagen query is altijd sneller, deze wordt de eerst keer dat hij
> runt gecompileerd
> net als in sql server wordt het beste executie plan bepaalt, oa mbv de
> Rushmore technology
Ok, dan is dat hoe ik het ga doen. Bedankt!!
Groetjes, Hugo