How to loop through a model to extract TEXT and MTEXT string + position

How to loop through a model to extract TEXT and MTEXT string + position

Anonymous
Not applicable
7,669 Views
6 Replies
Message 1 of 7

How to loop through a model to extract TEXT and MTEXT string + position

Anonymous
Not applicable

I have an AutoCAD and I am in Model space, how to loop through a model to extract all TEXT and MTEXT string + position?

 

This is my first VB.NET program with AutoCAD, I tried to use a code posted on the forum but it did not return anything (no error even when I remove Try-Catch

 

    Dim acDocEd As Editor
        Dim acTypValAr(3) As TypedValue
        Dim acSelFtr As SelectionFilter
        Dim acSSPrompt As PromptSelectionResult
        Dim acSSet As SelectionSet
        Dim selObj As SelectedObject

        acDocEd = Application.DocumentManager.MdiActiveDocument.Editor

        acSelFtr = New SelectionFilter(acTypValAr)
        acSSPrompt = acDocEd.SelectAll(acSelFtr)

        If acSSPrompt.Status = PromptStatus.OK Then
            acSSet = acSSPrompt.Value

            Using trans As Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction

                Try
                    For Each selObj In acSSet
                        Select Case selObj.ObjectId.ObjectClass.Name
                            Case "AcDbText"
                                Dim textObj As DBText = trans.GetObject(selObj.ObjectId, OpenMode.ForRead, False, True)
                                MsgBox("Text = " & textObj.TextString)
                                textObj.Dispose()
                            Case "AcDbMText"
                                Dim mtextObj As MText = trans.GetObject(selObj.ObjectId, OpenMode.ForRead, False, True)
                                MsgBox("Text = " & mtextObj.Contents)
                                mtextObj.Dispose()
                        End Select
                    Next selObj
                Catch ex As Exception
                Finally
                    trans.Commit()
                End Try
            End Using

        End If
    End Sub

 

0 Likes
Accepted solutions (1)
7,670 Views
6 Replies
Replies (6)
Message 2 of 7

BKSpurgeon
Collaborator
Collaborator

Two things that immediately come to mind: 

 

  • Your selection filter: are you actually creating one? Where is the code which filters in only text and Mtext?
  • Second is to be sure that the name of the Objects as strings actually come out as "AcDbText" and "AcDbMtext" -  you gotta make sure it is exact.

I don't know VB.NET but if i was using c# I simply do something like this:

 

case selObj.ObjectId.ObjectClass == RXClass.GetClass(typeof(Mtext))

 

You need something like this:

 

    Dim acTypValAr(3) As TypedValue
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<or"), 0)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "MTEXT"), 1)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "DBTEXT"), 2)    
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "or>"), 3)

    Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)

 

 

untested code warning: there may be typos etc.

Message 3 of 7

_gile
Consultant
Consultant
Accepted solution

Hi,

 

You can either use a selection filter and Editor.SelectAll() or iterate through the model space enities.

 

Using a selection filter

 

C#

   public class Commands
    {
        [CommandMethod("Test1")]
        public void Test1()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            TypedValue[] tvs = new[] 
            {
                new TypedValue(0, "TEXT,MTEXT"), // only DBText or MText
                new TypedValue(410, "Model")     // in model space
            };
            SelectionFilter filter = new SelectionFilter(tvs);
            PromptSelectionResult selection = ed.SelectAll(filter);
            if (selection.Status != PromptStatus.OK)
                return;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                foreach (SelectedObject obj in selection.Value)
                {
                    ObjectId id = obj.ObjectId;
                    if (id.ObjectClass.DxfName == "TEXT")
                    {
                        DBText text = (DBText)tr.GetObject(id, OpenMode.ForRead);
                        ed.WriteMessage("\nText = {0} ({1})", text.TextString, text.Position);
                    }
                    else
                    {
                        MText mtext = (MText)tr.GetObject(id, OpenMode.ForWrite);
                        ed.WriteMessage("\nText = {0} ({1})", mtext.Text, mtext.Location);
                    }
                }
                tr.Commit();
            }
        }

