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

Repeatedly Insert Block

35 REPLIES 35
SOLVED
Reply
Message 1 of 36
vince1327
4534 Views, 35 Replies

Repeatedly Insert Block

Hey everyone,

 

So i've been able to successfully import a single block at a time into an active drawing, now i'm trying to insert the same block multiple times to essentially create a layout within the drawing. How would i go about inserting a selected block "x" amount of times. For a better idea of where i'm stuck, i've commented a bit of code below with a better explanation.  What i've got so far is this:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DataExtraction;
using Autodesk.AutoCAD.Colors;
using DB_Extraction;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace CHTEST
{
public class CHTEST1
{
// This is the name of my command

[Autodesk.AutoCAD.Runtime.CommandMethod("CHTEST")]

public void CHTEST1()
{
{

Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
Point3d pMax = new Point3d();
string comp = "C:\\ACADSTUFF\\test.dwg";
// int numsprink = 5;

Transaction tr = doc.TransactionManager.StartTransaction();
using (DocumentLock acLckDoc = doc.LockDocument())

try
{

//Check to see if the layer CH-TST already exists, if so use it, if not create it and then use it
string sLayerName1 = "CH-TST";

LayerTable acLyrTbl1; acLyrTbl1 = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
LayerTableRecord acLyrTblRec;

if (acLyrTbl1.Has(sLayerName1) == false)
{
acLyrTblRec = new LayerTableRecord();
// Assign the layer a name
acLyrTblRec.Name = sLayerName1;

// Upgrade the Layer table for write
if (acLyrTbl1.IsWriteEnabled == false) acLyrTbl1.UpgradeOpen();

// Append the new layer to the Layer table and the transaction
acLyrTbl1.Add(acLyrTblRec);
tr.AddNewlyCreatedDBObject(acLyrTblRec, true);
}
else
{
// Open the layer if it already exists for write
acLyrTblRec = tr.GetObject(acLyrTbl1[sLayerName1], OpenMode.ForWrite) as LayerTableRecord;

}


//This partwill import the selected dwg into modelspace and activate it
string dwgName = HostApplicationServices.Current.FindFile(comp, acadApp.DocumentManager.MdiActiveDocument.Database, FindFileHint.Default);

Database db1 = new Database(false, false);

db1.ReadDwgFile(dwgName, System.IO.FileShare.Read, true, "");

ObjectId BlkId;

BlkId = doc.Database.Insert(dwgName, db1, false);

BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead, true);

BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);


//ideally this next section will iterate the import process "x" amount of times and allow for effetive block placement!

// Below is part of some code that i had used to copy a paperspace layout "x" amount of times. I understand the iteration part but am not sure how to apply it to a block. I don't know how to reference the block that i intend to insert and then have it populate "x" amount of times.
/*
for (int i = 1; i <= numLayouts; i++)
{
lm.CopyLayout("Layout1", "SP-" + i.ToString());
Layout layout = (Layout)trx.GetObject(lm.GetLayoutId("SP-" + i.ToString()), OpenMode.ForWrite);

}

*/


//FACSPR7

 

 

BlockReference bref = new BlockReference(pMax, BlkId);

bref.Layer = "CH-TST";

btr.AppendEntity(bref);

tr.AddNewlyCreatedDBObject(bref, true);

bref.ExplodeToOwnerSpace();

bref.Erase();

tr.Commit();


}
catch
{
MessageBox.Show("Failed to read the DWG from the refence folder, are you sure it is present?");
}
finally
{
tr.Dispose();
}

 


}

}
}

}

 

 

 

35 REPLIES 35
Message 21 of 36
vince1327
in reply to: cincir

Haha i feel your pain with the intellisense, i've slowly been getting used to it but sometimes...just sometimes. I've updated the code but still no luck. When i run the command, it imports my blocks, but i still don't have the custom attributes that i would see when the block is exploded. I'm not sure what's going on here? Is is possible to just explode the block to owner space and then copy it to the appropriate layer?

 

Thanks again!

Message 22 of 36
cincir
in reply to: vince1327

something must be missing. i have similar code in one of my software working. are your blocks dynamic? and you know you must set the values of nonconstant attributereferences in order them to be shown. i advise you to double-click one of your blockreferences and see that your attributedefinitions are successfully transported to your blockreference. if so nothing bad just assign values to attributereferences.

Message 23 of 36
vince1327
in reply to: cincir

Hey Cincir,

 

What do you mean that i must set the values of nonconstant attributereferences? Right now they import just fine and on the correct layer but i can only view my custom attributes if i explode the blocks. If i use attedit, i'm told that the block has no editable attributes.

 

Thanks again for all your help, it really is much appreciated.

Message 24 of 36
fieldguy
in reply to: vince1327

Have you come across "attsync"?  I don't know if you can do it in .net.  There is 1 post in this forum with no replies.

 

After you get the block inserted on the correct layer, try "attsync" manually (command line) to see if it fixes your attributes.  It's worth a try IMHO.

