UtilMethods.pas 30 KB

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