Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi CSV anpassen (https://www.delphipraxis.net/206659-csv-anpassen.html)

julchen 15. Jan 2021 21:15

CSV anpassen
 
Hallo,

Ich habe eine Liste, die ich nach dem Schema anpassen möchte:
Anrede;Titel;Titel;Nachname;Vorname;mit

Die Liste ist so aufgebaut:
Herr Mustermann mit
Herr Mustermann, Max mit
Herr Dr. Mustermann mit
Herr Dr. Mustermann, Max mit
Herr Prof. Dr. Mustermann mit
Herr Prof. Dr. Mustermann, Max mit

Das Semikolon nach Herr bekomme ich hin mit StringReplace.

Nach Prof. wollte ich mit pos und insert das Semikolon einfügen.
Funktioniert aber nicht.
Was mache ich da falsch?
Code:
var
  s1, s2:string;
  i: integer;
  pos1: integer;

begin
  for i := 0 to Memo1.Lines.Count - 1 do
  begin
  s1 := Memo1.lines[i];
  pos1 := pos('Prof.', s1, pos1 + 1 );
  if pos1 <> 0 then
  begin
   Insert(';' , s1 , pos1);
  end;
VG, Julia

juergen 15. Jan 2021 21:28

AW: CSV anpassen
 
Möchtest du das Ergebnis im Memo speichern?
Ich frag deshalb, weil du das Ergebnis nur in einer Variable vorhältst und man nicht sehen kann wie du diese weiter verwendest.
Wäre evtl. nicht das Ausführen von 2 StringRepace besser? Einmal mit ' ', ';' und einmal mit ', ', ';'
Evtl. direkt auf Memo.Text angewendet, falls das Memo das Ergebnis bekommen soll:

Delphi-Quellcode:
Memo.Text := StringReplace( Memo.Text, ' ', ';', [rfReplaceAll] );
Memo.Text := StringReplace( Memo.Text, ',', ';', [rfReplaceAll] );

Klaus01 15. Jan 2021 22:17

AW: CSV anpassen
 
.. wenn Du das als csv machen willst,

Dann sollten alles Zeilen die gleiche Anzahl von Elementen enthalten.

Herr, , ,Mustermann, ,mit
Herr, , ,Mustermann, Max, mit
Herr,Dr., ,Mustermann, ,mit
Herr,Dr., ,Mustermann, Max, mit
Herr,Prof.,Dr.,Mustermann, ,mit
Herr,Prof.,Dr., Mustermann, Max, mit

Das automatisch hinzubekommenist nicht so einfach.
Wie willst Du denn z.B. Namen und Vornamen unterscheiden?
Oder ist es bei den Daten sicher, dass zumindest der Nachname aufgelistet ist?

Die Titel, würde ich in ein Feld packen, also Prof, Prof. Dr., Prof. Dr. Dr.,

Grüße
Klaus

jziersch 16. Jan 2021 09:10

AW: CSV anpassen
 
Ich würde zunächst aufteilen in Nachname , Vorname (mit Pos(',')

anschliessend schauen welche Anreden und Titel noch vor dem Nachname stehen. Dafür brauchst Du ein Array mit allen möglichen Anreden und kannst über eine Schleife diese der Reihe nach im Nachnamen suchen.

if Pos( a[i], Copy(nachname, 1, Length(a[i])))=1 then ...

Am Ende kannst Du in einer StringList das CSV aufbauen. Es ist dort aber üblich, textelemente in "" zu stellen.

bernau 16. Jan 2021 11:09

AW: CSV anpassen
 
Zitat:

Zitat von Klaus01 (Beitrag 1481022)
Wie willst Du denn z.B. Namen und Vornamen unterscheiden?

Wie es aussieht, sind diese schon im Ursprung mit einem Komma (dem einzigen) separiert.

julchen 16. Jan 2021 17:23

AW: CSV anpassen
 
Hallo und Danke für die bisherige Rückmeldung,

Die Daten sehen so aus, wie im Beispiel angeführt.
Einen Nachnamen hat jeder Mitarbeiter.

Ich kopiere die Liste in ein Memo.

Die Anzahl der vorgegebenen Elemente, seien es Leerzeichen oder Kommas kann ich nicht beeinflussen.

Nachname und Vorname sind immer durch ein Komma getrennt.

Ich muss mal sehen, ob ich es heute noch schaffe, ein bisschen Code auszuprobieren.

VG, Julia

bernau 16. Jan 2021 21:07

AW: CSV anpassen
 
Frage:

1) Kann man davon ausgehen, dass der String IMMER mit einer Anrede anfängt (also Herr, oder Frau)?
2) Kann man davon ausgehen, dass der String IMMER mit dem Wort "mit" endet?

Oder kann die Anrede oder das Wort "mit" auch mal wegfallen?

Entsprechend kurz oder länger wird der Code. ;-)

Sinspin 17. Jan 2021 09:18

AW: CSV anpassen
 
CSV geht aber anders. TStringlist... Add(string)... CommaText und schon ist eine Zeile fertig.
Speichern in einer zweiten TStringList. Die auslesen via Text oder SaveToFile.
Dann hat man eine CSV Datei.

julchen 17. Jan 2021 10:39

AW: CSV anpassen
 
Zitat:

Zitat von bernau (Beitrag 1481065)
Frage:

1) Kann man davon ausgehen, dass der String IMMER mit einer Anrede anfängt (also Herr, oder Frau)?
2) Kann man davon ausgehen, dass der String IMMER mit dem Wort "mit" endet?

