Author Topic: Updating fields in Attributes  (Read 3695 times)

0 Members and 1 Guest are viewing this topic.

Jeff H

  • Needs a day job
  • Posts: 6150
Updating fields in Attributes
« on: July 08, 2011, 05:32:45 AM »
After seeing this Here and I know I need this in future, here is what I came up with at first.

This was first attempt at getting this to work and before any cleanup or refactoring.
Will post update later.
I thought I would  see what you guys come up with, on how much could be abstracted out to make easier to code with.

Basically get ExtentionDictionary from AttributeReference and use SetFieldCode

Needed for code to work
1. Block Named "C"
2. 1 Attribute that is a field and set
    a. Field Name: BlockPlaceHolder
    b. BlockRefrence Property Name: Position

I was having a problem at first and could not get it to work because
GetFieldCode() and looking at it with MgdDbg do not include "%<.......>%"
Manually add them are use GetFieldCode(FieldCodeFlags.AddMarkers)

Did in VB.Net---------(Please do not hate me)
Code: [Select]
    <CommandMethod("InsertBlockWithFieldAtts")> _
        Public Sub InsertBlockWithFieldAtts()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Using trx As Transaction = db.TransactionManager.StartTransaction()
                Dim bt As BlockTable = trx.GetObject(db.BlockTableId, OpenMode.ForRead)
                Dim modelBtr As BlockTableRecord = trx.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                Dim blockBtr As BlockTableRecord = trx.GetObject(bt("C"), OpenMode.ForRead)
                Dim insertPoint As Point3d = ed.GetPoint("Select Insertion Point").Value
                Dim bref As New BlockReference(insertPoint, blockBtr.ObjectId)
                modelBtr.AppendEntity(bref)
                trx.AddNewlyCreatedDBObject(bref, True)

                For Each id As ObjectId In blockBtr
                    If id.ObjectClass.Name = "AcDbAttributeDefinition" Then
                        Dim attDef As AttributeDefinition = trx.GetObject(id, OpenMode.ForRead)
                        Dim attref As New AttributeReference()
                        attref.SetAttributeFromBlock(attDef, bref.BlockTransform)

                        bref.AttributeCollection.AppendAttribute(attref)
                        trx.AddNewlyCreatedDBObject(attref, True)

                        If attDef.Constant Then
                            Continue For
                        End If

                        Dim extDic As DBDictionary = trx.GetObject(attref.ExtensionDictionary, OpenMode.ForRead)
                        Dim fieldDic As DBDictionary = trx.GetObject(extDic.GetAt("ACAD_FIELD"), OpenMode.ForRead)
                        Dim fld As Field = trx.GetObject(fieldDic.GetAt("TEXT"), OpenMode.ForWrite)

                        Dim strId As String = bref.ObjectId.OldIdPtr.ToString()
                        Dim updteStr As String = "%<\_ObjId " & strId & ">%"
                        Dim fieldCode As String = fld.GetFieldCode(FieldCodeFlags.AddMarkers)
                        Dim newFieldCode As String = fieldCode.Replace("?BlockRefId", updteStr)
                        fld.SetFieldCode(newFieldCode)

                    End If
                Next
                trx.Commit()
            End Using
            ed.Regen()
        End Sub


C# used online converter Link and did not do well--many errors.
Updated it to work.
Code: [Select]
[CommandMethod("InsertBlockWithFieldAtts")]
public void InsertBlockWithFieldAtts()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

using (Transaction trx = db.TransactionManager.StartTransaction()) {
BlockTable bt = trx.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord modelBtr = trx.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite);
BlockTableRecord blockBtr = trx.GetObject(bt("C"), OpenMode.ForRead);
Point3d insertPoint = ed.GetPoint("Select Insertion Point").Value;
BlockReference bref = new BlockReference(insertPoint, blockBtr.ObjectId);
modelBtr.AppendEntity(bref);
trx.AddNewlyCreatedDBObject(bref, true);

foreach (ObjectId id in blockBtr) {
if (id.ObjectClass.Name == "AcDbAttributeDefinition") {
AttributeDefinition attDef = trx.GetObject(id, OpenMode.ForRead);
AttributeReference attref = new AttributeReference();
attref.SetAttributeFromBlock(attDef, bref.BlockTransform);

bref.AttributeCollection.AppendAttribute(attref);
trx.AddNewlyCreatedDBObject(attref, true);

if (attDef.Constant) {
continue;
}

DBDictionary extDic = trx.GetObject(attref.ExtensionDictionary, OpenMode.ForRead);
DBDictionary fieldDic = trx.GetObject(extDic.GetAt("ACAD_FIELD"), OpenMode.ForRead);
Field fld = trx.GetObject(fieldDic.GetAt("TEXT"), OpenMode.ForWrite);

string strId = bref.ObjectId.OldIdPtr.ToString();
string updteStr = "%<\\_ObjId " + strId + ">%";
string fieldCode = fld.GetFieldCode(FieldCodeFlags.AddMarkers);
string newFieldCode = fieldCode.Replace("?BlockRefId", updteStr);
fld.SetFieldCode(newFieldCode);

}
}
trx.Commit();
}
ed.Regen();
}

Attached drawing with Block if you want to test with

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Updating fields in Attributes
« Reply #1 on: July 08, 2011, 11:12:50 AM »
In Arx, to clone a field, you can just use the new fields constructor I.e

Code: [Select]
AcDbField *pNewField = new AcDbField(pField->getFieldCode(AcDbField::kAddMarkers),pField->isTextField());
maybe .net is the same?

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Updating fields in Attributes
« Reply #2 on: July 08, 2011, 11:57:32 AM »
Not sure?

I added this real quick to test and inserts Mtxt, but shows the Tag Value and defaulted back to
%<\AcObjProp.16.2 Object(?BlockRefId,1).InsertionPoint \f "%lu6">%
instead of
%<\AcObjProp.16.2 Object(%<\_ObjId 2129683176>%,1).InsertionPoint \f "%lu6">%

Code: [Select]
                        Field mtxtfield = new Field(fld.GetFieldCode(FieldCodeFlags.AddMarkers), fld.IsTextField);
                        MText mtxt = new MText();
                        mtxt.SetField(mtxtfield);
                        mtxt.Location = Point3d.Origin;
                        modelBtr.AppendEntity(mtxt);
                        trx.AddNewlyCreatedDBObject(mtxt, true);


Copies the field but the ObjectId does not get updated

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Updating fields in Attributes
« Reply #3 on: July 08, 2011, 02:29:10 PM »
As for refactoring will be easier than I thought
Going by results from limited testing for fields in attribute definition and did not do any SSM fields
Other fields update automatically, so far it is just fields that pertain to block reference, if you use objects in blockdefinition they update automatically

airportman

  • Newt
  • Posts: 37
  • i customize when required
Re: Updating fields in Attributes
« Reply #4 on: November 23, 2012, 12:47:33 PM »
Jeff:

can you compile it into a working dll for download?
Perception is a state of mind  -/ Twitter = @hochanz -/ Intel i7 - 3.07GHz -/ 12GB Ram -/ Nvidia Quadro FX 1800

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Updating fields in Attributes
« Reply #5 on: November 26, 2012, 11:15:00 AM »
Jeff:

can you compile it into a working dll for download?
Will throw something together later today and post.