Hallo zusammen,
gibt es irgendeine Möglichkeit, dieses Statement funktionstüchtig zu bekommen?
Me!Liste.RowSource = "SELECT * , (33959 * acos( cos( radians('" & Me.Breitengrad & "') ) * cos( radians(Geo.latitude) )* cos( radians(Geo.longitude ) - radians('" & Me.Laengengrad & "') ) + sin(radians('" & Me.Breitengrad & "') ) * sin( radians(Geo.latitude) ))) AS distanz " & _
"FROM Geo " & _
"HAVING distanz < 20 "
Ziel ist es, in meinem Listenfeld, nur die Datensätze aus der Tabelle "Geo" abzubilden, welcher innerhalb des 20km Umkreises vom Breitengrad aus "Me.Breitengrad " und dem Längengrad aus "Me.Laengengrad " liegen.
Ich bin leider nicht wirklich fit in sachen VBA und allgemein auch Access.
Bisher sind leider alle meine Lösungsansätze gescheitert.
Scheinbar kann Access nicht mit den Funktionen "acos" und "radians" umgehen.
Habt ihr eine Idee wie ich das hinbekommen kann?
Vielen lieben Dank bereits für Eure Hilfe.
Viele Grüße
Adrjan
Hallo,
versuche das mal so:
Me!Liste.RowSource = "SELECT * FROM Geo WHERE (33959 * acos( cos( radians('" & Me.Breitengrad & "') ) * cos( radians(Geo.latitude) )* cos( radians(Geo.longitude ) - radians('" & Me.Laengengrad & "') ) + sin(radians('" & Me.Breitengrad & "') ) * sin( radians(Geo.latitude) ))) < 20"
Zeilenumbrüche musst Du einfügen, war ich jetzt zu faul dazu.
Das berechnet Feld wird nicht benötigt. Wenn Du es sehen willst, musst Du das mit der gleichen Formel eintragen. Die Formel wird also für das Feld benötigt und die WHERE Klausel.
Hallo,
die Radians-Funktion gibt es in Access-VBA/SQL nicht...
Möglicherweise geht dieses:
Dim strSQL as String
strSQL =SELECT * , fktDist( " & str(Me!Breitengrad) & ", latitude , longitude, " & str(Me!Laengengrad) & ") AS distanz FROM Geo HAVING distanz < 20
Me!Liste.RowSource = strSQL
und in einem Standard-Modul
ZitatPublic Function fktDist(Breitengrad As Double, latitude As Double, longitude As Double, Laengengrad As Double)
fktDist = 33959 * acos(Cos(Atn(Breitengrad)) * Cos(Atn(latitude)) * Cos(Atn(longitude) - Atn(Laengengrad)) + Sin(Atn(Breitengrad)) * Sin(Atn(latitude)))
End Function
Vielen Dank für eure Antworten.
Leider scheint es noch nicht zu funktionieren.
Dim strSQL as String
strSQL = "SELECT * , fktDist( " & str(Me!Breitengrad) & ", latitude , longitude, " & str(Me!Laengengrad) & ") AS distanz FROM Geo HAVING distanz < 20"
Me!Liste.RowSource = strSQL
Public Function fktDist(Breitengrad As Double, latitude As Double, longitude As Double, Laengengrad As Double)
fktDist = 33959 * acos(Cos(Atn(Breitengrad)) * Cos(Atn(latitude)) * Cos(Atn(longitude) - Atn(Laengengrad)) + Sin(Atn(Breitengrad)) * Sin(Atn(latitude)))
End Function
Leider erscheint nur eine leere Tabelle im Listenfeld.
Ein Fehler wird allerdings nicht angezeigt, nur finde ich nicht, woran es noch liegen kann.
Viele Grüße
Hallo,
ersetze mal HAVING durch WHERE.
Zitatersetze mal HAVING durch WHERE.
Leider hatte das keine Auswirkung.
Dann nimm den generierten SQL-Code und teste ihn im SQL-Fenster einer neuen Abfrage.
PS:
Sorry, aber der Ansatz von Klaus war schon ganz richtig, du kannst das berechnete Feld nicht im Kriterium verwenden.
Da muss also der komplette Ausdruck noch einmal ausgeschrieben werden.
strSQL = "SELECT * , fktDist( " & str(Me!Breitengrad) & ", latitude , longitude, " & str(Me!Laengengrad) & ") AS distanz " & _
"FROM Geo WHERE fktDist( " & str(Me!Breitengrad) & ", latitude , longitude, " & str(Me!Laengengrad) & ")< 20"
In einer gesonderten Abfrage kann ich die Public function aber nicht ansteuern (Undefinierte Funktion).
Public Function fktDist(Breitengrad As Double, latitude As Double, longitude As Double, Laengengrad As Double)
fktDist = 33959 * acos(Cos(Atn(Breitengrad)) * Cos(Atn(latitude)) * Cos(Atn(longitude) - Atn(Laengengrad)) + Sin(Atn(Breitengrad)) * Sin(Atn(latitude)))
End Function
ZitatDa muss also der komplette Ausdruck noch einmal ausgeschrieben werden.
Wie meinst du das genau?
Code siehe oben.
Befindet sich die Funktion nicht in einem allgemeinen Modul?
Ah OK.
Ich habe die Funktion nun in ein eigenes (allgemeines) Modul eingetragen. Jetzt greift die Abfrage darauf zu.
Also wenn ich das HAVING durch WHERE ersetze, dann kann er den Parameter "distanz" nicht finden.
Wenn ich "HAVING" belasse, dann erhalte ich die Fehlermeldung "HAVING-Klausel (distanz<20) ohne Gruppierung oder Aggregatfunktion".
Hallo,
wie soll man einen Vorschlag machen, wenn man nix sieht ?
Zeige daher bitte den vollständigen aktuell verwendeten SQL_Code.
Sorry.
Ich teste gerade folgende Abfrage:
SELECT *, fktDist(33.3334,Geo.latitude,Geo.longitude,69.952) AS distanz
FROM Geo
WHERE distanz < 20;
Hallo,
wie ich weiter oben schon geschrieben habe, muss in der Wherklausel die Berechnung auch verwendet werden.
SELECT *, fktDist(33.3334,Geo.latitude,Geo.longitude,69.952) AS distanz
FROM Geo
WHERE fktDist(33.3334,Geo.latitude,Geo.longitude,69.952) < 20
Brauchst Du das Feld Distanz zur Anzeige ?
Ja, ich möchte das Feld Distanz mit in das Listenfeld aufnehmen.
Die Abfrage funktioniert mit deinem Code zwar fehlerfrei, nur wird scheinbar kein Umkreis gefiltert, da alle Datensätze der Tabelle Geo angezeigt werden.
Bei der Public Function...
Public Function fktDist(Breitengrad As Double, latitude As Double, longitude As Double, Laengengrad As Double)
fktDist = 33959 * acos(Cos(Atn(Breitengrad)) * Cos(Atn(latitude)) * Cos(Atn(longitude) - Atn(Laengengrad)) + Sin(Atn(Breitengrad)) * Sin(Atn(latitude)))
End Function
..-musste ich noch eine weitere Funktion "ACos" hinzufügen, da Access anscheinend mit acos auch nicht umgehen kann.
Public Function ACos(x As Double) As Double
Const Pi = 3.14159265358979
'Pi = 4*Atn(1)
If x = 1 Then
ArcCos = 0
ElseIf x = -1 Then
ArcCos = Pi
ElseIf x < 1 And x > -1 Then
ArcCos = Atn(-x / Sqr((-x * x) + 1)) + Pi / 2
End If
End Function
Wie gesagt, haut die Umkreissuche aber trotzdem nicht hin...
Hallo,
was wird dann im Feld Distanz angezeigt, stehen da korrekte Zahlen ?
Du musst natürlich sicher sein, dass die Rechnung selbst stimmt. Zur Formel kann ich aber nichts sagen, habe ich keine Erfahrung.
Nein im Feld Distanz werden nur "0"en angezeigt.
Wahrscheinlich stimmt hier tatsächlich etwas mit der Formel nicht.
Hallo,
dann solltest Du natürlich erst mal sicher sein, dass die Formel korrekte Werte ermittelt. Erst dann kannst Du mal über das Filtern nachdenken.
Ich schaue mir morgen nochmal die Formel an.
Das liegt garantiert an der fktDist-Funktion.
Vielen Dank Dir und auch den anderen für Deine (Eure) Hilfe.
Das hat mir schon enorm weitergeholfen. :-)
LG & noch einen schönen Abend
Hallo Ardjan,
Zitatdann solltest Du natürlich erst mal sicher sein, dass die Formel korrekte Werte ermittelt. Erst dann kannst Du mal über das Filtern nachdenken.
Und besonders hilfreich ist dabei die Methode .Print des Debug-Objekts (siehe OH).
gruss ekkehard
Hallo,
im Rahmen einer Geocache-Datenbank hatte ich die folgenden Zeilen eingesetzt.
Vielleicht helfen die.
Harald
Option Compare Database
Option Explicit
Const PI = 3.14159265
Public Function Entfernung(ByVal Breite_1, ByVal Laenge_1, ByVal Breite_2, ByVal Laenge_2 As String) As Double
Const ErdUmfang = 6378
Const Polarradius = 6357
Const Exzentrizitaet = 0.081082 'Exzentrizität sqrt(1 - b^2/a^2) a:Erdumfang, b:Polarradius
Dim Breite_A, Breite_B, Laenge_A, Laenge_B As Double 'Koordinaten für zwei Punkte
Dim Distanz As Double
Dim ErdRadius As Double
Breite_A = Umwandeln(Breite_1)
Laenge_A = Umwandeln(Laenge_1)
Breite_B = Umwandeln(Breite_2)
Laenge_B = Umwandeln(Laenge_2)
ErdRadius = ErdUmfang * (1 - Exzentrizitaet ^ 2) / (1 - Exzentrizitaet ^ 2 * (Sin(Breite_A - (Breite_A - Breite_B) / 2)) ^ 2) ^ (3 / 2)
'http://www.kompf.de/gps/distcalc.html
Entfernung = ErdRadius * ArcCos(Sin(Breite_A) * Sin(Breite_B) + Cos(Breite_A) * Cos(Breite_B) * Cos(Laenge_B - Laenge_A))
End Function
Public Function Umwandeln(ByVal Eingabe As String) As Double
Dim I As Byte
Dim X As String
Dim Nachkomma As Double
Eingabe = Replace(Eingabe, "N", "")
Eingabe = Replace(Eingabe, "E", "")
Eingabe = LTrim(Eingabe)
X = ""
I = 1
Do While IsNumeric(Mid(Eingabe, I, 1))
X = X & Mid(Eingabe, I, 1)
I = I + 1
Loop
Umwandeln = (Val(X) + Val(Mid(Eingabe, I + 1)) / 60) * PI / 180
End Function
Private Function ArcCos(X As Double) As Double
'Arkuskosinus(X) = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)
'ArcCos = Atn(-x / Sqr(-x * x + 1)) + 2 * Atn(1)
'http://dbwiki.net/wiki/VBA_Tipp:_Arcussinus_und_Arcuscosinus
If X = 1 Then
ArcCos = 0
Else
If X = -1 Then
ArcCos = PI
Else
If X < 1 And X > -1 Then
ArcCos = Atn(-X / Sqr((-X * X) + 1)) + PI / 2
End If
End If
End If
End Function
Private Function ArcSin(X As Double) As Double
'Arkussinus(X) = Atn(X / Sqr(-X * X + 1))
ArcSin = Atn(X / Sqr(-X * X + 1))
End Function