UtilMethods.pas 26 KB

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