先打一个广告:我的独立博客网址是:http://wuyouqiang.sinaapp.com/。
我的新浪微博:http://weibo.com/freshairbrucewoo。
欢迎大家相互交流,共同提高技术。
这一篇博文终于要真正接触操作空间数据了,今天要完成讲解的功能就是导入Shape格式和MDB的空间数据格式到基于ArcSDE空间数据库插件的Oracle10g数据库中。这里面涉及到的功能和操作非常的多,我准备用两篇文章来介绍,这一篇介绍导入前的准备工作和Shape格式的导入。对于空间数据和ArcGIS没有基础知识的可以先了解和学习一下这方面的知识,在我这个项目系列博文中也有一些这方面的基础知识介绍,可以看看!下面开始具体介绍这个过程。
1.选择导入的格式
当然这里只支持两种格式(Shape和MDB),当然可以支持更多的空间数据格式,我在一篇博文专门介绍了八种数据格式的空间数据。为什么需要各种空间数据格式的导入呢?因为空间数据的来源多种多样,具体来源可以到google搜索。为了统一管理各种格式或各种来源的空间数据格式,也为了从集中的空间数据中发现更大的商业信息,所以必须找一种统一的格式来管理,我这个项目当然就是采用的基于空间数据库插件的Oracle10g,采用这种方式主要是想借用RDBMS的强大功能。
实现选择格式的思路相当的简单,就是用一个界面采用单选按钮来选择,具体实现选择的功能如下:
/// <summary> /// 下一步,选择导入空间数据的格式,支持Shape和MDB格式 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void nextBtn_Click(object sender, EventArgs e) { this.Close(); if (radioButton1.Checked) { //导入为Shape空间数据格式 FrmImportShapeFile faif = new FrmImportShapeFile(); faif.ShowDialog(); } else { //导入为MDB空间数据格式 FrmImportMDBFile fim = new FrmImportMDBFile(); fim.ShowDialog(); } }
从代码可以看出我们可以通过选择会进入下一个具体导入的界面,下一个界面的功能就是很复杂了。主要复杂的功能是对于需要导入的空间数据格式的检查,包括完整性检查、与数据库中已有表结构的数据结构是否一一对应或者能够兼容----如字段个数、字段类型、字段长度等。
2.Shape空间数据格式的导入
2.1 变量定义与初始化(在构造函数中初始化,也可以在对话框的Load函数中),见如下代码:
private IFeatureWorkspace pFW;//工作空间 public int sc_id = 4326;//空间参考系的ID private bool bSelectField = false; private Dictionary<string, IFields> fieldDic;//用于保存需要检查各个字段 public FrmImportShapeFile() { InitializeComponent(); if (pFW == null) { pFW = MapOperation.GetFeatrueWorkspace(); } fieldDic = new Dictionary<string, IFields>(); }
2.2 回到上一步:选择导入格式界面
/// <summary> /// 回到上一步:就是选择导入空间数据选择界面 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void preBtn_Click(object sender, EventArgs e) { FrmSelectFileFormat fsff = new FrmSelectFileFormat(); fsff.index = 0; fsff.Show(); this.Close(); }
2.3 使能相应按钮功能的复选按钮功能
/// <summary> /// 根据复选按钮使能相应的其他功能按钮 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void checkBox1_CheckedChanged(object sender, EventArgs e) { if (checkBox1.Checked)//使能选择字段 { bSelectField = true; selectUploadFieldBtn.Enabled = true; checkUploadFieldBtn.Enabled = true; } else { bSelectField = false; selectUploadFieldBtn.Enabled = false; checkUploadFieldBtn.Enabled = false; } }
2.4 转换导入Shape文件数据到SDE数据库中
/// <summary> /// 转换导入Shape文件数据到SDE数据库中 /// </summary> /// <param name="strPath">Shape文件路径</param> /// <param name="strFile">Shape文件名称,到后缀名的</param> /// <param name="strTableName">导入到SDE中的表名称</param> private void ConvertShpToSDE(string strPath, string strFile, string strTableName) { //创建一个输出shp文件的工作空间 IWorkspaceFactory pShpWorkspaceFactory = new ShapefileWorkspaceFactoryClass(); IWorkspace pSourceWS = pShpWorkspaceFactory.OpenFromFile(strPath, 0); /* //1.遍历数据集中的要素类并导入 IEnumDataset enumDs = pSourceWS.get_Datasets(esriDatasetType.esriDTFeatureDataset); IFeatureDataset featureDs = enumDs.Next() as IFeatureDataset; while (featureDs != null) { IFeatureClass featClass; IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer; for (int i = 0; i < fcContainer.ClassCount; i++) { featClass = fcContainer.get_Class(i); if (MapOperation.FindClassByName(workspace as IWorkspace, null, featClass.AliasName) != null) { MapOperation.AddFeatureClassToSDE(pSourceWS as IWorkspace, workspace as IWorkspace, featClass.AliasName, featClass.AliasName); } else { MapOperation.ConvertFeatureClass(pSourceWS as IWorkspace, workspace as IWorkspace, featClass.AliasName, featClass.AliasName); } } featureDs = enumDs.Next() as IFeatureDataset; } //2.遍历游离的要素类并导入 enumDs = pSourceWS.get_Datasets(esriDatasetType.esriDTFeatureClass); IFeatureClass featCl = enumDs.Next() as IFeatureClass; while (featCl != null) { if (MapOperation.FindClassByName(workspace as IWorkspace, null, featCl.AliasName) != null) { MapOperation.AddFeatureClassToSDE(pSourceWS as IWorkspace, workspace as IWorkspace, featCl.AliasName, featCl.AliasName); } else { MapOperation.ConvertFeatureClass(pSourceWS as IWorkspace, workspace as IWorkspace, featCl.AliasName, featCl.AliasName); } featCl = enumDs.Next() as IFeatureClass; }*/ IFeatureWorkspace pSourceFWS = (IFeatureWorkspace)pSourceWS; SqlHelper sh = new SqlHelper(); IFeatureClass pFC = pSourceFWS.OpenFeatureClass(strFile); IWorkspace2 pW2 = pFW as IWorkspace2; string sql = string.Empty; //判断是否在SDE中已经存在要素类,存在就追加,否则新建 if (pW2.get_NameExists(esriDatasetType.esriDTFeatureClass, strTableName)) { //是否选择了上载字段 if (fieldDic.ContainsKey(strFile)) { //选择了上载字段,就将对应字段插入到要素类中 AddFeatureClassToSDE(pSourceFWS, pFW, strFile, strTableName); } else { //没有就将全部字段插入要素类中 MapOperation.AddFeatureClassToSDE(pSourceWS, pFW as IWorkspace, pFC.AliasName, strTableName); } } else { //新建导入,在数据字典中插入一条游离图层的记录 MapOperation.ConvertFeatureClass(pSourceWS as IWorkspace, pFW as IWorkspace, pFC.AliasName, strTableName, sc_id); //MapOperation.CreateFeatureClass(pFW as IWorkspace2, null, strTableName, pFC.Fields, null, null, ""); //MapOperation.AddFeatureClassToSDE(pSourceWS, pFW as IWorkspace, pFC.AliasName, strTableName); sql = "select * from layer where table_name='" + strTableName + "'"; if (sh.GetRecordCount(sql) > 0) { return; } sql = "select max(ID) from layer"; OracleDataReader odr = sh.ReturnDataReader(sql); int result = 0; if (odr.Read()) { result = int.Parse(odr[0].ToString()); result += 1; } Hashtable ht = new Hashtable(); ht.Add("ID", result); sql = "select id from element where name='游离图层'"; odr = sh.ReturnDataReader(sql); if (odr.Read()) { ht.Add("PID", int.Parse(odr[0].ToString())); } else { ht.Add("PID", 2025); } ht.Add("TABLE_NAME", strTableName); ht.Add("TABLE_MAPNAME", strTableName); ht.Add("DESCRIPTION", "无辅助信息!"); if (pFC.ShapeType == esriGeometryType.esriGeometryPoint || pFC.ShapeType == esriGeometryType.esriGeometryMultipoint) { ht.Add("TYPE", "PT"); } else if (pFC.ShapeType == esriGeometryType.esriGeometryLine || pFC.ShapeType == esriGeometryType.esriGeometryPolyline) { ht.Add("TYPE", "PL"); } else if (pFC.ShapeType == esriGeometryType.esriGeometryPolygon) { ht.Add("TYPE", "PY"); } else { ht.Add("TYPE", "PY"); } sh.Insert("layer", ht); } }
上面的代码比较复杂,其中涉及到一个功能就是是否选择一些字段追加到以后的数据库表中,如果不是就全部导入,否则就是执行部分导入功能,全部导入功能是在前面介绍的空间数据操作类((1)MapOperation.AddFeatureClassToSDE(pSourceWS, pFW as IWorkspace, pFC.AliasName, strTableName);追加功能。(2)MapOperation.ConvertFeatureClass(pSourceWS as IWorkspace, pFW as IWorkspace, pFC.AliasName, strTableName, sc_id);新建一个表导入)介绍实现的,就不在具体介绍了,下面介绍部分追求字段功能,如下:
/// <summary> /// 将Shape文件中要素类选择的字段转换追加到sde数据库已有的要素类中 /// </summary> /// <param name="pSourceFW">源要素工作空间</param> /// <param name="pTargetFW">目标要素工作空间</param> /// <param name="nameOfSourceFeatureClass">源要素类名称</param> /// <param name="nameOfTargetFeatureClass">目标要素类名称</param> public void AddFeatureClassToSDE(IFeatureWorkspace pSourceFW, IFeatureWorkspace pTargetFW, string nameOfSourceFeatureClass, string nameOfTargetFeatureClass) { //打开源要素类 IFeatureClass pSourceFC = pSourceFW.OpenFeatureClass(nameOfSourceFeatureClass); //打开目标要素类 IFeatureClass pTargetFC = pTargetFW.OpenFeatureClass(nameOfTargetFeatureClass); //遍历源要素类的要素并依次插入目标要素类 IFeatureCursor pFeaCursor = pSourceFC.Search(null, false); IFeature pFeature = pFeaCursor.NextFeature(); IField pField = new FieldClass(); int iIndex = 0; while (pFeature != null) { IFeature tempFeature = pTargetFC.CreateFeature(); tempFeature.Shape = pFeature.Shape; try { //添加字段值 IFields pFs = fieldDic[nameOfSourceFeatureClass]; for (int j = 0; j < pFs.FieldCount; j++) { pField = pFs.get_Field(j); iIndex = tempFeature.Fields.FindField(pField.Name); if (pField.Editable && iIndex != -1) { tempFeature.set_Value(iIndex, pFeature.get_Value(j)); } } tempFeature.Store(); } catch (System.Exception ex) { MessageBox.Show(ex.Message); return; } pFeature = pFeaCursor.NextFeature(); } }
2.5 导入要素类到某一个具体的工作空间
/// <summary> /// 导入要素类到工作空间 /// </summary> /// <param name="apFD"></param> /// <param name="pathName"></param> /// <param name="fileName"></param> private void ImportFeatureClassToWorkSpace(IFeatureDataset apFD, string pathName, string fileName) { IWorkspaceName pInWorkspaceName; IFeatureDatasetName pOutFeatureDSName; IFeatureClassName pInFeatureClassName; IDatasetName pInDatasetName; IFeatureClassName pOutFeatureClassName; IDatasetName pOutDatasetName; long iCounter; IFields pOutFields, pInFields; IFieldChecker pFieldChecker; IField pGeoField; IGeometryDef pOutGeometryDef; IGeometryDefEdit pOutGeometryDefEdit; IName pName; IFeatureClass pInFeatureClass; IFeatureDataConverter pShpToClsConverter; IEnumFieldError pEnumFieldError = null; //得到一个输入SHP文件的工作空间, pInWorkspaceName = new WorkspaceNameClass(); pInWorkspaceName.PathName = pathName; pInWorkspaceName.WorkspaceFactoryProgID = "esriCore.ShapefileWorkspaceFactory.1"; //创建一个新的要素类名称,目的是为了以来PNAME接口的OPEN方法打开SHP文件 pInFeatureClassName = new FeatureClassNameClass(); pInDatasetName = (IDatasetName)pInFeatureClassName; pInDatasetName.Name = fileName; pInDatasetName.WorkspaceName = pInWorkspaceName; //打开一个SHP文件,将要读取它的字段集合 pName = (IName)pInFeatureClassName; pInFeatureClass = (IFeatureClass)pName.Open(); //通过FIELDCHECKER检查字段的合法性,为输入要素类获得字段集合 pInFields = pInFeatureClass.Fields; pFieldChecker = new FieldChecker(); pFieldChecker.Validate(pInFields, out pEnumFieldError, out pOutFields); //通过循环查找几何字段 pGeoField = null; for (iCounter = 0; iCounter < pOutFields.FieldCount; iCounter++) { if (pOutFields.get_Field((int)iCounter).Type == esriFieldType.esriFieldTypeGeometry) { pGeoField = pOutFields.get_Field((int)iCounter); break; } } //得到几何字段的几何定义 pOutGeometryDef = pGeoField.GeometryDef; //设置几何字段的空间参考和网格 pOutGeometryDefEdit = (IGeometryDefEdit)pOutGeometryDef; pOutGeometryDefEdit.GridCount_2 = 1; pOutGeometryDefEdit.set_GridSize(0, 1500000); //创建一个新的要素类名称作为可用的参数 pOutFeatureClassName = new FeatureClassNameClass(); pOutDatasetName = (IDatasetName)pOutFeatureClassName; pOutDatasetName.Name = pInDatasetName.Name; //创建一个新的数据集名称作为可用的参数 pOutFeatureDSName = (IFeatureDatasetName)new FeatureDatasetName(); //因为ConvertFeatureClass需要传入一个IFeatureDatasetName的参数, //通过它确定导入生成的要素类的工作空间和要素集合 //情况一 //如果本函数的参数(IFeatureDataset)是一个确切的值, //那么将它转换成IFeatureDatasetName接口就可以了。因为ConvertFeatureClass根据该接口就 //可以确定工作空间和要素集合,IFeatureClassName就可以不考虑上述问题 //情况二 //如果本函数的参数(IFeatureDataset)是一个NULL值,表示要创建独立要素类, //那么ConvertFeatureClass函数无法根据IFeatureDatasetName参数确定工作空间和要素集合 //这个时候需要IFeatureClassName参数确定工作空间和要素集合 //如果参数的值是NULL,说明要创建独立要素类 if (apFD == null) { //创建一个不存在的要素集合pFDN,通过它将IFeatureClassName和工作空间连接起来, //而ConvertFeatureClass函数并不使用该变量作为参数, IFeatureDatasetName pFDN = new FeatureDatasetNameClass(); IDatasetName pDN = (IDatasetName)pFDN; IDataset pDS = (IDataset)pFW; pDN.WorkspaceName = (IWorkspaceName)pDS.FullName; pDN.Name = pDS.Name; pOutFeatureClassName.FeatureDatasetName = (IDatasetName)pFDN; //将pOutFeatureDSName设置为Null,将它做为参数给ConvertFeatureClass函数, //因为IFeatureClassName本身已经和工作空间关联了,生成的 //要素类在工作空间的根目录下,即独立要素类 pOutFeatureDSName = null; } else//创建的要素类是在给定的参数(要素集合)下 { pOutFeatureDSName = (IFeatureDatasetName)apFD.FullName; } //开始导入 pShpToClsConverter = new FeatureDataConverterClass(); pShpToClsConverter.ConvertFeatureClass(pInFeatureClassName, null, pOutFeatureDSName, pOutFeatureClassName, pOutGeometryDef, pOutFields, "", 1000, 0); }
2.6 添加一个Shape文件到需要导入的空间列表中(包括具体的信息,以供查看和选择):
/// <summary> /// 添加一个Shape文件到DataGridViewX1中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void addFileBtn_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); //打开SHP文件 string StrFilter = "SHP文件(.shp) | *.shp"; ofd.Filter = StrFilter; string ImportShapeFileName; if (ofd.ShowDialog() == DialogResult.OK) { ImportShapeFileName = ofd.FileName; } else { return; } string ImportFileName = System.IO.Path.GetFileName(ImportShapeFileName); string ImportFileShortName = System.IO.Path.GetFileNameWithoutExtension(ImportShapeFileName); string ImportFilePath = System.IO.Path.GetDirectoryName(ImportShapeFileName); //导入Shape文件的相关信息到空间中 object[] obj = new object[3]; obj[0] = ImportFileName; obj[1] = ImportFileShortName; obj[2] = ImportFilePath; dataGridViewX1.Rows.Add(obj); }
2.7 和上一个功能类型,不过这个是添加一个目录,即这目录下的所有Shape文件都会被添加到控件列表中。
/// <summary> /// 添加一个目录下的所有Shape文件到DataGridViewX1中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void addFolderBtn_Click(object sender, EventArgs e) { FolderBrowserDialog folder = new FolderBrowserDialog(); if (folder.ShowDialog() == DialogResult.OK) { string strPath = folder.SelectedPath; if (strPath == "") { return ; } string []fileNames = Directory.GetFiles(strPath); string strTemp; foreach (string str in fileNames) { strTemp = str.Remove(0, str.LastIndexOf('\\')+1); if (strTemp.Substring(strTemp.IndexOf('.')) == ".shp") { object[] obj = new object[3]; obj[0] = strTemp; strTemp = strTemp.Remove(strTemp.IndexOf('.')); obj[1] = strTemp; obj[2] = strPath; dataGridViewX1.Rows.Add(obj); } } } }
2.8从显示Shape文件信息的控件列表中删除一个Shape文件的信息,就不需要导入的Shape文件可以先删除,免得影响视线。
/// <summary> /// 从DataGridViewX1删除一个文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void delFileBtn_Click(object sender, EventArgs e) { if (dataGridViewX1.CurrentRow.Index >= 0) { dataGridViewX1.Rows.Remove(dataGridViewX1.CurrentRow); } else { MessageBox.Show("请选择一个要删除的行!"); return ; } }
2.9完成导入Shape文件的按钮功能
/// <summary> /// 完成导入的功能,当所有准备和检查功能已经做完并且通过就可以通过完成按钮完成导入了 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void finishBtn_Click(object sender, EventArgs e) { int fileCount = dataGridViewX1.Rows.Count; //多个Shape文件内容依次导入 for (int i = 0; i < fileCount; ++i) { // string str = dataGridViewX1.Rows[i].Cells[1].Value.ToString(); // ImportFeatureClassToWorkSpace(null,dataGridViewX1.Rows[i].Cells[2].Value.ToString(), str); ConvertShpToSDE(dataGridViewX1.Rows[i].Cells[2].Value.ToString(), dataGridViewX1.Rows[i].Cells[0].Value.ToString(), dataGridViewX1.Rows[i].Cells[1].Value.ToString()); } LogHelp.writeLog(FrmMain.username, "空间数据管理", "空间数据Shape格式转换导入成功"); MessageBox.Show("导入数据完成!"); Close(); }
真正的导入函数是前面已经介绍过的ConvertShpToSDE函数。
2.10 把控件中的Shape文件信息保存起来(配置文件)以便下一次直接导入这些文件。
/// <summary> /// 保存DataGridViewX1的文件列表到配置文件中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void saveSetBtn_Click(object sender, EventArgs e) { System.IO.FileStream fs = new System.IO.FileStream(Directory.GetCurrentDirectory()+"\\set.ini", FileMode.Create); StreamWriter sw = new StreamWriter(fs); int fileCount = dataGridViewX1.Rows.Count - 1; //开始写入 for (int i = 0; i < fileCount; ++i) { string str = dataGridViewX1.Rows[i].Cells[0].Value.ToString(); sw.WriteLine(str); str = dataGridViewX1.Rows[i].Cells[1].Value.ToString(); sw.WriteLine(str); str = dataGridViewX1.Rows[i].Cells[2].Value.ToString(); sw.WriteLine(str); } //清空缓冲区 sw.Flush(); //关闭流 sw.Close(); fs.Close(); }
2.11读取配置文件的文件列表加载到控件中
/// <summary> /// 读取配置文件的文件列表加载到DataGridViewX1中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void readSetBtn_Click(object sender, EventArgs e) { dataGridViewX1.Rows.Clear(); StreamReader objReader = new StreamReader(Directory.GetCurrentDirectory() + "\\set.ini"); string sLine = ""; while ((sLine = objReader.ReadLine()) != null) { object[] obj = new object[3]; obj[0] = sLine; obj[1] = objReader.ReadLine(); obj[2] = objReader.ReadLine(); dataGridViewX1.Rows.Add(obj); } objReader.Close(); }
2.12 选择空间参考系(空间数据都有的)
/// <summary> /// 选择空间参考系 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void selectBtn_Click(object sender, EventArgs e) { FrmSelectSpatialReference fssr = new FrmSelectSpatialReference(); fssr.ShowDialog(); if (fssr.bOk) { spatialReTxt.Text = fssr.sc_id.ToString(); sc_id = fssr.sc_id; } }
2.13选择上载字段(没有选择的将不会导入到数据库中)
/// <summary> /// 选择上载字段 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void selectUploadFieldBtn_Click(object sender, EventArgs e) { if (dataGridViewX1.CurrentRow == null) { MessageBox.Show("选择一行!"); return; } string strPath = dataGridViewX1.CurrentRow.Cells[2].Value.ToString(); string strName = dataGridViewX1.CurrentRow.Cells[0].Value.ToString(); FrmSelectField fsf = new FrmSelectField(); fsf.InitDataGridView(); //创建一个输出shp文件的工作空间 IWorkspaceFactory pShpWorkspaceFactory = new ShapefileWorkspaceFactoryClass(); IWorkspace pSourceWS = pShpWorkspaceFactory.OpenFromFile(strPath, 0); IFeatureWorkspace pSourceFWS = (IFeatureWorkspace)pSourceWS; IFeatureClass pFC = pSourceFWS.OpenFeatureClass(strName); object[] obj = new object[4]; for (int i = 0; i < pFC.Fields.FieldCount; i++) { IField field = pFC.Fields.get_Field(i); obj[0] = false; obj[1] = field.Name; obj[2] = field.Type; obj[3] = field.Length; fsf.AddRowToDataGridView(obj); } fsf.ShowDialog(); //确实确定了选择,就把选择的结果和文件名对应保存起来。 if (fsf.bSelect) { IFields pFds = new FieldsClass(); IFieldsEdit pFdsEdit = pFds as IFieldsEdit; for (int i = 0; i < pFC.Fields.FieldCount; i++) { if (fsf.RowsIsSelect(i)) { IField field = pFC.Fields.get_Field(i); pFdsEdit.AddField(field); } } if (fieldDic.ContainsKey(strName)) { fieldDic.Remove(strName); } fieldDic.Add(strName, pFds); } }
2.14检查导入字段是否满足要求,不满足就提示哪些不满足,满足以后才能执行导入功能。
/// <summary> /// 检查字段按钮功能,检查需要导入字段是否满足要求 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void checkUploadFieldBtn_Click(object sender, EventArgs e) { if (dataGridViewX1.CurrentRow == null) { MessageBox.Show("选择一行!"); return; } string strPath = dataGridViewX1.CurrentRow.Cells[2].Value.ToString(); string strTableName = dataGridViewX1.CurrentRow.Cells[1].Value.ToString(); string strName = dataGridViewX1.CurrentRow.Cells[0].Value.ToString(); /* IWorkspace2 pW = pFW as IWorkspace2; if (!pW.get_NameExists(esriDatasetType.esriDTFeatureClass, strTableName)) { MessageBox.Show("数据库中不存在此表结构,不能检查!"); return; } //1.遍历数据集中的要素类找到并打开目标要素类 IEnumDataset enumDs = (pFW as IWorkspace).get_Datasets(esriDatasetType.esriDTFeatureDataset); IFeatureDataset featureDs = enumDs.Next() as IFeatureDataset; IFeatureClass pSDEFC = null; while (featureDs != null) { IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer; for (int i = 0; i < fcContainer.ClassCount; i++) { IFeatureClass pTempFC = fcContainer.get_Class(i); string strTemp = pTempFC.AliasName; if (pTempFC.AliasName.IndexOf('.') >= 0) { strTemp = strTemp.Substring(strTemp.IndexOf('.')+1); } if (strTemp.ToUpper() == strTableName.ToUpper()) { pSDEFC = fcContainer.get_Class(i); break; } } if (pSDEFC != null) { break; } featureDs = enumDs.Next() as IFeatureDataset; } //2.遍历游离的要素类 if (pSDEFC == null) { enumDs = (pFW as IWorkspace).get_Datasets(esriDatasetType.esriDTFeatureClass); IFeatureClass pTempFC = enumDs.Next() as IFeatureClass; while (pTempFC != null) { string strTemp = pTempFC.AliasName; if (pTempFC.AliasName.IndexOf('.') >= 0) { strTemp = strTemp.Substring(strTemp.IndexOf('.')+1); } if (strTemp.ToUpper() == strTableName.ToUpper()) { pSDEFC = pTempFC; break; } pTempFC = enumDs.Next() as IFeatureClass; } } */ SqlHelper sh = new SqlHelper(); string sql = "select * from jcsjk_fielddefine where table_name='" + strTableName.ToLower() + "'"; if (sh.GetRecordCount(sql) <= 0) { MessageBox.Show("没有定义该数据标准,不能检查!"); return; } if (!fieldDic.ContainsKey(strName)) { if (MessageBox.Show("此文件还没有选择上载字段,默认全部上载!是否继续检查?", "提示信息", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { IWorkspaceFactory pShpWorkspaceFactory = new ShapefileWorkspaceFactoryClass(); IWorkspace pSourceWS = pShpWorkspaceFactory.OpenFromFile(strPath, 0); IFeatureWorkspace pSourceFWS = (IFeatureWorkspace)pSourceWS; IFeatureClass pFC = pSourceFWS.OpenFeatureClass(strName); if (CheckFields(pFC.Fields, strTableName)) { MessageBox.Show("字段匹配"); } else { MessageBox.Show("字段不匹配"); } } } else { if (CheckFields(fieldDic[strName], strTableName)) { MessageBox.Show("字段匹配"); } else { MessageBox.Show("字段不匹配"); } } } /// <summary> /// 检查字段是否符合数据标准定义 /// </summary> /// <param name="pSourceFileds">字段集</param> /// <param name="strTableName">对应的标准名</param> /// <returns></returns> private bool CheckFields(IFields pSourceFileds, string strTableName) { SqlHelper sh = new SqlHelper(); string sql = "select * from jcsjk_fielddefine where table_name ='" + strTableName.ToUpper() + "' or table_name='" + strTableName.ToLower() + "'"; if (pSourceFileds.FieldCount != sh.GetRecordCount(sql)) { MessageBox.Show("字段数量不匹配!"); return false; } bool result = true; FrmFieldCheckResult ffcr = new FrmFieldCheckResult(); ffcr.InitDataGridView1(); ffcr.InitDataGridView2(); OracleDataReader odr = sh.ReturnDataReader(sql); object[] obj1 = new object[5]; object[] obj2 = new object[4]; for (int i = 0; i < pSourceFileds.FieldCount; i++) { odr.Read(); bool bMatch = true; if (odr["TYPE"].ToString() == "RowID") { IField pSourceField = pSourceFileds.get_Field(pSourceFileds.FindField("FID")); obj1[0] = pSourceField.Name; obj1[1] = pSourceField.Type; obj1[2] = pSourceField.Length; obj1[3] = pSourceField.IsNullable; obj2[0] = odr["NAME"].ToString(); obj2[1] = esriFieldType.esriFieldTypeOID; obj2[2] = odr["LENGTH"].ToString(); if (odr["ISNULL"].ToString() == "是") { obj2[3] = true; } else { obj2[3] = false; } if (obj1[1].ToString() != obj2[1].ToString() || obj1[2].ToString() != obj2[2].ToString() || obj1[3].ToString() != obj2[3].ToString()) { bMatch = false; result = false; } obj1[4] = bMatch; ffcr.AddRowToDataGridView1(obj1); ffcr.AddRowToDataGridView2(obj2); } else if (pSourceFileds.FindField(odr["NAME"].ToString()) >= 0) { IField pSourceField = pSourceFileds.get_Field(pSourceFileds.FindField(odr["NAME"].ToString())); obj1[0] = pSourceField.Name; obj1[1] = pSourceField.Type; obj1[2] = pSourceField.Length; obj1[3] = pSourceField.IsNullable; obj2[0] = odr["NAME"].ToString(); if (odr["TYPE"].ToString() == "RowID") { obj2[1] = esriFieldType.esriFieldTypeOID; } else if (odr["type"].ToString() == "整数型") { obj2[1] = esriFieldType.esriFieldTypeInteger; } else if (odr["type"].ToString() == "浮点型") { obj2[1] = esriFieldType.esriFieldTypeDouble; } else if (odr["type"].ToString() == "字符型") { obj2[1] = esriFieldType.esriFieldTypeString; } else if (odr["type"].ToString() == "图元") { obj2[1] = esriFieldType.esriFieldTypeGeometry; } obj2[2] = odr["LENGTH"].ToString(); if (odr["ISNULL"].ToString() == "是") { obj2[3] = true; } else { obj2[3] = false; } if (obj1[1].ToString() != obj2[1].ToString() || obj1[2].ToString() != obj2[2].ToString() || obj1[3].ToString() != obj2[3].ToString()) { bMatch = false; result = false; } obj1[4] = bMatch; ffcr.AddRowToDataGridView1(obj1); ffcr.AddRowToDataGridView2(obj2); } else { MessageBox.Show("字段名称不匹配!"); result = false; } } ffcr.ShowDialog(); return result; }
2.15根据已有的Shape文件,打开检查字段界面,选中一个具体的Shape文件就检查一个Shape文件,通过的就在控件中标示出来。
/// <summary> /// 检查文件字段,字段类型和长度 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void checkFileFieldBtn_Click(object sender, EventArgs e) { if (dataGridViewX1.CurrentRow == null) { MessageBox.Show("选择一行!"); return; } string strPath = dataGridViewX1.CurrentRow.Cells[2].Value.ToString(); string strName = dataGridViewX1.CurrentRow.Cells[0].Value.ToString(); FrmSelectField fsf = new FrmSelectField(); fsf.SetBtnVisible(false); fsf.Text = ((ButtonX)sender).Text; fsf.InitDataGridView(); //创建一个输出shp文件的工作空间 IWorkspaceFactory pShpWorkspaceFactory = new ShapefileWorkspaceFactoryClass(); IWorkspace pSourceWS = pShpWorkspaceFactory.OpenFromFile(strPath, 0); IFeatureWorkspace pSourceFWS = (IFeatureWorkspace)pSourceWS; IFeatureClass pFC = pSourceFWS.OpenFeatureClass(strName); object[] obj = new object[4]; for (int i = 0; i < pFC.Fields.FieldCount; i++) { IField field = pFC.Fields.get_Field(i); obj[0] = false; obj[1] = field.Name; obj[2] = field.Type; obj[3] = field.Length; fsf.AddRowToDataGridView(obj); } fsf.SetDataGridViewColumn(0); fsf.ShowDialog(); }
3.总结
空间数据的转换是比较复杂和繁琐的功能,需要考虑的方面非常多,只有细心的一点一滴的做好每一步才能出色的完成这些功能,尤其是数据格式的检查是最复杂的,必须一个一个字段去对比。
今天到此为止!