UtilMethods.pas 28 KB

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