codeman2001 Geschrieben 8. März 2006 Geschrieben 8. März 2006 hab nur 4 kleine Fragen. 1. Wie Spreche ich bestimme Datensätze und dann bestimmte Werte des Datensatzes an? 2. wie lese ich datensätze aus einer MS-Access (.mdb) Datei aus? 3. wie füge ich neue datensätze ein? 4. wie ändere ich bestehende datensätze? gruß Zitieren
Amstelchen Geschrieben 8. März 2006 Geschrieben 8. März 2006 mittels des von dir bevorzugten oder vorgegebenen zugriffsmodells; dies kann ADO(X), ADO.NET, DAO oder RDO sein. einige beispiele für ADO findest du z.b. bei activevb. s'Amstel Zitieren
codeman2001 Geschrieben 8. März 2006 Autor Geschrieben 8. März 2006 bis jetzt habe ich mir folgendes quelltext gebaut. geht das nicht auch mir "normalen" VB Quelltext? Private Sub Form_Load() Dim db As Database Dim rs As Recordset '-Datenbank implementieren Set db = OpenDatabase(".\Fahrbereitschaft.mdb") '-Tabelle auswaehlen Set rs = db.OpenRecordset("T_KFZ") '-Ersten Datensatz auswählen rs.MoveFirst '-Wiederhole solange nicht EOF (End of File) ist. Combo Box füllen. Zum nächsten Daten '-satz springen While Not rs.EOF DBComboKFZ.AddItem (rs!F_registrationnumber) rs.MoveNext Wend '-Datenbank schließen db.Close End Sub Damit fülle ich eine Combo Box (bsp. Auto Kennzeichen) mit den Inhalten einer Datenbank. Jetzt kann ich einen Datensatz auswählen und es werden die dazugehörigen werte (Marke, Modell....) in textfeldern ausgegeben. gruß Zitieren
Amstelchen Geschrieben 8. März 2006 Geschrieben 8. März 2006 bis jetzt habe ich mir folgendes quelltext gebaut. geht das nicht auch mir "normalen" VB Quelltext? der von dir reingestellte codeschnipsel zeigt den üblichen weg; deshalb kann ich dir nicht folgen, was du mit "normalen" VB quelltext meinst - willst du eine access-datenbank von VB aus ansprechen, ohne ADO zu verwenden, oder wie? s'Amstel Zitieren
codeman2001 Geschrieben 8. März 2006 Autor Geschrieben 8. März 2006 der von dir reingestellte codeschnipsel zeigt den üblichen weg; deshalb kann ich dir nicht folgen, was du mit "normalen" VB quelltext meinst - willst du eine access-datenbank von VB aus ansprechen, ohne ADO zu verwenden, oder wie? s'Amstel wenn es geht ja, oder ist es mit ADO einfacher? konnte mir den link noch nicht durchlesen... Zitieren
DevHB Geschrieben 8. März 2006 Geschrieben 8. März 2006 Hi, Du hast zwei Möglichkeiten, eine DB mit VB 6 anzusprechen: DAO und ADO. DAO ist älter und wird von MS nicht mehr weiterentwickelt, ADO ist die neuere Variante. Für den "normalen" Zugriff sollte man IMO ADO verwenden, wenn es darum geht, Tabellen zu ändern, nimmt man ADOX. Allerdings kommt man an manche Systemeinstellungen der DB nur mit DAO ran. Zu 1.) Dim Cn As ADODB.Connection Dim Rs As ADODB.Recordset Set Cn = New ADODB.Connection With Cn .ConnectionString = "C:\Test.mdb" .Mode = adShareDenyDone .Provider = "Microsoft.Jet.OLEDB.4.0" ' für Access 2000/XP ' 3.51 für Access97 Call .Open End With Set Rs = New ADODB.Recordset With Rs Set .ActiveConnection = Cn .LockType = adLockBatchOptimistic .CursorLocation = adUseClient .Source = "SELECT * FROM Tabelle" Call .Open End With Dim i As Long With Rs ' alle Felder des Rs durchlaufen ' Feld = Spalte in Tabelle For i = 0 To .Fields.Count - 1 ' Feldnamen und Feldwert ausgeben Debug.Print .Fields(i).Name & ": " & .Fields(i).Value Next i End With Änderungsabfragen immer per SQL - Statement über die Connection ausführen: Call Cn.Execute ("INSERT INTO ....") Dies ist wesentlich schneller und die Recordset - Methoden "AddNew", "edit" und "delete" sind teilweise unsicherer. 4.) Einfügen --> INSERT Statement Ändern --> UPDATE Statement Löschen --> DELETE Statement Zitieren
codeman2001 Geschrieben 9. März 2006 Autor Geschrieben 9. März 2006 Set gvRs = New ADODB.Recordset gvRs.Open "T_KFZ", gvConnection, adOpenDynamic, adLockReadOnly '-Springe zum ersten Datensatz gvRs.MoveFirst Me.DBComboKFZ.AddItem (gvRs!F_registrationnumber) so nehme ich ja den ersten datensatz und von diesem das feld F_registrationnumber wie kann ich denn den 2. datensatz auswählen? Zitieren
DevHB Geschrieben 9. März 2006 Geschrieben 9. März 2006 Naja, so wie mit DAO auch: Set gvRs = New ADODB.Recordset gvRs.Open "T_KFZ", gvConnection, adOpenDynamic, adLockReadOnly With Rs Call .MoveFirst Do While (Not (.EOF)) Call DBComboKFZ.AddItem(.Fields("F_registrationnumber").Value) ' nächsten datensatz anspringen Call .MoveNext Loop End With Was ist bei Dir "T_KFZ" ? Ist das der Tabellenname? Wenn dem so ist, mach das in einer SQL Anweisung ala "SELECT * FROM T_KFZ". Hierbei ist anzumerken, dass die Schreibweise mit dem ! veraltet und zu Fehleranfällig ist, Wartung ist auch Müll. Übersichlicher ist es mit "Rs.Fields("FeldName").Value" ! Ist die Combobox eine "DataCombo"? Wenn dem so ist, schmeiß die raus und nimm eine normale ComboBox, die DB-Combo ist für datengebundene Arbeitsweise, die man in VB 6 tunlichst vermeiden sollte! Außderdem sollte man der normalen Combo dann noch Wert in die ItemData Eigenschaft schreiben, damit man so Zugriff auf z.B. IDs hat. Ich würde Dir empfehlen, die Tutorials durchzuarbeiten und Dir das Beispiel mal anzuschauen: Tuts: http://activevb.de/tutorials/tut_adokurs/adokurs.html http://activevb.de/tutorials/tut_ado_db/adodb.html Tips http://activevb.de/tipps/vb6tipps/tipp0440.html Beispiel http://www.activevb.de/cgi-bin/upload/download.pl?id=2444 Zitieren
codeman2001 Geschrieben 9. März 2006 Autor Geschrieben 9. März 2006 also ich habe eine access datenbank, in der ein fuhrpark eingepflegt ist. Aufbau: T_KFZ - I_ID - F_Kennzeichen - F_Marke - F_Modell In einer combo box sollen jetzt die Autos nach ihrem kennzeichen aufgelistet werden (funktioniert bereits). Wenn ich jetzt ein kennzeichen in der combobox auswähle, sollen die dazugehörigen daten (F_Kennzeichen, F_Marke, F_Modell) in Textboxen (txt1 - txt3) eingetragen werden. ist wahrscheinlich relativ simpel, aber ich komme einfach nicht mehr weiter... gruß ***EDIT*** zusammengebastelt Set gvRs = New ADODB.Recordset With gvRs Set .ActiveConnection = gvConnection .Source = "SELECT T_KFZ.F_registrationnumber, " & _ "T_KFZ.F_manufacturer, " & _ "T_KFZ.F_type, " & _ "FROM F_KFZ " & _ "WHERE I_ID=Me.DBComboKFZI_ID.ListIndex;" 'Listindex ist ID des Datensatzes 'Call .Open Me.txtManufacturer.Text = gvRS!F_manufacturer Me.txtType.Text = gvRs!F_type Zitieren
codeman2001 Geschrieben 9. März 2006 Autor Geschrieben 9. März 2006 geht aber trotzdem noch nicht... Zitieren
DevHB Geschrieben 9. März 2006 Geschrieben 9. März 2006 Also, erstmal die entspr. SQL - Anweisung aufbauen: SELECT T_KFZ.I_ID, T_KFZ.F_Kennzeichen, T_KFZ.F_Marke, T_KFZ.Modell FROM T_KFZ dann musst Du die Daten mit dem Recordset wie in den Posts vorher aus der DB holen, die in die Combobox bügeln. Dann nimmst Du das "ComboBox_Click" Ereignis, um damit dass Füllen anzustoßen. Ich würde mir eine Funktion schreiben, die Dir die ComboBox füllt, eine die Dir die Werte an die Textboxen überträgt (ala Text1.Text = Rs.Fields("DeinFeld").Value) und fertig bist Du. Was hast Du bis jetzt probiert bzw. hast Du Dir mal die Links angeschaut? So langsam erschleicht sich die Ahnung, dass Du erstmal Dein DB Wissen aufbauen musst (SQL Statements etc.), denn das DB - Design (Tabellenaufbau) ist Mist (Stichwort: Normalisierung!). Ich kann Dir fertigen Code posten, doch das bringt Dir im Endeffekt überhaupt nichts, denn wer soll das Programm warten/erweitern? Grade Dein Edit gesehen: Auch das Stringverketten geht so nicht: = "SELECT T_KFZ.F_registrationnumber, " & _ "T_KFZ.F_manufacturer, " & _ "T_KFZ.F_type, " & _ "FROM F_KFZ " & _ "WHERE I_ID = " & Me.DBComboKFZI_ID.ListIndex & ";" Zitieren
codeman2001 Geschrieben 9. März 2006 Autor Geschrieben 9. März 2006 das habe ich bis jetzt: Option Explicit Dim gvConnection As ADODB.Connection Dim gvRs As ADODB.Recordset Dim lngComboIndex As Long '-Verbindung zur Datenbank herstellen Private Sub cmdConnect_Click() '-Comboboxen leeren Me.DBComboKFZ.Clear Me.DBComboKFZI_ID.Clear Set gvConnection = New ADODB.Connection With gvConnection .ConnectionString = ".\Fahrbereitschaft.mdb" .Provider = "Microsoft.Jet.OLEDB.4.0" .CursorLocation = adUseClient Call .Open End With If gvConnection.State = 1 Then '-Status: rot unvisible, gruen visible Me.lblNichtVerbunden.Visible = False Me.lblVerbunden.Visible = True Set gvRs = New ADODB.Recordset gvRs.Open "T_KFZ", gvConnection, adOpenDynamic, adLockReadOnly '-Springe zum ersten Datensatz gvRs.MoveFirst lngComboIndex = 0 While Not gvRs.EOF Me.DBComboKFZ.AddItem (gvRs!F_registrationnumber), lngComboIndex Me.DBComboKFZI_ID.AddItem (gvRs!I_ID), lngComboIndex gvRs.MoveNext lngComboIndex = lngComboIndex + 1 Wend Else MsgBox ("Fehler beim Verbinden der Datenbank") '-Status: gruen unvisible, rot visible Me.lblVerbunden.Visible = False Me.lblNichtVerbunden.Visible = True End If End Sub ----------------------------------------------------------------- Private Sub DBComboKFZ_Click() '-Index mit dem Kennzeichen abgleichen Me.DBComboKFZI_ID.ListIndex = Me.DBComboKFZ.ListIndex Set gvRs = New ADODB.Recordset gvRs.Open "T_KFZ", gvConnection, adOpenDynamic, adLockReadOnly With gvRs Set .ActiveConnection = gvConnection .Source = "SELECT T_KFZ.F_registrationnumber, _ T_KFZ.F_manufacturer, _ T_KFZ.F_type _ FROM T_KFZ _ WHERE T_KFZ.I_ID=" & Me.DBComboKFZI_ID.ListIndex & ";" Me.txtManufacturer.Text = gvRs!F_manufacturer Me.txtType.Text = gvRs!F_type End With End Sub mach nicht viel mit VB.... bin dabei das alles zu lesen, aber so richtig finde ich da nicht, was ich brauche... gruß Zitieren
DevHB Geschrieben 9. März 2006 Geschrieben 9. März 2006 Hi, wenn ich um 15.00 Uhr Schluss habe, mach ich mal ein Beispiel... Wird so gegen 16.00Uhr sein. Zitieren
codeman2001 Geschrieben 9. März 2006 Autor Geschrieben 9. März 2006 das wäre nett. jedoch bin ich morgen früh erst wieder "on" ... ich hoffe du kannst mit meinem Quelltext etwas anfangen... :mod: Zitieren
DevHB Geschrieben 9. März 2006 Geschrieben 9. März 2006 Also, hier eine Funktion zum Füllen einer ComboBox: ' fills combobox with specified Recordset Public Function FillComboBox(ByRef Rs As ADODB.Recordset, _ ByRef ctl As ComboBox, _ ByVal sFieldValue As String, _ ByVal sFieldID As String _ ) As Boolean Dim sTmp As String With ctl Call .Clear If (Rs.RecordCount = 0) Then FillComboBox = False Exit Function End If Call Rs.MoveFirst Do While Not Rs.EOF sTmp = GetText(Rs.Fields(sFieldValue).Value) Call .AddItem(sTmp) .ItemData(.NewIndex) = Rs.Fields(sFieldID).Value Call Rs.MoveNext Loop End With FillComboBox = True End Function ' read field value of specified recordset ' handles NULL values Public Function GetText(vDBText As Variant _ ) As String ' NULL value in field If (VBA.IsNull(vDBText)) Then GetText = VBA.Constants.vbNullString Else GetText = VBA.CStr(vDBText) End If End Function ' gets ComboBox Itemdata Public Function GetCboItemData(ctl As ComboBox _ ) As Long On Error Resume Next GetCboItemData = ctl.ItemData(ctl.ListIndex) End Function Zur Erklärung: FillComboBox füllt eine ComboBox Daten aus einem Recordsetobjekt. sFieldValue ist der Wert der angezeigt wird, sFieldID ist das Primärschlüsselfeld aus der Tabelle. Dieses wird in die ItemData Eigenschaft geschrieben und wird zum Filtern verwendet: ' Füllen der ComboBox: Call FillComboBox(Rs, DeineComboBox, "F_registrationnumber", "I_ID") Private Sub ComboBox_Click Dim sSQL As String Dim lID As Long lID = GetCboItemData(ComboBox) If (lID = -1) Then Exit Sub End If sSQL = "SELECT T_KFZ.F_registrationnumber, " & _ "T_KFZ.F_manufacturer, " & _ "T_KFZ.F_type, " & _ "FROM F_KFZ " & _ "WHERE I_ID = " & lID & ";" Dim Rs As ADODB.Recordset Set Rs = New ADODB.Recordset With Rs .ActiveConnection = Cn .CursorLocation = adUseClient .LockType = adLockOptimistic .Source = sSQL Call .Open End With If (Rs.RecordCount = 0) Then Call MsgBox ("Keine Daten gefunden!",vbOkOnly) Call Rs.Close Set Rs = Nothing Exit Function End If ' Werte in TextBox mit Funktion GetText ' wenn ein Recordset.Fields.Value = NULL ist ' dann gibt es einen Fehler, also vorher abfragen Text1.Text = GetText(Rs.Fields("DeinFeld").Value) End Sub So ungefähr müsste es aussehen. Code ist ungetestet, aber die Funktionen sind in leicht abgeänderter Art schon seit Jahren bei mir im Einsatz. Zitieren
codeman2001 Geschrieben 10. März 2006 Autor Geschrieben 10. März 2006 jo danke. ich habe es jetzt Set gvRs = New ADODB.Recordset With gvRs .ActiveConnection = gvConnection .CursorLocation = adUseClient .LockType = adLockBatchOptimistic .Source = "SELECT T_KFZ.F_registrationnumber, " & _ "T_KFZ.F_manufacturer, " & _ "T_KFZ.F_type " & _ "FROM T_KFZ " & _ "WHERE T_KFZ.I_ID = '" & lngID & "';" Call .Open End With Me.txtManufacturer.Text = gvRs!F_manufacturer Me.txtType.Text = gvRs!F_type bzw noch einfacher: gvRs.Filter = "I_ID like '" & Me.DBComboKFZI_ID.Text & "'" Me.txtManufacturer.Text = gvRs!F_manufacturer Me.txtType.Text = gvRs!F_type Zitieren
DevHB Geschrieben 10. März 2006 Geschrieben 10. März 2006 Die "Recordset.Filter" - Methode arbeitet in manchen Teilen nicht richtig. Zudem muss man darauf achten, das der Filter wieder zurückgesetzt wird (adFilterNone). Ich mache sowas über SQL - Statements... Ich würde Dir auch raten die statt "Rs!FeldName" die "Rs.Fields("Name).ValuE" zu verwenden, denn die "!" - Variante ist sehr fehleranfällig und ein Relikt aus alten Zeiten, dass tunlichst vermieden werden sollte. Zitieren
codeman2001 Geschrieben 13. März 2006 Autor Geschrieben 13. März 2006 hab da nochmal ne frage... irgendwann verzweifle ich daran :confused: ich habe jetzt noch eine userform (frmKFZ_Neu) und an diese Userform möchte ich mein Recordset und meine Verbindung übergeben... Zitieren
DevHB Geschrieben 13. März 2006 Geschrieben 13. März 2006 Hi, dass macht man am Besten über eine Property ' code für frmKFZNeu Private m_Connection As ADODB.Connection Public Property Set Connection(ByRef vData As ADODB.Connection) Set m_Connection = vData End Property Public Property Get Connection(ByRef vData As ADODB.Connection) Set Connection = m_Connection End Property ' Aufruf Sub OpenKFZNeu Call Load(frmKFZNeu) Set frmKFZNeu.Connection = DeineConnection Call frmKFZNeu.Show End Sub Code ist ungetestet. Allerdings würde ich mir überlegen, die Connection in ein Modul zu packen, dann hast Du Zugriff vom gesamten Projekt aus. Wofür willst Du das Recordset übergeben? Für eine Neuanlage brauchst Du es ja nicht, da man Änderungen über SQL machen sollte. Zitieren
codeman2001 Geschrieben 13. März 2006 Autor Geschrieben 13. März 2006 ich möchte über eine userform inhalte neu einpflegen... will das ohne sql befehle machen hab jetzt den code hier.. frmMain: Private Sub cmdCreateData_Click() Call Load(frmKFZ_Neu) Set frmKFZ_Neu.Recordset = rsKFZ <- Methode nich gefunden Call frmKFZ_Neu.Show End Sub frmKFZ_Neu Option Explicit Private WithEvents rsKFZ As ADODB.Recordset Public Property Set KFZ(ByRef rs As ADODB.Recordset) Set mrsKFZ = rs End Property Public Property Get KFZ() As ADODB.Recordset Set rsKFZ = mrsKFZ End Property Private Sub cmdOK_Click() rsKFZ.AddNew rsKFZ!I_ID = me.txtID_Value.text rsKFZ!F_RgNum = Me.txtRegNum_Value.Text rsKFZ!F_Manufact = Me.txtManufact_Value.Text rsKFZ!F_KFZType = Me.txtKFZType_Value.Text rsKFZ!F_YearOfBuild = Me.txtYearOfBuild_Value.Text rsKFZ!L_GasType = Me.cboGastype_Value.Text rsKFZ!F_BuyDate = Me.txtBuyDate_Value.Text rsKFZ!F_BuyKM = Me.txtBuyKM_Value.Text rsKFZ!F_ActualKM = Me.txtActualKM_Value.Text rsKFZ!F_TankCapacity = Me.txtTankCapacity_Value.Text rsKFZ.UpdateBatch End Sub Private Sub Form_Terminate() Set rsKFZ = Nothing End Sub Zitieren
DevHB Geschrieben 13. März 2006 Geschrieben 13. März 2006 Naja, wenn Du Deine Property so aussieht: Public Property Set KFZ(ByRef rs As ADODB.Recordset) Set mrsKFZ = rs End Property Public Property Get KFZ() As ADODB.Recordset Set rsKFZ = mrsKFZ End Property dann sollte man auch den richtigen Aufruf verwenden: Private Sub cmdCreateData_Click() Call Load(frmKFZ_Neu) ''''' Set frmKFZ_Neu.Recordset = rsKFZ <- Methode nich gefunden ''''' wird zu: Set frmKFZ_Neu.KFU = rsKFZ Call frmKFZ_Neu.Show End Sub Allerdings frage ich mich grade, wozu man Dir Tips gibt, wenn Du sie nicht beachtest::confused: - nicht die ! - Synthax verwenden - Änderungen an der DB über SQL und Connection und nicht über Recordset Für mich absolut unbegreiflich.... Zitieren
codeman2001 Geschrieben 13. März 2006 Autor Geschrieben 13. März 2006 geht immer noch nicht frmMain: Call Load(frmKFZ_Neu) Set frmKFZ_Neu.KFZ = rsKFZ Call frmKFZ_Neu.Show End Sub frmKFZ_Neu: Option Explicit Dim clsGUID As cGUID Private WithEvents rsKFZ As ADODB.Recordset Public Property Set KFZ(ByRef rs As ADODB.Recordset) Set mrsKFZ = rs End Property Public Property Get KFZ() As ADODB.Recordset Set rsKFZ = mrsKFZ End Property Private Sub cmdOK_Click() Set clsGUID = New cGUID rsKFZ.AddNew rsKFZ!I_ID = clsGUID.NewGuid rsKFZ!F_RegNum = Me.txtRegNum_Value.Text rsKFZ!F_Manufact = Me.txtManufact_Value.Text rsKFZ!F_KFZType = Me.txtKFZType_Value.Text rsKFZ!F_YearOfBuild = Me.txtYearOfBuild_Value.Text rsKFZ!L_GasType = Me.cboGastype_Value.Text rsKFZ!F_BuyDate = Me.txtBuyDate_Value.Text rsKFZ!F_BuyKM = Me.txtBuyKM_Value.Text rsKFZ!F_ActualKM = Me.txtActualKM_Value.Text rsKFZ!F_TankCapacity = Me.txtTankCapacity_Value.Text rsKFZ.UpdateBatch End Sub Private Sub Form_Terminate() Set rsKFZ = Nothing End Sub Fehler: Variable nicht definiert. mrsKFZ :confused: Zitieren
DevHB Geschrieben 13. März 2006 Geschrieben 13. März 2006 Ein bißchen selber nachdenken muss man schon, man sollte die Variablennamen auch beachten: --> Dies ist Dein formweites Recordset, welches für die Property zuständig ist 'Private WithEvents rsKFZ As ADODB.Recordset ' wird zu Private WithEvents [b]m[/b]rsKFZ As ADODB.Recordset Public Property Set KFZ(ByRef rs As ADODB.Recordset) Set mrsKFZ = rs End Property Public Property Get KFZ() As ADODB.Recordset Set rsKFZ = mrsKFZ End Property Zudem immer noch keine Antwort auf diese Frage: Allerdings frage ich mich grade, wozu man Dir Tips gibt, wenn Du sie nicht beachtest: - nicht die ! - Synthax verwenden - Änderungen an der DB über SQL und Connection und nicht über Recordset Für mich absolut unbegreiflich.... Zitieren
codeman2001 Geschrieben 13. März 2006 Autor Geschrieben 13. März 2006 Ein bißchen selber nachdenken muss man schon, man sollte die Variablennamen auch beachten: --> Dies ist Dein formweites Recordset, welches für die Property zuständig ist 'Private WithEvents rsKFZ As ADODB.Recordset ' wird zu Private WithEvents [b]m[/b]rsKFZ As ADODB.Recordset Public Property Set KFZ(ByRef rs As ADODB.Recordset) Set mrsKFZ = rs End Property Public Property Get KFZ() As ADODB.Recordset Set rsKFZ = mrsKFZ End Property Zudem immer noch keine Antwort auf diese Frage: weil mein ausbilder das so möchte... danke!!! jetzt funktioniert das... muss mir das nochmal genau abgucken, um zu begreifen, was das jetzt genau abläuft! Zitieren
DevHB Geschrieben 13. März 2006 Geschrieben 13. März 2006 Naja, dann kannst Du Deinem Ausbilder sagen, dass diese Art der Aktualiserung nicht sicher und performant ist. Ich kenne genug Anwendungen, bei denen es damit Probleme gab und ich bewege mich in der Sprache jetzt schon einige Jahre und kenne genug Beispielgeschichten von Programmierern, die VB schon seit VB 1 oder 3 machen. Ist nur ein gutgemeinter Rat, denn wenn Du auf andere DB - Systeme oder mit einer anderen Programmiersprache den Kram machst, dann wirst Du um SQL nicht herum kommen... Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.