Author Topic: Attributes Tag Update from Prompt Text  (Read 3889 times)

0 Members and 1 Guest are viewing this topic.

Xander

  • Guest
Attributes Tag Update from Prompt Text
« on: November 06, 2009, 03:33:56 AM »
I'm at a loss.... I've spent the last 4 hours scouring every possible site for a solution.  Basically I'm attempting to replace a Blocks Attribute Tag based on its prompt text.  I've managed to get the tags, compare them, but I cannot set them for some unknown reason...

Any ideas?

Update: Moved code to Attachment (10/11/2009)
« Last Edit: November 09, 2009, 07:13:43 PM by Xander »

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Attributes Tag Update from Prompt Text
« Reply #1 on: November 06, 2009, 12:59:33 PM »
how about OpenMode.forwrite?
James Maeding

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Attributes Tag Update from Prompt Text
« Reply #2 on: November 06, 2009, 01:12:02 PM »
just saw the upgradeopen, you probably already tried using forwrite instead anyway...
James Maeding

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Attributes Tag Update from Prompt Text
« Reply #3 on: November 06, 2009, 01:29:39 PM »
What do you expect to happen and what's actually failing?
Me

Slim©

  • Needs a day job
  • Posts: 6560
  • The Dude Abides...
Re: Attributes Tag Update from Prompt Text
« Reply #4 on: November 06, 2009, 01:41:42 PM »
Not sure if this will care for your problem.

If you are trying to set your attribute tags to be the same as your attribute prompts it my not work; if you have spaces in your prompts.
I drink beer and I know things....

Xander

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #5 on: November 06, 2009, 08:34:53 PM »
Thank-you all for your comments. 
I've tried OpenMode.ForWrite everywhere, DocumentLocks, Everything.

Basically my situation is thus, I have titleblocks which have multiple tags of 'XXXX'. Which as you can imagine is a real pain.
I'm attempting to replace these tags based on the prompt text.
The code runs smoothly, and if you put reporting in compares the tags correctly, it's just not replacing them as it should.

The dictionary 'dTags' is constructed to be "PromptText, NewTag". 

fixo

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #6 on: November 07, 2009, 03:55:28 PM »
Thank-you all for your comments. 
I've tried OpenMode.ForWrite everywhere, DocumentLocks, Everything.

Basically my situation is thus, I have titleblocks which have multiple tags of 'XXXX'. Which as you can imagine is a real pain.
I'm attempting to replace these tags based on the prompt text.
The code runs smoothly, and if you put reporting in compares the tags correctly, it's just not replacing them as it should.

The dictionary 'dTags' is constructed to be "PromptText, NewTag". 

Can you post a drawing with these blocks


~'J'~

fixo

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #7 on: November 07, 2009, 05:09:01 PM »
I know this is a bad method but it works fine
I've just added few lines of code
and try ... catch code block

Code: [Select]
        internal void GT_TitleBlocks_TagFix(string sBlockName)
        {
            Document acDWG = AcadApp.DocumentManager.MdiActiveDocument;
            Database acDB = acDWG.Database;
            Editor ed = acDWG.Editor;
            Dictionary<string, string> dTags = new Dictionary<string, string>();
            using (DocumentLock dcolock = acDWG.LockDocument())
            {
                using (Transaction acTrans = acDB.TransactionManager.StartTransaction())
                {
                    try
                    {
                        BlockTable acBT = acTrans.GetObject(acDB.BlockTableId, OpenMode.ForRead) as BlockTable;

                        if (!acBT.Has(sBlockName))
                            return;
                        BlockTableRecord acBTR = acTrans.GetObject(acBT[sBlockName], OpenMode.ForWrite) as BlockTableRecord;

                        if (acBTR.Name == "A3-TITLE")
                        {
                            dTags.Add("PROJECT TITLE", "PROJECT");
                            dTags.Add("ADDRESS LINE", "ADDRESS");
                            dTags.Add("CLIENT NAME", "CLIENT");
                            dTags.Add("SHEET TITLE", "TITLE");
                            dTags.Add("PROJECT NUMBER", "JOB");
                            dTags.Add("SHEET NUMBER", "SHT");
                            dTags.Add("ISSUE SUFFIX", "ISSUE");
                            dTags.Add("CAD FILE NAME", "CADFILE");
                        }
                        else
                        {
                            dTags.Add("DRAWING NUMBER", "SHT");
                            dTags.Add("SHEET TITLE LINE 1", "TITLE1");
                            dTags.Add("SHEET TITLE LINE 2", "TITLE2");
                            dTags.Add("DRAWN BY", "DRAWN");
                            dTags.Add("DATED", "DATE");
                            dTags.Add("SCALES", "SCALE");
                            dTags.Add("JOB NUMBER", "JOB");
                            dTags.Add("PROJECT TITLE", "PROJECT");
                            dTags.Add("ADDRESS LINE 1", "ADDRESS1");
                            dTags.Add("ADDRESS LINE 2", "ADDRESS2");
                            dTags.Add("ADDRESS LINE 3", "ADDRESS3");
                        }
                        foreach (ObjectId acID in acBTR)
                        {
                            Entity acE = acTrans.GetObject(acID, OpenMode.ForRead, false) as Entity;
                            if (acE is AttributeDefinition)
                            {
                                AttributeDefinition acAD = acE as AttributeDefinition;
                                foreach (string sPrompt in dTags.Keys)
                                {
                                    if (acAD.Prompt.ToUpper() == sPrompt.ToUpper())
                                    {
                                        acAD.UpgradeOpen();
                                        acAD.Tag = dTags[sPrompt];
                                    }
                                }
                            }
                        }
                        acTrans.Commit();

                        string command = "_ATTSYNC N " + sBlockName + Environment.NewLine + Environment.NewLine;

                        [color=red]acDWG.SendStringToExecute(command,true,false,false);[/color]
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception ex)
                    {
                        ed.WriteMessage("\n{0}", ex.StackTrace);
                    }
                }
            }
        }



