fpdbfexport.pp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. unit fpdbfexport;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, db, dbf, fpdbexport;
  6. Type
  7. { TDBFExportFieldItem }
  8. TDBFExportFieldItem = Class(TExportFieldItem)
  9. private
  10. FDestField: TField;
  11. Protected
  12. Property DestField : TField Read FDestField;
  13. end;
  14. { TDBFExportFormatSettings }
  15. TTableFormat = (tfDBaseIII,tfDBaseIV,tfDBaseVII,tfFoxPro);
  16. TDBFExportFormatSettings = class(TExportFormatSettings)
  17. private
  18. FAutoRename: Boolean;
  19. FTableFormat: TTableFormat;
  20. public
  21. Procedure Assign(Source : TPersistent); override;
  22. Published
  23. Property TableFormat : TTableFormat Read FTableFormat Write FTableFormat;
  24. Property AutoRenameFields : Boolean Read FAutoRename Write FAutoRename;
  25. end;
  26. { TFPCustomDBFExport }
  27. TFPCustomDBFExport = Class(TCustomDatasetExporter)
  28. Private
  29. FDBF : TDBF;
  30. FFileName: String;
  31. FAppendData: Boolean;
  32. function GetSettings: TDBFExportFormatSettings;
  33. procedure SetSettings(const AValue: TDBFExportFormatSettings);
  34. Protected
  35. Procedure CheckExportFieldNames(const MaxFieldNameLength: integer); virtual;
  36. Function BindFields : Boolean; override;
  37. Function CreateFormatSettings : TCustomExportFormatSettings; override;
  38. Function CreateExportFields : TExportFields; override;
  39. Procedure DoBeforeExecute; override;
  40. Procedure DoAfterExecute; override;
  41. Procedure DoDataRowStart; override;
  42. Procedure DoDataRowEnd; override;
  43. Procedure ExportField(EF : TExportFieldItem); override;
  44. Property FileName : String Read FFileName Write FFileName;
  45. Property AppendData : Boolean Read FAppendData Write FAppendData;
  46. Property DBF : TDBF Read FDBF;
  47. public
  48. Property FormatSettings : TDBFExportFormatSettings Read GetSettings Write SetSettings;
  49. end;
  50. TFPDBFExport = Class(TFPCustomDBFExport)
  51. Published
  52. Property FileName;
  53. Property Dataset;
  54. Property ExportFields;
  55. Property FromCurrent;
  56. Property RestorePosition;
  57. Property FormatSettings;
  58. Property OnExportRow;
  59. end;
  60. Procedure RegisterDBFExportFormat;
  61. Procedure UnRegisterDBFExportFormat;
  62. Const
  63. SDBFExport = 'DBF';
  64. SDBFFilter = '*.dbf';
  65. ResourceString
  66. SErrFailedToDeleteFile = 'Failed to delete existing DBF file: %s';
  67. SDBFDescription = 'DBF files';
  68. implementation
  69. { TFPCustomDBFExport }
  70. function TFPCustomDBFExport.GetSettings: TDBFExportFormatSettings;
  71. begin
  72. Result:=TDBFExportFormatSettings(Inherited FormatSettings);
  73. end;
  74. procedure TFPCustomDBFExport.SetSettings(const AValue: TDBFExportFormatSettings
  75. );
  76. begin
  77. Inherited FormatSettings.Assign(AValue);
  78. end;
  79. procedure TFPCustomDBFExport.CheckExportFieldNames(const MaxFieldNameLength: integer);
  80. Var
  81. i,NameCounter : Integer;
  82. EF : TExportFieldItem;
  83. NewFieldName : String;
  84. begin
  85. For i:=0 to ExportFields.Count-1 do
  86. begin
  87. EF:=ExportFields[i];
  88. { Cut off field name at max length, and
  89. rename if it already exists:}
  90. If (Length(EF.ExportedName)>MaxFieldNameLength) then
  91. begin
  92. NewFieldName:=Copy(EF.ExportedName,1,MaxFieldNameLength);
  93. If ExportFields.IndexOfExportedName(NewFieldName)<>-1 then
  94. begin
  95. NameCounter:=1;
  96. Repeat
  97. NewFieldName:=Copy(EF.ExportedName,1,8)+Format('%.2d',[NameCounter]);
  98. Until (ExportFIelds.IndexOfExportedName(NewFieldName)=-1);
  99. end;
  100. EF.ExportedName:=NewFieldName;
  101. end;
  102. end;
  103. end;
  104. function TFPCustomDBFExport.BindFields: Boolean;
  105. Const
  106. Levels : Array[TTableFormat] of integer = (3,4,7,25);
  107. Var
  108. EF : TDBFExportFieldItem;
  109. i : Integer;
  110. begin
  111. // DBase III,IV, and FoxPro have a 10 character field length limit.
  112. If FormatSettings.AutoRenameFields and (FormatSettings.TableFormat in [tfDbaseIII,tfDbaseIV,tfFoxPro]) then
  113. CheckExportFieldNames(10);
  114. // DBase VII has a 32 character field length limit.
  115. If FormatSettings.AutoRenameFields and (FormatSettings.TableFormat=tfDbaseVII) then
  116. CheckExportFieldNames(32);
  117. Result:=Inherited;
  118. try
  119. with FDBF.FieldDefs do
  120. begin
  121. Clear;
  122. For i:=0 to ExportFields.Count-1 do
  123. begin
  124. EF:=ExportFields[i] as TDBFExportFieldItem;
  125. If EF.Enabled and Assigned(EF.Field) then
  126. Add(EF.ExportedName,EF.Field.DataType,EF.Field.Size);
  127. end;
  128. FDBF.TableLevel:=Levels[FormatSettings.TableFormat];
  129. FDBF.CreateTable;
  130. FDBF.Exclusive := true;
  131. FDBF.Open;
  132. end;
  133. For i:=0 to ExportFields.Count-1 do
  134. begin
  135. EF:=ExportFIelds[i] as TDBFExportFieldItem;
  136. If EF.Enabled then
  137. EF.FDestField:=FDBF.FieldByName(EF.ExportedName);
  138. end;
  139. except
  140. UnBindFields;
  141. Raise;
  142. end;
  143. end;
  144. function TFPCustomDBFExport.CreateFormatSettings: TCustomExportFormatSettings;
  145. begin
  146. Result:=TDBFExportFormatSettings.Create(False);
  147. end;
  148. function TFPCustomDBFExport.CreateExportFields: TExportFields;
  149. begin
  150. Result:=TExportFields.Create(TDBFExportFieldItem);
  151. end;
  152. procedure TFPCustomDBFExport.DoBeforeExecute;
  153. Var
  154. FE : Boolean;
  155. begin
  156. Inherited;
  157. FDBF:=TDBF.Create(Self);
  158. FDBF.TableName:=FFileName;
  159. FE:=FileExists(FFileName);
  160. If FAppendData and FE then
  161. FDBF.Open
  162. else
  163. begin
  164. If FE and Not AppendData then
  165. begin
  166. If not DeleteFile(FFileName) then
  167. Raise EDataExporter.CreateFmt(SErrFailedToDeleteFile,[FFileName]);
  168. end;
  169. end;
  170. end;
  171. procedure TFPCustomDBFExport.DoAfterExecute;
  172. begin
  173. try
  174. FreeAndNil(FDBF);
  175. finally
  176. Inherited;
  177. end;
  178. end;
  179. procedure TFPCustomDBFExport.DoDataRowStart;
  180. begin
  181. FDBF.Append;
  182. end;
  183. procedure TFPCustomDBFExport.DoDataRowEnd;
  184. begin
  185. FDBF.Post;
  186. end;
  187. procedure TFPCustomDBFExport.ExportField(EF: TExportFieldItem);
  188. Var
  189. F : TDBFExportFieldItem;
  190. begin
  191. F:=EF as TDBFExportFieldItem;
  192. With F do
  193. // Export depending on field datatype;
  194. // convert to dbf data types where necessary.
  195. // Fall back to string if unknown datatype
  196. If FIeld.IsNull then
  197. DestField.Clear
  198. else if Field.Datatype in (IntFieldTypes+[ftAutoInc,ftLargeInt]) then
  199. DestField.AsInteger:=Field.AsInteger
  200. else if Field.Datatype in [ftBCD,ftCurrency,ftFloat,ftFMTBcd] then
  201. DestField.AsFloat:=Field.AsFloat
  202. else if Field.DataType in [ftString,ftFixedChar] then
  203. DestField.AsString:=Field.AsString
  204. else if (Field.DataType in ([ftWideMemo,ftWideString,ftFixedWideChar]+BlobFieldTypes)) then
  205. DestField.AsWideString:=Field.AsWideString
  206. { Note: we test for the wide text fields before the MemoFieldTypes, in order to
  207. let ftWideMemo end up at the right place }
  208. else if Field.DataType in MemoFieldTypes then
  209. DestField.AsString:=Field.AsString
  210. else if Field.DataType=ftBoolean then
  211. DestField.AsBoolean:=Field.AsBoolean
  212. else if field.DataType in DateFieldTypes then
  213. DestField.AsDatetime:=Field.AsDateTime
  214. else
  215. DestField.AsString:=Field.AsString
  216. end;
  217. Procedure RegisterDBFExportFormat;
  218. begin
  219. RegisterExportFormat(SDBFExport,SDBFDescription,SDBFFilter,TFPDBFExport);
  220. end;
  221. Procedure UnRegisterDBFExportFormat;
  222. begin
  223. UnregisterExportFormat(SDBFExport);
  224. end;
  225. { TDBFExportFormatSettings }
  226. procedure TDBFExportFormatSettings.Assign(Source: TPersistent);
  227. Var
  228. FS : TDBFExportFormatSettings;
  229. begin
  230. If Source is TDBFExportFormatSettings then
  231. begin
  232. FS:=Source as TDBFExportFormatSettings;
  233. AutoRenameFields:=FS.AutoRenameFields;
  234. TableFormat:=FS.TableFormat;
  235. end;
  236. inherited Assign(Source);
  237. end;
  238. end.