PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/BankConvert/bancomain.pas

https://bitbucket.org/reiniero/smalltools
Pascal | 408 lines | 298 code | 33 blank | 77 comment | 13 complexity | 099024b6ae5540e53ffb0be755fde89e MD5 | raw file
  1. unit bancomain;
  2. { Main unit for banco bank account info/management application
  3. Copyright (c) 2013 Reinier Olislagers
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to
  6. deal in the Software without restriction, including without limitation the
  7. rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. sell copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in
  11. all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  17. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  18. IN THE SOFTWARE.
  19. }
  20. {$mode objfpc}{$H+}
  21. interface
  22. uses
  23. Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  24. DBGrids, StdCtrls, EditBtn,
  25. bankconverter, transactioninfo, db,bufdataset,
  26. databaseexporter, Grids {$ifdef mswindows},shlobj{$endif};
  27. type
  28. { TForm1 }
  29. TForm1 = class(TForm)
  30. ExportDirectory: TDirectoryEdit;
  31. ExportFormatChoice: TListBox;
  32. DeleteButton: TButton;
  33. InputFile: TFileNameEdit;
  34. Label1: TLabel;
  35. ExportButton: TButton;
  36. DataSource1: TDataSource;
  37. DBGrid1: TDBGrid;
  38. Label2: TLabel;
  39. Label3: TLabel;
  40. Memo1: TMemo;
  41. ImportButton: TButton;
  42. procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  43. DataCol: Integer; Column: TColumn; State: TGridDrawState);
  44. procedure DeleteButtonClick(Sender: TObject);
  45. procedure ExportFormatChoiceSelectionChange(Sender: TObject; User: boolean);
  46. procedure FormCreate(Sender: TObject);
  47. procedure FormDestroy(Sender: TObject);
  48. procedure ImportButtonClick(Sender: TObject);
  49. procedure ExportButtonClick(Sender: TObject);
  50. private
  51. { private declarations }
  52. FChosenFormat: TExportFormats; //User-selected export format
  53. FData: TBufDataset;
  54. procedure SetChosenFormat(FormatText: string);
  55. public
  56. { public declarations }
  57. end;
  58. var
  59. Form1: TForm1;
  60. implementation
  61. {$R *.lfm}
  62. { TForm1 }
  63. procedure TForm1.FormCreate(Sender: TObject);
  64. var
  65. {$ifdef mswindows}
  66. InitialDir: Array[0..MaxPathLen] of Char; //Allocate memory for api call
  67. {$else}
  68. InitialDir: string;
  69. {$endif}
  70. begin
  71. ExportFormatChoice.Items.Add('ADO.Net dataset XML');
  72. ExportFormatChoice.Items.Add('CSV');
  73. ExportFormatChoice.Items.Add('DBF/DBase IV');
  74. ExportFormatChoice.Items.Add('DBF/DBase7');
  75. ExportFormatChoice.Items.Add('Firebird embedded');
  76. ExportFormatChoice.Items.Add('Latex');
  77. ExportFormatChoice.Items.Add('LibreOffice Calc');
  78. {$IFDEF MSWINDOWS}
  79. ExportFormatChoice.Items.Add('Microsoft Access');
  80. {$ENDIF}
  81. ExportFormatChoice.Items.Add('Microsoft Access XML');
  82. ExportFormatChoice.Items.Add('Microsoft Excel (xls)');
  83. ExportFormatChoice.Items.Add('Microsoft Excel (xlsx)');
  84. ExportFormatChoice.Items.Add('Sqlite');
  85. // Preselect CSV format, which should handle arbitrary length data well:
  86. FChosenFormat:=efXLS;
  87. ExportFormatChoice.ItemIndex := ExportFormatChoice.Items.IndexOf('Microsoft Excel (xls)');
  88. FData:=TBufDataset.Create(nil);
  89. // Let's forget about hash; it's not useful for end users
  90. //FData.FieldDefs.Add('hashid',ftString,32);
  91. FData.FieldDefs.Add('account',ftMemo);
  92. FData.FieldDefs.Add('currency',ftString,3); //ISO currency 3 character
  93. FData.FieldDefs.Add('amount',ftFloat); //not using currency as that inserts currency signs in csv export etc
  94. FData.FieldDefs.Add('bookdate',ftDateTime);
  95. FData.FieldDefs.Add('contraaccount',ftMemo);
  96. FData.FieldDefs.Add('memo',ftMemo);
  97. FData.CreateDataset;
  98. FData.Active:=true;
  99. DataSource1.DataSet:=FData;
  100. DBGrid1.DataSource:=DataSource1;
  101. InitialDir:='';
  102. {$ifdef mswindows}
  103. SHGetSpecialFolderPath(0,InitialDir,CSIDL_DESKTOPDIRECTORY,false);
  104. {$endif}
  105. {$ifdef darwin} //osx
  106. if InitialDir='' then
  107. InitialDir:=ExpandUNCFileNameUTF8('~/Desktop');
  108. {$endif}
  109. {$ifdef unix} //Linux, bsd
  110. if InitialDir='' then
  111. InitialDir:=ExpandUNCFileNameUTF8('~');
  112. {$endif}
  113. ExportDirectory.Directory:=InitialDir;
  114. Memo1.Visible:={$ifdef debug}true{$else}false{$endif};
  115. end;
  116. procedure TForm1.DeleteButtonClick(Sender: TObject);
  117. begin
  118. if MessageDlg('Delete data','Do you want to delete all imported transactions?',mtWarning,mbOkCancel,'')<>mrOk then
  119. exit;
  120. // Naive approach:
  121. while not(FData.EOF) do
  122. begin
  123. FData.Delete;
  124. end;
  125. end;
  126. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  127. DataCol: Integer; Column: TColumn; State: TGridDrawState);
  128. // Draw memo text instead of (Memo), draw other text as usual.
  129. // Requires grid DefaultDrawing to be false
  130. {
  131. Basically copied the existing DefaultDrawColumnCell procedure
  132. but tested for memo first. If no memo, pass on to default procedure.
  133. Maybe slower, more complicated, but it allows for changes in the
  134. core Lazarus DefaultDrawColumnCell procedure.
  135. Thanks to User137 & ludob on the Lazarus forum
  136. }
  137. var
  138. //determine if we're going to override normal Lazarus draw routines
  139. OverrideDraw: boolean;
  140. OurDisplayString: string;
  141. CurrentField: TField;
  142. begin
  143. OverrideDraw := false;
  144. // Make sure selected cells are highlighted
  145. if (gdSelected in State) then
  146. begin
  147. (Sender as TDBGrid).Canvas.Brush.Color := clHighlight;
  148. end
  149. else
  150. begin
  151. (Sender as TDBGrid).Canvas.Brush.Color := (Sender as TDBGrid).Color;
  152. end;
  153. // Draw background in any case - thanks to ludob on the forum:
  154. (Sender as TDBGrid).Canvas.FillRect(Rect);
  155. //Foreground
  156. try
  157. CurrentField := Column.Field;
  158. if CurrentField.DataType = ftMemo then
  159. begin
  160. OverrideDraw := true;
  161. end;
  162. except
  163. on E: Exception do
  164. begin
  165. // We might have an inactive datalink or whatever,
  166. // in that case, pass on our problems to the LCL
  167. OverrideDraw := false;
  168. end;
  169. end;
  170. if OverrideDraw = false then
  171. begin
  172. // Call normal procedure to handle drawing for us.
  173. (Sender as TDBGrid).DefaultDrawColumnCell(Rect, DataCol, Column, State);
  174. end
  175. else
  176. begin
  177. // Get to work displaying our memo contents
  178. // Basically shamelessly ripped from
  179. // DefaultDrawColumnCell
  180. OurDisplayString := '';
  181. if CurrentField <> nil then
  182. begin
  183. //DO display memo ;) OurDisplayString is string to be displayed
  184. try
  185. OurDisplayString := CurrentField.AsString; //DisplayText will only show (Memo)
  186. except
  187. // Ignore errors; use empty string as specified above
  188. end;
  189. end;
  190. //Actual foreground drawing, taken from Grids.DrawCellText coding:
  191. (Sender as TDBGrid).Canvas.TextRect(Rect, Rect.Left, Rect.Top, OurDisplayString);
  192. end;
  193. end;
  194. procedure TForm1.ExportFormatChoiceSelectionChange(Sender: TObject;
  195. User: boolean);
  196. begin
  197. SetChosenFormat(ExportFormatChoice.Items[ExportFormatChoice.ItemIndex]);
  198. end;
  199. procedure TForm1.FormDestroy(Sender: TObject);
  200. begin
  201. //todo: save
  202. if FData.Active then
  203. FData.Close;
  204. FData.Free;
  205. end;
  206. procedure TForm1.ImportButtonClick(Sender: TObject);
  207. var
  208. i:integer;
  209. Convert:TBankConverter;
  210. begin
  211. if (FileExistsUTF8(InputFile.Text) = false) then
  212. begin
  213. ShowMessage('No valid input file. Aborting.');
  214. exit;
  215. end;
  216. Convert:=TBankConverter.Create;
  217. try
  218. Convert.InputFile:=InputFile.Text;
  219. Convert.ImportTransactions;
  220. for i:=0 to Convert.Transactions.Count-1 do
  221. begin
  222. FData.Append;
  223. //FData.FieldByName('hashid').AsString:=Convert.Transactions[i].HashID;
  224. FData.FieldByName('account').AsString:=Convert.Transactions[i].Account;
  225. FData.FieldByName('currency').AsString:=Convert.Transactions[i].Currency;
  226. FData.FieldByName('amount').AsFloat:=Convert.Transactions[i].Amount;
  227. FData.FieldByName('bookdate').AsDateTime:=Convert.Transactions[i].BookDate;
  228. FData.FieldByName('contraaccount').AsString:=Convert.Transactions[i].ContraAccount;
  229. FData.FieldByName('memo').AsString:=Convert.Transactions[i].Memo;
  230. FData.Post;
  231. end;
  232. finally
  233. Convert.Free;
  234. end;
  235. end;
  236. procedure TForm1.ExportButtonClick(Sender: TObject);
  237. const
  238. ExportName='transactions';
  239. var
  240. Exporter: TDatabaseExporter;
  241. {$ifdef debug}
  242. i: integer;
  243. Fields: integer;
  244. {$endif}
  245. begin
  246. Memo1.Clear;
  247. {$IFDEF DEBUG}
  248. Memo1.Lines.Add('Dataset recordcount: '+inttostr(FData.RecordCount));
  249. FData.First;
  250. for i:=0 to FData.RecordCount-1 do
  251. begin
  252. Memo1.Lines.Add('Record no '+inttostr(i+1));
  253. for Fields:=0 to FData.Fields.Count-1 do
  254. begin
  255. Memo1.Lines.Add('Field '+FData.Fields[Fields].FieldName+'=*'+FData.Fields[Fields].AsString+'*');
  256. end;
  257. Memo1.Lines.Add('');
  258. FData.Next
  259. end;
  260. {$ENDIF}
  261. Exporter := TDatabaseExporter.Create;
  262. try
  263. Exporter.BaseFileName := IncludeTrailingPathDelimiter(ExportDirectory.Directory)+ExportName;
  264. Exporter.AddDataset(FData, ExportName);
  265. case FChosenFormat of
  266. {$IFDEF MSWINDOWS}
  267. efAccess:
  268. begin
  269. Exporter.ExportFormat := efAccess;
  270. end;
  271. {$ENDIF}
  272. efAccessXML:
  273. begin
  274. Exporter.ExportFormat := efAccessXML;
  275. end;
  276. efADONetXML:
  277. begin
  278. Exporter.ExportFormat := efADONetXML;
  279. end;
  280. efCalc:
  281. begin
  282. Exporter.ExportFormat := efCalc;
  283. end;
  284. efCSV:
  285. begin
  286. Exporter.ExportFormat := efCSV;
  287. end;
  288. efDBF4:
  289. begin
  290. Exporter.ExportFormat := efDBF4;
  291. end;
  292. efDBF7:
  293. begin
  294. Exporter.ExportFormat := efDBF7;
  295. end;
  296. efXLS:
  297. begin
  298. Exporter.ExportFormat := efXLS;
  299. end;
  300. efXLSX:
  301. begin
  302. Exporter.ExportFormat := efXLSX;
  303. end;
  304. efFirebird:
  305. begin
  306. Exporter.ExportFormat := efFirebird;
  307. end;
  308. efLatex:
  309. begin
  310. Exporter.ExportFormat := efLatex;
  311. end;
  312. efSQLite:
  313. begin
  314. Exporter.ExportFormat := efSQLite;
  315. end;
  316. else
  317. raise Exception.CreateFmt('Unknown export format code %d. Please fix the '
  318. +'program code.',
  319. [FChosenFormat]);
  320. end;
  321. try
  322. Exporter.ExportData;
  323. ShowMessage('Exported transactions to file starting with '+Exporter.BaseFileName);
  324. except
  325. on E: Exception do
  326. begin
  327. ShowMessage('Error exporting data. Technical details:'+E.Message);
  328. end;
  329. end;
  330. finally
  331. Exporter.Free;
  332. end;
  333. end;
  334. procedure TForm1.SetChosenFormat(FormatText: string);
  335. begin
  336. case UpperCase(FormatText) of
  337. {$IFDEF MSWINDOWS}
  338. 'MICROSOFT ACCESS', 'ACCESS', 'JET':
  339. FChosenFormat:=efAccess;
  340. {$ENDIF}
  341. 'MICROSOFT ACCESS XML', 'ACCESS XML', 'ACCESSXML':
  342. FChosenFormat:=efAccessXML;
  343. 'ADO.NET DATASET XML', 'ADO.NET XML', 'ADO.NET', 'ADONET':
  344. FChosenFormat:=efADONetXML;
  345. 'CSV', 'DELIMITED':
  346. FChosenFormat:=efCSV;
  347. 'DBF/DBASE IV', 'DB4', 'DBIV', 'DBF4', 'DBFIV', 'DBASEIV', 'DBASE4':
  348. FChosenFormat:=efDBF4;
  349. 'DBF/DBASE7', 'DB7', 'DBF7', 'DBASE7':
  350. FChosenFormat:=efDBF7;
  351. 'LIBREOFFICE CALC', 'CALC', 'ODS':
  352. FChosenFormat:=efCalc;
  353. 'MICROSOFT EXCEL (XLS)', 'XLS':
  354. FChosenFormat:=efXLS;
  355. // Use the Microsoft Excel alias for this format due to
  356. // support for >32767 characters per cell
  357. 'MICROSOFT EXCEL (XLSX)', 'MICROSOFT EXCEL', 'EXCEL', 'XLSX':
  358. FChosenFormat:=efXLSX;
  359. 'FIREBIRD EMBEDDED', 'FIREBIRD':
  360. FChosenFormat:=efFirebird;
  361. 'LATEX':
  362. FChosenFormat:=efLatex;
  363. 'SQLITE', 'SQLITE3':
  364. FChosenFormat:=efSQLite;
  365. else
  366. raise Exception.CreateFmt('Unknown export format %s. Please fix the '
  367. +'program code.',
  368. [FormatText]);
  369. end;
  370. end;
  371. end.