|
|
// <copyright file="ImportFileDialog.cs" company="PlaceholderCompany">
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
// </copyright>
|
|
|
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Data;
|
|
|
using System.Drawing;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Windows.Forms;
|
|
|
using System.Xml;
|
|
|
using GeoSigma.SigmaDrawerStyle;
|
|
|
using SigmaDrawerElement;
|
|
|
using UCDraw.TreeViewEx.Control;
|
|
|
|
|
|
namespace UCDraw
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 表格行和对象转换
|
|
|
/// </summary>
|
|
|
/// <param name="row">row</param>
|
|
|
/// <returns>ElementBase</returns>
|
|
|
public delegate ElementBase ConvertHandler(DataRow row);
|
|
|
|
|
|
/// <summary>
|
|
|
/// 数据导入类
|
|
|
/// </summary>
|
|
|
public partial class ImportFileDialog : Form, IRectangularCSGridPropertyChange
|
|
|
{
|
|
|
private const string X = "X";
|
|
|
private const string Y = "Y";
|
|
|
private const string Z = "Z";
|
|
|
private const string L = "L";
|
|
|
private const string Layer = "图层";
|
|
|
private const string Numerator = "分子";
|
|
|
private const string Denominator = "分母";
|
|
|
private const string FirstQuadrant = "第一象限";
|
|
|
private const string SecondQuadrant = "第二象限";
|
|
|
private const string ThirdQuadrant = "第三象限";
|
|
|
private const string FourthQuadrant = "第四象限";
|
|
|
private const string DX = "DX";
|
|
|
private const string DY = "DY";
|
|
|
private const string WellEndX = "井底X";
|
|
|
private const string WellEndY = "井底Y";
|
|
|
private const string WellInclinedAngle = "井斜角";
|
|
|
private const string AzimuthAngle = "方位角";
|
|
|
private const string InclinedDepth = "斜深";
|
|
|
private const string VerticalDepth = "垂深";
|
|
|
private const string Line123 = "123列";
|
|
|
private const string TheName = "名称";
|
|
|
private const int MaxRowOneTable = 20000;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 标记该字段是否必填
|
|
|
/// </summary>
|
|
|
public class FieldRequirement
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// Initializes a new instance of the <see cref="FieldRequirement"/> class.
|
|
|
/// </summary>
|
|
|
/// <param name="field">字段名称</param>
|
|
|
/// <param name="required">必填</param>
|
|
|
public FieldRequirement(string field, bool required)
|
|
|
{
|
|
|
Field = field;
|
|
|
Required = required;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 字段名称
|
|
|
/// </summary>
|
|
|
public string Field { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 是否必填
|
|
|
/// </summary>
|
|
|
public bool Required { get; set; }
|
|
|
}
|
|
|
|
|
|
// 点类信息
|
|
|
private static readonly FieldRequirement[] PointClass = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(Z, false),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
};
|
|
|
|
|
|
// 散点信息
|
|
|
private static readonly FieldRequirement[] ScatterPoint = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(Z, true),
|
|
|
};
|
|
|
|
|
|
// 十字点
|
|
|
private static readonly FieldRequirement[] CrossPoint = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(FirstQuadrant, true),
|
|
|
new FieldRequirement(SecondQuadrant, true),
|
|
|
new FieldRequirement(ThirdQuadrant, true),
|
|
|
new FieldRequirement(FourthQuadrant, true),
|
|
|
};
|
|
|
|
|
|
// 分数点
|
|
|
private static readonly FieldRequirement[] FractionPoint = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(Numerator, true),
|
|
|
new FieldRequirement(Denominator, true),
|
|
|
};
|
|
|
|
|
|
// 线类信息
|
|
|
private static readonly FieldRequirement[] LinesClass = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(Z, false),
|
|
|
new FieldRequirement(L, false),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
};
|
|
|
|
|
|
// 线类信息(123方式)
|
|
|
private static readonly FieldRequirement[] LineClass123 = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(Z, false),
|
|
|
new FieldRequirement(L, false),
|
|
|
new FieldRequirement(TheName, false),
|
|
|
new FieldRequirement(Line123, false),
|
|
|
};
|
|
|
|
|
|
// 偏移量法
|
|
|
private static readonly FieldRequirement[] OffsetMethod = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
new FieldRequirement(DX, true),
|
|
|
new FieldRequirement(DY, true),
|
|
|
};
|
|
|
|
|
|
// 平均角法一
|
|
|
private static readonly FieldRequirement[] AverageFisrtMethod = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
new FieldRequirement(WellInclinedAngle, true),
|
|
|
new FieldRequirement(AzimuthAngle, true),
|
|
|
new FieldRequirement(InclinedDepth, true),
|
|
|
};
|
|
|
|
|
|
// 平均角法二
|
|
|
private static readonly FieldRequirement[] AverageSecondMethod = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
new FieldRequirement(WellInclinedAngle, true),
|
|
|
new FieldRequirement(AzimuthAngle, true),
|
|
|
new FieldRequirement(VerticalDepth, true),
|
|
|
};
|
|
|
|
|
|
// 最小曲率法
|
|
|
private static readonly FieldRequirement[] MinCurveMethod = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
new FieldRequirement(WellInclinedAngle, true),
|
|
|
new FieldRequirement(AzimuthAngle, true),
|
|
|
new FieldRequirement(InclinedDepth, true),
|
|
|
};
|
|
|
|
|
|
// 井位坐标
|
|
|
private static readonly FieldRequirement[] WellPosition = new[]
|
|
|
{
|
|
|
new FieldRequirement(Layer, false),
|
|
|
new FieldRequirement(X, true),
|
|
|
new FieldRequirement(Y, true),
|
|
|
new FieldRequirement(TheName, true),
|
|
|
new FieldRequirement(WellEndX, true),
|
|
|
new FieldRequirement(WellEndY, true),
|
|
|
};
|
|
|
|
|
|
// 映射表
|
|
|
private static readonly Dictionary<ImportDataType, FieldRequirement[]> Map = new Dictionary<ImportDataType, FieldRequirement[]>
|
|
|
{
|
|
|
{ ImportDataType.PointClass, PointClass},
|
|
|
{ ImportDataType.ScatterPoint, ScatterPoint},
|
|
|
{ ImportDataType.CrossPoint, CrossPoint },
|
|
|
{ ImportDataType.FractionPoint, FractionPoint },
|
|
|
{ ImportDataType.LinesClass, LinesClass },
|
|
|
{ ImportDataType.LinesClass123, LineClass123 },
|
|
|
{ ImportDataType.OffsetMethod, OffsetMethod },
|
|
|
{ ImportDataType.AverageFisrtMethod, AverageFisrtMethod },
|
|
|
{ ImportDataType.MinCurveMethod, AverageFisrtMethod },
|
|
|
{ ImportDataType.AverageSecondMethod, AverageSecondMethod },
|
|
|
{ ImportDataType.WellPosition, WellPosition },
|
|
|
};
|
|
|
|
|
|
private GeoSigmaDrawLib.GeoSigmaXY geo;
|
|
|
private string nodeChecked = string.Empty;
|
|
|
private int column = 0;
|
|
|
// 最后一次打开文件时加载的表格数据
|
|
|
private List<List<string>> lastGridData = new List<List<string>>();
|
|
|
|
|
|
/// <summary>
|
|
|
/// GeoObj
|
|
|
/// </summary>
|
|
|
public GeoSigmaDrawLib.GeoSigmaXY GeoObj
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return this.geo;
|
|
|
}
|
|
|
set
|
|
|
{
|
|
|
this.geo = value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Initializes a new instance of the <see cref="ImportFileDialog"/> class.
|
|
|
/// </summary>
|
|
|
public ImportFileDialog()
|
|
|
{
|
|
|
InitializeComponent();
|
|
|
dgvProperty.ColumnHeadersVisible = false;
|
|
|
dgvProperty.AllowUserToAddRows = false;
|
|
|
dgvProperty.AllowUserToResizeColumns = false;
|
|
|
dgvProperty.AllowUserToResizeRows = false;
|
|
|
dgvProperty.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
|
|
|
dgvProperty.RowHeadersWidth = 47;
|
|
|
dgvProperty.Columns[0].Width = 146;
|
|
|
dgvProperty.Columns[1].Width = 146;
|
|
|
|
|
|
// 防止行号被掩盖
|
|
|
dgViewContent.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
|
|
|
}
|
|
|
|
|
|
private void LoadSingleSelectTreeView()
|
|
|
{
|
|
|
chkaddtvPointCurve.Nodes.Clear();
|
|
|
chkaddtvPointCurve.BeginUpdate();
|
|
|
|
|
|
var treeDesc = new[]
|
|
|
{
|
|
|
("基础点类", new[]
|
|
|
{
|
|
|
("点类信息", "PointClass"),
|
|
|
("散点信息", "ScatterPoint"),
|
|
|
("十字点", "CrossPoint"),
|
|
|
("分数点", "FractionPoint"),
|
|
|
}),
|
|
|
("基础线类", new[]
|
|
|
{
|
|
|
("线类信息", "LinesClass"),
|
|
|
("线类信息(123方式)", "LinesClass123"),
|
|
|
}),
|
|
|
("斜井轨迹", new[]
|
|
|
{
|
|
|
("偏移量法", "OffsetMethod"),
|
|
|
("平均角法一", "AverageFisrtMethod"),
|
|
|
("平均角法二", "AverageSecondMethod"),
|
|
|
("最小曲率法", "MinCurveMethod"),
|
|
|
("井位坐标", "WellPosition"),
|
|
|
}),
|
|
|
};
|
|
|
|
|
|
foreach (var (category, nodes) in treeDesc)
|
|
|
{
|
|
|
var categoryNode = new CheckBoxNoVisiableTreeNode(category);
|
|
|
|
|
|
foreach (var (text, name) in nodes)
|
|
|
{
|
|
|
var treeNode = new TreeNode(text)
|
|
|
{
|
|
|
Name = name,
|
|
|
};
|
|
|
categoryNode.Nodes.Add(treeNode);
|
|
|
}
|
|
|
|
|
|
chkaddtvPointCurve.Nodes.Add(categoryNode);
|
|
|
}
|
|
|
|
|
|
chkaddtvPointCurve.Nodes[0].Nodes[0].Checked = true;
|
|
|
|
|
|
chkaddtvPointCurve.ExpandAll();
|
|
|
chkaddtvPointCurve.EndUpdate();
|
|
|
chkaddtvPointCurve.Refresh();
|
|
|
}
|
|
|
|
|
|
private void ImportFileDialog_Load(object sender, EventArgs e)
|
|
|
{
|
|
|
this.LoadSingleSelectTreeView();
|
|
|
LoadPropertyGrid();
|
|
|
}
|
|
|
|
|
|
private void chkaddtvPointCurve_BeforeCheck(object sender, TreeViewCancelEventArgs e)
|
|
|
{
|
|
|
this.nodeChecked = e.Node.Name;
|
|
|
if (e.Action != TreeViewAction.Unknown)
|
|
|
{
|
|
|
TreeNode oldNode = this.chkaddtvPointCurve.Tag as TreeNode;
|
|
|
if (oldNode != null && oldNode != e.Node)
|
|
|
{
|
|
|
oldNode.Checked = false;
|
|
|
}
|
|
|
TreeNodeCollection nodes = this.chkaddtvPointCurve.Nodes;
|
|
|
foreach (TreeNode node in nodes)
|
|
|
{
|
|
|
foreach (TreeNode item in node.Nodes)
|
|
|
{
|
|
|
if (item != e.Node)
|
|
|
{
|
|
|
item.Checked = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
this.chkaddtvPointCurve.Tag = e.Node;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void btnSelectFile_Click(object sender, EventArgs e)
|
|
|
{
|
|
|
var ofd = new OpenFileDialog
|
|
|
{
|
|
|
Filter = "All file (*.*)|*.*||",
|
|
|
Multiselect = false,
|
|
|
};
|
|
|
if (ofd.ShowDialog() != DialogResult.OK)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
string fileNames = string.Empty;
|
|
|
foreach (var item in ofd.FileNames)
|
|
|
{
|
|
|
fileNames += item + " ";
|
|
|
}
|
|
|
|
|
|
this.txtFilePath.Text = fileNames.TrimEnd();
|
|
|
|
|
|
var gridData = ReadDataFromFile(ofd.FileNames[0], 0, -1);
|
|
|
lastGridData = ClearEmptyColumn(gridData);
|
|
|
|
|
|
LoadGirdData();
|
|
|
LoadPropertyGrid();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 忽略多少行
|
|
|
/// </summary>
|
|
|
private int SkipRowCount
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return (int)numUDStartRow.Value;
|
|
|
}
|
|
|
|
|
|
set
|
|
|
{
|
|
|
if (value < 1)
|
|
|
{
|
|
|
numUDStartRow.Value = 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
numUDStartRow.Value = value;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void LoadGirdData()
|
|
|
{
|
|
|
// 如果点太多,全部显示出来会导入表格控件加载数据很卡,这里只显示 200 行,而且看到全部点意义也不是那么大
|
|
|
// 如果后面用户就是需要看到全部点,那么后面可以做个分页,这样也不会卡
|
|
|
DataTable dt = CreateDataTable(lastGridData.Skip(SkipRowCount - 1).Take(MaxRowOneTable).ToList());
|
|
|
this.lbRows.Text = lastGridData.Count.ToString();
|
|
|
|
|
|
column = dt.Columns.Count;
|
|
|
dgViewContent.DataSource = dt;
|
|
|
|
|
|
dgViewContent.RowHeadersVisible = true;
|
|
|
dgViewContent.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
|
|
|
|
|
|
// 添加行号
|
|
|
for (int i = 0; i < dgViewContent.Rows.Count; i++)
|
|
|
{
|
|
|
dgViewContent.Rows[i].HeaderCell.Value = (1 + i).ToString();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private IEnumerable<string> ReadFile(string path)
|
|
|
{
|
|
|
using (StreamReader sr = new StreamReader(path, Encoding.Default))
|
|
|
{
|
|
|
string line;
|
|
|
while ((line = sr.ReadLine()) != null)
|
|
|
{
|
|
|
yield return line;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 统计非空的列
|
|
|
/// </summary>
|
|
|
/// <param name="gridData">字符串表格</param>
|
|
|
/// <returns>返回非空列的 index 集合</returns>
|
|
|
private HashSet<int> CountNonEmptyColumn(List<List<string>> gridData)
|
|
|
{
|
|
|
// 存储非空的列下标
|
|
|
HashSet<int> columns = new HashSet<int>();
|
|
|
|
|
|
foreach (var row in gridData)
|
|
|
{
|
|
|
for (int i = 0; i < row.Count; i++)
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(row[i]))
|
|
|
{
|
|
|
columns.Add(i);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return columns;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 从字符串表格中提取指定几列的数据
|
|
|
/// </summary>
|
|
|
/// <param name="gridData">字符串表格</param>
|
|
|
/// <param name="columns">要提取哪些列</param>
|
|
|
/// <returns>返回提取后的字符串表格</returns>
|
|
|
private List<List<string>> ExtractSpecificColumns(List<List<string>> gridData, ISet<int> columns)
|
|
|
{
|
|
|
List<List<string>> result = new List<List<string>>();
|
|
|
|
|
|
foreach (var row in gridData)
|
|
|
{
|
|
|
var newRow = new List<string>();
|
|
|
for (int i = 0; i < row.Count; i++)
|
|
|
{
|
|
|
if (columns.Contains(i))
|
|
|
{
|
|
|
newRow.Add(row[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
result.Add(newRow);
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 清理空列数据
|
|
|
/// </summary>
|
|
|
/// <param name="gridData">字符串表格</param>
|
|
|
/// <returns>返回清理掉空列的表格</returns>
|
|
|
private List<List<string>> ClearEmptyColumn(List<List<string>> gridData)
|
|
|
{
|
|
|
// 不考虑第一行的列是否为空,因为有时候第一行全是头,但是我们目前没有办法判断第一列是不是头,先忽略它
|
|
|
HashSet<int> columns = CountNonEmptyColumn(gridData.GetRange(1, gridData.Count - 1));
|
|
|
return ExtractSpecificColumns(gridData, columns);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 将一行字符串多个空格合并成为一个.
|
|
|
/// </summary>
|
|
|
/// <param name="line">字符串.</param>
|
|
|
/// <returns>返回处理后的字符串.</returns>
|
|
|
private static string NormalizeSpaces(string line)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(line))
|
|
|
{
|
|
|
return line;
|
|
|
}
|
|
|
|
|
|
StringBuilder sb = new StringBuilder(line.Length);
|
|
|
bool inSpace = false;
|
|
|
|
|
|
foreach (char c in line)
|
|
|
{
|
|
|
if (c == ' ')
|
|
|
{
|
|
|
if (!inSpace)
|
|
|
{
|
|
|
sb.Append(c);
|
|
|
inSpace = true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
sb.Append(c);
|
|
|
inSpace = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return sb.ToString().Trim();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 从文件中读取指定有效行,无效行是指其中的空行
|
|
|
/// </summary>
|
|
|
/// <param name="path">文件路径</param>
|
|
|
/// <param name="startRow">起始行</param>
|
|
|
/// <param name="maxRow">读取多少行</param>
|
|
|
/// <returns>返回由这些行按规则拆分后的数据</returns>
|
|
|
private List<List<string>> ReadDataFromFile(string path, int startRow, int maxRow)
|
|
|
{
|
|
|
// 小于0表示读到文件结尾
|
|
|
if (maxRow < 0)
|
|
|
{
|
|
|
maxRow = int.MaxValue;
|
|
|
}
|
|
|
|
|
|
char[] caSplit = new char[3] { ',', ' ', '\t' };
|
|
|
|
|
|
// 如果存在多个空格,当作一个,否则会引发很多 bug
|
|
|
// 不能简单的在 Split 里面跟上 StringSplitOptions.RemoveEmptyEntries,
|
|
|
// 这样会导致有完整表头,但是中间有的列没有数据时,数据向前串位
|
|
|
return ReadFile(path)
|
|
|
.Skip(startRow)
|
|
|
.Where(x => !string.IsNullOrWhiteSpace(x))
|
|
|
.Select(x => NormalizeSpaces(x))
|
|
|
.Select(x => x.Split(caSplit).ToList())
|
|
|
.Take(maxRow)
|
|
|
.ToList();
|
|
|
}
|
|
|
|
|
|
private DataTable CreateDataTable(List<List<string>> lines)
|
|
|
{
|
|
|
var dt = new DataTable();
|
|
|
|
|
|
List<string> headers = new List<string>();
|
|
|
if (chkFirstRow.Checked && lines.Count != 0) // 首行作为标签
|
|
|
{
|
|
|
headers = lines[0].ToList();
|
|
|
lines.RemoveAt(0);
|
|
|
}
|
|
|
|
|
|
// 根据条目最多的数据来确定列数,并添加列号
|
|
|
int column = lines.Max(s => s.Count);
|
|
|
if (chkFirstRow.Checked)
|
|
|
{
|
|
|
for (int i = 0; i < column; i++)
|
|
|
{
|
|
|
if (i < headers.Count)
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(headers[i]))
|
|
|
{
|
|
|
dt.Columns.Add($"{i + 1}-{headers[i]}");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
dt.Columns.Add((i + 1).ToString());
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
dt.Columns.Add((i + 1).ToString());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
for (int i = 0; i < column; i++)
|
|
|
{
|
|
|
dt.Columns.Add((i + 1).ToString());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
foreach (List<string> s in lines)
|
|
|
{
|
|
|
DataRow row = dt.NewRow();
|
|
|
row.ItemArray = s.ToArray();
|
|
|
dt.Rows.Add(row);
|
|
|
}
|
|
|
|
|
|
return dt;
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
void IRectangularCSGridPropertyChange.RCSGridPropertyChange()
|
|
|
{
|
|
|
throw new NotImplementedException();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 判断表格填写是否完整,必选项是否都做了选择
|
|
|
/// </summary>
|
|
|
/// <param name="tableDesc">表格描述信息</param>
|
|
|
/// <param name="message">如果不完整,返回的错误信息</param>
|
|
|
/// <returns>完整返回true,不完整返回false</returns>
|
|
|
private bool IsFormComplete(FieldRequirement[] tableDesc, out string message)
|
|
|
{
|
|
|
message = string.Empty;
|
|
|
|
|
|
for (int i = 0; i < tableDesc.Length && i < dgvProperty.RowCount; i++)
|
|
|
{
|
|
|
if (tableDesc[i].Required)
|
|
|
{
|
|
|
DataGridViewRow row = dgvProperty.Rows[i];
|
|
|
if (row.Cells[1].Value.ToString() == "无")
|
|
|
{
|
|
|
message = $"{tableDesc[i].Field} 为必选项";
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
private void btnImport_Click(object sender, EventArgs e)
|
|
|
{
|
|
|
if (txtFilePath.Text.Trim() == string.Empty)
|
|
|
{
|
|
|
MessageBox.Show("请选择数据文件!");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!Enum.TryParse<ImportDataType>(nodeChecked, out ImportDataType checkedType))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var tableDesc = Map[checkedType];
|
|
|
|
|
|
if (!IsFormComplete(tableDesc, out string errorMesssage))
|
|
|
{
|
|
|
MessageBox.Show(errorMesssage);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (checkedType == ImportDataType.LinesClass || checkedType == ImportDataType.LinesClass123)
|
|
|
{
|
|
|
ImportLines();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.PointClass)
|
|
|
{
|
|
|
ImportNormalPoint();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.ScatterPoint)
|
|
|
{
|
|
|
ImportScatterPoint();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.CrossPoint)
|
|
|
{
|
|
|
ImportCorssPoint();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.FractionPoint)
|
|
|
{
|
|
|
ImportFractionPoint();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.OffsetMethod)
|
|
|
{
|
|
|
ImportOffestMethod();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.AverageFisrtMethod || checkedType == ImportDataType.MinCurveMethod)
|
|
|
{
|
|
|
ImportAverageFirstMethod();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.AverageSecondMethod)
|
|
|
{
|
|
|
ImportAverageSecondMethod();
|
|
|
}
|
|
|
else if (checkedType == ImportDataType.WellPosition)
|
|
|
{
|
|
|
ImportWellPosition();
|
|
|
}
|
|
|
|
|
|
this.DialogResult = DialogResult.OK;
|
|
|
this.Close();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 返回点数据
|
|
|
/// </summary>
|
|
|
/// <param name="indexDict">列索字典,表示用户选中哪个字段对应哪一列</param>
|
|
|
/// <param name="maxColumn">表格的最大列数</param>
|
|
|
/// <returns>结果</returns>
|
|
|
private List<Dictionary<string, string>> DataTableValue(Dictionary<string, int> indexDict, int maxColumn)
|
|
|
{
|
|
|
string currentLayer = geo.GetCurrentLayer();
|
|
|
List<string> numberKeys = new List<string>()
|
|
|
{
|
|
|
X, Y, Z, L, Numerator, Denominator, DX, DY,
|
|
|
WellInclinedAngle, AzimuthAngle, InclinedDepth, VerticalDepth,
|
|
|
};
|
|
|
|
|
|
Dictionary<string, int> validIndexDict = RemoveIndexOutOfRange(indexDict, maxColumn);
|
|
|
|
|
|
var result = new List<Dictionary<string, string>>();
|
|
|
|
|
|
// 提取表格值 现在SkipRowCount是从1开始
|
|
|
foreach (List<string> strings in lastGridData.Skip(SkipRowCount - 1))
|
|
|
{
|
|
|
var data = new Dictionary<string, string>();
|
|
|
bool invalid = true;
|
|
|
|
|
|
foreach (var pair in validIndexDict)
|
|
|
{
|
|
|
string key = pair.Key;
|
|
|
|
|
|
// 忽略列数不足的行
|
|
|
if (pair.Value >= strings.Count())
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
string value = strings[pair.Value].ToString();
|
|
|
|
|
|
// 如果图层为空,则导入到当前图层
|
|
|
if (key == Layer && string.IsNullOrWhiteSpace(value))
|
|
|
{
|
|
|
value = currentLayer;
|
|
|
}
|
|
|
|
|
|
// 这些字符必须是数字,如果不是数字,该行数据格式不正确,忽略并继续
|
|
|
if (numberKeys.Contains(key))
|
|
|
{
|
|
|
if (!double.TryParse(value, out double _))
|
|
|
{
|
|
|
invalid = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
data.Add(key, value);
|
|
|
}
|
|
|
|
|
|
if (!invalid)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// 如果用户没配置图层,也导入到当前图层
|
|
|
if (!validIndexDict.ContainsKey(Layer))
|
|
|
{
|
|
|
data.Add(Layer, currentLayer);
|
|
|
}
|
|
|
|
|
|
result.Add(data);
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 移除超出范围的下标,即移除里面 index 小于0 或 大于maxColumn 的项
|
|
|
/// </summary>
|
|
|
/// <param name="indexDict">indexDict</param>
|
|
|
/// <param name="maxColumn">表格最大列数</param>
|
|
|
/// <returns>合法的下标字典</returns>
|
|
|
private Dictionary<string, int> RemoveIndexOutOfRange(Dictionary<string, int> indexDict, int maxColumn)
|
|
|
{
|
|
|
return indexDict
|
|
|
.Where(pair => pair.Value >= 0 && pair.Value < maxColumn)
|
|
|
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
|
}
|
|
|
|
|
|
private string ImportData(params string[] names)
|
|
|
{
|
|
|
var indexDict = ParseColumnIndex(names);
|
|
|
DataTable dataTable = (DataTable)dgViewContent.DataSource;
|
|
|
int maxColumn = dataTable.Columns.Count;
|
|
|
List<Dictionary<string, string>> points = DataTableValue(indexDict, maxColumn);
|
|
|
return DataToXml(points);
|
|
|
}
|
|
|
|
|
|
private void ImportCorssPoint()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer, FirstQuadrant, SecondQuadrant, ThirdQuadrant, FourthQuadrant);
|
|
|
geo.ImportCrossPoint(data);
|
|
|
}
|
|
|
|
|
|
private void ImportFractionPoint()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer, Numerator, Denominator);
|
|
|
geo.ImportFractionPoint(data);
|
|
|
}
|
|
|
private void ImportScatterPoint()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer);
|
|
|
geo.ImportScatterPoint(data);
|
|
|
}
|
|
|
|
|
|
private void ImportNormalPoint()
|
|
|
{
|
|
|
var data = ImportData(TheName, X, Y, Z, Layer);
|
|
|
geo.ImportNormalPoint(data);
|
|
|
}
|
|
|
|
|
|
private void ImportOffestMethod()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer, TheName, DX, DY);
|
|
|
geo.ImportOffestMethod(data);
|
|
|
}
|
|
|
|
|
|
private void ImportAverageFirstMethod()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer, TheName, WellInclinedAngle, AzimuthAngle, InclinedDepth);
|
|
|
geo.ImportAverageFristMethod(data);
|
|
|
}
|
|
|
|
|
|
private void ImportAverageSecondMethod()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer, TheName, WellInclinedAngle, AzimuthAngle, VerticalDepth);
|
|
|
geo.ImportAverageSecondMethod(data);
|
|
|
}
|
|
|
|
|
|
private void ImportWellPosition()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, Layer, TheName, WellEndX, WellEndY);
|
|
|
geo.ImportWellPosition(data);
|
|
|
}
|
|
|
|
|
|
private string XmlDocument2Gb2312(XmlDocument xmlDoc)
|
|
|
{
|
|
|
// 转换为以gb2312编码的字符串
|
|
|
using (MemoryStream stream = new MemoryStream())
|
|
|
{
|
|
|
XmlWriterSettings settings = new XmlWriterSettings();
|
|
|
settings.Encoding = Encoding.GetEncoding("gb2312"); // 设置编码为gb2312
|
|
|
settings.Indent = true;
|
|
|
|
|
|
using (XmlWriter writer = XmlWriter.Create(stream, settings))
|
|
|
{
|
|
|
xmlDoc.Save(writer);
|
|
|
}
|
|
|
|
|
|
string xmlString = Encoding.GetEncoding("gb2312").GetString(stream.ToArray());
|
|
|
return xmlString;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void ImportLines()
|
|
|
{
|
|
|
string data = ImportData(X, Y, Z, L, Layer, TheName);
|
|
|
geo.ImportCurve(data, nodeChecked);
|
|
|
}
|
|
|
|
|
|
private Dictionary<string, int> ParseColumnIndex(params string[] names)
|
|
|
{
|
|
|
var result = names.ToDictionary(key => key, value => 0);
|
|
|
|
|
|
foreach (DataGridViewRow row in dgvProperty.Rows)
|
|
|
{
|
|
|
string rowName = row.Cells[0].Value.ToString();
|
|
|
string rowValue = row.Cells[1].Value.ToString();
|
|
|
int value = (rowValue == "无" ? 0 : Convert.ToInt32(rowValue));
|
|
|
|
|
|
if (names.Contains(rowName))
|
|
|
{
|
|
|
result[rowName] = value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 将大家常用下标(从1开始)转为开发常用下标(从0开始)
|
|
|
result = result.ToDictionary(pair => pair.Key, pair => pair.Value - 1);
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
private string DataToXml(List<Dictionary<string, string>> points)
|
|
|
{
|
|
|
XmlDocument xmlDoc = new XmlDocument();
|
|
|
|
|
|
XmlElement rootElement = xmlDoc.CreateElement("Root");
|
|
|
xmlDoc.AppendChild(rootElement);
|
|
|
|
|
|
foreach (var point in points)
|
|
|
{
|
|
|
XmlElement pointElement = xmlDoc.CreateElement("Data");
|
|
|
foreach (var pair in point)
|
|
|
{
|
|
|
XmlElement element = xmlDoc.CreateElement(pair.Key);
|
|
|
element.InnerText = pair.Value;
|
|
|
pointElement.AppendChild(element);
|
|
|
}
|
|
|
|
|
|
rootElement.AppendChild(pointElement);
|
|
|
}
|
|
|
|
|
|
return XmlDocument2Gb2312(xmlDoc);
|
|
|
}
|
|
|
|
|
|
private void chkFirstRow_CheckedChanged(object sender, EventArgs e)
|
|
|
{
|
|
|
string strFile = this.txtFilePath.Text;
|
|
|
if (string.IsNullOrEmpty(strFile))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
chkFirstRow.CheckedChanged -= chkFirstRow_CheckedChanged;
|
|
|
try
|
|
|
{
|
|
|
this.LoadGirdData();
|
|
|
LoadPropertyGrid();
|
|
|
}
|
|
|
catch (System.Data.DuplicateNameException)
|
|
|
{
|
|
|
MessageBox.Show("首行有重复名称,不能作为标签");
|
|
|
chkFirstRow.Checked = false;
|
|
|
}
|
|
|
chkFirstRow.CheckedChanged += chkFirstRow_CheckedChanged;
|
|
|
}
|
|
|
|
|
|
private void numUDStartRow_ValueChanged(object sender, EventArgs e)
|
|
|
{
|
|
|
string strFile = this.txtFilePath.Text;
|
|
|
if (string.IsNullOrEmpty(strFile))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
this.LoadGirdData();
|
|
|
}
|
|
|
|
|
|
private void EnableDgvProperty(bool enable)
|
|
|
{
|
|
|
dgvProperty.Enabled = enable;
|
|
|
Color bgColor = enable ? Color.White : Color.LightGray;
|
|
|
dgvProperty.Columns[0].DefaultCellStyle.BackColor = bgColor;
|
|
|
dgvProperty.Columns[1].DefaultCellStyle.BackColor = bgColor;
|
|
|
}
|
|
|
|
|
|
private void chkaddtvPointCurve_AfterSelect(object sender, TreeViewEventArgs e)
|
|
|
{
|
|
|
//nodeChecked = e.Node.Name;
|
|
|
foreach (var pItem in chkaddtvPointCurve.Nodes)
|
|
|
{
|
|
|
TreeNode pNode = (TreeNode)pItem;
|
|
|
foreach (var cItem in pNode.Nodes)
|
|
|
{
|
|
|
TreeNode cNode = (TreeNode)cItem;
|
|
|
if (cNode.Checked)
|
|
|
{
|
|
|
cNode.Checked = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
var titles = new string[] { "基础点类", "基础线类", "斜井轨迹" };
|
|
|
|
|
|
if (titles.Contains(e.Node.Text))
|
|
|
{
|
|
|
EnableDgvProperty(false);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
EnableDgvProperty(true);
|
|
|
e.Node.Checked = true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 配置数据内容自动配置列号
|
|
|
private string AutoMatchLineNumber(string columnName)
|
|
|
{
|
|
|
DataTable dataTable = (DataTable)dgViewContent.DataSource;
|
|
|
if (dataTable != null && dataTable.Rows.Count > 0)
|
|
|
{
|
|
|
for (int i = 0; i < dataTable.Columns.Count; i++)
|
|
|
{
|
|
|
string value = dataTable.Rows[0][i].ToString().Trim();
|
|
|
if (string.Compare(value, columnName, true) == 0)
|
|
|
{
|
|
|
return $"{i + 1}";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return "无";
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 加载右下角配置表格
|
|
|
/// </summary>
|
|
|
/// <param name="gridDescs">表格描述信息</param>
|
|
|
public void LoadPropertyClass(FieldRequirement[] gridDescs)
|
|
|
{
|
|
|
dgvProperty.Rows.Clear();
|
|
|
|
|
|
for (int i = 0; i < gridDescs.Length; i++)
|
|
|
{
|
|
|
var tableDesc = gridDescs[i];
|
|
|
|
|
|
// 创建新的行
|
|
|
DataGridViewRow row = new DataGridViewRow();
|
|
|
|
|
|
// 设置行头,如果是必选,给行号后面加 *
|
|
|
int line = i + 1;
|
|
|
row.HeaderCell.Value = tableDesc.Required ? $"{line}*" : $"{line}";
|
|
|
|
|
|
// 添加名称单元格
|
|
|
DataGridViewTextBoxCell nameCell = new DataGridViewTextBoxCell();
|
|
|
nameCell.Value = tableDesc.Field;
|
|
|
row.Cells.Add(nameCell);
|
|
|
|
|
|
// 添加下拉列表单元格
|
|
|
DataGridViewComboBoxCell comboCell = new DataGridViewComboBoxCell();
|
|
|
comboCell.Items.Add("无");
|
|
|
comboCell.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
|
|
|
comboCell.Value = AutoMatchLineNumber(tableDesc.Field);
|
|
|
row.Cells.Add(comboCell);
|
|
|
|
|
|
// 给下拉列表添加数据
|
|
|
for (int j = 0; j < column; j++)
|
|
|
{
|
|
|
string value = $"{j + 1}";
|
|
|
comboCell.DisplayMember = value;
|
|
|
comboCell.ValueMember = value;
|
|
|
comboCell.Items.Add(value);
|
|
|
}
|
|
|
|
|
|
// 将新行添加至DataGridView控件
|
|
|
dgvProperty.Rows.Add(row);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void chkaddtvPointCurve_AfterCheck(object sender, TreeViewEventArgs e)
|
|
|
{
|
|
|
nodeChecked = e.Node.Name;
|
|
|
if (e.Node.Checked)
|
|
|
{
|
|
|
LoadPropertyGrid();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 加载属性表格
|
|
|
/// </summary>
|
|
|
public void LoadPropertyGrid()
|
|
|
{
|
|
|
if (!Enum.TryParse<ImportDataType>(nodeChecked, out ImportDataType checkedType))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (Map.ContainsKey(checkedType))
|
|
|
{
|
|
|
LoadPropertyClass(Map[checkedType]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// ImportDataType
|
|
|
/// </summary>
|
|
|
internal enum ImportDataType
|
|
|
{
|
|
|
PointClass,
|
|
|
ScatterPoint,
|
|
|
CrossPoint,
|
|
|
FractionPoint,
|
|
|
LinesClass,
|
|
|
LinesClass123,
|
|
|
OffsetMethod,
|
|
|
AverageFisrtMethod,
|
|
|
MinCurveMethod,
|
|
|
AverageSecondMethod,
|
|
|
WellPosition,
|
|
|
}
|
|
|
}
|