.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Add Block When Other Drawings Are Open

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
soccerazy
559 Views, 9 Replies

Add Block When Other Drawings Are Open

I'm trying to add a block with an attribute to a drawing. The command works if there is only one drawing open, but when there are other open drawings then the block doesn't appear. Strangely if I select the block in the block editor and then close the block editor the block suddenly appears. Do you know what is causing the block to not appear when other drawings are open?

 

I included the code below. "s1" works but "s2" has the strange behavior of the block not being visible.

 

Thanks for any help,

 

Casey Joyce

 

[CommandMethod("s1")]
public void AddBlockWithAttributeToDestination_WithNoOtherDrawingsOpen() {
    var attributeValue = "1234";
    var destination = Application.DocumentManager.MdiActiveDocument;
    using (var transaction = destination.TransactionManager.StartTransaction()) {
        addBlock(transaction, destination.Database, attributeValue);
        transaction.Commit();
    }
}

[CommandMethod("s2")]
public void AddBlockWithAttributeToDestination_WhileSourceDrawingIsOpen() {
    // pretend user selects info from opened source drawing
    var attributeValue = "1234";
    // pretend user selects destination drawing from popup list
    var destinationDrawing = @"c:\destination.dwg";

    // add block to destination drawing
    var destination = Application.DocumentManager.Open(destinationDrawing, false);
    using (var transaction = destination.TransactionManager.StartTransaction()) {
        using (var key = destination.LockDocument()) {
            addBlock(transaction, destination.Database, attributeValue);
        }
        transaction.Commit();
    }
}

void addBlock(Transaction transaction, Database database, string attributeValue) {
    // add block
    var block = new BlockTableRecord() { Name = "SampleBlock" };
    var table = transaction.GetObject(database.BlockTableId, OpenMode.ForWrite) as BlockTable;
    var blockId = table.Add(block);
    transaction.AddNewlyCreatedDBObject(block, true);
    // add block reference
    var blockReference = new BlockReference(Point3d.Origin, block.ObjectId);
    var modelSpace = transaction.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
    modelSpace.AppendEntity(blockReference);
    transaction.AddNewlyCreatedDBObject(blockReference, true);

    // set attribute definition
    var definition = new AttributeDefinition(
        new Point3d(1, 1, 0),
        attributeValue,
        "SampleAttribute",
        "",
        database.Textstyle);
    block.AppendEntity(definition);
    transaction.AddNewlyCreatedDBObject(definition, true);
    // add attribute reference
    var reference = new AttributeReference();
    reference.SetAttributeFromBlock(definition, blockReference.BlockTransform);
    blockReference.AttributeCollection.AppendAttribute(reference);
    transaction.AddNewlyCreatedDBObject(reference, true);
}

Tags (2)
9 REPLIES 9
Message 2 of 10
GTVic
in reply to: soccerazy

Maybe you should lock the document?

 

Using acLckDoc As DocumentLock = acNewDoc.LockDocument()

End Using
Message 3 of 10
soccerazy
in reply to: GTVic

Thanks for your response GTVic. I am using LockDocument in the s2 command, and that's the one that wasn't working.

Message 4 of 10
soccerazy
in reply to: soccerazy

I think I am going to be able to get s2 to work by adding CommandFlags.Session. So far it looks like its working.

 

[CommandMethod("s2", CommandFlags.Session)]

Message 5 of 10
GTVic
in reply to: soccerazy

Sorry, didn't notice that, maybe because it was inside the transaction. I think that is a problem, the document should be locked before starting the transaction. That is the way it is documented in the Developer's Guide

 

CommandFlags.Session might mask the problem. The effect of "Session" is not clear but I take it that nothing else can happen in the application while this command is running and then perhaps there is no need for a lock and the lock being out of order doesn't cause a problem.

Message 6 of 10
soccerazy
in reply to: GTVic

I moved the LockDocument outside the transaction as you and the Developer Guide suggested, thanks. When I keep the CommandFlags.Session this seems to work fine. So unless I find a better way I guess I'll stick with this.

 

Just FYI:

Even with the lock on the outside of the transaction, the CommandFlags.Session is still required for me to get "s2" to work.

 

I tried removing the LockDocument all together to see if CommandFlags.Session would take care of it, but it throws an exception in that case.

Message 7 of 10
GTVic
in reply to: soccerazy

Maybe you need to lock the source drawing, if I'm understanding your code correctly.

 

This is my subroutine to copy block definitions from a template DWG to the current drawing using the clone method. I use it for updating block definitions or bringing in missing blocks.

 

    Private Sub LoadBlocks()

        Dim dm As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
        Dim ed As Editor = dm.MdiActiveDocument.Editor
        Dim destDb As Database = dm.MdiActiveDocument.Database
        Dim sourceDb As Database = New Database(False, True)
        Dim mapping As IdMapping = New IdMapping()
        Dim blockIds As ObjectIdCollection = New ObjectIdCollection()
        Dim s As String
        Dim DisplayError As Boolean = False

        Try
            Using objLock As DocumentLock = AcadDoc.LockDocument()
                Try
                    sourceDb.ReadDwgFile(Path.Combine(Path.Combine(EngToolsPath.FullName, "Source"), cboSource.Text), System.IO.FileShare.Read, True, "")
                    Try
                        Using Trans As Transaction = sourceDb.TransactionManager.StartTransaction()
                            Try
                                Dim bt As BlockTable = Trans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False)
                                Dim btr As BlockTableRecord
                                For Each btrId As ObjectId In bt
                                    btr = Trans.GetObject(btrId, OpenMode.ForRead, False)
                                    If lstItems.SelectedItems.Contains(btr.Name) Then
                                        blockIds.Add(btrId)
                                    End If
                                    btr.Dispose()
                                Next
                            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                ed.WriteMessage(vbLf & "Error scanning for block definitions in source drawing: " & ex.Message & vbLf)
                                ed.UpdateScreen()
                                DisplayError = True
                            End Try
                        End Using
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                        ed.WriteMessage(vbLf & "Error reading from source drawing: " & ex.Message & vbLf)
                        ed.UpdateScreen()
                        DisplayError = True
                    End Try
                    If Not DisplayError Then
                        Try
                            Using Trans As Transaction = destDb.TransactionManager.StartTransaction()
                                Try
                                    sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, False)
                                    Trans.Commit()
                                    Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.AcadDocument.Regen(1)
                                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                    Trans.Abort()
                                    ed.WriteMessage(vbLf & "Error transferring blocks to current drawing: " & ex.Message & vbLf)
                                    ed.UpdateScreen()
                                    DisplayError = True
                                End Try
                            End Using
                        Catch ex As Autodesk.AutoCAD.Runtime.Exception
                            ed.WriteMessage(vbLf & "Error transferring blocks to current drawing: " & ex.Message & vbLf)
                            ed.UpdateScreen()
                            DisplayError = True
                        End Try
                    End If
                    sourceDb.Dispose()
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    ed.WriteMessage(vbLf & "Error reading from source drawing: " & ex.Message & vbLf)
                    ed.UpdateScreen()
                    DisplayError = True
                End Try
            End Using
        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            ed.WriteMessage(vbLf & "Error locking current drawing for update: " & ex.Message & vbLf)
            ed.UpdateScreen()
            DisplayError = True
        End Try

        lblError.Visible = DisplayError

    End Sub

 

Message 8 of 10
StephenPreston
in reply to: soccerazy

BTW (Just checking) Do you actually want to open the document in the editor (i.e. does the user need to see and interact with it). If not, then it is a lot easier (and faster) to open a DWG file in a side database (using Database.ReadDwgFile) to modify it programmatically.

Cheers,

Stephen Preston
Autodesk Developer Network
Message 9 of 10
jeff
in reply to: soccerazy

If you do want them to interact with it have you tried making it the active document first then add Block and BlockReference?

You can also find your answers @ TheSwamp
Message 10 of 10
soccerazy
in reply to: soccerazy

Thanks for everybody's responses. I do need both the source and destination drawing open for the user to interact with. Using the CommandFlags.Session and locking the drawings is working for my situation (at least so far).

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost