UtilMethods.pas 30 KB

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