eNullObjectID

WPerciful
Advocate
Advocate

eNullObjectID

WPerciful
Advocate
Advocate

I get an eNullObjectId error.  I thought I found the answer here, but I couldn't get it to work.  Please don't answer in C#. I've used code converters and they don't work well.

 

    Public Function FindReplace(ldate As String, fn As String, strFind As List(Of String), strReplace As List(Of String))
        Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Core.Application.DocumentManager.MdiActiveDocument.Editor,
            db As Database = New Database(False, True),
            dwgDir As String = IO.Path.GetDirectoryName(fn),
            dwgName As String = IO.Path.GetFileName(fn),
            dwgfullname As String = dwgDir & "\" & dwgName,
            log As New List(Of String)
        Using db
            Try 'FileOpenMode.OpenForReadAndAllShare
                db.ReadDwgFile(fn, FileOpenMode.OpenForReadAndAllShare, False, Nothing)
            Catch __unusedException1__ As System.Exception
                ed.WriteMessage(vbLf & "Unable to read drawing file.")
            End Try
            Dim lg As New List(Of String())(),
                txtClass = RXObject.GetClass(GetType(DBText)),
                mtxtClass = RXObject.GetClass(GetType(MText)),
                blkrefClass = RXObject.GetClass(GetType(BlockReference))
            Using tr = db.TransactionManager.StartTransaction
                Dim loDic As DBDictionary = CType(tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead, False), DBDictionary)
                For Each entry As DBDictionaryEntry In loDic
                    Dim layout = CType(tr.GetObject(entry.Value, OpenMode.ForRead), Layout)
                    Dim btr As BlockTableRecord = CType(tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)
                    For Each objID As ObjectId In btr
                        If objID.ObjectClass.IsDerivedFrom(blkrefClass) Then
                            Dim blkRef As BlockReference = CType(tr.GetObject(objID, OpenMode.ForRead), BlockReference),
                                acblkName As String = blkRef.Name,	'	Error is here
                                nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord),
                                attCol As AttributeCollection = blkRef.AttributeCollection
                            If attCol IsNot Nothing Then
                                For Each attId As ObjectId In attCol
                                    Dim att As AttributeReference = CType(tr.GetObject(attId, OpenMode.ForWrite), AttributeReference),
                                            wksp As String = att.BlockName.ToString,
                                            hand As String = att.Handle.ToString,
                                            val As String = att.TextString,
                                            locX As String = att.Position.X.ToString,
                                            locY As String = att.Position.Y.ToString,
                                            locZ As String = att.Position.Z.ToString
                                    For i = 0 To strFind.Count - 1
                                        If val.Contains(strFind(i)) = True Then
                                            att.TextString = val.Replace(strFind(i), strReplace(i))
                                            att.RecordGraphicsModified(True)
                                            att.AdjustAlignment(db)
                                            log.Add(ldate & "," & att.TextString & "," & val & "," & "Attribute" & "," & dwgName & "," & wksp & "," & hand & "," & locX & "," & locY & "," & locZ)
                                            Dim wbd As Database = HostApplicationServices.WorkingDatabase
                                            HostApplicationServices.WorkingDatabase = db
                                            att.AdjustAlignment(db)
                                        End If
                                    Next
                                Next
                            End If
                        End If
                    Next
                Next
                tr.Commit()
            End Using
            db.SaveAs(fn, DwgVersion.AC1027)
        End Using
        Return log
    End Function


Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes
Reply
Accepted solutions (1)
4,800 Views
16 Replies
Replies (16)

_gile
Mentor
Mentor

Hi,

 

Just a thought as you do not want a C# reply, try to replace:

If objID.ObjectClass.IsDerivedFrom(blkrefClass) Then

with:

If objID.ObjectClass = blkrefClass Then

so that you discard types which inherit from BlockReference as MInsertBlock, Table and ViewRepBlockReference.

 

And please the next time you post code, clean it before posting by deleting all unnecessary and unnecessary lines.
Some of us have to make an effort to read VB, make it easier for people to ask for help ...

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes

WPerciful
Advocate
Advocate

I attempted the change you suggested and I still get the same error.  I've tried locking the drawing as well, but that doesn't work.  Based on the error message I get, listed below, I think there is some connection to locked viewports or viewports on lock layers.  When I go back into the file that the program failed on and modify the viewports to display not locked and make sure the layer is on and unlocked, then the routine can handle the file fine.  Apologies for any excess code, as I part-time coder showing enough/too much always seems to be a struggle.  As in this case, the code doesn't touch viewports, so I can't see what could be causing the issue.

 

