按顺序匹配:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using System;
using System.Collections.Generic;
[assembly: CommandClass(typeof(BlockWithAttributeReplace.Commands))]
namespace BlockWithAttributeReplace
{
public class Commands
{
private Editor _ed;
[CommandMethod("ReplaceBlockWithAttributes")]
public void ReplaceBlockWithAttributes()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
_ed = doc.Editor;
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
string oldBlockName = "旧块";
string newBlockName = "新块";
int replacedCount = 0;
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
if (!bt.Has(newBlockName))
{
_ed.WriteMessage($"\n错误:新块 '{newBlockName}' 不存在");
return;
}
// 遍历所有块表记录(包含模型和布局空间)
foreach (ObjectId btrId in bt)
{
BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;
if (btr.IsLayout || btr.Name == BlockTableRecord.ModelSpace)
{
ProcessBlockReferencesInSpace(tr, btr, oldBlockName, newBlockName, ref replacedCount);
}
}
tr.Commit();
_ed.WriteMessage($"\n完成替换 {replacedCount} 个块");
}
}
catch (Exception ex)
{
_ed.WriteMessage($"\n操作出错: {ex.Message}\n{ex.StackTrace}");
}
}
private void ProcessBlockReferencesInSpace(
Transaction tr,
BlockTableRecord spaceBtr,
string oldBlockName,
string newBlockName,
ref int replacedCount)
{
string spaceName = spaceBtr.IsLayout ? $"布局 '{spaceBtr.Name}'" : "模型空间";
// 收集所有需要替换的块参照ID
List<ObjectId> blockIdsToReplace = new List<ObjectId>();
foreach (ObjectId objId in spaceBtr)
{
if (objId.ObjectClass.Name == "AcDbBlockReference")
{
BlockReference br = tr.GetObject(objId, OpenMode.ForRead) as BlockReference;
if (br != null && br.BlockName.Equals(oldBlockName, StringComparison.OrdinalIgnoreCase))
{
blockIdsToReplace.Add(objId);
}
}
}
foreach (ObjectId brId in blockIdsToReplace)
{
BlockReference oldBr = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;
if (ReplaceBlockWithAttr(oldBr, tr, newBlockName, spaceName))
{
replacedCount++;
}
}
}
private bool ReplaceBlockWithAttr(BlockReference oldBr, Transaction tr, string newBlockName, string spaceName)
{
try
{
// 1. 提取旧块属性值(按顺序)
List<string> attrValues = ExtractAttributesByOrder(oldBr, tr);
// 2. 保存关键属性
Point3d insertPoint = oldBr.Position;
Scale3d scale = oldBr.ScaleFactors;
double rotation = oldBr.Rotation;
string layer = oldBr.Layer;
ObjectId spaceId = oldBr.BlockTableRecordId;
// 3. 删除旧块
oldBr.UpgradeOpen();
oldBr.Erase();
// 4. 创建新块参照
BlockTable bt = tr.GetObject(tr.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord newBtr = tr.GetObject(bt[newBlockName], OpenMode.ForRead) as BlockTableRecord;
BlockReference newBr = new BlockReference(insertPoint, newBtr.ObjectId)
{
ScaleFactors = scale,
Rotation = rotation,
Layer = layer
};
// 5. 添加到原始空间
BlockTableRecord currentSpace = tr.GetObject(spaceId, OpenMode.ForWrite) as BlockTableRecord;
ObjectId newBrId = currentSpace.AppendEntity(newBr);
tr.AddNewlyCreatedDBObject(newBr, true);
// 6. 设置属性(按顺序)
if (attrValues.Count > 0)
{
AssignAttributesByOrder(newBr, tr, attrValues);
}
_ed.WriteMessage($"\n{spaceName} 成功替换块: {insertPoint}");
return true;
}
catch (Exception ex)
{
_ed.WriteMessage($"\n{spaceName} 替换失败: {ex.Message}");
return false;
}
}
// 按顺序提取属性值(忽略标记,只记录字符串值)
private List<string> ExtractAttributesByOrder(BlockReference br, Transaction tr)
{
List<string> attrValues = new List<string>();
if (br.AttributeCollection.Count > 0)
{
foreach (ObjectId attrId in br.AttributeCollection)
{
// 只处理属性参照(AttributeReference)
if (attrId.ObjectClass.Name == "AcDbAttribute")
{
AttributeReference attrRef = tr.GetObject(attrId, OpenMode.ForRead) as AttributeReference;
if (attrRef != null)
{
attrValues.Add(attrRef.TextString);
}
}
}
}
return attrValues;
}
// 按顺序赋值属性值
private void AssignAttributesByOrder(BlockReference newBr, Transaction tr, List<string> attrValues)
{
newBr.UpgradeOpen();
int index = 0;
foreach (ObjectId attrId in newBr.AttributeCollection)
{
// 如果已经赋值完所有旧属性,则停止
if (index >= attrValues.Count)
break;
// 只处理属性参照(AttributeReference)
if (attrId.ObjectClass.Name == "AcDbAttribute")
{
AttributeReference newAttr = tr.GetObject(attrId, OpenMode.ForWrite) as AttributeReference;
if (newAttr != null)
{
newAttr.TextString = attrValues[index];
index++;
}
}
}
}
}
}
按tag
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using System;
using System.Collections.Generic;
[assembly: CommandClass(typeof(BlockWithAttributeReplace.Commands))]
namespace BlockWithAttributeReplace
{
public class Commands
{
private Editor _ed;
[CommandMethod("ReplaceBlockWithAttributes")]
public void ReplaceBlockWithAttributes()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
_ed = doc.Editor;
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
string oldBlockName = "旧块";
string newBlockName = "新块";
int replacedCount = 0;
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
if (!bt.Has(newBlockName))
{
_ed.WriteMessage($"\n错误:新块 '{newBlockName}' 不存在");
return;
}
// 遍历所有块表记录(包含模型和布局空间)
foreach (ObjectId btrId in bt)
{
BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;
if (btr.IsLayout || btr.Name == BlockTableRecord.ModelSpace)
{
ProcessBlockReferencesInSpace(tr, btr, oldBlockName, newBlockName, ref replacedCount);
}
}
tr.Commit();
_ed.WriteMessage($"\n完成替换 {replacedCount} 个块");
}
}
catch (Exception ex)
{
_ed.WriteMessage($"\n操作出错: {ex.Message}\n{ex.StackTrace}");
}
}
private void ProcessBlockReferencesInSpace(
Transaction tr,
BlockTableRecord spaceBtr,
string oldBlockName,
string newBlockName,
ref int replacedCount)
{
string spaceName = spaceBtr.IsLayout ? $"布局 '{spaceBtr.Name}'" : "模型空间";
// 收集所有需要替换的块参照ID(避免在遍历时修改集合)
List<ObjectId> blockIdsToReplace = new List<ObjectId>();
foreach (ObjectId objId in spaceBtr)
{
if (objId.ObjectClass.Name == "AcDbBlockReference")
{
BlockReference br = tr.GetObject(objId, OpenMode.ForRead) as BlockReference;
if (br != null && br.BlockName.Equals(oldBlockName, StringComparison.OrdinalIgnoreCase))
{
blockIdsToReplace.Add(objId);
}
}
}
// 处理收集到的块参照
foreach (ObjectId brId in blockIdsToReplace)
{
BlockReference oldBr = tr.GetObject(brId, OpenMode.ForRead) as BlockReference;
if (ReplaceBlockWithAttr(oldBr, tr, newBlockName, spaceName))
{
replacedCount++;
}
}
}
private bool ReplaceBlockWithAttr(BlockReference oldBr, Transaction tr, string newBlockName, string spaceName)
{
try
{
// 1. 提取旧块属性值
Dictionary<string, string> attrValues = ExtractAttributes(oldBr, tr);
// 2. 保存关键属性
Point3d insertPoint = oldBr.Position; // 正确使用原始插入点
Scale3d scale = oldBr.ScaleFactors;
double rotation = oldBr.Rotation;
string layer = oldBr.Layer;
ObjectId spaceId = oldBr.BlockTableRecordId; // 原始空间ID
// 3. 删除旧块
oldBr.UpgradeOpen();
oldBr.Erase();
// 4. 创建新块参照
BlockTable bt = tr.GetObject(tr.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord newBtr = tr.GetObject(bt[newBlockName], OpenMode.ForRead) as BlockTableRecord;
BlockReference newBr = new BlockReference(insertPoint, newBtr.ObjectId)
{
ScaleFactors = scale,
Rotation = rotation,
Layer = layer
};
// 5. 添加到原始空间
BlockTableRecord currentSpace = tr.GetObject(spaceId, OpenMode.ForWrite) as BlockTableRecord;
ObjectId newBrId = currentSpace.AppendEntity(newBr);
tr.AddNewlyCreatedDBObject(newBr, true);
// 6. 设置属性
if (attrValues.Count > 0)
{
AssignAttributes(newBr, tr, attrValues);
}
_ed.WriteMessage($"\n{spaceName} 成功替换块: {insertPoint}");
return true;
}
catch (Exception ex)
{
_ed.WriteMessage($"\n{spaceName} 替换失败: {ex.Message}");
return false;
}
}
// 修复:完整属性提取方法
private Dictionary<string, string> ExtractAttributes(BlockReference br, Transaction tr)
{
Dictionary<string, string> attrValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// 检查是否有属性集合
if (br.AttributeCollection.Count > 0)
{
foreach (ObjectId attrId in br.AttributeCollection)
{
if (attrId.ObjectClass.Name == "AcDbAttribute")
{
AttributeReference attrRef = tr.GetObject(attrId, OpenMode.ForRead) as AttributeReference;
if (attrRef != null && !string.IsNullOrWhiteSpace(attrRef.Tag))
{
attrValues[attrRef.Tag] = attrRef.TextString;
}
}
}
}
return attrValues;
}
// 属性赋值方法
private void AssignAttributes(BlockReference newBr, Transaction tr, Dictionary<string, string> attrValues)
{
newBr.UpgradeOpen();
// 遍历新块的属性集合
foreach (ObjectId attrId in newBr.AttributeCollection)
{
AttributeReference newAttr = tr.GetObject(attrId, OpenMode.ForWrite) as AttributeReference;
if (newAttr != null &&
!string.IsNullOrWhiteSpace(newAttr.Tag) &&
attrValues.ContainsKey(newAttr.Tag))
{
newAttr.TextString = attrValues[newAttr.Tag];
}
}
}
}
}