Author Topic: Merging a textstyle  (Read 3303 times)

0 Members and 1 Guest are viewing this topic.

Bryco

  • Water Moccasin
  • Posts: 1883
Merging a textstyle
« on: December 29, 2008, 02:28:11 PM »
I've tried and failed to do this in vba and now I am failing in  C#.
Textstyles are nasty beasts when it comes down to it and they can display fairly odd behavior.
If you copyclip some text from a drawing that has a tablestyle using the text's textstyle, the tablestyle comes along for the ride.
I've ran the following code on a few different drawings and while it appears to work a save will bring up the error "Error writing/closing file"
If you try  format->Multiline style  you get a fatal error.
I can't imagine what Multiline style can have to do with it as there are no linetypes with text loaded
Code: [Select]
public void Mergetstyles(string newTstyle,string oldTstyle)
        {

            Database db = HostApplicationServices.WorkingDatabase;
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            TextStyleTable tstyles;
           
            if (newTstyle =="") return;
            if (oldTstyle == "") return;
            if (oldTstyle == "Standard")
            {
                MessageBox.Show("The Standard textstyle cannot be deleted.");
                return;
            }

            TypedValue[] tv = { new TypedValue(0, "Text,Mtext,Acad_Table") };
            SelectionFilter sf = new SelectionFilter(tv);
            PromptSelectionResult psr = ed.SelectAll(sf);
            if (psr.Status != PromptStatus.OK)
            {
                MessageBox.Show("There is no text or Mtext in this drawing, exiting now:");
                return;
            }
            SelectionSet ss = psr.Value;

            ObjectId oldId = ObjectId.Null,newId=ObjectId.Null;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                Entity ent;
                DBText text;
                MText mtext;
                tstyles = tr.GetObject
                    (db.TextStyleTableId, OpenMode.ForRead) as TextStyleTable;
                //oldId = tstyles[oldTstyle];
               // newId =tstyles[newTstyle];
                oldId = Tony.DBUtils.GetSymbolTableRecordId(db.TextStyleTableId, oldTstyle);
                newId = Tony.DBUtils.GetSymbolTableRecordId(db.TextStyleTableId, newTstyle);

                //Dimstyles
                DimStyleTable dims = tr.GetObject
                    (db.DimStyleTableId, OpenMode.ForRead) as DimStyleTable;
                DimStyleTableRecord activeDim=null;
                DimStyleTableRecord tempActiveDim = tr.GetObject
                    (dims["Standard"], OpenMode.ForRead) as DimStyleTableRecord;

                foreach (ObjectId dimId in dims)
                {         
                    DimStyleTableRecord dim = tr.GetObject(
                        dimId, OpenMode.ForRead) as DimStyleTableRecord;
                    //Changing the active dimstyle results in an override
                    if (dimId == db.Dimstyle)
                    {
                        activeDim = dim;
                        db.SetDimstyleData(tempActiveDim);
                    }
                    if (dim.Dimtxsty == oldId)
                    {
                        dim.UpgradeOpen();
                        dim.Dimtxsty = newId;
                    }
                }
                if(activeDim!=null)
                    db.SetDimstyleData(activeDim);
                //blocks
                BlockTable blocks = tr.GetObject
                    (db.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btr;
                foreach (ObjectId blockId in blocks)
                {
                    btr = tr.GetObject(blockId, OpenMode.ForRead) as BlockTableRecord;
                    if (btr.IsFromExternalReference) continue;
                    if (btr.IsLayout) continue;
                    if (btr.Name.Contains("*D")) continue;
                    foreach (ObjectId entId in btr)
                    {
                        ent = tr.GetObject(entId, OpenMode.ForRead) as Entity;
                        if (ent is DBText)
                        {
                            text = (DBText)ent;
                            if (text.TextStyle == oldId)
                            {
                                text.UpgradeOpen();
                                text.TextStyle = newId;
                            }
                            //We need to look at all blockrefs in case
                            //the attdef textstyle was changed after the insertion
                            if (ent is AttributeDefinition)
                            {
                                AttributeDefinition att = (AttributeDefinition)ent;
                                ObjectIdCollection ids = btr.GetBlockReferenceIds(true, true);
                                BlockReference br;
                                foreach (ObjectId blockrefId in ids)
                                {
                                    br = tr.GetObject
                                        (blockrefId, OpenMode.ForWrite) as BlockReference;
                                    foreach (ObjectId id in br.AttributeCollection)
                                    {
                                        AttributeReference attref = tr.GetObject
                                            (id, OpenMode.ForWrite) as AttributeReference;
                                        if (attref.TextStyle == oldId)
                                            attref.TextStyle = newId;
                                    }
                                }

                            }       
                           
                        }
                        if (ent is MText)
                        {
                            mtext = (MText)ent;
                            if (mtext.TextStyle == oldId)
                            {
                                mtext.UpgradeOpen();
                                mtext.TextStyle = newId;
                            }
                        }
                    }
                }
                foreach (SelectedObject so in ss)
                {
                    ent = tr.GetObject(so.ObjectId, OpenMode.ForWrite) as Entity;
                    if (ent is Table)
                    {
                        Table table = (Table)ent;
                        table.UpgradeOpen();
                        for (int cols = 0; cols < table.NumColumns; cols++)
                        {
                            for (int rows = 0; rows < table.NumRows; rows++)
                            {
                                if (table.TextStyle(rows, cols) == oldId)
                                    table.SetTextStyle(rows, cols, newId);
                            }
                        }
                        continue;
                    }
                    if (ent is DBText)
                    {
                        text = (DBText)ent;
                        if (text.TextStyle == oldId)
                            text.TextStyle = newId;
                        continue;
                    }

                    mtext = (MText)ent;
                    if (mtext.TextStyle == oldId)
                        mtext.TextStyle = newId;
                }

                tr.Commit();
            }

            GetTableStyles(oldId, newId);

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                TextStyleTableRecord oldTs = tr.GetObject
                    (oldId, OpenMode.ForWrite) as TextStyleTableRecord;
                db.Textstyle = newId;
                oldTs.Erase();
                ObjectIdCollection ids = new ObjectIdCollection();
                ids.Add(oldId);
                db.Purge(ids);
                tr.Commit();
            }
        }






        public static void GetTableStyles(ObjectId oldId, ObjectId newId)
        {
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBDictionary nod = tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead) as DBDictionary;
                ObjectId id = nod.GetAt("ACAD_TABLESTYLE");
                DBDictionary dic = tr.GetObject(id, OpenMode.ForRead) as DBDictionary;
                TableStyle table;
                foreach (DictionaryEntry eDict in dic)
                {
                    table = tr.GetObject((ObjectId)eDict.Value, OpenMode.ForWrite) as TableStyle;
                    if (table == null) continue;
                    foreach (RowType rt in Enum.GetValues(typeof(RowType)))
                    {
                        ObjectId idv = table.TextStyle(rt);
                        if (table.TextStyle(rt) == oldId)
                            table.SetTextStyle(newId, (int)rt);
                    }
                }
                tr.Commit();
            }
        }