If objID.ObjectClass = blkrefClass Then
    Dim blkRef As BlockReference = CType(tr.GetObject(objID, OpenMode.ForRead), BlockReference)
    If blkRef IsNot Nothing Then
        Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord),
            acblkName As String = blkRef.Name,
            attCol As AttributeCollection = blkRef.AttributeCollection
        If attCol IsNot Nothing Then
            For Each attId As ObjectId In attCol
                Dim att As AttributeReference = CType(tr.GetObject(attId, OpenMode.ForWrite), AttributeReference),
wksp As String = att.BlockName.ToString,
hand As String = att.Handle.ToString,
val As String = att.TextString,
locX As String = att.Position.X.ToString,
locY As String = att.Position.Y.ToString,
locZ As String = att.Position.Z.ToString
                For i = 0 To strFind.Count - 1
                    If val.Contains(strFind(i)) = True Then
att.TextString = val.Replace(strFind(i), strReplace(i))
att.RecordGraphicsModified(True)
att.AdjustAlignment(db)
log.Add(ldate & "," & att.TextString & "," & val & "," & "Attribute" & "," & dwgName & "," & wksp & "," & hand & "," & locX & "," & locY & "," & locZ)
Dim wbd As Database = HostApplicationServices.WorkingDatabase
HostApplicationServices.WorkingDatabase = db
att.AdjustAlignment(db)
                    End If
                Next
            Next
        End If
    End If
End If

Error message:

Autodesk.AutoCAD.Runtime.Exception: eNullObjectId
   at Autodesk.AutoCAD.DatabaseServices.TransactionManager.GetObjectInternal(AcDbTransactionManager* pTM, ObjectId id, OpenMode mode, Boolean openErased, Boolean forceOpenOnLockedLayer)
   at Autodesk.AutoCAD.DatabaseServices.Transaction.GetObject(ObjectId id, OpenMode mode)
   at Joshua.frmPermianBasinWellSiteFacilityGenerator.FindReplace(String ldate, String fn, List`1 strFind, List`1 strReplace) in E:\Joshua\16APR18\Joshua\frmPermianBasinWellSiteFacilityGenerator.vb:line 430
   at Joshua.frmPermianBasinWellSiteFacilityGenerator.cmdGenerate_Click(Object sender, EventArgs e) in E:\Joshua\16APR18\Joshua\frmPermianBasinWellSiteFacilityGenerator.vb:line 231
   at System.Windows.Forms.Control.OnClick(EventArgs e)



Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

ActivistInvestor
Advisor
Advisor

The error is not originating from the line you say it was:

 

acblkName As String = blkRef.Name,	'Error is here

 

The error is in a call to Transaction.GetObject() which is getting a null ObjectId.

 

I have no idea which call to GetObject() it is, because the line number in the exception message is relative to the start of the file.

 

Correctly identify the the line of code that is throwing the exception if you want more help.

 

0 Likes

WPerciful
Advocate
Advocate

The line that throws the error is listed below

 

  Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord),   ' This is the line that throws the error
            acblkName As String = blkRef.Name,


Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

ActivistInvestor
Advisor
Advisor

@WPercifulwrote:

The line that throws the error is listed below

 

  Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord),   ' This is the line that throws the error
            acblkName As String = blkRef.Name,

After looking at your above code again, You are making it extremely difficult for others to help you.

 

You have numerous assignment statement in a single line of code, separated by commas. That's the first bad coding habit you have to get rid of, because the compiler doesn't identify individual statements, it only identifies a line number. 

 

We are not going to guess which of the many assignment statements you have in a single line of code is the one that's throwing the exception.

 

Separate them into multiple lines of code, one assignment statement per line, and then tell us which of them it is.

0 Likes

WPerciful
Advocate
Advocate

To make sure I was following you, I rewrote that section to this:

 

Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
Dim acblkName As String = blkRef.Name
Dim attCol As AttributeCollection = blkRef.AttributeCollection

The line below throws the error:

 

Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)

 



Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

ActivistInvestor
Advisor
Advisor
Accepted solution

Just before the line of code that's throwing the exception, add this:

 

