.NET

Reply
Active Contributor
NayaraFJ
Posts: 42
Registered: ‎08-11-2011
Message 1 of 5 (852 Views)

Copy block of another drawing keeping the attributes and dynamic reference.

852 Views, 4 Replies
06-10-2013 04:25 AM

I am trying to copy the block from another drawing but I can not. With this code until I can, but when you close the drawing of the fatal error.

 

        m_blockInstanceId = InsertBlock("CABECALHOQUADRO", Class_Settings.GetCorrectPoint(new Point3d(line.StartPoint.X, line.StartPoint.Y + Class_Settings.DistCabecalho * escala, line.StartPoint.Z), escala),
                    escala, 0, m_attributeValues, m_dynamicPropertyValues);

                ChangeExistingBlock(m_blockInstanceId, line.StartPoint.DistanceTo(LinesStartRodapeLM[cont].StartPoint));

 

 

 public static ObjectId InsertBlock(string blockName, Point3d insPoint, double blkScale, double rotAng,
      Dictionary<string, string> attributeValues, Dictionary<string, int> dynamicParameterValues)
        {
            Document document = Application.DocumentManager.MdiActiveDocument;
            Database database = document.Database;

            ObjectId retBlockID = ObjectId.Null;
            ObjectId blkID = ObjectId.Null;


            try
            {
                using (Transaction trans = database.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)(trans.GetObject(database.BlockTableId, OpenMode.ForWrite));
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    if (bt.Has(blockName))
                    {
                        blkID = bt[blockName];
                    }
                    else
                    {
                        return retBlockID;
                    }

                    BlockReference br = new BlockReference(insPoint, blkID);

                    int no_of_notches = 0;
                    //set dynamic properties here
                    foreach (DynamicBlockReferenceProperty dbrProp in br.DynamicBlockReferencePropertyCollection)
                    {
                        //the no of notches to be visible and the property name is "Visibility"
                        if (dynamicParameterValues.ContainsKey(dbrProp.PropertyName))
                        {
                            no_of_notches = dynamicParameterValues[dbrProp.PropertyName];
                        }
                    }

                    List<AttributeReference> lstAR = new List<AttributeReference>();
                    // Iterate the block defination and find the attribute definition
                    BlockTableRecord empBtr = (BlockTableRecord)trans.GetObject(blkID, OpenMode.ForRead);

                    foreach (ObjectId id in empBtr)
                    {
                        Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead, false);
                        // Use it to open the current object! 
                        if (ent is AttributeDefinition)  // We use .NET's RunTimeTypeInformation (RTTI) to establish type.
                        {
                            // Set the properties from the attribute definition on our attribute reference
                            AttributeDefinition attDef = ((AttributeDefinition)(ent));

                            if (!attDef.Constant)
                            {
                                AttributeReference attRef = new AttributeReference();
                                attRef.SetDatabaseDefaults(database);
                                attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                                //control the visibility of the attribute values
                                if (attRef.Visible == false)
                                {
                                    if (attRef.Tag.StartsWith("NOTCH"))
                                    {
                                        string notch_no = attRef.Tag.Substring(5);
                                        try
                                        {
                                            int notch_num = Convert.ToInt32(notch_no);
                                            if (notch_num <= no_of_notches)
                                            {
                                                attRef.Visible = true;
                                            }
                                        }
                                        catch
                                        {
                                        }
                                    }
                                    else if (attRef.Tag.StartsWith("ADDFAB2"))
                                    {
                                        if (no_of_notches > 0)
                                        {
                                            attRef.Visible = true;
                                        }
                                    }
                                }

                                if (attributeValues.ContainsKey(attRef.Tag))
                                {
                                    attRef.TextString = attributeValues[attRef.Tag];
                                }
                                else
                                {
                                    attRef.TextString = attDef.TextString;
                                }

                                //requires the working database - Kailas Dhage
                                attRef.AdjustAlignment(HostApplicationServices.WorkingDatabase);

                                lstAR.Add(attRef);
                            }
                        }
                    }

                    // Add the reference to ModelSpace
                    retBlockID = btr.AppendEntity(br);
                    trans.AddNewlyCreatedDBObject(br, true);

                    foreach (AttributeReference attRef in lstAR)
                    {
                        // Add the attribute reference to the block reference
                        br.AttributeCollection.AppendAttribute(attRef);

                        // let the transaction know
                        trans.AddNewlyCreatedDBObject(attRef, true);
                    }

                    Entity blkInstance = br as Entity;
                    if (blkInstance != null)
                    {
                        //Insertion with proper attribute has completed Scale the block as per Ltscale
                        Matrix3d transform = Matrix3d.Scaling(blkScale, insPoint);
                        blkInstance.TransformBy(transform);

                        //rotate block if rotation angle is not zero
                        transform = Matrix3d.Rotation(rotAng, new Vector3d(0, 0, 1), insPoint);
                        blkInstance.TransformBy(transform);
                    }

                    //set dynamic properties here
                    foreach (DynamicBlockReferenceProperty dbrProp in br.DynamicBlockReferencePropertyCollection)
                    {
                        //the no of notches to be visible and the property name is "Visibility"
                        if (dynamicParameterValues.ContainsKey(dbrProp.PropertyName))
                        {
                            object[] allowedValues = dbrProp.GetAllowedValues();
                            no_of_notches = dynamicParameterValues[dbrProp.PropertyName];
                            dbrProp.Value = allowedValues[no_of_notches].ToString();
                        }
                    }

                    trans.Commit();
                    trans.Dispose();
                }
            }
            catch (System.Exception)
            {
                retBlockID = ObjectId.Null;
            }

            return retBlockID;
        }

 

        private static void ChangeExistingBlock(ObjectId id, double valor)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            Transaction tr = db.TransactionManager.StartTransaction();

            using (tr)
            {
                BlockReference br1 = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                tr.Commit();
                if (br1 != null && br1.IsDynamicBlock)
                {
                    DynamicBlockReferencePropertyCollection pc1 = br1.DynamicBlockReferencePropertyCollection;
                    for (int i = 0; i < pc1.Count; i++)
                    {
                        DynamicBlockReferenceProperty prop1 = pc1[i];


                        if (prop1.PropertyName == "Distance1" && !prop1.ReadOnly)
                        {

                            prop1.Value = valor;

                        }

                    }
                }

            }
        }

 