Oder kann die Anrede oder das Wort "mit" auch mal wegfallen?

Entsprechend kurz oder länger wird der Code. ;-)

Die Anrede ist immer Herr oder Frau.

Es gibt immer ein mit.

julchen 17. Jan 2021 10:44

AW: CSV anpassen
 
Ich habe die Funktion CompareStrings gefunden.

Ich habe da den ganzen Morgen schon mit rumgespielt, aber es klappt nicht.
Habe schon alle möglichen Kombinationen durch und komme nicht weiter.
Wenn Herr kleiner als Prof ist, dann ein Semikolon, sonst zwei.

Code:
procedure TForm1.Button1Click(Sender: TObject);
var herr, prof: string;
begin

  herr := 'Herr';
  prof := 'Prof.';
  CompareStrings(herr, prof);
end;

procedure TForm1.CompareStrings(const herr, prof: string);
var
  result : Integer;
  i: Integer;
begin

  begin
  for i := 0 to Memo1.Lines.Count - 1 do
     result := AnsiCompareText(herr , prof);
     if result < 0 then
     begin
       Memo1.Text := Stringreplace(Memo1.Text, herr, 'Herr;' , [rfReplaceAll])
     end

  end;

   for i := 0 to Memo1.Lines.Count - 1 do
     result := AnsiCompareText('Herr;', prof);
     if result < 0 then
     begin
       Memo1.Text := Stringreplace(Memo1.Text, 'Herr' , 'Herr;;' , [rfReplaceAll])
     end

  end;

Klaus01 17. Jan 2021 11:57

AW: CSV anpassen
 
.. CompareStrings vergleicht die Zeichen der Zeichenkette nicht deren Länge.
Da ist es egal ob am Ende ein Semikolon ist oder auch zwei.
'Herr' und 'Prof' unterscheiden sich schon beim ersten Zeichen.

Grüße
Klaus

stifflersmom 17. Jan 2021 11:58

AW: CSV anpassen
 
Da Deine Titel immer eien Punkt beinhalten, kannst Du wohl mit einer Stringlist arbeiten
So mal aus dem Ärmel:

Code:
procedure inputcsv;
var sl : TstringList;
    Anrede, Titel, Name, Vorname, Suffix : String;
begin
 sl := TStringList.Create();
 sl.Delimiter := ',';
 sl.StrictDelimiter := true;
 Try
// Als Beispiel, später sollte das bei Dir eine übergeben Variable an ene Funktion sein,
// die als Ausgabe dann Deinen Wunschstring enthält
 sl.DelimitedText := 'Herr,Prof., Mustermann, Max, mit';

 Anrede := sl[0];
 If Pos('.',sl[1]) > 0 Then // Titel vorhanden
 Begin
 Titel := sl[1];
 Name := sl[2];
 Vorname := sl[3];
 Suffix := sl[4];
 end
 else Begin
 Titel := '';
 Name := sl[1];
 Vorname := sl[2];
 Suffix := sl[3];
 End;
 Finally
  sl.free

End;
Hier gibt es keine Fehlerüberpüfung und sonstige Feinheiten und im Name darf auch kein Punkt vorkommen, aber grundsätzlich siehst Du hier einen gangbaren Weg.

bernau 17. Jan 2021 12:23

AW: CSV anpassen
 
Probier es mal damit. BtnStartClick muss du dir entsprechend anpassen:

Delphi-Quellcode:
Procedure SplitAtPosAndTrim(const aSource: String; const aPosOfRightPart: Integer; var aLeftPart: string; var aRightPart: String);
begin
  aRightPart := Trim(copy(aSource, aPosOfRightPart, length(aSource) - aPosOfRightPart+1));
  aLeftPart := Trim(copy(aSource, 1, aPosOfRightPart-1));
end;

Function KonvertToCsvString(aSourceString: String): String;
const
  lTitelVorgaben: array [0 .. 2] of string = ('Dr.', 'Prof.', 'Dipl.-Ing.');
var
  lAnrede: String;
  lTitel1: String;
  lTitel2: String;
  lNachname: String;
  lVorname: String;
  lMit: string;
var
  lpos: Integer;
  a: Integer;
begin
  //*************************************************************
  // Vorsorglich Sonderzeichnen und Leerzeichen am Anfang und Ende ntfernen
  aSourceString := Trim(aSourceString);
  //*************************************************************
  // "mit" ist immer vorhanden und muss extrahiert werden
  SplitAtPosAndTrim(aSourceString, length(aSourceString) - 3, aSourceString, lMit);
  // Hier ggf kontrollieren, ob Source tatsächlich mit dem Wort "Mit" endete. > "if not SameText(lmit,'mit') then"
  //*************************************************************
  // Anrede ist immer als erstes vorhanden. Bis zum ersten Leerzeichen.
  lpos := PosEx(' ', aSourceString);
  SplitAtPosAndTrim(aSourceString, lpos, lAnrede, aSourceString);
  //*************************************************************
  // Anrede 1 filtern
  for a := low(lTitelVorgaben) to high(lTitelVorgaben) do
    if StartsText(lTitelVorgaben[a], aSourceString) then
      begin
        SplitAtPosAndTrim(aSourceString, length(lTitelVorgaben[a]) + 1, lTitel1, aSourceString);
        Break;
      end;
  //*************************************************************
  // Anrede 2 filtern
  for a := low(lTitelVorgaben) to high(lTitelVorgaben) do
    if StartsText(lTitelVorgaben[a], aSourceString) then
      begin
        SplitAtPosAndTrim(aSourceString, length(lTitelVorgaben[a]) + 1, lTitel2, aSourceString);
        Break;
      end;
  //***************************************************************************************
  // Nachname und Vorname ermitteln
  lpos := pos(',', aSourceString);
  if lpos = 0 then
    lNachname := aSourceString
  else
    begin
      SplitAtPosAndTrim(aSourceString, lpos + 1, lNachname, lVorname);
      // abschliessendes Komma entfernen
      lNachname := copy(lNachname, 1, length(lNachname) - 1);
    end;

  Result := lAnrede + ';' + lTitel1 + ';' + lTitel2 + ';' + lNachname + ';' + lVorname + ';' + lMit;