Bryco

  • Water Moccasin
  • Posts: 1883
Re: Merging a textstyle
« Reply #1 on: December 29, 2008, 07:12:32 PM »
So far so good, I forgot when cycling through dimstyles you need a new transaction for each cycle.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Merging a textstyle
« Reply #2 on: December 29, 2008, 07:39:28 PM »
So far so good, I forgot when cycling through dimstyles you need a new transaction for each cycle.

That's usefull information !
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Merging a textstyle
« Reply #3 on: January 05, 2009, 01:45:56 PM »
Here is one I did in lisp if you need a fix right now.  Not ready yet to look at C# code.

[ http://www.theswamp.org/index.php?topic=17659.0 ]

So far so good, I forgot when cycling through dimstyles you need a new transaction for each cycle.

That's usefull information !

Second that!
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Merging a textstyle
« Reply #4 on: January 05, 2009, 11:01:33 PM »
Thanks Tim but It seems to be working fine now.
I didn't bother posting the fix till now as I didn't think there would be any interest in it.
I have to mess with so many different styles of client drawings that it comes in handy for me.
I am surprised at how much stuff you have to go through to delete a textstyle, and while I probably have very slow code here, I couldn't find a way to lessen the iterations and have it always work. (For the drawings I tested).
 I find it interesting that net doesn't try to use collections. While a lisper is as happy as Larry messing with the nod, coming from a vba background, collections make  coding easier and I immediately made a function to access Tablestyles as a collection.
I wonder if (regardless of how acad stores it's data) there would have been a big hit in speed if all the api's had been converted to collections eg foreach(Tablestyle ts in tablestyles).

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Merging a textstyle
« Reply #5 on: January 06, 2009, 11:21:49 AM »
I noticed that you didn't step through any block references to get at attributes.  Wouldn't you need to to get rid of all the offending text styles?  I my take a longer look at the code today, right now I'm still not all awake, to see if I can help any.  Not sure I can.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.