home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 05 / anwendg / dbdoc.bas next >
Encoding:
BASIC Source File  |  1989-03-17  |  12.3 KB  |  328 lines

  1. '* ------------------------------------------------------- *
  2. '*                      DBDOC.BAS                          *
  3. '* Demonstration des Zugriffs auf DBASE III Datenbankfiles *
  4. '* aus Quick Basic. Das Programm gibt den Inhalt einer     *
  5. '* dBase III-Datei auf dem Bildschirm aus.                 *
  6. '*              (c) 1989 G.Born  &  TOOLBOX                *
  7. '* ------------------------------------------------------- *
  8. '*             Compiler : Quick Basic 4.0/4.5              *
  9. '* ------------------------------------------------------- *
  10. '* Wichtiger Hinweis: Einige Anweisungszeilen paßten nicht *
  11. '* in eine Druckzeile, daher sind abgedruckte Zeilen, die  *
  12. '* mit ... enden bzW. beginnen, als eine Basic-Zeile zu    *
  13. '* verstehen. Die ... können ersatzlos gestrichen werden.  *
  14. '* ------------------------------------------------------- *
  15. TYPE header                    '* Header einer DBASE Datei
  16.   version   AS STRING * 1      '* Version 03H oder 83H
  17.   datum     AS STRING * 3      '* Datum JJ MM TT
  18.   records   AS LONG            '* Records in Datenbank
  19.   headerb   AS INTEGER         '* Zahl der Bytes im Kopf
  20.   recordb   AS INTEGER         '* Zahl der Bytes pro Record
  21.   reserve   AS STRING * 20     '* reservierte Bytes
  22. END TYPE
  23.  
  24. TYPE feld                      '* Feldbeschreibung im Kopf
  25.   fname     AS STRING * 11     '* Feldname 11 Zeichen
  26.   ftyp      AS STRING * 1      '* C N L D M
  27.   dummy1    AS STRING * 4      '* Dummy Feld
  28.   laenge    AS STRING * 1      '* Zahl der Stellen
  29.   komma     AS STRING * 1      '* Zahl der Nachkommastellen
  30.   dummy2    AS STRING * 2      '* reservierte Bytes
  31.   id        AS STRING * 1      '* ID Byte
  32.   dummy3    AS STRING * 11     '* reserviert
  33. END TYPE
  34.  
  35. DIM kopf(1) AS header          '* Variable für Dateiheader
  36. DIM felder(0 TO 128) AS feld   '* Beschreibung f. 128 Felder
  37. anzahl% = 0                    '* Zahl der Felder
  38.  
  39. ein% = 1                       '* Kanal für I/O
  40. filename$ = ""                 '* Dateiname
  41.  
  42. ON ERROR GOTO fehler           '* Fehlerbehandlung
  43.  
  44. '* --------------  Hauptprogramm  --------------------------
  45.  
  46. CLS                            '* Clear Screen
  47. PRINT "DBASE III (DBF) DOC        (c) 1989 G.Born & TOOLBOX"
  48. PRINT
  49. INPUT "File    : ", filename$  '* lese Dateiname
  50. PRINT
  51. IF filename$ = "" THEN         '* Leereingabe ?
  52.   PRINT "Der Name der Eingabedatei fehlt"
  53.   END
  54. END IF
  55. '* --------- Bearbeitung der DBASE III Datei ---------------
  56. '* Dabei ist darauf zu achten, daß ein File mit dem ange-  *
  57. '* gegeben Namen existiert, da QBASIC im BINARY-Mode bei   *
  58. '* fehlender Datei eine neue Datei anlegt. Trick: Datei    *
  59. '* erst im INPUT Mode öffnen, falls die Datei nicht vor-   *
  60. '* handen ist, bricht BASIC ab und verzweigt zu Fehler!    *
  61.  
  62. OPEN filename$ FOR INPUT AS #ein%     '* Datei vorhanden?
  63. CLOSE #ein%                           '* vorhanden -> close
  64. OPEN filename$ FOR BINARY AS #ein%    '* öffne als Binary
  65.  
  66. CALL GetHeader(ein%)                  '* lese Header
  67.  
  68. '*   ***  Ausgabe des Headers der DBASE III Datei ***      *
  69. '*  Die Version gibt dabei an, ob intern Memofelder be-    *
  70. '*  nutzt wurden (version = 83H -> Memodatei)              *
  71.  
  72. PRINT "Header der dBase III-Datei"
  73. PRINT
  74. PRINT "Version      "; HEX$(ASC(kopf(1).version))
  75. PRINT "Datum        "; ASC(MID$(kopf(1).datum, 3, 1)); ".";
  76. PRINT ASC(MID$(kopf(1).datum, 2, 1)); ".";
  77. PRINT ASC(MID$(kopf(1).datum, 1, 1))
  78. PRINT "Records      "; kopf(1).records
  79. PRINT "Header Länge "; kopf(1).headerb
  80. PRINT "Record Länge "; kopf(1).recordb
  81. PRINT
  82. INPUT "Weiter, bitte die <RET> Taste betätigen", tmp$
  83.  
  84. '* lese und decodiere die Feldbescheibung der dBase III-   *
  85. '* Datei, es sind maximal 128 Felder zulässig              *
  86.  
  87. CALL GetFieldDef(ein%)              '* lese Feldbeschreibung
  88.  
  89. PRINT "Feldbeschreibung der Datei "; filename$
  90. PRINT
  91. PRINT "Feldname   │   Typ    │ Stellen │ Kommastellen"
  92. PRINT "───────────┼──────────┼─────────┼─────────────"
  93.  
  94. FOR i% = 1 TO anzahl%               '* n Felddefinitionen
  95.   PRINT felder(i%).fname; "│";      '* Name des Feldes
  96.   SELECT CASE felder(i%).ftyp       '* gebe Feldtyp aus
  97.     CASE "N"
  98.       PRINT "Numerisch │";
  99.     CASE "C"
  100.       PRINT "Character │";
  101.     CASE "L"
  102.       PRINT "Logical   │";
  103.     CASE "D"
  104.       PRINT "Datum     │";
  105.     CASE "M"
  106.       PRINT "Memo      │";
  107.   END SELECT
  108.   PRINT USING "##"; SPC(4); ASC(felder(i%).laenge);
  109.                                     '* Feldlänge
  110.   PRINT "   │   "; ASC(felder(i%).komma)
  111.                                     '! Nachkommastellen
  112. NEXT i%
  113. PRINT "───────────┴──────────┴─────────┴─────────────"
  114.  
  115. '* Hinweis: Die Recordlänge ist 1 Byte größer als dies     *
  116. '*          aus den Feldlängen ersichtlich ist, da         *
  117. '*          im ersten Byte des Records die Information     *
  118. '*          für gelöschte Sätze steht (*).                 *
  119.  
  120. PRINT "Recordlänge in Bytes      "; kopf(1).recordb
  121. PRINT
  122. INPUT "Weiter, bitte die <RET> Taste betätigen", tmp$
  123.  
  124. '* lese und decodiere die Datensätze der DBASE III Datei   *
  125.  
  126. PRINT "Datensätze der DBASE III Datei "; filename$
  127. PRINT
  128.  
  129. '*  Hier wird gezeigt, wie der Inhalt der Datei satzweise  *
  130. '* per FOR Schleife gelesen werden kann.                   *
  131.  
  132. CALL GotoBottom                '* auf 1. Satz
  133. FOR i% = 1 TO kopf(1).records  '* Schleife über alle Records
  134.   CALL GetRecord(ein%, satz$)  '* lese Satz
  135.   PRINT satz$                  '* dokumentiere Satz
  136.   CALL Skip                    '* nächster Satz
  137. NEXT i%
  138.  
  139. '* Der Inhalt des letzten Satzes wird verändert und in die *
  140. '* Datenbank zurückgespeichert                             *
  141.  
  142. satz1$ = " " + "Hallo" + MID$(satz$, 7)  '* ändere Feld 1
  143. CALL PutRecord(ein%, satz1$)             '* speichere Satz
  144.  
  145. '* Alternativ besteht die Möglichkeit, die Datei satzweise *
  146. '* zu lesen, bis EOF() erreicht ist. Hierfür dient die     *
  147. '* Funktion DBEof().                                       *
  148.  
  149. PRINT "Lese Datei nochmals"
  150. CALL GotoBottom                        '* auf 1. Satz
  151. CALL DBEof(ein%, status%)              '* EOF erreicht ?
  152. WHILE NOT status%
  153.   CALL GetRecord(ein%, satz$)          '* lese Satz
  154.   CALL Skip                            '* nächster Satz
  155.   CALL DBEof(ein%, status%)            '* EOF erreicht ?
  156. WEND
  157. PRINT "EOF Erreicht"
  158.  
  159. '* Es wird ein leerer Satz angefügt und mit dem Inhalt des *
  160. '* vorletzten Satzes überschreiben                         *
  161.  
  162. PRINT "Leersatz anhängen"
  163. CALL AppendBlank(ein%)               '* Leersatz anhängen
  164. CALL PutRecord(ein%, satz$)          '* alten Satz speichern
  165.  
  166. CLOSE
  167. PRINT "Ende DBDOC"
  168. END
  169.  
  170. fehler:                      '*  Fehlerbehandlung in DBDOC
  171.  
  172. IF ERR = 53 THEN
  173.   PRINT "Die Datei "; filename$; " existiert nicht"
  174. ELSE
  175.   PRINT "Fehler : "; ERR; " unbekannt"
  176.   PRINT "Programmabbruch"
  177. END IF
  178. END                          '* MSDOS Exit
  179. RETURN
  180.  
  181. SUB AppendBlank (handle%)
  182. '* Hänge einen leeren Satz in die DBASE III - Datenbank an *
  183. '* nach dem Aufruf steht der Schreiblesezeiger auf diesem  *
  184. '* Satz, d.h. PutRecord kann direkt Daten speichern.       *
  185.  
  186. SHARED kopf() AS header            '* Kopfdaten
  187. SHARED felder() AS feld, anzahl%   '* Feldbeschreibung
  188. SHARED recnr&                      '* Byte Feldanfang
  189.  
  190.   satz$ = STRING$(kopf(1).recordb, " ") '* Buffer mit Blanks
  191.   recnr& = kopf(1).headerb + 1 + ...
  192.                       ...(kopf(1).recordb * kopf(1).records)
  193.  
  194.   PUT #handle%, recnr&, satz$       '* schreibe Buffer in DB
  195.   satz$ = CHR$(&H1A)                '* create EOF()
  196.   PUT #handle%, , satz$             '* EOF anhängen
  197.  
  198.   kopf(1).datum = CHR$(VAL(MID$(DATE$, 9, 2))) + ...
  199.                ...CHR$(VAL(MID$(DATE$, 1, 2))) + ...
  200.                ...CHR$(VAL(MID$(DATE$, 4, 2)))        '* Tag
  201.   kopf(1).records = kopf(1).records + 1
  202.                                     '* Korrektur Recordzahl
  203.   PUT #handle%, 1, kopf(1)          '* Header aktualisieren
  204. END SUB
  205.  
  206. SUB DBEof (handle%, ende%)
  207. '*  Prüfe, ob EOF() der Datenbank erreicht ist
  208.  
  209. SHARED kopf() AS header                '* Kopfdaten
  210. SHARED felder() AS feld, anzahl%       '* Feldbeschreibung
  211. SHARED recnr&                          '* Byte Feldanfang
  212.  
  213.   IF recnr& >= kopf(1).headerb + 1 + (kopf(1).recordb * ...
  214.               ...kopf(1).records) THEN
  215.    ende% = -1                           '* True
  216.   ELSE
  217.    ende% = 0                            '* False
  218.   END IF
  219. END SUB
  220.  
  221. SUB GetFieldDef (handle%)
  222. '* lese und decodiere die Feldbescheibung der dBase III-   *
  223. '* Datei, es sind maximal 128 Felder zulässig              *
  224.  
  225. SHARED kopf() AS header              '* Kopfdaten
  226. SHARED felder() AS feld, anzahl%     '* Feldbeschreibung
  227. SHARED recnr&                        '* Schreib-/Lesezeiger
  228.  
  229.   anzahl% = ((kopf(1).headerb - 1) / 32) - 1
  230.                                  '* Zahl der Felder
  231.   SEEK #handle%, 33              '* setze Zeiger auf 1. Feld
  232.   FOR i% = 1 TO anzahl%          '* lese n Felddefinitionen
  233.     GET #handle%, , felder(i%)   '* lese Definition Feld
  234.     IF EOF(handle%) THEN         '* Fehler abfangen?
  235.       PRINT "Fehler: Ende Feldbeschreibung erreicht "
  236.       END
  237.     END IF
  238.   NEXT i%
  239.      '* prüfe, ob nächstes Byte das Header Ende signalisiert
  240.   headend$ = " "                   '* Check Header Ende
  241.   GET #handle%, , headend$         '* lese Zeichen
  242.   IF headend$ <> CHR$(&HD) THEN    '* Ende = 0DH
  243.     PRINT "Fehler: Header Ende nicht gefunden"
  244.     END
  245.   END IF
  246.   recnr& = SEEK(handle%)           '* merke Feldanfang
  247. END SUB
  248.  
  249. SUB GetHeader (handle%)
  250. '* Die Routine liest den Dateiheader ein und prüft, ob es  *
  251. '* sich um eine gültige dBase III-Datei handelt. Im Fehler-*
  252. '* fall terminiert das Programm mit einer Meldung.         *
  253. SHARED kopf() AS header
  254.  
  255. GET #handle%, 1, kopf(1)            '* lese Kopf der Datei
  256. IF EOF(handle%) THEN                '* dBase Datei ?
  257.   PRINT "Keine dBase III-Datei, da (EOF) erreicht"
  258.   END
  259. END IF
  260. vers% = ASC(kopf(1).version)        '* decode Versionscode
  261. IF vers% <> &H83 AND vers% <> &H3 THEN
  262.   PRINT "Keine dBase III-Datei, da Header (Code) falsch"
  263.   PRINT "Code : "; HEX$(ASC(kopf(1).version))
  264.   END
  265. ELSE
  266.   IF vers% = &H2 THEN               '* dBase II-Header
  267.     PRINT "dBase II-Header"
  268.     END
  269.   END IF
  270. END IF
  271. END SUB
  272.  
  273. SUB GetRecord (handle%, buffer$)
  274. '* lese einen Satz aus der dBase III-Datenbank und         *
  275. '* gebe das Ergebnis in buffer$ zurück. Die Daten sind     *
  276. '* als ASCII - Text in der Datenbank abgelegt.             *
  277. SHARED kopf() AS header              '* Kopfdaten
  278. SHARED felder() AS feld, anzahl%     '* Feldbeschreibung
  279. SHARED recnr&                        '* Byte Feldanfang
  280.  
  281.   buffer$ = SPACE$(kopf(1).recordb)  '* Buffer auf Satzlänge
  282.   GET #handle%, recnr&, buffer$      '* lese Satz in Buffer
  283. END SUB
  284.  
  285. SUB GotoBottom
  286. '* Positioniere den Schreib- / Lesezeiger auf Satz 1.      *
  287. SHARED kopf() AS header                '* Kopfdaten
  288. SHARED felder() AS feld, anzahl%       '* Feldbeschreibung
  289. SHARED recnr&                          '* Byte Feldanfang
  290.  
  291.   recnr& = kopf(1).headerb + 1         '* erster Satz
  292. END SUB
  293.  
  294. SUB PutRecord (handle%, buffer$)
  295. '* Schreibe einen Satz in die dBase III - Datenbank.       *
  296. '* Die Daten sind als ASCII - Text im Puffer, geordnet     *
  297. '* nach Feldern, abzulegen. Achtung: Die Bufferlänge       *
  298. '* muß gleich der Recordlänge in DBASE sein !!!            *
  299. '* Der Inhalt des Puffers wird an der aktuellen Stelle     *
  300. '* in die Datenbank abgespeichert.                         *
  301. SHARED kopf() AS header                '* Kopfdaten
  302. SHARED felder() AS feld, anzahl%       '* Feldbeschreibung
  303. SHARED recnr&                          '* Byte Feldanfang
  304.  
  305.   IF LEN(buffer$) <> kopf(1).recordb THEN
  306.     PRINT "Fehler: Satzlänge falsch -> soll : ";
  307.     PRINT kopf(1).recordb; " ist : "; LEN(buffer$)
  308.   END IF
  309.   PUT #handle%, recnr&, buffer$     '* schreibe Buffer in DB
  310.  
  311.   kopf(1).datum = CHR$(VAL(MID$(DATE$, 9, 2))) + ...
  312.                ...CHR$(VAL(MID$(DATE$, 1, 2))) + ...
  313.                ...CHR$(VAL(MID$(DATE$, 4, 2)))
  314.   PUT #handle%, 2, kopf(1).datum    '* Datum aktualisieren
  315. END SUB
  316.  
  317. SUB Skip
  318. '* Positioniere den Schreib-/Lesezeiger einen Satz weiter  *
  319. SHARED kopf() AS header                '* Kopfdaten
  320. SHARED felder() AS feld, anzahl%       '* Feldbeschreibung
  321. SHARED recnr&                          '* Byte Feldanfang
  322.  
  323.   recnr& = recnr& + kopf(1).recordb    '* nächster Satz
  324. END SUB
  325.  
  326. '* ------------------------------------------------------- *
  327. '*                  Ende von DBDOC.BAS                     *
  328.