public static System.Data.DataTable PasteUserSelectedData(string strAtts, string strDynAtts) { #region Variable Declaration System.Data.DataTable dtRetVal = new System.Data.DataTable(); PromptPointOptions ppoOpts; AcadDataServ.DynamicBlockReferencePropertyCollection dbrpcDynamicProps; AcadDataServ.BlockReference brBlkRef; Autodesk.AutoCAD.DatabaseServices.AttributeCollection acAttCol; AcadDataServ.AttributeReference arAttRef = new AttributeReference(); System.IntPtr hwnd; PromptPointResult res; char[] charArr = new char[1]; string[] strAttsArr, strDynAttsArr; int j = 0; string strTemp = ""; #endregion End Of Variable Declaration //get the names of all the attributes and dynamic attributes that the user wants from the block attributes charArr[0] = ','; if ((strAtts == "") || (strAtts == null)) { strAttsArr = new string[0]; } else { strAttsArr = strAtts.Split(charArr); } if ((strDynAtts == "") || (strDynAtts == null)) { strDynAttsArr = new string[0]; } else { strDynAttsArr = strDynAtts.Split(charArr); } //add all of the columns that are needed into the data table that will be returned to the user //to do this in one for loop a simple if else statement is required which just goes the length of both arrays for (int i = 0; i < strAttsArr.Length + strDynAttsArr.Length; i++) { //check to see if the column that is being added should come from the regular attributes or dynamic attributes if (i < strAttsArr.Length) { //add the column from the regular attributes dtRetVal.Columns.Add(strAttsArr[i], typeof(string)); }//otherwise the column that should be added comes from the dynamic attributes array else { //add the column from the dynamic attributes dtRetVal.Columns.Add(strDynAttsArr[i - strAttsArr.Length], typeof(string)); } } dtRetVal.Columns.Add("FILEFROM", typeof(string)); dtRetVal.Columns.Add("FILETO", typeof(string)); AcadDataServ.Database dbCopyFrom = null; AcadAppServ.Document docCopyFrom = null; AcadAppServ.DocumentCollection docs = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager; foreach (AcadAppServ.Document doc in docs) { if (doc.Name.Equals(sCopyFromDocName)) { docCopyFrom = doc; dbCopyFrom = doc.Database; break; } } //prompt the user to select blocks and then see if the blocks contain the attributes specified using (docCopyFrom.LockDocument()) { AcadAppServ.Document activeDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; using (activeDoc.LockDocument()) { Editor ed = activeDoc.Editor; AcadDataServ.Database db = activeDoc.Database; // The following two lines are useful to set the focus on the AutoCAD editor from a modeless form hwnd = adsw_acadDocWnd(); SetFocus(hwnd); // Build a filter list so that any point can be selected ppoOpts = new PromptPointOptions(""); ppoOpts.Message = "\nSPECIFY A POINT TO PASTE THE OBJECTS:"; res = ed.GetPoint(ppoOpts); // Do nothing if selection is unsuccessful just prompt user that selection failed if (res.Status != PromptStatus.OK) { ed.WriteMessage("USER PASTE CANCELLED"); }//otherwise the user has selected something that should be handled and checked for the appropriate attributes else { ObjectId btrCopyToId = ObjectId.Null; using (Transaction tr = db.TransactionManager.StartTransaction()) { //Open the block table records for writing so that the program can copy all of the autocad data BlockTable btCopyTo = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; btrCopyToId = btCopyTo[BlockTableRecord.ModelSpace]; tr.Commit(); } if (dbCopyFrom == null) return new System.Data.DataTable(); using (IdMapping idmCopyTo = new IdMapping()) { if (docCopyFrom.Name == activeDoc.Name) { //attempt to copy all of the data db.DeepCloneObjects(oidCollection, btrCopyToId, idmCopyTo, false); } else { //attempt to copy all of the data dbCopyFrom.WblockCloneObjects(oidCollection, btrCopyToId, idmCopyTo, DuplicateRecordCloning.Ignore, false); } idPairsCopyTo = new IdPair[0]; //go through all of the objects that were pasted and move them by the specified offset between the two points selected by the user Matrix3d m3d = Matrix3d.Displacement(p3dCopyFrom.GetVectorTo(res.Value)); using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (IdPair idp in idmCopyTo) { ObjectId oidSrc = idp.Key; if (oidCollection.Contains(oidSrc)) { if (idp.IsCloned == true) { ObjectId oidDest = idp.Value; using (Autodesk.AutoCAD.Runtime.RXClass rxClass = oidDest.ObjectClass) { bool isAnEntity = rxClass.IsDerivedFrom(Autodesk.AutoCAD.Runtime.RXClass.GetClass(typeof(Entity))); if (isAnEntity == false) continue; Entity entCurrent = tr.GetObject(oidDest, OpenMode.ForRead) as Entity; if (entCurrent == null) continue; string entDxfName = entCurrent.GetRXClass().DxfName; SequenceEnd seqEnd = entCurrent as SequenceEnd; if (seqEnd != null) continue; //check to make sure this in not an attribute reference because attributes are part of blocks and blocks will be moved along with the attributes that are //contained within them, the check for MODEL is to make sure that this is not a child of some other block or object if ((entCurrent.BlockName.ToUpper().Contains("MODEL")) && (!entCurrent.ToString().ToUpper().Contains("ATTRIBUTEREFERENCE"))) { //since this is an object that needs to be moved upgrade the status of the transaction for this object so that it can be written to for the changes entCurrent.UpgradeOpen(); //move the object based upon the point selected for the copy and the point selected for the paste entCurrent.TransformBy(m3d); //now downgrade the status of the transaction for read only because the object doesn't need to be manipulated anymore entCurrent.DowngradeOpen(); try { //check to see if the entity is a block so that its attributes can be saved in a data table for use later if (idp.Key.ObjectClass.DxfName.ToUpper().Contains("INSERT")) { //save the id pairs so that attributes of that id pair can updated if needed later after the paste has occurred Array.Resize(ref idPairsCopyTo, idPairsCopyTo.Length + 1); idPairsCopyTo[j] = new IdPair(idp.Key, idp.Value, idp.IsCloned, idp.IsPrimary, idp.IsOwnerTranslated); //get the block reference for the current object id from the database of blocks brBlkRef = (AcadDataServ.BlockReference)entCurrent; //add a new row to the data table for each block that was selected dtRetVal.Rows.Add(); //put the name of the file for each block for the file it came from as well as the file it is going to strTemp = AcadAppServ.Application.DocumentManager.GetDocument(db).Name; strTemp = strTemp.Substring(strTemp.LastIndexOf("\\") + 1); dtRetVal.Rows[j]["FILETO"] = strTemp; strTemp = AcadAppServ.Application.DocumentManager.GetDocument(dbCopyFrom).Name; strTemp = strTemp.Substring(strTemp.LastIndexOf("\\") + 1); dtRetVal.Rows[j]["FILEFROM"] = strTemp; //check to see if the block has any dynamic properties and that we need to get dynamic properties //because if the calling function isn't looking for dynamic properties, then ignore this section if ((strDynAttsArr.Length > 0) && (brBlkRef.IsDynamicBlock == true)) { //get the appropriate dynamic properties for this block reference dbrpcDynamicProps = brBlkRef.DynamicBlockReferencePropertyCollection; //go through all of the dynamic properties and search for one of the list of dynamic properties for which the program wants a value foreach (AcadDataServ.DynamicBlockReferenceProperty dbrpDynamicProp in dbrpcDynamicProps) { //go through all dynamic attributes for which the program is searching and see if this dynamic attribute matches for (int i = 0; i < strDynAttsArr.Length; i++) { //if the dynamic attribute is this one then save the value to the data table in the current row and then exit this loop gracefully if (dbrpDynamicProp.PropertyName == strDynAttsArr[i]) { //save the value to the data table dtRetVal.Rows[j][strDynAttsArr[i]] = dbrpDynamicProp.Value.ToString(); i += strDynAttsArr.Length; } } } } //once the dynamic attribute search is complete, then search for the regular attributes of this block acAttCol = brBlkRef.AttributeCollection; //go through the collection of attributes and see if this one is in the list of attributes for which the program is searching foreach (AcadDataServ.ObjectId oiAttId in acAttCol) { //get the current attribute and check that one against the list of attributes arAttRef = (AcadDataServ.AttributeReference)tr.GetObject(oiAttId, AcadDataServ.OpenMode.ForRead); //check all attributes against the list of attributes for which the program is searching for (int i = 0; i < strAttsArr.Length; i++) { //is this attribute the one the program needs to find if (arAttRef.Tag == strAttsArr[i]) { //store the value into the data table and then exit the loop gracefully dtRetVal.Rows[j][strAttsArr[i]] = arAttRef.TextString; i += strAttsArr.Length; } } } j++; } } catch { } } } } } } tr.Commit(); } } } } } AcadAppServ.Application.DocumentManager.MdiActiveDocument.Editor.Regen(); return dtRetVal; }