end;

procedure TForm1.BtnStartClick(Sender: TObject);
var
  a:Integer;
begin
  for a:=0 to MemoSource.lines.count-1 do
    MemoDest.lines.add(KonvertToCsvString(MemoSource.Lines[a]));
end;

julchen 17. Jan 2021 12:48

AW: CSV anpassen
 
Was ist Startstext?
Ich kann das nicht deklarieren.

bernau 17. Jan 2021 12:51

AW: CSV anpassen
 
Unit System.StrUtils einbinden.

http://docwiki.embarcadero.com/Libra...ils.StartsText

julchen 17. Jan 2021 13:01

AW: CSV anpassen
 
Das sieht schon gut aus.
Es gibt noch einen Fehler.
Zwischen Dr. (ohne Prof.) und Nachname werden zwei Semikolons eingefügt.
Dadurch verschiebt sich Dr. zu Prof.

EmWieMichael 17. Jan 2021 13:38

AW: CSV anpassen
 
Sicher führen viele Wege nach Rom. Hier ist einer davon:
Delphi-Quellcode:
procedure TSIPForm.Test;
 var Line, aWord : String;
     A          : Array [1..6] of String;
     I, K, L    : Integer;

  function GetNextWord(var S:String):String;
   var P:Integer;
  begin
    Result:='';
    P:=Pos(#32, S);
    if (P > 0) then
     begin
       Result:=Copy(S, 1, P - 1);
       Delete(S, 1, P);
     end;
  end;

begin
  RichEdit.Clear;
  RichEdit.Lines.Add('Herr Mustermann mit');
  RichEdit.Lines.Add('Herr Mustermann, Max mit');
  RichEdit.Lines.Add('Herr Dr. Mustermann mit');
  RichEdit.Lines.Add('Herr Dr. Mustermann, Max mit');
  RichEdit.Lines.Add('Herr Prof. Dr. Mustermann mit');
  RichEdit.Lines.Add('Herr Prof. Dr. Mustermann, Max mit');
  RichEdit.Lines.Add('');
  for L:=0 to RichEdit.Lines.Count - 1 do if (RichEdit.Lines[L] > '') then
   begin
     Line:=RichEdit.Lines[L];
     for I:=1 to 6 do A[I]:='';
     repeat
       aWord:=GetNextWord(Line);
       if (aWord > '') then
        begin
          if (A[1] = '') then A[1]:=aWord
          else
           begin
             if (aWord = 'Prof.') or (aWord = 'Dr.') then
              begin
                if (A[2] = '') then A[2]:=aWord else A[3]:=aWord;
              end
             else
              begin
                K:=Pos(',', aWord);
                if (K > 0) then Delete(aWord, K, 1);
                if (A[4] = '') then A[4]:=aWord else A[5]:=aWord;
              end;
           end;
        end;
       A[6]:='mit';
     until (aWord = '');
     Line:='';
     for I:=1 to 6 do Line:=Line + A[I] + ';';
     Delete(Line, Length(Line), 1);
     RichEdit.Lines.Add(Line);
   end;
end;

bernau 17. Jan 2021 16:15

AW: CSV anpassen
 
Zitat:

Zitat von julchen (Beitrag 1481083)
Das sieht schon gut aus.
Es gibt noch einen Fehler.
Zwischen Dr. (ohne Prof.) und Nachname werden zwei Semikolons eingefügt.
Dadurch verschiebt sich Dr. zu Prof.

Das ist Absicht. Vielleicht habe ich dich auch falsch verstanden, aber
a) CSV macht m.E. nur Sinn, wenn man einen Wert immer an der gleichen Stelle erwarten kann.
b) In deinem eingangspost hast du geschrieben wie das Ergebnis aussehen soll
Zitat:

Anrede;Titel;Titel;Nachname;Vorname;mit
1. Eintrag = Anrede
2. Eintrag = Titel1
3. Eintrag = Titel2
4. Eintrag = Nachname
5. Eintrag = Vorname
6. Eintrag = mit

Um es mal untereinander darzustellen (Mit dem Zeichen '>' aufgefüllt. Leerzeichen werden hier leider entfernt)

Code:
Herr;>>>>>;>>>;Mustermann;>>>;mit
Herr;>>>>>;>>>;Mustermann;Max;mit
Herr;Dr.>>;>>>;Mustermann;>>>;mit
Herr;Dr.>>;>>>;Mustermann;Max;mit
Herr;Prof.;Dr.;Mustermann;>>>;mit
Herr;Prof.;Dr.;Mustermann;Max;mit

Klaus01 17. Jan 2021 16:46

AW: CSV anpassen
 
.. wie schonmal angemerk, würde ich die Titel zusammenfassem.
Denn es gibt auch Menschen die mehr als zwei Titel haben.
Prof. Dr. Dr. rer. Nat.
Prof. Dr. Dipl.-Ing.

usw.

Grüße
Klaus

bernau 17. Jan 2021 16:59