VB (with the help of Telerik code converter)

        <CommandMethod("Test1")>
        Public Sub Test1()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Dim tvs As TypedValue() = New TypedValue() _
            {
                New TypedValue(0, "TEXT,MTEXT"), ' only DBText or MText
                New TypedValue(410, "Model")     ' in model space
            }
            Dim filter As New SelectionFilter(tvs)
            Dim selection As PromptSelectionResult = ed.SelectAll(filter)
            If selection.Status <> PromptStatus.OK Then
                Return
            End If

            Using tr As Transaction = db.TransactionManager.StartTransaction()
                For Each obj As SelectedObject In selection.Value
                    Dim id As ObjectId = obj.ObjectId
                    If id.ObjectClass.DxfName = "TEXT" Then
                        Dim text As DBText = DirectCast(tr.GetObject(id, OpenMode.ForRead), DBText)
                        ed.WriteMessage(vbLf & "Text = {0} ({1})", text.TextString, text.Position)
                    Else
                        Dim mtext As MText = DirectCast(tr.GetObject(id, OpenMode.ForWrite), MText)
                        ed.WriteMessage(vbLf & "Text = {0} ({1})", mtext.Text, mtext.Location)
                    End If
                Next
                tr.Commit()
            End Using
        End Sub

Iterating through all model space entities (this may be a little faster than using a selection set)

 

C#

        [CommandMethod("Test2")]
        public void Test2()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var model = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                foreach (ObjectId id in model)
                {
                    switch (id.ObjectClass.DxfName)
                    {
                        case "TEXT":
                            var text = (DBText)tr.GetObject(id, OpenMode.ForRead);
                            ed.WriteMessage($"\nText = {text.TextString} ({text.Position})");
                            break;
                        case "MTEXT":
                            var mtext = (MText)tr.GetObject(id, OpenMode.ForWrite);
                            ed.WriteMessage($"\nText = {mtext.Text} ({mtext.Location})");
                            break;
                        default:
                            break;
                    }
                }
                tr.Commit();
            }
        }

VB

        <CommandMethod("Test2")>
        Public Sub Test2()
            Dim doc = Application.DocumentManager.MdiActiveDocument
            Dim db = doc.Database
            Dim ed = doc.Editor

            Using tr = db.TransactionManager.StartTransaction()
                Dim model = DirectCast(tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead), BlockTableRecord)
                For Each id As ObjectId In model
                    Select Case id.ObjectClass.DxfName
                        Case "TEXT"
                            Dim text = DirectCast(tr.GetObject(id, OpenMode.ForRead), DBText)
                            ed.WriteMessage(vbLf & "Text = {0} ({1})", text.TextString, text.Position)
                            Exit Select
                        Case "MTEXT"
                            Dim mtext = DirectCast(tr.GetObject(id, OpenMode.ForWrite), MText)
                            ed.WriteMessage(vbLf & "Text = {0} ({1})", mtext.Text, mtext.Location)
                            Exit Select
                        Case Else
                            Exit Select
                    End Select
                Next
                tr.Commit()
            End Using
        End Sub

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 7

Anonymous
Not applicable

Thanks, the last VB code works well

0 Likes
Message 5 of 7

Anonymous
Not applicable

Thanks - this is my first AutoCAD code so I am lacks of basic knowledge. The bad thing is that I could only find 1 book on AutoCAD .NET but I could not place the order.

0 Likes
Message 6 of 7

Anonymous
Not applicable

Hi,

 

The code above works perfectly for MTEXT but when I am trying to extract TEXT, although I do find 38 TEXT objects in my drawing, when I try to read it using TextString, all I find is blanks. Could you please help me that? Why is this happening?

 

Looking forward to your reply

0 Likes
Message 7 of 7

paul_bachner
Community Visitor
Community Visitor

Because someone edited the text and backed spaced all the text away instead of erasing the object.

0 Likes