dbftool.lpr 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. program dbftool;
  2. {
  3. Reads and exports DBF files.
  4. Can create a set of 2 demo DBF files in current directory to test with.
  5. Demonstrates creating DBF tables, filling it with data,
  6. and exporting datasets.
  7. }
  8. {$mode objfpc}{$H+}
  9. uses {$IFDEF UNIX} {$IFDEF UseCThreads}
  10. cthreads, {$ENDIF} {$ENDIF}
  11. Classes,
  12. SysUtils,
  13. CustApp,
  14. DB,
  15. dbf,
  16. dbf_fields,
  17. dbf_common,
  18. dateutils,
  19. fpdbexport,
  20. fpcsvexport,
  21. fpdbfexport,
  22. fpfixedexport,
  23. fprtfexport,
  24. fpsimplejsonexport,
  25. fpsimplexmlexport,
  26. fpsqlexport,
  27. fptexexport,
  28. fpxmlxsdexport;
  29. type
  30. { TDBFTool }
  31. TDBFTool = class(TCustomApplication)
  32. private
  33. // Exports recordset to specified format
  34. procedure ExportDBF(var MyDbf: TDbf; ExportFormat: string);
  35. // Executable name without path
  36. function GetExeName: string;
  37. protected
  38. procedure DoRun; override;
  39. public
  40. constructor Create(TheOwner: TComponent); override;
  41. destructor Destroy; override;
  42. procedure WriteHelp; virtual;
  43. end;
  44. // Creates 2 demonstration DBFs in Directory
  45. // with dbase compatibility level TableLevel
  46. procedure CreateDemoDBFs(Directory: string; TableLevel: integer);
  47. // Data structure and data adapted from Firebird employee sample database that
  48. // are also used in the SQLDB tutorials on Lazarus wiki/demo directory.
  49. var
  50. CurDir: string; //current directory
  51. NewDBF: TDBF;
  52. i: integer;
  53. begin
  54. // Get current working directory (need not be application directory):
  55. CurDir := '';
  56. GetDir(0,CurDir);
  57. NewDBF := TDBF.Create(nil);
  58. try
  59. if Directory = '' then
  60. begin
  61. NewDBF.FilePathFull := ExpandFileName(CurDir);
  62. end
  63. else
  64. NewDBF.FilePathFull := ExpandFileName(Directory) {full absolute path};
  65. if TableLevel <= 0 then
  66. NewDBF.TableLevel := 4 {default to DBase IV}
  67. else
  68. NewDBF.TableLevel := TableLevel;
  69. NewDBF.TableName := 'customer.dbf';
  70. writeln('Creating ', NewDBF.TableName, ' with table level ', NewDBF.TableLevel);
  71. if TableLevel >= 30 {Visual FoxPro} then
  72. begin
  73. NewDBF.FieldDefs.Add('CUST_NO', ftAutoInc);
  74. end
  75. else
  76. NewDBF.FieldDefs.Add('CUST_NO', ftInteger);
  77. NewDBF.FieldDefs.Add('CUSTOMER', ftString, 25);
  78. NewDBF.FieldDefs.Add('CITY', ftString, 25);
  79. NewDBF.FieldDefs.Add('COUNTRY', ftString, 15);
  80. NewDBF.CreateTable;
  81. NewDBF.Open;
  82. for i := 1 to 5 do //keep size manageable until we have working files
  83. begin
  84. NewDBF.Append;
  85. if (NewDBF.FieldDefs.Find('CUST_NO').DataType <> ftAutoInc) then
  86. NewDBF.FieldByName('CUST_NO').AsInteger := i;
  87. case i of
  88. 1:
  89. begin
  90. NewDBF.FieldByName('CUSTOMER').AsString := 'Michael Design';
  91. NewDBF.FieldByName('CITY').AsString := 'San Diego';
  92. NewDBF.FieldByName('COUNTRY').AsString := 'USA';
  93. end;
  94. 2: //Let's try a duplicate row
  95. begin
  96. NewDBF.FieldByName('CUSTOMER').AsString := 'Michael Design';
  97. NewDBF.FieldByName('CITY').AsString := 'San Diego';
  98. NewDBF.FieldByName('COUNTRY').AsString := 'USA';
  99. end;
  100. 3:
  101. begin
  102. NewDBF.FieldByName('CUSTOMER').AsString := 'VC Technologies';
  103. NewDBF.FieldByName('CITY').AsString := 'Dallas';
  104. NewDBF.FieldByName('COUNTRY').AsString := 'USA';
  105. end;
  106. 4:
  107. begin
  108. NewDBF.FieldByName('CUSTOMER').AsString := 'Klämpfl, Van Canneyt';
  109. NewDBF.FieldByName('CITY').AsString := 'Boston';
  110. NewDBF.FieldByName('COUNTRY').AsString := 'USA';
  111. end;
  112. 5:
  113. begin
  114. NewDBF.FieldByName('CUSTOMER').AsString := 'Felipe''s Bank';
  115. NewDBF.FieldByName('CITY').AsString := 'Manchester';
  116. NewDBF.FieldByName('COUNTRY').AsString := 'England';
  117. end;
  118. end;
  119. NewDBF.Post;
  120. end;
  121. NewDBF.Close;
  122. finally
  123. NewDBF.Free;
  124. end;
  125. NewDBF := TDBF.Create(nil);
  126. try
  127. if Directory = '' then
  128. NewDBF.FilePathFull := ExpandFileName(CurDir)
  129. else
  130. NewDBF.FilePathFull := ExpandFileName(Directory) {full absolute path};
  131. if TableLevel <= 0 then
  132. NewDBF.TableLevel := 4 {default to DBase IV}
  133. else
  134. NewDBF.TableLevel := TableLevel;
  135. NewDBF.TableName := 'employee.dbf';
  136. writeln('Creating ', NewDBF.TableName, ' with table level ', NewDBF.TableLevel);
  137. if TableLevel >= 30 {Visual FoxPro} then
  138. begin
  139. NewDBF.FieldDefs.Add('EMP_NO', ftAutoInc);
  140. end
  141. else
  142. NewDBF.FieldDefs.Add('EMP_NO', ftInteger);
  143. NewDBF.FieldDefs.Add('FIRST_NAME', ftString, 15);
  144. NewDBF.FieldDefs.Add('LAST_NAME', ftString, 20);
  145. NewDBF.FieldDefs.Add('PHONE_EXT', ftString, 4);
  146. NewDBF.FieldDefs.Add('JOB_CODE', ftString, 5);
  147. NewDBF.FieldDefs.Add('JOB_GRADE', ftInteger);
  148. NewDBF.FieldDefs.Add('JOB_COUNTR', ftString, 15); //Note 10 character limit for table/field names in most DBases
  149. NewDBF.FieldDefs.Add('SALARY', ftFloat);
  150. NewDBF.CreateTable;
  151. NewDBF.Open;
  152. for i := 1 to 5 do //keep size manageable until we have working files
  153. begin
  154. NewDBF.Append;
  155. if (NewDBF.FieldDefs.Find('EMP_NO').DataType <> ftAutoInc) then
  156. NewDBF.FieldByName('EMP_NO').AsInteger := i;
  157. case i of
  158. 1:
  159. begin
  160. NewDBF.FieldByName('FIRST_NAME').AsString := 'William';
  161. NewDBF.FieldByName('LAST_NAME').AsString := 'Shatner';
  162. NewDBF.FieldByName('PHONE_EXT').AsString := '1702';
  163. NewDBF.FieldByName('JOB_CODE').AsString := 'CEO';
  164. NewDBF.FieldByName('JOB_GRADE').AsInteger := 1;
  165. NewDBF.FieldByName('JOB_COUNTR').AsString := 'USA';
  166. NewDBF.FieldByName('SALARY').AsFloat := 48000;
  167. end;
  168. 2:
  169. begin
  170. NewDBF.FieldByName('FIRST_NAME').AsString := 'Ivan';
  171. NewDBF.FieldByName('LAST_NAME').AsString := 'Ishenin';
  172. NewDBF.FieldByName('PHONE_EXT').AsString := '9802';
  173. NewDBF.FieldByName('JOB_CODE').AsString := 'Eng';
  174. NewDBF.FieldByName('JOB_GRADE').AsInteger := 2;
  175. NewDBF.FieldByName('JOB_COUNTR').AsString := 'Russia';
  176. NewDBF.FieldByName('SALARY').AsFloat := 38000;
  177. end;
  178. 3:
  179. begin
  180. NewDBF.FieldByName('FIRST_NAME').AsString := 'Erin';
  181. NewDBF.FieldByName('LAST_NAME').AsString := 'Powell';
  182. NewDBF.FieldByName('PHONE_EXT').AsString := '1703';
  183. NewDBF.FieldByName('JOB_CODE').AsString := 'Admin';
  184. NewDBF.FieldByName('JOB_GRADE').AsInteger := 2;
  185. NewDBF.FieldByName('JOB_COUNTR').AsString := 'USA';
  186. NewDBF.FieldByName('SALARY').AsFloat := 45368;
  187. end;
  188. 4:
  189. begin
  190. NewDBF.FieldByName('FIRST_NAME').AsString := 'Margaret';
  191. NewDBF.FieldByName('LAST_NAME').AsString := 'Tetchy';
  192. NewDBF.FieldByName('PHONE_EXT').AsString := '3804';
  193. NewDBF.FieldByName('JOB_CODE').AsString := 'Eng';
  194. NewDBF.FieldByName('JOB_GRADE').AsInteger := 3;
  195. NewDBF.FieldByName('JOB_COUNTR').AsString := 'England';
  196. NewDBF.FieldByName('SALARY').AsFloat := 28045;
  197. end;
  198. 5:
  199. begin
  200. NewDBF.FieldByName('FIRST_NAME').AsString := 'Sergey';
  201. NewDBF.FieldByName('LAST_NAME').AsString := 'Bron';
  202. NewDBF.FieldByName('PHONE_EXT').AsString := '3807';
  203. NewDBF.FieldByName('JOB_CODE').AsString := 'Admin';
  204. NewDBF.FieldByName('JOB_GRADE').AsInteger := 3;
  205. NewDBF.FieldByName('JOB_COUNTR').AsString := 'England';
  206. NewDBF.FieldByName('SALARY').AsFloat := 24468;
  207. end;
  208. end;
  209. NewDBF.Post;
  210. end;
  211. NewDBF.Close;
  212. finally
  213. NewDBF.Free;
  214. end;
  215. end;
  216. // Gets list of all .dbf files in current directory and its subdirectories.
  217. procedure GetDBFList(Results: TStringList);
  218. var
  219. r: TSearchRec;
  220. begin
  221. results.Clear;
  222. if FindFirst('*', faAnyFile - faDirectory -
  223. {$WARNINGS OFF}
  224. faVolumeID - faSymLink
  225. {$WARNINGS ON}
  226. , r) = 0 then
  227. begin
  228. repeat
  229. begin
  230. // Cater for both case-sensitive and case-insensitive filesystems
  231. // ignore any directories
  232. if ((r.Attr and faDirectory) <> faDirectory) and
  233. (LowerCase(ExtractFileExt(r.Name))='.dbf') then
  234. results.add(expandfilename(r.Name));
  235. end;
  236. until (FindNext(r) <> 0);
  237. findclose(r);
  238. end;
  239. end;
  240. // Convert binary field contents to strings with hexadecimal representation.
  241. // Useful for displaying binary field contents.
  242. function BinFieldToHex(BinarySource: TField): string;
  243. var
  244. HexValue: PChar;
  245. begin
  246. Result := '';
  247. HexValue := StrAlloc(Length(BinarySource.AsBytes));
  248. try
  249. try
  250. BinToHex(PChar(BinarySource.AsBytes), HexValue, Length(BinarySource.AsBytes));
  251. Result := 'size: ' + IntToStr(Length(BinarySource.AsBytes)) + '; hex: ' + HexValue;
  252. except
  253. on E: Exception do
  254. begin
  255. Result := 'exception: ' + E.ClassName + '/' + E.Message;
  256. end;
  257. end;
  258. finally
  259. StrDispose(HexValue);
  260. end;
  261. end;
  262. // Writes contents of available records to screen
  263. procedure PrintRecords(DBf: TDBf);
  264. var
  265. i: integer;
  266. RecordCount: integer;
  267. begin
  268. Dbf.First;
  269. RecordCount:=0;
  270. while not (Dbf.EOF) do
  271. begin
  272. RecordCount := RecordCount + 1;
  273. writeln('Record ' + IntToStr(RecordCount));
  274. for i := 0 to DBf.Fields.Count - 1 do
  275. begin
  276. if DBF.fields[i].IsNull then
  277. writeln('Field ', DBf.Fields[i].FieldName, ' is ***NULL***')
  278. else
  279. if DBF.Fields[i].DataType in [ftVarBytes, ftBytes] then
  280. writeln('Field ', DBF.Fields[i].FieldName, ' has value: binary ' + BinFieldToHex(DBF.Fields[i]))
  281. else
  282. writeln('Field ', DBf.Fields[i].FieldName, ' has value: ' + DBf.fields[i].AsString);
  283. end;
  284. DBF.Next;
  285. writeln('');
  286. end;
  287. end;
  288. { TDBFTool }
  289. procedure TDBFTool.ExportDBF(var MyDbf: TDbf; ExportFormat: string);
  290. var
  291. ExportSettings: TCustomExportFormatSettings;
  292. Exporter: TCustomFileExporter;
  293. begin
  294. try
  295. case UpperCase(ExportFormat) of
  296. 'ACCESS', 'MSACCESS':
  297. begin
  298. Exporter := TXMLXSDExporter.Create(nil);
  299. ExportSettings := TXMLXSDFormatSettings.Create(true);
  300. (ExportSettings as TXMLXSDFormatSettings).CreateXSD := true;
  301. (ExportSettings as TXMLXSDFormatSettings).ExportFormat :=
  302. AccessCompatible;
  303. (ExportSettings as TXMLXSDFormatSettings).DecimalSeparator := '.';
  304. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.xml');
  305. end;
  306. 'ADO', 'ADONET', 'ADO.NET':
  307. begin
  308. Exporter := TXMLXSDExporter.Create(nil);
  309. ExportSettings := TXMLXSDFormatSettings.Create(true);
  310. (ExportSettings as TXMLXSDFormatSettings).CreateXSD := true;
  311. (ExportSettings as TXMLXSDFormatSettings).ExportFormat :=
  312. ADONETCompatible;
  313. (ExportSettings as TXMLXSDFormatSettings).DecimalSeparator := '.';
  314. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.xml');
  315. end;
  316. 'CSVEXCEL', 'EXCELCSV', 'CREATIVYST':
  317. begin
  318. Exporter := TCSVExporter.Create(nil);
  319. ExportSettings := TCSVFormatSettings.Create(true);
  320. (ExportSettings as TCSVFormatSettings).RowDelimiter:=LineEnding;
  321. //todo: delimiter?
  322. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.csv');
  323. end;
  324. 'CSV', 'CSVRFC4180', 'CSVLIBRE', 'CSVLIBREOFFICE', 'CSVOPENOFFICE':
  325. begin
  326. Exporter := TCSVExporter.Create(nil);
  327. ExportSettings := TCSVFormatSettings.Create(true);
  328. (ExportSettings as TCSVFormatSettings).DecimalSeparator := '.';
  329. (ExportSettings as TCSVFormatSettings).StringQuoteChar := '"';
  330. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.csv');
  331. end;
  332. 'DATASET', 'DELPHI':
  333. begin
  334. Exporter := TXMLXSDExporter.Create(nil);
  335. ExportSettings := TXMLXSDFormatSettings.Create(true);
  336. (ExportSettings as TXMLXSDFormatSettings).ExportFormat :=
  337. DelphiClientDataset;
  338. (ExportSettings as TXMLXSDFormatSettings).DecimalSeparator := '.';
  339. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.xml');
  340. end;
  341. 'EXCEL', 'EXCELXML':
  342. begin
  343. Exporter := TXMLXSDExporter.Create(nil);
  344. ExportSettings := TXMLXSDFormatSettings.Create(true);
  345. (ExportSettings as TXMLXSDFormatSettings).ExportFormat := ExcelCompatible;
  346. (ExportSettings as TXMLXSDFormatSettings).DecimalSeparator := '.';
  347. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.xml');
  348. end;
  349. 'JSON':
  350. begin
  351. Exporter := TSimpleJSONExporter.Create(nil);
  352. ExportSettings := TSimpleJSONFormatSettings.Create(true);
  353. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.json');
  354. end;
  355. 'SIMPLEXML', 'XML':
  356. begin
  357. Exporter := TSimpleXMLExporter.Create(nil);
  358. ExportSettings := TSimpleXMLFormatSettings.Create(true);
  359. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.xml');
  360. end;
  361. 'RTF':
  362. begin
  363. Exporter := TRTFExporter.Create(nil);
  364. ExportSettings := TSimpleXMLFormatSettings.Create(true);
  365. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.rtf');
  366. end;
  367. 'SQL':
  368. begin
  369. Exporter := TSQLExporter.Create(nil);
  370. ExportSettings := TSQLFormatSettings.Create(true);
  371. (ExportSettings as TSQLFormatSettings).QuoteChar := '"';
  372. (ExportSettings as TSQLFormatSettings).DecimalSeparator := '.';
  373. (ExportSettings as TSQLFormatSettings).TableName := ChangeFileExt(MyDBF.TableName,'');
  374. (ExportSettings as TSQLFormatSettings).DateFormat := 'yyyy"-"mm"-"dd'; //ISO 8601, yyyy-mm-dd
  375. (ExportSettings as TSQLFormatSettings).TimeFormat := 'hh":"nn":"ss'; //ISO 8601, hh:mm:ss;
  376. (ExportSettings as TSQLFormatSettings).DateTimeFormat :=
  377. (ExportSettings as TSQLFormatSettings).DateFormat + '"T"' + (ExportSettings as TSQLFormatSettings).TimeFormat; //ISO 8601
  378. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.sql');
  379. end;
  380. 'TEX', 'LATEX':
  381. begin
  382. Exporter := TTeXExporter.Create(nil);
  383. ExportSettings := TTeXExportFormatSettings.Create(true);
  384. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.tex');
  385. end;
  386. 'TEXT', 'FIXED', 'FIXEDTEXT':
  387. begin
  388. Exporter := TFixedLengthExporter.Create(nil);
  389. ExportSettings := nil;
  390. Exporter.FileName := MyDBF.FilePathFull + ChangeFileExt(MyDBF.TableName, '.txt');
  391. end
  392. else
  393. begin
  394. writeln('***Error: Unknown export format ' + ExportFormat + ' specified' + '. Aborting');
  395. Exporter := nil;
  396. ExportSettings := nil;
  397. Terminate;
  398. Exit;
  399. end;
  400. end;
  401. if assigned(ExportSettings) then
  402. Exporter.FormatSettings := ExportSettings;
  403. Exporter.Dataset := MyDBF;
  404. MyDBF.First; // we've just read the last record - make sure export starts at beginning
  405. Exporter.Execute;
  406. writeln('Completed export to ' + Exporter.FileName);
  407. finally
  408. if assigned(Exporter) then
  409. Exporter.Free;
  410. if assigned(ExportSettings) then
  411. ExportSettings.Free;
  412. end;
  413. end;
  414. function TDBFTool.GetExeName: string;
  415. begin
  416. result := ExtractFileName(ExeName);
  417. end;
  418. procedure TDBFTool.DoRun;
  419. var
  420. DBFs: TStringList;
  421. Demo: boolean;
  422. ErrorMsg: string;
  423. FileNo: integer;
  424. MyDbf: TDbf;
  425. TableLevel: integer;
  426. begin
  427. // quick check parameters
  428. ErrorMsg := CheckOptions('h', 'createdemo exportformat: help tablelevel:');
  429. if ErrorMsg <> '' then
  430. begin
  431. ShowException(Exception.Create(ErrorMsg));
  432. Terminate;
  433. Exit;
  434. end;
  435. // parse parameters
  436. if HasOption('h', 'help') then
  437. begin
  438. WriteHelp;
  439. Terminate;
  440. Exit;
  441. end;
  442. DBFs := TStringList.Create;
  443. try
  444. Demo := false;
  445. if HasOption('createdemo') then
  446. Demo := true;
  447. TableLevel := 4; //DBF
  448. if HasOption('tablelevel') then
  449. TableLevel := StrToIntDef(GetOptionValue('tablelevel'), 4);
  450. if Demo then
  451. begin
  452. try
  453. CreateDemoDBFs('', TableLevel);
  454. except
  455. on E: Exception do
  456. begin
  457. writeln('*** Error creating demo databases: ' + E.Message);
  458. Terminate;
  459. Exit;
  460. end;
  461. end;
  462. end;
  463. // Process all dbfs if no files specified
  464. if DBFs.Count = 0 then
  465. GetDBFList(DBFs);
  466. if DBFs.Count = 0 then
  467. begin
  468. writeln('Could not find any dbf files.');
  469. writeln('Use ' + GetExeName + ' --createdemo to create some test DBF files.');
  470. end;
  471. for FileNo := 0 to DBFs.Count - 1 do
  472. begin
  473. if not (fileexists(DBFs[FileNo])) then
  474. begin
  475. writeln('Sorry, file ',DBFs[FileNo],' does not exist. Ignoring it.');
  476. continue;
  477. end;
  478. MyDbf := TDbf.Create(nil);
  479. try
  480. try
  481. MyDbf.FilePath := ExtractFilePath(DBFs[FileNo]);
  482. MyDbf.TableName := ExtractFileName(DBFs[FileNo]);
  483. MyDbf.ReadOnly := true;
  484. writeln('*** Opening: ' + DBFs[FileNo]);
  485. MyDbf.Open;
  486. writeln('Database tablelevel: ' + IntToStr(MyDbf.TableLevel));
  487. writeln('Database codepage: ' + IntToStr(MyDBF.CodePage));
  488. PrintRecords(MyDBF);
  489. if HasOption('exportformat') then
  490. begin
  491. try
  492. ExportDBF(MyDbf,GetOptionValue('exportformat'));
  493. except
  494. on E: Exception do
  495. begin
  496. writeln('*** Problem exporting file ', FileNo, ': ', E.Message);
  497. end;
  498. end;
  499. end;
  500. MyDbf.Close;
  501. except
  502. on E: Exception do
  503. begin
  504. writeln('*** Error reading file ', FileNo, ': ', E.Message);
  505. end;
  506. end;
  507. finally
  508. MyDbf.Free;
  509. end;
  510. end;
  511. finally
  512. DBFs.Free;
  513. end;
  514. // stop program loop
  515. Terminate;
  516. end;
  517. constructor TDBFTool.Create(TheOwner: TComponent);
  518. begin
  519. inherited Create(TheOwner);
  520. StopOnException := true;
  521. end;
  522. destructor TDBFTool.Destroy;
  523. begin
  524. inherited Destroy;
  525. end;
  526. procedure TDBFTool.WriteHelp;
  527. begin
  528. writeln('Read/print all dbfs in current directory');
  529. writeln('Usage info: ', GetExeName, ' -h');
  530. writeln('');
  531. writeln('--createdemo create demo database in current directory');
  532. writeln('--tablelevel=<n> optional: desired tablelevel for demo db');
  533. writeln(' 3 DBase III');
  534. writeln(' 4 DBase IV (default if no tablelevel given)');
  535. writeln(' 7 Visual DBase 7');
  536. writeln(' 25 FoxPro 2.x');
  537. writeln(' 30 Visual FoxPro');
  538. writeln('--exportformat=<text> export dbfs to format. Format can be:');
  539. writeln(' access Microsoft Access XML');
  540. writeln(' adonet ADO.Net dataset XML');
  541. writeln(' csvexcel Excel/Creativyst format CSV text file ');
  542. writeln(' (with locale dependent output)');
  543. writeln(' csvRFC4180 LibreOffice/RFC4180 format CSV text file');
  544. writeln(' dataset Delphi dataset XML');
  545. writeln(' excel Microsoft Excel XML');
  546. writeln(' fixedtext Fixed length text file');
  547. writeln(' json JSON file');
  548. writeln(' rtf Rich Text Format');
  549. writeln(' simplexml Simple XML');
  550. writeln(' sql SQL insert statements');
  551. writeln(' tex LaTeX file');
  552. end;
  553. var
  554. Application: TDBFTool;
  555. begin
  556. Application := TDBFTool.Create(nil);
  557. Application.Title := 'DBFTool';
  558. Application.Run;
  559. Application.Free;
  560. end.