If blkRef.BlockTableRecord.IsNull Then
  ed.WriteMessage("\nBlockReference {0} has a null BlockTableRecord", blkRef.Handle.ToString())
EndIf

If you see this message displayed, enter this LISP and post what it returns:

 

Command: (entget (handent "<handle>"))

Where <handle> is the value displayed by the above call to WriteMessage().

 

WPerciful
Advocate
Advocate

I will be implementing your advice shortly, but first I've cleaned up all of my code per your comments.  Then I rested and posted below.  Thank you for your patience!  This time the error was here:

 

 If blkRef IsNot Nothing Then

Cleaned up code:

 

    Public Function FindReplace(ldate As String, fn As String, strFind As List(Of String), strReplace As List(Of String))
        ' Using docLock As DocumentLock = Core.Application.DocumentManager.MdiActiveDocument.LockDocument()
        Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Core.Application.DocumentManager.MdiActiveDocument.Editor
        Dim db As Database = New Database(False, True)
        Dim dwgDir As String = IO.Path.GetDirectoryName(fn)
        Dim dwgName As String = IO.Path.GetFileName(fn)
        Dim dwgfullname As String = dwgDir & "\" & dwgName
        Dim Log As New List(Of String)
        Using db
            Try 'FileOpenMode.OpenForReadAndAllShare
                db.ReadDwgFile(fn, FileOpenMode.OpenForReadAndAllShare, False, Nothing)
            Catch __unusedException1__ As System.Exception
                ed.WriteMessage(vbLf & "Unable to read drawing file.")
            End Try
            Dim lg As New List(Of String())()
            Dim txtClass = RXObject.GetClass(GetType(DBText))
            Dim mtxtClass = RXObject.GetClass(GetType(MText))
            Dim blkrefClass = RXObject.GetClass(GetType(BlockReference))
            Using tr = db.TransactionManager.StartTransaction
                Dim loDic As DBDictionary = CType(tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead, False), DBDictionary)
                For Each entry As DBDictionaryEntry In loDic
                    Dim layout = CType(tr.GetObject(entry.Value, OpenMode.ForRead), Layout)
                    Dim btr As BlockTableRecord = CType(tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)
                    For Each objID As ObjectId In btr
                        If objID.ObjectClass.IsDerivedFrom(txtClass) Then
                            Dim txt As DBText = CType(tr.GetObject(objID, OpenMode.ForWrite), DBText)
                            Dim wksp As String = txt.BlockName.ToString
                            Dim hand As String = txt.Handle.ToString
                            Dim val As String = txt.TextString
                            Dim locX As String = txt.Position.X.ToString
                            Dim locY As String = txt.Position.Y.ToString
                            Dim locZ As String = txt.Position.Z.ToString
                            For i = 0 To strFind.Count - 1
                                If val.Contains(strFind(i)) Then
                                    txt.TextString = val.Replace(strFind(i), strReplace(i))
                                    txt.RecordGraphicsModified(True)
                                    log.Add(ldate & "," & txt.TextString & "," & val & "," & "DBText" & "," & dwgName & "," & wksp & "," & hand & "," & locX & "," & locY & "," & locZ)
                                    '   Need this code in order to insure that the attributes alignment remains
                                    txt.AdjustAlignment(db)
                                End If
                            Next
                        End If
                        If objID.ObjectClass.IsDerivedFrom(mtxtClass) Then
                            Dim mtxt As MText = CType(tr.GetObject(objID, OpenMode.ForWrite), MText)
                            Dim wksp As String = mtxt.BlockName.ToString
                            Dim hand As String = mtxt.Handle.ToString
                            Dim Val As String = mtxt.Contents.ToString
                            Dim locX As String = mtxt.Location.X.ToString
                            Dim locY As String = mtxt.Location.Y.ToString
                            Dim locZ As String = mtxt.Location.Z.ToString
                            For i = 0 To strFind.Count - 1
                                If val.Contains(strFind(i)) = True Then
                                    mtxt.Contents = val.Replace(strFind(i), strReplace(i))
                                    mtxt.RecordGraphicsModified(True)
                                    log.Add(ldate & "," & mtxt.Contents & "," & val & "," & "MText" & "," & dwgName & "," & wksp & "," & hand & "," & locX & "," & locY & "," & locZ)
                                End If
                            Next
                        End If
                        If objID.ObjectClass = blkrefClass Then
                            Dim blkRef As BlockReference = CType(tr.GetObject(objID, OpenMode.ForRead), BlockReference)
                            If blkRef IsNot Nothing Then
                                Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                                Dim acblkName As String = blkRef.Name
                                Dim attCol As AttributeCollection = blkRef.AttributeCollection
                                If attCol IsNot Nothing Then
                                    For Each attId As ObjectId In attCol
                                        Dim att As AttributeReference = CType(tr.GetObject(attId, OpenMode.ForWrite), AttributeReference)
                                        Dim wksp As String = att.BlockName.ToString
                                        Dim hand As String = att.Handle.ToString
                                        Dim Val As String = att.TextString
                                        Dim locX As String = att.Position.X.ToString
                                        Dim locY As String = att.Position.Y.ToString
                                        Dim locZ As String = att.Position.Z.ToString
                                        For i = 0 To strFind.Count - 1
                                            If val.Contains(strFind(i)) = True Then
                                                att.TextString = val.Replace(strFind(i), strReplace(i))
                                                att.RecordGraphicsModified(True)
                                                att.AdjustAlignment(db)
                                                log.Add(ldate & "," & att.TextString & "," & val & "," & "Attribute" & "," & dwgName & "," & wksp & "," & hand & "," & locX & "," & locY & "," & locZ)
                                                Dim wbd As Database = HostApplicationServices.WorkingDatabase
                                                HostApplicationServices.WorkingDatabase = db
                                                att.AdjustAlignment(db)
                                            End If
                                        Next
                                    Next
                                End If
                            End If
                        End If
                    Next
                Next
                tr.Commit()
            End Using
            db.SaveAs(fn, DwgVersion.AC1027)
            'db.SaveAs(fn, Autodesk.AutoCAD.DatabaseServices.DwgVersion.Current)
        End Using
        Return log
        ' End Using
    End Function

 



Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

