Einzelnen Beitrag anzeigen

Borschti

Registriert seit: 1. Nov 2007
Ort: Marburg Lahn
235 Beiträge
 
Delphi 2007 Professional
 
#3

Re: Access Violation 30 Sek. nach letzter Anweisung?

  Alt 17. Jun 2008, 15:16
Also hab die StringList freigegeben, hat aber nichts genützt.

Datenaufbereiten:

Delphi-Quellcode:
procedure Datenaufbereiten(ParamListe : TStringlist; ParamTrenner : string; ParamPanel : TVisiStatusPanel);
var
  Zaehler : Integer;
  Feldliste : TStringlist;
  Datenliste : TStringlist;
  AktFeld : Integer;
begin
  (* Erzeugung einer Stringlist fuer die Speicherung der Feldangaben *)
  Feldliste := TStringlist.Create;
  (* Erzeugung einer Stringlist fuer die Zwischenspeicherung der Dateninhalte einer Textzeile *)
  Datenliste := TStringlist.Create;

  (* Schliessen der temporaeren Tabelle *)
  DataModule1.TempDaten.Active := false;

  (* Wenn die uebergebene Liste, die alle Textzeilen der Textdatei enthaelt, existiert, dann... *)
  if ParamListe <> nil then
    begin
     (* Wenn die uebergebene Liste auch wirklich Zeilen hat, dann... *)
      if ParamListe.Count > 0 then
        begin
          (* ... wird als erstes die Datenstruktur der temporaeren Tabelle aufgebaut. Dazu *)
          (* werden die Feldbeschreibungen (FieldDefs) zunaechst geloescht.                *)
          DataModule1.TempDaten.FieldDefs.Clear;

          (* Die erste Zeile (ACHTUNG: Indexwert 0) wird in ihre Bestandteile (Feldanga-)  *)
          (* aufgespalten. Der Feldtrenner wird dabei an die Prozedur DatenTrennen durch-  *)
          (* gereicht.                                                                     *)
          DatenTrennen(ParamListe.Strings[0], ParamTrenner, FeldListe);

          (* Der Einfachheit halber, werden in der temporaeren Tabelle nur Felder vom Da-  *)
          (* tentyp String und einer Dimension von 30 Zeichen angelegt. Mittels FOR-       *)
          (* Schleife wird die Feldliste vom ersten bis zum letzten Eintrag abgearbeitet.  *)
          (* Wiederum ist zu beachten, dass der Index mit 0 und nicht mit 1 beginnt.       *)
          for Zaehler := 0 to Feldliste.Count - 1 do
            begin
              (* With-Konstrukt vereinfacht die Angabe von Eigenschaften. *)
              with DataModule1.TempDaten Do
                begin
                  (* Mit der Methode IndexOf wird geprueft, ob in den FieldDefs schon ein  *)
                  (* Feld mit dem aktuellen Feldnamen existiert. Ein Feldname darf nicht   *)
                  (* doppelt vergeben werden. Wenn die Moeglichkeit besteht, dass ein Feld *)
                  (* mehrfach benoetigt wird, muesste in einem Else-Zweig ein Ersatzkon-   *)
                  (* strukt gebildet werden, das evtl. mit einem laufenden Zaehler zur Un- *)
                  (* scheidung der Felder beitraegt. In diesem Beispiel wird darauf jedoch *)
                  (* verzichtet.                                                           *)
                  if FieldDefs.IndexOf(AnsiUpperCase(Feldliste.Strings[Zaehler])) < 0 then
                    FieldDefs.Add(AnsiUpperCase(Feldliste.Strings[Zaehler]), ftString, 30, False);

                end;
            end;

          (* Die Tabelle Land, die fuer die Demonstration eines Lookup-Feldes in der Tabelle *)
          (* TempDaten benoetigt wird, muss vor der eigentlichen Tabelle geoeffnet werden.   *)
          DataModule1.Land.Active := true;

          (* Oeffnen der temporaeren Tabelle namens TempDaten. Ueber einen Editor ist ein    *)
          (* Lookup- und ein CalcField angelegt worden. *)
          DataModule1.TempDaten.Active := true;

          (* Die Datenzeilen aus der uebergebenen Stringlist werden verarbeitet. Da die Da-  *)
          (* ten ab der zweiten Zeile angenommen werden, ist als Startwert fuer die FOR-     *)
          (* Schleife auf 1 zu setzen (entspricht dem 2. Element der Liste!).                *)
          for Zaehler := 1 to ParamListe.Count - 1 do
            begin
              (* Die Prozedur DatenTrennen kann fuer die Datenzeilen auch verwendet werden, weil *)
              (* fuer die Funktionalitaet unerheblich ist, ob es sich um die erste Zeile mit der *)
              (* Feldbeschreibung handelt oder eine der nachfolgenden Datenzeilen. Alle Zeilen   *)
              (* enthalten schliesslich einzelne Elemente, die mit einem Trennzeichen (z.B. Se-  *)
              (* mikolon) voneinander getrennt sind. Uebergeben wird hier jedoch eine zweite     *)
              (* Stringlist, die fuer die Zwischenspeicherung der Daten vorbehalten ist.         *)
              DatenTrennen(ParamListe.Strings[Zaehler], ParamTrenner, Datenliste);

              (* Wenn die Anzahl der Feldbeschreibungen mit der Anzahl der gefundenen Daten-     *)
              (* elemente uebereinstimmt, ist die Wahrscheinlichkeit gross, dass die Struktur in *)
              (* Ordnung ist. Bei einer Abweichung muss sind entweder zu viele oder zu wenige    *)
              (* Informationen in der Datenzeile. Ursache kann eine "missbraeuchliche" Nutzung   *)
              (* des Trennzeichens sein. Das kann vor allem bei einem Komma als Trennzeichen     *)
              (* auftreten sofern bei Gleitkommazahlen auch ein Komma uebergeben wird.           *)
              if Feldliste.Count = Datenliste.Count then
                begin
                  (* Datensatz in der temporaeren Tabelle anfuegen und in den Editiermodus schalten. *)
                  (* Die Append-Methode sorgt fuer beides, so dass die Edit-Methode nicht aufgerufen *)
                  (* wird.                                                                           *)
                  DataModule1.TempDaten.Append;

                  (* Mit einer FOR-Schleife koennen alle Felder durchlaufen werden *)
                  For AktFeld := 0 to Datenliste.Count - 1 do
                    begin
                      with DataModule1.TempDaten Do
                        begin
                          (* Fieldbyname-Methode zum Ansprechen eines Datenfeldes mit dem in der  *)
                          (* Stringlist gespeicherten Feldnamen. Da die Reihenfolge der Feld- und *)
                          (* Datenzeile identisch sein soll, kann die Zuordnung des Inhalts ein-  *)
                          (* fach ueber den Index erfolgen.                                       *)
                          Fieldbyname(Feldliste.Strings[AktFeld]).Asstring := Datenliste.Strings[AktFeld];
                        end;
                    end;
                  (* Nach der Zuweisung aller Daten kann der Datensatz gespeichert werden. Dieses *)
                  (* geschieht mit der Post-Methode der Tabelle.                                  *)
                  DataModule1.TempDaten.Post;
                end;

              (* Pruefung, ob ein Statusbar-Panel uebergeben wurde. Soll der Fortschritt nicht    *)
              (* angezeigt werden, reicht es aus, der Prozedur anstelle des Objekts den Wert NIL  *)
              (* mitzugeben also z.B. Datenaufbereiten(Datenliste; ';', nil).                     *)
              if ParamPanel <> nil then
                begin
                  (* Panel sichtbar machen *)
                  ParamPanel.Enabled := true;
                  (* GaugeAttrs nutzbar, wenn das Panel vom Typ skGauge ist. Die Eigenschaft Po-  *)
                  (* sition gibt den Wert an, den der Fortschrittsbalken erhalten soll. In diesem *)
                  (* Fall wird eine prozentuale Darstellung gewaehlt. Die mathematische Funktion  *)
                  (* DIV wird zur Division genutzt, weil so ein ganzzahliger Wert ermittelt wird, *)
                  (* wie es von der Eigenschaft verlangt wird. Diese Funktion wird gerne gemein-  *)
                  (* sam mit der Funktion MOD gelehrt. Sie fuehrt ebenfalls eine Division durch,  *)
                  (* gibt dann aber den ganzzahligen Rest zurueck.                                *)
                  (* Beispiele:                                                                   *)
                  (*              5 / 2 = 2.5,   5 DIV 2 = 2,  5 MOD 2 = 1                        *)
                  (*             10 / 2 = 5  ,  10 DIV 2 = 5, 10 MOD 2 = 0                        *)
                  ParamPanel.GaugeAttrs.Position := Zaehler * 100 div (ParamListe.Count - 1);

                  (* Mit ProcessMessages wird eine Windows-Message abgesendet, deren Konsequenz   *)
                  (* ein Refresh der Anwendung ist.                                               *)
                  Application.ProcessMessages;
                end;

            end;

          (* Panel unsichtbar machen *)
          if ParamPanel <> nil then
            ParamPanel.Enabled := false;
        end;
    end;

  (* den Speicher der Stringlisten wieder freigeben und die Objekte eliminieren *)
  FreeAndNil(Datenliste);
  FreeAndNil(FeldListe);