Xander

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #8 on: November 08, 2009, 06:35:56 PM »
Thanks, and indeed this is a horrible method of doing things, and one I will attempt to avoid if possible.

I've found some crucial information over the weekend which explains why my code doesn't work:
Quote
AttributeDefinition - These are the ORIGINAL attribute specifications, as in the initial titleblock inserted into the other drawings.  It is practically useless to set these definitions (and believe it or not I was changing them...)

AttributeReference - These are the CURRENT attribute items, the ones in the current block.

The prompt text is only stored within the attribute definition and will need to be compared with the reference.

I hope this pathetic attempt at an explanation makes sense.

Regards,
Xander

Xander

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #9 on: November 08, 2009, 11:11:50 PM »
Just thought I would post my solution to the issue I brought up just in-case anyone comes across a similar issue.

Thanks once again to all who offered help!

Update: Moved code to Attachment (10/11/2009)
« Last Edit: November 09, 2009, 07:14:41 PM by Xander »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Attributes Tag Update from Prompt Text
« Reply #10 on: November 09, 2009, 12:22:13 AM »

Don't have time to have a good look at the moment.

... but a comment:
personally I'd put 'something' in the catch statement.
.. assuming you want to let the user know about any exceptions.
 .. .. in my opinion what you have done is similar to the VB 'on error resume next' which is not the ideal way to design code.\\\


Thanks for posting Xander.

Regards
Kerry
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Xander

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #11 on: November 09, 2009, 01:58:20 AM »
Thanks Kerry, any feedback is appreciated.

I used the catch statements initially because AutoCAD crashed out each time (I was using a null BlockReference), and for my purposes I have it feed into a log reporter.  If it detects anything fatal it alerts the user.

From my experiences C# has no equivalent to On Error Resume Next but similar functionality can be obtain through looping Catch and Try.


Don't have time to have a good look at the moment.

... but a comment:
personally I'd put 'something' in the catch statement.
.. assuming you want to let the user know about any exceptions.
 .. .. in my opinion what you have done is similar to the VB 'on error resume next' which is not the ideal way to design code.\\\


Thanks for posting Xander.

Regards
Kerry

jmaeding

  • Bull Frog
  • Posts: 304
  • I'm just here for the Shelties.
Re: Attributes Tag Update from Prompt Text
« Reply #12 on: November 09, 2009, 11:37:59 AM »
wow, so not only do atts have their own text props, they have their own tags??
What I did in lisp to deal with this was to gather info on a block insert, then erase and re-insert.
Part of that info could be the prompt values for use in filling in atts later.  Sometimes even the att order is needed to get the values back in correctly if propmpts were the same.
The beauty of this is it allows the user to edit the block in block editor (before the re-insert), then re-insert the blocks.  You end up with a more powerful end tool.  Also, its very confusing to explain to users that their block edits will not update attributes.  So I tell them to run the tool and it fixes it
In this case, I would have edited the block def, then re-inserted and updated atts.
Either way, thx for posting final working code.
James Maeding

