fpdbexport.pp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. unit fpDBExport;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, DB;
  6. Type
  7. TCustomDatasetExporter = Class;
  8. // Quote string fields if value contains a space or delimiter char.
  9. TQuoteString = (qsAlways,qsSpace,qsDelimiter);
  10. TQuoteStrings = Set of TQuoteString;
  11. TAlignField = (afLeft,afRight);
  12. { TExportFieldItem }
  13. TExportFieldItem = Class(TCollectionItem)
  14. private
  15. FEnabled: Boolean;
  16. FField: TField;
  17. FFieldName: String;
  18. FExportedName: String;
  19. function GetExportedName: String;
  20. function GetExporter: TCustomDatasetExporter;
  21. procedure SetExportedName(const AValue: String);
  22. Protected
  23. Procedure BindField (ADataset : TDataset); virtual;
  24. procedure SetFieldName(const AValue: String); virtual;
  25. Public
  26. Constructor Create(ACollection : TCollection); override;
  27. Procedure Assign(Source : TPersistent); override;
  28. Property Field : TField Read FField;
  29. Property Exporter : TCustomDatasetExporter Read GetExporter;
  30. Published
  31. Property Enabled : Boolean Read FEnabled Write FEnabled default True;
  32. Property FieldName : String Read FFieldName Write SetFieldName;
  33. Property ExportedName : String Read GetExportedName Write SetExportedName;
  34. end;
  35. { TExportFields }
  36. TExportFields = Class(TCollection)
  37. private
  38. FExporter : TCustomDatasetExporter;
  39. function GetFieldItem(Index : Integer): TExportFieldItem;
  40. procedure SetFieldItem(Index : Integer; const AValue: TExportFieldItem);
  41. Public
  42. Function IndexOfField(Const AFieldName : String) : Integer;
  43. Function IndexOfExportedName(Const AFieldName : String) : Integer;
  44. Function FindExportField(Const AFieldName : String) : TExportFieldItem;
  45. Function FindExportName(Const AFieldName : String) : TExportFieldItem;
  46. Function AddField(Const AFieldName : String) : TExportFieldItem; virtual;
  47. Property Fields[Index : Integer] : TExportFieldItem Read GetFieldItem Write SetFieldItem; Default;
  48. Property Exporter : TCustomDatasetExporter Read FExporter;
  49. end;
  50. { TCustomExportFormatSettings }
  51. TCustomExportFormatSettings = Class(TPersistent)
  52. private
  53. FBooleanFalse : String;
  54. FBooleanTrue : String;
  55. FCurrencyDigits: Integer;
  56. FCurrencySymbol : String;
  57. FDateFormat : String;
  58. FIntegerFormat: String;
  59. FTimeFormat : String;
  60. FDateTimeFormat : String;
  61. FDecimalSeparator: Char;
  62. FUseDisplayText : Boolean;
  63. Protected
  64. Procedure InitSettings; virtual;
  65. Property UseDisplayText : Boolean Read FUseDisplayText Write FUseDisplayText;
  66. Property IntegerFormat : String Read FIntegerFormat Write FIntegerFormat;
  67. Property DecimalSeparator : Char Read FDecimalSeparator Write FDecimalSeparator;
  68. Property CurrencySymbol : String Read FCurrencySymbol Write FCurrencySymbol;
  69. Property CurrencyDigits : Integer Read FCurrencyDigits Write FCurrencyDigits;
  70. Property BooleanTrue : String Read FBooleanTrue Write FBooleanTrue;
  71. Property BooleanFalse : String Read FBooleanFalse Write FBooleanFalse;
  72. Property DateFormat : String Read FDateFormat Write FDateFormat;
  73. Property TimeFormat : String Read FTimeFormat Write FTimeFormat;
  74. Property DateTimeFormat : String Read FDateTimeFormat Write FDateTimeFormat;
  75. Public
  76. Constructor Create(DoInitSettings : Boolean); virtual;
  77. Procedure Assign(Source : TPersistent); override;
  78. end;
  79. TCustomExportFormatSettingsClass = Class of TCustomExportFormatSettings;
  80. { TExportFormatSettings }
  81. TExportFormatSettings = Class(TCustomExportFormatSettings)
  82. Published
  83. Property IntegerFormat;
  84. Property DecimalSeparator;
  85. Property CurrencySymbol;
  86. Property CurrencyDigits;
  87. Property BooleanTrue;
  88. Property BooleanFalse ;
  89. Property DateFormat;
  90. Property TimeFormat;
  91. Property DateTimeFormat;
  92. end;
  93. TOnExportRowEvent = Procedure(Sender : TObject; Var AllowExport : Boolean) of object;
  94. TExportProgressEvent = Procedure(Sender : TObject; Const ItemNo : Integer) of object;
  95. { TCustomDatasetExporter }
  96. TCustomDatasetExporter = Class(TComponent)
  97. private
  98. FAfterExecute: TNotifyEvent;
  99. FBeforeExecute: TNotifyEvent;
  100. FCanceled: Boolean;
  101. FDataset: TDataset;
  102. FFormatSettings: TCustomExportFormatSettings;
  103. FExportFields: TExportFields;
  104. FFromCurrent: Boolean;
  105. FOnExportRow: TOnExportRowEvent;
  106. FonProgress: TExportProgressEvent;
  107. FRestorePosition: Boolean;
  108. procedure SetDataset(const AValue: TDataset);
  109. procedure SetExportFields(const AValue: TExportFields);
  110. procedure SetFormatSettings(const AValue: TCustomExportFormatSettings);
  111. Protected
  112. // Override this if you need a descendent of TExportFormatSettings
  113. Function CreateFormatSettings : TCustomExportFormatSettings; virtual;
  114. // Checks if Dataset is assigned and whether it is in browse mode.
  115. Procedure CheckDataset(InBrowse : Boolean);
  116. // Allocate TField in TExportFieldItem
  117. Function BindFields : Boolean; virtual;
  118. // Nil out fields.
  119. Procedure UnbindFields;
  120. // Override if a descendent of TExportFieldItem is needed.
  121. Function CreateExportFields : TExportFields; Virtual;
  122. // Executes BeforeExecute event. Override (but call inherited)
  123. Procedure DoBeforeExecute; virtual;
  124. // Executes AfterExecute event. Override (but call inherited)
  125. // Note this is also executed in case of an exception !!
  126. Procedure DoAfterExecute; virtual;
  127. // Returns True if current row should be exported
  128. Function DoDataRow : Boolean; virtual;
  129. // Override to write data prior to data start.
  130. Procedure DoDataHeader; virtual;
  131. // Override to write data after data start.
  132. Procedure DoDataFooter; virtual;
  133. // Override to write something at row start.
  134. Procedure DoDataRowStart; virtual;
  135. // Override if a simple loop is not enough.
  136. Procedure ExportDataRow; virtual;
  137. // Override to write something at row start.
  138. Procedure DoDataRowEnd; virtual;
  139. // Called after row was exported
  140. Procedure DoProgress(ItemNo : Integer); Virtual;
  141. // Override if each field can be written as-is.
  142. Procedure ExportField(EF : TExportFieldItem); virtual;
  143. // Format field as string, according to settings
  144. Function FormatField(F : TField) : String; virtual;
  145. // Raise EDataExporter error
  146. Procedure ExportError(Msg : String); overload;
  147. Procedure ExportError(Fmt : String; Args: Array of const); overload;
  148. Public
  149. Constructor Create(AOwner : TComponent); override;
  150. Destructor Destroy; override;
  151. // Build default fieldmap - adds all fields.
  152. Procedure BuildDefaultFieldMap(AMap : TExportFields); virtual;
  153. // Do export. Returns the number of records exported.
  154. Function Execute : Integer; virtual;
  155. // Call this to cancel the export
  156. Procedure Cancel;
  157. // Show the default configuration dialog, if one was assigned.
  158. // Returns false if the dialog was cancelled.
  159. Function ShowConfigDialog : Boolean;
  160. // Don't use. Needed for nil of dataset.
  161. Procedure Notification(AComponent: TComponent; Operation : TOperation); override;
  162. // True if export was canceled (using Cancel);
  163. Property Canceled : Boolean Read FCanceled;
  164. Public
  165. // Properties
  166. Property Dataset : TDataset Read FDataset Write SetDataset;
  167. Property ExportFields : TExportFields Read FExportFields Write SetExportFields;
  168. Property FromCurrent : Boolean Read FFromCurrent Write FFromCurrent Default True;
  169. Property RestorePosition : Boolean Read FRestorePosition Write FRestorePosition;
  170. Property FormatSettings : TCustomExportFormatSettings Read FFormatSettings Write SetFormatSettings;
  171. // Events
  172. Property AfterExecute : TNotifyEvent Read FAfterExecute Write FAfterExecute;
  173. Property BeforeExecute : TNotifyEvent Read FBeforeExecute Write FBeforeExecute;
  174. Property OnExportRow : TOnExportRowEvent Read FOnExportRow Write FOnExportRow;
  175. Property OnProgress : TExportProgressEvent Read FonProgress Write FOnProgress;
  176. end;
  177. TCustomDatasetExporterClass = Class of TCustomDatasetExporter;
  178. { TStreamExporter }
  179. TStreamExporter = Class(TCustomDatasetExporter)
  180. Private
  181. FStream: TStream;
  182. Protected
  183. Property Stream : TStream Read FStream;
  184. // Frees the stream.
  185. Procedure CloseStream;
  186. Public
  187. Procedure ExportToStream(AStream : TStream);
  188. end;
  189. { TCustomFileExporter }
  190. TCustomFileExporter = Class(TStreamExporter)
  191. private
  192. FFileName: String;
  193. FTextFile: Text;
  194. FTextFileOpen: Boolean;
  195. FopenedStream : Boolean;
  196. protected
  197. // Creates a file stream
  198. procedure OpenStream; virtual;
  199. // Override if some checking needs to be done on valid names
  200. procedure SetFileName(const AValue: String); virtual;
  201. // Override if some checking needs to be done prior to opening.
  202. Procedure CheckFileName; virtual;
  203. // Use to open/close textfile. Creates a file stream.
  204. Procedure OpenTextFile;
  205. Procedure CloseTextFile;
  206. // Access to stream/file
  207. Property TextFile : Text Read FTextFile;
  208. Property TextFileOpen : Boolean Read FTextFileOpen;
  209. Public
  210. Destructor Destroy; override;
  211. // Publish in descendents.
  212. Property FileName : String Read FFileName Write SetFileName;
  213. end;
  214. EDataExporter = Class(Exception);
  215. { TExportFormatItem }
  216. TExportConfigureEvent = Function (Exporter : TCustomDatasetExporter) : Boolean of object;
  217. TExportFormatItem = Class(TCollectionItem)
  218. private
  219. FClass: TCustomDatasetExporterClass;
  220. FDescription: String;
  221. FExtensions: String;
  222. FName: String;
  223. FOnConfigure: TExportConfigureEvent;
  224. procedure SetName(const AValue: String);
  225. Public
  226. Property ExportClass : TCustomDatasetExporterClass Read FClass Write FClass;
  227. Published
  228. Property Name : String Read FName Write SetName;
  229. Property Description : String Read FDescription Write FDescription;
  230. Property Extensions : String Read FExtensions Write FExtensions;
  231. Property OnConfigureDialog : TExportConfigureEvent Read FOnConfigure Write FOnConfigure;
  232. end;
  233. TExportFormats = Class(TCollection)
  234. private
  235. function GetFormat(Index : Integer): TExportFormatItem;
  236. procedure SetFormat(Index : Integer; const AValue: TExportFormatItem);
  237. Public
  238. // Registration/Unregistration
  239. Function RegisterExportFormat(Const AName,ADescription,AExtensions : String; AClass : TCustomDatasetExporterClass) : TExportFormatItem;
  240. Procedure UnRegisterExportFormat(AClass : TCustomDatasetExporterClass);
  241. Procedure UnRegisterExportFormat(Const AName : String);
  242. // Searching
  243. Function IndexOfFormat(Const AName : String): Integer;
  244. Function IndexOfExportClass(AClass : TCustomDataSetExporterClass): Integer;
  245. Function FindFormat(Const AName : String) : TExportFormatItem;
  246. Function FindFormatByClass(AClass : TCustomDataSetExporterClass) : TExportFormatItem;
  247. // Shows configuration dialog, if one was configured for this class
  248. Function ConfigureExport(AnExport : TCustomDatasetExporter) : Boolean;
  249. Function FormatByName(Const AName : String) : TExportFormatItem;
  250. // Utilityfunctions
  251. Function ConstructFilter(AnExport : TCustomDatasetExporter) : String;
  252. Property Formats[Index : Integer] : TExportFormatItem Read GetFormat Write SetFormat; default;
  253. end;
  254. Function ExportFormats : TExportFormats;
  255. // Easy access functions
  256. Function RegisterExportFormat(Const AName,ADescription,AExtensions : String; AClass : TCustomDatasetExporterClass) : TExportFormatItem;
  257. Procedure UnRegisterExportFormat(AClass : TCustomDatasetExporterClass);
  258. Procedure UnRegisterExportFormat(Const AName : String);
  259. Const
  260. StringFieldTypes = [ftString,ftFixedChar,ftWidestring,ftFixedWideChar];
  261. IntFieldTypes = [ftInteger,ftWord,ftsmallint,ftautoinc];
  262. OrdFieldTypes = IntFieldTypes +[ftBoolean,ftLargeInt];
  263. DateFieldTypes = [ftDate,ftTime,ftDateTime,ftTimeStamp];
  264. MemoFieldTypes = [ftMemo,ftFmtMemo,ftWideMemo];
  265. BlobFieldTypes = [ftBlob,ftGraphic,ftOraBlob,ftOraClob];
  266. implementation
  267. uses streamio;
  268. ResourceString
  269. SErrNoDataset = 'Dataset not assigned';
  270. SErrNoBrowse = 'Dataset not in browse mode';
  271. SErrNoFileName = 'No filename set for export';
  272. SErrFormatExists = 'An export format with name "%s" already exists.';
  273. SUnknownExportFormat = 'Unknown export format "%s"';
  274. SExportFilter = '%s files';
  275. SAllFilesFilter = 'All files';
  276. SErrDuplicateExportName = 'Exported fieldname "%s" already exists';
  277. { TExportFieldItem }
  278. procedure TExportFieldItem.SetFieldName(const AValue: String);
  279. begin
  280. if (FFieldName<>AValue) then
  281. begin
  282. FField:=Nil;
  283. FFieldName:=AValue;
  284. end;
  285. end;
  286. constructor TExportFieldItem.Create(ACollection: TCollection);
  287. begin
  288. inherited Create(ACollection);
  289. FEnabled:=True;
  290. end;
  291. function TExportFieldItem.GetExportedName: String;
  292. begin
  293. Result:=FExportedName;
  294. If (Result='') then
  295. Result:=FFieldName;
  296. end;
  297. function TExportFieldItem.GetExporter: TCustomDatasetExporter;
  298. begin
  299. If Collection is TExportFields then
  300. Result:=(Collection as TExportFields).Exporter;
  301. end;
  302. procedure TExportFieldItem.SetExportedName(const AValue: String);
  303. Var
  304. I : TExportFieldItem;
  305. begin
  306. If (FExportedName<>AValue) then
  307. begin
  308. If (AValue<>'') then
  309. begin
  310. I:=(Collection as TExportFields).FindExportName(AValue);
  311. If (I<>Nil) and (I<>Self) then
  312. Raise EDataExporter.CreateFmt(SErrDuplicateExportName,[AValue]);
  313. end;
  314. FExportedName:=AValue;
  315. end;
  316. end;
  317. procedure TExportFieldItem.BindField(ADataset: TDataset);
  318. begin
  319. FField:=ADataSet.FieldByName(FieldName);
  320. end;
  321. procedure TExportFieldItem.Assign(Source: TPersistent);
  322. Var
  323. EF : TExportFieldItem;
  324. begin
  325. if (Source is TExportFieldItem) then
  326. begin
  327. EF:=Source as TExportFieldItem;
  328. FieldName:=EF.FieldName;
  329. Enabled:=EF.Enabled;
  330. FExportedName:=EF.FExportedName;
  331. end
  332. else
  333. Inherited;
  334. end;
  335. { TExportFields }
  336. function TExportFields.GetFieldItem(Index : Integer): TExportFieldItem;
  337. begin
  338. Result:=TExportFieldItem(Items[Index]);
  339. end;
  340. procedure TExportFields.SetFieldItem(Index : Integer; const AValue: TExportFieldItem);
  341. begin
  342. Items[Index]:=AValue;
  343. end;
  344. function TExportFields.IndexOfField(const AFieldName: String): Integer;
  345. begin
  346. Result:=Count-1;
  347. While (Result>=0) and (CompareText(GetFieldItem(Result).FieldName,AFieldName)<>0) do
  348. Dec(Result);
  349. end;
  350. function TExportFields.IndexOfExportedName(const AFieldName: String): Integer;
  351. begin
  352. Result:=Count-1;
  353. While (Result>=0) and (CompareText(GetFieldItem(Result).ExportedName,AFieldName)<>0) do
  354. Dec(Result);
  355. end;
  356. function TExportFields.FindExportField(const AFieldName: String
  357. ): TExportFieldItem;
  358. Var
  359. I : Integer;
  360. begin
  361. I:=IndexOfField(AFieldName);
  362. If (I<>-1) then
  363. Result:=GetFieldItem(I)
  364. else
  365. Result:=Nil;
  366. end;
  367. function TExportFields.FindExportName(const AFieldName: String
  368. ): TExportFieldItem;
  369. Var
  370. I : Integer;
  371. begin
  372. I:=IndexOfExportedName(AFieldName);
  373. If (I<>-1) then
  374. Result:=GetFieldItem(I)
  375. else
  376. Result:=Nil;
  377. end;
  378. function TExportFields.AddField(Const AFieldName: String): TExportFieldItem;
  379. begin
  380. Result:=(Add as TExportFieldItem);
  381. Result.FieldName:=AFieldName;
  382. end;
  383. { TCustomDatasetExporter }
  384. procedure TCustomDatasetExporter.SetDataset(const AValue: TDataset);
  385. begin
  386. if (FDataset<>AValue) then
  387. begin
  388. If (FDataset<>Nil) then
  389. FDataset.RemoveFreeNotification(Self);
  390. FDataset:=AValue;
  391. FDataset.FreeNotification(Self);
  392. UnbindFields;
  393. end;
  394. end;
  395. procedure TCustomDatasetExporter.SetExportFields(const AValue: TExportFields);
  396. begin
  397. FExportFields.Assign(AValue);
  398. end;
  399. procedure TCustomDatasetExporter.SetFormatSettings(
  400. const AValue: TCustomExportFormatSettings);
  401. begin
  402. if FFormatSettings<>AValue then
  403. FFormatSettings.Assign(AValue);
  404. end;
  405. Function TCustomDatasetExporter.CreateFormatSettings : TCustomExportFormatSettings;
  406. begin
  407. Result:=TExportFormatSettings.Create(False);
  408. end;
  409. procedure TCustomDatasetExporter.CheckDataset(InBrowse : Boolean);
  410. begin
  411. If Not Assigned(Dataset) then
  412. Raise EDataExporter.Create(SErrNoDataset);
  413. If InBrowse and Not (Dataset.State=dsBrowse) then
  414. Raise EDataExporter.Create(SErrNoBrowse);
  415. end;
  416. function TCustomDatasetExporter.BindFields: Boolean;
  417. Var
  418. I : integer;
  419. begin
  420. Result:=(ExportFields.Count=0);
  421. If Result then
  422. BuildDefaultFieldMap(ExportFields);
  423. Try
  424. For I:=0 to ExportFields.Count-1 do
  425. ExportFields[i].BindField(Dataset);
  426. except
  427. UnbindFields;
  428. Raise;
  429. end;
  430. end;
  431. procedure TCustomDatasetExporter.UnbindFields;
  432. Var
  433. I : Integer;
  434. begin
  435. For I:=0 TO FExportFields.Count-1 do
  436. Fexportfields[i].FField:=Nil;
  437. end;
  438. Function TCustomDatasetExporter.CreateExportFields : TExportFields;
  439. begin
  440. Result:=TExportFields.Create(TExportFieldItem);
  441. end;
  442. procedure TCustomDatasetExporter.DoBeforeExecute;
  443. begin
  444. If Assigned(FBeforeExecute) then
  445. FBeforeExecute(Self)
  446. end;
  447. procedure TCustomDatasetExporter.DoAfterExecute;
  448. begin
  449. If Assigned(FAfterExecute) then
  450. FAfterExecute(Self)
  451. end;
  452. function TCustomDatasetExporter.DoDataRow: Boolean;
  453. begin
  454. Result:=True;
  455. If Assigned(FonExportRow) then
  456. FOnExportRow(Self,Result);
  457. end;
  458. procedure TCustomDatasetExporter.DoDataHeader;
  459. begin
  460. // Do nothing
  461. end;
  462. procedure TCustomDatasetExporter.DoDataFooter;
  463. begin
  464. // No nothing
  465. end;
  466. procedure TCustomDatasetExporter.DoDataRowStart;
  467. begin
  468. // Do nothing
  469. end;
  470. procedure TCustomDatasetExporter.ExportDataRow;
  471. Var
  472. I : Integer;
  473. begin
  474. For I:=0 to FExportFields.Count-1 do
  475. If FExportFields[I].Enabled then
  476. ExportField(FExportFields[i]);
  477. end;
  478. procedure TCustomDatasetExporter.DoDataRowEnd;
  479. begin
  480. // Do nothing
  481. end;
  482. procedure TCustomDatasetExporter.DoProgress(ItemNo: Integer);
  483. begin
  484. If Assigned(FOnProgress) then
  485. FOnProgress(Self,ItemNo);
  486. end;
  487. procedure TCustomDatasetExporter.ExportField(EF: TExportFieldItem);
  488. begin
  489. // Do nothing
  490. end;
  491. Function TCustomDatasetExporter.FormatField(F: TField) : String;
  492. Var
  493. FS : TFormatSettings;
  494. begin
  495. If (F.DataType in IntFieldTypes) then
  496. begin
  497. If (FormatSettings.IntegerFormat)<>'' then
  498. Result:=Format(FormatSettings.IntegerFormat,[F.AsInteger])
  499. else if FormatSettings.UseDisplayText then
  500. Result:=F.DisplayText
  501. else
  502. Result:=F.AsString;
  503. end
  504. else if (F.DataType=ftBoolean) then
  505. begin
  506. If F.AsBoolean then
  507. Result:=FormatSettings.BooleanTrue
  508. else
  509. Result:=FormatSettings.BooleanFalse;
  510. If (Result='') then
  511. if FormatSettings.UseDisplayText then
  512. Result:=F.DisplayText
  513. else
  514. Result:=F.AsString;
  515. end
  516. else if (F.DataType=ftDate) then
  517. begin
  518. If (FormatSettings.DateFormat<>'') then
  519. Result:=FormatDateTime(FormatSettings.DateFormat,F.AsDateTime)
  520. else if FormatSettings.UseDisplayText then
  521. Result:=F.DisplayText
  522. else
  523. Result:=F.AsString;
  524. end
  525. else if (F.DataType=ftTime) then
  526. begin
  527. If (FormatSettings.TimeFormat<>'') then
  528. Result:=FormatDateTime(FormatSettings.TimeFormat,F.AsDateTime)
  529. else if FormatSettings.UseDisplayText then
  530. Result:=F.DisplayText
  531. else
  532. Result:=F.AsString;
  533. end
  534. else if (F.DataType in [ftDateTime,ftTimeStamp]) then
  535. begin
  536. If (FormatSettings.DateTimeFormat<>'') then
  537. Result:=FormatDateTime(FormatSettings.DateTimeFormat,F.AsDateTime)
  538. else if FormatSettings.UseDisplayText then
  539. Result:=F.DisplayText
  540. else
  541. Result:=F.AsString;
  542. end
  543. else if (F.DataType=ftCurrency) then
  544. begin
  545. If (FormatSettings.CurrencySymbol<>'') then
  546. begin
  547. FS:=DefaultFormatSettings;
  548. FS.CurrencyString:=FormatSettings.CurrencySymbol;
  549. Result:=CurrToStrF(F.AsCurrency,ffCurrency,FormatSettings.CurrencyDigits,FS);
  550. end
  551. else if FormatSettings.UseDisplayText then
  552. Result:=F.DisplayText
  553. else
  554. Result:=F.AsString;
  555. end
  556. else if FormatSettings.UseDisplayText then
  557. Result:=F.DisplayText
  558. else
  559. Result:=F.AsString;
  560. end;
  561. procedure TCustomDatasetExporter.ExportError(Msg: String);
  562. begin
  563. Raise EDataExporter.Create(Msg);
  564. end;
  565. procedure TCustomDatasetExporter.ExportError(Fmt: String;
  566. Args: array of const);
  567. begin
  568. Raise EDataExporter.CreateFmt(Fmt,Args);
  569. end;
  570. constructor TCustomDatasetExporter.Create(AOwner: TComponent);
  571. begin
  572. inherited Create(AOwner);
  573. FromCurrent:=True;
  574. FExportFields:=CreateExportFields;
  575. FExportFields.FExporter:=Self;
  576. FFormatSettings:=CreateFormatSettings;
  577. end;
  578. destructor TCustomDatasetExporter.Destroy;
  579. begin
  580. FreeAndNil(FExportFields);
  581. inherited Destroy;
  582. end;
  583. procedure TCustomDatasetExporter.BuildDefaultFieldMap(AMap : TExportFields);
  584. Var
  585. I : Integer;
  586. F : TField;
  587. begin
  588. CheckDataset(False);
  589. AMap.Clear;
  590. For I:=0 to FDataset.Fields.Count-1 do
  591. begin
  592. F:=FDataset.Fields[i];
  593. AMap.AddField(F.FieldName);
  594. end;
  595. end;
  596. Function TCustomDatasetExporter.Execute : Integer;
  597. Var
  598. B : Boolean;
  599. BM : TBookMarkStr;
  600. begin
  601. Result:=0;
  602. FCanceled:=False;
  603. DoBeforeExecute;
  604. Try
  605. CheckDataset(True);
  606. B:=BindFields;
  607. try
  608. DoDataHeader;
  609. Dataset.DisableControls;
  610. Try
  611. BM:=Dataset.BookMark;
  612. try
  613. If not FromCurrent then
  614. Dataset.First;
  615. While not (Dataset.EOF or FCanceled) do
  616. begin
  617. if DoDataRow then
  618. begin
  619. Inc(Result);
  620. DoDataRowStart;
  621. ExportDataRow;
  622. DoDataRowEnd;
  623. DoProgress(Result);
  624. end;
  625. Dataset.Next;
  626. end;
  627. DoDataFooter;
  628. finally
  629. If RestorePosition then
  630. Dataset.BookMark:=Bm;
  631. end;
  632. Finally
  633. Dataset.EnableControls;
  634. end;
  635. Finally
  636. If B then
  637. FExportFields.Clear;
  638. end;
  639. Finally
  640. DoAfterExecute;
  641. end;
  642. end;
  643. procedure TCustomDatasetExporter.Cancel;
  644. begin
  645. FCanceled:=True;
  646. end;
  647. function TCustomDatasetExporter.ShowConfigDialog: Boolean;
  648. begin
  649. Result:=ExportFormats.ConfigureExport(Self);
  650. end;
  651. procedure TCustomDatasetExporter.Notification(AComponent: TComponent;
  652. Operation: TOperation);
  653. begin
  654. If (Operation=opRemove) and (AComponent=FDataset) then
  655. FDataset:=Nil;
  656. inherited Notification(AComponent, Operation);
  657. end;
  658. { TStreamExporter }
  659. procedure TStreamExporter.CloseStream;
  660. begin
  661. FreeAndNil(FStream);
  662. end;
  663. procedure TStreamExporter.ExportToStream(AStream: TStream);
  664. begin
  665. FStream:=AStream;
  666. try
  667. Execute;
  668. Finally
  669. FStream:=Nil;
  670. end;
  671. end;
  672. { TCustomFileExporter }
  673. procedure TCustomFileExporter.SetFileName(const AValue: String);
  674. begin
  675. if FFileName=AValue then exit;
  676. FFileName:=AValue;
  677. end;
  678. procedure TCustomFileExporter.CheckFileName;
  679. begin
  680. If (FFileName='') then
  681. ExportError(SErrNoFileName);
  682. end;
  683. procedure TCustomFileExporter.OpenTextFile;
  684. begin
  685. CheckFileName;
  686. FOpenedStream:=(Stream=Nil);
  687. If FOpenedStream then
  688. OpenStream;
  689. AssignStream(FTextFile,Stream);
  690. Rewrite(FTextFile);
  691. FTextFileOpen:=True;
  692. end;
  693. procedure TCustomFileExporter.CloseTextFile;
  694. begin
  695. CloseFile(FTextFile);
  696. FTextFileOpen:=False;
  697. If FOpenedStream then
  698. CloseStream;
  699. end;
  700. procedure TCustomFileExporter.OpenStream;
  701. begin
  702. CheckFileName;
  703. FStream:=TFileStream.Create(FFileName,fmCreate);
  704. end;
  705. Destructor TCustomFileExporter.Destroy;
  706. begin
  707. If TextFileOpen then
  708. CloseTextFile;
  709. CloseStream;
  710. inherited Destroy;
  711. end;
  712. { TCustomExportFormatSettings }
  713. procedure TCustomExportFormatSettings.InitSettings;
  714. begin
  715. FIntegerFormat:='%d';
  716. FDateFormat:=ShortDateFormat;
  717. FTimeFormat:=ShortTimeFormat;
  718. FDateTimeFormat:=ShortDateFormat+' '+ShortTimeFormat;
  719. FBooleanTrue:='True';
  720. FBooleanFalse:='False';
  721. FDecimalSeparator:=sysutils.decimalseparator;
  722. FCurrencySymbol:=sysutils.CurrencyString;
  723. end;
  724. constructor TCustomExportFormatSettings.Create(DoInitSettings: Boolean);
  725. begin
  726. If DoInitSettings then
  727. InitSettings;
  728. end;
  729. procedure TCustomExportFormatSettings.Assign(Source: TPersistent);
  730. Var
  731. FS : TCustomExportFormatSettings;
  732. begin
  733. If (Source is TCustomExportFormatSettings) then
  734. begin
  735. FS:=Source as TCustomExportFormatSettings;
  736. FBooleanFalse:=FS.FBooleanFalse;
  737. FBooleanTrue:=FS.FBooleanTrue;
  738. FCurrencyDigits:=FS.FCurrencyDigits;
  739. FCurrencySymbol:=FS.FCurrencySymbol;
  740. FDateFormat:=FS.FDateFormat;
  741. FIntegerFormat:=FS.IntegerFormat;
  742. FTimeFormat:=FS.FTimeFormat;
  743. FDateTimeFormat:=FS.FDateTimeFormat;
  744. FDecimalSeparator:=FS.FDecimalSeparator;
  745. FUseDisplayText:=FS.FUseDisplayText;
  746. end
  747. else
  748. inherited Assign(Source);
  749. end;
  750. { TExportFormats }
  751. function TExportFormats.GetFormat(Index : Integer): TExportFormatItem;
  752. begin
  753. Result:=TExportFormatItem(Items[Index]);
  754. end;
  755. procedure TExportFormats.SetFormat(Index : Integer; const AValue: TExportFormatItem
  756. );
  757. begin
  758. Items[Index]:=AValue;
  759. end;
  760. function TExportFormats.RegisterExportFormat(Const AName, ADescription,
  761. AExtensions: String; AClass: TCustomDatasetExporterClass): TExportFormatItem;
  762. begin
  763. If (IndexOfFormat(AName)<>-1) then
  764. Raise EDataExporter.CreateFmt(SErrFormatExists,[AName]);
  765. Result:=Add as TExportFormatItem;
  766. Result.Name:=AName;
  767. Result.Description:=ADescription;
  768. Result.Extensions:=AExtensions;
  769. Result.ExportClass:=AClass;
  770. end;
  771. function TExportFormats.IndexOfFormat(const AName: String): Integer;
  772. begin
  773. Result:=Count-1;
  774. While (Result>=0) and (CompareText(GetFormat(Result).Name,AName)<>0) do
  775. Dec(Result);
  776. end;
  777. function TExportFormats.IndexOfExportClass(AClass: TCustomDataSetExporterClass
  778. ): Integer;
  779. begin
  780. Result:=Count-1;
  781. While (Result>=0) and (GetFormat(Result).ExportClass<>AClass) do
  782. Dec(Result);
  783. end;
  784. function TExportFormats.FindFormat(const AName: String): TExportFormatItem;
  785. Var
  786. I : Integer;
  787. begin
  788. I:=IndexOfFormat(AName);
  789. If (I=-1) then
  790. Result:=Nil
  791. else
  792. Result:=GetFormat(I);
  793. end;
  794. function TExportFormats.FindFormatByClass(AClass: TCustomDataSetExporterClass): TExportFormatItem;
  795. Var
  796. I : Integer;
  797. begin
  798. I:=IndexOfExportClass(AClass);
  799. If (I=-1) then
  800. Result:=Nil
  801. else
  802. Result:=GetFormat(I);
  803. end;
  804. function TExportFormats.ConfigureExport(AnExport: TCustomDatasetExporter
  805. ): Boolean;
  806. Var
  807. F : TExportFormatItem;
  808. begin
  809. Result:=True;
  810. F:=FindFormatByClass(TCustomDatasetExporterClass(AnExport.ClassType));
  811. If Assigned(F) and Assigned(F.OnConfigureDialog) then
  812. Result:=F.OnConfigureDialog(AnExport);
  813. end;
  814. function TExportFormats.FormatByName(const AName: String): TExportFormatItem;
  815. begin
  816. Result:=FindFormat(AName);
  817. If (Result=Nil) then
  818. Raise EDataExporter.CreateFmt(SUnknownExportFormat,[AName]);
  819. end;
  820. function TExportFormats.ConstructFilter(AnExport: TCustomDatasetExporter
  821. ): String;
  822. Procedure AddToResult(S : String);
  823. begin
  824. If (Result<>'') and (S<>'') then
  825. Result:=Result+'|';
  826. Result:=Result+S;
  827. end;
  828. Var
  829. F : TExportFormatItem;
  830. P : Integer;
  831. S,E : String;
  832. begin
  833. Result:='';
  834. F:=FindFormatByClass(TCustomDatasetExporterClass(AnExport.ClassType));
  835. If (F=Nil) then
  836. Exit;
  837. S:=F.Extensions;
  838. While (S<>'') do
  839. begin
  840. P:=Pos(';',S);
  841. If (P=0) then
  842. P:=Length(S)+1;
  843. E:=Copy(S,1,P-1);
  844. If (Length(E)>1) then // Make sure there actually is an extension
  845. begin
  846. If (E[1]='.') then
  847. system.Delete(E,1,1);
  848. AddToResult(Format(SExportFilter,[E])+Format('|*.%s',[E]));
  849. end;
  850. system.Delete(S,1,P);
  851. end;
  852. AddToResult(SAllFilesFilter+'|*');
  853. end;
  854. Procedure TExportFormats.UnRegisterExportFormat(AClass : TCustomDatasetExporterClass);
  855. begin
  856. FindFormatByClass(AClass).Free;
  857. end;
  858. Procedure TExportFormats.UnRegisterExportFormat(Const AName : String);
  859. begin
  860. FindFormat(AName).Free;
  861. end;
  862. { TExportFormatItem }
  863. procedure TExportFormatItem.SetName(const AValue: String);
  864. Var
  865. I : TExportFormatItem;
  866. begin
  867. if (FName=AValue) then
  868. exit;
  869. If (AValue<>'') then
  870. begin
  871. I:=TExportFormats(Collection).FindFormat(AValue);
  872. If (I<>Nil) and (I<>Self) then
  873. Raise EDataExporter.CreateFmt(SErrFormatExists,[AValue]);
  874. end;
  875. FName:=AValue;
  876. end;
  877. Var
  878. EF : TExportFormats;
  879. Procedure InitExportFormats;
  880. begin
  881. EF:=TExportFormats.Create(TExportFormatItem);
  882. end;
  883. Procedure DoneExportFormats;
  884. begin
  885. FreeAndNil(EF);
  886. end;
  887. Function ExportFormats : TExportFormats;
  888. begin
  889. If (EF=Nil) then
  890. InitExportFormats;
  891. Result:=EF;
  892. end;
  893. Function RegisterExportFormat(Const AName,ADescription,AExtensions : String; AClass : TCustomDatasetExporterClass) : TExportFormatItem;
  894. begin
  895. Result:=ExportFormats.RegisterExportFormat(AName,ADescription,AExtensions,AClass);
  896. end;
  897. Procedure UnRegisterExportFormat(AClass : TCustomDatasetExporterClass);
  898. begin
  899. ExportFormats.UnregisterExportFormat(AClass);
  900. end;
  901. Procedure UnRegisterExportFormat(Const AName : String);
  902. begin
  903. ExportFormats.UnregisterExportFormat(AName);
  904. end;
  905. Initialization
  906. Finalization
  907. DoneExportFormats;
  908. end.