BillsClipboard.pas 13 KB

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