AW: CSV anpassen
 
Zitat:

Zitat von Klaus01 (Beitrag 1481096)
.. wie schonmal angemerk, würde ich die Titel zusammenfassem.

So würde ich es auch machen. Aber wir wissen ja nicht, weshalb die Trennung gewünscht ist.

Moombas 18. Jan 2021 07:46

AW: CSV anpassen
 
Wie Klaus bereits hier schrieb: https://www.delphipraxis.net/1481022-post3.html
Wäre es am Besten, eine klare Struktur als CSV zu haben.
Wobei ich immer die Variante mit "" bevorzuge, dann wäre das bei dir:
"Anrede";"Titel";"Nachname";"Vorname";"mit" //wozu das "mit" auch immer steht

Diese kann man dann (zumindest in Lazarus) mittels bereits existierender Funktion in ein Grid laden:
Delphi-Quellcode:
Grid.LoadFromCSVFile('Dateiname')
Dies kannst du dann entsprechend viel leichter behandeln und die Fehlerquote ist geringer.

Oben bitte mal ignorieren, ich denke du willst aus deinen Daten eine richtige CSV machen, diese also "korrigieren".

Woher kommt denn deine Text/CSV-Datei? Musst du sie wirklich selber anpassen oder wäre es nicht ggf. Sinnvoller die Quelle anzupassen (wenn möglich).

Jumpy 18. Jan 2021 09:12

AW: CSV anpassen
 
Könnte man das nicht irgendwie OOP sauber lösen, anstatt so eine Stringlist Orgie?

Man erstellt ein Objekt für eine Person mit den Benötigten Feldern, übergibt dann den jetzigen langen String für eine Person an das Objekt. Darin wird der String zerlegt und auf die Felder verteilt. Dann kriegt das Objekt noch eine ToCSVString Funktion oder so, die das in der richtigen Reihenfolge mit Semikolon getrennt raus gibt.

Bei der Zerlegung des String bleiben natürlich trotzdem die bisher genannten Probleme zu Unterscheiden, was was ist.

Uwe Raabe 18. Jan 2021 11:02

AW: CSV anpassen
 
Zitat:

Zitat von Klaus01 (Beitrag 1481096)
.. wie schonmal angemerk, würde ich die Titel zusammenfassem.

Würde ich auch machen. Hier mal eine rudimentäre Funktion dafür:
Delphi-Quellcode:
function MakeCSV(Line: string): string;
var
  lst: TStringList;
  M: Integer;
  N: Integer;
begin
  lst := TStringList.Create;
  try
    { Anrede }
    N := Line.IndexOf(' ');
    lst.Add(Line.Substring(0, N));
    Line := Line.Remove(0, N + 1);
    { Titel }
    N := Line.LastIndexOf('.');
    if N > 0 then begin
      { Punkt mitnehmen }
      lst.Add(Line.Substring(0, N + 1));
      Line := Line.Remove(0, N + 2);
    end
    else begin
      { kein Titel }
      lst.Add('');
    end;
    { gibt es einen Vornamen? }
    N := Line.IndexOf(',');
    if N > 0 then begin
      { Nachname }
      lst.Add(Line.Substring(0, N));
      { Komma und Leerzeichen mit entfernen }
      Line := Line.Remove(0, N + 2);
      { Vorname }
      N := Line.IndexOf(' ');
      lst.Add(Line.Substring(0, N));
      Line := Line.Remove(0, N + 1);
    end
    else begin
      { Nachname }
      N := Line.IndexOf(' ');
      lst.Add(Line.Substring(0, N));
      Line := Line.Remove(0, N + 1);
      { kein Vorname }
      lst.Add('');
    end;
    { "mit" }
    lst.Add(Line);

    Result := lst.CommaText;
  finally
    lst.Free;
  end;
end;

julchen 18. Jan 2021 19:55

AW: CSV anpassen
 
Hallo,

vielen Dank für eure Hilfe und die tollen Codebeispiele.
Hätte ich nieeeeee geschafft.
Mit dem Titel habe ich mir überlegt, das ein Eintrag für alle Titel reicht.
Werde Morgen mit dem Code weiterarbeiten. Melde mich dann wieder.
Bis dahin und ich noch einen schönen Abend euch allen.
VG Julia

Rollo62 19. Jan 2021 08:06

AW: CSV anpassen
 
Zitat:

Zitat von julchen (Beitrag 1481151)
Hätte ich nieeeeee geschafft.

Dooooch, sicher.
Übung mach die Meisterin :-D

Blup 20. Jan 2021 10:12

AW: CSV anpassen
 
@Jumpy
OOP bedeuted nicht, das alle Methoden die irgendetwas mit dem Datenobjekt zu tun haben, auch im Datenobjekt implementiert werden.
Methoden für den Export oder Import gehören dann eher in eine Klasse die das entsprechende Dateiformat representiert.

Da es sich hier um zwei verschiedene Formate handelt, würde ich den Export und Import zumindest in zwei Methoden aufteilen.
Das erhöht vieleicht auch die Lesbarkeit.

Als Trennzeichen soll das Semikolon genutz werden.
Ich habe den Code von Uwe Raabe ein bischen abgewandelt https://www.delphipraxis.net/1481113-post23.html

Delphi-Quellcode:
type
  TMyData = record
    Anrede: string;
    Titel: string;
    Nachname: string;
    Vorname: string;
    mit: string;
  end;

function TextToMyData(ALine: string): TMyData;
var
  N: Integer;