Active Contributor
NayaraFJ
Posts: 42
Registered: ‎08-11-2011
Message 2 of 5 (841 Views)

Re: Copy block of another drawing keeping the attributes and dynamic reference.

06-10-2013 04:57 AM in reply to: NayaraFJ

Sem título.png

*Expert Elite*
norman.yuan
Posts: 1,049
Registered: ‎04-27-2009
Message 3 of 5 (825 Views)

Re: Copy block of another drawing keeping the attributes and dynamic reference.

06-10-2013 07:05 AM in reply to: NayaraFJ

Have you debugged the code? By the way, your code has nothing to do with "Copying block from another drawing...". It just create a BlockReference from an existing block definition in the same drawing.

 

I can see 2 things are obviuosly wrong:

 

1. The InsertBlock() method returns ObjectId.Null in 2 cased:

 

a. If the block definition already exists in the drawing. In this case, your ChangeExistingBlock() method simply does not work, because the code would try to get a BlockReference from an ObjectNull. What you should do is: if the lock definition already exist, you need to find a block reference to this block refinition and return the blockreference's ObjectId. If no existing blockrerference is found, you create a new BlockReference (insert one).

 

b. the "catch" clause in the InsertBlock silently supressed the possible exception and then return Object.Null.

 

So, in your ollowing code, you must be prepared for getting an Object.Null back and do it accordingly.

 

2. In your ChangeExistingBlock(), you placed transaction.Commit() ahead of the code that change's dynamic properties of a dynamic block. It should be:

 

using (tr)

{

  Blockreference br1=(BlockReference)tr.Get...(...,OpenMode.ForRead);

  if (br1.IsDynamicBlock)

  {

     br1.UpgradeOpen();

    //update dynamic properties here

  }

  tr.Commit()

}

Active Contributor
NayaraFJ
Posts: 42
Registered: ‎08-11-2011
Message 4 of 5 (810 Views)

Re: Copy block of another drawing keeping the attributes and dynamic reference.

