Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Teilstring extrahieren
D. Annies - Sa 05.01.13 09:48
Titel: Teilstring extrahieren
Hi, Delpher,
ich möchte aus einem langen SQL-String den Teil als Dateinamen vergeben, der hinter der
WHERE-Phrase steht, gefolgt von der Endung '.xls'.
Beispiel: aus "Select * from Db.dbf where Klasse = '7a' soll als Dateiname werden: Klasse = 7a.xls
Wo ist denn in meiner Idee der Fehler? Die Anführungszeichen müssen ja auch noch raus.
Delphi-Quelltext
1: 2: 3:
| if pos('where', inputstring) > 0 then fname := copy(inputstring, pos+1, length(inputstring)) + '.xls'; showmessage(fname); |
Der Fehler liegt im Moment bei pos+1
Vielen Dank für Ideen,
D. Annies
Mathematiker - Sa 05.01.13 10:05
Hallo,
pos ist eine Funktion, die Parameter benötigt, und keine einfache Variable, d.h.
Delphi-Quelltext
1: 2: 3:
| stelle:=pos('where', inputstring); if stelle > 0 then fname := copy(inputstring, stelle+6, length(inputstring)) + '.xls'; |
funktioniert dann. stelle+6 ist wichtig, da 'where'+Leerzeichen sechs Zeichen lang ist.
Anschließend kannst Du noch mit
Delphi-Quelltext
1: 2: 3: 4: 5:
| stelle:=pos(chr(39), inputstring); while stelle > 0 do begin delete(inputstring,stelle,1); stelle:=pos(chr(39), inputstring); end; |
die '=chr(39) entfernen.
Beste Grüße
Mathematiker
Horst_H - Sa 05.01.13 10:07
Hallo,
Du brauchst eine Variable, die die Position speichert oder Du fragst es nochmals ab.
HIer frage ich Anfang und Ende ab.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| testString := uppercase(inputstring); posWHERE := pos('WHERE', testString); posXLS := pos('XLS', testString); if (posWHERE > 0) AND (posXLS > posWHERE) then begin inc(posWHERE,length('WHERE')+1); inc(posXLS,length('XLS')+1); fName:= copy(inputstring, posWhere, posXLS-posWhere+1); ... end; |
Gruß Horst
haentschman - Sa 05.01.13 10:26
Moin...
Ich bin dafür, das Problem an der Wurzel zu packen. 8) Wo / wie wird denn der SQL String zusammengesetzt ? Ist der hardcodiert ? Sollte man sich nicht schon zum Zeitpunkt des Zusammensetzens den "where Wert" für den Dateinamen merken als den später wieder rauszufrickeln ?
D. Annies - Sa 05.01.13 10:26
Vielen Dank für eure schnellen (und richtigen) Antworten!
Jetzt komme ich wieder weiter.
LG, Detlef
haentschman - Sa 05.01.13 10:28
...hast du meinen Einwand gelesen ?
D. Annies - Sa 05.01.13 11:35
@ haentschman:
So, jetzt habe ich deinen Einwand gelesen - sehr interessant,
aber der SQL-String ist nicht hardcodiert, sondern ich nehme ihn
aus einer Textdatei und kann ihn zur Laufzeit noch ändern/anpassen.
Ausprobieren werde ich deine Idee aber auch mal, denn die Idee habe
ich schon verstanden.
Danke, Detlef
haentschman - Sa 05.01.13 13:03
...gern geschehen. Alle lernen ständig dazu... 8)
Horst_H - Sa 05.01.13 16:30
Hallo,
haentschman hat schon recht, wenn man ohnehin den Abfragestring selbst aufbaut, kann man den Dateinamen frühest möglich extrahieren.
Wenn man schon pos benutzen will, wäre PosEx sicher auch angebracht, da es ab einer vorherigen Fund/Suchstelle suchen könnte.
http://www.delphi-treff.de/tutorials/objectpascal/stringverarbeitung/die-wichtigsten-funktionen/
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| const SuchStr1 = 'WHERE'; SuchStr2 = '.XLS';
begin fName := ''; testString := uppercase(inputstring); posWHERE := pos(SuchStr1, testString); if (posWHERE > 0) then begin inc(posWHERE,length(SuchStr1)+1); posXLS := posEX(SuchStr2, testString,posWHERE); IF posXLS >0 then begin inc(posXLS,length(SuchStr2)+1); fName:= copy(inputstring, posWhere, posXLS-posWhere+1); end; end; |
Gruß Horst
D. Annies - Sa 05.01.13 16:46
Danke, ich bin begeistert!
Gruß, Detlef
D. Annies - Sa 05.01.13 20:04
Etwas ist mir noch aufgefallen:
Der Dateiname hat (leider) immer vor der Endung .xls eine Leertaste.
Habe es auch schon mit lenght(teilstring)-1 versucht, ohne Erfolg.
LG, Detlef
D. Annies - Sa 05.01.13 22:13
Wie kann man denn diesen SpaghettiCode noch etwas komprimieren?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| stelle := pos(chr(39), fname); while stelle > 0 do begin delete(fname, stelle, 1); stelle := pos(chr(39), fname); end;
stelle := pos(chr(61), fname); while stelle > 0 do begin delete(fname, stelle, 1); stelle := pos(chr(61), fname); end;
stelle := pos(chr(37), fname); while stelle > 0 do begin delete(fname, stelle, 1); stelle := pos(chr(37), fname); end;
stelle := pos(chr(40), fname); while stelle > 0 do begin delete(fname, stelle, 1); stelle := pos(chr(40), fname); end;
stelle := pos(chr(41), fname); while stelle > 0 do begin delete(fname, stelle, 1); stelle := pos(chr(41), fname); end; fname := fname + '.xls'; |
LG, Detlef
Mathematiker - Sa 05.01.13 22:54
Hallo,
D. Annies hat folgendes geschrieben : |
| Wie kann man denn diesen SpaghettiCode noch etwas komprimieren? |
Mein Vorschlag wäre, alle Zeichen zu einem String zusammenzufassen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| loeschstring:=chr(39)+chr(61)+chr(37)+chr(40)+chr(41); for i:=1 to length(loeschstring) do begin stelle := pos(loeschstring[i], fname); while stelle > 0 do begin delete(fname, stelle, 1); stelle := pos(loeschstring[i], fname); end; end; fname := fname + '.xls'; |
Beste Grüße
Mathematiker
D. Annies - Sa 05.01.13 23:58
Danke, sieht sehr gut aus!
Also:
var loeschstring : String;
oder
var loeschstring : String[10];
ich bin ja immer vorsichtig ...
LG, Detlef
Mathematiker - So 06.01.13 00:30
Hallo,
D. Annies hat folgendes geschrieben : |
Also:
var loeschstring : String;
oder
var loeschstring : String[10]; |
Beides ist möglich. Ich bevorzuge string, ohne Begrenzung.
Zu Pascal-Zeiten hätte ich den String noch eingeschränkt, aber bei den heutigen Computern ...
Beste Grüße
Mathematiker
Delphi-Laie - So 06.01.13 01:24
D. Annies hat folgendes geschrieben : |
Der Dateiname hat (leider) immer vor der Endung .xls eine Leertaste.
Habe es auch schon mit lenght(teilstring)-1 versucht, ohne Erfolg. |
Na, wohl nicht Leertaste, sondern Leerzeichen.
Mit Delete bekommt man Teile aus einem String gelöscht, ich glaube, die Syntax lautet: Delete(Stringvariable,Startposition,Anzahl_Löschzeichen).
Delete - So 06.01.13 08:19
D. Annies hat folgendes geschrieben : |
| Der Dateiname hat (leider) immer vor der Endung .xls eine Leertaste. |
Leerzeichen an Anfang und Ende eines Strings entfernt man mit Trim.
D. Annies - So 06.01.13 10:47
Gibt es noch einen begabten, der auch diesen Code zusammenfassen kann?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| stelle := pos('WHERE', teststring); if stelle > 0 then fname := copy(teststring, stelle+6, length(teststring)-1);
stelle := pos('ORDER', teststring); if stelle > 0 then fname := copy(teststring, stelle+6, length(teststring)-1);
stelle := pos('GROUP', teststring); if stelle > 0 then fname := copy(teststring, stelle+6, length(teststring)-1); |
Danke, Detlef
Mathematiker - So 06.01.13 11:17
Hallo,
mein Vorschlag:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| const suchstring:array[1..3] of string[6] = ('WHERE','ORDER','GROUP'); ... for i:=1 to 3 do begin stelle := pos(suchstring[i], teststring); if stelle > 0 then fname := copy(teststring, stelle+length(suchstring[i])+1, length(teststring)-1); end; |
Beste Grüße
Mathematiker
D. Annies - So 06.01.13 13:13
Kurze Nachfrage: Warum nicht VAR suchstring: ...
LG Det
Mathematiker - So 06.01.13 13:33
Hallo,
D. Annies hat folgendes geschrieben : |
| Kurze Nachfrage: Warum nicht VAR suchstring: |
Wählst Du var, so musst Du im Text die Wörter zuweisen, z.B.
Delphi-Quelltext
1: 2: 3: 4: 5:
| var suchstring:array[1..3] of string[6]; ... suchstring[1]:='WHERE'; suchstring[2]:='ORDER'; suchstring[3]:='GROUP'; |
Mit const können die entsprechenden Werte automatisch zugewiesen werden.
Beste Grüße
Mathematiker
D. Annies - So 06.01.13 14:18
Toll! und Danke!
WasWeißDennIch - So 06.01.13 19:02
Ich möchte noch einmal auf haentschmans berechtigten Einwand zurückkommen. Wenn die Dateinamen in einer Datei stehen, wieso wird dann nicht gleich beim Auslesen der neue Dateiname gebildet? Diese ganze Pos-Frickelei erscheint mir eher kontraproduktiv, die Verwendung von Shortstrings macht das Ganze dann noch schlimmer und ist auch unnötig, da eine Stringkonstante automatisch die richtige Länge aufweist, ohne dass man sie extra einschränkt. Ich habe gerade kein Delphi zur Hand, aber wenn man Pos unter Delphi >= 2009 mit einem Shortstring und einem String-Parameter anwendet, sollte es zumindest eine (vermeidbare) Compilerwarnung geben, da dort Shortstrings 1 Byte und Strings 2 Byte je Zeichen besitzen. Ich denke, man kann das auch einfacher gestalten (Pseudo-Code):
Delphi-Quelltext
1: 2: 3: 4: 5:
| var DateinameXLS, DateinameSQL: string; begin DateinameSQL := gelesener_Wert_aus_Datei; DateinameXLS := ChangeFileExt(DateinameSQL, '.xls'); |
Weiterhin kann ich nur dringend empfehlen, SQL-Parameter zu verwenden. Neben der automatisch korrekten SQL-Syntax werden damit auch SQL-Injections vermieden (und schneller sind Prepared Statements nebenher auch noch).
Delphi-Quelltext
1: 2: 3:
| Query.SQL.Text := 'SELECT Feldliste FROM Tabelle WHERE Feldwert = :wert'; ... Query.ParamByName('wert').Value := DateinameSQL; |
Mathematiker - So 06.01.13 19:11
WasWeißDennIch hat folgendes geschrieben : |
| Ich habe gerade kein Delphi zur Hand, aber wenn man Pos unter Delphi >= 2009 mit einem Shortstring und einem String-Parameter anwendet, sollte es zumindest eine (vermeidbare) Compilerwarnung geben, da dort Shortstrings 1 Byte und Strings 2 Byte je Zeichen besitzen. |
Toll, was Du alles weißt. Wir sind alle beeindruckt. :?
Ich würde aber erst einmal lesen, welche Compiler D.Annies nutzt. Dein Hinweis auf Delphi 2009-Strings bringt ihm absolut nichts!
Beste Grüße
Mathematiker
WasWeißDennIch - So 06.01.13 19:16
Entschuldigung, ich wusste nicht, dass man hier nur spezifische Antworten für spezifische User mit spezifischen Delphi-Versionen geben darf. Naja, nach einem evtl. Delphi-Update hätte er es ja dann selbst gemerkt, ich werde in Zukunft auf allgemeingültige Antworten verzichten. Dann kann man ja gleich alles per PM lösen und braucht kein Forum mehr.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!