1. 程式人生 > >AE屬性表操作(1)

AE屬性表操作(1)

今天給大家分享一個AE屬性表操作的程式原始碼,希望對有需要的筒子一定的幫助,小弟倍感榮幸!


好了,廢話少說!首先說說實現了哪些操作吧……

實現的操作包括:1、開啟屬性表;2、編輯屬性表;3、增加屬性列;4、資料排序;5、欄位計算……

嗯,實現的功能目前就這些吧,後續還會繼續跟進,還望大家多多關注……下面就分功能說說我的實現方式吧……

1、開啟屬性表

屬性表的開啟是在TOC的右鍵選單中開啟的,首先新建一個類OpenAttribute,繼承BaseCommand,OpenAttribute類的原始碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.Controls;

namespace MapDemo
{
    public sealed class OpenAttribute : BaseCommand
    {
        IMapControl3 m_mapControl;
        AxMapControl _MapControl;

        public OpenAttribute(AxMapControl pMapControl)
        {
            base.m_caption = "檢視屬性表";
            _MapControl = pMapControl;
        }

        public override void OnClick()
        {
            formTable formtable = new formTable(_MapControl, m_mapControl);
            formtable.Show();

        }

        public override void OnCreate(object hook)
        {
            m_mapControl = (IMapControl3)hook;
        }
    }
}

解釋一下,AxMapControl引數是為了後面屬性表操作時重新整理檢視的。接著在toc右鍵事件中新增程式碼:
//檢視屬性表
            m_menuLayer.AddItem(new OpenAttribute(mapMain), -1, 2, false, esriCommandStyles.esriCommandStyleIconAndText);

如此這般,這般如此,我們期待的屬性表就出現了,效果呢比較醜陋,莫怪莫怪……


屬性表開啟之後呢,大家就看到了有關屬性表操作的一些功能了,不過呢,屬性表的大開的工作還尚未完成。接下來呢,新增如下引用:

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;

完了之後,定義一下變數:
AxMapControl _MapControl;
        IMapControl3 m_mapControl;
        public DataTable dt2;        
        ITableSort pTs;//處理排序
        bool up = true;
        int row_index = 0;
        int col_index = 0;
        public string strAddField = "";
        RowAndCol[] pRowAndCol = new RowAndCol[10000];
        int count = 0;

這個視窗的引數為:
ublic formTable(AxMapControl pMapControl,IMapControl3 pMapCtrl)
        {
            InitializeComponent();
            _MapControl = pMapControl;
            m_mapControl = pMapCtrl;
        }

這樣,下面就可以顯示屬性了,在form_load事件中寫如下程式碼:
private void formTable_Load(object sender, EventArgs e)
        {
            TableShow();
        }

此處,呼叫了TableShow方法,TableShow的程式碼如下:
public void TableShow()
        {
            ILayer pLayer = (ILayer)m_mapControl.CustomProperty;
            IFeatureLayer pFLayer = pLayer as IFeatureLayer;
            IFeatureClass pFeatureClass = pFLayer.FeatureClass;

            if (pFeatureClass == null) return;

            DataTable dt = new DataTable();
            DataColumn dc = null;

            for (int i = 0; i < pFeatureClass.Fields.FieldCount; i++)
            {

                dc = new DataColumn(pFeatureClass.Fields.get_Field(i).Name);

                dt.Columns.Add(dc);

            }

            IFeatureCursor pFeatureCuror = pFeatureClass.Search(null, false);
            IFeature pFeature = pFeatureCuror.NextFeature();

            DataRow dr = null;
            while (pFeature != null)
            {
                dr = dt.NewRow();
                for (int j = 0; j < pFeatureClass.Fields.FieldCount; j++)
                {
                    if (pFeatureClass.FindField(pFeatureClass.ShapeFieldName) == j)
                    {

                        dr[j] = pFeatureClass.ShapeType.ToString();
                    }
                    else
                    {
                        dr[j] = pFeature.get_Value(j).ToString();

                    }
                }

                dt.Rows.Add(dr);
                pFeature = pFeatureCuror.NextFeature();
            }
            gdvAttribute.DataSource = dt;
            dt2 = dt;
        }