06-10-2013 01:03 PM in reply to: NayaraFJ

Hello Norman!

 


Really ChangeExistingBlock method was wrong, I saw that the method InsertBlock already modified the dynamic blocks and I'm changed the code by removing the method ChangeExistingBlock. Already debug the program and although there is the possibility of the method InsertBlock  returns null is not the reason. At the beginning of the program I copy all the blocks needed for my current file, I'm guessing that the real mistake is to this point, although my only Autocad closes with fatal error when I try to edit dynamic blocks.

 

My code is now like this:

 

                string[] tags = new string[] { };
                string[] values = new string[] { };
                Dictionary<string, string> m_attributeValues = FillDictionary(new string[] { "TOT_QTD", "TOT_PESO"}, new string[]{quantidadeTot[cont], pesoTot[cont]});
                Dictionary<string, double> m_dynamicPropertyValues = FillDictionary(new string[] { "Distance1" }, new double[] { line.StartPoint.DistanceTo(LinesStartRodapeLM[cont].StartPoint) });
                
                InsertBlock("CABECALHOQUADRO", Class_Settings.GetCorrectPoint(new Point3d(line.StartPoint.X, line.StartPoint.Y + Class_Settings.DistCabecalho * escala, line.StartPoint.Z), escala),
                    escala, 0, m_attributeValues, m_dynamicPropertyValues);

 

public static ObjectId InsertBlock(string blockName, Point3d insPoint, double blkScale, double rotAng,
      Dictionary<string, string> attributeValues, Dictionary<string, double> dynamicParameterValues)
        {
            Document document = Application.DocumentManager.MdiActiveDocument;
            Database database = document.Database;

            ObjectId retBlockID = ObjectId.Null;
            ObjectId blkID = ObjectId.Null;


            try
            {
                using (Transaction trans = database.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)(trans.GetObject(database.BlockTableId, OpenMode.ForWrite));
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    if (bt.Has(blockName))
                    {
                        blkID = bt[blockName];
                    }
                    else
                    {
                        return retBlockID;
                    }

                    BlockReference br = new BlockReference(insPoint, blkID);


                    double no_of_notches = 0;
                    //set dynamic properties here
                    foreach (DynamicBlockReferenceProperty dbrProp in br.DynamicBlockReferencePropertyCollection)
                    {
                        //the no of notches to be visible and the property name is "Visibility"
                        if (dynamicParameterValues.ContainsKey(dbrProp.PropertyName))
                        {
                            no_of_notches = dynamicParameterValues[dbrProp.PropertyName];
                        }
                    }

                    List<AttributeReference> lstAR = new List<AttributeReference>();
                    // Iterate the block defination and find the attribute definition
                    BlockTableRecord empBtr = (BlockTableRecord)trans.GetObject(blkID, OpenMode.ForRead);

                    foreach (ObjectId id in empBtr)
                    {
                        Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead, false);
                        // Use it to open the current object! 
                        if (ent is AttributeDefinition)  // We use .NET's RunTimeTypeInformation (RTTI) to establish type.
                        {
                            // Set the properties from the attribute definition on our attribute reference
                            AttributeDefinition attDef = ((AttributeDefinition)(ent));

                            if (!attDef.Constant)
                            {
                                AttributeReference attRef = new AttributeReference();
                                attRef.SetDatabaseDefaults(database);
                                attRef.SetAttributeFromBlock(attDef, br.BlockTransform);

                                if (attributeValues.ContainsKey(attRef.Tag))
                                {
                                    attRef.TextString = attributeValues[attRef.Tag];
                                }
                                else
                                {
                                    attRef.TextString = attDef.TextString;
                                }

                                //requires the working database - Kailas Dhage
                                attRef.AdjustAlignment(HostApplicationServices.WorkingDatabase);

                                lstAR.Add(attRef);
                            }
                        }
                    }

                    // Add the reference to ModelSpace
                    retBlockID = btr.AppendEntity(br);
                    trans.AddNewlyCreatedDBObject(br, true);

                    foreach (AttributeReference attRef in lstAR)
                    {
                        // Add the attribute reference to the block reference
                        br.AttributeCollection.AppendAttribute(attRef);

                        // let the transaction know
                        trans.AddNewlyCreatedDBObject(attRef, true);
                    }

                    Entity blkInstance = br as Entity;
                    if (blkInstance != null)
                    {
                        //Insertion with proper attribute has completed Scale the block as per Ltscale
                        Matrix3d transform = Matrix3d.Scaling(blkScale, insPoint);
                        blkInstance.TransformBy(transform);

                        //rotate block if rotation angle is not zero
                        transform = Matrix3d.Rotation(rotAng, new Vector3d(0, 0, 1), insPoint);
                        blkInstance.TransformBy(transform);
                    }

                    //set dynamic properties here

                    if (br.IsDynamicBlock)
                    {
                        foreach (DynamicBlockReferenceProperty dbrProp in br.DynamicBlockReferencePropertyCollection)
                        {
                            //the no of notches to be visible and the property name is "Visibility"
                            if (dynamicParameterValues.ContainsKey(dbrProp.PropertyName))
                            {

                                no_of_notches = dynamicParameterValues[dbrProp.PropertyName];
                                dbrProp.Value = no_of_notches;
                            }
                        }
                        
                    }

                    btr.UpdateAnonymousBlocks();
                    trans.Commit();
                }
            }
            catch (System.Exception)
            {
                retBlockID = ObjectId.Null;
            }

            return retBlockID;
        }

 


