BillsClipboard.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. unit BillsClipboard;
  2. interface
  3. uses
  4. Clipbrd, Classes, BillsDm, ZhAPI, XmlDoc, XmlIntf, Windows, sdIDTree;
  5. type
  6. TInnerClipboard = class(TClipboard);
  7. TBillsBlockNode = class
  8. private
  9. FID: Integer;
  10. FParentID: Integer;
  11. FNextSiblingID: Integer;
  12. FCode: string;
  13. FB_Code: string;
  14. FName: string;
  15. FUnits: string;
  16. FPrice: Double;
  17. FOrgQuantity: Double;
  18. FMisQuantity: Double;
  19. FOthQuantity: Double;
  20. FQuantity: Double;
  21. FDrawingCode: string;
  22. FAlias: string;
  23. FDgnQuantity1: Double;
  24. FDgnQuantity2: Double;
  25. FMemoStr: string;
  26. FDealCode: string;
  27. FDealCompany: string;
  28. public
  29. procedure SaveToXmlNode(AXmlNode: IXMLNode);
  30. procedure LoadFromXmlNode(AXmlNode: IXMLNode);
  31. end;
  32. TBillsClipboard = class
  33. private
  34. FStream: TMemoryStream;
  35. FBillsData: TBillsData;
  36. FNodeList: TList;
  37. procedure SaveToClipboard(AFormat: Word);
  38. procedure LoadFromClipboard(AFormat: Word);
  39. procedure SaveToStream;
  40. procedure LoadFromStream;
  41. procedure SaveToXmlFile(const AFileName: string);
  42. procedure LoadFromXmlFile(const AFileName: string);
  43. procedure SaveNodesToXml(AXmlNode: IXMLNode);
  44. procedure LoadNodesFromXml(AXmlNode: IXMLNode);
  45. procedure CopyBillsNodeData(ANode: TsdIDTreeNode);
  46. procedure CopyBillsNode(ANode: TsdIDTreeNode);
  47. procedure CopyData(ANode: TsdIDTreeNode; ACount: Integer);
  48. function AddBillsNode(ANode: TsdIDTreeNode; APos: Integer): TsdIDTreeNode;
  49. procedure PasteBillsNodeData(ANode: TsdIDTreeNode; APasteNode: TBillsBlockNode);
  50. procedure PasteChildren(AParentNode: TsdIDTreeNode; APasteParentID: Integer);
  51. procedure PasteNextSibling(APreSibling: TsdIDTreeNode; APasteNodeID: Integer);
  52. procedure PasteBillsNode(ANode: TsdIDTreeNode; APos: Integer; APasteNode: TBillsBlockNode);
  53. procedure PasteData(ANode: TsdIDTreeNode; APos: Integer);
  54. procedure Clear;
  55. public
  56. constructor Create(ABillsData: TBillsData);
  57. destructor Destroy; override;
  58. procedure Copy(ANode: TsdIDTreeNode; ACount: Integer);
  59. // APos: 0[×ÓÏî] 1[ºóÏî] 2[ǰÏî]
  60. procedure Paste(ANode: TsdIDTreeNode; APos: Integer);
  61. end;
  62. function HasBillsBlockFormat: Boolean;
  63. implementation
  64. uses sdDB, Math, SysUtils, UtilMethods;
  65. var
  66. CF_BillsBlock: Word;
  67. function HasBillsBlockFormat: Boolean;
  68. begin
  69. Result := Clipboard.HasFormat(CF_BillsBlock);
  70. end;
  71. { TBillsClipboard }
  72. function TBillsClipboard.AddBillsNode(ANode: TsdIDTreeNode;
  73. APos: Integer): TsdIDTreeNode;
  74. begin
  75. // ×ÓÏî²åÈë
  76. if APos = 0 then
  77. Result := ANode.Owner.Add(ANode.ID, -1)
  78. // ºóÏî²åÈë
  79. else if APos = 1 then
  80. Result := ANode.Owner.Add(ANode.ParentID, ANode.NextSiblingID)
  81. // ǰÏî²åÈë
  82. else if APos = 2 then
  83. Result := ANode.Owner.Add(ANode.ParentID, ANode.ID);
  84. end;
  85. procedure TBillsClipboard.Clear;
  86. begin
  87. ClearObjects(FNodeList);
  88. FNodeList.Clear;
  89. end;
  90. procedure TBillsClipboard.Copy(ANode: TsdIDTreeNode; ACount: Integer);
  91. begin
  92. Clear;
  93. CopyData(ANode, ACount);
  94. SaveToStream;
  95. SaveToClipboard(CF_BillsBlock);
  96. end;
  97. procedure TBillsClipboard.CopyBillsNode(ANode: TsdIDTreeNode);
  98. var
  99. iChild: Integer;
  100. begin
  101. if Assigned(ANode) then
  102. begin
  103. CopyBillsNodeData(ANode);
  104. for iChild := 0 to ANode.ChildCount - 1 do
  105. CopyBillsNode(ANode.ChildNodes[iChild]);
  106. end;
  107. end;
  108. procedure TBillsClipboard.CopyBillsNodeData(ANode: TsdIDTreeNode);
  109. var
  110. vNode: TBillsBlockNode;
  111. begin
  112. vNode := TBillsBlockNode.Create;
  113. FNodeList.Add(vNode);
  114. vNode.FID := ANode.Rec.ValueByName('ID').AsInteger;
  115. vNode.FParentID := ANode.Rec.ValueByName('ParentID').AsInteger;
  116. vNode.FNextSiblingID := ANode.Rec.ValueByName('NextSiblingID').AsInteger;
  117. vNode.FCode := ANode.Rec.ValueByName('Code').AsString;
  118. vNode.FB_Code := ANode.Rec.ValueByName('B_Code').AsString;
  119. vNode.FName := ANode.Rec.ValueByName('Name').AsString;
  120. vNode.FUnits := ANode.Rec.ValueByName('Units').AsString;
  121. vNode.FPrice := ANode.Rec.ValueByName('Price').AsFloat;
  122. vNode.FOrgQuantity := ANode.Rec.ValueByName('OrgQuantity').AsFloat;
  123. vNode.FMisQuantity := ANode.Rec.ValueByName('MisQuantity').AsFloat;
  124. vNode.FOthQuantity := ANode.Rec.ValueByName('OthQuantity').AsFloat;
  125. vNode.FQuantity := ANode.Rec.ValueByName('Quantity').AsFloat;
  126. vNode.FDrawingCode := ANode.Rec.ValueByName('DrawingCode').AsString;
  127. vNode.FAlias := ANode.Rec.ValueByName('Alias').AsString;
  128. vNode.FDgnQuantity1 := ANode.Rec.ValueByName('DgnQuantity1').AsFloat;
  129. vNode.FDgnQuantity2 := ANode.Rec.ValueByName('DgnQuantity2').AsFloat;
  130. vNode.FMemoStr := ANode.Rec.ValueByName('MemoStr').AsString;
  131. vNode.FDealCode := ANode.Rec.ValueByName('DealCode').AsString;
  132. vNode.FDealCompany := ANode.Rec.ValueByName('DealCompany').AsString;
  133. end;
  134. procedure TBillsClipboard.CopyData(ANode: TsdIDTreeNode; ACount: Integer);
  135. begin
  136. while Assigned(ANode) and (ACount > 0) do
  137. begin
  138. CopyBillsNode(ANode);
  139. Dec(ACount, ANode.PosterityCount + 1);
  140. ANode := ANode.NextSibling;
  141. end;
  142. end;
  143. constructor TBillsClipboard.Create(ABillsData: TBillsData);
  144. begin
  145. FStream := TMemoryStream.Create;
  146. FBillsData := ABillsData;
  147. FNodeList := TList.Create;
  148. end;
  149. destructor TBillsClipboard.Destroy;
  150. begin
  151. ClearObjects(FNodeList);
  152. FNodeList.Free;
  153. FStream.Free;
  154. inherited;
  155. end;
  156. procedure TBillsClipboard.LoadFromClipboard(AFormat: Word);
  157. procedure LockAndLoadData(AData: THandle);
  158. var
  159. DataPtr: Pointer;
  160. begin
  161. DataPtr := GlobalLock(AData);
  162. try
  163. FStream.WriteBuffer(DataPtr^, GlobalSize(AData));
  164. FStream.Position := 0;
  165. finally
  166. GlobalUnlock(AData);
  167. end;
  168. end;
  169. var
  170. Data: THandle;
  171. begin
  172. Clipboard.Open;
  173. try
  174. Data := GetClipboardData(AFormat);
  175. if Data <> 0 then
  176. LockAndLoadData(Data);
  177. finally
  178. Clipboard.Close;
  179. end;
  180. end;
  181. procedure TBillsClipboard.LoadFromStream;
  182. var
  183. FXmlDocument: IXMLDocument;
  184. I: Integer;
  185. begin
  186. FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument;
  187. try
  188. FXmlDocument.LoadFromStream(FStream);
  189. FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl];
  190. LoadNodesFromXml(FXmlDocument.DocumentElement);
  191. finally
  192. FXmlDocument := nil;
  193. end;
  194. end;
  195. procedure TBillsClipboard.LoadFromXmlFile(const AFileName: string);
  196. var
  197. FXmlDocument: IXMLDocument;
  198. I: Integer;
  199. begin
  200. FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument;
  201. try
  202. FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAutoPrefix,doNamespaceDecl];
  203. if not FileExists(AFileName) then Exit;
  204. FXmlDocument.LoadFromFile(AFileName);
  205. LoadNodesFromXml(FXmlDocument.DocumentElement);
  206. finally
  207. FXmlDocument := nil;
  208. end;
  209. end;
  210. procedure TBillsClipboard.LoadNodesFromXml(AXmlNode: IXMLNode);
  211. var
  212. BillsBlockNode: TBillsBlockNode;
  213. iNum: Integer;
  214. ParentXmlNode, CurXmlNode: IXMLNode;
  215. begin
  216. ParentXmlNode := AXmlNode.ChildNodes.FindNode('BillsBlockNodes');
  217. for iNum := 0 to ParentXmlNode.ChildNodes.Count - 1 do
  218. begin
  219. CurXmlNode := ParentXmlNode.ChildNodes.Nodes[iNum];
  220. BillsBlockNode := TBillsBlockNode.Create;
  221. FNodeList.Add(BillsBlockNode);
  222. BillsBlockNode.LoadFromXmlNode(CurXmlNode);
  223. end;
  224. end;
  225. procedure TBillsClipboard.Paste(ANode: TsdIDTreeNode; APos: Integer);
  226. begin
  227. Clear;
  228. LoadFromClipboard(CF_BillsBlock);
  229. LoadFromStream;
  230. PasteData(ANode, APos);
  231. end;
  232. procedure TBillsClipboard.PasteBillsNode(ANode: TsdIDTreeNode;
  233. APos: Integer; APasteNode: TBillsBlockNode);
  234. var
  235. stnCurrent: TsdIDTreeNode;
  236. begin
  237. stnCurrent := AddBillsNode(ANode, APos);
  238. PasteBillsNodeData(stnCurrent, APasteNode);
  239. PasteChildren(stnCurrent, APasteNode.FID);
  240. PasteNextSibling(stnCurrent, APasteNode.FNextSiblingID);
  241. end;
  242. procedure TBillsClipboard.PasteBillsNodeData(ANode: TsdIDTreeNode;
  243. APasteNode: TBillsBlockNode);
  244. begin
  245. ANode.Rec.ValueByName('Code').AsString := APasteNode.FCode;
  246. ANode.Rec.ValueByName('B_Code').AsString := APasteNode.FB_Code;
  247. ANode.Rec.ValueByName('Name').AsString := APasteNode.FName;
  248. ANode.Rec.ValueByName('Units').AsString := APasteNode.FUnits;
  249. ANode.Rec.ValueByName('Price').AsFloat := APasteNode.FPrice;
  250. ANode.Rec.ValueByName('OrgQuantity').AsFloat := QuantityRoundTo(APasteNode.FOrgQuantity);
  251. ANode.Rec.ValueByName('MisQuantity').AsFloat := QuantityRoundTo(APasteNode.FMisQuantity);
  252. ANode.Rec.ValueByName('OthQuantity').AsFloat := QuantityRoundTo(APasteNode.FOthQuantity);
  253. ANode.Rec.ValueByName('Quantity').AsFloat := QuantityRoundTo(APasteNode.FQuantity);
  254. ANode.Rec.ValueByName('DrawingCode').AsString := APasteNode.FDrawingCode;
  255. ANode.Rec.ValueByName('Alias').AsString := APasteNode.FAlias;
  256. ANode.Rec.ValueByName('DgnQuantity1').AsFloat := QuantityRoundTo(APasteNode.FDgnQuantity1);
  257. ANode.Rec.ValueByName('DgnQuantity2').AsFloat := QuantityRoundTo(APasteNode.FDgnQuantity2);
  258. ANode.Rec.ValueByName('MemoStr').AsString := APasteNode.FMemoStr;
  259. ANode.Rec.ValueByName('DealCode').AsString := APasteNode.FDealCode;
  260. ANode.Rec.ValueByName('DealCompany').AsString := APasteNode.FDealCompany;
  261. end;
  262. procedure TBillsClipboard.PasteChildren(AParentNode: TsdIDTreeNode;
  263. APasteParentID: Integer);
  264. var
  265. iNode: Integer;
  266. begin
  267. for iNode := 0 to FNodeList.Count - 1 do
  268. if TBillsBlockNode(FNodeList.Items[iNode]).FParentID = APasteParentID then
  269. begin
  270. PasteBillsNode(AParentNode, 0, TBillsBlockNode(FNodeList.Items[iNode]));
  271. Break;
  272. end;
  273. end;
  274. procedure TBillsClipboard.PasteData(ANode: TsdIDTreeNode; APos: Integer);
  275. var
  276. I: Integer;
  277. vPasteNode: TBillsBlockNode;
  278. begin
  279. PasteBillsNode(ANode, APos, TBillsBlockNode(FNodeList.First));
  280. end;
  281. procedure TBillsClipboard.PasteNextSibling(APreSibling: TsdIDTreeNode;
  282. APasteNodeID: Integer);
  283. var
  284. iNode: Integer;
  285. begin
  286. if APasteNodeID = -1 then Exit;
  287. for iNode := 0 to FNodeList.Count - 1 do
  288. if TBillsBlockNode(FNodeList.Items[iNode]).FID = APasteNodeID then
  289. begin
  290. PasteBillsNode(APreSibling, 1, TBillsBlockNode(FNodeList.Items[iNode]));
  291. Break;
  292. end;
  293. end;
  294. procedure TBillsClipboard.SaveNodesToXml(AXmlNode: IXMLNode);
  295. var
  296. ParentXmlNode, CurXmlNode: IXMLNode;
  297. iNum: Integer;
  298. BillsBlockNode: TBillsBlockNode;
  299. begin
  300. ParentXmlNode := AXmlNode.AddChild('BillsBlockNodes');
  301. for iNum := 0 to FNodeList.Count - 1 do
  302. begin
  303. BillsBlockNode := TBillsBlockNode(FNodeList.Items[iNum]);
  304. CurXmlNode := ParentXmlNode.AddChild('BillsBlockNode');
  305. BillsBlockNode.SaveToXmlNode(CurXmlNode);
  306. end;
  307. end;
  308. procedure TBillsClipboard.SaveToClipboard(AFormat: Word);
  309. begin
  310. Clipboard.Open;
  311. try
  312. EmptyClipboard;
  313. FStream.Position := 0;
  314. TInnerClipboard(Clipboard).SetBuffer(AFormat, FStream.Memory^, FStream.Size);
  315. finally
  316. Clipboard.Close;
  317. end;
  318. end;
  319. procedure TBillsClipboard.SaveToStream;
  320. var
  321. FXmlDocument: IXMLDocument;
  322. I: Integer;
  323. begin
  324. FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument;
  325. try
  326. FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAttrNull,doAutoPrefix,doNamespaceDecl];
  327. FXmlDocument.Active := True;
  328. FXmlDocument.Encoding := 'GB2312';
  329. FXmlDocument.AddChild('BillsBlock_M');
  330. SaveNodesToXml(FXmlDocument.DocumentElement);
  331. FXmlDocument.SaveToStream(FStream);
  332. finally
  333. FXmlDocument := nil;
  334. end;
  335. end;
  336. procedure TBillsClipboard.SaveToXmlFile(const AFileName: string);
  337. var
  338. FXmlDocument: IXMLDocument;
  339. I: Integer;
  340. begin
  341. FXmlDocument := TXMLDocument.Create(nil) as IXMLDocument;
  342. try
  343. FXmlDocument.Options := [doNodeAutoCreate,doNodeAutoIndent,doAttrNull,doAutoPrefix,doNamespaceDecl];
  344. FXmlDocument.Active := True;
  345. FXmlDocument.Encoding := 'GB2312';
  346. FXmlDocument.AddChild('BillsBlock_M');
  347. SaveNodesToXml(FXmlDocument.DocumentElement);
  348. FXmlDocument.SaveToFile(AFileName);
  349. finally
  350. FXmlDocument := nil;
  351. end;
  352. end;
  353. { TBillsBlockNode }
  354. procedure TBillsBlockNode.LoadFromXmlNode(AXmlNode: IXMLNode);
  355. begin
  356. FID := AXmlNode.Attributes['ID'];
  357. FParentID := AXmlNode.Attributes['ParentID'];
  358. FNextSiblingID := AXmlNode.Attributes['NextSiblingID'];
  359. FCode := AXmlNode.Attributes['Code'];
  360. FB_Code := AXmlNode.Attributes['B_Code'];
  361. FName := AXmlNode.Attributes['Name'];
  362. FUnits := AXmlNode.Attributes['Units'];
  363. FPrice := AXmlNode.Attributes['Price'];
  364. FOrgQuantity := AXmlNode.Attributes['OrgQuantity'];
  365. FMisQuantity := AXmlNode.Attributes['MisQuantity'];
  366. FOthQuantity := AXmlNode.Attributes['OthQuantity'];
  367. FQuantity := AXmlNode.Attributes['Quantity'];
  368. FDrawingCode := AXmlNode.Attributes['DrawingCode'];
  369. FAlias := AXmlNode.Attributes['Alias'];
  370. FDgnQuantity1 := AXmlNode.Attributes['DgnQuantity1'];
  371. FDgnQuantity2 := AXmlNode.Attributes['DgnQuantity2'];
  372. FMemoStr := AXmlNode.Attributes['MemoStr'];
  373. FDealCode := AXmlNode.Attributes['DealCode'];
  374. FDealCompany := AXmlNode.Attributes['DealCompany'];
  375. end;
  376. procedure TBillsBlockNode.SaveToXmlNode(AXmlNode: IXMLNode);
  377. begin
  378. AXmlNode.Attributes['ID'] := FID;
  379. AXmlNode.Attributes['ParentID'] := FParentID;
  380. AXmlNode.Attributes['NextSiblingID'] := FNextSiblingID;
  381. AXmlNode.Attributes['Code'] := FCode;
  382. AXmlNode.Attributes['B_Code'] := FB_Code;
  383. AXmlNode.Attributes['Name'] := FName;
  384. AXmlNode.Attributes['Units'] := FUnits;
  385. AXmlNode.Attributes['Price'] := FPrice;
  386. AXmlNode.Attributes['OrgQuantity'] := FOrgQuantity;
  387. AXmlNode.Attributes['MisQuantity'] := FMisQuantity;
  388. AXmlNode.Attributes['OthQuantity'] := FOthQuantity;
  389. AXmlNode.Attributes['Quantity'] := FQuantity;
  390. AXmlNode.Attributes['DrawingCode'] := FDrawingCode;
  391. AXmlNode.Attributes['Alias'] := FAlias;
  392. AXmlNode.Attributes['DgnQuantity1'] := FDgnQuantity1;
  393. AXmlNode.Attributes['DgnQuantity2'] := FDgnQuantity2;
  394. AXmlNode.Attributes['MemoStr'] := FMemoStr;
  395. AXmlNode.Attributes['DealCode'] := FDealCode;
  396. AXmlNode.Attributes['DealCompany'] := FDealCompany;
  397. end;
  398. initialization
  399. CF_BillsBlock := RegisterClipboardFormat('Zh.BillsBlock');
  400. end.