using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using OfficeOpenXml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace uBIM_EarthTools { [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] public class DwgDataExport : IExternalCommand { public Result Execute(Autodesk.Revit.UI.ExternalCommandData CommandData, ref string Message, ElementSet elementset) { #region 变量 Autodesk.Revit.ApplicationServices.Application Revit = CommandData.Application.Application; Autodesk.Revit.UI.UIDocument uidoc = CommandData.Application.ActiveUIDocument; Autodesk.Revit.DB.Document doc = CommandData.Application.ActiveUIDocument.Document; // ICollection currentselectid = uidoc.Selection.GetElementIds(); Autodesk.Revit.DB.View curview = doc.ActiveView; List textnoteList = (new FilteredElementCollector(doc, curview.Id)). WherePasses(new ElementClassFilter(typeof(TextNote))). ToElements().Select(x => x as TextNote).ToList();//所有文字 XYZ pointFirstTable_L = new XYZ(); XYZ pointFirstTable_R = new XYZ(); XYZ pointSecTable = new XYZ(); XYZ pointLayer_L = new XYZ();//地层编号左侧x坐标 XYZ pointLayer_R = new XYZ();//地层编号右侧x坐标 XYZ pointButtom_L = new XYZ();//层底高程左侧x坐标 XYZ pointButtom_R = new XYZ();//层底高程右侧x坐标 XYZ pointStart = new XYZ();//此坐标以下为地层数据 XYZ pointNum = new XYZ();//钻孔编号 XYZ pointLevel = new XYZ();//孔口标高 XYZ pointX = new XYZ();//孔口X XYZ pointY = new XYZ();//孔口Y List boreholes = new List(); #endregion #region 用户选取点 try { pointFirstTable_L = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击第一个图框左上角……"); pointFirstTable_R = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击第一个图框右下角……"); pointSecTable = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击第二个图框左上角……"); pointLayer_L = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击地层编号列左侧……"); pointLayer_R = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击地层编号列右侧……"); pointButtom_L = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击层底高程列左侧……"); pointButtom_R = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击层底高程列右侧……"); pointStart = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击地层数据上方横线……"); pointNum = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击钻孔编号数字左下角……"); pointLevel = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击孔口标高数字左下角……"); pointX = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击孔口X数字左下角……"); pointY = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "点击地孔口Y数字左下角……"); } catch { return Result.Succeeded; } #endregion #region 保存路径 string localFilePath = String.Empty; SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "Excel files|*.xlsx"; saveFileDialog.FileName = doc.Title.Replace(".rvt", "") + "-" + DateTime.Now.ToString("yyyyMMdd"); saveFileDialog.FilterIndex = 1; saveFileDialog.RestoreDirectory = true; if (saveFileDialog.ShowDialog() == DialogResult.OK) { localFilePath = saveFileDialog.FileName.ToString(); } else return Result.Cancelled; #endregion #region 获取数据 TransactionStatus status = TransactionStatus.Uninitialized; TransactionGroup transGroup = new TransactionGroup(doc, "地质建模"); if (transGroup.Start() == TransactionStatus.Started) { Transaction transaction = new Transaction(doc, "uBIM"); int k = 0; while (true) { #region 临时变量 XYZ origin_k = pointFirstTable_L + new XYZ(k * (pointSecTable.X - pointFirstTable_L.X), 0, 0);//当前图框左上角坐标 List textnoteKList = new List(); //当前图框里的textnote List dcbhList = new List(); //地层编号 List dcgcList = new List(); //地层高程 List delTextnoteList = new List(); //被归并的textnote,后面被排除 #endregion #region 获取当前图框里的textnote foreach (TextNote tntmp in textnoteList) { if (tntmp.Coord.X > origin_k.X && tntmp.Coord.X < origin_k.X + (pointFirstTable_R.X - pointFirstTable_L.X) && tntmp.Coord.Y > origin_k.Y - (pointFirstTable_L.Y - pointFirstTable_R.Y) && tntmp.Coord.Y < origin_k.Y) { //消重 //当前条件:距离相差1cm且文字相等 Boolean dub = false; for (int i = 0; i <= textnoteKList.Count - 1; i++) { TextNote tntmp1 = textnoteKList[i]; if (tntmp.Coord.DistanceTo(tntmp1.Coord) < 1 / 304.8 && tntmp.Text == tntmp1.Text) { dub = true; break; } } if (dub == false) textnoteKList.Add(tntmp); } } if (textnoteKList.Count == 0) //获取不到时,跳出 break; #endregion #region 获取当前图框编号,标高,X,Y TextNote zkbhTn = Common.Textnote_At_Point(new XYZ(origin_k.X + pointNum.X - pointFirstTable_L.X, pointNum.Y, pointNum.Z), textnoteKList, 4); //钻孔编号 TextNote kkbgTn = Common.Textnote_At_Point(new XYZ(origin_k.X + pointLevel.X - pointFirstTable_L.X, pointLevel.Y, pointLevel.Z), textnoteKList, 4); //孔口标高 TextNote xTn = Common.Textnote_At_Point(new XYZ(origin_k.X + pointX.X - pointFirstTable_L.X, pointX.Y, pointX.Z), textnoteKList, 4); //孔口X TextNote yTn = Common.Textnote_At_Point(new XYZ(origin_k.X + pointY.X - pointFirstTable_L.X, pointY.Y, pointY.Z), textnoteKList, 4); //孔口Y //钻孔编号跟孔口标高不对应时,跳至下个图框 if (zkbhTn == null || kkbgTn == null) { k++; continue; } #endregion #region 归并地层编号中类似3-1的文字(当前条件:X公差:4mm;Y公差:2mm;字高公差:null) foreach (TextNote tntmp1 in textnoteKList) { if (tntmp1.Coord.X > origin_k.X + pointLayer_R.X - pointFirstTable_L.X)//排除超出范围的 continue; if (delTextnoteList.Contains(tntmp1))//排除已剔除的 continue; if (tntmp1.Text.Contains("."))//排除包含"."的 continue; foreach (TextNote tntmp2 in textnoteKList) { if (delTextnoteList.Contains(tntmp2))//排除已剔除的 continue; if (tntmp2.Coord.X > origin_k.X + pointLayer_R.X - pointFirstTable_L.X)//排除超出范围的 continue; if (tntmp2.Text.Contains("."))//排除包含"."的 continue; if (tntmp1.Id == tntmp2.Id)//排除与当前比较的同一TextNote continue; //三重过滤:X相近、Y相近、字高不一 if (Math.Abs(tntmp1.Coord.X - tntmp2.Coord.X) < 4 / 304.8 && Math.Abs(tntmp1.Coord.Y - tntmp2.Coord.Y) < 2 / 304.8)// &&Math.Abs(tntmp1.Height - tntmp2.Height) > 0.00001 / 304.8) { transaction.Start(); if (tntmp1.Coord.X < tntmp2.Coord.X) { tntmp1.Text = tntmp1.Text + "-" + tntmp2.Text; delTextnoteList.Add(tntmp2); } else { tntmp2.Text = tntmp2.Text + "-" + tntmp1.Text; delTextnoteList.Add(tntmp1); } transaction.Commit(); } } } textnoteKList = textnoteKList.Except(delTextnoteList).ToList(); #endregion #region 获取当前图框内所有地层编号与地层高程,并按从高到低排序 foreach (var tntmp in textnoteKList) { if (tntmp.Coord.Y > pointStart.Y) continue; else if (tntmp.Coord.X > origin_k.X + pointLayer_L.X - pointFirstTable_L.X && tntmp.Coord.X < origin_k.X + pointLayer_R.X - pointFirstTable_L.X) { dcbhList.Add(tntmp); } else if (tntmp.Coord.X > origin_k.X + pointButtom_L.X - pointFirstTable_L.X && tntmp.Coord.X < origin_k.X + pointButtom_R.X - pointFirstTable_L.X) { dcgcList.Add(tntmp); } } dcbhList = dcbhList.OrderByDescending(x => x.Coord.Y).ToList(); dcgcList = dcgcList.OrderByDescending(x => x.Coord.Y).ToList(); #endregion #region 寻找已有钻孔列表中有没有相同编号,没有时新建钻孔 Borehole bh; if (boreholes.Count != 0 && boreholes.Select(x => x.Name).ToList().Contains(zkbhTn.Text)) { bh = boreholes.ElementAt(boreholes.Select(x => x.Name).ToList().IndexOf(zkbhTn.Text)); } else { bh = new Borehole { Name = zkbhTn.Text }; bh.ValueList.Add(new GeologyLayer(dcbhList.First().Text, new XYZ(System.Convert.ToDouble(xTn.Text), System.Convert.ToDouble(yTn.Text), System.Convert.ToDouble(kkbgTn.Text)))); boreholes.Add(bh); } #endregion #region 导出对应的钻孔地层数据 for (int i = 0; i < (dcbhList.Count < dcgcList.Count ? dcbhList.Count : dcgcList.Count); i++) { string dcbh_i = dcbhList[i].Text; string dcmc_i = dcgcList[i].Text; double x = System.Convert.ToDouble(xTn.Text); double y = System.Convert.ToDouble(yTn.Text); double z = System.Convert.ToDouble(dcmc_i); GeologyLayer geologyLayer = new GeologyLayer(dcbh_i, new XYZ(x, y, z)); bh.ValueList.Add(geologyLayer); } #endregion k++; } } status = transGroup.RollBack(); #endregion #region 导出数据 if (boreholes.Count == 0) { MessageBox.Show("当前界面无法读取到钻孔数据", "uBIM"); return Result.Succeeded; } using (ExcelPackage excelPackage = new ExcelPackage()) { using (FileStream fs = new FileStream(localFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { excelPackage.Load(fs); ExcelWorksheet excelWorksheet = excelPackage.Workbook.Worksheets["Data"]; if (excelWorksheet == null) { excelWorksheet = excelPackage.Workbook.Worksheets.Add("Data"); } excelWorksheet.Cells.Clear(); excelWorksheet.Cells.Style.Numberformat.Format = "@"; for (int i = 0; i < boreholes.Count; i++) { Borehole borehole = boreholes[i]; if (borehole.ValueList.Count != 0) { excelWorksheet.Cells[2 * i + 1, 1].Value = borehole.Name; excelWorksheet.Cells[2 * i + 1, 2].Value = borehole.ValueList[0].Point.X; excelWorksheet.Cells[2 * i + 1, 3].Value = borehole.ValueList[0].Point.Y; excelWorksheet.Cells[2 * i + 2, 1].Value = borehole.Name; excelWorksheet.Cells[2 * i + 2, 2].Value = borehole.ValueList[0].Point.X; excelWorksheet.Cells[2 * i + 2, 3].Value = borehole.ValueList[0].Point.Y; for (int j = 0; j < borehole.ValueList.Count; j++) { excelWorksheet.Cells[2 * i + 1, j + 4].Value = borehole.ValueList[j].Type; excelWorksheet.Cells[2 * i + 2, j + 4].Value = borehole.ValueList[j].Point.Z; } } } } File.WriteAllBytes(localFilePath, excelPackage.GetAsByteArray()); } #endregion return Result.Succeeded; } } }