效果如下:
具体代码如下
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.Civil;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
using Application = Autodesk.AutoCAD.ApplicationServices.Core.Application;
using Entity = Autodesk.AutoCAD.DatabaseServices.Entity;
using Exception = Autodesk.AutoCAD.Runtime.Exception;
using Table = Autodesk.AutoCAD.DatabaseServices.Table;
namespace Civil3DTools
{
internal class CreateStationTable
{
private const string TableStyleName = "逐桩坐标表";
private const double TextHeight = 2.5;
private const double MajInterval = 1000;
private const double MinInterval = 25;
private const int NumRows = 5;
private const int NumCols = 11;
private const double TableBreakHeight = 240;
private const double TableBreakSpace = 100;
private const double DataRowHeight = 7.85;
private const double HeaderRowHeight = 7.20;
private const double TitleRowHeight = 11.45;
private readonly Database db;
private readonly Document doc;
private readonly Editor ed;
private readonly Table table;
private readonly double[] widths = {37.5, 37.5, 37.5, 11.25, 37.5, 37.5, 37.5, 11.25, 37.5, 37.5, 37.5};
private ObjectId alignmentId;
private CivilDocument civilDoc;
private ObjectId tableStyleId;
/// <summary>
/// 构造函数
/// </summary>
public CreateStationTable()
{
doc = Application.DocumentManager.MdiActiveDocument;
db = doc.Database;
ed = doc.Editor;
civilDoc = CivilApplication.ActiveDocument;
alignmentId = ObjectId.Null;
tableStyleId = ObjectId.Null;
table = new Table();
}
public void CreateTable()
{
try
{
SelectEntity();
if (alignmentId == ObjectId.Null) return;
GetTableStyleId();
CreatTableHeader();
SetTableHeaderStyle();
SetTableHeaderText();
PopulateData();
SetGirdLineVisiablity();
SetGirdLineWeight();
InsertTable();
}
catch (Exception e)
{
ed.WriteMessage(e.Message);
}
}
private void InsertTable()
{
table.GenerateLayout();
var tj = new TableJig(table);
var pr = ed.Drag(tj);
if (pr.Status != PromptStatus.OK) return;
using (var tr = db.TransactionManager.StartTransaction())
{
var btr = db.CurrentSpaceId.GetObject(OpenMode.ForWrite) as BlockTableRecord;
btr.AppendEntity(table);
tr.AddNewlyCreatedDBObject(table, true);
tr.Commit();
}
}
private void SetGirdLineWeight()
{
var lw = LineWeight.LineWeight060;
var numRows = table.Rows.Count;
table.Cells[2, -1].Borders.Top.LineWeight = lw;
table.Cells[numRows - 1, -1].Borders.Top.LineWeight = lw;
for (var i = 2; i < numRows; i++)
{
table.Cells[i, 0].Borders.Left.LineWeight = lw;
table.Cells[i, NumCols - 1].Borders.Right.LineWeight = lw;
}
}
private void SetGirdLineVisiablity()
{
var numRows = table.Rows.Count;
table.Cells[0, -1].Borders.Top.IsVisible = false;
table.Cells[0, -1].Borders.Bottom.IsVisible = false;
table.Cells[0, -1].Borders.Left.IsVisible = false;
table.Cells[0, -1].Borders.Right.IsVisible = false;
table.Cells[1, -1].Borders.Top.IsVisible = false;
table.Cells[1, -1].Borders.Bottom.IsVisible = false;
table.Cells[1, -1].Borders.Right.IsVisible = false;
table.Cells[1, -1].Borders.Vertical.IsVisible = false;
table.Cells[numRows - 1, -1].Borders.Top.IsVisible = false;
table.Cells[numRows - 1, -1].Borders.Bottom.IsVisible = false;
table.Cells[numRows - 1, -1].Borders.Right.IsVisible = false;
table.Cells[numRows - 1, -1].Borders.Vertical.IsVisible = false;
for (var i = 3; i < table.Rows.Count; i++)
{
table.Cells[i, 3].Borders.Top.IsVisible = false;
table.Cells[i, 3].Borders.Bottom.IsVisible = false;
table.Cells[i, 7].Borders.Top.IsVisible = false;
table.Cells[i, 7].Borders.Bottom.IsVisible = false;
}
}
private void PopulateData()
{
using (var tr = db.TransactionManager.StartTransaction())
{
var al = alignmentId.GetObject(OpenMode.ForRead) as Alignment;
var stations = al.GetStationSet(StationTypes.Major | StationTypes.Minor, MajInterval, MinInterval);
var tableTopHeaderRowsNum = table.Rows.Count - 1;
var tableDataRowsHeight = TableBreakHeight - table.Height;
table.InsertRows(tableTopHeaderRowsNum, DataRowHeight, (int) Math.Ceiling(stations.Length / 3.0));
var tableDataRowHeight = table.Rows[tableTopHeaderRowsNum].Height;
var rowsNumPerPage = (int) (tableDataRowsHeight / tableDataRowHeight);
var rowsNumTotal = table.Rows.Count;
var mod = (rowsNumTotal - tableTopHeaderRowsNum - 1) % rowsNumPerPage;
if (mod > 0) table.InsertRows(rowsNumTotal - 1, tableDataRowHeight, rowsNumPerPage - mod);
for (var i = 0; i < stations.Length; i++)
{
var station = stations[i];
var rowIndex = i % rowsNumPerPage + rowsNumPerPage * (i / rowsNumPerPage / 3);
var columIndex = 0;
if (i / rowsNumPerPage % 3 == 1)
columIndex = 4;
else if (i / rowsNumPerPage % 3 == 2) columIndex = 8;
string staWithEqu;
try
{
staWithEqu = al.GetStationStringWithEquations(station.RawStation);
}
catch (Exception e)
{
staWithEqu = station.RawStation.ToStationString();
ed.WriteMessage(e.Message);
}
var r = tableTopHeaderRowsNum + rowIndex;
table.Cells[r, columIndex].TextString = "K" + staWithEqu;
table.Cells[r, columIndex + 1].DataType = new DataTypeParameter(DataType.Double, UnitType.Unitless);
table.Cells[r, columIndex + 1].Value = station.Location.X;
table.Cells[r, columIndex + 1].DataFormat = "%lu2%pr3";
table.Cells[r, columIndex + 2].DataType = new DataTypeParameter(DataType.Double, UnitType.Unitless);
table.Cells[r, columIndex + 2].Value = station.Location.Y;
table.Cells[r, columIndex + 2].DataFormat = "%lu2%pr3";
}
tr.Commit();
}
}
private void SetTableHeaderText()
{
table.Cells[0, 0].TextString = "路线逐桩坐标表";
CellRange range;
range = CellRange.Create(table, 1, 0, 1, NumCols - 5);
table.MergeCells(range);
table.Cells[0, 0].Alignment = CellAlignment.MiddleLeft;
table.Cells[1, 0].TextString = "%<\\AcVar CustomDP.项目名称>%";
range = CellRange.Create(table, 1, NumCols - 4, 1, NumCols - 1);
table.MergeCells(range);
table.Cells[1, NumCols - 4].Alignment = CellAlignment.MiddleRight;
table.Cells[1, NumCols - 4].Borders.Horizontal.Margin = 10;
table.Cells[1, NumCols - 4].TextString = "第 页 共 页";
for (var i = 0; i < 3; i++)
{
range = CellRange.Create(table, 2, i * 4 + 0, 3, i * 4 + 0);
table.MergeCells(range);
table.Cells[2, i * 4 + 0].TextString = "桩号";
range = CellRange.Create(table, 2, i * 4 + 0, 3, i * 4 + 2);
table.MergeCells(range);
table.Cells[2, i * 4 + 1].TextString = "坐标";
table.Cells[3, i * 4 + 1].TextString = "N";
table.Cells[3, i * 4 + 2].TextString = "E";
}
var num2 = NumCols / 2;
range = CellRange.Create(table, NumCols - 1, 0, NumRows - 1, num2 - 1);
table.MergeCells(range);
table.Cells[NumRows - 1, 0].Alignment = CellAlignment.MiddleLeft;
table.Cells[NumRows - 1, 0].Borders.Horizontal.Margin = 60;
table.Cells[NumRows - 1, 0].TextString = "编制:%<\\AcVar CustomDP.编制>%";
range = CellRange.Create(table, NumCols - 1, num2, NumRows - 1, NumCols - 1);
table.MergeCells(range);
table.Cells[NumRows - 1, num2].Alignment = CellAlignment.MiddleLeft;
table.Cells[NumRows - 1, num2].Borders.Horizontal.Margin = 60;
table.Cells[NumRows - 1, num2].TextString = "复核:%<\\AcVar CustomDP.复核>%";
}
private void SetTableHeaderStyle()
{
table.Cells[0, -1].Style = "_TITLE";
for (var i = 0; i < NumRows; i++) table.Cells[i, -1].Style = "_HEADER";
table.Rows[0].Height = TitleRowHeight;
table.Rows[1].Height = HeaderRowHeight;
for (var i = 2; i < NumRows; i++) table.Rows[i].Height = DataRowHeight;
table.BreakFlowDirection = TableBreakFlowDirection.Right;
table.BreakOptions = TableBreakOptions.EnableBreaking | TableBreakOptions.RepeatTopLabels |
TableBreakOptions.RepeatBottomLabels;
table.SetBreakHeight(0, TableBreakHeight);
table.SetBreakSpacing(TableBreakSpace);
}
private void CreatTableHeader()
{
if (table == null) return;
table.SetSize(NumRows, NumCols);
if (tableStyleId == ObjectId.Null) return;
table.TableStyle = tableStyleId;
for (var i = 0; i < NumCols; i++) table.Columns[i].Width = widths[i];
}
/// <summary>
/// 获取表格样式
/// </summary>
private void GetTableStyleId()
{
var tsdId = db.TableStyleDictionaryId;
using (var tr = db.TransactionManager.StartTransaction())
{
var tsd = tsdId.GetObject(OpenMode.ForRead) as DBDictionary;
if (tsd.Contains(TableStyleName))
{
tableStyleId = tsd.GetAt(TableStyleName);
}
else
{
var ts = new TableStyle();
var txtStyleId = ObjectId.Null;
GetTxtStyleId("表格标题", "黑体", true, ref txtStyleId);
ts.SetTextStyle(txtStyleId, (int) RowType.TitleRow);
GetTxtStyleId("表格表头", "宋体", true, ref txtStyleId);
ts.SetTextStyle(txtStyleId, (int) RowType.HeaderRow);
GetTxtStyleId("表格数据", "宋体", true, ref txtStyleId);
ts.SetTextStyle(txtStyleId, (int) RowType.DataRow);
ts.SetTextHeight(TextHeight * 2, (int) RowType.TitleRow);
ts.SetTextHeight(TextHeight * 1.2, (int) RowType.HeaderRow);
ts.SetTextHeight(TextHeight, (int) RowType.DataRow);
ts.HorizontalCellMargin = TextHeight * 0.2;
ts.VerticalCellMargin = TextHeight * 0.5;
ts.SetAlignment(CellAlignment.MiddleCenter, (int) RowType.DataRow);
tsd.UpgradeOpen();
tableStyleId = tsd.SetAt(TableStyleName, ts);
tr.AddNewlyCreatedDBObject(ts, true);
tsd.DowngradeOpen();
}
tr.Commit();
}
}
private void GetTxtStyleId(string txtStyleName, string fontName, bool bold, ref ObjectId txtStyleId)
{
var tstId = db.TextStyleTableId;
using (var tr = db.TransactionManager.StartTransaction())
{
var tst = tstId.GetObject(OpenMode.ForRead) as TextStyleTable;
if (tst.Has(txtStyleName))
{
txtStyleId = tst[txtStyleName];
}
else
{
var tstr = new TextStyleTableRecord();
tstr.Name = txtStyleName;
var fd = new FontDescriptor(fontName, bold, false, 1, 1);
tstr.Font = fd;
tst.UpgradeOpen();
txtStyleId = tst.Add(tstr);
tr.AddNewlyCreatedDBObject(tstr, true);
tst.DowngradeOpen();
}
tr.Commit();
}
}
/// <summary>
/// 选择路线
/// </summary>
private void SelectEntity()
{
var peo = new PromptEntityOptions("");
peo.Message = "\n拾取路线";
peo.SetRejectMessage("\n选择的不是路线,请重新选择");
peo.AddAllowedClass(typeof(Alignment), true);
peo.AllowObjectOnLockedLayer = false;
var per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
alignmentId = per.ObjectId;
}
}
internal class TableJig : EntityJig
{
private readonly Table m_table;
private Point3d m_insertPt;
public TableJig(Entity entity) : base(entity)
{
m_table = entity as Table;
m_insertPt = Point3d.Origin;
}
protected override SamplerStatus Sampler(JigPrompts jp)
{
var jo = new JigPromptPointOptions("");
jo.Message = "\n拾取表格插入点";
var pr = jp.AcquirePoint(jo);
if (pr.Status == PromptStatus.OK)
{
if (m_insertPt == pr.Value) return SamplerStatus.NoChange;
m_insertPt = pr.Value;
return SamplerStatus.OK;
}
return SamplerStatus.Cancel;
}
protected override bool Update()
{
m_table.Position = m_insertPt;
return true;
}
}
public static class MyExtensionMethods
{
public static string ToStationString(this double Value)
{
var civilDoc = CivilApplication.ActiveDocument;
var staSetting = civilDoc.Settings.DrawingSettings.AmbientSettings.Station;
var stationString = Value.ToString("F" + staSetting.Precision.Value);
var symbolPosition = staSetting.StationDelimiterPosition.Value;
switch (symbolPosition)
{
case StationDelimiterPositionType.Delimiter10:
stationString = stationString.Insert(stationString.IndexOf('.') - 1, "+");
break;
case StationDelimiterPositionType.Delimiter100:
stationString = stationString.Insert(stationString.IndexOf('.') - 2, "+");
break;
case StationDelimiterPositionType.Delimiter1000:
stationString = stationString.Insert(stationString.IndexOf('.') - 3, "+");
break;
case StationDelimiterPositionType.Delimiter10000:
stationString = stationString.Insert(stationString.IndexOf('.') - 4, "+");
break;
case StationDelimiterPositionType.Delimiter100000:
stationString = stationString.Insert(stationString.IndexOf('.') - 5, "+");
break;
}
return stationString;
}
}
public class CivilTableToCsv
{
private readonly Document doc;
private string fileName;
private readonly Database db;
private readonly Editor ed;
private readonly List<MText> mts;
private ObjectId tableId;
public CivilTableToCsv()
{
doc = Application.DocumentManager.MdiActiveDocument;
ed = doc.Editor;
db = doc.Database;
mts = new List<MText>();
fileName = null;
}
public void Export()
{
SelectTable();
if (tableId == ObjectId.Null) return;
GetFileName();
if (fileName == null) return;
GetMtext();
if (mts.Count < 1) return;
var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
var sw = new StreamWriter(fs, Encoding.UTF8);
var sortedMts = from mt in mts
orderby mt.Location.Y descending, mt.Location.X
group mt by mt.Location.Y;
Array.ForEach(sortedMts.ToArray(), a =>
{
Array.ForEach(a.ToArray(), b => { sw.Write("{0},", b.Text); });
sw.Write(Environment.NewLine);
});
sw.Flush();
sw.Close();
fs.Close();
}
/// <summary>
/// 提取要输出的文本
/// </summary>
private void GetMtext()
{
var Objs = new DBObjectCollection();
using (var tr = db.TransactionManager.StartTransaction())
{
var ent = tableId.GetObject(OpenMode.ForRead) as Entity;
var tmpObjs = new DBObjectCollection();
ent.Explode(tmpObjs);
if (tmpObjs.Count == 1)
{
ent = tmpObjs[0] as Entity;
ent.Explode(Objs);
}
tr.Commit();
}
if (Objs.Count > 0)
using (var tr = db.TransactionManager.StartTransaction())
{
foreach (var obj in Objs)
{
var mt = obj as MText;
if (mt != null) mts.Add(mt);
}
tr.Commit();
}
}
private void GetFileName()
{
var sf = new SaveFileDialog
{
Filter = "scv文件|*.csv|所有文件|*.*",
AddExtension = true,
Title = "保存文件"
};
if (sf.ShowDialog() == DialogResult.OK) fileName = sf.FileName;
}
private void SelectTable()
{
var peo = new PromptEntityOptions("");
peo.Message = "\n选择需要输出的表格";
peo.SetRejectMessage("\n选择的不是Civil3D表格,请重新选择");
peo.AddAllowedClass(typeof(Autodesk.Civil.DatabaseServices.Table), false);
var per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
tableId = per.ObjectId;
}
}
}