begin
  { "Anrede" immer vorhanden }
  N := ALine.IndexOf(' ');
  Result.Anrede := ALine.Substring(0, N);
  ALine := ALine.Remove(0, N + 1);

  { "Titel" ein oder mehrere optional }
  N := ALine.LastIndexOf('.');
  if N > 0 then
  begin
    { Punkt mitnehmen }
    Result.Titel := ALine.Substring(0, N + 1);
    ALine := ALine.Remove(0, N + 2);
  end;

  { "mit" immer vorhanden }
  N := ALine.LastIndexOf(' ');
  if N > 0 then
  begin
    Result.mit := ALine.Substring(N + 1);
    ALine := ALine.Remove(N);
  end;

  { "Vorname" optional }
  N := ALine.IndexOf(',');
  if N > 0 then
  begin
    Result.Vorname := ALine.Substring(N + 1);
    Result.Vorname := Result.Vorname.Trim;
    ALine := ALine.Remove(N);
  end;

  { "Nachname" immer vorhanden }
  Result.Nachname := ALine.Trim;
end;

function MyDataToCSV(const AValue: TMyData): string;
var
  lst: TStringList;
begin
  lst := TStringList.Create;
  try
    lst.QuoteChar := '"';
    lst.Delimiter := ';';
    lst.StrictDelimiter := True;

    { Anrede;Titel;Nachname;Vorname;mit }
    lst.Add(AValue.Anrede);
    lst.Add(AValue.Titel);
    lst.Add(AValue.Nachname);
    lst.Add(AValue.Vorname);
    lst.Add(AValue.mit);

    Result := lst.DelimitedText;
  finally
    lst.Free;
  end;
end;

procedure TForm1.TestClick(Sender: TObject);
var
  i: Integer;
  s: string;
  v: TMyData;
begin
  Memo2.Lines.Clear;
  for i := 0 to Memo1.Lines.Count - 1 do
  begin
    s := Memo1.Lines[i];
    { leere Zeilen ignorieren (Textdateien enthalten als letztes Zeichen häufig noch einen Zeilenumbruch) }
    if s.Length > 0 then
    begin
      v := TextToMyData(s);
      s := MyDataToCSV(v);
      Memo2.Lines.Add(s);
    end;
  end;
end;

julchen 22. Jan 2021 19:00

AW: CSV anpassen
 
Hallo,

meine Beispieltexte haben noch eine zweite Hälfte, die für mich bis her nicht das Problem waren, da es fest definierte Zeichen gibt, die ich mit StringReplace gegen ein Semikolon tauschen konnte.
Mit eurem Code laufen die Texte auseinander.

Aus:
Herr Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr Dr. Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr Dr. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr Prof. Dr. Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr Prof. Dr. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)

Wird:
Herr;;Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00;;Uhr)
Herr;;Mustermann;Max mit ABCDEFGHI/00A (1): Terminplan(08:00;Uhr)
Herr;Dr.;Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00;Max mit ABCDEFGHI/00A (1): Terminplan(08:00;Uhr)
Herr;Dr.;Mustermann;Max mit ABCDEFGHI/00A (1): Terminplan(08:00;Uhr)
Herr;Prof. Dr.;Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00;Max mit ABCDEFGHI/00A (1): Terminplan(08:00;Uhr)
Herr;Prof. Dr.;Mustermann;Max mit ABCDEFGHI/00A (1): Terminplan(08:00;Uhr)

Ich habe mit den Codes so ein bisschen rumgespielt und auch versucht, die Variante von Blup an mein Problem anzupassen und zu erweitern, da es die für mich einfachste Variante war, die ich verstehen konnte.

Das Problem ist wohl wirklich, den Vornamen zu fassen :-(

Uwe Raabe 22. Jan 2021 19:37

AW: CSV anpassen
 
Ich denke, mein obiges Codebeispiel kommt mit den Texten ganz gut klar.

EmWieMichael 23. Jan 2021 10:08

AW: CSV anpassen
 
Ohne jemanden entmutigen zu wollen (und ich kenn ja auch die Qualität der zu untersuchenden Daten nicht), aber spätestens wenn Sätze wie

Herr Dr. Mustermann, K. mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr von Mustermann, Klaus W. mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)

auftauchen, wird klar, dass die hier vorgestellten Lösungen nicht funktionieren.

Die Logik zur Ermittlung des Vornamens ist doch relativ simpel:
Ist das aktuelle Wort nicht 'mit' und der Familienname ist bereits identifiziert, dann ist das Wort der Vorname.

Uwe Raabe 23. Jan 2021 11:54

AW: CSV anpassen
 
Zitat:

Zitat von EmWieMichael (Beitrag 1481440)
Ohne jemanden entmutigen zu wollen (und ich kenn ja auch die Qualität der zu untersuchenden Daten nicht), aber spätestens wenn Sätze wie

Herr Dr. Mustermann, K. mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Herr von Mustermann, Klaus W. mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)

auftauchen, wird klar, dass die hier vorgestellten Lösungen nicht funktionieren.

Wenn keine vollständigen Regeln definiert sind, kann man halt nur eine Analyse der verfügbaren Daten vornehmen und passende Regeln daraus ableiten. Sobald dann aber Daten auftauchen, für die diese Regeln nicht gelten, muss man halt nochmal ran. Das ist dann halt nicht zu vermeiden.

Delphi.Narium 23. Jan 2021 15:37

AW: CSV anpassen
 
Just for fun mal ein Pascalscript zum Thema:
Delphi-Quellcode:
program JustForFun;
var
  i        : Integer;
  sl       : TStringList;
  sAnrede  : String;
  sTitel   : String;
  sNachname : String;
  sVorname : String;
  sABCD    : String;
  sTermin  : String;
  iPos     : Integer;
  sTemp    : String;
