UtilMethods.pas 28 KB

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