Message 25 of 36
vince1327
in reply to: fieldguy

Ok so i've figured out what's going on with the help of our design guys here. The original dwg already contains the block, with attributes and all. When i bring it into my new drawing with this code, it creates a block out of this block and loses all it's attributes until it's exploded. When it is exploded, it takes on the layer it was assigned in the original dwg. So what i need to do now is bring in the block from the original dwg as it is and re-assign it's layer. What is the easiest way to do this do you know?

 

thanks again!

Message 26 of 36
vince1327
in reply to: vince1327

Also, if i explode the original dwg previous to running my import command, it still loses all it's attributes. I'm not sure why?

Message 27 of 36
vince1327
in reply to: fieldguy

Hey fieldguy,

 

No luck with attsync, i'm still experimenting though, i will prevail!

Message 28 of 36
jeff
in reply to: vince1327

Your block definition(BlocktableRecord) contain the AttributeDefinition. When you create a BlockReference you need to add a AttributeReference for each AttributeDefinition.

 

When you explode the reference you are getting all the entites in the BlockDefinition including the AttributeDefinition and it showing the default value. Notice when you explode the entity then double on the AttributeDefinition how the Edit Attribute Definition dialog shows instead of 'Edit Attributes' or 'Enhanced Att ed'

 

Here are some examples of inserting a Drawing into another drawing then adding the AttributeReferences in F#, C#, & VB

 

http://www.theswamp.org/index.php?topic=37686.msg427843#msg427843

You can also find your answers @ TheSwamp
Message 29 of 36
vince1327
in reply to: vince1327

Hey Jeff,

 

Thanks a million, i'm going through some now and i'll see if i can make this work.

 

Cheers

Vince

Message 30 of 36
vince1327
in reply to: jeff

Hey Guys,

 

I've been going through the examples posted previously at the Swamp and have come to two problems. The first one is that in the sample code there are references to "CreateLayer", "InsertBlockReference" and "RadiansToDegrees" which don't exist. Are these placeholders for code or are these documented fuctions in the API i can't seem to find?

 

The other thing is that just by reading through the code, these examples don't seem to sync the attributes from the original blocks but rather provide the option to add new ones (multiple ones)...My existing blocks have attributes with values already and I have hundreds of them that i'd rather not have to redo manually. Hopefully i'm wrong or there's another way to accomplish what i'm trying to do.

 

Thanks again

Vince

Message 31 of 36
kdub_nz
in reply to: vince1327

>> The first one is that in the sample code there are references to "CreateLayer", "InsertBlockReference" and "RadiansToDegrees" which don't exist. Are these placeholders for code or are these documented fuctions in the API i can't seem to find? <<

 

Have a look at Reply #28

http://www.theswamp.org/index.php?topic=37686.msg427833#msg427833

 

OR

make the .NET forum current

and do a search for the keyword you want

 

Regards

 

//

Everything will work just as you expect it to, unless your expectations are incorrect.

class keyThumper<T> : Lazy<T>;      another  Swamper

Message 32 of 36
vince1327
in reply to: kdub_nz

When i try to put the code together from reply 28, i get the errors i posted above. When i try the compiled dll that was attached to the post and run BI_20, i get an eFilerError which halts everything. It's making me crazy that what i'm trying to do should be so simple yet is so annoyingly difficult. I've also gone through the .NET forums with no luck on this. I'll keep tacking at it and post any progress.

 

Cheers

Vince

Message 33 of 36
jeff
in reply to: vince1327

Maybe try one thing at a time.

 

1. Can you manually or through the UI insert a block into a drawing?(I guess you are inserting a drawing as block vs a block from another drawing)

2. Can you code just the part to insert another blockreference with attributes?

You can also find your answers @ TheSwamp
Message 34 of 36
vince1327
in reply to: jeff

Hey Jeff,

 

1.) I can insert the block with no problems manually by going to "Insert"-->"Block" from the AutoCAD 2012 GUI.

2.) I'm not sure what you mean here....i need it to be able to insert the block reference with the original attributes and then do that "x' times over. I've tried pre-exploding/bursting the original block in the original dwg but to no avail.

Message 35 of 36
hgasty1001
in reply to: vince1327

Try this:

 

Private Sub InsertAttibuteInBlockRef(ByVal blkRef As BlockReference, ByVal attributeTag As String, ByVal attributeText As String, ByVal tr As Transaction)
        Dim btr As BlockTableRecord = DirectCast(tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
        For Each attId As ObjectId In btr
            Dim ent As Entity = DirectCast(tr.GetObject(attId, OpenMode.ForRead), Entity)
            If TypeOf ent Is AttributeDefinition Then
                Dim attDef As AttributeDefinition = DirectCast(ent, AttributeDefinition)
                Dim attRef As New AttributeReference()
                attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform)
                If attRef.Tag = attributeTag Then
                    attRef.TextString = attributeText
                    Dim id As ObjectId = blkRef.AttributeCollection.AppendAttribute(attRef)
                    tr.AddNewlyCreatedDBObject(attRef, True)
                    Exit For
                End If
            End If
        Next
    End Sub
 