begin
  sl := TStringList.Create;
  // Statt eine Datei zu lesen
  // sl.LoadFromFile('c:\temp\wie.auch.immer.txt');
  sl.Add('Herr Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Dr. Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Dr. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Prof. Dr. Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Prof. Dr. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Prof. Dr. rer. nat. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Prof. Dr. Dipl.-Ing. Hummel, Johann-Nepomuk mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Frau Dr. Wespe, Natalie mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Frau Dr. med. Müller-Lüdenscheid, Cleopatra mit Julius Cäsar/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr van Gogh, Vincent Willem mit Gustav Klimt/00A (1): Terminplan(08:00 Uhr)');
  sl.Add('Herr Wells, H. G. mit Böll, Heinrich/00A (1): Terminplan(08:00 Uhr)');
  for i := 0 to sl.Count - 1 do begin
    sTemp  := Trim(sl[i]);
    // Falls mal jemand 'ne Leerzeile einschmuggelt:
    if sTemp = '' then continue;
    WriteLn('Quelle: ' + sl[i]); // Ausgabe nur zum Testen
    // Zuerst den Termin holen:
    iPos   := Pos('Terminplan',sTemp);
    sTermin := Copy(sl[i],iPos,Length(sTemp));
    // Den Termin entfernen.
    sTemp  := Copy(sTemp,1,iPos - 3);
    // Position von " mit " ermitteln
    iPos   := Pos(' mit ',sTemp);
    // und alles hinter " mit " holen.
    sABCD  := Copy(sTemp,iPos + 5,Length(sTemp));
    // Alles, einschließlich " mit " entfernen.
    sTemp  := Copy(sTemp,1,iPos - 1);
    // Gibt es ein Komma, dann gibt es auch einen Vornamen.
    iPos    := Pos(', ',sTemp);
    sVorname := '';
    if iPos > 0 then begin
      sVorname := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      sTemp   := Copy(sTemp,1,iPos - 1);
    end;
    // Erstes Leerzeichen suchen, davor steht die Anrede.
    iPos   := Pos(' ',sTemp);
    sAnrede := Copy(sTemp,1,iPos - 1);
    // Anrede entfernen.
    sTemp  := Copy(sTemp,iPos + 1,Length(sTemp));
    // Haben wir 'nen Punkt, so haben wir auch 'nen Titel:
    sTitel := '';
    iPos := Pos('. ',sTemp);
    while iPos > 0 do begin
      sTitel := Format('%s %s',[sTitel,Copy(sTemp,1,iPos)]);
      sTemp := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      iPos  := Pos('. ',sTemp);
    end;
    sTitel   := Trim(sTitel);
    // Der verbliebene Rest entspricht dem Nachnamen:
    sNachname := sTemp;
    sl[i]    := Format('%s;%s;%s;%s;mit %s: %s', [sAnrede, sTitel, sNachname, sVorname, sABCD, sTermin]);
    WriteLn('CSV  : ' + sl[i]); // Ausgabe nur zum Testen
  end;
  // sl.SaveToFile('c:\temp\wie.auch.immer.csv');
  sl.Free;
end.
Die Ausgabe dazu:
Code:
Quelle: Herr Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;;Mustermann;;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;;Mustermann;Max;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Dr. Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;Dr.;Mustermann;;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Dr. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;Dr.;Mustermann;Max;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Prof. Dr. Mustermann mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;Prof. Dr.;Mustermann;;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Prof. Dr. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;Prof. Dr.;Mustermann;Max;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Prof. Dr. rer. nat. Mustermann, Max mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;Prof. Dr. rer. nat.;Mustermann;Max;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Prof. Dr. Dipl.-Ing. Hummel, Johann-Nepomuk mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;Prof. Dr. Dipl.-Ing.;Hummel;Johann-Nepomuk;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Frau Dr. Wespe, Natalie mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
CSV  : Frau;Dr.;Wespe;Natalie;mit ABCDEFGHI/00A (1): Terminplan(08:00 Uhr)
Quelle: Frau Dr. med. Müller-Lüdenscheid, Cleopatra mit Julius Cäsar/00A (1): Terminplan(08:00 Uhr)
CSV  : Frau;Dr. med.;Müller-Lüdenscheid;Cleopatra;mit Julius Cäsar/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr van Gogh, Vincent Willem mit Gustav Klimt/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;;van Gogh;Vincent Willem;mit Gustav Klimt/00A (1): Terminplan(08:00 Uhr)
Quelle: Herr Wells, H. G. mit Böll, Heinrich/00A (1): Terminplan(08:00 Uhr)
CSV  : Herr;;Wells;H. G.;mit Böll, Heinrich/00A (1): Terminplan(08:00 Uhr)

julchen 24. Jan 2021 15:48

AW: CSV anpassen
 
Hallo,

warum funktioniert dein Code nicht?
Was mache ich da falsch?
Code:
// === laden ==============================================
procedure TForm1.Button1Click(Sender: TObject);
var str: TStringlist;
begin
     str := Tstringlist.Create;
     try
     str.LoadFromFile('c:\users\Julia\documents\stringlist.txt');
     Memo1.Lines.AddStrings(str);
     finally
     str.Free;
     end;
end;



// === verarbeitung ==============================================
procedure TForm1.Button2Click(Sender: TObject);
var
  i : Integer;
  sl : TStringList;
  sAnrede : String;
  sTitel : String;
  sNachname : String;
  sVorname : String;
  sABCD : String;
  sTermin : String;
  iPos : Integer;
  sTemp : String;