這樣呢,屬性表的顯示就完成了。

2、新增欄位

先看看那個“新增欄位”按鈕的事件吧……
ILayer pLayer = (ILayer)m_mapControl.CustomProperty;
            IFeatureLayer pFLayer = pLayer as IFeatureLayer;
            formAddField formaddfield = new formAddField(pFLayer, gdvAttribute);
            formaddfield.Show();

此處,呼叫了窗體formAddField ,傳遞的引數是IFeatureLayer pFLayer 和DataGridView gdvAttribute,那麼,下面看看formAddField的設計以及實現


介面呢也是比較簡單,看看formAddField 的程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Controls;

namespace MapDemo
{
    public partial class formAddField : Form
    {
        private IFeatureLayer _FeatureLayer = null;
        private DataGridView _dgv;
        public formAddField(IFeatureLayer pFeatureLayer, DataGridView dgv)
        {
            InitializeComponent();
            _FeatureLayer = pFeatureLayer;
            _dgv = dgv;
        }

        private void formAddField_Load(object sender, EventArgs e)
        {
            this.cmbFieldType.Items.Add("長整型");
            this.cmbFieldType.Items.Add("短整型");
            this.cmbFieldType.Items.Add("浮點型");
            this.cmbFieldType.Items.Add("雙精度");
            this.cmbFieldType.Items.Add("文字型");
            this.cmbFieldType.Items.Add("日期型");
            this.cmbFieldType.SelectedIndex = 0;
        }

