Werte aus txt-Datei in Editkomponenten schreiben



  • ich stimme zu, dass es so etwas umständlich ist. ich werds mal mit der TStringList probieren.



  • habs jetzt fast:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
       if (OpenDialog1->Execute()) {
          TStringList* temp = new TStringList();
          temp->LoadFromFile(OpenDialog1->FileName);
          Edit1->Text = temp->Strings[0];
          Edit2->Text = temp->Strings[1];
          Edit3->Text = temp->Strings[2];
          }
    }
    

    nu muss ich nur noch den String ab der Position ":" ausgeben. jmd eine idee?



  • Dafür gibt es die Methoden AnsiString::AnsiPos() und AnsiString::SubString(). Mit AnsiPos kannst Du die Position des Doppelpunktes ermittleln, mit SubString einen Teil des Strings kopieren.



  • void __fastcall TForm1::Button1Click(TObject *Sender)
    {
       if (OpenDialog1->Execute()) {
          TStringList* temp = new TStringList();
          temp->LoadFromFile(OpenDialog1->FileName);
          AnsiString s1(temp->Strings[0]);
          Edit1->Text = SubString(s1.Pos(":"),100);
          }
    }
    

    habs mal versucht, aber bekomm die Meldung: E2268 Aufruf der undefinierten Funktion 'SubString'

    klingt für mich wie fehlender Header, welcher soll das denn sein?
    using namespace std; hab ich auch drin



  • Hallo,

    nee mit fehlendem Header hat das nichts zu tun. Die Meldung besagt dass eine Funktion aufgerufen wird, die nicht existiert. SubString, Pos und Length gehören allesamt zu AnsiString

    AnsiString s1 = temp->Strings[0]; 
    int pos = s1.Pos(":");
    Edit1->Text = s1.SubString(pos,s1.Length()-pos);
    

    LG, Micha



  • ja na klar 🙂 nu hab ich es:

    void __fastcall TForm1::ffnen1Click(TObject *Sender)
    {
       if (OpenDialog1->Execute()) {
          TStringList* temp = new TStringList();
          temp->LoadFromFile(OpenDialog1->FileName);
          AnsiString s1(temp->Strings[0]);
          AnsiString s2(temp->Strings[1]);
          AnsiString s3(temp->Strings[2]);
          Edit1->Text = s1.SubString(s1.Pos(":")+2,100);
          Edit2->Text = s2.SubString(s2.Pos(":")+2,100);
          Edit3->Text = s3.SubString(s3.Pos(":")+2,100);
          delete temp;
          }
    }
    

    supi danke



  • Dann vielleicht abschließend noch der Hinweis, dass der direkte Zugriff auf die einzelnen Zeilen der StringList zu einem Zugriffsfehler führt, wenn weniger als 3 Zeilen in der StringList sind. Du solltest eventuell eine entsprechende Überprüfung einbauen (siehe TStringList::Count).
    Auch bei der Position des Doppelpunktes kann eine Überprüfung nicht schaden, auch wenn es in diesem Fall nicht zu einem Fehler führt, wenn kein Doppelpunkt vorhanden ist, sondern nur dazu, dass die komplette Zeile kopiert wird, zumindest so lange diese nicht leer ist. Ich würde also zumindest noch prüfen, ob die aktuelle Zeile leer ist (siehe AnsiString.IsEmpty()).



  • das stimmt. drücke ich speichern wenn nur 2 Editfelder ausgefüllt sind, klappt das. Öffne ich diese datei danach gibts einen Fehler. Das will ich natürlich nicht.
    wie stell ich das am schlausten an? würde das mit einer if Abfrage machen. Am besten wäre ja wenn er die Datei trotzdem öffnet und die entsprechenden Editfelder einfach leer lässt.

    das hab ich bisher:

    void __fastcall TForm1::BatchOeffnenExecute(TObject *Sender)
    {
       if (OpenDialog1->Execute()) {
          temp->LoadFromFile(OpenDialog1->FileName);
          if (temp->Count >=3) {
             AnsiString s1(temp->Strings[0]);
             AnsiString s2(temp->Strings[1]);
             AnsiString s3(temp->Strings[2]);
             Edit1->Text = s1.SubString(s1.Pos(":")+2,s1.Length());
             Edit2->Text = s2.SubString(s2.Pos(":")+2,s2.Length());
             Edit3->Text = s3.SubString(s3.Pos(":")+2,s3.Length());
             }
          }
    }
    


  • Ok, ich zeig Dir mal die Luxusvariante, bei der es egal ist, wie viele TEdits Du schlußendlich auf dem Formular hast:

    // TStringList aus Datei laden
    for (int i = 0; i < slTemp->Count; i++)
    {
    	AnsiString asCurLine = slTemp->Strings[i];
    	if (!asCurLine.IsEmpty()) // nur wenn Zeile nicht leer
    	{
    		TEdit* pEdit;
    		//Editfeld zu Zeile suchen
    		for (int x = 0; x < this->ComponentCount; x++) // durch Liste der Komponenten des Formulars iterieren
    		{
    			if (this->Components[x]->ClassNameIs("TEdit")) // nur wenn Komponente ein Editfeld ist
    			{
    				pEdit = dynamic_cast <TEdit*> (this->Components[x]);
    				if (pEdit) // nur wenn gültigen Zeiger erhalten
    				{
    					if (pEdit->Name == "Edit" + AnsiString(i+1)) // nur wenn der Name des Editfeldes dem Index (+ 1) aus der StringList entspricht, also Zeile 0 = Edit1
    					{
    						int iPos = asCurLine.AnsiPos(":");
    						if (iPos) // nur wenn Doppelpunkt gefunden
    						{
    							asCurLine = asCurLine.Delete(1, iPos); // alles bis einschließlich des Doppelpunktes löschen
    							pEdit->Text = asCurLine.Trim(); // und dem Editfeld zuweisen. Eventuell vorhandene Leerzeichen am Anfang und Ende des Strings werden dabei gelöscht
    						}
    					}
    				}
    			}
    		}
    	}
    }
    

    Mit einer ähnlichen Schleife könnte man auch das Speichern realisieren. Wenn der Text in der Datei vor dem Doppelpunkt für Dich eigentlich unwichtig ist, könnte man dort auch den Namen des Editfeldes reinschreiben, dann kann man den Eidtfeldern auch richtige Namen geben. Damit bist Du dann unabhängig davon, dass die Edits immer korrekt durchnummeriert sein müssen. Dabei kann man dann beim Einlesen die Eigenschaft Values von TStrings hervorragend verwenden.

    Ich hoffe das erschlägt Dich jetzt nicht...



  • erst mal vielen Dank für die Mühe.
    ui, na ob ich das verstehe...

    davor kommt noch:

    TStringList* temp = new TStringList();
    void __fastcall TForm1::BatchOeffnenExecute(TObject *Sender)
    {
    if (OpenDialog1->Execute()) {
       temp->LoadFromFile(OpenDialog1->FileName);
    
    //Dein Code
    
    }
    

    oder?

    verstehe schon

    TEdit* pEdit; // Editfeld zu Zeile suchen
    for (int x = 0; x < this->ComponentCount; x++)
    

    nicht mehr



  • rudpower schrieb:

    davor kommt noch:
    ...
    //Dein Code
    oder?

    Nein, das ist soweit richtig. 😉

    rudpower schrieb:

    verstehe schon

    TEdit* pEdit; // Editfeld zu Zeile suchen
    for (int x = 0; x < this->ComponentCount; x++)
    

    nicht mehr

    Das steht ja auch so nicht da, sondern in einer eigenen Zeile und bezieht sich auf die Schleife darunter. Der Name des Editfeldes ist direkt von der Zeile in der Stringlist abhängig. Zeile 0 enthält immer den Wert für Edit1, Zeile 1 immer den Wert für Edit2 usw.

    Bei

    TEdit* pEdit;
    

    wird einfach nur ein Zeiger deklariert, praktisch ist das nur eine Hilfsvariable, die für den Zugriff benötigt wird. Die Iteration über die Komponenten ergibt immer einen Zeiger vom Typ TComponent, den können wir allerdings nicht brauchen, sondern brauchen einen Zeiger auf das TEdit. Dafür ist der dynamic_cast da. Damit wird versucht den Zeiger vom Typ TComponent in TEdit zu casten. Gelingt dies, enthält pEdit anschließend den Zeiger. Wenn der Cast nicht erfolgreich war (zB weil die Komponente kein TEdit ist), dann enthält der Zeiger NULL. Das wird mit

    if (pEdit)
    

    geprüft und der Rest des Codes nur dann ausgeführt, wenn der Cast tatsächlich erfolgreich war und der Wert in pEdit ungleich NULL ist. Dieser Rest besteht eigentlich nur noch aus der Aufteilung des Strngs und der Zuweisung zum Editfeld.

    Ist das so verständlicher?

    Man muss das bei 3 Editfeldern auch nicht so machen, aber wenn es mal mehr werden, erleichtert es einem die Arbeit. Du brauchst nicht für jedes weitere Editfeld eine neue if-Abfrage, sondern musst eigentlich nichts weiter machen, als die Strings an der entsprechenden Position in die Datei zu schreiben. Der Code funktioniert also mit 3 Editfeldern genau so gut, wie mit 100 Editfeldern.

    Schau es Dir noch mal in Ruhe an... Wenn Du gar nicht klar kommst, zeige ich Dir gerne auch den leicht verständlicheren, aber unter Umständen, schwerer wartbaren Code.



  • hab es so halbwegs verstanden bzw nachvollziehen können. Aber ich könnt das nie im Leben selbst schreiben. Kenne ja schon die Eigenschaft Components gar nicht.

    Hatte statt Editkomponenten TLMDLabeled-Komponenten. Hatte das im Code entsprechend abgeändert. Die Felder blieben aber leer. Hab dann doch Editkomponenten genommen.

    trage ich nur bei 2 Editkomponenten Werte ein speichere und lade, gibts einen Fehler (EAccessViolation).



  • Die Unerfahrenheit legt sich mit der Zeit. 😉

    Ich kann Dir nur empfehlen, Dir die unverständlichen Sachen in der Hilfe anzusehen und gegebenenfalls noch einmal nachzufragen.


Anmelden zum Antworten