Jump to content

Retrieve AutoCAD Block Records from .NET WinForm


Alex_AMF

Recommended Posts

  • Replies 31
  • Created
  • Last Reply

Top Posters In This Topic

  • Alex_AMF

    16

  • BlackBox

    13

  • fixo

    3

Top Posters In This Topic

For kicks... What happens when you try the same declaration in a class with only Autodesk Imports statements (i.e., using AutoCAD 2010-2012 .NET Wizards, etc.)...??? :unsure:

 

I followed that wizard as it showed. So I created a new project (a plugin, not a windows form) and I was able to delcare my AcadApplication variable correctly (not amiguous this time).

Link to comment
Share on other sites

For kicks... What happens when you try the same declaration in a class with only Autodesk Imports statements (i.e., using AutoCAD 2010-2012 .NET Wizards, etc.)...??? :unsure:

 

Now for the very weird part ... I copy pasted my project folder to another location in an attempt to delete stuff without screwing the whole thing up. All my references are working! :huh:

Link to comment
Share on other sites

Thanks heh ... It's just not working in the place I want it to lol :( I wanted it to work in the C:\ directory not my Project Backups haha

 

I'll see what I can do with that tomorrow. Thanks for all the help! :notworthy: :thumbsup:

Link to comment
Share on other sites

The only real COM coding I do is with Visual LISP (ActiveX COM API), for .NET development even when I interact with COM it's to access non-.NET API exposed Objects in my plug-ins, so that is something I completely overlooked in your prior screen shot(s)... Thanks for coming back to post the solution. :beer:

Link to comment
Share on other sites

Thanks a lot to you BlackBox, you helped a lot! Here's the answer on how to retrieve blocks:

 

 

   Public dic_Contents As New SortedDictionary(Of Integer, List(Of String))

   Public Function GetBlockContents(ByVal vActiveDoc As AcadDocument)
       Try
           CleanSelectionSets(vActiveDoc)

           For y As Integer = 0 To sSet1.Count - 1
               Dim myObj = sSet1.Item(y).GetAttributes
               FillStock2(sSet1.Count, myObj, y)
           Next

       Catch ex As Exception
           MsgBox(ex.Message)
       End Try

       Return dic_Contents
   End Function

   Private Sub CleanSelectionSets(ByVal vActiveDoc As AcadDocument)
       'Remove all selection sets from the drawing (if any)
       System.Threading.Thread.Sleep(500)
       For Each selSet As AcadSelectionSet In vActiveDoc.SelectionSets
           System.Threading.Thread.Sleep(500)
           selSet.Delete()
           System.Threading.Thread.Sleep(500)
       Next

       sSet1 = vActiveDoc.SelectionSets.Add("selstock2")
       sSet2 = vActiveDoc.SelectionSets.Add("selrevis1")
       sSet3 = vActiveDoc.SelectionSets.Add("selblocknt")
       System.Threading.Thread.Sleep(500)
       sSet1 = GetBlockSet(vActiveDoc, "STOCK2")
       sSet2 = GetBlockSet(vActiveDoc, "REVIS1")
       sSet3 = GetBlockSet(vActiveDoc, "BLOCKNT")
   End Sub

   Private Function GetBlockSet(ByVal vActiveDoc As AcadDocument, ByVal BlockName As String)
       System.Threading.Thread.Sleep(500)
       Dim BlockSet As AcadSelectionSet
       Dim dxfCode(1) As Short
       Dim dxfValue(1) As Object

       System.Threading.Thread.Sleep(500)
       For Each selSet As AcadSelectionSet In vActiveDoc.SelectionSets
           System.Threading.Thread.Sleep(500)
           If selSet.Count > 0 Then
               If selSet.Name = BlockName Then selSet.Delete()
           Else
               Exit For
           End If
       Next

       BlockSet = vActiveDoc.SelectionSets.Add(BlockName)
       dxfCode(0) = 0
       dxfCode(1) = 2
       dxfValue(0) = "INSERT"
       dxfValue(1) = BlockName
       BlockSet.Select(Common.AcSelect.acSelectionSetAll, , , dxfCode, dxfValue)
       Return BlockSet
   End Function

   Private Sub FillStock2(ByVal NumBlocks As Integer, ByVal BlockSet As Object, ByVal k As Integer)
       Dim PartNo As String = ""
       Dim Qty As String = ""
       Dim ItemNo As String = ""
       Dim myList As New List(Of String)

       For y As Integer = 0 To UBound(BlockSet)
           Select Case BlockSet(y).TagString
               Case "PART"
                   PartNo = BlockSet(y).TextString.ToUpper
               Case "QTY"
                   Qty = BlockSet(y).TextString.ToUpper
               Case "ITEM"
                   ItemNo = BlockSet(y).TextString.ToUpper
           End Select
       Next

       myList.Add(PartNo)
       myList.Add(Qty)
       dic_Contents.Add(CInt(ItemNo), myList)
   End Sub

 

