UtilMethods.pas 30 KB

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