Author Topic: Getting the dictionary / XRecord parent  (Read 3895 times)

0 Members and 1 Guest are viewing this topic.

rogue

  • Guest
Getting the dictionary / XRecord parent
« on: February 22, 2008, 12:56:19 PM »
I'm attempting to read XRecord data that was written by another application. I can see it in the DXF file if I export, but Ive had no luck trying to get the name of the owning dictionary. I tried 'peeking' at it using DBView, and it crashes autocad with a "not open for write" error.

I wrote up a routine that grabs the ObjectID of XRecords during the Object.Modified event, and "catch them" as they pass by, when the entities that are using the XRecords get modified. When all the events are 'over', I ran a second routine to get the XRecord objects from the ObjectID's, and tried traversing up the parent tree to the Dictionary. While the XRecord objects seem to be ok, (in that I can get their NAME property, anyway), the routine tanks when it tries to get the name of the parent Dictionary. I pass the routine below, and ObjectID of an XRecord.

The error is "Run-time error '-2145386494 (80200002)':"
' "Not applicable"

Sub getDictName(lngXRecID As Long)
' attempts to get owner dictionary name, if passed the
' object ID of an xrecord. Runs fine until I attempt to
' get the name of the dictionary, then returns the following error:
' "Run-time error '-2145386494 (80200002)':"
' "Not applicable"


Dim objTmp As AcadObject
Dim objXRec As AcadXRecord
Dim lngOwnerID As Long
Dim objDict As AcadDictionary


Set objTmp = ThisDrawing.ObjectIdToObject(lngXRecID)
If objTmp Is Nothing Then
Debug.Print "No Object found for ObjectID"
Exit Sub
End If

' make sure its an Xrecord
If Not (objTmp.ObjectName = "AcDbXrecord") Then
Debug.Print "passed ObjectID was not for an XRecord"
Exit Sub
Else
Set objXRec = objTmp ' set into XRecord Object
Debug.Print "XRecord name is "; objXRec.Name
End If

' get the owner of the XRecord
lngOwnerID = objXRec.OwnerID
Set objTmp = ThisDrawing.ObjectIdToObject(lngOwnerID)

' make sure its a dictionary
If Not (objTmp.ObjectName = "AcDbDictionary") Then
Debug.Print "Owner of XRecord was not a Dictionary"
Else
' set into Dictionary Object
Set objDict = objTmp
' get a "Not applicable" error messager here
Debug.Print "The Dictionary name is "; objDict.Name
End If

End Sub

Im hoping to get the owning Dictionary, so I can see all of the available XRecords.
Its only string data, should be easy enough to return. or am I going about this the wrong way?
is there another way to get the Dictionary name? Is the dictionary name even needed ?

... perplexed in Poughkeepsie

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Getting the dictionary / XRecord parent
« Reply #1 on: February 22, 2008, 03:05:23 PM »
Dear Perplexed,
I just ran your code on a sample drawing I have with Dictionaries & Xrecords in it. It ran fine......could you post a drawing with the data you are working with? Along with the code you are obtaining the Xrecord's ObjectID with?

rogue

  • Guest
Re: Getting the dictionary / XRecord parent
« Reply #2 on: February 25, 2008, 06:57:01 AM »
i attached a sample drawing. As for getting the objectID's goes, it was a simple routine that just used debug.print in the Acaddocument.objectmodified event. if you dxfout this drawing, and load it in notepad, do a search for "y:\" ( a drive letter), you'll see a portion of the xrecords in question.

I, too, have run code on other drawings and had no problem. Both the code I posted previously, and DBVIEW, tank on THIS drawing, but neither my code, nor DBVIEW, tanks on drawings that do NOT have entities created by the 3rd party application in question. Im beginning to think its protected in some way? Is this possible?  I quick browse thru the loaded applications shows no special ARX, in any but the default directories... unless Im missing something ...  ?

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Getting the dictionary / XRecord parent
« Reply #3 on: February 25, 2008, 03:03:37 PM »
OK, without investigating too deep, it looks like the Dictionary that Xrecord references does not have a name property. Much like the base Acad Dictionaries for Groups, Layouts, Materials, and others are Dictionaries without a name property. Any of these choke on the .Name call as well.

So the 3rd party app is Creating a Dictionary and not giving it a name property.  Knowing this you can code around it, depending on what you are trying to do with it.

rogue

  • Guest
Re: Getting the dictionary / XRecord parent
« Reply #4 on: February 26, 2008, 06:50:43 AM »

>>it looks like the Dictionary that Xrecord references does not have a name property.

I was beginning to think so - much like an 'anonymous' block ?

>> Knowing this you can code around it, depending on what you are trying to

