乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 139|回复: 13

[编程交流] .中的NET Update块属性

[复制链接]

1

主题

6

帖子

5

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-6 19:25:01 | 显示全部楼层 |阅读模式
我正在开发一个应用程序,使用用户输入和access数据库从模板自动生成一组图形。
 
作为其中的一部分,我有一些代码被调用来更新单个块属性。它适用于模型空间中的块!
 
我的问题是纸张空间。它没有更新现有属性,而是添加了一个同名的新属性。
 
如何访问Paperspace块属性?!?用于此操作的代码如下所示。
 
  1. Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
  2.        Dim acBlkTable As BlockTable
  3.        Dim acBlkDef As BlockTableRecord
  4.        Dim acCurLyr As ObjectId
  5.        Dim acAttRef As DatabaseServices.AttributeReference = Nothing
  6.        Dim attFound As Boolean = False
  7.        Try
  8.            acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
  9.            acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)
  10.            Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
  11.            acCurLyr = acdb.Clayer
  12.            If acLyrTbl.Has("0") Then
  13.                acdb.Clayer = acLyrTbl("0")
  14.            End If
  15.            For Each acEntId In acBlkDef
  16.                Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
  17.                If Not IsNothing(acEnt) Then
  18.                    If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then
  19.                        Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)
  20.                        If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
  21.                            acAttRef = New AttributeReference
  22.                            acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)
  23.                            If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
  24.                                attFound = True
  25.                                Exit For
  26.                            End If
  27.                        End If
  28.                    End If
  29.                End If
  30.            Next
  31.            DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)
  32.            'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
  33.            If Not attFound Then
  34.                acAttRef.Tag = attTag
  35.                acAttRef.Justify = AttachmentPoint.MiddleCenter
  36.                acTrans.AddNewlyCreatedDBObject(acAttRef, True)
  37.                acAttRef.UpgradeOpen()
  38.            End If
  39.            acAttRef.TextString = textValue
  40.            acAttRef.DowngradeOpen()
  41.            acdb.Clayer = acCurLyr
  42.        Catch ex As Exception
  43.            MsgBox("Update Block Attribute: " & ex.Message)
  44.        End Try
  45.    End Sub
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2022-7-6 19:31:15 | 显示全部楼层
 
欢迎来到CADTutor。
 
您还没有发布完整的代码或示例图,因此我(或其他人)很难准确指出您面临的问题。
 