end;
dazu noch Datentrennen:

Delphi-Quellcode:
procedure Datentrennen(ParamZeile, ParamTrenner : string; Var ParamListe : TStringlist);
var
  TrennPos : integer;
  StartPos : integer;
  Zaehler : integer;
  MyMsg : string;
begin
    (* Uebergebene TStringlist wird geleert *)
    ParamListe.Clear;

    (* Ausgangswert fuer die Suche des Trennzeichens innerhalb der Zeichenkette. Die Funktion *)
    (* PosEx (Unit StrUtils) unterstuetzt im Gegensatz zur Funktion Pos die Suche einer       *)
    (* Zeichenfolge ab einer definierten Position. Zunaechst soll ab der 1. Stelle gesucht    *)
    (* werden.                                                                                *)
    StartPos := 1;

    (* TrennPos nimmt den Rueckgabewert von PosEx áuf und stellt die Position der gesuchten   *)
    (* Zeichenkette dar.                                                                      *)
    TrennPos := PosEx(ParamTrenner, ParamZeile, StartPos);

    (* Sofern ein Trennzeichen gefunden wurde... *)
    while (TrennPos > 0) do
      begin
        (* ... wird mit der Funktion Copy ab dem Ausgangswert bis zum Trennzeichen eine Zeichen- *)
        (* kette herauskopiert und der Stringlist angefuegt.                                     *)
        Paramliste.Add (COPY(ParamZeile, StartPos, TrennPos - StartPos));

        (* Um zu pruefen, ob ein weiteres Trennzeichen in der Zeichenkette vorkommt, wird der    *)
        (* Ausgangswert erhoeht. Dabei wird zu der Position des zuletzt gefundenen Trennzeichens *)
        (* der Wert 1 addiert.                                                                   *)
        StartPos := TrennPos + 1;
        TrennPos := PosEx(ParamTrenner, ParamZeile, StartPos);
      end;

    (* Zeichenkette fuer die Ausgabe der Stringlist wird mit einem Leerstring initialisiert      *)
    MyMsg := '';

    (* In die Zeichenkette werden alle Elemente der Stringlist eingefuegt. Fuer eine uebersicht- *)
    (* liche Darstellung wird nach jedem Element jeweils ein Zeilenumbruch (englisch Carriage    *)
    (* Return [CR]) angefuegt, der im ASCII-Zeichensatz mit dem Wert 13 definiert ist.           *)
    for Zaehler := 0 to ParamListe.Count -1 do
      begin
        MyMsg := MyMsg + ParamListe.Strings[Zaehler] + #13;
      end;

    (* Ausgabe der Stringlist in einer Messagebox *)
    //showmessage(MyMsg);
end;
Hoffe das hilft dir weiter, ich kann einfach keinen Fehler finden da die Prozeduren auch in anderen Programmen zum Einsatz kommen glaube ich auch nicht das hier der Fehler liegt.

mfg
Alex
  Mit Zitat antworten Zitat