.中的NET Update块属性
我正在开发一个应用程序,使用用户输入和access数据库从模板自动生成一组图形。作为其中的一部分,我有一些代码被调用来更新单个块属性。它适用于模型空间中的块!
我的问题是纸张空间。它没有更新现有属性,而是添加了一个同名的新属性。
如何访问Paperspace块属性?!?用于此操作的代码如下所示。
Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
Dim acBlkTable As BlockTable
Dim acBlkDef As BlockTableRecord
Dim acCurLyr As ObjectId
Dim acAttRef As DatabaseServices.AttributeReference = Nothing
Dim attFound As Boolean = False
Try
acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)
Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
acCurLyr = acdb.Clayer
If acLyrTbl.Has("0") Then
acdb.Clayer = acLyrTbl("0")
End If
For Each acEntId In acBlkDef
Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
If Not IsNothing(acEnt) Then
If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then
Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)
If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
acAttRef = New AttributeReference
acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)
If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
attFound = True
Exit For
End If
End If
End If
End If
Next
DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)
'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
If Not attFound Then
acAttRef.Tag = attTag
acAttRef.Justify = AttachmentPoint.MiddleCenter
acTrans.AddNewlyCreatedDBObject(acAttRef, True)
acAttRef.UpgradeOpen()
End If
acAttRef.TextString = textValue
acAttRef.DowngradeOpen()
acdb.Clayer = acCurLyr
Catch ex As Exception
MsgBox("Update Block Attribute: " & ex.Message)
End Try
End Sub
欢迎来到CADTutor。
您还没有发布完整的代码或示例图,因此我(或其他人)很难准确指出您面临的问题。
也就是说,这可能会有所帮助:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace BlackBox.AutoCAD.Samples
{
class FOO
{
private DocumentCollection acDocs = acApp.DocumentManager;
void UpdateBlockAttributes(string blockName, string tagString, string textString)
{
Document doc = acDocs.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
tagString = tagString.ToUpper();
// set clayer to "0" layer
acApp.SetSystemVariable("clayer", "0");
using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
{
// get the blocktable
BlockTable bt =
(BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
// instead of iterating the entire blocktable, check to see if
// the target block exists within this database's blocktable
if (!bt.Has(blockName))
{
// if not, then notify user, and exit
// uncomment the notification, if you feel it useful - I tend
// to not call writemessage() within non-commandmethod methods
//ed.WriteMessage("\nerror; Block \"{0}\" does not exist ", blockName);
return;
}
// otherwise, open the blocktablerecord
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(bt, OpenMode.ForRead);
// and instead, simply iterate all inserts of the target blocktablerecord
foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
{
BlockReference br =
(BlockReference)tr.GetObject(id, OpenMode.ForRead);
// <-- check for locked layer here?
// check for attributes
foreach (ObjectId attId in br.AttributeCollection)
{
AttributeReference ar =
tr.GetObject(attId, OpenMode.ForRead) as AttributeReference;
if (ar != null && ar.Tag.ToUpper() == tagString)
{
ar.UpgradeOpen();
ar.TextString = textString;
ar.DowngradeOpen();
}
}
}
tr.Commit();
}
}
}
}
然后我调用sub来更新属性。(描述(CONT)是属性。)
acBlkRef = InsertBlockReference("TBClean", False, New Point3d(-0.5, 0.5, 0), True, "TITLE", Colors.Color.FromColorIndex(Colors.ColorMethod.ByAci, 0)) 'black
下面是函数和子函数的代码
UpdateBlockAttribute(acBlkRef, "DESCRIPTION(CONT)", strDesc)
Private Function InsertBlockReference(blockName As String, modelSpace As Boolean, insPt As Point3d, updateExisting As Boolean, Optional layerName As String = "", Optional layerColor As Colors.Color = Nothing) As BlockReference
Dim acBlkTable As BlockTable
Dim acLyrTbl As LayerTable
Dim acCurLyrID As ObjectId
Dim acBlkRef As BlockReference = Nothing
Dim acSpaceID As ObjectId
Dim acBlkTableRecord As BlockTableRecord
Dim acBlkTableRecordID As ObjectId
Dim acNewLyr As New LayerTableRecord
Try
acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
If IsNothing(acBlkTable) Then
'InsertBlockReference = Nothing
Return Nothing
End If
'store current layer to make it current again after function
acLyrTbl = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
acCurLyrID = acdb.Clayer
'if a layer is specified, set it to the current layer
If layerName <> "" Then
If acLyrTbl.Has(layerName) Then
acdb.Clayer = acLyrTbl(layerName)
Else
acNewLyr.Name = layerName
acNewLyr.Color = layerColor
acLyrTbl.UpgradeOpen()
acLyrTbl.Add(acNewLyr)
acLyrTbl.DowngradeOpen()
acTrans.AddNewlyCreatedDBObject(acNewLyr, True)
acdb.Clayer = acLyrTbl(layerName)
End If
End If
'check to see if the block is already in the CAD file
If acBlkTable.Has(blockName) And updateExisting Then
'get the BlockReference for the block
acBlkTableRecord = DirectCast(acTrans.GetObject(acBlkTable.Item(blockName), OpenMode.ForRead), BlockTableRecord)
Dim acObjIdColl As ObjectIdCollection = acBlkTableRecord.GetBlockReferenceIds(True, True)
Dim acEntId As ObjectId
For Each acEntId In acObjIdColl
'acBlkRef = acEntId.GetObject(OpenMode.ForRead)
acBlkRef = TryCast(acEntId.GetObject(OpenMode.ForWrite), BlockReference)
Next
Else
'if the block is NOT in the CAD file, insert it from the dwg file
If IO.File.Exists(Me.txtCADBlocksPath.Text & "\" & blockName & ".dwg") Then
Dim acBlkSourceDb As Database
acBlkSourceDb = New Database(False, True)
acBlkSourceDb.ReadDwgFile(Me.txtCADBlocksPath.Text & "\" & blockName & ".dwg", FileOpenMode.OpenForReadAndAllShare, True, Nothing)
acBlkTableRecordID = acdb.Insert(blockName, acBlkSourceDb, True)
'insert the new block
acBlkRef = New BlockReference(insPt, acBlkTableRecordID)
'select the correct block table record to insert the new block into... ModelSpace or PaperSpace
If modelSpace = True Then
acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
Else
acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
End If
acBlkTableRecord = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForWrite), BlockTableRecord)
acBlkTableRecord.AppendEntity(acBlkRef)
acTrans.AddNewlyCreatedDBObject(acBlkRef, True)
Else
MsgBox("InsertBlock: Block """ & blockName & """ DWG not found")
Return Nothing
End If
End If
Catch ex As Exception
MsgBox("InsertBlock: " & ex.Message)
Finally
acdb.Clayer = acCurLyrID
End Try
Return acBlkRef
End Function
我希望这一切都有意义。
我必须在图纸上清除一些机密数据后才能发布,但如果你仍然需要的话,我可以这样做。 感谢您的澄清。
所以请原谅我的提问,因为我忽略了一定有原因,但是如果您以编程方式插入BlockReference,然后修改所述BlockReference的属性,为什么不手动保存更正的块的副本并插入/覆盖BlockTableRecord呢?
您甚至可以首先迭代我上面介绍的现有插入,根据需要存储值和属性,然后根据需要在结果块中填充所述值。
干杯 考虑:
Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
Dim acBlkTable As BlockTable
Dim acBlkDef As BlockTableRecord
Dim acCurLyr As ObjectId
Dim acAttRef As DatabaseServices.AttributeReference = Nothing
Dim attFound As Boolean = False
Try
acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
'acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)
Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
acCurLyr = acdb.Clayer
If acLyrTbl.Has("0") Then
acdb.Clayer = acLyrTbl("0")
End If
If acBlkTable.Has(acBlkRef.Name) Then
acBlkDef = acTrans.GetObject(acBlkRef.Id, OpenMode.ForRead)
End If
For Each acEntId In acBlkDef
Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
If Not IsNothing(acEnt) Then
If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then
Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)
If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
acAttRef = New AttributeReference
acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)
If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
attFound = True
Exit For
End If
End If
End If
End If
Next
DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)
'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
If Not attFound Then
acAttRef.Tag = attTag
acAttRef.Justify = AttachmentPoint.MiddleCenter
acTrans.AddNewlyCreatedDBObject(acAttRef, True)
acAttRef.UpgradeOpen()
End If
acAttRef.TextString = textValue
acAttRef.DowngradeOpen()
acBlkDef.SynchronizeAttributes()
acdb.Clayer = acCurLyr
Catch ex As Exception
MsgBox("Update Block Attribute: " & ex.Message)
End Try
End Sub 对不起,我没有回应。我有一段时间不在办公室了。
这个程序将被我们的起草者使用。这个想法是,它将是相当动态的。他们将能够将其块(使用适当的块名和属性名)放置在文件夹中,并将程序指向该位置。这将使他们能够使砌块外观与客户相符。程序将根据他们的选择为他们更新该块。查找块中存在的属性并在不存在时添加,将确保块中存在所有必需字段。
我们正试图引导起草领导朝着更稳健的方向发展,但目前这正是他们想要的。
您发送的最后一段代码能否解决纸张空间属性问题?
据我所知,我的问题不是打开或读取paperspace块,而是定位属性。
由于某种原因,当它比较时。tag to attTag它永远不会找到匹配项,即使它确实存在。
这只是在纸上。这就是我不明白的。
问题是否可能是我没有将其指向特定布局?
现在我回到办公室,我将仔细查看您提供的代码。
再次感谢您的投入。
别担心;最近我自己工作了太多的时间,而且似乎不会很快停止。
在任何情况下,发布一个示例图形可能是明智的,您可以用这种方式复制这个问题,这样我们就不必从头开始设置示例数据集和代码等,以便尝试和帮助?
干杯 terminal\u template\u已擦除。图纸
附着了模板dwg的擦除版本。在这种情况下,我正在更新paperspace中TBCLEAN标题栏上的DESCRIPTION(CONT)属性。
就像我说的,它找不到现有的属性,所以它会创建一个同名的新属性并更新该值。
经过进一步研究,我想知道这个问题是否源于没有选择布局选项卡。我开始尝试把它融入到组合中,但我还没有成功。请参阅下面我更新的子代码。但我觉得我错过了一步。
我得到一个响应,它没有设置为对象的实例。(适用于所有属性)
var btr = <BlockTable>["<BlockName>"].GetObject(<OpenMode>);
感谢您如此快速地发布图纸,并提供更多信息。
我会尽快找到答案的——我现在正在完成其他人的项目(为什么你要等到提交文件结束,做垂直剖面,卫生运行,修改风暴(如果有的话),并设计供水和供水干管的垂直方向,我无能为力,但这就是我被要求做的,dah dah dahhh.Grrr)。
此外,您计划支持什么版本?
干杯 AutoCad 2013和。net framework 4 我觉得我离得很近,但仍然缺少一些东西。
我已经对因子布局进行了修改。
我已经能够确认它现在正在迭代正确的块,并且确实拉入了该属性,但是,它仍然无法识别标记是否等于传入的attTag。我附上了我的输出问题的快速屏幕截图。如果查看属性名称,可以看到它创建了一个具有相同名称的新属性。
Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
Dim acBlkTable As BlockTable = Nothing
Dim acBlkDef As BlockTableRecord
Dim acCurLyr As ObjectId
Dim acAttRef As DatabaseServices.AttributeReference = Nothing
Dim attFound As Boolean = False
Dim acSpaceID As ObjectId
Try
acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
If modelSpace = False Then
acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
Else
acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
End If
acBlkDef = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForRead), BlockTableRecord)
'acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)
Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
acCurLyr = acdb.Clayer
If acLyrTbl.Has("0") Then
acdb.Clayer = acLyrTbl("0")
End If
For Each acEntId In acBlkDef
Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
If Not IsNothing(acEnt) Then
If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then
Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)
If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
acAttRef = New AttributeReference
acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)
If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
attFound = True
Exit For
End If
End If
End If
End If
Next
DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)
'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
If Not attFound Then
acAttRef.Tag = attTag
acAttRef.Justify = AttachmentPoint.MiddleCenter
acTrans.AddNewlyCreatedDBObject(acAttRef, True)
acAttRef.UpgradeOpen()
End If
acAttRef.TextString = textValue
acAttRef.DowngradeOpen()
acBlkDef.SynchronizeAttributes()
acdb.Clayer = acCurLyr
Catch ex As Exception
MsgBox("Update Block Attribute: " & ex.Message & acAttRef.BlockName.ToString & " - " & acAttRef.Tag.ToString)
End Try
End Sub
纸张空间块。docx文件
页:
[1]
2