UtilMethods.pas 26 KB

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