begin
  sl := TStringList.Create;

  Memo1.Lines.AddStrings(sl);

  for i := 0 to sl.Count - 1 do begin
    sTemp := Trim(sl[i]);
    // Falls mal jemand 'ne Leerzeile einschmuggelt:
    if sTemp = '' then continue;
    WriteLn('Quelle: ' + sl[i]); // Ausgabe nur zum Testen
    // Zuerst den Termin holen:
    iPos := Pos('Terminplan',sTemp);
    sTermin := Copy(sl[i],iPos,Length(sTemp));
    // Den Termin entfernen.
    sTemp := Copy(sTemp,1,iPos - 3);
    // Position von " mit " ermitteln
    iPos := Pos(' mit ',sTemp);
    // und alles hinter " mit " holen.
    sABCD := Copy(sTemp,iPos + 5,Length(sTemp));
    // Alles, einschließlich " mit " entfernen.
    sTemp := Copy(sTemp,1,iPos - 1);
    // Gibt es ein Komma, dann gibt es auch einen Vornamen.
    iPos := Pos(', ',sTemp);
    sVorname := '';
    if iPos > 0 then begin
      sVorname := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      sTemp := Copy(sTemp,1,iPos - 1);
    end;
    // Erstes Leerzeichen suchen, davor steht die Anrede.
    iPos := Pos(' ',sTemp);
    sAnrede := Copy(sTemp,1,iPos - 1);
    // Anrede entfernen.
    sTemp := Copy(sTemp,iPos + 1,Length(sTemp));
    // Haben wir 'nen Punkt, so haben wir auch 'nen Titel:
    sTitel := '';
    iPos := Pos('. ',sTemp);
    while iPos > 0 do begin
      sTitel := Format('%s %s',[sTitel,Copy(sTemp,1,iPos)]);
      sTemp := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      iPos := Pos('. ',sTemp);
    end;
    sTitel := Trim(sTitel);
    // Der verbliebene Rest entspricht dem Nachnamen:
    sNachname := sTemp;
    sl[i] := Format('%s;%s;%s;%s;mit %s: %s', [sAnrede, sTitel, sNachname, sVorname, sABCD, sTermin]);
    WriteLn('CSV : ' + sl[i]); // Ausgabe nur zum Testen
  end;
   sl.SaveToFile('c:\users\Julia\documents\stringlist.txt');

  sl.Free;
end;

// === speichern ==============================================
procedure TForm1.Button3Click(Sender: TObject);
var str: TStringlist;
i: integer;
begin
     str := tstringlist.Create;
     try
     Memo1.Lines.SaveToFile('c:\users\Julia\documents\stringlist.txt');
     finally
     str.Free;
     end;

end;

Delphi.Narium 24. Jan 2021 15:58

AW: CSV anpassen
 
Delphi-Quellcode:
// === verarbeitung ==============================================
procedure TForm1.Button2Click(Sender: TObject);
var
  i : Integer;
  sl : TStringList;
  sAnrede : String;
  sTitel : String;
  sNachname : String;
  sVorname : String;
  sABCD : String;
  sTermin : String;
  iPos : Integer;
  sTemp : String;
begin
  sl := TStringList.Create;
// Was mag hier wohl in sl sein?
// Ziemlich genau nichts.
// In meinem Beispiel waren die Daten per .Add in die Stringliste eingefügt worden.
// Hier müsstest Du sie daher aus dem Memo übernehmen.
// statt
//   Memo1.Lines.AddStrings(sl);
// eher
  sl.AddStrings(Memo1.Lines);
  for i := 0 to sl.Count - 1 do begin
    sTemp := Trim(sl[i]);
    // Falls mal jemand 'ne Leerzeile einschmuggelt:
    if sTemp = '' then continue;
    // WriteLn('Quelle: ' + sl[i]); // Ausgabe nur zum Testen
    // Zuerst den Termin holen:
    iPos := Pos('Terminplan',sTemp);
    sTermin := Copy(sl[i],iPos,Length(sTemp));
    // Den Termin entfernen.
    sTemp := Copy(sTemp,1,iPos - 3);
    // Position von " mit " ermitteln
    iPos := Pos(' mit ',sTemp);
    // und alles hinter " mit " holen.
    sABCD := Copy(sTemp,iPos + 5,Length(sTemp));
    // Alles, einschließlich " mit " entfernen.
    sTemp := Copy(sTemp,1,iPos - 1);
    // Gibt es ein Komma, dann gibt es auch einen Vornamen.
    iPos := Pos(', ',sTemp);
    sVorname := '';
    if iPos > 0 then begin
      sVorname := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      sTemp := Copy(sTemp,1,iPos - 1);
    end;
    // Erstes Leerzeichen suchen, davor steht die Anrede.
    iPos := Pos(' ',sTemp);
    sAnrede := Copy(sTemp,1,iPos - 1);
    // Anrede entfernen.
    sTemp := Copy(sTemp,iPos + 1,Length(sTemp));
    // Haben wir 'nen Punkt, so haben wir auch 'nen Titel:
    sTitel := '';
    iPos := Pos('. ',sTemp);
    while iPos > 0 do begin
      sTitel := Format('%s %s',[sTitel,Copy(sTemp,1,iPos)]);
      sTemp := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      iPos := Pos('. ',sTemp);
    end;
    sTitel := Trim(sTitel);
    // Der verbliebene Rest entspricht dem Nachnamen:
    sNachname := sTemp;
    sl[i] := Format('%s;%s;%s;%s;mit %s: %s', [sAnrede, sTitel, sNachname, sVorname, sABCD, sTermin]);
