UtilMethods.pas 28 KB

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