UtilMethods.pas 26 KB

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