Well, it *sounds* easy, anyway.  Im trying to get the dictionary, read the path information, and associated string variables, so I can check the referenced directory (stored in the XRecords) for the extra MSOffice files it uses to store extra information.  I wont  have the luxury of waiting around for an Object Modified event; and there might be more than one dictionary, as far as I can tell. But I know the names of the XRecords, and these will be pretty consistent between drawings.

How can I code around this? The only code Ive seen shows one getting the dictionary by using its name. While the same is true for existing  XRecord code, The XRecord names are plainly available in the DXF.

So, you've opened the door a crack, but theres still a chain on the damn thing......


MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Getting the dictionary / XRecord parent
« Reply #5 on: February 26, 2008, 07:02:50 AM »
Just woke up so I'm bleary eyed ... just a small note ... dictionaries that don't sport a name property still have a handle (which you can exploit later via the handletoobject method) ... for what it's worth ... mmm ... coffee ...

... thinks to self ... if you could sent me a sample drawing I've got about 15 minutes before I hit the shower and then drive to work ... call me crazy but I think I can crack this nut ...
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Getting the dictionary / XRecord parent
« Reply #6 on: February 26, 2008, 11:13:49 AM »
Michael, there's a small sample drawing attached to their second post.

Rogue,
Here is one way of doing it. ALthough with a huge drawing it may take a while.
Code: [Select]

Function get_the_dict(strXRecName As String) As AcadDictionary
Dim oEnt As AcadEntity
Dim oDict As AcadDictionary
Dim oXrec As AcadXRecord
Dim oTmp2 As AcadObject

For Each oEnt In ThisDrawing.ModelSpace
    If oEnt.HasExtensionDictionary = True Then
        Set oDict = oEnt.GetExtensionDictionary
        For Each oTmp2 In oDict
            If TypeOf oTmp2 Is AcadXRecord Then
                Set oXrec = oTmp2
                If oXrec.Name = strXRecName Then
                    Set get_the_dict = oDict
                    Exit Function
                End If
            End If
        Next
    End If
Next
End Function

Sub test()
Dim oDict As AcadDictionary
Set oDict = get_the_dict("MV_PRODUCTS")
If Not oDict Is Nothing Then
    Debug.Print oDict.Handle
    'do whatever you want with it now that you have it
End If
End Sub
« Last Edit: February 26, 2008, 11:25:08 AM by Jeff_M »

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Getting the dictionary / XRecord parent
« Reply #7 on: February 26, 2008, 11:46:28 AM »
Actually, while that does what I thought you had asked for, this will get the Xrecorddata based on the xrecord name. And I think is what you were really after.....inspect the return values for xcode & xdata at the end of the test2 sub.....
Code: [Select]
Function get_the_Xrec(strXRecName As String) As AcadXRecord
Dim oEnt As AcadEntity
Dim oDict As AcadDictionary
Dim oXrec As AcadXRecord
Dim oTmp2 As AcadObject

For Each oEnt In ThisDrawing.ModelSpace
    If oEnt.HasExtensionDictionary = True Then
        Set oDict = oEnt.GetExtensionDictionary
        For Each oTmp2 In oDict
            If TypeOf oTmp2 Is AcadXRecord Then
                Set oXrec = oTmp2
                If oXrec.Name = strXRecName Then
                    Set get_the_Xrec = oXrec
                    Exit Function
                End If
            End If
        Next
    End If
Next
End Function

Sub test2()
Dim oXrec As AcadXRecord
Set oXrec = get_the_Xrec("MV_PRODUCTS")
If Not oXrec Is Nothing Then
    Debug.Print oXrec.Handle
    'do whatever you want with it now that you have it
    Dim xdata As Variant
    Dim xcode As Variant
    oXrec.GetXRecordData xcode, xdata
End If
End Sub

rogue

  • Guest
Re: Getting the dictionary / XRecord parent
« Reply #8 on: February 26, 2008, 12:48:28 PM »
Who hoo! That's it! With that snippet, and the code I just emailed to your GMail account, I should be able to 'climb up the tree' fairly quickly.

And I must say, Ive been posting a *version* of this question, off and on, to various boards for months. This is first reply Ive gotten. Thanx!

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: Getting the dictionary / XRecord parent
« Reply #9 on: February 27, 2008, 09:12:31 AM »
FYI ... I provided a detailed map of the hierarchies and relationship links (which are multiple) for the data model provided via email. Up to the original poster to decide if it's something he wants to make public. 'Til then I have to err on the side of confidentiality.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

rogue

  • Guest
Re: Getting the dictionary / XRecord parent
« Reply #10 on: February 28, 2008, 06:35:11 AM »
I been wrestling with a bit of a flu, so i havent had time to play much with the code, or the diagram. But I'll rewrite it as something a bit more generic (say "resuable code") and post it up here... and thahx again, guys....