        /// <summary>
        /// 改變事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbFieldType_SelectedIndexChanged(object sender, EventArgs e)
        {
            string strFieldType = cmbFieldType.Text;
            switch (strFieldType)
            {
                case "長整型":
                    {
                        panelPrecision.Visible = true;
                        panelScale.Visible = false;
                        break;
                    }
                case "短整型":
                    {
                        panelPrecision.Visible = true;
                        panelScale.Visible = false;
                        break;
                    }
                case "浮點型":
                    {
                        panelPrecision.Visible = true;
                        panelScale.Visible = true;
                        break;
                    }
                case "雙精度":
                    {
                        panelPrecision.Visible = true;
                        panelScale.Visible = true;
                        break;
                    }
                case "文字型":
                    {
                        panelPrecision.Visible = true;
                        panelScale.Visible = false;
                        lblPrecision.Text = "長度";
                        break;
                    }
                default://日期型0
                    {
                        panelPrecision.Visible = false;
                        panelScale.Visible = false;
                        break;
                    }
            } 
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            string strFieldName = txtFieldName.Text;
            string strFieldType = cmbFieldType.Text;
            try
            {
                IFeatureLayer editAttributeLayer = _FeatureLayer;

                //Field collection
                IFieldsEdit pFieldsEdit;
                //獲取FeatureLayer
                IFeatureLayer pFeatureLayer = editAttributeLayer;

                //從FeatureLayer獲取工作空間
                IDataset pDataSet = pFeatureLayer.FeatureClass as IDataset;
                IWorkspace pWorkSpace = pDataSet.Workspace;
                //設定欄位屬性
                IField pNewField = new FieldClass();
                IFieldEdit pFieldEdit = pNewField as IFieldEdit;
                pFieldEdit.AliasName_2 = strFieldName;
                pFieldEdit.Name_2 = strFieldName;
                switch (strFieldType)
                {
                    case "長整型":
                    {
                        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeInteger;
                        pFieldEdit.Precision_2 = int.Parse(txtPrecision.Text);
                        break;
                    }
                    case "Class1.cs短整型":
                    {
                        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
                        pFieldEdit.Precision_2 = int.Parse(txtPrecision.Text);
                        break;
                    }
                    case "浮點型":
                    {
                        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeSingle;
                        pFieldEdit.Precision_2 = int.Parse(txtPrecision.Text);
                        pFieldEdit.Scale_2 = int.Parse(txtScale.Text);
                        break;
                    }
                    case "雙精度":
                    {
                        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
                        pFieldEdit.Precision_2 = int.Parse(txtPrecision.Text);
                        pFieldEdit.Scale_2 = int.Parse(txtScale.Text);
                        break;
                    }
                    case "文字型":
                    {
                        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
                        pFieldEdit.Length_2 = int.Parse(txtPrecision.Text);
                        break;
                    }
                    default://日期型0
                    {
                        pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDate;
                        break;
                    }
                }               
                //新增欄位
                try
                {
                    int theField = pFeatureLayer.FeatureClass.Fields.FindField(strFieldName);
                    if (theField == -1)
                    {
                        pFeatureLayer.FeatureClass.AddField(pFieldEdit);
                        MessageBox.Show("欄位新增成功!");
                    }
                    else
                    {
                        MessageBox.Show("欄位已經存在!");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Field " + pFieldEdit.Name + " was not added due to an error (" + ex.Message + " )");
                }

            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }            
            this.Close();
            RefreshTable refresh = new RefreshTable();
            refresh.Refresh(_dgv, _FeatureLayer);
        }

        private void btnCancle_Click(object sender, EventArgs e)
        {
            this.Close();
        }        
    }
}

首先,在窗體載入的時候將資料型別新增進去,之後在型別選擇改變時觸發其屬性控制控制元件的顯示或者改變,接下來就是最重要的新增欄位了,大家注意到了,在this.Close()之後,還呼叫了RefreshTable 的Refresh方法,傳遞的引數是datagridview _dgv和Ifeaturelayer _FeatureLayer,Refresh方法主要是實現新增自斷後顯示的重新整理,由於後面還有涉及到,所以,這個後面一併說。

3、編輯屬性並儲存

還是先看看那兩個按鈕的時間吧:
/// <summary>
        /// 編輯屬性,並定位到最後一行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolEditor_Click(object sender, EventArgs e)
        {
            gdvAttribute.ReadOnly = false;
            this.gdvAttribute.CurrentCell = this.gdvAttribute.Rows[this.gdvAttribute.Rows.Count - 2].Cells[0];
        }

 /// <summary>
        /// 儲存編輯
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolSave_Click(object sender, EventArgs e)
        {
            gdvAttribute.ReadOnly = true;
            ILayer pLayer = (ILayer)m_mapControl.CustomProperty;
            IFeatureLayer pFLayer = pLayer as IFeatureLayer;
            IFeatureClass pFeatureClass = pFLayer.FeatureClass;
            ITable pTable;
            //pTable = pFeatureClass.CreateFeature().Table;//很重要的一種獲取shp表格的一種方式         
            pTable = pFLayer as ITable;
            //將改變的記錄值傳給shp中的表
            int i = 0;
            while (pRowAndCol[i].Column != 0 || pRowAndCol[i].Row != 0)
            {
                IRow pRow;
                pRow = pTable.GetRow(pRowAndCol[i].Row);
                pRow.set_Value(pRowAndCol[i].Column, pRowAndCol[i].Value);
                pRow.Store();
                i++;
            }
            count = 0;
            for (int j = 0; j < i; j++)
            {
                pRowAndCol[j].Row = 0;
                pRowAndCol[j].Column = 0;
                pRowAndCol[j].Value = null;
            }
            MessageBox.Show("儲存成功!", "提示", MessageBoxButtons.OK);
        }

在儲存屬性表的時候,出現了pRowAndCol,對他的定義如下:
public struct RowAndCol
        {
            //欄位
            private int row;
            private int column;
            private string _value;