Public Sub BlkInsert(ByVal basePath As String, ByVal blkName As String, ByVal px As Point3d, ByVal theta As Double, ByVal sx As Double, ByVal Layer As String, ByVal side As String, ByVal AttValList As ArrayList, ByVal AttTagList As ArrayList)
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database

        acCurDb = HostApplicationServices.WorkingDatabase()

        Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
            Dim acBlkTbl As BlockTable
            acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)

            If acBlkTbl.Has(blkName) Then
                Dim blkObjId = acBlkTbl(blkName)
                Dim acBlkTblRec As BlockTableRecord
                acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                Dim blkRef As BlockReference = New BlockReference(px, blkObjId)

                blkRef.Rotation = theta
                blkRef.ScaleFactors = New Scale3d(sx, sx, 1)
                blkRef.Layer = Layer

                acBlkTblRec.AppendEntity(blkRef)
                acTrans.AddNewlyCreatedDBObject(blkRef, True)


                Dim dPropsCollection As DynamicBlockReferencePropertyCollection
                dPropsCollection = blkRef.DynamicBlockReferencePropertyCollection

                For Each dprop As DynamicBlockReferenceProperty In dPropsCollection
                    If dprop.PropertyName = "Visibility1" Then
                        dprop.Value = side
                    End If
                Next

                Try
                    Dim i As Integer = 0
                    For Each tag As String In AttTagList
                        InsertAttibuteInBlockRef(blkRef, tag, AttValList(i).ToString, acTrans)
                        i = i + 1
                    Next
                    acBlkTblRec.UpdateAnonymousBlocks()
                    blkRef.RecordGraphicsModified(True)
                Catch ex As Exception
                    MsgBox(ex.Message)
                End Try
            Else
                Dim blkFile As String = basePath + "\\" + blkName + ".dwg"
                Dim blkObjId As ObjectId
                Dim dbDwg As New Database(False, True)
                dbDwg.ReadDwgFile(blkFile, IO.FileShare.Read, True, "")
                blkObjId = acCurDb.Insert(blkName, dbDwg, True)
                dbDwg.Dispose()
                Dim acBlkTblRec As BlockTableRecord
                acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                Dim blkRef As BlockReference = New BlockReference(px, blkObjId)

                blkRef.Rotation = theta
                blkRef.ScaleFactors = New Scale3d(sx, sx, 1)
                blkRef.Layer = Layer

                acBlkTblRec.AppendEntity(blkRef)
                acTrans.AddNewlyCreatedDBObject(blkRef, True)


                Dim dPropsCollection As DynamicBlockReferencePropertyCollection
                dPropsCollection = blkRef.DynamicBlockReferencePropertyCollection

                For Each dprop As DynamicBlockReferenceProperty In dPropsCollection
                    If dprop.PropertyName = "Visibility1" Then
                        dprop.Value = side
                    End If
                Next
                Dim i As Integer = 0
                For Each tag As String In AttTagList
                    InsertAttibuteInBlockRef(blkRef, tag, AttValList(i).ToString, acTrans)
                    i = i + 1
                Next
                acBlkTblRec.UpdateAnonymousBlocks()
                blkRef.RecordGraphicsModified(True)
            End If
            acTrans.Commit()
        End Using
    End Sub
<CommandMethod("MBLKTEST")> _
    Public Sub Blktest()
        Dim TagList As New ArrayList
        Dim ValList As New ArrayList
        Dim side As String = "Top"

        TagList.Add("TAG1")
        TagList.Add("TAG2")
        

        ValList.Add("VAL1")
        ValList.Add("VAL2")
        

        Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database

        Dim pr As PromptPointResult = ed.GetPoint("Pick a point:")

        If pr.Status = PromptStatus.OK Then
            Dim i As Integer = 0
            Dim n As Integer = 10
            Dim basePath As String = "C:\\MyBasePath"
            Dim px As Point3d = pr.Value

            For i = 0 To n
                AlInsert(basePath, "MyBlockName", px, 0, 1, "0", side, ValList, TagList)
                px = Polar(px, 3500, 0)
            Next

        End If


    End Sub
Private Function Polar(ByVal bpoint As Point3d, ByVal r As Double, ByVal theta As Double) As Point3d
        Dim px As New Point3d(bpoint.X + r * Math.Cos(theta), bpoint.Y + r * Math.Sin(theta), bpoint.Z)
        Return px
    End Function

 

You will need a dynamic block with 2 visibility states (the "side" parameter) and 2 attributes , or you can just get rid off that part of the code, and use a simple block with attributes.

 

Gaston Nunez

 

 

 

Message 36 of 36
vince1327
in reply to: hgasty1001

Thanks gasty1001,

 

I actually got it running with help from jeff, sorry for the delayed response. Thanks for the help though!

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