UtilMethods.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. unit UtilMethods;
  2. interface
  3. uses
  4. Controls, ZhAPI, ActnList, ZjIDTree, DB, ZjGridDBA, ZjGrid, Windows, Messages,
  5. sdDB, VCLZip, VCLUnZip, Dialogs, Forms, ShlObj, Classes, StrUtils, Math, ADODB,
  6. IdGlobal;
  7. type
  8. TRoundMode = (rmNearest, rmUp, rmDown);
  9. TBookmarkRefreshEvent = procedure (AExpandFrame: Boolean) of object;
  10. {RoundTo}
  11. function QuantityRoundTo(AValue: Double): Double;
  12. function PriceRoundTo(AValue: Double): Double;
  13. function TotalPriceRoundTo(AValue: Double): Double;
  14. function CommonRoundTo(AValue: Double; ADigit: Integer; RoundMode: TRoundMode = rmNearest): Double;
  15. {Interface Control}
  16. procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
  17. procedure SetDxBtnAction(AAction: TAction; ADxBtn: TObject);
  18. {DataBase Rela}
  19. function GetsdDataSetNewID(ADataSet: TsdDataSet; const AIndex: string): Integer;
  20. procedure ExecuteSql(AConnection: TADOConnection; const ASql: string);
  21. function QueryData(AConnection: TADOConnection; const ASql: string): TADOQuery;
  22. {Message}
  23. procedure WarningMessage(const AMsg: string; AHandle: THandle = 0);
  24. procedure ErrorMessage(const AMsg: string; AHandle: THandle = 0);
  25. function QuestMessage(const AMsg: string; AHandle: THandle = 0): Boolean;
  26. function QuestMessageYesNo(const AMsg: string; AHandle: THandle = 0): Boolean;
  27. procedure TipMessage(const AMsg: string; AHandle: THandle = 0);
  28. procedure DataSetErrorMessage(var Allow: Boolean; const AMsg: string);
  29. {Get Common Path}
  30. function GetAppFilePath: string;
  31. function GetMyProjectsFilePath: string;
  32. function GetEmptyDataBaseFileName: string;
  33. function GetTemplateBillsFileName: string;
  34. function GetTemplateXlsFileName: string;
  35. function GetBackupFilePath: string;
  36. function GetReportTemplatePath: string;
  37. function GetAppTempPath: string;
  38. {Select & Save File Choose}
  39. function GetFilter(AExt: string): string;
  40. function SelectFile(var AFileName: string; const AExt: string): Boolean;
  41. function SelectFiles(AFiles: TStrings; const AExt: string): Boolean;
  42. function SaveFile(var FileName: string; const AExt: string): Boolean;
  43. function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
  44. AParentHandle: THandle = 0; AHasNewFolderBtn: Boolean = True): Boolean;
  45. function FixPathByAppPath(AFileName: string): string;
  46. function BrowseFolder(var APath: string; const ATitle: string;
  47. AParentHandle: THandle; AHasNewFolderBtn: Boolean = True): Boolean;
  48. {CheckStrings}
  49. function CheckPeg(const AStr: string): Boolean;
  50. function CheckValidPassword(APassword: string): Boolean;
  51. function ValidInteger(var AKey: Char): Boolean;
  52. {MergeStrings}
  53. function MergeRelaBGL(const ABGLCode1, ABGLCode2: string): string;
  54. procedure MergeRelaBGLAndNum(var ABGLCode1, ABGLNum1: string; const ABGLCode2, ABGLNum2: string);
  55. {CodeTransform}
  56. function B_CodeToIndexCode(const AB_Code: string): string;
  57. function ChinessNum(const ADigitNum: Integer): string;
  58. function Num2Peg(ANum: Double): string;
  59. {Compare Code}
  60. //function CompareCodeWithChar(const ACode1, ACode2: string): Integer;
  61. {Tree Relative}
  62. function CreateTree: TZjIDTree;
  63. procedure DisConnectTree(ATree: TZjIDTree);
  64. procedure ConnectTree(ATree: TZjIDTree; ADataset: TDataSet);
  65. procedure InitGridHead(AGridDBA: TZjGridDBA; AGrid: TZJGrid);
  66. {Generate Name/Directory/Path}
  67. function GetTempFileDir: string;
  68. function GetTempFilePath: string;
  69. function GetTempName(ALength: Integer = 8): string;
  70. function GetTempFileName: string; overload;
  71. function GetTempFileName(const APath, AExt: string): string; overload;
  72. function GenerateTempFolder(AGeneratePath: string): string;
  73. function GetNewGUIDFileName(const AGeneratePath: string): string;
  74. {Progress bar Control}
  75. procedure UpdateSysProgress(APosition: Integer; const AHint: string);
  76. procedure UpdateProgress(APosition: Integer; const AHint: string);
  77. procedure DisableSysProgress;
  78. procedure EnableSysProgress;
  79. {Interface RePaint Control}
  80. procedure BeginUpdateWindow(AHandle: THandle);
  81. procedure EndUpdateWindow(AHandle: THandle);
  82. {Zip}
  83. procedure ZipFolder(AFileFolder, AFileName: string; ACheckMode: Integer = 0);
  84. function UnZipFile(AFileName, AFileFolder: string): Boolean;
  85. {Copy By Stream}
  86. procedure CopyFileByStream(const ASourceFile, ADestFile: string);
  87. procedure AppendTestLog(const AFileName, ALog: string);
  88. // Add by chenshilong, 2014-04-11
  89. function GetVersion(APartCount: Integer = 4): string;
  90. function ExtractFileNameWithoutExt(const AFileName: string): string;
  91. function ShortText(AText: string; AWidth: Integer): string; // 文本缩略显示
  92. function CustomWidthText(AText: string; AWidth: Integer): string;
  93. function ReplaceCharsForJson(AText: string): string; // 替换Json文本中的特殊字符
  94. function RecoverCharsFromJson(AText: string): string; // 下载得到的Json文本恢复成用户需要的文本
  95. procedure FindFiles(APath, AExtName: string; AFileList: TStrings);
  96. function DeleteFolder(const FolderStr: string): Boolean;
  97. function HasExt(const AFileName: string): Boolean;
  98. function CopyFolder(const SrcFolder, DstFolder: string): Boolean;
  99. function FileCount(APath: string): Integer;
  100. implementation
  101. uses
  102. SysUtils, dxBar, MainFrm, ConstUnit, Globals, StdCtrls, ShellAPI;
  103. var
  104. SysProgressDisabled: Boolean;
  105. {RoundTo}
  106. function InnerRoundTo(const AValue: Extended; const ADigit: Integer; RoundMode: TRoundMode): Extended;
  107. var
  108. LFactor, Offset, HFactor: Extended;
  109. begin
  110. LFactor := IntPower(10, ADigit);
  111. HFactor := IntPower(10, abs(ADigit));
  112. Result := AValue;
  113. case RoundMode of
  114. rmNearest:
  115. begin
  116. if AValue >= 0 then
  117. Offset := 0.5
  118. else
  119. Offset := -0.5;
  120. Result := Trunc((AValue * HFactor) + Offset) * LFactor;
  121. end;
  122. rmUP:
  123. begin
  124. if Frac(AValue / LFactor) > 0 then
  125. Result := Trunc(AValue * HFactor + 1) * LFactor
  126. else
  127. Result := Trunc(AValue * HFactor) * LFactor;
  128. end;
  129. rmDown:
  130. begin
  131. Result := Trunc(AValue * HFactor) * LFactor;
  132. end;
  133. end;
  134. end;
  135. function QuantityRoundTo(AValue: Double): Double;
  136. begin
  137. if Assigned(OpenProjectManager.CurProjectData) then
  138. Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.QuantityDigit)
  139. else
  140. Result := CommonRoundTo(AValue, iQuantityDigit);
  141. end;
  142. function PriceRoundTo(AValue: Double): Double;
  143. begin
  144. if Assigned(OpenProjectManager.CurProjectData) then
  145. Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.PriceDigit)
  146. else
  147. Result := CommonRoundTo(AValue, iPriceDigit);
  148. end;
  149. function TotalPriceRoundTo(AValue: Double): Double;
  150. begin
  151. if Assigned(OpenProjectManager.CurProjectData) then
  152. Result := CommonRoundTo(AValue, -OpenProjectManager.CurProjectData.ProjProperties.TotalPriceDigit)
  153. else
  154. Result := CommonRoundTo(AValue, iTotalPriceDigit);
  155. end;
  156. function CommonRoundTo(AValue: Double; ADigit: Integer; RoundMode: TRoundMode = rmNearest): Double;
  157. var
  158. X: Double;
  159. P: Pointer;
  160. I: Integer;
  161. Buf: array [0..7] of Byte;
  162. begin
  163. P := @AValue;
  164. CopyMemory(@Buf[0], P, SizeOf(AValue));
  165. // 进位处理,从后往前,如果当前byte为$FF,则往前一byte进1
  166. // 注意到尾数开始的位置停止
  167. // 这里说的前后是二进制串,实际存储前后相反
  168. for I := 0 to 6 do
  169. if (I < 6) and (Buf[I] = $FF) then
  170. Buf[I] := 0
  171. else
  172. begin
  173. Buf[I] := Buf[I] + 1;
  174. Break;
  175. end;
  176. P := @X;
  177. CopyMemory(P, @Buf[0], SizeOf(X));
  178. Result := InnerRoundTo(X, ADigit, RoundMode);
  179. end;
  180. {Interface Control}
  181. procedure AlignControl(AControl, AParent: TWinControl; AAlign: TAlign);
  182. begin
  183. if Assigned(AControl) then
  184. begin
  185. if Assigned(AControl.Parent) then
  186. AControl.Parent.RemoveControl(AControl);
  187. AControl.Parent := AParent;
  188. AControl.Align := AAlign;
  189. end;
  190. end;
  191. procedure SetDxBtnAction(AAction: TAction; ADxBtn: TObject);
  192. begin
  193. if Assigned(ADxBtn) then
  194. if ADxBtn is TdxBarButton then
  195. TdxBarButton(ADxBtn).Action := AAction;
  196. end;
  197. {DataBase Rela}
  198. function GetsdDataSetNewID(ADataSet: TsdDataSet; const AIndex: string): Integer;
  199. var
  200. idx: TsdIndex;
  201. begin
  202. idx := ADataSet.FindIndex(AIndex);
  203. if idx.RecordCount > 0 then
  204. Result := idx.Records[idx.RecordCount - 1].ValueByName('ID').AsInteger + 1
  205. else
  206. Result := 1;
  207. end;
  208. procedure ExecuteSql(AConnection: TADOConnection; const ASql: string);
  209. var
  210. vQuery: TADOQuery;
  211. begin
  212. vQuery := TADOQuery.Create(nil);
  213. try
  214. vQuery.Connection := AConnection;
  215. vQuery.SQL.Add(ASql);
  216. vQuery.ExecSQL;
  217. finally
  218. vQuery.Free;
  219. end;
  220. end;
  221. function QueryData(AConnection: TADOConnection; const ASql: string): TADOQuery;
  222. begin
  223. Result := TADOQuery.Create(nil);
  224. Result.Connection := AConnection;
  225. Result.SQL.Clear;
  226. Result.SQL.Add(ASql);
  227. Result.Open;
  228. end;
  229. {Message}
  230. function GetValidHandle(AHandle: THandle = 0): THandle;
  231. begin
  232. if AHandle = 0 then
  233. begin
  234. if (Screen.ActiveForm <> nil) and (Screen.ActiveForm.HandleAllocated) then
  235. Result := Screen.ActiveForm.Handle
  236. else
  237. Result := Application.Handle;
  238. end
  239. else
  240. Result := AHandle;
  241. end;
  242. procedure WarningMessage(const AMsg: string; AHandle: THandle = 0);
  243. begin
  244. MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('警告'), MB_OK or MB_ICONWARNING);
  245. end;
  246. procedure ErrorMessage(const AMsg: string; AHandle: THandle = 0);
  247. begin
  248. MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('错误'), MB_OK or MB_ICONERROR);
  249. end;
  250. function QuestMessage(const AMsg: string; AHandle: THandle = 0): Boolean;
  251. begin
  252. Result := MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('询问'), MB_OKCANCEL or MB_ICONQUESTION) = IDOK;
  253. end;
  254. function QuestMessageYesNo(const AMsg: string; AHandle: THandle = 0): Boolean;
  255. begin
  256. Result := MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('询问'), MB_YESNO or MB_ICONQUESTION) = IDYes;
  257. end;
  258. procedure TipMessage(const AMsg: string; AHandle: THandle = 0);
  259. begin
  260. MessageBox(GetValidHandle(AHandle), PChar(AMsg), PChar('提示'), MB_OK or MB_ICONINFORMATION);
  261. end;
  262. procedure DataSetErrorMessage(var Allow: Boolean; const AMsg: string);
  263. begin
  264. Allow := False;
  265. ErrorMessage(AMsg);
  266. end;
  267. {Get Common Path}
  268. function GetAppFilePath: string;
  269. begin
  270. Result := ExtractFilePath(ParamStr(0));
  271. end;
  272. function GetMyProjectsFilePath: string;
  273. begin
  274. Result := GetAppFilePath + '我的项目\';
  275. end;
  276. function GetEmptyDataBaseFileName: string;
  277. begin
  278. Result := GetAppFilePath + 'Data\Base.dat';
  279. end;
  280. function GetTemplateBillsFileName: string;
  281. begin
  282. Result := GetAppFilePath + 'Data\Template.xls';
  283. end;
  284. function GetTemplateXlsFileName: string;
  285. begin
  286. Result := GetAppFilePath + 'Data\Basic.xls';
  287. end;
  288. function GetBackupFilePath: string;
  289. begin
  290. Result := GetAppFilePath + 'TenderBackup\';
  291. end;
  292. function GetReportTemplatePath: string;
  293. begin
  294. Result := GetAppFilePath + 'ReportTemplates\';
  295. end;
  296. function GetAppTempPath: string;
  297. begin
  298. Result := GetAppFilePath + 'Temp\';
  299. if DirectoryExists(Result) then
  300. CreateDirectoryInDeep(Result);
  301. end;
  302. {Select & Save File Choose}
  303. function GetFilter(AExt: string): string;
  304. begin
  305. if AExt = '' then
  306. Result := '所有文件(*.*)|*.*'
  307. else
  308. begin
  309. if AExt[1] <> '.' then
  310. AExt := '.' + AExt;
  311. Result := Format('(*%s)|*%s', [AExt, AExt]);
  312. end;
  313. end;
  314. function SelectFile(var AFileName: string; const AExt: string): Boolean;
  315. var
  316. odFile: TOpenDialog;
  317. begin
  318. odFile := TOpenDialog.Create(nil);
  319. try
  320. odFile.Filter := GetFilter(AExt);
  321. if odFile.Execute then
  322. begin
  323. Application.ProcessMessages;
  324. AFileName := odFile.FileName;
  325. Result := True;
  326. end
  327. else
  328. Result := False;
  329. finally
  330. odFile.Free;
  331. end;
  332. end;
  333. function SelectFiles(AFiles: TStrings; const AExt: string): Boolean;
  334. var
  335. odFile: TOpenDialog;
  336. begin
  337. odFile := TOpenDialog.Create(nil);
  338. try
  339. odFile.Options := odFile.Options + [ofAllowMultiSelect];
  340. odFile.Filter := GetFilter(AExt);
  341. if odFile.Execute then
  342. begin
  343. Application.ProcessMessages;
  344. AFiles.Assign(odFile.Files);
  345. Result := True;
  346. end
  347. else
  348. Result := False;
  349. finally
  350. odFile.Free;
  351. end;
  352. end;
  353. function SaveFile(var FileName: string; const AExt: string): Boolean;
  354. var
  355. sdFile: TSaveDialog;
  356. begin
  357. sdFile := TSaveDialog.Create(nil);
  358. try
  359. sdFile.FileName := FileName;
  360. sdFile.DefaultExt := AExt;
  361. sdFile.Filter := GetFilter(AExt);
  362. Result := sdFile.Execute;
  363. if Result then
  364. FileName := sdFile.FileName;
  365. Application.ProcessMessages;
  366. finally
  367. sdFile.Free;
  368. end;
  369. end;
  370. function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
  371. AParentHandle: THandle; AHasNewFolderBtn: Boolean): Boolean;
  372. var
  373. pID: PItemIDList;
  374. bInfo: TBrowseInfo;
  375. AHandle: THandle;
  376. PStr: array[0..1023] of Char;
  377. sPath: string;
  378. function BFCallBack(Hwnd: HWND; uMsg: UINT; lParam, lpData: LPARAM): Integer; stdcall;
  379. begin
  380. if uMsg = BFFM_INITIALIZED then
  381. begin
  382. SendMessage(Hwnd, BFFM_SETSELECTION, 1, lpData);
  383. end;
  384. Result := 0;
  385. end;
  386. begin
  387. Result := False;
  388. if AParentHandle = 0 then
  389. AHandle := Screen.ActiveForm.Handle
  390. else
  391. AHandle := AParentHandle;
  392. if ADirectory = '' then
  393. sPath := GetAppFilePath
  394. else
  395. sPath := ADirectory;
  396. with bInfo do
  397. begin
  398. hwndOwner := AParentHandle;
  399. iImage := 0;
  400. lParam := Integer(PChar(sPath));
  401. lpszTitle := PChar(ATitle);
  402. pidlRoot := nil;
  403. pszDisplayName := nil;
  404. if AHasNewFolderBtn then
  405. ulFlags := BIF_RETURNONLYFSDIRS or BIF_USENEWUI
  406. else
  407. ulFlags := BIF_RETURNONLYFSDIRS;
  408. lpfn := @BFCallBack;
  409. end;
  410. pID := SHBrowseForFolder(bInfo);
  411. if pID <> nil then
  412. begin
  413. SHGetPathFromIDList(pID, PStr);
  414. ADirectory := StrPas(PStr);
  415. if (ADirectory <> '') and (ADirectory[Length(ADirectory)] <> '\') then
  416. ADirectory := ADirectory + '\';
  417. Result := True;
  418. end;
  419. end;
  420. function FixPathByAppPath(AFileName: string): string;
  421. begin
  422. Result := AFileName;
  423. if AnsiPos(':\', Result) = 0 then
  424. begin
  425. if (Result <> '') and (Result[1] = '\') then
  426. Delete(Result, 1, 1);
  427. Result := ExtractFilePath(Application.ExeName) + Result;
  428. end;
  429. end;
  430. var
  431. PathStr: string;
  432. function BrowseFolder(var APath: string; const ATitle: string; AParentHandle: THandle;
  433. AHasNewFolderBtn: Boolean): Boolean;
  434. function BFCallBackFunc(hwnd: HWND; uMsg: UINT; lParam: LPARAM; lpData: LPARAM): Integer; stdcall;
  435. begin
  436. Result := 0;
  437. case uMsg of
  438. BFFM_INITIALIZED : // 初始化设置目录。
  439. begin
  440. SendMessage(Hwnd,BFFM_SETSELECTION,-1,Integer(PathStr));
  441. end;
  442. end;
  443. end;
  444. var
  445. pID: PItemIDList;
  446. bInfo: TBrowseInfo;
  447. PStr: array[0..1023] of Char;
  448. sPath: string;
  449. Hdl: THandle;
  450. begin
  451. Result := False;
  452. PathStr := '';
  453. if AParentHandle = 0 then
  454. Hdl := Screen.ActiveForm.Handle
  455. else
  456. Hdl := AParentHandle;
  457. sPath := FixPathByAppPath(APath);
  458. if DirectoryExists(sPath) then
  459. PathStr := sPath;
  460. bInfo.hwndOwner := Hdl;
  461. bInfo.iImage := 0;
  462. bInfo.lParam := 0;
  463. bInfo.lpszTitle := PChar(ATitle);
  464. bInfo.pidlRoot := nil;
  465. bInfo.pszDisplayName := nil;
  466. if (not AHasNewFolderBtn) then
  467. bInfo.ulFlags := BIF_RETURNONLYFSDIRS
  468. else
  469. bInfo.ulFlags := BIF_RETURNONLYFSDIRS or BIF_USENEWUI;
  470. bInfo.lpfn := @BFCallBackFunc;
  471. pID := SHBrowseForFolder(bInfo);
  472. if pID <> nil then
  473. begin
  474. SHGetPathFromIDList(pID,pStr);
  475. APath := StrPas(pStr);
  476. if (APath <> '') and (APath[Length(APath)] <> '\') then
  477. APath := APath + '\';
  478. Result := True;
  479. end;
  480. end;
  481. {CheckStrings}
  482. function CheckPeg(const AStr: string): Boolean;
  483. function GetPosition(const AName, AStr, AStrSpare: string): Integer;
  484. begin
  485. Result := Pos(AStr, AName);
  486. if Result = 0 then
  487. Result := Pos(AStrSpare, AName);
  488. end;
  489. var
  490. iPosK, iPosPlus: Integer;
  491. fNum: Double;
  492. begin
  493. Result := False;
  494. iPosK := GetPosition(AStr, 'K', 'k');
  495. iPosPlus := GetPosition(AStr, '+', '+');
  496. if (iPosK = 0) or (iPosPlus = 0) or (iPosPlus < iPosK) then Exit;
  497. Result := TryStrToFloat(Copy(AStr, iPosK + 1, iPosPlus - iPosK - 1), fNum);
  498. end;
  499. function CheckValidPassword(APassword: string): Boolean;
  500. var
  501. iIndex, iLength: Integer;
  502. begin
  503. Result := True;
  504. if APassword = '' then Exit;
  505. iIndex := 1;
  506. iLength := Length(APassword);
  507. Result := (iLength >= 6) and (iLength <= 16);
  508. while Result and (iIndex < iLength) do
  509. begin
  510. Result := APassword[iIndex] in ['A'..'Z', 'a'..'z', '0'..'9'];
  511. Inc(iIndex);
  512. end;
  513. end;
  514. function ValidInteger(var AKey: Char): Boolean;
  515. begin
  516. if AKey in ['+', '-', '0'..'9', #8, #13, #35, #36,
  517. #37, #38, #39, #40, #46] then
  518. begin
  519. Result := True;
  520. end
  521. else
  522. begin
  523. AKey := #0;
  524. Result := False;
  525. end;
  526. end;
  527. {MergeStrings}
  528. function MergeRelaBGL(const ABGLCode1, ABGLCode2: string): string;
  529. var
  530. sgs1, sgs2: TStrings;
  531. i1, i2: Integer;
  532. bExist: Boolean;
  533. begin
  534. Result := ABGLCode1;
  535. sgs1 := TStringList.Create;
  536. sgs2 := TStringList.Create;
  537. try
  538. sgs1.Delimiter := ';';
  539. sgs2.Delimiter := ';';
  540. sgs1.DelimitedText := ABGLCode1;
  541. sgs2.DelimitedText := ABGLCode2;
  542. for i2 := 0 to sgs2.Count - 1 do
  543. begin
  544. bExist := False;
  545. for i1 := 0 to sgs1.Count - 1 do
  546. if SameText(sgs2[i2], sgs1[i1]) then
  547. begin
  548. bExist := True;
  549. Break;
  550. end;
  551. if not bExist then
  552. sgs1.Add(sgs2[i2]);
  553. end;
  554. Result := sgs1.DelimitedText;
  555. finally
  556. sgs1.Free;
  557. sgs2.Free;
  558. end;
  559. end;
  560. procedure MergeRelaBGLAndNum(var ABGLCode1, ABGLNum1: string; const ABGLCode2, ABGLNum2: string);
  561. var
  562. sgsC1, sgsC2, sgsN1, sgsN2: TStrings;
  563. i1, i2: Integer;
  564. bExist: Boolean;
  565. begin
  566. sgsC1 := TStringList.Create;
  567. sgsC2 := TStringList.Create;
  568. sgsN1 := TStringList.Create;
  569. sgsN2 := TStringList.Create;
  570. try
  571. sgsC1.Delimiter := ';';
  572. sgsC2.Delimiter := ';';
  573. sgsC1.DelimitedText := ABGLCode1;
  574. sgsC2.DelimitedText := ABGLCode2;
  575. sgsN1.Delimiter := ';';
  576. sgsN2.Delimiter := ';';
  577. sgsN1.DelimitedText := ABGLNum1;
  578. sgsN2.DelimitedText := ABGLNum2;
  579. for i2 := 0 to sgsC2.Count - 1 do
  580. begin
  581. bExist := False;
  582. for i1 := 0 to sgsC1.Count - 1 do
  583. if SameText(sgsC2[i2], sgsC1[i1]) then
  584. begin
  585. bExist := True;
  586. Break;
  587. end;
  588. if bExist then
  589. begin
  590. sgsN1[i1] := FloatToStr(StrToFloatDef(sgsN1[i1], 0) + StrToFloatDef(sgsN2[i2], 0))
  591. end
  592. else
  593. begin
  594. sgsC1.Add(sgsC2[i2]);
  595. sgsN1.Add(sgsN2[i2]);
  596. end;
  597. end;
  598. ABGLCode1 := sgsC1.DelimitedText;
  599. ABGLNum1 := sgsN1.DelimitedText;
  600. finally
  601. sgsC1.Free;
  602. sgsC2.Free;
  603. sgsN1.Free;
  604. sgsN2.Free;
  605. end;
  606. end;
  607. function B_CodeToIndexCode(const AB_Code: string): string;
  608. var
  609. sgs: TStrings;
  610. i, iNum, iError: Integer;
  611. sError: string;
  612. begin
  613. sgs := TStringList.Create;
  614. try
  615. Result := '';
  616. sgs.Delimiter := '-';
  617. sgs.DelimitedText := AB_Code;
  618. for i := 0 to sgs.Count - 1 do
  619. begin
  620. Val(sgs[i], iNum, iError);
  621. if iError = 0 then
  622. sError := ''
  623. else
  624. sError := Copy(sgs[i], iError, Length(sgs[i])-iError+1);
  625. if iError = 0 then
  626. Result := Result + Format('%4d', [iNum]) + Format('%-4s', [sError])
  627. else if iNum = 0 then
  628. Result := Result + '9999' + Format('%-4s', [sError])
  629. else
  630. Result := Result + Format('%4d', [iNum]) + Format('%-4s', [sError]);
  631. end;
  632. finally
  633. sgs.Free;
  634. end;
  635. end;
  636. function ChinessNum(const ADigitNum: Integer): string;
  637. function TransChineseNum(const ANum, AZeroNum: Integer): string;
  638. begin
  639. Result := '';
  640. case ANum of
  641. 1: if AZeroNum <> 1 then Result := '一';
  642. 2: Result := '二';
  643. 3: Result := '三';
  644. 4: Result := '四';
  645. 5: Result := '五';
  646. 6: Result := '六';
  647. 7: Result := '七';
  648. 8: Result := '八';
  649. 9: Result := '九';
  650. end;
  651. if (Result = '') and ((AZeroNum <> 1) or (ANum = 0)) then Exit;
  652. case AZeroNum of
  653. 0: Result := Result;
  654. 1: Result := Result + '十';
  655. 2: Result := Result + '百';
  656. 3: Result := Result + '千';
  657. 4: Result := Result + '万';
  658. end;
  659. end;
  660. var
  661. iBai, iShi, iGe: Integer;
  662. begin
  663. Result := '';
  664. if (ADigitNum < 0) and (ADigitNum > 10000) then Exit;
  665. iBai := ADigitNum div 100;
  666. iShi := (ADigitNum mod 100) div 10;
  667. iGe := (ADigitNum mod 100) mod 10;
  668. Result := TransChineseNum(iBai, 2) + TransChineseNum(iShi, 1) + TransChineseNum(iGe, 0);
  669. end;
  670. function CheckDigit(ANum: Double): Integer;
  671. begin
  672. if abs(ANum - advRoundTo(ANum, -2)) > 0.0001 then
  673. Result := 3
  674. else if abs(ANum - advRoundTo(ANum, -1)) > 0.001 then
  675. Result := 2
  676. else if abs(ANum - AdvRoundTo(ANum, 0)) > 0.01 then
  677. Result := 1
  678. else
  679. Result := 0;
  680. end;
  681. function Num2Peg(ANum: Double): string;
  682. var
  683. fMod: Double;
  684. iK, iDigit: Integer;
  685. sDigit: string;
  686. begin
  687. iK := Trunc(ANum/1000);
  688. fMod := Frac(ANum/1000)*1000;
  689. iDigit := CheckDigit(fMod);
  690. case iDigit of
  691. 3: sDigit := FormatFloat('000.000', AdvRoundTo(fMod, -3));
  692. 2: sDigit := FormatFloat('000.00', AdvRoundTo(fMod, -2));
  693. 1: sDigit := FormatFloat('000.0', AdvRoundTo(fMod, -1));
  694. 0: sDigit := FormatFloat('000', Trunc(AdvRoundTo(fMod, 0)));
  695. end;
  696. { case iDigit of
  697. 3: Result := Format('K%d+%3.3f', [iK, ]);
  698. 2: Result := Format('K%d+%3.2f', [iK, AdvRoundTo(fMod, -2)]);
  699. 1: Result := Format('K%d+%3.1f', [iK, AdvRoundTo(fMod, -1)]);
  700. 0: Result := Format('K%d+%s', [iK, FormatFloat('000', [])]);
  701. end; }
  702. Result := Format('K%d+%s', [iK, sDigit]);
  703. end;
  704. {Tree Relative}
  705. function CreateTree: TZjIDTree;
  706. begin
  707. Result := TZjIDTree.Create;
  708. Result.KeyFieldName := 'ID';
  709. Result.ParentFieldName := 'ParentID';
  710. Result.NextSiblingFieldName := 'NextSiblingID';
  711. Result.AutoCreateKeyID := True;
  712. Result.AutoExpand := True;
  713. end;
  714. procedure DisConnectTree(ATree: TZjIDTree);
  715. begin
  716. ATree.DataSet := nil;
  717. ATree.Active := False;
  718. end;
  719. procedure ConnectTree(ATree: TZjIDTree; ADataset: TDataSet);
  720. begin
  721. ATree.DataSet := ADataset;
  722. ATree.Active := True;
  723. end;
  724. procedure InitGridHead(AGridDBA: TZjGridDBA; AGrid: TZJGrid);
  725. var
  726. I: Integer;
  727. begin
  728. for I := 0 to AGridDBA.Columns.Count - 1 do
  729. AGrid.Cells[I + 1, 0].Text := AGridDBA.Columns[I].Title.Caption;
  730. end;
  731. {Generate Name/Path}
  732. function GetTempFileDir: string;
  733. var
  734. TempPath: string;
  735. begin
  736. TempPath := GetEnvironmentVariable('TMP');
  737. if TempPath = '' then
  738. TempPath := GetEnvironmentVariable('TEMP');
  739. if TempPath = '' then
  740. begin
  741. if not DirectoryExists(ExtractFileDir(ParamStr(0)) + '\Temp') then
  742. CreateDir(ExtractFileDir(ParamStr(0)) + '\Temp');
  743. TempPath := ExtractFileDir(ParamStr(0)) + '\Temp';
  744. end;
  745. Result := TempPath;
  746. end;
  747. function GetTempFilePath: string;
  748. begin
  749. Result := GetTempFileDir + '\';
  750. end;
  751. function GetTempName(ALength: Integer): string;
  752. const
  753. CodedBuf: array[0..35] of Char = ('0', '1', '2', '3', '4', '5',
  754. '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
  755. 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  756. 'W', 'X', 'Y', 'Z');
  757. var
  758. Temp: string;
  759. Num: Integer;
  760. begin
  761. Randomize;
  762. Temp := '';
  763. while Length(Temp) < ALength do
  764. begin
  765. Num := Random(37);
  766. If Num <> 36 Then
  767. Temp := Temp + CodedBuf[Num]; // 0..35
  768. end;
  769. Result := Temp;
  770. end;
  771. function GetTempFileName: string;
  772. var
  773. TempExt: string;
  774. begin
  775. Result := GetTempFilePath + GetTempName;
  776. TempExt := '.' + GetTempName(3);
  777. while SameText(TempExt, '.mdb') or SameText(TempExt, '.db') or
  778. SameText(TempExt, '.ldb') do
  779. TempExt := '.' + GetTempName(3);
  780. Result := Result + TempExt;
  781. while FileExists(Result) do
  782. begin
  783. Result := GetTempFilePath + GetTempName;
  784. TempExt := '.' + GetTempName(3);
  785. while SameText(TempExt, '.mdb') or SameText(TempExt, '.db') or
  786. SameText(TempExt, '.ldb') do
  787. TempExt := '.' + GetTempName(3);
  788. Result := Result + TempExt;
  789. end;
  790. end;
  791. function GetTempFileName(const APath, AExt: string): string;
  792. begin
  793. Result := APath + GetTempName + AExt;
  794. while FileExists(Result) do
  795. Result := APath + GetTempName + AExt;
  796. end;
  797. function GenerateTempFolder(AGeneratePath: string): string;
  798. begin
  799. Result := AGeneratePath + GetTempName;
  800. while DirectoryExists(Result) do
  801. Result := AGeneratePath + GetTempName;
  802. CreateDirectoryInDeep(Result);
  803. end;
  804. function GetNewGUIDFileName(const AGeneratePath: string): string;
  805. var
  806. gFile: TGUID;
  807. begin
  808. repeat
  809. CreateGUID(gFile);
  810. Result := AGeneratePath + GUIDToString(gFile);
  811. until not FileExists(Result);
  812. end;
  813. {Progress bar Control}
  814. procedure UpdateSysProgress(APosition: Integer; const AHint: string);
  815. begin
  816. if not SysProgressDisabled then
  817. UpdateProgress(APosition, AHint);
  818. end;
  819. procedure UpdateProgress(APosition: Integer; const AHint: string);
  820. begin
  821. MainForm.UpdateProgress(APosition, AHint);
  822. end;
  823. procedure DisableSysProgress;
  824. begin
  825. SysProgressDisabled := True;
  826. end;
  827. procedure EnableSysProgress;
  828. begin
  829. SysProgressDisabled := False;
  830. end;
  831. {Interface RePaint Control}
  832. procedure BeginUpdateWindow(AHandle: THandle);
  833. begin
  834. SendMessage(AHandle, WM_SETREDRAW, 0, 0);
  835. end;
  836. procedure EndUpdateWindow(AHandle: THandle);
  837. begin
  838. SendMessage(AHandle, WM_SETREDRAW, 1, 0);
  839. end;
  840. {Zip}
  841. function ZipComplete(const AFileName: string; ACheckMode: Integer): Boolean;
  842. const
  843. i4k = 4096;
  844. var
  845. iSize1, iSize2: Integer;
  846. begin
  847. iSize1 := FileSizeByName(AFileName);
  848. Sleep(300);
  849. iSize2 := FileSizeByName(AFileName);
  850. Result := (iSize1 = iSize2);
  851. if ACheckMode = 0 then
  852. Result := Result and (iSize1 > i4k);
  853. end;
  854. procedure ZipFolder(AFileFolder, AFileName: string; ACheckMode: Integer = 0);
  855. procedure AppendLog(const ALog: string);
  856. begin
  857. if SupportManager.ConfigInfo.IsLog then
  858. MeasureLog.AppendLogTo(ALog);
  859. end;
  860. var
  861. sTempFile: string;
  862. vZip: TVCLZip;
  863. iCount: Integer;
  864. begin
  865. AppendLog('Zip');
  866. sTempFile := GetTempFileName;
  867. vZip := TVCLZip.Create(nil);
  868. iCount := 0;
  869. try
  870. vZip.FilesList.Clear;
  871. vZip.ZipName := sTempFile;
  872. vzip.RootDir := AFileFolder;
  873. vZip.OverwriteMode := Always;
  874. //vZip.AddDirEntriesOnRecurse:=True;
  875. vZip.RelativePaths := True;
  876. //vZip.RecreateDirs := True;
  877. vZip.FilesList.Add(AFileFolder + '\*.*');
  878. vZip.Zip;
  879. AppendLog(Format('Check Zip File, FileSize - %d', [FileSizeByName(sTempFile)]));
  880. while not ZipComplete(sTempFile, ACheckMode) and (iCount < 10) do
  881. begin
  882. Sleep(200);
  883. Inc(iCount);
  884. AppendLog(Format('Check Zip File - %d, FileSize - %d', [iCount + 1, FileSizeByName(sTempFile)]));
  885. end;
  886. AppendLog('Check Zip File --> Pass');
  887. CopyFileOrFolder(sTempFile, AFileName);
  888. AppendLog('Zip --> Pass');
  889. finally
  890. vZip.Free;
  891. if FileExists(sTempFile) then
  892. DeleteFile(sTempFile);
  893. end;
  894. end;
  895. function UnZipFile(AFileName, AFileFolder: string): Boolean;
  896. var
  897. vUnZip: TVCLZip;
  898. begin
  899. Result := True;
  900. vUnZip := TVCLZip.Create(nil);
  901. try
  902. vUnZip.FilesList.Clear;
  903. vUnZip.ZipName := AFileName;
  904. vUnZip.ReadZip;
  905. vUnZip.DestDir := AFileFolder;
  906. vUnZip.OverwriteMode := Always;
  907. vUnZip.RecreateDirs := True;
  908. vUnZip.RelativePaths := True;
  909. vUnZip.DoAll := True;
  910. vUnZip.FilesList.Add('*.*');
  911. try
  912. vUnZip.UnZip;
  913. except
  914. Result := False;
  915. end;
  916. finally
  917. vUnZip.Free;
  918. end;
  919. end;
  920. {Copy By Stream}
  921. procedure CopyFileByStream(const ASourceFile, ADestFile: string);
  922. var
  923. MS: TMemoryStream;
  924. begin
  925. MS := TMemoryStream.Create;
  926. try
  927. MS.LoadFromFile(ASourceFile);
  928. if FileExists(ADestFile) then
  929. DeleteFile(ADestFile);
  930. MS.SaveToFile(ADestFile);
  931. finally
  932. MS.Free;
  933. end;
  934. end;
  935. procedure AppendTestLog(const AFileName, ALog: string);
  936. var
  937. f: TextFile;
  938. begin
  939. try
  940. if FileExists(AFileName) then
  941. begin
  942. AssignFile(f, AFileName);
  943. Append(f);
  944. Writeln(f, ALog);
  945. end
  946. else
  947. begin
  948. AssignFile(f, AFileName);
  949. Rewrite(f);
  950. Writeln(f, ALog);
  951. end;
  952. finally
  953. CloseFile(f);
  954. end;
  955. end;
  956. function GetVersion(APartCount: Integer = 4): string;
  957. var
  958. V1, V2, V3, V4: Word;
  959. FInfoSize, FF: Cardinal;
  960. FInfo: Pointer;
  961. FFixed: PVSFIXEDFILEINFO;
  962. begin
  963. FInfoSize := GetFileVersionInfoSize(PChar(Application.ExeName), FF);
  964. FInfo := AllocMem(FInfoSize);
  965. try
  966. GetFileVersionInfo(PChar(Application.ExeName), FF, FInfoSize, FInfo);
  967. VerQueryValue(FInfo, '\', Pointer(FFixed), FInfoSize);
  968. V1 := FFixed.dwFileVersionMS shr 16;
  969. V2 := FFixed.dwFileVersionMS and $FFFF;
  970. V3 := FFixed.dwFileVersionLS shr 16;
  971. V4 := FFixed.dwFileVersionLS and $FFFF;
  972. finally
  973. Dispose(FInfo);
  974. end;
  975. Result := '';
  976. case APartCount of
  977. 1:
  978. Result := Format('%d', [V1]);
  979. 2:
  980. Result := Format('%d.%d', [V1, V2]);
  981. 3:
  982. Result := Format('%d.%d.%d', [V1, V2, V3]);
  983. 4:
  984. Result := Format('%d.%d.%d.%d', [V1, V2, V3, V4]);
  985. end;
  986. end;
  987. function ExtractFileNameWithoutExt(const AFileName: string): string;
  988. var
  989. sFileName, Ext: string;
  990. begin
  991. Result := '';
  992. if AFileName = '' then
  993. Exit;
  994. sFileName := AFileName;
  995. if sFileName[Length(sFileName)] = '\' then
  996. Delete(sFileName, Length(sFileName), 1);
  997. Result := ExtractFileName(sFileName);
  998. Ext := ExtractFileExt(sFileName);
  999. Delete(Result, Length(Result) - Length(Ext) + 1, Length(Ext));
  1000. end;
  1001. function ShortText(AText: string; AWidth: Integer): string;
  1002. var vMM: TMemo;
  1003. begin
  1004. if Trim(AText) = '' then
  1005. begin
  1006. Result := '';
  1007. Exit;
  1008. end;
  1009. vMM := TMemo.Create(nil);
  1010. try
  1011. vMM.Visible := False;
  1012. vMM.WordWrap := True;
  1013. vMM.parent := Application.MainForm;
  1014. vMM.Width := AWidth - 10; // 10像素留给3个小点
  1015. vMM.Text := AText;
  1016. if vMM.Lines.Count > 1 then
  1017. Result := vMM.Lines[0] + '...'
  1018. else
  1019. Result := AText;
  1020. finally
  1021. vMM.Free;
  1022. end;
  1023. end;
  1024. function CustomWidthText(AText: string; AWidth: Integer): string;
  1025. var vMM: TMemo;
  1026. i: Integer;
  1027. begin
  1028. if Trim(AText) = '' then
  1029. begin
  1030. Result := '';
  1031. Exit;
  1032. end;
  1033. vMM := TMemo.Create(nil);
  1034. try
  1035. vMM.Visible := False;
  1036. vMM.WordWrap := True;
  1037. vMM.parent := Application.MainForm;
  1038. vMM.Width := AWidth;
  1039. vMM.Text := AText;
  1040. for i := 0 to vMM.Lines.Count - 1 do
  1041. begin
  1042. if i = 0 then
  1043. Result := vMM.Lines[i]
  1044. else
  1045. Result := Result + #10#13 + vMM.Lines[i];
  1046. end;
  1047. finally
  1048. vMM.Free;
  1049. end;
  1050. end;
  1051. function ReplaceCharsForJson(AText: string): string;
  1052. const
  1053. BefChar: array [0..7] of Char = ('{', '}', ',', ':', '"', '[', ']', '%');
  1054. AftChar: array [0..7] of string = ('{', '}', ',', ':', '"', '【', '】', '♂');
  1055. var I: Integer;
  1056. begin
  1057. AText := Trim(AText);
  1058. Result := AText;
  1059. if AText = '' then Exit;
  1060. for I := low(BefChar) to High(BefChar) do
  1061. begin
  1062. if Pos(BefChar[I], AText) > 0 then
  1063. AText := StringReplace(AText, BefChar[I], AftChar[I], [rfReplaceAll]);
  1064. end;
  1065. Result := AText;
  1066. end;
  1067. function RecoverCharsFromJson(AText: string): string;
  1068. const
  1069. BefStr: array [0..3] of string = ('♂', '\r\n', '\r', '\n');
  1070. AftStr: array [0..3] of string = ('%', '', '', '');
  1071. var I: Integer;
  1072. begin
  1073. AText := Trim(AText);
  1074. Result := AText;
  1075. if AText = '' then Exit;
  1076. for I := low(BefStr) to High(BefStr) do
  1077. begin
  1078. if Pos(BefStr[I], AText) > 0 then
  1079. AText := StringReplace(AText, BefStr[I], AftStr[I], [rfReplaceAll]);
  1080. end;
  1081. Result := AText;
  1082. end;
  1083. procedure FindFiles(APath, AExtName: string; AFileList: TStrings);
  1084. var
  1085. SRec: TSearchRec;
  1086. retval: Integer;
  1087. begin
  1088. AFileList.Clear;
  1089. retval := FindFirst(APath + AExtName, faAnyFile, sRec);
  1090. try
  1091. while retval = 0 do
  1092. begin
  1093. if (SRec.Attr and faDirectory) = 0 then
  1094. AFileList.Add(Srec.Name);
  1095. retval := FindNext(SRec);
  1096. end;
  1097. finally
  1098. FindClose(SRec);
  1099. end;
  1100. end;
  1101. function DeleteFolder(const FolderStr: string): Boolean;
  1102. var
  1103. fos: SHFILEOPSTRUCT;
  1104. begin
  1105. ZeroMemory(@fos, SizeOf(fos));
  1106. fos.Wnd := HWND_DESKTOP;
  1107. fos.wFunc := FO_DELETE;
  1108. fos.fFlags := FOF_SILENT OR FOF_ALLOWUNDO OR FOF_NOCONFIRMATION;
  1109. fos.pFrom := PChar(FolderStr + #0);
  1110. Result := SHFileOperation(fos) <> 0;
  1111. end;
  1112. function HasExt(const AFileName: string): Boolean;
  1113. begin
  1114. Result := ExtractFileExt(AFileName) <> '';
  1115. end;
  1116. function CopyFolder(const SrcFolder, DstFolder: string): Boolean;
  1117. var
  1118. fos: SHFILEOPSTRUCT;
  1119. begin
  1120. ZeroMemory(@fos, SizeOf(fos));
  1121. fos.Wnd := HWND_DESKTOP;
  1122. fos.wFunc := FO_COPY;
  1123. fos.fFlags := FOF_SILENT OR FOF_ALLOWUNDO;
  1124. fos.pFrom := PChar(SrcFolder + #0);
  1125. fos.pTo := PChar(DstFolder + #0);
  1126. Result := SHFileOperation(fos) <> 0;
  1127. end;
  1128. function FileCount(APath: string): Integer;
  1129. var
  1130. vSR: TSearchRec;
  1131. iRetval: Integer;
  1132. vSL: TStringList;
  1133. begin
  1134. vSL := TStringList.Create;
  1135. iRetval := FindFirst(APath + '*.*', faAnyFile, vSR);
  1136. try
  1137. while iRetval = 0 do
  1138. begin
  1139. if (vSR.Attr and faDirectory) = 0 then
  1140. vSL.Add(vSR.Name);
  1141. iRetval := FindNext(vSR);
  1142. end;
  1143. Result := vSL.Count;
  1144. finally
  1145. FindClose(vSR);
  1146. vSL.Free;
  1147. end;
  1148. end;
  1149. end.