ActivistInvestor
Advisor
Advisor

@WPercifulwrote:

I will be implementing your advice shortly, but first I've cleaned up all of my code per your comments.  Then I rested and posted below.  Thank you for your patience!  This time the error was here:

 

 If blkRef IsNot Nothing Then

What is the error? An eNullObjectId exception can't happen on the above line.

 

 

0 Likes

WPerciful
Advocate
Advocate

This line of code:

 

Dim nbtr As BlockTableRecord = CType(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)

 Results in this error:

Autodesk.AutoCAD.Runtime.Exception: eNullObjectId
at Autodesk.AutoCAD.DatabaseServices.TransactionManager.GetObjectInternal(AcDbTransactionManager* pTM, ObjectId id, OpenMode mode, Boolean openErased, Boolean forceOpenOnLockedLayer)
at Autodesk.AutoCAD.DatabaseServices.Transaction.GetObject(ObjectId id, OpenMode mode)
at Joshua.frmPermianBasinWellSiteFacilityGenerator.FindReplace(String ldate, String fn, List`1 strFind, List`1 strReplace) in E:\Joshua\16APR18\Joshua\frmPermianBasinWellSiteFacilityGenerator.vb:line 433

The function is processing a folder of drawings.  When it crashed I attempts to paste in the lisp that you wrote in your one post.  Replaced 'handle' with the value that was written down.  The lisp returns nil, as it doesn't find a handent.



Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

ActivistInvestor
Advisor
Advisor

You didn't mention that you're processing drawings not open in the editor.  If the file isn't open in the editor, the LISP will not work.  You can write down the handle value displayed, and then open the file that was being processed when the error occurred in the editor and then use the LISP.

 

This may not be it, but you're changing the working database to the database you're processing and not changing it back to the current database afterwards:

 

Dim wbd As Database = HostApplicationServices.WorkingDatabase
HostApplicationServices.WorkingDatabase = db
att.AdjustAlignment(db)
HostApplicationServices.WorkingDatabase = wdb

 

 

0 Likes

_gile
Mentor
Mentor