也就是说,这可能会有所帮助:
 
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  5. namespace BlackBox.AutoCAD.Samples
  6. {
  7.    class FOO
  8.    {
  9.        private DocumentCollection acDocs = acApp.DocumentManager;
  10.        void UpdateBlockAttributes(string blockName, string tagString, string textString)
  11.        {
  12.            Document doc = acDocs.MdiActiveDocument;
  13.            Database db = doc.Database;
  14.            Editor ed = doc.Editor;
  15.            tagString = tagString.ToUpper();
  16.            // set clayer to "0" layer
  17.            acApp.SetSystemVariable("clayer", "0");
  18.            
  19.            using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
  20.            {
  21.                // get the blocktable
  22.                BlockTable bt =
  23.                    (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  24.                // instead of iterating the entire blocktable, check to see if
  25.                // the target block exists within this database's blocktable
  26.                if (!bt.Has(blockName))
  27.                {
  28.                    // if not, then notify user, and exit
  29.                    // uncomment the notification, if you feel it useful - I tend
  30.                    // to not call writemessage() within non-commandmethod methods
  31.                    //ed.WriteMessage("\nerror; Block "{0}" does not exist ", blockName);
  32.                    return;
  33.                }
  34.                // otherwise, open the blocktablerecord
  35.                BlockTableRecord btr =
  36.                    (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
  37.                
  38.                // and instead, simply iterate all inserts of the target blocktablerecord
  39.                foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
  40.                {
  41.                    BlockReference br =
  42.                        (BlockReference)tr.GetObject(id, OpenMode.ForRead);
  43.                    // <-- check for locked layer here?
  44.                    // check for attributes
  45.                    foreach (ObjectId attId in br.AttributeCollection)
  46.                    {
  47.                        AttributeReference ar =
  48.                            tr.GetObject(attId, OpenMode.ForRead) as AttributeReference;
  49.                        if (ar != null && ar.Tag.ToUpper() == tagString)
  50.                        {
  51.                            ar.UpgradeOpen();
  52.                            ar.TextString = textString;
  53.                            ar.DowngradeOpen();
  54.                        }
  55.                    }
  56.                }
  57.                tr.Commit();
  58.            }
  59.        }
  60.    }
  61. }

 
然后我调用sub来更新属性。(描述(CONT)是属性。)
  1. acBlkRef = InsertBlockReference("TBClean", False, New Point3d(-0.5, 0.5, 0), True, "TITLE", Colors.Color.FromColorIndex(Colors.ColorMethod.ByAci, 0)) 'black

 
下面是函数和子函数的代码
  1. UpdateBlockAttribute(acBlkRef, "DESCRIPTION(CONT)", strDesc)

 
  1. 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
  2.        Dim acBlkTable As BlockTable
  3.        Dim acLyrTbl As LayerTable
  4.        Dim acCurLyrID As ObjectId
  5.        Dim acBlkRef As BlockReference = Nothing
  6.        Dim acSpaceID As ObjectId
  7.        Dim acBlkTableRecord As BlockTableRecord
  8.        Dim acBlkTableRecordID As ObjectId
  9.        Dim acNewLyr As New LayerTableRecord
  10.        Try
  11.            acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
  12.            If IsNothing(acBlkTable) Then
  13.                'InsertBlockReference = Nothing
  14.                Return Nothing
  15.            End If
  16.            'store current layer to make it current again after function
  17.            acLyrTbl = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
  18.            acCurLyrID = acdb.Clayer
  19.            'if a layer is specified, set it to the current layer
  20.            If layerName <> "" Then
  21.                If acLyrTbl.Has(layerName) Then
  22.                    acdb.Clayer = acLyrTbl(layerName)
  23.                Else
  24.                    acNewLyr.Name = layerName
  25.                    acNewLyr.Color = layerColor
  26.                    acLyrTbl.UpgradeOpen()
  27.                    acLyrTbl.Add(acNewLyr)
  28.                    acLyrTbl.DowngradeOpen()
  29.                    acTrans.AddNewlyCreatedDBObject(acNewLyr, True)
  30.                    acdb.Clayer = acLyrTbl(layerName)
  31.                End If
  32.            End If
  33.            'check to see if the block is already in the CAD file
  34.            If acBlkTable.Has(blockName) And updateExisting Then
  35.                'get the BlockReference for the block
  36.                acBlkTableRecord = DirectCast(acTrans.GetObject(acBlkTable.Item(blockName), OpenMode.ForRead), BlockTableRecord)
  37.                Dim acObjIdColl As ObjectIdCollection = acBlkTableRecord.GetBlockReferenceIds(True, True)
  38.                Dim acEntId As ObjectId
  39.                For Each acEntId In acObjIdColl
  40.                    'acBlkRef = acEntId.GetObject(OpenMode.ForRead)
  41.                    acBlkRef = TryCast(acEntId.GetObject(OpenMode.ForWrite), BlockReference)
  42.                Next
  43.            Else
  44.                'if the block is NOT in the CAD file, insert it from the dwg file
  45.                If IO.File.Exists(Me.txtCADBlocksPath.Text & "" & blockName & ".dwg") Then
  46.                    Dim acBlkSourceDb As Database
  47.                    acBlkSourceDb = New Database(False, True)
  48.                    acBlkSourceDb.ReadDwgFile(Me.txtCADBlocksPath.Text & "" & blockName & ".dwg", FileOpenMode.OpenForReadAndAllShare, True, Nothing)
  49.                    acBlkTableRecordID = acdb.Insert(blockName, acBlkSourceDb, True)
  50.                    'insert the new block
  51.                    acBlkRef = New BlockReference(insPt, acBlkTableRecordID)
  52.                    'select the correct block table record to insert the new block into... ModelSpace or PaperSpace
  53.                    If modelSpace = True Then
  54.                        acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
  55.                    Else
  56.                        acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
  57.                    End If
  58.                    acBlkTableRecord = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForWrite), BlockTableRecord)
  59.                    acBlkTableRecord.AppendEntity(acBlkRef)
  60.                    acTrans.AddNewlyCreatedDBObject(acBlkRef, True)
  61.                Else
  62.                    MsgBox("InsertBlock: Block """ & blockName & """ DWG not found")
  63.                    Return Nothing
  64.                End If
  65.            End If
  66.        Catch ex As Exception
  67.            MsgBox("InsertBlock: " & ex.Message)
  68.        Finally
  69.            acdb.Clayer = acCurLyrID
  70.        End Try
  71.        Return acBlkRef
  72.    End Function

 
我希望这一切都有意义。
 
我必须在图纸上清除一些机密数据后才能发布,但如果你仍然需要的话,我可以这样做。
回复

使用道具 举报

106

主题

1万

帖子

101

银币

顶梁支柱

Rank: 50Rank: 50

铜币
1299
发表于 2022-7-6 19:37:15 | 显示全部楼层
感谢您的澄清。
 
所以请原谅我的提问,因为我忽略了一定有原因,但是如果您以编程方式插入BlockReference,然后修改所述BlockReference的属性,为什么不手动保存更正的块的副本并插入/覆盖BlockTableRecord呢?
 
您甚至可以首先迭代我上面介绍的现有插入,根据需要存储值和属性,然后根据需要在结果块中填充所述值。
 
干杯
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2022-7-6 19:40:47 | 显示全部楼层
考虑:
 
  1. Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
  2.        Dim acBlkTable As BlockTable
  3.        Dim acBlkDef As BlockTableRecord
  4.        Dim acCurLyr As ObjectId
  5.        Dim acAttRef As DatabaseServices.AttributeReference = Nothing
  6.        Dim attFound As Boolean = False
  7.        Try
  8.            acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
  9.            'acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)
  10.            Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
  11.            acCurLyr = acdb.Clayer
  12.            If acLyrTbl.Has("0") Then
  13.                acdb.Clayer = acLyrTbl("0")
  14.            End If
  15.            If acBlkTable.Has(acBlkRef.Name) Then
  16.                acBlkDef = acTrans.GetObject(acBlkRef.Id, OpenMode.ForRead)
  17.            End If
  18.            For Each acEntId In acBlkDef
  19.                Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
  20.                If Not IsNothing(acEnt) Then
  21.                    If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then
  22.                        Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)
  23.                        If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
  24.                            acAttRef = New AttributeReference
  25.                            acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)
  26.                            If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
  27.                                attFound = True
  28.                                Exit For
  29.                            End If
  30.                        End If
  31.                    End If
  32.                End If
  33.            Next
  34.            DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)
  35.            'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
  36.            If Not attFound Then
  37.                acAttRef.Tag = attTag
  38.                acAttRef.Justify = AttachmentPoint.MiddleCenter
  39.                acTrans.AddNewlyCreatedDBObject(acAttRef, True)
  40.                acAttRef.UpgradeOpen()
  41.            End If
  42.            acAttRef.TextString = textValue
  43.            acAttRef.DowngradeOpen()
  44.            acBlkDef.SynchronizeAttributes()
  45.            acdb.Clayer = acCurLyr
  46.        Catch ex As Exception
  47.            MsgBox("Update Block Attribute: " & ex.Message)
  48.        End Try
  49.    End Sub
回复

使用道具 举报

1

主题

6

帖子

5

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-6 19:43:51 | 显示全部楼层
对不起,我没有回应。我有一段时间不在办公室了。
 
这个程序将被我们的起草者使用。这个想法是,它将是相当动态的。他们将能够将其块(使用适当的块名和属性名)放置在文件夹中,并将程序指向该位置。这将使他们能够使砌块外观与客户相符。程序将根据他们的选择为他们更新该块。查找块中存在的属性并在不存在时添加,将确保块中存在所有必需字段。
 
我们正试图引导起草领导朝着更稳健的方向发展,但目前这正是他们想要的。
 
您发送的最后一段代码能否解决纸张空间属性问题?
 
据我所知,我的问题不是打开或读取paperspace块,而是定位属性。
由于某种原因,当它比较时。tag to attTag它永远不会找到匹配项,即使它确实存在。
这只是在纸上。这就是我不明白的。
问题是否可能是我没有将其指向特定布局?
 
现在我回到办公室,我将仔细查看您提供的代码。
 
再次感谢您的投入。
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2022-7-6 19:51:53 | 显示全部楼层
 
别担心;最近我自己工作了太多的时间,而且似乎不会很快停止。
 
在任何情况下,发布一个示例图形可能是明智的,您可以用这种方式复制这个问题,这样我们就不必从头开始设置示例数据集和代码等,以便尝试和帮助?
 
干杯
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2022-7-6 19:55:31 | 显示全部楼层
terminal\u template\u已擦除。图纸
 
附着了模板dwg的擦除版本。在这种情况下,我正在更新paperspace中TBCLEAN标题栏上的DESCRIPTION(CONT)属性。
 
就像我说的,它找不到现有的属性,所以它会创建一个同名的新属性并更新该值。
 
经过进一步研究,我想知道这个问题是否源于没有选择布局选项卡。我开始尝试把它融入到组合中,但我还没有成功。请参阅下面我更新的子代码。但我觉得我错过了一步。
 
我得到一个响应,它没有设置为对象的实例。(适用于所有属性)
 
  1. var btr = <BlockTable>["<BlockName>"].GetObject(<OpenMode>);
回复

使用道具 举报

1

主题

6

帖子

5

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-6 19:59:22 | 显示全部楼层
感谢您如此快速地发布图纸,并提供更多信息。
 
我会尽快找到答案的——我现在正在完成其他人的项目(为什么你要等到提交文件结束,做垂直剖面,卫生运行,修改风暴(如果有的话),并设计供水和供水干管的垂直方向,我无能为力,但这就是我被要求做的,dah dah dahhh.Grrr)。
 
 
 
此外,您计划支持什么版本?
 
干杯
回复

使用道具 举报

44

主题

3166

帖子

2803

银币

中流砥柱

Rank: 25

铜币
557
发表于 2022-7-6 20:04:49 | 显示全部楼层
AutoCad 2013和。net framework 4
回复

使用道具 举报

1

主题

6

帖子

5

银币

初来乍到

Rank: 1

铜币
5
发表于 2022-7-6 20:08:58 | 显示全部楼层
我觉得我离得很近,但仍然缺少一些东西。
我已经对因子布局进行了修改。
我已经能够确认它现在正在迭代正确的块,并且确实拉入了该属性,但是,它仍然无法识别标记是否等于传入的attTag。我附上了我的输出问题的快速屏幕截图。如果查看属性名称,可以看到它创建了一个具有相同名称的新属性。
 
  1. Private Sub UpdateBlockAttribute(acBlkRef As BlockReference, attTag As String, textValue As String, Optional modelSpace As Boolean = True)
  2.        Dim acBlkTable As BlockTable = Nothing
  3.        Dim acBlkDef As BlockTableRecord
  4.        Dim acCurLyr As ObjectId
  5.        Dim acAttRef As DatabaseServices.AttributeReference = Nothing
  6.        Dim attFound As Boolean = False
  7.        Dim acSpaceID As ObjectId
  8.        Try
  9.            acBlkTable = acTrans.GetObject(acdb.BlockTableId, OpenMode.ForRead)
  10.            If modelSpace = False Then
  11.                acSpaceID = acBlkTable(BlockTableRecord.PaperSpace)
  12.            Else
  13.                acSpaceID = acBlkTable(BlockTableRecord.ModelSpace)
  14.            End If
  15.            acBlkDef = DirectCast(acTrans.GetObject(acSpaceID, OpenMode.ForRead), BlockTableRecord)
  16.            'acBlkDef = DirectCast(acBlkTable(acBlkRef.Name).GetObject(OpenMode.ForRead), BlockTableRecord)
  17.            Dim acLyrTbl As LayerTable = acTrans.GetObject(acdb.LayerTableId, OpenMode.ForRead)
  18.            acCurLyr = acdb.Clayer
  19.            If acLyrTbl.Has("0") Then
  20.                acdb.Clayer = acLyrTbl("0")
  21.            End If
  22.            For Each acEntId In acBlkDef
  23.                Dim acEnt As Entity = acTrans.GetObject(acEntId, OpenMode.ForRead)
  24.                If Not IsNothing(acEnt) Then
  25.                    If acEnt.GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.AttributeDefinition" Then
  26.                        Dim acAttDef As AttributeDefinition = DirectCast(acEnt, AttributeDefinition)
  27.                        If Not IsNothing(acAttDef) And Not acAttDef.Constant Then
  28.                            acAttRef = New AttributeReference
  29.                            acAttRef.SetAttributeFromBlock(acAttDef, DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).BlockTransform)
  30.                            If acAttDef.Tag.ToString = attTag Or acAttRef.Tag.ToString = attTag Then
  31.                                attFound = True
  32.                                Exit For
  33.                            End If
  34.                        End If
  35.                    End If
  36.                End If
  37.            Next
  38.            DirectCast(acTrans.GetObject(acBlkRef.ObjectId, OpenMode.ForRead), BlockReference).AttributeCollection.AppendAttribute(acAttRef)
  39.            'IF THE ATTRIBUTE DOES NOT EXIST, ADD A NEW ONE...
  40.            If Not attFound Then
  41.                acAttRef.Tag = attTag
  42.                acAttRef.Justify = AttachmentPoint.MiddleCenter
  43.                acTrans.AddNewlyCreatedDBObject(acAttRef, True)
  44.                acAttRef.UpgradeOpen()
  45.            End If
  46.            acAttRef.TextString = textValue
  47.            acAttRef.DowngradeOpen()
  48.            acBlkDef.SynchronizeAttributes()
  49.            acdb.Clayer = acCurLyr
  50.        Catch ex As Exception
  51.            MsgBox("Update Block Attribute: " & ex.Message & acAttRef.BlockName.ToString & " - " & acAttRef.Tag.ToString)
  52.        End Try
  53.    End Sub

 
纸张空间块。docx文件
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-3-4 14:47 , Processed in 0.817247 second(s), 72 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表