I'm trying to read text from TEXT and MTEXT objects in AutoCAD 2010 using VB.NET and have run into difficulties. Here is my code:
<Autodesk.AutoCAD.Runtime.CommandMethod("runTest", CommandFlags.Session)> _
Public Sub Test()
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
Dim textObj As Autodesk.AutoCAD.Interop.Common.AcadText
Dim mtextObj As Autodesk.AutoCAD.Interop.Common.AcadMText
acDocEd = Application.DocumentManager.MdiActiveDocument.Editor
acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<or"), 0)
acTypValAr.SetValue(New TypedValue(DxfCode.Start, "TEXT"), 1)
acTypValAr.SetValue(New TypedValue(DxfCode.Start, "MTEXT"), 2)
acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "or>"), 3)
acSelFtr = New SelectionFilter(acTypValAr)
acSSPrompt = acDocEd.SelectAll(acSelFtr)
If acSSPrompt.Status = PromptStatus.OK Then
acSSet = acSSPrompt.Value
For Each selObj In acSSet
If selObj.GetType.ToString = "TEXT" Then
textObj = selObj
MsgBox("Text = " & textObj.TextString)
Else
mtextObj = selObj
MsgBox("Text = " & mtextObj.TextString)
End If
Next selObj
End If
End Sub
I realize that the ".TextString" method only works on TEXT and MTEXT objects and not a generic "SelectedObject", so I tried to detect the object type (my code does not work), then I need to convert the selected object to either TEXT or MTEXT (again my code doesn't work).
Is there a better way to do this? Can it be done without using COM objects?
Thanks in advance,
Constantine
Yes, it can be done without COM.
One problem you have there is that selObj.GetType.ToString will always return the Fully Qualified Type Name (which will ALWAYS be "Autodesk.AutoCAD.EditorInput.SelectedObject")
The other problem is that you can't just cast from SelectedObject to things derived from DbObject. (or to COM AcadText or AcadMText) You have to use a Transaction and the ObjectId pointer provided by the SelectedObject, and open the object for read. As you'll see below, the ObjectId also has an ObjectClass property which is useful for Type-Testing an object without opening it.
For the simplest change needed to make your code work, remove your declaration of textObj and mtextObj, and replace your For Each selObj...Next with this code:
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
Thanks Chief,
Thanks, that worked. As I transition from VBA to VB.NET, I am lacking a fundamental understanding of VB.NET, such as when to use a transaction, and of the AutoCAD object model so that I can avoid using COM. Do you know of good sources, on line or in book(s), for these topics?
Thanks,
Constantine
When to use a transaction or not is based on the AutoCAD API, as opposed to VB, and basically, if you are using COM, (ie. methods/objects exposed under the Interop and Interop.Common namespace) you never use a transaction, because the COM wrappers take care of it for you. If you are using the managed API, you need to use a transaction any time you want to access objects through the ObjectID.
As far as sources go, this is starting to get repetitive, but:
1) there is a blog by Kean Walmsley called Through the Interface
http://through-the-interface.typepad.com/through_the_interface/
It is a great reference, especially if you get the RSS feed, making it easier to search through his posts.
2) the ObjectARX Software developers kit contains some .NET examples and the ARX help files. I use the ARX help files when the .NET help is less than helpful.
3) There is an online Developer Guide for .NET, but I don't have a handy link to post, because I don't use it.
There are also several people who frequent this discussion group who are also on 'The Swamp'. I am not a member over there.
As far as books, there is one, which has earned mixed reviews on this group, by ....Jerry.... I'm drawing a blank on his last name. (sorry Jerry 😉
VB.NET For AutoCAD 2010
Jerry Winters
I purchased the book, I'd recommend it. go buy it.
Hi,
I want to display string from autocad to datagridview. Can you help me?
Please see attachment.
If you use windows form datagridview then you have create
List<string, int> mtextcounts which is include mtext string (unique) and number of count
then pass it as argument in your datagridview , say on button click:
this.DataGridView1,DataSource=mtextcounts
this.DataGridView1.DataMember="YourColumnName"
See how I would do it, with limited testing:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.EditorInput; namespace MtextTools { public partial class Form1 : Form { // added button1, button2, datagridview1, label1 for test private SortedList<string, int> dgvsource = new SortedList<string, int>(); private BindingSource bind = new BindingSource(); public Form1() { InitializeComponent(); } private void btnSelect_Click(object sender, EventArgs e) { this.dataGridView1.Columns.Clear(); this.label1.Text = ""; // this.Hide();// if modeless testMtextCount(); bind = new BindingSource(); bind.DataSource = null; bind.DataSource = dgvsource; this.dataGridView1.DataSource = bind; this.dataGridView1.Columns[0].HeaderText = "MODEL"; this.dataGridView1.Columns[1].HeaderText = "QUANTITY"; this.dataGridView1.Columns[0].Width = 240; this.dataGridView1.Columns[1].Width = 120; this.dataGridView1.DataMember = bind.DataMember; this.label1.Text = "SUM RUNS: "; string runs = dgvsource.Values.Sum().ToString(); this.label1.Text = this.label1.Text + runs; //clear data dgvsource.Clear(); runs = ""; // this.Show();// if modeless } private void testMtextCount() { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForRemoval = "\nFailed to select mtexts!"; pso.MessageForAdding = "\nPlease, select the mtexts on screen: "; // build filter to select the mtexts SelectionFilter filter = new SelectionFilter(new TypedValue[] { new TypedValue(0, "mtext") } ); // perform mtext selection PromptSelectionResult sres = ed.GetSelection(pso, filter);// might be SelectAll instead if (sres.Status != PromptStatus.OK) return; try { SelectionSet sset = sres.Value; using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (SelectedObject sobj in sset) { Entity ent = tr.GetObject(sobj.ObjectId, OpenMode.ForRead, false) as Entity; MText mtx = ent as MText; object[] datum = new object[] { mtx.Text, 1}; if (!dgvsource.ContainsKey(mtx.Text)) { dgvsource.Add(mtx.Text, 1); } else { dgvsource[mtx.Text]+=1; } } tr.Commit(); } } catch (System.Exception ex) { Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.Message + "\n" + ex.StackTrace); } } private void btnExit_Click(object sender, EventArgs e) { this.Close(); } private void Form1_Load(object sender, EventArgs e) { this.dataGridView1.AllowUserToOrderColumns = false; this.dataGridView1.AllowUserToAddRows = false; this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; } } }
Thanks Hallex (*Pro) for your feedback.However,you mistake my idea. I want to display that table on win form (VB.NET better) after that export to excel winh same columns and rows. I have mtext and dtext. Can you help me?
Hey, can you read by my lips: my nickname is Hallex
without any prefixes, keep it in mind,
Well, going farter, you can try attached files with my bad explanation,
coz I'm not a teacher to make your homework
Great Hallex. Thank you very much. All text are OK.How about block. For example,I want to count block base on their layer or their tag (layer is MODEL) . And how to export them to excel that we choice. I hope I did not bother you. Thanks.
Better yet to start a new topic with new question,
then more peoples could to help you with it
Here is just similar one on what you need
http://www.acadnetwork.com/topic-228.0.html
About Excel part serach for this question on this forum,
or on theswamp.com