UtilMethods.pas 27 KB

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