Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi StringGrid mit Daten füllen und farblich Darstellen (https://www.delphipraxis.net/128425-stringgrid-mit-daten-fuellen-und-farblich-darstellen.html)

Jens Hartmann 29. Jan 2009 16:14


StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo mal wieder zusammen,

Habe folgendes Problem, ich habe ein Memo, in dem folgende Daten zu sehen sind.


100 Ereignis
Alarm MG 100 EIN
Einbruch Bewegungsmelder Tür 1

101 Ereignis
Alarm MG 100 AUS
Einbruch Bewegungsmelder Tür 1

102 Ereignis
Löschen EMG EIN
Löschen durchgeführt


Jetzt meine Frage, gibt es eine einfache Möglichkeit, diese Daten in ein StringGrid zu implementieren.

Und zwar in etwa so wie im Anhang.

Da die Daten über einen Tag lang gesehen unterschiedliche Mengen aufweisen können, muss das StringGrid automatisch immer Größer werden.

Am Ende eines Tages würde ich das StringGrid gerne als z.B. Excel-File oder ähnlich speichern, und das String Grid leeren und neu befüllen.

MFG

Jens

mkinzler 29. Jan 2009 16:16

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Ja, du müsstest dann das Zeichen des Grids selber übernehmen (OwnerDraw)

Jens Hartmann 29. Jan 2009 16:30

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Also, ich könnte mir verstellen, das ich den Text in meinem Memo oder direkt von der Schnittstelle (COM1) auf Textinhalt prüfe. Dann den Text auswerten und dem Grid zuweise. Meine Frage ist halt, wie kann ich dem Grid den look von meiner gezeigten Datei geben und dem Grid sagen wann es wie und wo welche Daten eintragen soll.


Jens

mkinzler 29. Jan 2009 17:17

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Ein Grid kann das von haus aus nicht, deshalb ist ja OwnerDraw ( .onDrawCell()) nötig)

Willie1 29. Jan 2009 17:22

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo Jens,
du musst das Ereignis OnDrawCell benutzen, da kannst du das Aussehen jeder Zelle selbst zeichnen.

Willie

Jens Hartmann 29. Jan 2009 19:51

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Zitat:

Ein Grid kann das von haus aus nicht, deshalb ist ja OwnerDraw ( .onDrawCell()) nötig)
Macht das denn dann überhaupt Sinn mit einem Grid zu arbeiten. Oder Wäre es sinnvoll die Daten anders zu verarbeiten.

Mein Problem besteht ja auch darin, wie bekomme ich den die ständig neu kommenden Daten immer wieder in das Grid aber halt

Datensatz 1 zerlegen in Spalte 1,2 und 3
und dann weiter mit neuem Datensatz.
Nächste Zeile Grid und wieder Spalte 1,2,und 3

Ich denke das ich also mit ColCount und RowCount da weiter käme.

MFG

Jens

mkinzler 29. Jan 2009 19:56

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Wo kommen die Daten her?

Jens Hartmann 29. Jan 2009 22:04

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Die Daten lese ich von einer seriellen Schnittstelle ein.

Meine Frage zum einlesen!!

Ich habe mich ein bißchen durch´s Netzt gelesen und durch die Delphi Hilfe.

Ich muss halt dazu sagen, das ich mich mit dem Grid noch gar nicht auskennen und es schon sehr kompakt finde.

Was ich allerdings mittlerweile weiß,


Ich muss mir eine Schleife bauen, die die Daten ständig einlesen tut und in eine Zelle im Grid einfügt. Anschließend muss ich die Zelle auf der der Focus sitzt hochzählen und weiter eintragen lassen.

Nach fühlen der gesamten Zeile müsste ich über den Text entscheiden ob die Zeile ROT GELB oder WEIß wird, die Zeile einfärben und in die nächste Zeile den Focus setzen.

Ist das soweit der Richtige Weg?

MFG

Jens

mkinzler 29. Jan 2009 22:06

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Man könnte auch über den Einsatz einer Datenbank nachdenken

Jens Hartmann 29. Jan 2009 22:14

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Habe ich auch schon gemacht, ich weiß nur nicht so richtig, wie ich das Problem jetzt angehe.


Das Problem ist, das ich das Programm für meine Firma geschrieben habe um unseren Kunden die Möglichkeit zu geben, die Ereignisse der Einbruch- oder Brandmeldeanlage ständig mitzuschreiben und Zukunftssicher festzuhalten.

Der Kunden soll mit dem Programm nicht viel arbeiten müssen, sondern nur im Fall z.B. Einbruch eine Möglichkeit haben,diese Daten komfortable einzusehen.

Er soll auf den ersten Blick z.B. den Alarm erkennen. (ROTE Zeile) oder STÖRUNG (GELBE ZEILE) etc.
Mit der Datenbank wäre eine super Lösung (also z.B. DBGrid denke ich), allerdings müsste ich dem User, dann auch eine Useroberfläche bereitstellen dieses auszuführen.

Anders hatte ich halt an Excel gedacht.

Ich denke allerdings mittlerweile anders. Datenbank wäre natürlich warscheinlich besser.

MFG


Jens

Jens Hartmann 30. Jan 2009 21:50

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo nochmal zusammen,

So ich habe jetzt den ganzen Nachmittag mich mit dem StringGrid auseinnander gesetzt und habe jetzt schon so ein paar Sachen rausgefunden, wie ich es mit Daten füllen kann.

Leider bekomme ich diese Funktion nicht in mein Programm integriert.

Mit folgender Funktion fülle ich momentan mein Memo und eine Textdatei als Datensicherung:

Delphi-Quellcode:
procedure TForm1.DatenverarbeitungMB256;
Var
  Datum             :String;
  Jahr              :String;
  Monat             :String;
  Sicherung         :String;
  SL                :TStringList;
  I                 :Integer;
