Jetzt, nach einem halben Jahr, muss ich hier noch mal einen ergänzenden Post los werden.
Ich bin echt geflasht, wie sich die Fähigkeiten von ChatGPT entwickelt haben. Ich möchte das mal an einem Beispiel demonstrieren.
Bin gerade dabei ein Text-Verarbeitungsprogramm, dass ich mal vor 30 Jahren für DOS geschrieben habe, in die moderne Windows-Welt (Cross-Plattform) für FMX zu transformieren. Mal abgesehen, dass mir ChatGPT eine Menge zu dem alten DOS-Kram und Turbo-Pascal helfen konnte (dazu mache ich mal ein eigenes Video), ich nutze ChatGPT seit einiger Zeit recht häufig, als besseren Such-Ersatz für Google. Und das ist echt 1000 mal besser.
Aber hin und wieder lasse ich mir auch mal ein paar Code-Schnipsel erstellen. Ich bin echt beeindruckt, das die KI inzwischen an komplexen Beschreibungen versteht und dann auch einen (immer häufiger) sofort funktionierenden Code zurück liefert.
Bei dem folgenden code hat es auf Anhieb funktioniert:
Meine Frage lautete:
Kontext: Delphi, FMX. Ich habe einen Text ( ein Inhaltsverzeichnis), da steht am Anfang jeder Zeile eine Gliederungsnummer (z.B. "1.1.") und am Ende der Zeile (zuvor ein Leerzeichen) die Seitenzahl. Kannst Du mir eine Routine schreiben, die diesen Text in ein TTreeview einliest und dabei die Gliederungsebene in den entsprechenden Levels abbildet? Der Text sieht so aus:
1. Einleitung ......................... 1
1.1. Ein Wort über dieses Handbuch ...... 2
1.2. System-Voraussetzungen ............. 3
1.3. Die Dateien auf der Originaldiskette 3
1.4. Die Installation des Programmes .... 4
1.5. Start des Programmes ............... 5
2. Die Menüs von SKRIPT ............... 9
2.1. Das Menü "Text" .................... 9
2.1.1. Der Befehl "Holen" ................. 9
2.1.2. Der Befehl "Sichern" ............... 11
2.1.3. Der Befehl "Als ... Sichern" ....... 12
2.1.4. Der Befehl "Neuanlage" ............. 12
2.1.5. Der Befehl "Dateiname" ............. 12
Die Antwort (die Erläuterungen habe ich mal wegelassen):
Delphi-Quellcode:
procedure TextToTreeView(const Text: string; TreeView: TTreeView);
var
Lines: TStringList;
I: Integer;
LastItem: array of TTreeViewItem;
Level, CurLevel: Integer;
Line, Num, S: string;
P: Integer;
begin
Lines := TStringList.Create;
try
Lines.Text := Text;
SetLength(LastItem, 10); // Unterstützt bis zur Gliederungsebene 9.x.x.x.x.x.x.x.x.x
for I := 0 to Lines.Count - 1 do
begin
Line := Lines[I];
P := Pos('.', Line);
if P > 0 then
begin
// Nummer extrahieren
Num := Copy(Line, 1, P-1);
Delete(Line, 1, P);
Level := 1;
while (Length(Line) > 1) and (Line[2] = '.') do
begin
Delete(Line, 1, 2);
Inc(Level);
end;
// Text extrahieren (ohne führende und endende Leerzeichen)
S := Trim(Line);
// Item hinzufügen
if Level = 1 then
begin
LastItem[0] := TTreeViewItem.Create(TreeView);
LastItem[0].Parent := TreeView;
LastItem[0].Text := S;
end
else if Level <= Length(LastItem) then
begin
CurLevel := Level - 1;
LastItem[CurLevel] := TTreeViewItem.Create(LastItem[CurLevel-1]);
LastItem[CurLevel].Parent := LastItem[CurLevel-1];
LastItem[CurLevel].Text := S;
end;
end;
end;
finally
Lines.Free;
end;
end;
Kompiliert im Programm sieht das Ergebnis dann wie in Bild 1 in der Anlage aus.
Nun gefielen mir aber nicht die Punkte und die Seitenzahlen am Ende (sind eher nebensache), aber ich brauch die Seitenzahl auch irgendwo gespeichert, damit ich beim Klick auf einen Eintrag an die entsprechende Stelle im Text springen kann.
Meine Ergänzende Bitte lautete also:
Das funktioniert super! Kannst Du die Funktion noch so abändern, dass der Wert der Seitenzahl in den jeweiligen TTreeviewItems in den Tag-Wert gespeichert wird und die Punkte und die Seitenzahlen aus dem Text entfernt werden?
Die neue Funktion und das Ergebnis im Programm einkompiliert in Bildanlage 2:
Delphi-Quellcode:
procedure TextToTreeView(
const Text:
string; TreeView: TTreeView);
var
Lines: TStringList;
I: Integer;
LastItem:
array of TTreeViewItem;
Level, CurLevel: Integer;
Line, Num, S:
string;
P, PPage: Integer;
PageNum: Integer;
begin
Lines := TStringList.Create;
try
Lines.Text := Text;
SetLength(LastItem, 10);
// Unterstützt bis zur Gliederungsebene 9.x.x.x.x.x.x.x.x.x
for I := 0
to Lines.Count - 1
do
begin
Line := Lines[I];
P := Pos('
.', Line);
if P > 0
then
begin
// Nummer extrahieren
Num := Copy(Line, 1, P-1);
Delete(Line, 1, P);
Level := 1;
while (Length(Line) > 1)
and (Line[2] = '
.')
do
begin
Delete(Line, 1, 2);
Inc(Level);
end;
// Seitenzahl extrahieren
PPage := Length(Line);
while (PPage > 0)
and (Line[PPage] >= '
0')
and (Line[PPage] <= '
9')
do
Dec(PPage);
// Falls eine Seitenzahl gefunden wurde, extrahiere und lösche sie aus Line
if PPage < Length(Line)
then
begin
PageNum := StrToInt(Trim(Copy(Line, PPage+1, MaxInt)));
SetLength(Line, PPage);
// Schneidet den String ab, um die Seitenzahl zu entfernen
end
else
PageNum := -1;
// oder wie Sie nicht zugewiesene Werte darstellen möchten
// Text extrahieren (ohne führende und endende Leerzeichen)
S := Trim(Line);
// Punkte aus dem Text entfernen
S := StringReplace(S, '
.', '
', [rfReplaceAll]);
// Item hinzufügen
if Level = 1
then
begin
LastItem[0] := TTreeViewItem.Create(TreeView);
LastItem[0].Parent := TreeView;
LastItem[0].Text := S;
LastItem[0].Tag := PageNum;
end
else if Level <= Length(LastItem)
then
begin
CurLevel := Level - 1;
LastItem[CurLevel] := TTreeViewItem.Create(LastItem[CurLevel-1]);
LastItem[CurLevel].Parent := LastItem[CurLevel-1];
LastItem[CurLevel].Text := S;
LastItem[CurLevel].Tag := PageNum;
end;
end;
end;
finally
Lines.Free;
end;
end;
Bei dieser Variante fehlten aber die Punkte am Anfang und hier wurden teilweise - unpassender Weise - Zahlen wieder gegeben.
Auch mit zwei weiteren Nachfragen hat ChatGPT das aber nicht hinbekommen, so dass ich es selber angepasst habe (siehe Erläuternungen mit // HS
:
Delphi-Quellcode:
procedure TextToTreeView(
const Text:
string; TreeView: TTreeView);
var
Lines: TStringList;
I: Integer;
LastItem:
array of TTreeViewItem;
Level, CurLevel: Integer;
Line, Num, S:
string;
P, PPage: Integer;
PageNum: Integer;
begin
Lines := TStringList.Create;
try
Lines.Text := Text;
SetLength(LastItem, 10);
// Unterstützt bis zur Gliederungsebene 9.x.x.x.x.x.x.x.x.x
for I := 0
to Lines.Count - 1
do
begin
Line := Lines[I];
P := Pos('
.', Line);
if P > 0
then
begin
// Nummer extrahieren
var oldLine:= Line;
// HS: Punkte werden noch gebraucht, also merken
Num := Copy(Line, 1, P-1);
Delete(Line, 1, P);
Level := 1;
while (Length(Line) > 1)
and (Line[2] = '
.')
do
begin
Delete(Line, 1, 2);
Inc(Level);
end;
Line := OldLine;
// HS: Die alte Line wiederherstellen
// Seitenzahl extrahieren
PPage := Length(Line);
while (PPage > 0)
and (Line[PPage] >= '
0')
and (Line[PPage] <= '
9')
do
Dec(PPage);
// Falls eine Seitenzahl gefunden wurde, extrahiere und lösche sie aus Line
if PPage < Length(Line)
then
begin
PageNum := StrToInt(Trim(Copy(Line, PPage+1, MaxInt)));
SetLength(Line, PPage);
// Schneidet den String ab, um die Seitenzahl zu entfernen
end
else
PageNum := -1;
// oder wie Sie nicht zugewiesene Werte darstellen möchten
// Text extrahieren (ohne führende und endende Leerzeichen)
S := Trim(Line);
// Punkte aus dem Text entfernen
var ALeftPart := Copy (S, 1, Pos ('
', S)-1);
// HS: Punkte vorne lassen
var ARightPart := '
' + Trim (Copy (S, Length (AleftPart)+1, Length (s)));
// HS: Rechter Teil
//S := StringReplace(S, '.', '', [rfReplaceAll]); // HS: Nicht alle Punkte entfernen
ARightPart := StringReplace(ARightPart, '
.', '
', [rfReplaceAll]);
// HS: Sondern nur im rechten Teile
s := ALeftPart + ARightPart;
// HS
// Item hinzufügen
if Level = 1
then
begin
LastItem[0] := TTreeViewItem.Create(TreeView);
LastItem[0].Parent := TreeView;
LastItem[0].Text := S;
LastItem[0].Tag := PageNum;
end
else if Level <= Length(LastItem)
then
begin
CurLevel := Level - 1;
LastItem[CurLevel] := TTreeViewItem.Create(LastItem[CurLevel-1]);
LastItem[CurLevel].Parent := LastItem[CurLevel-1];
LastItem[CurLevel].Text := S;
LastItem[CurLevel].Tag := PageNum;
end;
end;
end;
finally
Lines.Free;
end;
end;
Somit sieht es dann wie im dritten Bild dargestellt aus.
Also auch wenn der Code es nicht 100 Prozentig war, es hat mir eine Menge Zeit eingespart, die kleine Anpassung meinerseits hat nur 10 Minuten gedauert.
Also ich bin echt beindruckt....