UtilMethods.pas 29 KB

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