            //行屬性
            public int Row
            {
                get
                {
                    return row;
                }
                set
                {
                    row = value;
                }
            }
            //列屬性
            public int Column
            {
                get
                {
                    return column;
                }
                set
                {
                    column = value;
                }
            }
            //值屬性
            public string Value
            {
                get
                {
                    return _value;
                }
                set
                {
                    _value = value;
                }
            }
        }

4、刪除選擇

顧名思義,就是刪除選擇的行,這裡的選擇可以是多選,也可是單選,看看對應按鈕的事件吧:
/// <summary>
        /// 刪除行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolDelSelect_Click(object sender, EventArgs e)
        {
            if (((MessageBox.Show("確定要刪除嗎", "警告", MessageBoxButtons.YesNo)) == DialogResult.Yes))
            {
                ILayer pLayer = (ILayer)m_mapControl.CustomProperty;
                IFeatureLayer pFLayer = pLayer as IFeatureLayer;
                ITable pTable = pFLayer as ITable;
                IRow pRow = pTable.GetRow(row_index);
                pRow.Delete();
                TableShow();
                MessageBox.Show("刪除成功!", "提示", MessageBoxButtons.OK);
                _MapControl.ActiveView.Refresh();
            }
        }

此處,看看下面這個事件:
private void gdvAttribute_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            //記錄值一旦改變觸發此事件
            //在dataGridView中獲取改變記錄的行數,列數和記錄值
            pRowAndCol[count].Row = gdvAttribute.CurrentCell.RowIndex;
            pRowAndCol[count].Column = gdvAttribute.CurrentCell.ColumnIndex;
            pRowAndCol[count].Value = gdvAttribute.Rows[gdvAttribute.CurrentCell.RowIndex].Cells[gdvAttribute.CurrentCell.ColumnIndex].Value.ToString();
            count++;
        }

5、匯出Excel

首先得新增程式對Microsoft.Office.Interop.Excel的引用,新增完成之後方可匯出:
/// <summary>
        /// 匯出Excel
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolExpXLS_Click(object sender, EventArgs e)
        {
            ILayer pLayer = (ILayer)m_mapControl.CustomProperty;
            IFeatureLayer pFLayer = pLayer as IFeatureLayer;
            IFeatureClass pFeatureClass = pFLayer.FeatureClass;
            IFields pFields = pFeatureClass.Fields;
            ExportExcel(gdvAttribute, pFields);
        }

        private void ExportExcel(DataGridView myDGV, IFields pFields)
        {
            string saveFileName = "";
            SaveFileDialog saveDialog = new SaveFileDialog();
            saveDialog.DefaultExt = "xls";
            saveDialog.Filter = "Excel檔案|*.xls";
            saveDialog.ShowDialog();
            saveFileName = saveDialog.FileName;
            if (saveFileName.IndexOf(":") < 0) return; //被點了取消 

            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
            if (xlApp == null)
            {
                MessageBox.Show("無法建立Excel物件,可能您的機子未安裝Excel");
                return;
            }

            Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
            Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
            Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];//取得sheet1

            //寫入標題
            for (int i = 0; i < myDGV.ColumnCount; i++)
            {
                worksheet.Columns.Cells[1, i + 1] = myDGV.Columns[i].HeaderText;
            }
            //寫入數值
            for (int r = 0; r < myDGV.Rows.Count; r++)
            {
                for (int i = 0; i < myDGV.ColumnCount; i++)
                {
                    worksheet.Cells[r + 2, i + 1] = myDGV.Rows[r].Cells[i].Value;
                }
                System.Windows.Forms.Application.DoEvents();
            }

            worksheet.Columns.EntireColumn.AutoFit();//列寬自適應

            if (saveFileName != "")
            {
                try
                {
                    workbook.Saved = true;
                    workbook.SaveCopyAs(saveFileName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("匯出檔案時出錯,檔案可能正被開啟!\n" + ex.Message);
                }
                xlApp.Quit();
                GC.Collect();//強行銷燬 
                MessageBox.Show("資料儲存成功", "提示", MessageBoxButtons.OK);
            }
        }