//  WriteLn('CSV : ' + sl[i]); // Ausgabe nur zum Testen
  end;
  sl.SaveToFile('c:\users\Julia\documents\stringlist.txt');
  sl.Free;
end;

julchen 25. Jan 2021 20:21

AW: CSV anpassen
 
Hallo und guten Abend,

der Code/ die Codes funktionieren.
Und auch noch, wenn ich dran rumgepfuscht habe.
Das ist die gute Nachricht.

Die schlechte Nachricht:
Die Datei, aus der ich die Daten ziehe, enthält irgendwas an versteckten Zeichen.
Da muss ich mal sehen, wo das Problem ist.
Lade ich die Daten aus meiner Liste, bekomme ich als Ergebnis:
;;;;mit : Herr ...

Schreibe ich den Text direkt ins Memo oder in eine saubere Text-Datei, läuft´s.

Bis dahin und vielen, vielen Dank für alle Supporter,

VG, Julia

Delphi.Narium 26. Jan 2021 11:44

AW: CSV anpassen
 
Das müssen nicht unbedingt versteckten Zeichen (o. ä.) sein.
Ein marginal anderer Aufbau der Textdatei gegenüber Deinen Beispielen könnte schon derartige "Nebenfolgen" haben.

Wäre es möglich, dass Du mal eine "Originaldatei" hier anhängst. Ohne konkrete Daten sehe ich momentan keine Chance, dem Problem auf die Spur zu kommen. Vermutlich ist der Inhalt der Datei etwas anders aufgebaut, als von Dir vermutet / erwartet.

Ausgehend von meinem Script: Wenn die Zeichenfolge 'Terminplan' nicht enthalten ist, wäre das ';;;;mit : Herr ...' eine zu erwartende Folge.

Moombas 26. Jan 2021 12:15

AW: CSV anpassen
 
Ich möchte nochmal die Frage aufwerfen @julchen, hast du nicht ggf. die Möglichkeit die Quelle zu ändern, das von vorneherein eine vernünftige CSV bei dir ankommt, mit der du auch arbeiten kannst?

julchen 26. Jan 2021 15:51

AW: CSV anpassen
 
Hallo Narium,

ich habe es hinbekommen:

Code:
procedure TForm1.Button2Click(Sender: TObject);
var
  i : Integer;
  sl : TStringList;
  sAnrede : String;
  sTitel : String;
  sNachname : String;
  sVorname : String;
  sABCD : String;
  sTermin : String;
  iPos : Integer;
  sTemp : String;
 
begin
  sl := TStringList.Create;
  sl.AddStrings(Memo1.Lines);

  try
   for i := 0 to sl.Count - 1 do begin
    sTemp := Trim(sl[i]);
    if sTemp = '' then continue;
    iPos := Pos('mit',sTemp);

    sABCD := Copy(sTemp,iPos + 5,Length(sTemp));
    sTemp := Copy(sTemp,1,iPos - 1);

    iPos := Pos(', ',sTemp);
    sVorname := '';
    if iPos > 0 then begin
      sVorname := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      sTemp := Copy(sTemp,1,iPos - 1);
    end;

    iPos := Pos(' ',sTemp);
    sAnrede := Copy(sTemp,1,iPos - 1);

    sTemp := Copy(sTemp,iPos + 1,Length(sTemp));

    sTitel := '';
    iPos := Pos('. ',sTemp);
    while iPos > 0 do begin
      sTitel := Format('%s %s',[sTitel,Copy(sTemp,1,iPos)]);
      sTemp := Trim(Copy(sTemp,iPos + 1,Length(sTemp)));
      iPos := Pos('. ',sTemp);
    end;
    sTitel := Trim(sTitel);

    sNachname := sTemp;

    sl[i] := Format('%s;%s;%s;%s;mit %s: %s', [sAnrede, sTitel, sNachname, sVorname, sABCD, sTermin]);

  end;

  Memo2.Lines.assign(sl);
  finally
  sl.Free;
  end;
Vielen, vielen Dank an euch alle :love: und bis zum nächsten Problem :pale:

Delphi.Narium 26. Jan 2021 16:26

AW: CSV anpassen
 
Hallo Julchen, bitte ändere Deine Code noch ein bisserl:
Delphi-Quellcode:
//  Statt:
  iPos := Pos('mit',sTemp);
  sABCD := Copy(sTemp,iPos + 5,Length(sTemp));
//  lieber:
  iPos := Pos('mit :',sTemp);
  sABCD := Copy(sTemp,iPos + 5,Length(sTemp));
Ansonsten kannst Du z. B. beim Namen Schmitt oder bei Schmitz auf ein unerwartetes Ergebnis stoßen. Bei denen kommt die Zeichenfolge mit halt schon vor der erwünschten Trennstelle mit : vor. In dem Fall würde das Ergebnis dann deutlich falsch ausfallen.

julchen 26. Jan 2021 17:44

AW: CSV anpassen
 
Danke für den Tipp. :thumb:

An mit im Nachnamen habe ich nicht gedacht.
"mit :" hat es wieder zerrissen, aber mit " mit" läuft bis jetzt. :-D

VG und auf zum nächsten Problem ...

himitsu 26. Jan 2021 17:58

AW: CSV anpassen
 
mittermeier :stupid:

Dann vielleicht mal an RegEx denken (ganzes Wort suchen)


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:47 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz