TheSwamp

Code Red => .NET => Topic started by: TJK44 on November 17, 2011, 10:59:31 AM

Title: Xref multiple times with one dwg file
Post by: TJK44 on November 17, 2011, 10:59:31 AM
I have wrote this command that wblocks out each block to a parts folder and then I xref each of these parts back in to an empty dwg file. It works fine, but noticed that if there is more than one block with the same name, the new dwg only shows the last block that was added to the parts folder with that name. Do i have to cycle through each block and assign the block name plus an incrementing number, or is there a way with one block in this folder to automatically xref it back each time it was present on the previous drawing? The purpose of this is to generate a clean drawing file from the old one that could have a bunch of stuff we don't need. Currently I am creating a folder called xrefs inside the parts folder and cycling through each wblock and incrementing a number at the end. Would like to not have to do that seeing it just will take up a lot of extra storage.

Thanks for any help,

Ted
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 18, 2011, 09:09:35 AM
In addition to what I had posted, it seems like if I xref the same dwg more than once, the one that was referenced before gets replaced by the next one and so on. The position of each xref is different. Anyone have an idea as to why each time I xref the same dwg the other one would get replaced?

**UPDATE
It appears that the xrefobjID is getting the same objectID each time it reads that file to xref, so that is why it is replacing the files that are already xreferenced in the drawing. Is there anyway around this?
Title: Re: Xref multiple times with one dwg file
Post by: MexicanCustard on November 18, 2011, 10:27:34 AM
Are you using the same name when adding it to the drawing?

I.E. db.OverlayXref(filepath, XrefName);
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 18, 2011, 10:33:23 AM
Yes, does that have to be unique each time or it will generate a the same ID? Here is what I have for that line of code

Code: [Select]
Dim xrefObjId As ObjectId = xrefdb.AttachXref(file, Path.GetFileNameWithoutExtension(file))
Title: Re: Xref multiple times with one dwg file
Post by: MexicanCustard on November 18, 2011, 10:43:13 AM
Yes, that has to be unique.
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 18, 2011, 10:48:17 AM
I tried to increment a number after the blockname and in the xref manager it said i had three different xrefs, but still only wound up with one drawing. What I want to do is only see 1 xref for all three of the drawing with the same block name. Here is the entire code I am working with if you or anyone could offer any suggestions. Thanks.

Code: [Select]
        <CommandMethod("CreateMasterDWG")> _
        Public Sub newBlock()
            Dim document As Document = Application.DocumentManager.MdiActiveDocument
            Dim editor As Editor = document.Editor
            Dim database As Database = document.Database

            Dim fName2 As String = database.Filename
            If fName2 = "" Then
                Exit Sub
            End If
            Dim curdir2 As String = Path.GetDirectoryName(fName2)
            Dim db As Database = New Database(True, False)
            Dim i As Integer = 1
            Dim frm1 As New Form1
            Dim strFileName As String
            frm1.SaveFileDialog1.InitialDirectory = curdir2
            frm1.SaveFileDialog1.Title = "Select a location to save the master file."
            frm1.SaveFileDialog1.Filter = "Drawing Files|*.dwg"
            frm1.SaveFileDialog1.AddExtension = True

            If frm1.SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
                strFileName = frm1.SaveFileDialog1.FileName
                Dim xrefPath As String = strFileName
            Else
                Exit Sub
            End If

            Using trans As Transaction = db.TransactionManager.StartTransaction()
                db.SaveAs(strFileName, DwgVersion.Newest)
            End Using
            Dim xrefdb As Database = New Database(False, False)
            xrefdb.ReadDwgFile(strFileName, FileShare.ReadWrite, False, "")

            Dim oidc As New ObjectIdCollection()
            Try
                Using trans As Transaction = database.TransactionManager.StartTransaction()
                    Dim btr As BlockTable = DirectCast(trans.GetObject(database.BlockTableId, OpenMode.ForRead), BlockTable)
                    Dim btrMs As BlockTableRecord = TryCast(btr(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead), BlockTableRecord)
                    'Dim i As Integer = 0
                    Dim partnum As String = ""
                    'go through each object in the block table record
                    For Each entID As ObjectId In btrMs
                        'create the objectIDCollection used to create the wblock
                        Dim oidc2 As New ObjectIdCollection()
                        'create variable used to determine is it is a block reference
                        Dim ent As Entity = trans.GetObject(entID, OpenMode.ForRead, False)
                        'if it is a block then perform code below
                        If TypeOf ent Is BlockReference Then
                            'since it is a block, add to the IDcollection
                            oidc2.Add(entID)
                            Dim blkRef As BlockReference = TryCast(trans.GetObject(entID, OpenMode.ForRead, False), BlockReference)
                            Dim attRefIds As AttributeCollection = blkRef.AttributeCollection

                            'cycle through the attributes associated with the current block
                            For Each attrefid As ObjectId In attRefIds
                                Dim attref As AttributeReference = trans.GetObject(attrefid, OpenMode.ForRead, False)

                                Select Case attref.Tag
                                    'if block has attribute project ID then create the wblock
                                    Case "Part Number"
                                        'create string with partnum

                                        Dim strPartNum As String = attref.TextString

                                        Dim DestData As New Database(True, False)

                                        Using document.LockDocument()
                                            Using transNewDb As Transaction = DestData.TransactionManager.StartTransaction()
                                                Dim bt As BlockTable = TryCast(transNewDb.GetObject(DestData.BlockTableId, OpenMode.ForRead), BlockTable)
                                                Dim IDMap As New IdMapping()
                                                DestData.WblockCloneObjects(oidc2, bt(BlockTableRecord.ModelSpace), IDMap, DuplicateRecordCloning.Replace, False)
                                                transNewDb.Commit()

                                                Dim fName As String = database.Filename
                                                Dim curdir As String = Path.GetDirectoryName(fName)

                                                If Not Directory.Exists(curdir & "\parts") Then
                                                    Directory.CreateDirectory(curdir & "\parts")
                                                End If
                                                Directory.CreateDirectory(curdir & "\parts\xrefs")
                                                DestData.SaveAs(curdir & "\parts\" & strPartNum & ".dwg", DwgVersion.Newest)
                                                DestData.SaveAs(curdir & "\parts\xrefs\" & strPartNum & ".dwg", DwgVersion.Newest)
                                                Dim strPartFile As String = curdir & "\parts\" & strPartNum & ".dwg"
                                                'CreateXrefMaster(strFileName, strPartFile)

                                                Using trx As Transaction = xrefdb.TransactionManager.StartTransaction()
                                                    Dim xrefBt As BlockTable = trx.GetObject(xrefdb.BlockTableId, OpenMode.ForWrite)
                                                    Dim btrMs2 As BlockTableRecord = trx.GetObject(xrefBt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

                                                    Dim file As String = strPartFile
                                                    'list the names of all files in the specified directory

                                                    Dim xrefObjId As New ObjectId

                                                    xrefObjId = xrefdb.AttachXref(file, Path.GetFileNameWithoutExtension(file))

                                                    Dim bref As New BlockReference(Point3d.Origin, xrefObjId)

                                                    btrMs2.AppendEntity(bref)

                                                    trx.AddNewlyCreatedDBObject(bref, True)

                                                    trx.Commit()


                                                End Using

                                            End Using
                                        End Using


                                End Select

                            Next

                        End If
                       
                    Next

                End Using

                xrefdb.SaveAs(strFileName, DwgVersion.Newest)

            Catch ex As System.Exception
                Windows.MessageBox.Show("Error occurred: " & ex.Message, "Error", Windows.MessageBoxButton.OK, Windows.MessageBoxImage.Error)
            End Try
        End Sub
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 18, 2011, 10:49:03 AM
Have you tried to Xref the drawing once then insert as many BlockReference's as needed using the xref's BlockTableRecord?
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 18, 2011, 10:53:47 AM
I'm sorry, I kind of understand what you are saying Jeff. Do you mean after it creates the first xref, if it sees another block with the same name that was already xreferenced then use the xref that is already in the btr and give it the coordinates of the block?
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 18, 2011, 11:52:53 AM
I'm sorry, I kind of understand what you are saying Jeff.
No need to apologize as I rarely understand what I am saying either.
What I want to do is only see 1 xref for all three of the drawing with the same block name.
I think I am confused on the intent, sorry about that.
 
 
 
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 18, 2011, 11:57:48 AM
Well I got all the correct xrefs showing on the new file it is creating. Now my only problem is they are not showing up at the correct positions when I open the drawing. I changed the position for the blockreference that is creating the xref each time and that seemed to bring in each of the xrefs. I'll keep playing with it, seems I am getting closer. Here is my code now if anyone would like to give any input. Thanks.

Quote
I think I am confused on the intent, sorry about that.
What I am trying to do is basically clean up a drawing. I am searching a drawing for blocks that contain the attribute Part Number. If it does I am wblocking each of them and then want to xref whatever blocks it found that had a part number attribute into a new drawing.

Code: [Select]
        <CommandMethod("CreateMasterDWG")> _
        Public Sub newBlock()
            Dim document As Document = Application.DocumentManager.MdiActiveDocument
            Dim editor As Editor = document.Editor
            Dim database As Database = document.Database

            Dim fName2 As String = database.Filename
            If fName2 = "" Then
                Exit Sub
            End If
            Dim curdir2 As String = Path.GetDirectoryName(fName2)
            Dim db As Database = New Database(True, False)
            Dim i As Integer = 1
            Dim frm1 As New Form1
            Dim strFileName As String
            frm1.SaveFileDialog1.InitialDirectory = curdir2
            frm1.SaveFileDialog1.Title = "Select a location to save the master file."
            frm1.SaveFileDialog1.Filter = "Drawing Files|*.dwg"
            frm1.SaveFileDialog1.AddExtension = True

            If frm1.SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
                strFileName = frm1.SaveFileDialog1.FileName
                Dim xrefPath As String = strFileName
            Else
                Exit Sub
            End If

            Using trans As Transaction = db.TransactionManager.StartTransaction()
                db.SaveAs(strFileName, DwgVersion.Newest)
            End Using
            Dim xrefdb As Database = New Database(False, False)
            xrefdb.ReadDwgFile(strFileName, FileShare.ReadWrite, False, "")

            Dim oidc As New ObjectIdCollection()
            Try
                Using trans As Transaction = database.TransactionManager.StartTransaction()
                    Dim btr As BlockTable = DirectCast(trans.GetObject(database.BlockTableId, OpenMode.ForRead), BlockTable)
                    Dim btrMs As BlockTableRecord = TryCast(btr(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead), BlockTableRecord)
                    'Dim i As Integer = 0
                    Dim partnum As String = ""
                    'go through each object in the block table record
                    For Each entID As ObjectId In btrMs
                        'create the objectIDCollection used to create the wblock
                        Dim oidc2 As New ObjectIdCollection()
                        'create variable used to determine is it is a block reference
                        Dim ent As Entity = trans.GetObject(entID, OpenMode.ForRead, False)
                        'if it is a block then perform code below
                        If TypeOf ent Is BlockReference Then
                            'since it is a block, add to the IDcollection
                            oidc2.Add(entID)
                            Dim blkRef As BlockReference = TryCast(trans.GetObject(entID, OpenMode.ForRead, False), BlockReference)
                            Dim attRefIds As AttributeCollection = blkRef.AttributeCollection

                            'cycle through the attributes associated with the current block
                            For Each attrefid As ObjectId In attRefIds
                                Dim attref As AttributeReference = trans.GetObject(attrefid, OpenMode.ForRead, False)

                                Select Case attref.Tag
                                    'if block has attribute project ID then create the wblock
                                    Case "Part Number"
                                        'create string with partnum

                                        Dim strPartNum As String = attref.TextString

                                        Dim DestData As New Database(True, False)

                                        Using document.LockDocument()
                                            Using transNewDb As Transaction = DestData.TransactionManager.StartTransaction()
                                                Dim bt As BlockTable = TryCast(transNewDb.GetObject(DestData.BlockTableId, OpenMode.ForRead), BlockTable)
                                                Dim IDMap As New IdMapping()
                                                DestData.WblockCloneObjects(oidc2, bt(BlockTableRecord.ModelSpace), IDMap, DuplicateRecordCloning.Replace, False)
                                                transNewDb.Commit()

                                                Dim fName As String = database.Filename
                                                Dim curdir As String = Path.GetDirectoryName(fName)

                                                If Not Directory.Exists(curdir & "\parts") Then
                                                    Directory.CreateDirectory(curdir & "\parts")
                                                End If
                                                Directory.CreateDirectory(curdir & "\parts\xrefs")
                                                DestData.SaveAs(curdir & "\parts\" & strPartNum & ".dwg", DwgVersion.Newest)
                                                DestData.SaveAs(curdir & "\parts\xrefs\" & strPartNum & ".dwg", DwgVersion.Newest)
                                                Dim strPartFile As String = curdir & "\parts\" & strPartNum & ".dwg"
                                                'CreateXrefMaster(strFileName, strPartFile)

                                                Using trx As Transaction = xrefdb.TransactionManager.StartTransaction()
                                                    Dim xrefBt As BlockTable = trx.GetObject(xrefdb.BlockTableId, OpenMode.ForWrite)
                                                    Dim btrMs2 As BlockTableRecord = trx.GetObject(xrefBt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

                                                    Dim coords As Point3d = blkRef.Position()

                                                    Dim file As String = strPartFile
                                                    'list the names of all files in the specified directory

                                                    Dim xrefObjId As New ObjectId

                                                    xrefObjId = xrefdb.AttachXref(file, Path.GetFileNameWithoutExtension(file))

                                                    Dim bref As New BlockReference(coords, xrefObjId)

                                                    btrMs2.AppendEntity(bref)

                                                    trx.AddNewlyCreatedDBObject(bref, True)

                                                    trx.Commit()

                                                    xrefdb.SaveAs(strFileName, DwgVersion.Newest)

                                                End Using

                                            End Using
                                        End Using


                                End Select

                            Next

                        End If
                       
                    Next

                End Using
                Directory.Delete(curdir2 & "\parts\xrefs", True)


            Catch ex As System.Exception
                Windows.MessageBox.Show("Error occurred: " & ex.Message, "Error", Windows.MessageBoxButton.OK, Windows.MessageBoxImage.Error)
            End Try
        End Sub
Title: Re: Xref multiple times with one dwg file
Post by: MexicanCustard on November 21, 2011, 08:28:23 AM
If I'm understanding correctly, your trying to insert the same drawing as an Xref but in a different location like you would a block?
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 21, 2011, 08:52:27 AM
Yes, I am generating a dwg file with wblock and then would like to create a new empty drawing and xref the file. The problem I am having is when a block is referenced more than once. The block is in the drawing correctly, but they are not in the correct position. If I'm going through a drawing and wblocking each block and then doing an xref it will show up in the new drawing but they will be on top of each other. An example would be I had 4 of the same part on the drawing and then I run this and the 4 parts will be on top of each other instead of having the correct position and rotation.
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 21, 2011, 11:07:01 AM
I think some of the confusion is you are using xref to mean a BlockReference.
 
Here are some 'loose' definitions

Xref----A BlockTableRecord that is mapped to anoter Drawing. You will never see a xref in a drawing.

BlockReference---- A 'Insert' that is a graphical representation of a BlockTableRecord which can have its own scale, InsertionPoint(wich transform all objects from its orgin definition), etc.....
 
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 21, 2011, 11:10:38 AM
Sorry you're right Jeff. I am trying to use blockreferences in my situation. Do you still use db.AttachXRef to reference a block in a drawing?
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 21, 2011, 11:21:15 AM
You use AttachXRef once and  AttachXRef will return a ObjectId of the newly created BlockTableRecord.

Then you can create as my BlockReference's as you want passing in the ObjectId to the BlockReference's second argument in its constructor.
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 21, 2011, 11:25:37 AM
Code: [Select]
                Dim xrefId As ObjectId = db.AttachXref("FilePath", "Name of block")
                For i As Integer = 0 To 10
                    Dim xrefBref As New BlockReference(Point3d.Origin, xrefId)
                Next
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 21, 2011, 11:35:09 AM
That's what I am doing, but it doesn't put the blockreferences at the correct positions. I'm using Point3d.Origin for the point. Everytime I reference it changes the location of the other blocks that were added previously if the blockreference file changes I think is what is happening.  I tried to increment the number at the end of each block drawing file and then performed the same reference action and it recreated the drawing as I wanted and the block references were all in the correct position. The only problem with this is I don't want those extra files and also, if it's the same part it should only reference one drawing, and not reference a separate drawing per instance of the part.
Title: Re: Xref multiple times with one dwg file
Post by: kaefer on November 22, 2011, 07:56:53 AM
... if it's the same part it should only reference one drawing, and not reference a separate drawing per instance of the part.

I'm confused. Based on your message here (http://www.theswamp.org/index.php?topic=40103.msg453903#msg453903), you were to loop through the model space trying to replace all block references based only on the occurence of the attribute "Part Number". Please forgive me a couple of remarks:

You don't have Option Strict On], primarily to avoid implicit conversions. Replace them with CType and TryCast instead.

You don't seem to account for case-sensitive string comparison, and spaces in attribute tags are a no-no.

The loop over the AttributeReferences could be made more transparent with Linq's query expressions. If you want to replace one BlockReference with another BlockReference, you could as well keep it and replace its definition (that is the BlockTableRecord property). Taken together, maybe you could make use of this VB.NET code, which tries to illustrate those concerns, including the erasure of the attributes. Xrefs with attributes, anyone?

Code: [Select]
    Public Sub replaceBlock()
        Dim doc = Application.DocumentManager.MdiActiveDocument
        Dim ed = doc.Editor
        Dim db = doc.Database
        Dim ofd =
            New OpenFileDialog(
                "Select drawing to attach",
                Nothing,
                "dwg",
                "DrawingToAttach",
                OpenFileDialog.OpenFileDialogFlags.NoFtpSites)
        If ofd.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
            Exit Sub
        End If
        Dim xName =
            SymbolUtilityServices.GetSymbolNameFromPathName(
                ofd.Filename, "dwg")
        xName =
            SymbolUtilityServices.RepairSymbolName(
                xName, False)
        Dim xBtrId = db.OverlayXref(ofd.Filename, xName)
        Using tr As Transaction = db.TransactionManager.StartTransaction()
            Dim bt = CType(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
            For Each bref In
                From id In CType(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord).Cast(Of ObjectId)()
                Select br = TryCast(tr.GetObject(id, OpenMode.ForRead), BlockReference)
                Where br IsNot Nothing AndAlso _
                    (From id In br.AttributeCollection.Cast(Of ObjectId)()
                     Select ar = TryCast(tr.GetObject(id, OpenMode.ForRead), AttributeReference)
                     Where ar IsNot Nothing) _
                    .FirstOrDefault(Function(attref) attref.Tag.Equals("PartNumber", StringComparison.InvariantCultureIgnoreCase)) _
                    IsNot Nothing
                bref.UpgradeOpen()
                bref.BlockTableRecord = xBtrId
                For Each attref In
                    From id In bref.AttributeCollection.Cast(Of ObjectId)()
                    Select ar = TryCast(tr.GetObject(id, OpenMode.ForWrite), AttributeReference)
                    Where ar IsNot Nothing
                    attref.Erase()
                Next
            Next
            tr.Commit()
        End Using
    End Sub
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 08:25:10 AM
I'm sorry I haven't been as clear as I probably could be. This is the process I am trying to create. Initially a user is going to have a drawing with a bunch of blocks and other entities in it. The purpose of this command is to only select the blocks that have the Part Number attribute, then wblock each of these blocks and then auto populate a new blank drawing file with these blocks that have the part number attribute. So far the code I had posted here http://www.theswamp.org/index.php?topic=40103.msg453886#msg453886 (http://www.theswamp.org/index.php?topic=40103.msg453886#msg453886) does all of this for me except in the instance the initial drawing has multiples of the same block with the same part number. The new blank drawing is being created and populated, but the positioning of the blocks is not correct. It is xreferencing each of the blocks that contained a part number in the drawing, the problem lies if there is more than one with the exact same part number they appear directly on top of each other.

What I was trying to do was wblock each time it encountered a block with a part number and at the same time attach it as an xref and save the drawing and keep looping through the original drawing. I think the problem is that each time the wblock is rewritten (because it sees a block with the same part number) it is xreferencing it, but it also is changing what xreferences the drawing already has with the same partnumber. I am naming the file "partnumber.dwg". I don't even know if it is possible to do this, because of the xreference file changing it seems it will change what is already xreferenced in the drawing.

I hope that clarifies or makes any sense on what I am trying to accomplish.

Thank you in advance for any help,

Ted
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 11:37:12 AM
I think I understand.
If so you might try

1.Iterate the BlockTable looking for BlockTableRecords that contain the AttributeDefinition
2. If it does WBlockCloneObjects the entites fom the BlockTableRecords into a new Drawings modelspace
3.Get a collection insertion points from GetBlockReferenceIds 
4. Xref the new drawing in then insert a new BlockReference at each Postion
 
Is that what you are trying to do?
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 11:46:38 AM
Yes, I think you are understanding what I am trying to do. The problem I am having is dealing with the same block reference more than once from the blocktablerecords. Basically Im trying to add an xref to a blockreference more than once and they all have different insertion points. Right now after it completes, all blockreferences that are the same have the same insertion point and lie on top of each other.

What you have wrote there is what I am aiming for Jeff.
Title: Re: Xref multiple times with one dwg file
Post by: MexicanCustard on November 22, 2011, 01:33:37 PM
Sounds like it would work better if you would bring them in as blocks and not xrefs.  I've never tried bringing in the same file as an xref and just changing its block name and location.  Obviously thats impossible using the ACAD interface and can only be done programatically.  Is there a reason your using Xrefs instead of blocks?

Have you looked at the database with ArxDbg after loading them to confirm there are actually two BlockReferences?
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 02:16:20 PM
I haven't looked in the ArxDbg. For the blocks I know that aren't in the correct location if I highlight one a drag it there will be another one underneath it.

They want xrefs so the file size isn't so large.
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 02:55:50 PM
One way to get past this is maybe to wblock and then if it encounters another block with the same part number thats already been wblocked, perform a copy in the new drawing and give it the proper coordinates. Any thoughts on that maybe working?
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 03:02:10 PM
So you need to take the blocks out and change them to xref for I guess memory reasons?
 
If it is the same block but with different attribute value does it need to be a different block or xref?
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 03:10:52 PM
If it has a different attribute (partnumber) it is fine, the problem comes in when there are multiples of the same part(block). In this case each block will be a part in the drawing. If I use this code it will bring all the blocks in as xref's each referencing the correct drawing but their positions are way off.


Code: [Select]
Dim xrefObjId As ObjectId = xrefdb.AttachXref(strPartFile, Path.GetFileNameWithoutExtension(strPartFile))

Dim bref As New BlockReference(Point3d.Origin, xrefObjId)

Dim scale As Scale3d = blkRef.ScaleFactors
bref.Position = blkRef.Position
bref.Rotation = blkRef.Rotation
bref.ScaleFactors = scale

btrMs2.AppendEntity(bref)

blkRef is defined like this

Code: [Select]
Using trans As Transaction = database.TransactionManager.StartTransaction()
                    Dim btr As BlockTable = DirectCast(trans.GetObject(database.BlockTableId, OpenMode.ForRead), BlockTable)
                    Dim btrMs As BlockTableRecord = TryCast(btr(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead), BlockTableRecord)
                    'go through each object in the block table record
                    For Each entID As ObjectId In btrMs
                        'create the objectIDCollection used to create the wblock
                        Dim oidc2 As New ObjectIdCollection()
                        'create variable used to determine is it is a block reference
                        Dim ent As Entity = trans.GetObject(entID, OpenMode.ForRead, False)
                        'if it is a block then perform code below
                        If TypeOf ent Is BlockReference Then
                            'since it is a block, add to the IDcollection
                            oidc2.Add(entID)
                            Dim blkRef As BlockReference = TryCast(trans.GetObject(entID, OpenMode.ForRead, False), BlockReference)
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 03:26:58 PM
Dim bref As New BlockReference(Point3d.Origin, xrefObjId)
 
That needs to be the position of the blockreference from original file.
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 03:50:11 PM
That brings in all the blocks (parts) from the original drawing, but their positions in the new drawing are not correct. Here is what it looks like before and after I run the command with zoom extents.

Code: [Select]
Dim bref As New BlockReference(blkRef.Position, xrefObjId)
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 03:59:04 PM
Have not tested your code but will get a chance later.
Might have something to do with wblocking the blockreference or something is not getting translated correctly
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 04:03:13 PM
Thanks a lot Jeff, let me know if you have any questions about getting it to run when you have the time.
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 04:36:18 PM
Got it loaded up and can read it easier in VS
Could you load a test drawing with some of blocks?
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 22, 2011, 04:43:54 PM
Here is the same one that I took a screen shot of earlier.

Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 07:35:21 PM
Sorry got tied up and need to go but will have time tomorrow to post more.
 
I at least see what the problem is.
Title: Re: Xref multiple times with one dwg file
Post by: Kerry on November 22, 2011, 08:05:39 PM
Jeff,
I've waiting for 4 1/2 days for an accurate, concise, relevant  description of the problem issues from the OP in one post ... care to share ??

added:

No hurry ... I'm just being a pedant :)
Regards
Title: Re: Xref multiple times with one dwg file
Post by: Jeff H on November 22, 2011, 11:38:12 PM
Sorry about that I had someone come in the office and need some things and then had to run out to get my son.
 
I am staying at relatives house tonight to help get son to sleep and get him up because he is going to ride with them....... that does not matter but have no info, VS, AutoCAD, etc.... in front of me. So this is coming from where ever I can pull it out.
 
-The first obvious thing is to break up the function because it is just too much to 
  try to focus on at once. There are 4, 10 or however many databases, 
  transactions to keep up with.
 
 
 
-You are Wblocking the BlockReference. So you are creating a file that contains a
  'insert' inserted at the same position.
 
Quote
If it has a different attribute (partnumber) it is fine, the problem comes in when there are multiples of the same part(block). In this case each block will be a part in the drawing

-You are using the PartNumber as the unique identifier. The only thing that
  differentiates a xref from one another is the part number
 
-When a BlockReference with the same BlockDefinition have different values for
  the part numbers a new file to xref is created. You are creating files to xref based
  on the part number.
 
-Maybe you want a different 'xref' for each 'Part Number' but you are naming your 
 files and xref blockTableRecord with the textstring value of the AttributeReference.
 If they have the same part number than they will come from last created file to  xref, same block  or not.
 Give them all the same part number and see what happens.
 It just keeps overwriting itself. Still not clear but would make more sense to me to 
 use block name
 
If I use this code it will bring all the blocks in as xref's each referencing the correct drawing but their positions are way off.

Code: [Select]
Dim bref As New BlockReference(Point3d.Origin, xrefObjId)
Dim scale As Scale3d = blkRef.ScaleFactors
bref.Position = blkRef.Position



First you set postion at the orgin then you change to the BlockReference's Position.
 
Again the reason it is off is because you create a file with a 'insert' at say (10,10) where it belongs. Then you xref it that and insert it a (10,10) so now it is at (20,20)
 
When you use Point3d.Origin the reason they are on top of each other is the same reason as explained above. If they have the same PartNumber they are Defined from the same definition which is the last file added with that part number.
 
So when you have multiple blockreferences and do NOT want a different xref for each insert I think it creates too much complexity creating the files to be xrefed with a BlockReference.
Which one do you choose?
Have to transform all the others.
etc....
 
 
There is probably better methods or to avoid it all together but if needed the first thing that comes to mind is wblock the definition so each entity is the same distance from the xref file orgin as it was in the definition. That way the Blcokreference insertion point could be used.
 
Use the BlockName as identifier so that way you could do something like
 
XrefID
 
If bt.Has("BlockName") then
XrefID = bt("BlockName")
Else
XrefID = db.AttachXref.......
End If
 
Blockref = new Blockreference(pnt, XrefID )
 
 
 
Sorry I am in hurry and hope that helps but tommorrow will be able to post something that maybe makes more sense.
 
 
 
Title: Re: Xref multiple times with one dwg file
Post by: kaefer on November 23, 2011, 05:40:39 AM
@Jeff H: Congratulations for your promotion!
@TJK44: Okay, here I'm at it again, still not according to your spec (but close, hopefully).

In the source drawing, collect the ObjectIds of the BlockReferences and their names.
Code: [Select]
        Dim xNames = New List(Of String)()
        Dim oidc = New ObjectIdCollection()
        ' Collect BlockReferences and Xref names
        Using tr As Transaction = db.TransactionManager.StartTransaction()
            For Each br In
            From bref In SymbolUtilityServices.GetBlockModelSpaceId(db).GetObject(Of BlockTableRecord)().GetObjects(Of BlockReference)()
            Where
                bref.AttributeCollection.GetObjects(Of AttributeReference)() _
                .FirstOrDefault(Function(attref) attref.Tag.Equals("Part Number", StringComparison.InvariantCultureIgnoreCase)) _
                IsNot Nothing AndAlso _
                targetFiles.Contains(bref.Name, StringComparer.InvariantCultureIgnoreCase)
            Select bref
                oidc.Add(br.ObjectId)
                If Not xNames.Contains(br.Name, StringComparer.InvariantCultureIgnoreCase) Then
                    xNames.Add(br.Name)
                End If
            Next
            tr.Commit()
        End Using

Then create a side database, where the Xrefs are attached (or overlayed). After that, using WBlockCloneObjects with DuplicateRecordCloning.Ignore, I'll transfer the BlockReferences collected in the previous step. Voila, they're instances of external refences. Only thing to do is to remove their attributes, and to save the whole thing.

Code: [Select]
        Using destDb = New Database(True, True),
            destTr = destDb.TransactionManager.StartTransaction()
            For Each xName In xNames
                destDb.OverlayXref(System.IO.Path.Combine(targetDir, xName), xName)
            Next
            Dim msId = SymbolUtilityServices.GetBlockModelSpaceId(destDb)
            destDb.WblockCloneObjects(oidc, msId, New IdMapping(), DuplicateRecordCloning.Ignore, False)

Complete code attached.
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 23, 2011, 08:14:10 AM
I'm trying to download the complete code you posted kaefer to take a look at it, for some reason everytime I click the link (or any link) it prompts me to download index.php and I can never download the file.

*Resolved - used IE instead of Firefox
Title: Re: Xref multiple times with one dwg file
Post by: TJK44 on November 30, 2011, 11:27:01 AM
I found a way to get the xrefs to show in the correct positions. If the original block has a position of 0,0,0 and then I xref it using this code it works. The only problem with this is the user can not pick an insertion point for the block. I'll keep working on it when I have the time and report back.

Code: [Select]
Dim bref As New BlockReference(blkRef.Position, xrefObjId)
bref.Rotation = blkref.Rotation
bref.ScaleFactors = blkref.ScaleFactors