Hallo zusammen,
bin bei der Suche im Form nicht fündig geworden, darum bitte ich um Eure Hilfe:
Es geht um eine Tabelle die u.a. die Spalte Modell hat. Der Inhalt ist in der Regel wie folgt:
1.0 TSI, 1.2 TSI, 1.4 TSI, 1.4 TSI, 1.6, 1.0 TSI, 1.2 TSI, 1.4 TSI, 1.8 TSI, 1.6 TDI, 2.0 TDI, 1.2 TFSI, 1.4 TFSI, 1.8 TFSI, 1.6 TDI
Wie zu ersehen sind einige Werte doppelt enthalten - 1.0 TSI, 1.2 TSI, 1.4 TSI...
Gibt es eine Möglichkeit diese doppelten Werte zu löschen und den String sortiert aufsteigend anzuzeigen?
Beste Grüße Torsten
Hallo,
das wird ziemlich aufwendig. Du musst die einzelnen Werte in ein Array einlesen und dieses Array sortieren, anschließend was doppelt ist entfernen.
In einer Datenbank sind solche Felder nicht vorgesehen, daher gibt es da kein fertige Lösung, das muss selbst programmiert werden.
Eine korrekt aufgebaute Datenbank enthält in einem Feld immer nur einen Wert (atomare Inhalte > 1.Normalform).
Wie kommt dieses falsche Datenmodell zu Stande, wird das importiert ?
Die zutreffenden Modell sollten als Datensätze in einer extra Tabelle vorliegen.
Kann das noch geändert werden ?
Hallo Klaus,
anbei eine Demo-DB die den Vorgang darstellt.
Aus der Tabelle 04_tbl... ist der String zu meiner Anfrage
Die Module sind nicht von mir, das Verständnis dafür habe ich leider nicht. Sie wurden mit Eure Hilfe in der Vergangenheit erstellt.
Gruß Torsten
Hallo,
die Zip-Datei ist (von mir) nicht zu öffnen...
Hallo Franz,
versuche es bitte mit .7z, habe die Endung in zip geändert, da man 7z nicht hochladen kann.
Du wirst Deinen Code sicherlich wieder erkennen ;-)
Gruß Torsten
Hallo,
der Aufbau ist falsch, das wurde ja bereits gesagt. So wird es immer wieder zu Fehlern und Korrekturbedarf kommen, das wird also kein einmaliger Vorgang sein. Solche Listen erzeugt man zur Anzeige, gespeichert werden die Modellzuordnungen aber "atomar", d.h. jede in einem einzelnen Datensatz. Dazu legst du eine neue Tabelle mit Artikelnr. und Modellspalte und einem eindeutigen Mehrfelderindex über Artikel und Modell an, liest die "04_tbl..." per VBA in einer Recordset-Schleife aus, trennst die Modellspalte mit Hilfe der Split-Funktion in einen Array auf, und fügst die einzelnen Elemente in einer Schleife in die neue Tabelle ein. Dabei ignorierst du einfach den Fehler der bei doppelten Einträgen auftritt.
Zur Erzeugung der Auflistung zur Anzeige in Formularen und Berichten kannst du die Funktion SQLListe aus dem dbWiki einsetzen.
Hallo,
7z: das solltest Du gleich sagen...
ja, ich kann mich dunkel erinnern, aber beim String-Zusammenbau in einem Feld war es nicht die Intension, diese Strings weiter zu bearbeiten. Das war lediglich für die Anzeige (z. B. in einem Bericht) gedacht...
Ansonsten siehe Beitrag von Klaus.
So ich habe mich Erholt ;-)
Ich versuche Eure Erklärung zu verstehen:
ZitatSolche Listen erzeugt man zur Anzeige, gespeichert werden die Modellzuordnungen aber "atomar", d.h. jede in einem einzelnen Datensatz.
Wenn ich das richtig verstehe: Das ist in der Tabelle 03_tbl... so vorhanden.
Könnt Ihr bitte nochmal schauen?
Beste Grüße Torsten
Hallo Torsten,
ich habe mir deine DB etwas angesehen und bin vielleicht noch auf einen weiteren Lösungsweg gekommen.
Du liest die Datensätze aus 03_tbl... Feld Fahrzeug aus und entfernst dabei die doppelten Einträge anschließend als String aneinander fügen und in 04_tbl... das Feld Fahrzeug überschreiben.
Das gleiche machst du mit dem Feld Modell.
Vielleicht wäre das noch eine weitere Möglichkeit, ist ja auch schnell gemacht...
Gruß
Hallo ProVBA,
während ich den letzten Post geschrieben habe kam Deine Nachricht rein.
Vielen Dank das Du Dich auch mit meinem Problem beschäftigst, ich werde gleich nachher beigehen und es ausprobieren.
Gruß Torsten
@ ProVBA und @ all
Wenn ich Dich richtig verstanden habe, habe ich das mit
Modell: sqlliste("select distinct [color=red]modell[/color] from 02_tbl_~~~~~_aktuell where artikel_nr ='" & [artikel_nr] & "'")bereits versucht.
Das Ergebnis (mein Problem warum ich den Thread eröffnet habe) ist aber nicht 100% richtig, denn es wird "nur" der gesamte String geprüft. Es müßte aber der Inhalt des Strings verglichen werden.
Am Beispiel 1.0 TSI kann man es nachvollziehen: Kommt 3 mal (Datensatz 1-3 in 02_tbl_...) vor und wird 2mal statt 1mal aufgelistet.
Zitat1.0 TSI, 1.2 TSI, 1.4 TSI, 1.4 TSI, 1.6, 1.0 TSI, 1.2 TSI, 1.4 TSI, 1.8 TSI, 1.6 TDI, 2.0 TDI, 1.2 TFSI, 1.4 TFSI, 1.8 TFSI, 1.6 TDI
Ich hoffe ich konnte mich verständlich rüberbringen.
Hallo,
das macht ja schon deshalb keinen Sinn, weil bereits in "02_tbl_..." (ebenso wie in "01_tbl_...") in der Spalte Modell eine Auflistung steht.
Wenn das Problem (bzw. die DB) schon ein Vorgeschichte hat, hättest du evtl. im alten Thread bleiben sollen oder zumindest darauf verweisen. Oder du solltest dein Anliegen und den ganzen Zusammenhang etwas ausführlicher schildern.
ZitatEs müßte aber der Inhalt des Strings verglichen werden.
Womit und zu welchem Zweck?
Mmmmh, etwas ausführlicher?
Mehr als die DB offen legen und sagen was ich möchte kann ich eigentlich nicht.
ZitatWenn das Problem (bzw. die DB) schon ein Vorgeschichte hat, hättest du evtl. im alten Thread bleiben sollen oder zumindest darauf verweisen. Oder du solltest dein Anliegen und den ganzen Zusammenhang etwas ausführlicher schildern.
Die DB hat keine Vorgeschichte, sie wurde zwar von einer früheren kopiert und angepaßt, aber das Ergebnis muß jetzt anders sein - ohne doppelte Werte im String.
Zu Deiner Frage:
ZitatWomit und zu welchem Zweck?
Damit im String
Zitat1.0 TSI, 1.2 TSI, 1.4 TSI, 1.4 TSI, 1.6,||| 1.0 TSI, 1.2 TSI, 1.4 TSI, 1.8 TSI, 1.6 TDI, 2.0 TDI,||| 1.2 TFSI, 1.4 TFSI, 1.8 TFSI, 1.6 TDI
die rot hinterlegten Modelle nicht mehr aufgelistet bzw. gelöscht und der Rest aufsteigend sortiert werden.
Um beim Beispiel 1.0 TSI zu bleiben: Einer von den 3 Stringwerten (der 2. oder 3.) wurde ja gelöscht, aber eben nicht der 2. (siehe 02_tbl_...) weil der String im 2. und 3. Datensatz im ganzen identisch ist.
Bis zum 1. ||| = String aus 1. Datensatz
Bis zum 2. ||| = String aus 2. + 3. Datensatz
Danach = String aus 4. + 5. Datensatz
Es wird bei der Prüfung im String nicht auf die Werte jeweils bis zum Komma geprüft sondern nur der gesamte.
Ich hoffe es ist jetzt nicht zu verwirrend beschrieben.
Hallo,
unabhängig von fragwürdigem DB-Konzept und Tabellenstruktur, hier ein SQL(Tabellen)-VBA-gemischtes Beispiel, um in einem Komma-getrennten Wertelisten-String Doubletten zu entfernen und die Einzelwerte zu sortieren..
Function DDASA(strStr As String) As String
' Funktion DeleteDoubletsAndSortAsc
Dim a, db As Database, i As Long, strErg As String, rs As DAO.Recordset
Set db = CurrentDb
On Error Resume Next
db.Execute "delete * from tblTemp"
db.Execute " Create Table tblTemp (strItem Text(50) Primary Key)"
On Error GoTo myErr
a = Split(strStr, ",")
For i = LBound(a) To UBound(a)
db.Execute "insert into tblTemp (strItem) Values ('" & a(i) & "')"
Next
Set rs = db.OpenRecordset("select * from tblTemp order by strItem", dbOpenSnapshot)
Do Until rs.EOF
strErg = strErg & ", " & Trim(rs(0))
rs.MoveNext
Loop
If Len(strErg) > 1 Then
DDASA = Mid(strErg, 3)
Else
DDASA = ""
End If
Exit_F:
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Function
myErr:
MsgBox Err.Number & ": " & Err.Description
Resume Exit_F
End Function
Guten Morgen Franz,
ich habe mich gefreut das Du Dir nochmals Gedanken gemacht hast.
Bitte helfe mir noch wie ich das in der Abfrage umsetzen muß - meine Versuche brachten kein Erfolg.
Gruß Torsten
Hallo,
--kopier den Code in ein Standardmodul (und schreib noch "Public" vor "Function" in der ersten Zeile).
Public Function DDASA(strStr As String) As String
--ruf die Funktion in einer berechneten Abfragespalte auf :
Select *, DDASA ([Modell]) as ModellSortiert from [04_tbl_eibach_fzg_1-zeilig]
Franz,
es hapert bei mir mit dem anlegen einer berechneten Abfragespalte.
Siehe Anhang - Meine Versuche gingen in diese Richtung, so funktioniert es natürlich nicht.
Hallo,
dort muss einfach stehen:
ModellSortiert: DDSA([Modell])
"Modell" muss dabei die Tabellenspalte sein, in der der zu bearbeitende String drinsteht.
Fast perfekt, leider schleicht sich noch am Ende ein , 1.0 TSI ein, siehe Anhang.
Hurra, ich glaube es funktioniert jetzt:
Ich habe in Deiner Funktion DDASA ein Leerzeichen (siehe Anhang) eingefügt und somit ist in der tblTemp kein 2. Datensatz ( 1.0 TSI) ohne Leerzeichen vorhanden.
Kannst Du das bestätigen das es daran liegen kann?
Hi,
du könntest statt dessen auch die Trim-Funktion beim Füllen von tblTemp einsetzen und nicht erst beim Auslesen.
PS:
Zitat von: Torsten. am Februar 10, 2016, 11:58:37
Die Module sind nicht von mir, [...]. Sie wurden mit Eure Hilfe in der Vergangenheit erstellt.
Zitat von: Torsten. am Februar 10, 2016, 19:07:19
Die DB hat keine Vorgeschichte, sie wurde zwar von einer früheren kopiert und angepaßt,
aber das Ergebnis muß jetzt anders sein
Ist für mich ein Widerspruch, aber was soll's...?
Hallo MaggieMay,
würdest Du mir bitte behilflich sein wie der Code der Trim-Funktion zu sein hat und wo er wie eingefügt werden soll?
Gruß Torsten
Hallo,
etwas Eigeninitiative kann nicht schaden. Einfach mal in einer Abfrage trim eingeben, den Cursur drauf stehen lassen und F1 drücken.
Das Ergebnis sieht dann zB so aus:
Zitat
LTrim, RTrim, and Trim Functions
Office 2013 and later
Contribute to this content
Use GitHub to suggest and submit changes. See our guidelines for contributing to VBA documentation.
Returns a Variant (String) containing a copy of a specified string without leading spaces (LTrim), trailing spaces (RTrim), or both leading and trailing spaces (Trim).
Syntax
LTrim(string)
RTrim(string)
Trim(string)
The required string argument is any valid string expression. If string contains Null, Null is returned.
Example
This example uses the LTrim function to strip leading spaces and the RTrim function to strip trailing spaces from a string variable. It uses the Trim function to strip both types of spaces.
Dim MyString, TrimString
MyString = " <-Trim-> " ' Initialize string.
TrimString = LTrim(MyString) ' TrimString = "<-Trim-> ".
TrimString = RTrim(MyString) ' TrimString = " <-Trim->".
TrimString = LTrim(RTrim(MyString)) ' TrimString = "<-Trim->".
' Using the Trim function alone achieves the same result.
TrimString = Trim(MyString) ' TrimString = "<-Trim->".
Hallo Jürgen,
vielen Dank für Deinen Hinweis das ich doch ein wenig Eigeninitiative leisten sollte.
Was vermutest Du wenn Du meine Fragen hier im Forum liest, welchen Kennntissstand ich bezügl. Access habe?
Hättest Du Dir die Mühe gemacht (was ich nicht verlange) bspw. nur die in diesem Thread zu lesen, würdest Du sehen das Deine Information zum Thema Trim... für mich nichtssagend ist.
Von so her lass es einfach sein, hinter der Hecke hervor zu springen und mir solch eine blöde Antwort zu geben!
Hallo,
@Torsten
mit solchen Äußerungen machst Du Dir keine Freunde und schiebst Dich schnell auf ein Abstellgleis und kriegst gar keine Antwort. Und Du willst ja Hilfe. Jürgen hat Dir umfangreiches Infomaterial zu Trim zukommen lassen. Und noch einen Tipp wie man an solche Infos in der Hilfe findet. Von daher, bin ich ziemlich sicher, dass die Mitleser erkennen, wer jetzt die blöde Antwort gegeben hat. Um mal bei Deinem unpassenden Vokabular zu bleiben.
Eine solche Äußerung ist schlicht und ergreifend eine Frechheit gegenüber dem der sich bemüht DIR zu helfen. Das gehört sich nicht.
Hallo Torsten,
mein Tipp bezog sich auf den Code aus Antwort #13, dort wird die Trim-Funktion beim Auslesen der Tabelle eingesetzt, was allerdings zu spät ist, da so nicht alle Duplikate erkannt werden. Wendest du aber die Trim-Funktion bereits beim Speichern ein, ist alles OK.
In Gänze sieht das dann so aus:
Function DDASA(strStr As String) As String
' Funktion DeleteDoubletsAndSortAsc
Dim a, db As Database, i As Long, strErg As String, rs As DAO.Recordset
Set db = CurrentDb
On Error Resume Next
db.Execute "delete * from tblTemp"
db.Execute " Create Table tblTemp (strItem Text(50) Primary Key)"
On Error GoTo myErr
a = Split(strStr, ",") [color=blue]' der Split-Parameter bleibt unverändert[/color]
For i = LBound(a) To UBound(a)
db.Execute "insert into tblTemp (strItem) Values ('" & [color=blue]Trim[/color](a(i)) & "')" [color=blue] ' <--- hier macht Trim mehr Sinn[/color]
Next
Set rs = db.OpenRecordset("select * from tblTemp order by strItem", dbOpenSnapshot)
Do Until rs.EOF
strErg = strErg & ", " & rs(0) [color=blue]' <--- hier ist Trim überflüssig, wurde also entfernt[/color]
rs.MoveNext
Loop
If Len(strErg) > 1 Then
DDASA = Mid(strErg, 3)
Else
DDASA = ""
End If
Exit_F:
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Function
myErr:
MsgBox Err.Number & ": " & Err.Description
Resume Exit_F
End Function
@ Klaus
Das sehe ich natürlich anders.
Hätte ich auf meine Fragen und Probleme die im Laufe der Jahre angefallen sind, solche Antworten bekommen, wäre ich nie zum Ergebnis gekommen.
Ich mache 3 Kreuze das es solch geduldige und hilfsbereite Programmierer wie Franz, Oma, MaggieMay, Peter, Dir und all die die mir über die Jahre geholfen haben, gibt.
Und übrigens da war keine Antwort dabei die nur annähernd so war wie sie vorhin kam.
Gruß Torsten
Nachtrag:
Das beste Beispiel ist die Antwort von MaggieMay zuvor.
Ich übertreibe jetzt ein wenig, aber ich bekomme vor Freude Tränen in den Augen, wenn ich sehe das er sich die Mühe macht, mir das aufdröselt, es noch kommentiert und mir auch noch "mundgerecht" serviert - nur anders könnte ich es nicht umsetzen.
Mir ist völlig bewußt das es keine Selbstverständlichkeit ist.