根据 Excel 表格建立 Shp 文件
土木水电学院 3S 实验室 肖泽云
三峡大学土木水电学院 肖泽云
根据 Excel 表格建立 Shp 文件主要是通过 Excel 表格中的数值信息,如用
于表示点坐标的 x 值、y 值以及一些属性信息,来建立一个 shp 数据文件,该文
件中点的几何位置即为 Excel 表格中指定的数值,并根据要求添加一些相关的属
性信息。
具体来讲,整个过程主要包括三个方面:导入 Excel 数据表、新建 shp 数
据文件、添加数据(包括几何数据和属性数据)。下面就以根据Excel 表格生成
Shp 点数据文件为例,来具体介绍整个过程中的各主要部分:
一、导入 Excel 数据表
导入 Excel 数据表主要有两种方式,一种是通过 OleDb 数据源的形式打开
Excel 表格,还有一种就是以 Application 的形式通过调用 Excel 对象来打开表
格。由于采用OleDb 数据源的形式比较具有通用性,使用这种方式不仅可以打开
Excel 表格,还可以打开 Access 数据库、SQL 数据库等(具体调用方式稍有差别),
下面主要介绍第一种方式:
首先,在全局变量中定义数据源连接对象,如下:
OleDbConnection oledbcConnection;//Excel 连接
然后,添加一个菜单项或按钮用于打开 Excel 数据表,为其 Click()事件添
加如下代码:
try
{
OpenFileDialog openDG = new OpenFileDialog();
openDG.Title = "打开Excel表格";
openDG.Filter = "Excel表格(*.xls)|*.xls|CSV格式
(*.csv)|*.csv|所有文件(*.*)|*.*";
openDG.ShowDialog();
string filename;
filename = openDG.FileName;
string strConn
= @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
+ filename + ";Extended Properties=Excel 8.0";
oledbcConnection = new OleDbConnection(strConn);
oledbcConnection.Open();
DataTable table = new DataTable();
table =
oledbcConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new
object[] { null, null, null, "TABLE" });
excelBookComboBoxEx.Items.Clear();
foreach (DataRow dr in table.Rows)
{
excelBookComboBoxEx.Items.Add((String)dr["TABLE_NAME"]);
QQ:289700062
第 1 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
}
excelBookComboBoxEx.Text =
excelBookComboBoxEx.Items[0].ToString();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
其中,excelBookComboBoxEx 为一个 ComboBox 组件,用于显示该 Excel 文
件中的表名称(一个 Excel 文件中可能包含有很多表,而且每个表的名称都不一
样,且第一个数据表的名称不一定就为“Sheet1”)。为了避免由于 Excel 文件
中不存在该表名而出现错误,利用一个 ComboBox 组件将该 Excel 文件中所有的
表名列出来。其中变量 table 中保存了该 Excel 表格的所有表格信息,所以
“dr["TABLE_NAME"]”即为获取该行中对应的表名。
在 excelBookComboBoxEx 控件中选择 Excel 表格中要打开的 Excel 工作表
后,通过一个数据库连接命令和前面定义的数据源连接来获得工作表中的数据。
添加一个按钮用于确定打开 Excel 中某个工作表,为其 Click()事件添加如下代
码:
try
{
string sheetName = excelBookComboBoxEx.Text;
string strCom = @" SELECT * FROM [" + sheetName + "]";
OleDbDataAdapter myCommand = new
OleDbDataAdapter(strCom, oledbcConnection);
DataSet myDataSet = new DataSet();
myCommand.Fill(myDataSet, "[" + sheetName + "]");
excelDataGridViewX.DataMember = "[" + sheetName + "]";
excelDataGridViewX.DataSource = myDataSet;
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
上述代码中,excelDataGridViewX 表示一个数据表格控件用于显示 Excel
表格中的数据。
二、新建 shp 数据文件
由于通过 Excel 表格来建立一个 Shp 点数据文件,可能会涉及到新建 Shp
数据文件,所有在此先介绍新建 Shp 数据文件的过程。新建一个 Form 用于表示
创建 Shp 文件的界面,设置 Form 的 Name 属性为“CreateShpFile”,然后在该
界面上添加如下图所示控件(红色字体表示该控件的名称):
QQ:289700062
第 2 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
现说明一下该窗体中主要的控件,filePathTextBox 控件用于表示文件的路
径,saveFileButton 控件用于表示保存路径浏览,fileNameTextBox 控件用于表示
新建的文件名,shpTypeComboBox 用于表示新建的数据类型(如Point、Polyline、
Polygon 等),创建按钮用于根据设置开始创建新的Shp 文件,取消按钮用于取
消创建新 Shp 文件。
首先,在全局变量中定义三个变量,如下代码:
private AxMapControl axMapControl;
private string filePath;
private string fileName;
其中,axMapControl 表示 MapControl 控件(主要用于将新建的数据文件添
加至地图中),filePath 为新建数据文件的路径,fileName 为新建数据文件的名称。
更改 CreateShpFile 窗体的构造函数为如下:
public CreateShpFile(AxMapControl _axMapControl)
{
axMapControl = _axMapControl;
InitializeComponent();
}
这样在定义 CreateShpFile 类时就要求指定 MapControl 对象。
为保存文件路径按钮(saveFileButton)的 Click()事件添加如下代码:
private void saveFileButton_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog saveDG = new SaveFileDialog();
saveDG.Title = "新建Shp文件";
saveDG.Filter = "Shp文件(*.shp)|*.shp";
saveDG.ShowDialog();
string saveFilePath = saveDG.FileName;
int i = saveFilePath.LastIndexOf(@"\");
int length = saveFilePath.Length;
filePath =
Microsoft.VisualBasic.Strings.Left(saveFilePath, i+1);
QQ:289700062
第 3 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
filePathTextBox.Text = filePath;
fileName =
Microsoft.VisualBasic.Strings.Right(saveFilePath, length - i - 1);
fileNameTextBox.Text = fileName;
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
}
在上述代码中,在保存的全路径名称 saveFilePath 通过符号“\”来区分文
件路径及文件名。当更改 filePathTextBox 控件及 fileNameTextBox 控件中的文字
内容时,相应要更改全局变量 filePath 和 fileName,所以为 filePathTextBox 控件
及 fileNameTextBox 控件的 TextChanged()事件添加如下代码:
private void filePathTextBox_TextChanged(object sender,
EventArgs e)
{
filePath = filePathTextBox.Text;
}
private void fileNameTextBox_TextChanged(object sender,
EventArgs e)
{
fileName = fileNameTextBox.Text;
}
创 建 一 个 新 的 Shp 数 据 文 件 可 以 通 过 IWorkspaceFactory 接 口 和
IFeatureWorkspace 接口来实现,如下为“创建”按钮的 Click()事件添加的代码:
private void 创建_Click(object sender, EventArgs e)
{
IWorkspaceFactory pShpWksFact = new
ShapefileWorkspaceFactory();
IFeatureWorkspace pFeatWks;
pFeatWks =
(IFeatureWorkspace)pShpWksFact.OpenFromFile(filePath, 0);
const string strShapeFieldName = "Shape";
//定义属性字段
IFields pFields;
IFieldsEdit pFieldsEdit;
pFields = new FieldsClass();
pFieldsEdit = (IFieldsEdit)pFields;
IField pField = new FieldClass();
IFieldEdit pFieldEdit = new FieldClass();
QQ:289700062
第 4 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
pFieldEdit.Name_2 = strShapeFieldName;
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
pField = (IField)pFieldEdit;
//定义几何属性
IGeometryDef pGeomDef = new GeometryDefClass();
IGeometryDefEdit pGeomDefEdit = new GeometryDefClass();
pGeomDefEdit = (IGeometryDefEdit)pGeomDef;
switch (shpTypeComboBox.Text)
{
case "Point":
pGeomDefEdit.GeometryType_2 =
esriGeometryType.esriGeometryPoint;
break;
case "Polyline":
pGeomDefEdit.GeometryType_2 =
esriGeometryType.esriGeometryPolyline;
break;
case "Polygon":
pGeomDefEdit.GeometryType_2 =
esriGeometryType.esriGeometryPolygon;
break;
case "MultiPoint":
pGeomDefEdit.GeometryType_2 =
esriGeometryType.esriGeometryMultipoint;
break;
case "MultiPatch":
pGeomDefEdit.GeometryType_2 =
esriGeometryType.esriGeometryMultiPatch;
break;
}
pGeomDefEdit.SpatialReference_2 = (ISpatialReference)new
UnknownCoordinateSystem();
pFieldEdit.GeometryDef_2 = pGeomDef;
pFieldsEdit.AddField(pField);
pFields = (IFields)pFieldsEdit;
IFeatureClass pFeatureClass;
pFeatureClass = pFeatWks.CreateFeatureClass(fileName,
pFields, null, null, esriFeatureType.esriFTSimple, strShapeFieldName,
"");
//添加新建的数据至Map中
axMapControl.AddShapeFile(filePath, fileName);
this.Hide();
QQ:289700062
第 5 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
}
具体来说,创建Shp 文件的过程分为四步:第一步,建立 IWorkspaceFactory
和 IFeatureWorkspace 工作空间(根据文件路径);第二步,定义数据的属性字段,
默认要为其创建一个名为“Shape”的属性字段用于表示其几何形状,该字段格
式 esriFieldType.esriFieldTypeGeometry;第三步,定义几何属性,在前面已经指
定了 Shp 数据的类型(点、线、面),在此需要定义其 GeometryType 并指定空间
参考系统,默认为 UnknownCoordinateSystem;第四步,在 IFeatureWorkspace 工
作空间中创建 Shp 数据文件。
三、添加数据
在添加几何数据时,先定义 IFeature 对象,如下:
IFeature pFeature = pFeatureClass.CreateFeature();
如果创建点数据,则直接定义一个 IPoint 对象用于表示点,并设置该点的
位置,如下:
IPoint pPoint = new PointClass();
pPoint.PutCoords(pointX, pointY);
如果为线或面数据,它们的边界由一系列点组成,可以使用 IPointCollection
接口来实现。
添加属性数据之前,必须保证有对应的属性字段,由于新建数据并没有添
加其他的属性字段,所以根据要求 Excel 表格中指定的数据列来添加相应的字段。
添加属性字段主要采用 IField 接口来实现,如下定义:
IField pfield = new FieldClass();
然后定义一个 IFieldEdit 对象来修改或设置字段相应信息(注意:对 IField
对象是无法直接修改的,属性字段的修改必须通过 IFieldEdit 来完成),如下定义:
IFieldEdit pfieldEdit = new FieldClass();
然后根据修改或添加需要,对 IFieldEdit 对象的属性进行相应修改,如下:
pfieldEdit.Name_2 = “新的字段”;
pfieldEdit.Type_2 =
esriFieldType.esriFieldTypeString;
其中,IFieldEdit 的 Name_2 属性表示设置字段名称(注意:不是 Name 属
性,修改属性字段名称应使用 Name_2 属性),Type_2 属性表示设置属性字段的
数据类型(如 String、Float、Double 等)。
修 改 或 设 置 某 个 数 据 ( IFeature ) 的 某 个 属 性 值 可 以 直 接 通 过
IFeature.set_Value()方法来修改,也可以通过定义一个 IField 对象来修改,如下直
接使用 IFeature.set_Value()方法来修改的代码:
pFeature.set_Value(pFeature.Fields.FindField(fieldName),
dataRow.Cells[fieldName].Value.ToString());
新建一个窗体,设置其 Name 为 CreateShpFileBaseOnExcel,为其添加如下
图所示控件:
QQ:289700062
第 6 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
其中大部分控件与前面介绍的新建 Shp 文件类似,在此介绍 xComboBoxEx
控件用于指定生成的 Shp 中点数据的 X 坐标值为 Excel 工作表第几列的单元格数
值,同样 yComboBoxEx 控件用于指定点数据的 Y 坐标值为 Excel 工作表中哪一
列的单元格数值,fieldListBox 列表控件列出了 Excel 工作表中所有的列,若需要
添加这些列的值为相应点 数据的属性值,则点击 按钮将该列添加到右侧
addFieldListBox 列表控件中。当然,若不需要添加该列值,也可用点击 按钮
将该列从右侧 addFieldListBox 列表控件中移到左侧 fieldListBox 列表控件。为这
两个按钮 addFieldButtonX 和 delFieldButtonX 的 Click()事件添加如下代码:
private void delFieldButtonX_Click(object sender, EventArgs e)
{
if (addFieldListBox.SelectedItem != null)
{
fieldListBox.Items.Add(addFieldListBox.SelectedItem);
addFieldListBox.Items.Remove(addFieldListBox.SelectedItem);
}
}
private void addFieldButtonX_Click(object sender, EventArgs e)
{
if (fieldListBox.SelectedItem != null)
{
addFieldListBox.Items.Add(fieldListBox.SelectedItem);
fieldListBox.Items.Remove(fieldListBox.SelectedItem);
QQ:289700062
第 7 页 共 16 页
Email:xwebsite@163.com
土木水电学院 3S 实验室 肖泽云
}
}
同样,定义全局变量并修改构造函数,如下代码:
private DevComponents.DotNetBar.Controls.DataGridViewX
excelDataGridViewX;
private AxMapControl axMapControl;
private string filePath;
private string fileName;
public CreateShpFileBaseOnExcel(AxMapControl _axMapControl,
DevComponents.DotNetBar.Controls.DataGridViewX _excelDataGridViewX)
{
axMapControl = _axMapControl;
excelDataGridViewX=_excelDataGridViewX;
InitializeComponent();
}
其中,excelDataGridViewX 变量用于表示 Excel 工作表中获取的数据表,接
下来要获取数据(如点的 X 坐标、Y 坐标等)都直接从该变量中获取。
在窗体的 Load()事件中,为 xComboBoxEx、yComboBoxEx 和 fieldListBox
等控件添加项,如下代码:
private void CreateShpFile_Load(object sender, EventArgs e)
{
for (int i = 0; i < excelDataGridViewX.Columns.Count; i++)
{
string
headerString=excelDataGridViewX.Columns[i].HeaderText;
xComboBoxEx.Items.Add(headerString);
yComboBoxEx.Items.Add(headerString);
fieldListBox.Items.Add(headerString);
}
}
此时,根据 Excel 表格建立 Shp 文件在新建 Shp 文件的基础上增加了添加
属性字段、添加几何数据和添加属性数据,如下代码所示:
private void 创建_Click(object sender, EventArgs e)
{
try
{
IWorkspaceFactory pShpWksFact = new
ShapefileWorkspaceFactory();
IFeatureWorkspace pFeatWks;
pFeatWks =
(IFeatureWorkspace)pShpWksFact.OpenFromFile(filePath, 0);
const string strShapeFieldName = "Shape";
QQ:289700062
第 8 页 共 16 页
Email:xwebsite@163.com