begin
  Datum := DatetoStr(Date);
  Jahr := FormatDateTime('yyyy',strtodatetime(Datum));
  Monat := FormatDateTime('mmmm',strtodatetime(Datum));
  CreateDir('..\Daten\');
  CreateDir('..\Daten\'+Jahr);
  CreateDir('..\Daten\'+Jahr+'\'+Monat);

  sl := TStringList.Create;

  try
    MMUEZ2000.Lines.Add(Zeile);
    sl.AddStrings(MMUEZ2000.Lines);

    for i := 0 to sl.Count -1 do
    begin
      sl[i] := trim(StringReplace(sl[i], #$D, '', [rfReplaceAll]));
      sl[i] := StringReplace(sl[i], #129, 'ü', [rfReplaceAll]);
      sl[i] := trim(StringReplace(sl[i], #132, 'ä', [rfReplaceAll]));
      sl[i] := StringReplace(sl[i], #142, 'Ä', [rfReplaceAll]);
      sl[i] := StringReplace(sl[i], #148, 'ö', [rfReplaceAll]);
      sl[i] := StringReplace(sl[i], #153, 'Ö', [rfReplaceAll]);
      sl[i] := StringReplace(sl[i], #154, 'Ü', [rfReplaceAll]);

      sl[i] := StringReplace(sl[i], #10#13, ' ', [rfReplaceAll]);

      if sl[i] <> ''
       then
       Zeile:='';
       Memo.Lines.Append(SL[I]);
       Speichermemo.Lines.Append(SL[I]);
       MMUEZ2000.Clear;
    end;

  finally
    sl.Free;
  end;
  Zeile:='';
  Sicherung := ('..\Daten\'+Jahr+'\'+Monat+'\'+Datum+'.txt');
  Speichermemo.Lines.SaveToFile(Sicherung);
  Label1.Caption := Sicherung;
end;
Um einer Frage vorzubeugen, ich weiß das das Speicherziel so momentan noch nicht in Ordnung ist (Schreibrechte etc.) Ist nur hier auf meinem Testsystem so.

Der Text in meinem Memo wird Zeilenweise über eine COM-Schnittstelle eingelesen.

Mein Grid habe ich jetzt so wie im Anhang zusammengestellt und die Daten sollen wie in dem Bild gezeigt eingefügt werden.

Wie kann ich den das jetzt alles angehen.

MFG

Jens

Jens Hartmann 31. Jan 2009 08:02

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
so, habe heute Nacht noch ein bißchen probiert und gespielt, und habe es zumindestens schon mal geschaft, die Daten ins Grid zu übernehmen.

Allerdings so wie im Anhang (Chaos).

Delphi-Quellcode:
Zelle := Zelle+1;
    for i := 0 to sl.Count -1 do
      begin
        sl[i] := trim(StringReplace(sl[i], #$D, '', [rfReplaceAll]));
        sl[i] := StringReplace(sl[i], #129, 'ü', [rfReplaceAll]);
        sl[i] := trim(StringReplace(sl[i], #132, 'ä', [rfReplaceAll]));
        sl[i] := StringReplace(sl[i], #142, 'Ä', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #148, 'ö', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #153, 'Ö', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #154, 'Ü', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #10#13, ' ', [rfReplaceAll]);
      if sl[i] <> '' then
          Zeile:='';
          Memo.Lines.Append(SL[I]);
          Speichermemo.Lines.Append(SL[I]);
          for IA := 0 to sl.Count -1 do
            begin
              sl[IA] := StringReplace(sl[IA], 'Ereignis', '', [rfReplaceAll]);
              sl[IA] := StringReplace(sl[IA], ':', '', [rfReplaceAll]);
              AppendStr(Ereignisnummer,(SL[IA]));
              Label7.Caption := Ereignisnummer;
              SGMBSerie.Cells[Zelle,Spalte] := Label7.Caption;
            end;
          MMUEZ2000.Clear;
      end;
    sl.Free;
    Finally;
        if Zelle >=6 then
        begin
        Spalte := Spalte+1;
        Zelle := 0;
        end;
MFG

Jens

jaenicke 1. Feb 2009 00:09

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe wie angekündigt mich eben noch kurz drangesetzt, das Projekt liegt im Anhang. Ich habe das jetzt einfach nur schnell heruntergeschrieben und nicht besonders optimiert oder elegant geschrieben, funktionieren tut es aber. ;-)

Der Quelltext sieht so aus, ich denke der sollte auch ohne Kommentare verständlich sein:
Delphi-Quellcode:
type
  TMyDataEntry = record
    Index: Integer;
    DateString, IdString, Line1, Line2: String;
  end;

  TMySimpleParser = class
  private
    Data: String;
    DataPointer: Integer;
    function OemToAnsi(const OemStr: string): string;
    procedure SkipSpaces;
    procedure SkipTrash;
    function GetTextLength(UpToLineEnd: Boolean): Integer;
  public
    Entries: array of TMyDataEntry;
    procedure Parse(Text: String);
  end;
Delphi-Quellcode:
{ TMySimpleParser }

function TMySimpleParser.OemToAnsi(const OemStr: string): string;
begin
  SetLength(Result, Length(OemStr));
  if Length(Result) > 0 then
    OemToCharBuff(PChar(OemStr), PChar(Result), Length(Result));
end;

procedure TMySimpleParser.SkipSpaces;
begin
  while (DataPointer < Length(Data)) and (Data[DataPointer] = ' ') do
    Inc(DataPointer);
end;

procedure TMySimpleParser.SkipTrash;
begin
  while (DataPointer < Length(Data)) and (Data[DataPointer] in [#13, #10, #32]) do
    Inc(DataPointer);
end;

function TMySimpleParser.GetTextLength(UpToLineEnd: Boolean): Integer;

  function IsTerminatingChar(CharIndex: Integer): Boolean;
  begin
    if UpToLineEnd then
      Result := Data[CharIndex] in [#13, #10]
    else
      Result := Data[CharIndex] in [#13, #10, #32];
  end;

var
  CurPointer: Integer;
begin
  Result := -1;
  CurPointer := DataPointer;
  while Result < 0 do
  begin
    while (CurPointer < Length(Data)) and not IsTerminatingChar(CurPointer) do
      Inc(CurPointer);
    if (CurPointer + 1 < Length(Data)) and not IsTerminatingChar(CurPointer + 1) then
      Inc(CurPointer)
    else
      Result := CurPointer - DataPointer;
    if CurPointer = Length(Data) then
      Result := CurPointer - DataPointer + 1;
  end;
end;

procedure TMySimpleParser.Parse(Text: String);
var
  CurEntry: ^TMyDataEntry;
  TextLen: Integer;
begin
  Data := Text;
  DataPointer := 1;
  SetLength(Entries, 0);
  SkipTrash;
  while DataPointer < Length(Data) do
  begin
    SetLength(Entries, Length(Entries) + 1);
    CurEntry := @Entries[High(Entries)];

    TextLen := GetTextLength(False);
    CurEntry.Index := StrToInt(Copy(Data, DataPointer, TextLen));
    DataPointer := DataPointer + TextLen;
    SkipSpaces;

    TextLen := GetTextLength(False);
    CurEntry.DateString := Copy(Data, DataPointer, TextLen);
    DataPointer := DataPointer + TextLen;
    SkipSpaces;

    if Data[DataPointer] <> #13 then
    begin
      TextLen := GetTextLength(False);
      CurEntry.IdString := Copy(Data, DataPointer, TextLen);
      DataPointer := DataPointer + TextLen;
    end;
    SkipTrash;

    TextLen := GetTextLength(True);
    CurEntry.Line1 := Copy(Data, DataPointer, TextLen);
    DataPointer := DataPointer + TextLen;
    SkipTrash;

    TextLen := GetTextLength(True);
    CurEntry.Line2 := OemToAnsi(Copy(Data, DataPointer, TextLen));
    DataPointer := DataPointer + TextLen;
    SkipTrash;
  end;
end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Parser: TMySimpleParser;
  FileStream: TFileStream;
  FileContents: TStringStream;
  i: Integer;
begin
  FileStream := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'test.txt', fmOpenRead);
  FileContents := TStringStream.Create('');
  FileContents.CopyFrom(FileStream, FileStream.Size);
  FileStream.Free;
  Parser := TMySimpleParser.Create;
  Parser.Parse(FileContents.DataString);
  FileContents.Free;
  StringGrid1.RowCount := Length(Parser.Entries);
  for i := 0 to High(Parser.Entries) do
  begin
    StringGrid1.Cells[0, i + 1] := IntToStr(Parser.Entries[i].Index);
    StringGrid1.Cells[1, i + 1] := Parser.Entries[i].DateString;
    StringGrid1.Cells[2, i + 1] := Parser.Entries[i].IdString;
    StringGrid1.Cells[3, i + 1] := Parser.Entries[i].Line1;
    StringGrid1.Cells[4, i + 1] := Parser.Entries[i].Line2;
  end;
  Parser.Free;
end;

Jens Hartmann 2. Feb 2009 19:48

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo zusammen, also das Beispiel ist echt super und Funktioniert auch wunderbar. Leider muss ich zu meiner Schande gestehen, das ich es echt nicht verstehe.

MFG

Jens

jaenicke 2. Feb 2009 20:52

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Ist dir denn klar, was ich grundsätzlich mache?
Ich lese den Text in ein dynamisches Array ein. Jeweils ein Datensatz wird in einem Record TMyDataEntry gespeichert.

Mein Vorgehen: Ich verändere den String nicht, lösche also bereits bearbeitete Bereiche nicht, sondern gehe zeichenweise durch den Text. Wo ich im Text Data gerade bin speichere ich in DataPointer.

So, jetzt zur Analyse selbst:
Teilweise gehen die einzelnen Teile des Datensatzes bis zum Zeilenende, teilweise bis zum nächsten Leerzeichen. GetTextLength gibt das nächste Leerzeichen oder explizit das nächste Zeilenumbruchzeichen (wenn UpToLineEnd True ist) zurück.

Mit Hilfe dieser Funktion weiß ich also die Länge des nächsten Teils des aktuellen Datensatzes. Den kopiere ich aus dem String, danach setze ich die Position dahinter (bis dahin bin ich ja fertig), und überspringe danach alle Leerzeichen (SkipSpaces) oder auch Leerzeichen und Zeilenumbruchszeichen (SkipTrash).
Dann bin ich jeweils beim nächsten Bestandteil des Datensatzes.

Am Ende sorge ich mit SkipTrash dafür, dass ich direkt vor dem nächsten Datensatz stehe, also alle folgenden Zeilenumbruchszeichen und Leerzeichen übersprungen habe (oder am Ende des Textes). Das mache ich bis ich am Ende des Textes angekommen bin.

Danach kann ich das Array Entries auslesen, in dem die Datensätze gespeichert sind.

Jens Hartmann 2. Feb 2009 21:30

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also ich will es mal so erklären, Verstanden habe ich schon, was Du da gemacht hast und wie das ganze so ungefähr ablaufen könnte. Das Problem ist nur, ich habe das ganz dann mal mit einer anderen Datei versucht anzupassen und da komme ich einfach nicht mit klar.

Ich bekomme schon dirrekt beim Compilieren die Meldung, das "Ereignis" kein Integer Wert ist. Das ist auch logisch, weil er wenn ich deinen weg verstanden habe nach der Ereignisnummer sucht, die bei dem Datensatz den du genutz hast am Anfang einer Zeile steht:

Deine genutzt Datei:


102 01.02.00 21:05 ID: 2
Codebetrieb EIN
Codebetrieb


Andere Datei


Ereignis: 0840
Datum: 25.11.2008, Uhrzeit: 17:45:56
Schalteinrichtung: 001 GESCHLOSSEN
Hauptbereich: 001, Unterbereich: 000


Die Datei die Du genommen hast, hast du vermutlich aus einem anderen Tread von mir.

Das Problem ist allerdings, das die Datensätze von Zentraletyp zu Zentralentyp unterschiedlich sind.

Ich hänge dir mal eine Übungsprojekt von mir an, wo ich mich schon selber (vor unserem ersten Kontakt)mit dem Problem beschäftigt habe.

In dem Zuge, kannst du ja auch mal sagen was Du von dem Übungsprojekt so hälst, da ich eigendlich selber Anfänger bin, habe ich in den letzten Tage mal angefangen Problem von mir in einem Übungsprojekt zu beschreiben und würde Sie gerne Später als Beitrag der Nachwelt zur Verfügung stellen. (Als Anfänger Übungstool).

so jetzt wieder zum wichtigen Thema.

Also wie Du sehen wirst unter Textdateien einlesen, gibt es ein SGTextdatei in dem ich michh versucht habe.

Im Anhang dabei ist auch mal ein andere Datensatz.

Achso, Die Daten lese ich Übrigens über eine COM-Schnittstelle ein. Jetzt ist für mich allein die Frage, Speicher ich die Daten dann erst in eine Textdate zwischen und bearbeite Sie oder bearbeiter ich Sie direkt und füge Sie ins Grid ein.

Danke Übrigens nochmal für deine Mühe.

MFG

Jens

jaenicke 4. Feb 2009 16:54

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Dort könntest du ähnlich vorgehen. Je nachdem ob da auch Leerzeichen / Zeilenumbruchszeichen drin stehen. Bis zum ersten : gehen, schauen ob da Ereignis steht. Bis zum Zeilenende lesen. Wieder bis zum : lesen, usw.

Du könntest das natürlich auch ohne Prüfung machen und einfach immer zeilenweise in einer TStringList vorgehen. In deiner neuen Testdatei sind ja keine weiteren Leer- oder Steuerzeichen drin.
Den Text könntest du entweder direkt beim Empfang auswerten oder in einem String speichern und komplett in StringList.Text legen um die einzelnen Zeilen zu analysieren.

// EDIT:
Ach ja: Und wegen den verschiedenen Datenformaten könntest du jeweils eine Leseklasse mit einer gemeinsamen Hauptklasse schreiben, die du dann entsprechend benutzen kannst.

Jens Hartmann 4. Feb 2009 20:53

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo Sebastian,

das ist ja genau mein Problem, was ich nicht verstehe, wie genau mache ich das mit dem suchen z.B. nach : oder soo und sage dann ließ davor oder ließ so lange.

Also ich habe echt verstanden wie du das machst. Mein großes Problem, ist allerdings mein bescheidens Englisch und daher, versteh ich halt nicht genau wo du in den Funktion was und wie genau machst.

Ich habe jetzt noch lange mit POS, POSEX, SEEK und StringReplaced gespielt, ich komme aber leider zu keinem Erfolgsbringenden Ergebnis.

MFG

Jens

jaenicke 9. Feb 2009 18:51

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ok, ich habe das Beispiel mal kurz umgeschrieben, es liegt im Anhang. Ich habe jetzt je eine Klasse für die beiden Formate erstellt, beide abgeleitet von einer Basisklasse. So kannst du möglichst viel wiederverwenden.

Ich hab das noch ein wenig mehr modularisiert, vielleicht hilft das beim Verständnis. Ohne konkrete Fragen weiß ich nicht so recht was ich erklären muss und was klar ist. Denn eigentlich sollte auch der Debugger beim Verständnis helfen. ;-)

Jens Hartmann 9. Feb 2009 19:42

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Alles klar, werde das später noch durcharbeiten und mich dann heute oder morgen mal mit konkreten Fragen melden.

Ich hoffe das ist OK

MFG

Jens

jaenicke 9. Feb 2009 20:11

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Ja natürlich, und konkrete Fragen zu beantworten ist auch kein Problem.

Das ganze ließe sich jedenfalls noch beliebig erweitern, je nachdem was du genau mit den Daten vor hast und wie unterschiedlich die Daten sind. Denn auch die Daten selbst könnte man natürlich in Klassen speichern, damit da auch mehr Variationen möglich sind. ;-)

Jens Hartmann 10. Feb 2009 18:40

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Sebastian,

so jetzt habe ich ein paar Fragen.

Ich habe mir dein Projekt jetzt nochmal angesehen und auch den DEBUGGER durchlaufen lassen.

Dann habe ich die Unit in mein Projekt implementiert und die Funktionen in meine LeseFunktion der Schnittstelle mit eingebunden.

Dabei kommt es leider noch (aber logischer weiße) zu einem Fehler (Fehler beim Parsen)

Die Erklärung liegt darin, das nach dem Begriff Ereignis gesucht wird.

Delphi-Quellcode:
    CurLine := ReadLine;
    if Pos('Ereignis:', CurLine) <> 1 then
      raise Exception.Create('Fehler beim Parsen in Zeile:'#13#10 + CurLine
        + #13#10#13#10'Ereignis: erwartet!');
    Delete(CurLine, 1, 10);
    CurEntry.Index := StrToInt(CurLine);
Also den Ablauf hier habe ich (so hoffe ich) verstanden, der Var CurLine (vom Typ String) wird eine gelesen Zeile zugewiesen, mit POS wird ja jetzt gesucht ob Ereignis wirklich an Pos. 1 ist, ist das nicht der Fall, bekomme ich den Fehler "Fehler beim Parsen".
Da meine Daten je nach Zeitpunkt Programmstart anders sind, ist das wahrscheinlich mein Verständnisproblem.

Ich hänge unten mal noch eine Datei an, die ich eben Aufgezeichnet habe.

Ich denke ich muss nach der Position von "Ereignis: 0000" suchen (0000 ist nur ein Beispiel, der Ausdruck könnte natürlich auch mit 0814 anfangen, da diese Nummer ja von der Einbruchmeldanlage mit gesendet wird und in dieser nur ein kleiner Puffer ist der Überschrieben wird, wenn die Daten nicht ausgedruckt wurden.)
und dann diese auf 1 setzten oder so ähnlich.

Das Problem, dabei ist nämlich leider auch, das das Wort Ereignis an einem anderen Punkt auch auftauchen kann. (Liegt daran, das ich in der Einbruchmeldeanlage Ereignistexte selber nach belieben einrichten kann).

PS: In der Datei im Anhang, sieht man wie so ein Anfang auch schon mal aussehen kann,
Die Meldung AKTUELLE EREIGNISSE DRUCKEN, kommt nur wenn der Drucker nicht angeschlossen war und Daten im Puffer der Einbruchmeldeanlage liegen,

Und das Ereignis (nur beim ersten Ereignis) mit einem A anfängt, muss auch an der Einbruchmeldeanlage liegen, da das auch nur am Anfang einmal ist, aber auch auf dem Original Papierdrucker so ausgedruckt wird.

Daher gesehen, denke ich halt das ich nach dem ersten richtigen Ereigniss suchen muss.

Jens

Jens Hartmann 10. Feb 2009 19:37

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo Sebastian,

lass mal mit den Bemühungen, ich hab´s geknackt und ich glaube auch verstanden, ich werde jetzt erstmal noch ein wenig basteln.

Ich habe einfach die if Anweisungen angepasst und sie her es funktioniert soweit.

Habe nur leider den Teil der ParserUtilis noch nicht komplett geraft.
Aber ich denke das schaff ich auch noch.


Melde mich bestimmt nochmal.

Danke schon mal

Jens

Jens Hartmann 11. Feb 2009 15:11

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo Sebastian,

habe jetzt auch den Teil von ParserUtils so weit verstanden.
Jetzt habe ich mal eine Frage, ich habe ja deine Klasse ParserUtils in mein Programm eingebunden.

In der Projektverwaltung ist die jetzt seltsamerweise so eingetragen

P
Pa
Par
Pars
Parse
Parser
...
...
...
ParserUtils.pas

Woran kann das liegen?

MFG

Jens

Jens Hartmann 11. Feb 2009 16:32

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo nochmal,

So nachdem ich jetzt nochmal lang überlegt und probiert habe, habe ich nochmal ein paar Fragen.

Ich lese für das Parsen ja aus einer Textdatei, diese Datei wird ja im laufe eines Tages immer Größer.

Kann ich es irgendwie realisiern, das immer nur das gelesen wird, was wirklich von der Schnittstelle kommt und wenn wie bekomme ich das dann Parsen frei.

Mit folgendem Code arbeite ich jetzt.

Delphi-Quellcode:
procedure TForm1.DatenverarbeitungMB256;
Var
  Datum             :String;
  Jahr              :String;
  Monat             :String;
  Sicherung         :String;
  SL                :TStringList;
  I                 :Integer;
  IA                :Integer;
  IB                :Integer;
  IC                :Integer;
  ID                :Integer;
  N                 :Integer;
  Parser: TMySimpleBaseParser;
begin
  Datum := DatetoStr(Date);
  Jahr := FormatDateTime('yyyy',strtodatetime(Datum));
  Monat := FormatDateTime('mmmm',strtodatetime(Datum));
  CreateDir('..\Daten\');
  CreateDir('..\Daten\'+Jahr);
  CreateDir('..\Daten\'+Jahr+'\'+Monat);

  sl := TStringList.Create;

  try
    MMUEZ2000.Lines.Add(Zeile);
    sl.AddStrings(MMUEZ2000.Lines);
    for i := 0 to sl.Count -1 do
      begin
        sl[i] := trim(StringReplace(sl[i], #$D, '', [rfReplaceAll]));
        sl[i] := StringReplace(sl[i], #129, 'ü', [rfReplaceAll]);
        sl[i] := trim(StringReplace(sl[i], #132, 'ä', [rfReplaceAll]));
        sl[i] := StringReplace(sl[i], #142, 'Ä', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #148, 'ö', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #153, 'Ö', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #154, 'Ü', [rfReplaceAll]);
        sl[i] := StringReplace(sl[i], #10#13, ' ', [rfReplaceAll]);
      if sl[i] <> '' then
          Zeile:='';
          Parser := TMySimpleParserMB256plus.Create;
          DoParse(Parser, ExtractFilePath(ParamStr(0)) + '..\Daten\'+Jahr+'\'+Monat+'\'+Datum+'.txt');
          DisplayResult(Parser);
          Parser.Free;
          Memo.Lines.Append(SL[I]);
          Speichermemo.Lines.Append(SL[I]);
      end;
      MMUEZ2000.Clear;
    sl.Free;
  finally

  end;
  Zeile:='';
  Sicherung := ('..\Daten\'+Jahr+'\'+Monat+'\'+Datum+'.txt');
  Speichermemo.Lines.SaveToFile(Sicherung);
  Label1.Caption := Sicherung;
end;
Außerdem habe ich noch folgendes Problem, im Anhang habe ich die mal einen großen Ereignissppeicher eingefügt, und ein paar Bilder wie das Ergebnis aussehen sollte.

Man kann an Hand der Datei erkennen, Das teilweise eine Zeile sehr lang ist, und zwar solang, das ich sie nicht in ein Feld von meinem Grid bekomme.

Wie kann ich in meinem Grid dem Feld dann sagen Zeilenumbruch ?

Gruß

Jens

jaenicke 11. Feb 2009 18:39

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Zitat:

Zitat von Jens Hartmann
In der Projektverwaltung ist die jetzt seltsamerweise so eingetragen

Hast du davon vielleicht mal einen Screenshot, ich weiß nicht wie du das meinst. :gruebel:
Meinst du das so als Unterordner?

Zitat:

Zitat von Jens Hartmann
Kann ich es irgendwie realisiern, das immer nur das gelesen wird, was wirklich von der Schnittstelle kommt und wenn wie bekomme ich das dann Parsen frei.

Ich habe das absichtlich so gemacht, dass Text und kein Dateiname zum Parsen übergeben wird. Der Text kann natürlich auch nur ein gerade übertragener Teil sein.

Du müsstest nur irgendwie sicherstellen, dass keine halben Einträge drin stehen, aber ansonsten kannst du auch einfach nur einen gerade empfangenen Text als String übergeben.

Zitat:

Zitat von Jens Hartmann
Delphi-Quellcode:
        sl[i] := trim(StringReplace(sl[i], #$D, '', [rfReplaceAll]));
        sl[i] := StringReplace(sl[i], #129, 'ü', [rfReplaceAll]);
        sl[i] := trim(StringReplace(sl[i], #132, 'ä', [rfReplaceAll]));
...

Das kannst du dir sparen. ;-)
In meinem Quelltext gibt es u.a. die Funktion OemToAnsi, die (hoffe ich ;-)) genau diese Umwandlung in einem Schritt macht. Die könntest du als class function deklarieren und dann einfach mit TMySimpleParser.OemToAnsi() aufrufen.

Zitat:

Zitat von Jens Hartmann
Delphi-Quellcode:
          Parser := TMySimpleParserMB256plus.Create;
          DoParse(Parser, ExtractFilePath(ParamStr(0)) + '..\Daten\'+Jahr+'\'+Monat+'\'+Datum+'.txt');
          DisplayResult(Parser);
          Parser.Free;

Du musst den Parser nicht jedesmal neu erzeugen, wenn das jedesmal der selbe Parsertyp ist, dann kannst du den vor der Schleife erzeugen und danach wieder freigeben.
Die bisherigen Einträge werden in Parse ohnehin gelöscht:
Zitat:

Delphi-Quellcode:
SetLength(Entries, 0);

Zitat:

Zitat von Jens Hartmann
Man kann an Hand der Datei erkennen, Das teilweise eine Zeile sehr lang ist, und zwar solang, das ich sie nicht in ein Feld von meinem Grid bekomme.

Wie kann ich in meinem Grid dem Feld dann sagen Zeilenumbruch ?

Das gibt es nicht vorgefertigt. In dem Screenshot wird aber auch kein StringGrid verwendet, es handelt sich dort um eine TListView bzw. eine TVirtualStringTree. Letztere wäre vermutlich am besten geeignet, ist aber auch etwas schwieriger zu benutzen.
http://www.delphi-treff.de/tutorials...rtualtreeview/

Jens Hartmann 11. Feb 2009 18:52

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Danke erstmal,

im Anhang mal den Screenshot

jaenicke 11. Feb 2009 19:45

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Das sieht natürlich sehr komisch aus. Schau mal in den Projektquelltext (Projekt --> Quelltext anzeigen), was steht denn dort? (Oben bei den eingebundenen Units, das müsste ja die selbe Liste sein.)

Vor allem wundert es mich, dass das kompiliert wird. :shock: Irgendetwas stimmt da nicht, aber sowas habe ich noch nicht gesehen. :cyclops:

Jens Hartmann 11. Feb 2009 20:29

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Das ist eigendlich in Ordnung.

Ich habe diese Dateien jetzt einfach gelöscht, Funktioniert.

Projektdatei ist so gewesen:
Delphi-Quellcode:
  Alarm in 'Alarm.pas' {Form1},
  ParserUtils in 'ParserUtils.pas' {Stringverarbeitung Datensätze},
  Lizenz in 'Lizenz.pas' {TFLizenz},
  Messageform in 'Messageform.pas' {FMessagebox};
Werde das mit dem VirtualTreeView gleich mal durchlesen.

Also wäre es besser wenn ich mein Grid gegen ein VirtualTreeView austausche.

Hast Du da noch Tips

jaenicke 11. Feb 2009 21:29

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Zitat:

Zitat von Jens Hartmann
Das ist eigendlich in Ordnung.

Ich habe diese Dateien jetzt einfach gelöscht, Funktioniert.

Dann vermute ich, dass der Fehler in der XML-Projektdatei (.bdsproj) lag. Der Compiler benutzt aber nur die .dpr, so dass das Kompilieren trotzdem funktioniert.

Zitat:

Zitat von Jens Hartmann
Also wäre es besser wenn ich mein Grid gegen ein VirtualTreeView austausche.

Hast Du da noch Tips

Der Unterschied ist da vor allem, dass man die Daten nicht einfach in die Komponente legt, sondern dass die Daten selbst gespeichert werden. Bei der Anzeige werden diese dann angefordert.

Um die Darstellung so anpassen zu können, wie man es möchte, wäre es am sinnvollsten den Inhalt selbst zu zeichnen. So habe ich es jedenfalls gemacht. Ob es mehrzeilig auch anders geht, bin ich gerade nicht sicher.

Jens Hartmann 11. Feb 2009 21:39

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Das heißt also, das ich mich jetzt erstmal mit dem VirtualTreeView beschäftigen sollte.

Das werde ich jetzt erstmal machen, ich denke das ich da bestimmt auf Dich zukomme.

Ich werde aber dann dazu einen neune Tread aufmachen, damit auch andere später die Fragen dazu finden und nutzten könne.

Also danke schon mal bis bald.

Gruß Jens

Jens Hartmann 14. Feb 2009 12:27

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo Sebastian,

So ich habe mich jetzt mit dem VirtualTreeView beschäftig, und versuche jetzt da mal weiterzukommen.

Als erstes habe ich mir deine Klasse Parsen kopiert und eine Klasse TreeViewParsen erstellt, um mir die vorhanden nicht zu zerstören.

Das funktioniert auch genau so wie vorher mit Parsen.

Jetzt habe ich versucht in meiner Buffer Verarbeitung von COM1 nur die aktuelle Zeile einlesen, um mir das öffnen der Datei zu sparen, und vorallem das immer wiederholte lesen der gesamten Datei.

Also ist mein Ziel jetzt, Zeile lesen und im VirtualStringTree einzupflegen.

Leider hänge ich schon an folgendem Punkt:

Meine Zeile wird eingelesen und erhält auch den aktuellen Wert.

Delphi-Quellcode:
Procedure TForm1.Bufferverarbeitung;
Var
     I                 :Integer;
     Laenge            :Integer;
     ParserTreeView : TMyBaseParser;
begin
Laenge:=Length(Buffer);
I:=1;
while I < Laenge+1 do
                begin
                Zeile:=Zeile+Buffer[I];
                IF Buffer[i] =#13 then begin
                                       ParserTreeView := TMyParserMB256plus.Create;
                                       ParserTreeView.Parse(Zeile);
                                       TreeViewResult(ParserTreeView);
                                       ParserTreeView.Free;
                                       case RGZentralentyp.ItemIndex of
                                         0 : DatenverarbeitungMB24;
                                         1 : DatenverarbeitungMB48;
                                         2 : DatenverarbeitungMB100;
                                         3 : DatenverarbeitungMB256;
                                         4 : DatenverarbeitungUEZ2000;
                                         5 : DatenverarbeitungBMC1024;
                                       end;
                                       end;

                INC(I);
                end;
Buffer:='';
end;
Wir hatten schon mal darüber gesprochen, das ich das mit StringReplaced lassen könnte, da diese Funktion in Parsen ja vorhanden ist. Leider funktiioniert das aber nicht.

Wenn ich beim Debuggen in Liste überwachter Ausdrücke mir den Wert von Zeile ansehe, ist das soweit in Ordnung, das immer nur die aktuelle Zeile vorhanden ist.

Natürlich mit den ganzen Steuerzeichen.


Es wird dann auch die Klasse Parsen durchgeführt, und an folgendem Punkt überspringt dann mein Programm

Delphi-Quellcode:
procedure TMyParserMB256plus.Parse(Text: String);
var
  CurEntry: ^TMyDataEntry;
  CurLine: String;
  i1 : integer;
  i2 : integer;
  temp : String;
begin
  Data := Text;
  DataPointer := 1;
  SetLength(Entries, 0);
  SkipTrash;
  CurLine := ReadLine;
  while DataPointer < Length(Data) do [b]//Hier bleibt mein Programm stehen und Überspringt die gesamte Zuweisung von Entries[/b]
  begin
    SetLength(Entries, Length(Entries) + 1);
    CurEntry := @Entries[High(Entries)];
Was mache ich falsch

Gruß

Jens

jaenicke 14. Feb 2009 17:12

Re: StringGrid mit Daten füllen und farblich Darstellen
 
So funktioniert das auch nicht. Ich habe ja geschrieben: An Parse kannst du nur ganze Datensätze übergeben. Wenn du das nicht gewährleisten kannst, dann müsstest du das Parsen selbst zeilenweise aufbauen, d.h. eine Methode AddLine oder so basteln, die immer nur eine Zeile hinzufügt z.B.
Dann müsste jeweils der aktuelle Status, also an welcher Stelle des Parsens man ist gespeichert werden ODER so lange Zeilen hinzugefügt werden bis der aktuelle Eintrag komplett ist.

Wo genau kommen denn die Daten an? Letztlich ließe sich das genau dort bereits verarbeiten ohne viele Zwischenschritte. Dafür könnte sich ein endlicher Automat eignen, der entsprechend einem Zustandsdiagramm direkt zeichenweise analysiert. Damit könnten auch inkomplette Eingänge bereits verarbeitet werden.
Beispiel: der Automat bleibt bei Buchstaben in dem entsprechenden Zustand und bei Zeichen #13 geht er in den nächsten Zustand über.

Das ist praktisch die selbe Vorgehensweise wie bei einem Taschenrechner. Wenn man das erst richtig verstanden hat, dann ist das auch relativ einfach zu implementieren. Das Planen ist das größere Problem. ;-)

Jens Hartmann 14. Feb 2009 17:20

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Hallo Sebastian,

ich sitze jetzt schon den ganzen Nachmittag hiervor und vor ca. 5 Minuten, habe ich es jetzt aufjedenfall so weit, das ich alle Zeilen sauber und richtig auswerte.

Ich denke nur nach deiner gerade gestellten antwort, das das wahrscheinlich total falsch ist, was ich gemacht habe.

Hier meine Lösung:

Delphi-Quellcode:
Procedure TForm1.Bufferverarbeitung;
Var
     I                 :Integer;
     Laenge            :Integer;
     Übergabe          :String;
     ParserTreeView : TMyBaseParser;
begin
Laenge:=Length(Buffer);
I:=1;
while I < Laenge+1 do
                begin
                Zeile:=Zeile+Buffer[I];
                IF Buffer[i] =#13 then begin
                                       Übergabe := Zeile;
                                       Übergabe := StringReplace(Übergabe, #154, 'Ü', [rfReplaceAll]);
                                       Übergabe := trim(StringReplace(Übergabe, #$D, '', [rfReplaceAll]));
                                       Übergabe:= StringReplace(Übergabe, #129, 'ü', [rfReplaceAll]);
                                       Übergabe := trim(StringReplace(Übergabe, #132, 'ä', [rfReplaceAll]));
                                       Übergabe := StringReplace(Übergabe, #142, 'Ä', [rfReplaceAll]);
                                       Übergabe := StringReplace(Übergabe, #148, 'ö', [rfReplaceAll]);
                                       Übergabe := StringReplace(Übergabe, #153, 'Ö', [rfReplaceAll]);
                                       Übergabe := StringReplace(Übergabe, #154, 'Ü', [rfReplaceAll]);
                                       Übergabe := StringReplace(Übergabe, #10#13, ' ', [rfReplaceAll]);
                                       
                                       ParserTreeView := TMyParserMB256plus.Create;
                                       ParserTreeView.Parse(Übergabe);
                                       TreeViewResult(ParserTreeView);
                                       ParserTreeView.Free;

                                       case RGZentralentyp.ItemIndex of
                                         0 : DatenverarbeitungMB24;
                                         1 : DatenverarbeitungMB48;
                                         2 : DatenverarbeitungMB100;
                                         3 : DatenverarbeitungMB256;
                                         4 : DatenverarbeitungUEZ2000;
                                         5 : DatenverarbeitungBMC1024;
                                       end;
                                       end;

                INC(I);
                end;
Buffer:='';
end;
und hier die Verarbeitung in ParserUtils:

Delphi-Quellcode:
procedure TMyParserMB256plus.Parse(Text: String);
var
  CurEntry: ^TMyDataEntry;
  CurLine: String;
  i1 : integer;
  i2 : integer;
  temp : String;
begin
  Data := Text;
  OemToAnsi(Data);
  DataPointer := 1;
  SetLength(Entries, 0);
  SkipTrash;
  CurLine := ReadLine;
  //while DataPointer = Length(Data) do
  //begin
  SetLength(Entries, Length(Entries) + 1);
  CurEntry := @Entries[High(Entries)];

{Indexbehandlungsroutine}

    if Pos('Ereignis:', CurLine) = 1 then
    begin
    Delete(CurLine, 1, 10);
    CurEntry.LfdNr := StrToInt(CurLine);
    CurLine := ReadLine;
    end;

{Datum & Uhrzeitbehandlungsroutine}

    if Pos('Datum:', CurLine) = 1 then
    begin
    Temp := CurLine;
    Delete(CurLine, 1, 7);
    Delete(CurLine, 11, 19);
    CurEntry.Datum := CurLine;
    CurLine := Temp;
    Delete(Curline,1, 28);
    CurEntry.Uhrzeit := Curline;
    CurLine := ReadLine;
    end;

{Ereignisbehandlungsroutine}
        if Pos('Ereignis:', CurLine) <> 1 then
          begin
            if Pos('Datum:', CurLine) <> 1 then
              begin
                if Pos('Extern', CurLine)
                or Pos('Intern', CurLine)
                or Pos('Unscharf', CurLine)= 1 then
                  begin
                  CurEntry.Ereignis := CurLine;
                  CurLine := ReadLine;
                  end;
              end;
            end;

        if Pos('Ereignis:', CurLine) <> 1 then
          begin
            if Pos('Datum:', CurLine) <> 1 then
              begin
                if Pos('AP', CurLine)
                or Pos('IE', CurLine) = 1 then
                begin
                CurEntry.Teilnehmer := CurLine;
                CurLine := ReadLine;
                end;
              end;
          end;

        if Pos('Ereignis:', CurLine) <> 1 then
          begin
            if Pos('Datum:', CurLine) <> 1 then
              begin
                if Pos('Hauptbereich:', CurLine) = 1 then
                begin
                CurEntry.Bereich := CurLine;
                CurLine := ReadLine;
                end;
              end;
          end;

  end;

Die ankommenden Daten kommen von der COM Schnittstelle und werden so eingelesen:

Delphi-Quellcode:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  Daten: String;
begin
  ComPort1.ReadStr(Daten, Count);
  Buffer:=Buffer+Daten;
  Bufferverarbeitung;
end;
Gruß Jens

jaenicke 14. Feb 2009 17:37

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Wenn die Daten immer diese Zeilenanfänge haben, dann ist das natürlich auch möglich das daran zu erkennen. In den Beispielen war das aber nicht immer so. Und sobald du eine Zeile ohne den Kontext nicht zuordnen kannst, kommst du so nicht weiter.

Wichtig ist dabei aber, dass du die Anzahl der Einträge nur erhöhen darfst, wenn auch tatsächlich der Anfang eines neuen Eintrags, also dessen erste Zeile, vorliegt. Denn sonst füllst du die Zeile immer in einen neuen Eintrag.

Nebenbei sehe ich keinen Grund für eine globale Variable Buffer, das kannst du doch auch direkt an die entsprechende Verarbeitungsroutine (Bufferverarbeitung) als Parameter weiterleiten (es sei denn du willst jedesmal den kompletten Buffer wirklich durchlaufen). Globale Variablen sind zwar nicht per se schlecht, aber je mehr man sie benutzt, desto unübersichtlicher wird das Programm. Und man muss dann ganz genau dokumentieren wo in die Variablen geschrieben wird und wo sie wann benutzt werden (als Kommentar bei der Deklaration der Variablen z.B.).

Übersichtlicher ist es, wenn man globale Variablen nur da benutzt, wo es nötig ist.

// EDIT:
Ich meinte das, wenn du nur die aktuelle Zeile verarbeitest, aber ich sehe gerade, dass du immer den kompletten Buffer neu analysiert. :gruebel:

Jens Hartmann 14. Feb 2009 17:54

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Das mit der Var. Buffer ist mir bekannt, habe ich allerdings noch als global, weil ich nicht wußte ob ich mal drauf zugreifen muss.

Ich brauche aber nur die Var. Zeile als Global und das werde ich somit ändern.

Ich denke schon das ich das so machen kann, da jede neue Zeile mit einer neuen Ereignissnummer anfängt.

Ich muss jetzt nur noch alle Möglichen Ereigniss in die If / Or Abfrage setzten (soviele sind es nicht) und denke mir dann, das ich die Daten an das VirtualStringTree übergeben kann.

Ich muss doch eigendlich nur mit der ersten gelesenen Ereignisnummer anfangen, die Daten die da kommen weiter eintragen, und sollte eine weitere Ereignisnummer kommen den VirtualSringTree um eine weitere Zeile erweitern.

Weiß nicht, aber denke mir das das so hinhauen könnte.

Wenn diese Lösung hier nicht so gut ist, will ich es auch gerne anders Probieren.

Wenn das so Funktioniert, braucht ich für andere Zentralentypen nur die entsprechenden If/OR Abfragen und das wär´s.

Da die Datensätze bei anderen Zentralentypen anders aufgebaut sein können, muss ich eh, je nach Eingestelltem Zentraltyp das VirtualStringTree neu zeichnen.

Gruß

Jens

Jens Hartmann 16. Feb 2009 21:21

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Habe jetzt noch eine wenig ausprobiert,und bin leider doch nicht so weit.

Ich habe die entgegennahme jetzt direkt in die Verarbeitung der Schnittstellendaten eingepflegt.

Habe jetzt mal Texte geändert und so, sieht dann so ein Datensatz aus.

#$A#$D#$A'Ereignis: 6091'#$D#$A'Datum: 09.12.2008, Uhrzeit: 18:31:41'#$D#$A'Unscharf'#$D#$A'Hauptbereich: 001, Unterbereich: 000'#$D

Ergebnis als Textdatei gespeichert Hab den mal als Quellcode gewandelt, damit man die Kommentare erkenne kann

Delphi-Quellcode:
Ereignis: 5773                           //Immer so
Datum: 09.12.2008, Uhrzeit: 19:07:31     //Immer so
Sabotagemeldergruppe: 0004 EIN          //Doch sehr viele Varianten erscheint aber in jedem Datensatz
AP E/A E: 04 Differential-Eingang       //Wenig Varianten, aber dafür nicht in jedem Datensatz vorhanden
Hauptbereich: 001, Unterbereich: 000     //Text kann evtl. auch "vbaelrvgbaelrvub" sein

//(Hauptbereich z.B. könnte auch einen selbst erstellten Namen habe)


Ereignis: 5774
Datum: 09.12.2008, Uhrzeit: 19:07:31
AP E/A E: 05 Sabotage Sirene EIN
Hauptbereich: 001
Ich hoffe du kannst erkennen, das die Datensätze doch unterschiedlich sein können. Ich übergebe jetzt doch wieder einen kompletten Datensatz an die Parsefunktion.

Mein Problem ist jetzt, immer noch die genaue Zuweisung der Daten in die richtigen Zeilen

Wenn ich mir den kompletten Datensatz ansehe, habe ich ja immer die Trennung zwischen den Zeilenvorschüben, Leider weiß ich immer noch nicht wie ich erkennen soll, das in der Mitte ein Teildatensatz fehlt.

Eréignis ist klar, damit fängt der Datensatz immer an
Datum somit auch kein Problem und
Uhrzeit bekomme ich auch gefilter.
Der Teilnehmer Text, wenn er da ist, könnte ich mir momentan noch vorstellen in an den Kürzeln AP, IE, MAKRO AE zu erkenne.
Der Bereich ist immer der letzte Datensatz allerdings ohne festen Namen

Vieleicht kannst du mir mal folgende Funktionen von der ParsenUtils erklären. Da habert es nämlich bei mir.

Delphi-Quellcode:
procedure TMyBaseParser.SkipTrash;
begin
  while (DataPointer < Length(Data)) and (Data[DataPointer] in [#13, #10, #32]) do
    Inc(DataPointer);
end;

function TMyBaseParser.GetTextLength(UpToLineEnd: Boolean): Integer;

  function IsTerminatingChar(CharIndex: Integer): Boolean;
  begin
    if UpToLineEnd then
      Result := Data[CharIndex] in [#13, #10]
    else
      Result := Data[CharIndex] in [#13, #10, #32];
  end;

var
  CurPointer: Integer;
begin
  Result := -1;
  CurPointer := DataPointer;
  while Result < 0 do
  begin
    while (CurPointer < Length(Data)) and not IsTerminatingChar(CurPointer) do
      Inc(CurPointer);
    if (CurPointer + 1 < Length(Data)) and not IsTerminatingChar(CurPointer + 1) then
      Inc(CurPointer)
    else
      Result := CurPointer - DataPointer;
    if CurPointer = Length(Data) then
      Result := CurPointer - DataPointer + 1;
  end;
end;

Blup 17. Feb 2009 09:31

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Die Funktion GetTextLength ist unnötig kompliziert (oder künstlerische Freiheit).
Delphi-Quellcode:
var
  CurPointer: Integer;
begin
  CurPointer := DataPointer;

  while (CurPointer <= Length(Data)) and not IsTerminatingChar(CurPointer) do
    Inc(CurPointer);

  Result := CurPointer - DataPointer;
end;

Jens Hartmann 17. Feb 2009 15:56

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Kann schon möglich sein, gibt es den hier auch jemanden, der mir die Funktionen auch irgendwie erklären kann, damit auch ich den Ablauf verstehe ?

Gruß

Jens

Jens Hartmann 17. Feb 2009 18:05

Re: StringGrid mit Daten füllen und farblich Darstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hab es hinbekommen, den kompletten Datensatz auszuwerten. Und bekomme auch alle Rückgaben in mein Unit zurück. Leider habe ich jetzt ein anderes Problem.

Die Daten werden nur dann in mein StringGrid eingetragen, wenn ich im Debugmodus im Unit Parsen einen Breakpoint setze.
Nehme ich dann den Breakpoint weg, sind meine Daten sauber und auch richtig sortiert in meinem StringGrid.

Lass ich mein Programm normal laufen, gelangen keine Einträge in mein StringGrid, In einem Memo kann ich aber sehen, das Daten kommen und auch übergeben werden.

Ich häng mal die komplette fertige Unit Parsen und die Übergabe an.. bzw füge sie als Code bei:

Delphi-Quellcode:
unit Parsen;

interface

uses
  Windows, SysUtils;

type
  TMyDataEntry = record
    LfdNr: Integer;
    Datum, Uhrzeit, Ereignis, Teilnehmer, Bereich : String;
  end;

  TMyBaseParser = class
  private
    Data: String;
    DataPointer: Integer;
    function OemToAnsi(const OemStr: string): string;
    procedure SkipSpaces;
    procedure SkipTrash;
    function GetTextLength(UpToLineEnd: Boolean): Integer;
    function ReadLine: String;
  public
    Entries: array of TMyDataEntry;
    procedure Parse(Text: String); virtual; abstract;
  end;

  TMyParserMB256plus = class(TMyBaseParser)
  private
  public
    procedure Parse(Text: String); override;
  end;

var
Zähler : integer;

implementation

{ TMySimpleBaseParser }

function TMyBaseParser.OemToAnsi(const OemStr: string): string;
begin
  SetLength(Result, Length(OemStr));
  if Length(Result) > 0 then
    OemToCharBuff(PChar(OemStr), PChar(Result), Length(Result));
end;

procedure TMyBaseParser.SkipSpaces;
begin
  while (DataPointer < Length(Data)) and (Data[DataPointer] = ' ') do
    Inc(DataPointer);
end;

procedure TMyBaseParser.SkipTrash;
begin
  while (DataPointer < Length(Data)) and (Data[DataPointer] in [#13, #10, #32]) do
    Inc(DataPointer);
end;

function TMyBaseParser.GetTextLength(UpToLineEnd: Boolean): Integer;

  function IsTerminatingChar(CharIndex: Integer): Boolean;
  begin
    if UpToLineEnd then
      Result := Data[CharIndex] in [#13, #10]
    else
      Result := Data[CharIndex] in [#13, #10, #32];
  end;

var
  CurPointer: Integer;
begin
  CurPointer := DataPointer;

  while (CurPointer <= Length(Data)) and not IsTerminatingChar(CurPointer) do
    Inc(CurPointer);

  Result := CurPointer - DataPointer;
end;

function TMyBaseParser.ReadLine: String;
var
  TextLen: Integer;
begin
  TextLen := GetTextLength(True);
  Result := Copy(Data, DataPointer, TextLen);
  DataPointer := DataPointer + TextLen;
  SkipTrash;
end;

{ TMyParserMB256plus }


procedure TMyParserMB256plus.Parse(Text: String);
var
  CurEntry : ^TMyDataEntry;
  CurLine  : String;
  TempDatum : String;
  Temp1     : String;
  Temp2     : String;

begin
  Data := Text;
  DataPointer := 1;
  SetLength(Entries, 0);
  SkipTrash;
  while DataPointer < Length(Data) do
  begin
    SetLength(Entries, Length(Entries) + 1);
    CurEntry := @Entries[High(Entries)];

{Indexbehandlungsroutine}
    CurLine := ReadLine;
    if Pos('Ereignis:', CurLine) = 1 then
      begin
        Delete(CurLine, 1, 10);
        CurEntry.LfdNr := StrToInt(CurLine);
        CurLine := ReadLine;
      end;

{Datum & Uhrzeitbehandlungsroutine}
    if Pos('Datum:', CurLine) = 1 then
      begin
        TempDatum := CurLine;
        Delete(CurLine, 1, 7);
        Delete(CurLine, 11, 19);
        CurEntry.Datum := CurLine;
        CurLine := TempDatum;
        Delete(Curline,1, 28);
        CurEntry.Uhrzeit := Curline;
        {Ende Datumseintrag}

{Ereignisbehandlungsroutine}
        CurEntry.Ereignis := ReadLine;
        CurLine := ReadLine;
      if Pos('Hauptbereich:', CurLine) <> 1 then
        begin
          if Pos('AP', CurLine)
          or Pos('IE', CurLine)
          or Pos('Makro', CurLine)
          or Pos('Modem', CurLine)= 1 then
            begin
              CurEntry.Teilnehmer := CurLine;
              CurEntry.Bereich := ReadLine;
            end;
        end
      else
        begin
          CurEntry.Bereich := CurLine;
        end;
      end;
  end;
end;
end.
Hier die Übernahme in mein Unit

Delphi-Quellcode:
procedure TForm1.TreeViewResult(ParserTreeView: TMyBaseParser);
var
  i: Integer;
begin
  for i := 0 to High(ParserTreeView.Entries) do
  begin
  if ParserTreeView.Entries[i].LfdNr = 0 then
    begin
      RCount := RCount+1;
      SGMB256plus.RowCount := RCount+1;
      Memo2.Lines.Add(IntToStr(ParserTreeView.Entries[i].LfdNr));
      SGMB256plus.Cells[0, RCount + 1] := IntToStr(ParserTreeView.Entries[i].LfdNr);
    end;
  if ParserTreeView.Entries[i].Datum <> '' then
    begin
      Memo3.Lines.Add(ParserTreeView.Entries[i].Datum);
      SGMB256plus.Cells[1, RCount + 1] := ParserTreeView.Entries[i].Datum;
    end;
  if ParserTreeView.Entries[i].Uhrzeit <> '' then
    begin
      Memo4.Lines.Add(ParserTreeView.Entries[i].Uhrzeit);
      SGMB256plus.Cells[2, RCount + 1] := ParserTreeView.Entries[i].Uhrzeit;
    end;
  if ParserTreeView.Entries[i].Ereignis <> '' then
    begin
      Memo5.Lines.Add(ParserTreeView.Entries[i].Ereignis);
      SGMB256plus.Cells[3, RCount + 1] := ParserTreeView.Entries[i].Ereignis;
    end;
  if ParserTreeView.Entries[i].Teilnehmer <> '' then
    begin
      Memo6.Lines.Add(ParserTreeView.Entries[i].Teilnehmer);
      SGMB256plus.Cells[4, RCount + 1] := ParserTreeView.Entries[i].Teilnehmer;
    end;
  if ParserTreeView.Entries[i].Bereich <> '' then
    begin
      Memo7.Lines.Add(ParserTreeView.Entries[i].Bereich);
      SGMB256plus.Cells[5, RCount + 1] := ParserTreeView.Entries[i].Bereich;
    end;
  end;
end;
Und im Anhang mal noch ein Bild im DebugModus, wo man sieht, das die Daten auch wirklich so sind, wie sie sein sollen.

Danke schon mal. Vieleicht weiß ja jemand woran es liegen kann..

MFG


Jens


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:21 Uhr.
Seite 1 von 3  1 23      

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