Xander

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #13 on: November 09, 2009, 05:55:19 PM »
I too have a similar function for Lisp, and I wanted to convert it to .NET.
The interesting thing I found last night (always happens when you think you've found the perfect solution) was running the code on multiple layouts with multiple matching tags.... Didn't work to well to say the least.... But I will post a solution to this when I get it.

wow, so not only do atts have their own text props, they have their own tags??
What I did in lisp to deal with this was to gather info on a block insert, then erase and re-insert.
Part of that info could be the prompt values for use in filling in atts later.  Sometimes even the att order is needed to get the values back in correctly if propmpts were the same.
The beauty of this is it allows the user to edit the block in block editor (before the re-insert), then re-insert the blocks.  You end up with a more powerful end tool.  Also, its very confusing to explain to users that their block edits will not update attributes.  So I tell them to run the tool and it fixes it
In this case, I would have edited the block def, then re-inserted and updated atts.
Either way, thx for posting final working code.
« Last Edit: November 09, 2009, 07:15:13 PM by Xander »

Xander

  • Guest
Re: Attributes Tag Update from Prompt Text
« Reply #14 on: November 09, 2009, 07:23:29 PM »
Alright, I have resolved my issue, and got a final solution (fingers crossed).
One note though, ensure the dictionary of values is in the same order as the drawings, all hell shouldn't break loose, but if the attributes were as drastic as mine were anything could happen. 


Example:
The code changes from:


to:



Code: [Select]
        internal void GT_Attribute_Update(Database acDB, string sBlockName, Dictionary<string, string> dTags, int iCount)
        {
            try
            {
                using (Transaction acTrans = acDB.TransactionManager.StartTransaction())
                {
                    //Make a BlockTable and Reference to the BlockName Specified
                    BlockTable acBT = acTrans.GetObject(acDB.BlockTableId, OpenMode.ForRead) as BlockTable;
                    BlockTableRecord acBTR = acTrans.GetObject(acBT[sBlockName], OpenMode.ForRead) as BlockTableRecord;

                    //Create a collection of all object referencing the specified block
                    ObjectIdCollection acOIC = acBTR.GetBlockReferenceIds(true, false);

                    //Iterate through each object
                    foreach (ObjectId acID in acOIC)
                    {
                        //Making Reference
                        BlockReference acBR = acTrans.GetObject(acID, OpenMode.ForRead) as BlockReference;

                        if (acBR != null && acBTR.HasAttributeDefinitions)
                        {
                            int i = 0;
                            //For each reference, iterate through any attributes
                            foreach (ObjectId acID2 in acBR.AttributeCollection)
                            {
                                //Grab the AttributeReference for Tag Comparison
                                AttributeReference acAR = acTrans.GetObject(acID2, OpenMode.ForRead, false) as AttributeReference;
                                //Iterate through the tags to replace

                                foreach (string sValue in dTags.Keys)
                                {
                                    string sReplace = sValue.Replace("«" + i.ToString(), "");
                                    //If the incorrect tags match, replace
                                    if (acAR.Tag.ToUpper() == sReplace.ToUpper())
                                    {
                                        System.Windows.Forms.MessageBox.Show("About to Replace «" + acAR.Tag + "to " + dTags[sValue]);
                                        //Upgrade, change, downgrade
                                        acAR.UpgradeOpen();
                                        acAR.Tag = dTags[sValue];
                                        acAR.DowngradeOpen();
                                        i++;
                                    }
                                }
                            }
                        }
                    }
                    //COMMIT THE TRANSACTION!
                    acTrans.Commit();
                }
            }
            //Catch any errors
            catch (Autodesk.AutoCAD.Runtime.Exception e)
            {
            }
        }

        /// <summary>
        /// Searches through Title Blocks for Incorrect Attribute Naming
        /// An attempts to resolve the issue.
        /// </summary>
        /// <param name="sBlockName">BlockName containing Attributes</param>
        /// <date>09 November 2009</date>
        internal void GT_TitleBlocks_TagFix(string sBlockName)
        {
            //Reference the current Document and Database
            Document acDWG = Application.DocumentManager.MdiActiveDocument;
            Database acDB = acDWG.Database;

            //Create new dictionarys for Prompts, Tags and Values
            Dictionary<string, string> dTags = new Dictionary<string, string>();
            Dictionary<string, string> dChangeTags = new Dictionary<string, string>();
            int i = 0;
            //Attempt the following, catching any errors where possible
            try
            {
                using (Transaction acTrans = acDB.TransactionManager.StartTransaction())
                {
                    //Make a reference to the block table
                    BlockTable acBT = acTrans.GetObject(acDB.BlockTableId, OpenMode.ForRead) as BlockTable;
                    //Make a record of all blocks with the specified block name
                    BlockTableRecord acBTR = acTrans.GetObject(acBT[sBlockName], OpenMode.ForRead) as BlockTableRecord;

                    switch (acBTR.Name)
                    {
                        case "A0-TITLE":
                        case "A1-TITLE":
                        case "A2-TITLE":
                            dTags.Add("DRAWING NUMBER", "SHT");
                            dTags.Add("SHEET TITLE LINE 1", "TITLE1");
                            dTags.Add("SHEET TITLE LINE 2", "TITLE2");
                            dTags.Add("DRAWN BY", "DRAWN");
                            dTags.Add("DATED", "DATE");
                            dTags.Add("SCALES", "SCALE");
                            dTags.Add("JOB NUMBER", "JOB");
                            dTags.Add("PROJECT TITLE", "PROJECT");
                            dTags.Add("ADDRESS LINE 1", "ADDRESS1");
                            dTags.Add("ADDRESS LINE 2", "ADDRESS2");
                            dTags.Add("ADDRESS LINE 3", "ADDRESS3");
                            break;
                        case "A3-TITLE":
                            dTags.Add("PROJECT TITLE", "PROJECT");
                            dTags.Add("ADDRESS LINE", "ADDRESS");
                            dTags.Add("CLIENT NAME", "CLIENT");
                            dTags.Add("SHEET TITLE", "TITLE");
                            dTags.Add("PROJECT NUMBER", "NUMBER");
                            dTags.Add("SHEET NUMBER", "SHT");
                            dTags.Add("ISSUE SUFFIX", "ISSUE");
                            dTags.Add("CAD FILE NAME", "CADFILE");
                            break;                       
                        case "B1-TITLE":
                            dTags.Add("DRAWING NUMBER", "SHT");
                            dTags.Add("SHEET TITTLE LINE 1", "TITLE1");
                            dTags.Add("SHEET TITTLE LINE 2", "TITLE2");
                            dTags.Add("DRAWN BY", "DRAWN");
                            dTags.Add("DATED", "DATE");
                            dTags.Add("SCALES", "SCALE");
                            dTags.Add("JOB NUMBER", "JOB");
                            dTags.Add("PROJECT TITLE", "PROJECT");
                            dTags.Add("ADDRESS LINE 1", "ADDRESS1");
                            dTags.Add("ADDRESS LINE 2", "ADDRESS2");
                            dTags.Add("ADDRESS LINE 3", "ADDRESS3");
                            break;
                    }
                   
                    //Proceed if the record has Attribute Definitions
                    if (acBTR.HasAttributeDefinitions)
                    {
                        //Iterate through each object searching for Attribute Definitions
                        foreach (ObjectId acID in acBTR)
                        {
                            DBObject acDBO = acTrans.GetObject(acID, OpenMode.ForRead);
                            AttributeDefinition acAD = acDBO as AttributeDefinition;

                            //Check if there is a Definition
                            if (acAD != null)
                            {
                                //Iterate through the dictionary
                                foreach (string sPrompt in dTags.Keys)
                                {
                                    //Comparing the prompt strings and Tags
                                    //(Conversion to upper is not required but helps avoid errors later)
                                    if (acAD.Prompt.ToUpper() == sPrompt.ToUpper() && acAD.Tag.ToUpper() != dTags[sPrompt].ToUpper())
                                    {
                                        //Build a string to split later, containg a number count.
                                        //This also helps avoid Duplication of Tags within the Dictioanry
                                        dChangeTags.Add(acAD.Tag + "«" + i.ToString(), dTags[sPrompt]);
                                        i++;
                                    }
                                }
                            }
                        }
                    }
                    acTrans.Commit();
                }
            }
            //Catch and report any errors back to the user
            catch (Autodesk.AutoCAD.Runtime.Exception e)
            {
                //System.Windows.Forms.MessageBox.Show(e.StackTrace);
            }
            //If there is more than one entry in the dictionary
            if (dChangeTags.Count >= 1)
            {
                //Update the Attributes in the specified block
                GT_Attribute_Update(acDB, sBlockName, dChangeTags, i);
            }
        }