Title Block Replacement - Does not honor constant attribute

Title Block Replacement - Does not honor constant attribute

ThomasRambach
Advisor Advisor
1,476 Views
6 Replies
Message 1 of 7

Title Block Replacement - Does not honor constant attribute

ThomasRambach
Advisor
Advisor

I have some code that replaces title blocks in batch that works good (excerpt below). But for some reason the few attributes in the block that are set to Constant = Yes are appearing in an DDATTE edit of the block after it's inserted even with the attribute set correctly. A manual insert of the block has the desire result. What am I doing wrong? What am I missing?

 

Code:

 

private static bool ProcessTitleBlockObjectMigration(Transaction transaction, Database db, ObjectId id, string titleBlocksPath)
        {
            using (DBObject dbObj = transaction.GetObject(id, OpenMode.ForRead))
            {
                if (dbObj is BlockReference)
                {
                    BlockReference blockRef = (BlockReference)dbObj;
                    string blockName = blockRef.Name;
                    ObjectId ownerId = blockRef.OwnerId;
                    string replacementBlockName = GetReplacementBlockName(blockName);

                    if (replacementBlockName == "")
                        return false;

                    // Upgrade to write access.
                    blockRef.UpgradeOpen();
                    // store the current block position/scale/tranform/attributes
                    Point3d position = blockRef.Position;
                    Scale3d scaleFactors = blockRef.ScaleFactors;
                    Matrix3d tranformMatrix = blockRef.BlockTransform;
                    Dictionary<string, string> attributeDataDict = CadUtils.ExtractBlockAttributedata(transaction, blockRef);

                    // MAPPING CODE
                    RemapAttribute(attributeDataDict, "MATL", "MATERIAL");
                    RemapAttribute(attributeDataDict, "REV", "REV.");
                    RemapAttribute(attributeDataDict, "HEAT", "HEAT_TREATMENT");
                    RemapAttribute(attributeDataDict, "SPECS", "SPECIFICATIONS");
                    RemapAttribute(attributeDataDict, "DSGN", "DSG/INT");
                    RemapAttribute(attributeDataDict, "NOTES", "DRAWING_TYPE");
                    RemapAttribute(attributeDataDict, "DWG_TITLE", "DRAWING_DESCRIPTION");
                    RemapAttribute(attributeDataDict, "EFC", "EFC No.");


                    if (attributeDataDict.ContainsKey("XXX-000000-00000"))
                        RemapAttribute(attributeDataDict, "XXX-000000-00000", "DWG_NO");



                    // Hard rule. Check rev and make it 0 if its blank or -
                    if (attributeDataDict.ContainsKey("REV."))
                    {
                        string rev = attributeDataDict["REV."].Trim();
                        if (rev == "" || rev == "-")
                            attributeDataDict["REV."] = "0";
                    }

                    blockRef.Erase();

                    ObjectId btrId = CadUtils.LoadBlockFromFile(transaction, db, titleBlocksPath + "\\" + replacementBlockName, (replacementBlockName.Replace(".dwg", "")).Replace("_","")); // Replace "_" added by TJR
                    BlockReference newBtr = new BlockReference(position, btrId);

                    using (BlockTableRecord space = (BlockTableRecord)transaction.GetObject(ownerId, OpenMode.ForWrite))
                    {
                        space.AppendEntity(newBtr);
                        transaction.AddNewlyCreatedDBObject(newBtr, true);

                        newBtr.Position = position; // Added by TJR 07/07/2018 ####
                        newBtr.ScaleFactors = scaleFactors;
                        newBtr.BlockTransform = tranformMatrix;
                        CadUtils.CopyAttributesToBlock(db, transaction, newBtr, attributeDataDict);
                    }


                    return true;
                }

                return false;
            }
        }
0 Likes
Accepted solutions (1)
1,477 Views
6 Replies
Replies (6)
Message 2 of 7

norman.yuan
Mentor
Mentor

I am not very sure "Does not honor..." mean: do these constant attributes present, or not present after your code inserts the replacing block?

 

Also, it looks like the most portion of your code shown here is about retrieve existing attribute values before existing block is erased. This is totally irrelevant to the issue at hand. Probably, the code in CadUtil.CopyAttributesToBlock() actually add the attributes to the newly inserted block reference. That is where the code may not write correctly.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 7

ThomasRambach
Advisor
Advisor

You're right... here's that code:

 

public static List<ObjectId> CopyAttributesToBlock(Database db, Transaction transaction, BlockReference br, Dictionary<string,string> dataDict )
        {

            if(!dataDict.ContainsKey("DWG_NO"))
                Log.LogFailure("Attribute did not exist DWG_NO in file " + db.Filename);

            List<ObjectId> refIdList = new List<ObjectId>();
            List<string> unusedKeys = dataDict.Keys.ToList<string>();
            using (BlockTableRecord btr = (BlockTableRecord)transaction.GetObject(br.BlockTableRecord, OpenMode.ForWrite, false, true))
            {
                foreach (ObjectId id in btr)
                {
                    using (Entity ent = (Entity)transaction.GetObject(id, OpenMode.ForRead, false, true))
                    {
                        if (ent is AttributeDefinition)
                        {
                            AttributeDefinition def = (AttributeDefinition)ent;
                            using (AttributeReference attributeRef = new AttributeReference())
                            {
                                attributeRef.SetAttributeFromBlock(def, br.BlockTransform);
                                br.AttributeCollection.AppendAttribute(attributeRef);
                                if (dataDict.ContainsKey(attributeRef.Tag))
                                {
                                    attributeRef.TextString = dataDict[attributeRef.Tag];
                                    unusedKeys.Remove(attributeRef.Tag);
                                }
                                refIdList.Add(attributeRef.Id);

                                Database wdb = HostApplicationServices.WorkingDatabase;
                                HostApplicationServices.WorkingDatabase = db;
                                attributeRef.AdjustAlignment(db);
                                HostApplicationServices.WorkingDatabase = wdb;
                            }
                        }
                    }
                }

                // Log attributes that are not found that ar enot listed here
                foreach(string key in unusedKeys)
                {

                        Log.LogFailure("Attribute had no mapping "+key+ " in file " + db.Filename);
                }
            }

            return refIdList;
        }

    }
0 Likes
Message 4 of 7

norman.yuan
Mentor
Mentor

It seems to me, your code DOES NOT add the newly created AttributeReference to the transaction with 

transaction.AddNewlyCreatedDBObject(), thus, no AttributeReference would eventually be added the replacing block after your code execution (except for the constant attribute, which AutoCAD treats it as Text entity in the block definition).

 

Here is what in your post's title confuses me: the replacing block should not have any regular attribute in it (because of not being added into the transaction), yet you are saying "does not honor constant attribute"...

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 5 of 7

ThomasRambach
Advisor
Advisor

@norman.yuan I think I'm confusing myself. I inherited this code so I'm trying to reverse engineer it. The code might be missing something. The other normal attributes copy without issues (somehow). The attributes marked as constant come in acting as normal attributes and not constant attributes.

0 Likes
Message 6 of 7

ActivistInvestor
Mentor
Mentor
Accepted solution
Your code is not checking each AttributeDefinition to see if it is constant and skipping it in that case.
0 Likes
Message 7 of 7

ThomasRambach
Advisor
Advisor

I got that figured out. I added a check to determine if it was a constant attribute and skip the value copy if it is and everything is working. Thanks for the sanity checks.

0 Likes