My dictionary contents will be populated with the part numbers and their quantities. All of them being identified by the dictionary key of their item number (all sorted correctly using the sorted dictionary). If anyone would enlighten me on how to create a better alternative for the "Thread.Sleep(500)" that would be awesome!

 

I seem to always get the following error when I'm cleaning the selection sets (but not if i step through the program slowly...):

Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED)
Link to comment
Share on other sites

I found a great alternative to the "Thread.Sleep(X)" ... Since that can over-wait or under-wait certain processes depending on the computer / server speed, I used Microsoft's fix for the Call Rejected by Callee errors:

 

http://msdn.microsoft.com/en-us/library/vstudio/ms228772(v=vs.100).aspx

 

Transformed that into VB.NET code, and simply added "MessageFilter.Register()" before any COM automations, followed by MessageFilter.Revoke() after the COM automation had finished.

 

Hope it can help someone else :)

Link to comment
Share on other sites

Thanks a lot to you BlackBox, you helped a lot!

 

You're welcome; that is kind of you to say. :)

 

If anyone would enlighten me on how to create a better alternative for the "Thread.Sleep(500)" that would be awesome!

 

Methinks you will see a significant gain in efficiency if you instead iterate the BlockTable conditionally filtering each BlockTableRecord for those identified as needed... This would also make your code more portable for batch processing. :thumbsup:

Link to comment
Share on other sites

Methinks you will see a significant gain in efficiency if you instead iterate the BlockTable conditionally filtering each BlockTableRecord for those identified as needed... This would also make your code more portable for batch processing. :thumbsup:

 

Here's a quick .NET API Method in C# (sorry on both counts, :rofl:), for you to pull from, as an example:

 

       void Foo()
       {
           Database db = 
               HostApplicationServices.WorkingDatabase;

           using (Transaction tr = 
               db.TransactionManager.StartOpenCloseTransaction())
           {
               BlockTable bt =
                   (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

               BlockTableRecord btr =
                   (BlockTable)tr.GetObject(db.[blockTableRecord.ModelSpace], OpenMode.ForRead);

               foreach (ObjectId id in btr)
               {
                   BlockReference br =
                       tr.GetObject(id, OpenMode.ForRead) as BlockReference;

                   if (br != null)
                   {
                       switch (br.Name.ToUpper())
                       {
                           case "STOCK2" :
                               //<-- do STOCK2 work

                           case "REVIS1" :
                               //<-- do REVIS1 work

                           case "BLOCKNT" :
                               //<-- do BLOCKNT work

                           default :
                               break;
                       }
                   }
               }

               tr.Commit();

           }
       }

Edited by BlackBox
Code correction; you want to iterate BlockTableRecord.ModelSpace and not the BlockTable itself.
Link to comment
Share on other sites

Cool :) Thanks! I'll need to do .NET API work eventually so I'll definately look into that. Also I'll probably optimise this whole thing once it's completed. Or when I have less work to do. Till then, take care ;)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...