Before I import the blocks needed with this method.

 public static void ImportBlocks()
        {
            string pachBlock = Path.Combine(Path.GetTempPath(), "TECNOMETAL_ATTLM");
            if (!Directory.Exists(pachBlock))
                Directory.CreateDirectory(pachBlock);
            pachBlock = Path.Combine(pachBlock, "Blocos.dwg");
            CopyBlocosDWG(pachBlock);
            DocumentCollection dm = Application.DocumentManager;
            Editor ed = dm.MdiActiveDocument.Editor;
            Database destDb = dm.MdiActiveDocument.Database;
            Database sourceDb = new Database(false, true);

            try
            {
                sourceDb.ReadDwgFile(pachBlock,  System.IO.FileShare.Read, true, "");

                // Create a variable to store the list of block identifiers
                ObjectIdCollection blockIds = new ObjectIdCollection();
                Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager;

                using (Transaction myT = tm.StartTransaction())
                {
                    // Open the block table
                    BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);

                    // Check each block in the block table
                    foreach (ObjectId btrId in bt)
                    {
                        BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false);

                        // Only add named & non-layout blocks to the copy list
                        if (!btr.IsAnonymous && !btr.IsLayout)
                            blockIds.Add(btrId);
                        btr.Dispose();
                    } myT.Commit();
                }

                // Copy blocks from source to destination database
                IdMapping mapping = new IdMapping();

                sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

                ed.WriteMessage("\nCopied "
                                + blockIds.Count.ToString()
                                + " block definitions from "
                                + pachBlock
                                + " to the current drawing.");
            }

            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ed.WriteMessage("\nError during copy: " + ex.Message);
            }

            sourceDb.Dispose();
        }

 I also tried to save the database but also gives error: eFileSharingViolation

ADN Support Specialist
Balaji_Ram
Posts: 737
Registered: ‎03-21-2011
Message 5 of 5 (768 Views)

Re: Copy block of another drawing keeping the attributes and dynamic reference.

06-17-2013 09:55 PM in reply to: NayaraFJ

Hello,

 

If you are getting "eFileSharingViolation" error during save, then can you post a sample project along with the drawing file for me to reproduce the issue.

 

Also, can you try saving the database as :

 

     Document doc = Application.DocumentManager.MdiActiveDocument;

    Database db = doc.Database;

 

    db.SaveAs(

        doc.Name, 

        true, 

        DwgVersion.Current, 

        doc.Database.SecurityParameters);



Balaji
Developer Technical Services
Autodesk Developer Network

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Are You Going To Be @ AU 2014? Feel free to drop by our AU topic post and share your plans, plug a class that you're teaching, or simply check out who else from the community might be in attendance. Ohh and don't forgot to stop by the Autodesk Help | Learn | Collaborate booths in the Exhibit Hall and meet our community team if you get a chance!