dbftool.lpr 20 KB

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