Beispiel - Schreiben von externen Dateien / Asynchroner Dialog
Beispiel - Schreiben von externen Dateien / Asynchroner Dialog Erstellen einer externen Datei mit Fsi...-Befehlen und Verwendung asynchroner Dialoge
- Siehe:
FsiOpen (),FsiWrite (),WinDialogRun ()
Die hier vorgestellte Funktion schreibt den Inhalt einer Datei in eine externe Datei.
Der Funktion wird ein Elternobjekt übergeben. Das Elternobjekt wird verwendet, um den Dialog zur Fortschrittsanzeige an einen bestehenden Frame anzuhängen. Wird in diesem Parameter 0 übergeben, wird kein Elternobjekt verwendet.
Alle weiteren Parameter werden zum Exportieren der Datensätze benötigt. In diesem Beispiel werden die Datensätze einer Artikel-Datei ausgelagert. Es muss die Nummer des Schlüssels und der Pfad und der Name der externen Datei übergeben werden.
Die Parameter, in der das Transparent-Zeichen, der Feld- und der Datensatztrenner angegeben werden, sind optional.
sub ArtRecExport
(
aHdlParent : handle; // Elternobjekt
aKeyNo : int; // Schlüsselnummer
aExtFileName : alpha(4096); // Name der externen Datei
opt aMeta : alpha(1); // Transparent-Zeichen
opt aFldSep : alpha(10); // Feldtrenner
opt aRecSep : alpha(10); // Datensatztrenner
) : logic;
local
{
tHdlDlg : handle; // Deskriptor des Dialoges
tHdlProgressBar : handle; // Deskriptor des ProgressBar-Objektes
tErg : int; // Ergebnis-Wert
tMeta : alpha(1); // Meta-Zeichen
tFldSep : alpha(10); // Feld-Trennzeichen
tRecSep : alpha(10); // Datensatz-Trennzeichen
tHdlExtFile : int; // Deskriptor der externen Datei
tBuffer : alpha(4096); // Buffer zum Schreiben in externe Datei
}
{
Sollten die optionalen Parameter nicht angegeben werden, müssen sie auf Standardwerte gesetzt werden. Anschließend wird die übergebene Datei mit dem Befehl FsiOpen () geöffnet. Die Parameter des Befehls erzeugen die Datei und richten einen exklusiven Schreib-/Lesezugriff ein.
// Standardbelegung setzen
if (aMeta = '')
tMeta # '~';
else
tMeta # aMeta;
if (aFldSep = '')
tFldSep # ',';
else
tFldSep # aFldSep;
if (aRecSep = '')
tRecSep # StrChar(13)+StrChar(10)
else
tRecSep # aRecSep;
// Datei öffnen
tHdlExtFile # FsiOpen(aExtFileName, _FsiAcsRW | _FsiDenyRW | _FsiCreate);
Die Datei kann nicht geöffnet werden, wenn sie bereits existiert oder das Verzeichnis nicht vorhanden ist. In diesen Fällen gibt der Befehl einen negativen Wert zurück, der in der weiteren Verarbeitung ausgewertet werden müsste. Um das Beispiel möglichst einfach zu gestalten, wurde auf eine Fehlerbehandlung verzichtet.
Der Dialog, der mit der Anweisung WinOpen () geladen wird besteht aus einem ProgressBar-Objekt und einer Schaltfläche. Die Eigenschaft ProgressPos des Fortschritt-Objekts ist auf 0 gesetzt. Die Schaltfläche ist als "Abbrechen"-Schaltfläche definiert (kann über das Kontextmenü der Schaltfläche im Dialog-Assistenten gesetzt werden).
Der Deskriptor des Progress -Objekts wird noch häufiger benötigt, daher wird er in einer Variablen zwischengespeichert. Es wird dadurch ein besseres Laufzeitverhalten, verglichen mit der Referenzierung über den Namen, erreicht. Die Anzahl der zu exportierenden Datensätze wird in die Eigenschaft ProgressMax eingetragen.
// Dialog laden
tHdlDlg # WinOpen('DlgProgress', _WinOpenDialog);
tHdlProgressBar # $ProgressBar;
tHdlProgressBar->wpProgressMax # RecInfo(aFileNo, _RecCount);
Mit dem Befehl WinDialogRun () wird der geladene Dialog gestartet. Wurde ein Elternobjekt angegeben, wird dieses Objekt mit übergeben. Die Option _WinDialogAsync sorgt dafür, dass nach dem Darstellen des Dialoges die Funktion fortgesetzt wird.
if (aHdlParent != 0)
tHdlDlg->WinDialogRun(_WinDialogAsync, aHdlParent);
else
tHdlDlg->WinDialogRun(_WinDialogAsync);
Nach der Anzeige des Dialoges kann mit dem Auslagern der Datensätze begonnen werden. Dazu wird eine Schleife erstellt, die über alle Datensätze der Artikel-Datei läuft. Die Schleife wird abgebrochen, wenn das Ende der Datei erreicht wird (tErg != _rNoRec ), oder der Benutzer die Abbrechen-Schaltfläche drückt (tHdlDlg-> WinDialogResult () != _WinIdCancel ).
Mit dem Befehl WinDialogResult () wird regelmäßig der Zustand des Dialoges überprüft. Der Befehl gibt die ID der gedrückten Schaltfläche zurück.
tErg # RecRead(aFileNo, aKeyNo, _RecFirst);
while ((tHdlDlg->WinDialogResult() != _WinIdCancel) and (tErg != _rNoRec))
{
Nachdem ein Datensatz gelesen wurde, wird die Position des Fortschrittbalkens um eins erhöht. Mit den Formatierungszeichen und den Feldern aus der Artikel-Datei wird eine Variable zusammengesetzt, die nach der Wandlung in den ANSI-Zeichensatz (StrCnv ()) mit dem Befehl FsiWrite () in die externe Datei geschrieben wird.
Anschließend wird der nächste Datensatz gelesen und die Schleife wird erneut durchlaufen.
tHdlProgressBar->wpProgressPos # tHdlProgressBar->wpProgressPos + 1;
tBuffer # tMeta + CnvAI(ArtNummer) + tMeta + tFldSep +
tMeta + ArtBezeichnung + tMeta + tFldSep +
tMeta + ArtBild + tMeta + tFldSep +
tMeta + CnvAF(ArtPreis) +tMeta + tFldSep +
tMeta + ArtTyp + tMeta + tRecSep;
tBuffer # StrCnv(tBuffer, _StrToANSI);
tHdlExtFile->FsiWrite(tBuffer);
tErg # RecRead(fArtikel, aKeyNo, _RecNext);
}
Nachdem der letzte Datensatz gelesen wurde, kann die externe Datei mit dem Befehle FsiClose () geschlossen werden. Anschließend wird mit WinClose () der geladene Dialog geschlossen und die Funktion beendet.
tHdlExtFile->FsiClose();
tHdlDlg->WinClose();
return(true);
}
Die angegebene Funktion exportiert nur die Datensätze aus einer bestimmten Datei. Sie kann aber leicht mit den Befehlen FileInfo (), SbrInfo () und den Fld... ()-Befehlen so umgeschrieben werden, dass sie für beliebige Dateien verwendet werden kann.
Um die Funktion möglichst einfach zu halten, findet keine Fehlerbehandlung statt. Fehler können beim Öffnen der externen Datei und beim Laden des Dialoges auftreten. Zudem können fehlerhafte Werte an die Funktion übergeben werden. Diese Prüfungen können auf einfache Weise durch if...else-Abfragen realisiert werden.
Die Funktion verändert den Inhalt der Feldpuffer. Dieses Problem kann beseitigt werden, indem zu Beginn der Inhalt gesichert und am Ende der Funktion wieder hergestellt wird. Das kann mit folgenden Code-Segmenten erfolgen:
// Datensatzpuffer sichern
tHdlRecBuffer # RecBufCreate(fArtikel);
RecBufCopy(fArtikel, tHdlRecBuffer);
...
// Datensatzpuffer wieder herstellen
RecBufCopy(tHdlRecBuffer, fArtikel);
RecBufDestroy(tHdlRecBuffer);
Im folgenden die komplette Funktion ohne Anmerkungen:
sub ArtRecExport
(
aHdlParent : handle; // Elternobjekt
aKeyNo : int; // Schlüsselnummer
aExtFileName : alpha(4096); // Name der externen Datei
opt aMeta : alpha(1); // Transparent-Zeichen
opt aFldSep : alpha(10); // Feldtrenner
opt aRecSep : alpha(10); // Datensatztrenner
) : logic;
local
{
tHdlDlg : handle; // Deskriptor des Dialoges
tHdlProgressBar : handle; // Deskriptor des ProgressBar-Objektes
tErg : int; // Ergebnis-Wert
tMeta : alpha(1); // Meta-Zeichen
tFldSep : alpha(10); // Feld-Trennzeichen
tRecSep : alpha(10); // Datensatz-Trennzeichen
tHdlExtFile : int; // Deskriptor der externen Datei
tBuffer : alpha(4096); // Buffer zum Schreiben in externe Datei
}
{
// Standardbelegung setzen
if (aMeta = '')
tMeta # '~';
else
tMeta # aMeta;
if (aFldSep = '')
tFldSep # ',';
else
tFldSep # aFldSep;
if (aRecSep = '')
tRecSep # StrChar(13) + StrChar(10);
else
tRecSep # aRecSep;
// Datei öffnen
tHdlExtFile # FsiOpen(aExtFileName, _FsiAcsRW | _FsiDenyRW | _FsiCreate);
// Dialog laden
tHdlDlg # WinOpen('DlgProgress', _WinOpenDialog);
tHdlProgressBar # $ProgressBar;
// Eigenschaft auf die Anzahl der Datensätze setzen
tHdlProgressBar->wpProgressMax # RecInfo(aFileNo, _RecCount);
// Dialog asynchron starten
if (aHdlParent != 0)
tHdlDlg->WinDialogRun(_WinDialogAsync, aHdlParent);
else
tHdlDlg->WinDialogRun(_WinDialogAsync);
// Ersten Datensatz lesen
tErg # RecRead(aFileNo, aKeyNo, _RecFirst);
// Schleifenabbruch bei Drücken von "Abbrechen" oder am Ende der Datei
while ((tHdlDlg->WinDialogResult() != _WinIdCancel) and (tErg != _rNoRec))
{
// Fortschritt setzen
tHdlProgressBar->wpProgressPos # tHdlProgressBar->wpProgressPos + 1;
// Datensatz zusammenstellen
tBuffer # tMeta + CnvAI(ArtNummer) + tMeta + tFldSep +
tMeta + ArtBezeichnung + tMeta + tFldSep +
tMeta + ArtBild + tMeta + tFldSep +
tMeta + CnvAF(ArtPreis) +tMeta + tFldSep +
tMeta + ArtTyp + tMeta + tRecSep;
// Zeichenkette in ANSI-Zeichensatz wandeln und schreiben
tBuffer # StrCnv(tBuffer, _StrToANSI);
tHdlExtFile->FsiWrite(tBuffer);
// Nächsten Datensatz lesen
tErg # RecRead(fArtikel, aKeyNo, _RecNext);
}
// Externe Datei und Dialog schließen
tHdlExtFile->FsiClose();
tHdlDlg->WinClose();
return(true);
}