Try this code snippet that I cleaned up. I deleted everything that I thought was not directly related to your problem. If it does not cause more error, you can add other features that you find useful by testing them one by one.

 

        Private Sub FindReplace(ByVal fn As String, ByVal strFind As List(Of String), ByVal strReplace As List(Of String))
            Dim textClass = RXObject.GetClass(GetType(DBText))
            Dim mtextClass = RXObject.GetClass(GetType(MText))
            Dim brclass = RXObject.GetClass(GetType(BlockReference))
            Dim workingDb = HostApplicationServices.WorkingDatabase
            Using db = New Database(False, True)
                db.ReadDwgFile(fn, FileOpenMode.OpenForReadAndAllShare, False, Nothing)
                HostApplicationServices.WorkingDatabase = db
                Using tr = db.TransactionManager.StartTransaction()
                    Dim layoutDict = CType(tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)
                    For Each entry As DBDictionaryEntry In layoutDict
                        Dim layout = CType(tr.GetObject(entry.Value, OpenMode.ForRead), Layout)
                        Dim btr = CType(tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)
                        For Each id As ObjectId In btr
                            Dim objClass = id.ObjectClass
                            If objClass.IsDerivedFrom(textClass) Then
                                Dim text = CType(tr.GetObject(id, OpenMode.ForRead), DBText)
                                Dim value = text.TextString
                                For i As Integer = 0 To strFind.Count - 1
                                    If value.Contains(strFind(i)) Then
                                        If Not text.IsWriteEnabled Then tr.GetObject(id, OpenMode.ForWrite, False, True)
                                        text.TextString = value.Replace(strFind(i), strReplace(i))
                                    End If
                                Next
                            ElseIf objClass.IsDerivedFrom(mtextClass) Then
                                Dim mtext = CType(tr.GetObject(id, OpenMode.ForRead), MText)
                                Dim value = mtext.Contents
                                For i As Integer = 0 To strFind.Count - 1
                                    If value.Contains(strFind(i)) Then
                                        If Not mtext.IsWriteEnabled Then tr.GetObject(id, OpenMode.ForWrite, False, True)
                                        mtext.Contents = value.Replace(strFind(i), strReplace(i))
                                    End If
                                Next
                            ElseIf objClass = brclass Then
                                Dim br = CType(tr.GetObject(id, OpenMode.ForRead), BlockReference)
                                For Each attId As ObjectId In br.AttributeCollection
                                    Dim att = CType(tr.GetObject(attId, OpenMode.ForRead), AttributeReference)
                                    Dim value = att.TextString
                                    For i As Integer = 0 To strFind.Count - 1
                                        If value.Contains(strFind(i)) Then
                                            If Not att.IsWriteEnabled Then tr.GetObject(attId, OpenMode.ForWrite, False, True)
                                            att.TextString = value.Replace(strFind(i), strReplace(i))
                                            att.AdjustAlignment(db)
                                        End If
                                    Next
                                Next
                            End If
                        Next
                    Next
                    tr.Commit()
                    db.SaveAs(fn, DwgVersion.AC1027)
                End Using
            End Using


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

WPerciful
Advocate
Advocate

This morning I went back over it and realized you had given me the answer yesterday.

 

If blkRef.BlockTableRecord.IsNull Then
  ed.WriteMessage("\nBlockReference {0} has a null BlockTableRecord", blkRef.Handle.ToString())
Else
' Moved my code here
EndIf

 

I also added this

HostApplicationServices.WorkingDatabase = wdb

Thank you for all of your help!



Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

WPerciful
Advocate
Advocate

M,

 

Merci beaucoup!  I will be working to streamline my code and write it cleaner.  You've been very helpful.



Wayne Perciful
Founder | Perciful Consulting LLC
Perciful Consulting

0 Likes

ActivistInvestor
Advisor
Advisor

That's fine, but skipping the opening of the BlockTableRecord doesn't really solve the problem if you actually need to open the BlockTableRecord (your code gets the block name but doesn't use it).

 

I'd still like to know why that's happening, as there shouldn't be a BlockReference with a null BlockTableRecord property, unless the DWG file is corrupt.

 


@WPercifulwrote:

This morning I went back over it and realized you had given me the answer yesterday.

 

If blkRef.BlockTableRecord.IsNull Then
  ed.WriteMessage("\nBlockReference {0} has a null BlockTableRecord", blkRef.Handle.ToString())
Else
' Moved my code here
EndIf

 

I also added this

HostApplicationServices.WorkingDatabase = wdb

Thank you for all of your help!


 

 

0 Likes

jgreyestx43MB3
Community Visitor
Community Visitor

PLease forgive my ignorance, but not being an experienced LISP programmer, what was the final code that fixed the error. I'm getting the same error message "eNullObjectId" when I try to insert a pipe support in AutoCAD Plant 3D.

Regards,

Jesse

0 Likes