![9a0ecf4cd0d35b861822ab61e510a950.png](https://i-blog.csdnimg.cn/blog_migrate/ca3de04920a1bffef97085fdef7ba4cc.jpeg)
# 0 引言
需求分析:
当需要在固定位置插入块或者是批量替换块时,可以通过获取块的坐标值,然后根据坐标位置进行插入块或者替换。
关键的第一步:就是获取块参照的坐标值。
结果:
![90d294fff2c83dee93bf12ad1432ca0a.gif](https://i-blog.csdnimg.cn/blog_migrate/6a2e573cb686150b03a9fa565d62a931.gif)
# 1. 代码分析
逻辑:
1. 设置选择集过滤,根据块名称选择块。
2. 块参照(BlockReference)类自带的Position()方法输出坐标
3. 通过NPOI方式输出到Excel
这里做了一个Button按钮来进行交互操作
![1954fe49d847e6d78cc1ee230cc5acc9.png](https://i-blog.csdnimg.cn/blog_migrate/ec9d541ec60dc8b5fab4fa2bde9884b8.png)
这里再啰嗦一下这个按钮添加的过程
找到工具性添加Button控件
![0802040909a353240caf42bd5e942c1f.png](https://i-blog.csdnimg.cn/blog_migrate/d8b58611f5be7bb38972efde9f3bb1a5.png)
属性里面更改一下文本属性
![680f8133d040f3a48c00dd1083b22539.png](https://i-blog.csdnimg.cn/blog_migrate/befd423360c6d8e6f12e67d2452a322e.png)
然后双击控件 下面添加代码即可!(为你操碎了心)
设置选择集过滤,可以根据自己需求增加过滤条件,前面都说过怎么弄
![fca15c3c60ee62c455a9e5857bea22ab.png](https://i-blog.csdnimg.cn/blog_migrate/0cbd2b3da305c04272142c401438a1e0.png)
获取块参照坐标,用到的就是下面这个方法
![dcea2a0184a8c46242efb7a50200ec40.png](https://i-blog.csdnimg.cn/blog_migrate/1011bbd1a4a3db63af0a588fcc64feee.jpeg)
![b129176428eeb155875fd336528bd9e3.png](https://i-blog.csdnimg.cn/blog_migrate/e6a3efaf9ac722ae7621f1dc7630fad7.jpeg)
遍历所有的块参照,依次获取即可
接下来就是输出的过程了,还是跟之前一样,使用NOPI的方式进行Excel读写,Excel几种读写方式见:https://www.cnblogs.com/kenjiang/p/10790652.html
为什么用这个,之前也说过了,因为不需要Office环境,还快,有一点不好就是新建项目都要去下载NOPI相应的依赖包,挺麻烦的。
![b389e7588398657ab66a26c8086a3e72.png](https://i-blog.csdnimg.cn/blog_migrate/187efffb9e81c1eeffbfff1b38c7c5f6.jpeg)
![271d386e28809b7d99961ac9956613a9.png](https://i-blog.csdnimg.cn/blog_migrate/867cdd57164665b213a015d130e508de.jpeg)
写入的代码就不详细说了,毕竟出现第二次了。
完整代码:
//存储读取坐标
List<string> lstAddStr = new List<string>();
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Application.DocumentManager.MdiActiveDocument;
SetFocus(doc.Window.Handle); //选择完文件在切换焦点
//锁定文档
using (DocumentLock acLckDoc = doc.LockDocument())
{
//设置选择集过滤器选取块 比如图框
TypedValue[] typeValue = new TypedValue[]
{
new TypedValue((int)DxfCode.BlockName,"TKA3(297X420)GZED_$2018.07") // 你自己的块名称
};
SelectionSet acSSet = this.SelectSsGet("GetSelection", null, typeValue);
if (acSSet != null)
{
foreach (SelectedObject selObj in acSSet)
{
// 确认返回的是合法的SelectedObject对象
if (selObj != null) //
{
//开始启动事物调整文字位置点和对齐点
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockReference brf = trans.GetObject(selObj.ObjectId, OpenMode.ForWrite) as BlockReference;
lstAddStr.Add(brf.Position.ToString());//获取块参照的坐标
}
}
}
}
}
//数据接下来输出到EXCEL表格
IWorkbook wk = null; //新建IWorkbook对象
string localFilePath = "D:块参照坐标.xlsx";
// 调用一个系统自带的保存文件对话框 写一个EXCEL
SaveFileDialog saveFileDialog = new SaveFileDialog(); //新建winform自带保存文件对话框对象
saveFileDialog.Filter = "Excel Office97-2003(*.xls)|*.xls|Excel Office2007及以上(*.xlsx)|*.xlsx"; //过滤只能存储的对象
DialogResult result = saveFileDialog.ShowDialog(); //显示对话框
localFilePath = saveFileDialog.FileName.ToString();
//07版之前和之后创建方式不一样
if (localFilePath.IndexOf(".xlsx") > 0) // 2007版
{
wk = new XSSFWorkbook(); //创建表格对象07版之后
}
else if (localFilePath.IndexOf(".xls") > 0) // 创建表格对象 2003版本
{
wk = new HSSFWorkbook(); //03版
}
//创建工作簿
ISheet tb = wk.CreateSheet("输出坐标数据");
for (int i = 0; i < lstAddStr.Count; i++)
{
ICell cell = tb.CreateRow(i).CreateCell(0); //单元格对象 第i行第0列 cell 单元格对象
cell.SetCellValue(lstAddStr[i]);//循环往单元格赋值
}
//创建文件
using (FileStream fs = File.OpenWrite(localFilePath)) //打开一个xls文件,如果没有则自行创建,如果存在myxls.xls文件则在创建是不要打开该文件!
{
wk.Write(fs); //文件IO 创建EXCEL
MessageBox.Show("已经成功输出块坐标^_^!");
fs.Close();
}
/// <summary>
/// 获取选择集
/// </summary>
/// <param name="selectStr">选择方式</param>
/// <param name="point3dCollection">选择点集合</param>
/// <param name="typedValue">过滤参数</param>
/// <returns></returns>
public SelectionSet SelectSsGet(string selectStr, Point3dCollection point3dCollection, TypedValue[] typedValue)
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
// 将过滤条件赋值给SelectionFilter对象
SelectionFilter selfilter = null;
if (typedValue != null)
{
selfilter = new SelectionFilter(typedValue);
}
// 请求在图形区域选择对象
PromptSelectionResult psr;
if (selectStr == "GetSelection") // 提示用户从图形文件中选取对象
{
psr = ed.GetSelection(selfilter);
}
else if (selectStr == "SelectAll") //选择当前空间内所有未锁定及未冻结的对象
{
psr = ed.SelectAll(selfilter);
}
else if (selectStr == "SelectCrossingPolygon") //选择由给定点定义的多边形内的所有对象以及与多边形相交的对象。多边形可以是任意形状,但不能与自己交叉或接触。
{
psr = ed.SelectCrossingPolygon(point3dCollection, selfilter);
}
// 选择与选择围栏相交的所有对象。围栏选择与多边形选择类似,所不同的是围栏不是封闭的, 围栏同样不能与自己相交
else if (selectStr == "SelectFence")
{
psr = ed.SelectFence(point3dCollection, selfilter);
}
// 选择完全框入由点定义的多边形内的对象。多边形可以是任意形状,但不能与自己交叉或接触
else if (selectStr == "SelectWindowPolygon")
{
psr = ed.SelectWindowPolygon(point3dCollection, selfilter);
}
else if (selectStr == "SelectCrossingWindow") //选择由两个点定义的窗口内的对象以及与窗口相交的对象
{
Point3d point1 = point3dCollection[0];
Point3d point2 = point3dCollection[1];
psr = ed.SelectCrossingWindow(point1, point2, selfilter);
}
else if (selectStr == "SelectWindow") // 选择完全框入由两个点定义的矩形内的所有对象。
{
Point3d point1 = point3dCollection[0];
Point3d point2 = point3dCollection[1];
psr = ed.SelectCrossingWindow(point1, point2, selfilter);
}
else
{
return null;
}
// 如果提示状态OK,表示对象已选
if (psr.Status == PromptStatus.OK)
{
SelectionSet sSet = psr.Value;
ed.WriteMessage("Number of objects selected: " + sSet.Count.ToString() + "n");// 打印选择对象数量
return sSet;
}
else
{
// 打印选择对象数量
ed.WriteMessage("Number of objects selected 0 n");
return null;
}
}
今天就到这了!
原文请关注公众号:数据智能笔记
http://weixin.qq.com/r/L0yosLHE2uylrfXT9xk9 (二维码自动识别)