属性テーブルの表示example
今回は、shape fileの属性値をDataGridView controlに表示するexampleにdbf操作のメニューを付け加えていきます。
元になるprogramは、属性テーブルの表示example [Chapter 7-1]のex07に付け加えていきます。
Program Coding
Form design
Main Form
Main Formの変更・追加はありません。
属性テーブルの表示example [Chapter 7-1]そのまんまです。
Attribute View Form
Fieldの追加 Form
Fieldの削除 Form
Field名の変更 Form
Coding
それでは、 Fieldの追加 Formからcodingを始めていきます。
Fieldの追加 Form
まずは、Add Field FormのCodeは、
Public Class frmAddField Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click If ValidateForm() Then Me.DialogResult = System.Windows.Forms.DialogResult.OK Me.Hide() End If End Sub Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click Me.DialogResult = System.Windows.Forms.DialogResult.Cancel Me.Hide() End Sub Private Sub cmbFieldType_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbFieldType.SelectedIndexChanged fldPrecision.Enabled = (cmbFieldType.Text = "Double") lblPrecision.Enabled = (cmbFieldType.Text = "Double") End Sub Private Function ValidateForm() As Boolean Dim retval As Boolean = True Dim err_msg As String = "Errors:" & vbCrLf & "-------" If txtFieldName.Text = String.Empty OrElse txtFieldName.Text.Length < 1 Then err_msg &= vbCrLf & "無効なフィールド名" retval = False End If If cmbFieldType.Text = "[Select one]" Then err_msg &= vbCrLf & "フィールドタイプの選択" retval = False End If If retval = False Then MsgBox(err_msg) Return retval End Function End Class
ComboBoxとTextBoxに値設定してるだけです。
ここで、注意事項
-
フィールド名の長さは、10byteまでです。(アルファベットと数字と記号)
-
記号は”_”だけに統一した方がベストです。
-
日本語のフィールド名は使わない。
です。
Fieldの削除 Form
まずは、Delete Field FormのCodeは、
Public Class frmDelField Public t_sf As New MapWinGIS.Shapefile Private Sub frmDelFeild_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 'Add any initialization Dim i As Integer btnOK.Enabled = False For i = 0 To t_sf.NumFields - 1 clb.Items.Insert(i, t_sf.Field(i).Name) Next End Sub Private Sub cmbField_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) btnOK.Enabled = True End Sub Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click If Not clb.CheckedItems.Count = 0 Then If MsgBox("選択したフィールドを削除します." & _ Environment.NewLine & Environment.NewLine & _ "よろしいですか?", MsgBoxStyle.Exclamation Or MsgBoxStyle.YesNo, "フィールド削除確認") = MsgBoxResult.Yes Then Me.DialogResult = Windows.Forms.DialogResult.OK Me.Hide() Else Me.DialogResult = Windows.Forms.DialogResult.Cancel End If Else Me.DialogResult = Windows.Forms.DialogResult.Cancel Me.Hide() End If End Sub Private Sub clb_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles clb.ItemCheck btnOK.Enabled = (clb.SelectedItems.Count > 0) End Sub End Class
cmbFieldに対象となるShape fileのField名を入れてます。
また、削除対象のField名をチェックすることで選択します。
Field名の変更 Form
まずは、Rename Field FormのCodeは、
Public Class frmRenField Public t_sf As New MapWinGIS.Shapefile Public CurrentIndex As Integer Public retval As Integer Private Sub frmRenField_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 'Add any initialization after the InitializeComponent() call Dim i As Integer btnOK.Enabled = False For i = 0 To t_sf.NumFields - 1 cmbField.Items.Insert(i, t_sf.Field(i).Name) If i = CurrentIndex Then cmbField.Text = t_sf.Field(i).Name btnOK.Enabled = True End If Next End Sub Private Sub cmbField_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmbField.SelectedIndexChanged btnOK.Enabled = True retval = cmbField.SelectedIndex End Sub Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click If ValidateNewName() Then 'If mapwinutility.logger.msg("Warning! This will permanently rename this field. Do you wish to proceed?", MsgBoxStyle.Exclamation Or MsgBoxStyle.YesNo, "Confirm rename") = MsgBoxResult.Yes Then Me.DialogResult = Windows.Forms.DialogResult.OK 'End If Else MsgBox("Please enter only letters, numbers or _ (underscore) characters for the new name, and ensure that the name you have entered has no more than 11 characters", "Attribute Table Editor") 'txtNewName.Focus() End If End Sub Private Function ValidateNewName() As Boolean Dim c As Char For Each c In txtNewName.Text If (Not Char.IsLetterOrDigit(c) And c <> "_") OrElse txtNewName.Text.Length > 11 Then Return False Next Return True End Function End Class
Form Load時にcmbFieldにShape fileのField名を入れてます。
Attribute View Formのcodeing
それでは、次にField追加、Field削除、Field名変更のそれぞれのButton eventを実装します。
フィールドの追加
フィールドの追加のbutton click event発生時のcodingは、
Private Sub フィールド追加ToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles フィールド追加ToolStripMenuItem.Click Dim dlg As frmAddField 'Table編集の開始 t_sf.StartEditingTable() dlg = New frmAddField dlg.TopMost = True If dlg.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then If dlg.txtFieldName.Text = String.Empty OrElse dlg.txtFieldName.Text.Length < 1 Then MsgBox("フィールド名を正しく入力してください.", MsgBoxStyle.DefaultButton1, "Error Field Name") Exit Sub End If 'Fieldの追加 CreateField(dlg.txtFieldName.Text, dlg.cmbFieldType.Text, dlg.fldPrecision.Value, dlg.fldWidth.Value) RefreshGrid() '編集終了 t_sf.StopEditingTable() End If End Sub
CreateField関数でdbfにfieldを追加します。
subroutine RefreshGrid()でdbfを再度読み込んで、DataGridViewを新しいDataTableに更新します。
このCreateField関数の中で、t_sf.StartEditingTable()で編集の開始をTureとし、t_sf.StopEditingTable()で編集の終了をtrueして、編集時にだけdbfファイルを操作できるようにしています。Field削除、Field名変更も同様になっています。
Function CreateFieldは、
Private Function CreateField(ByVal fldName As String, ByVal fldType As String, ByVal fldPrec As Integer, ByVal fldWidth As Integer) As Integer Dim i As Integer For i = 0 To t_sf.NumFields - 1 If fldName = t_sf.Field(i).Name Then ' This is a duplicate entry, not allowed! MsgBox("追加したフィールド : " & fldName & _ "はすでに存在します。", MsgBoxStyle.OkOnly Or MsgBoxStyle.Information, "Error Field") Return -999 Exit Function End If Next Dim fld As MapWinGIS.Field fld = New MapWinGIS.Field fld.Name = fldName Select Case fldType Case "Double" fld.Type = MapWinGIS.FieldType.DOUBLE_FIELD fld.Precision = fldPrec Case "Integer" fld.Type = MapWinGIS.FieldType.INTEGER_FIELD fld.Precision = 0 Case "String" fld.Type = MapWinGIS.FieldType.STRING_FIELD fld.Precision = 0 Case "Else" MsgBox("予期せぬエラーが発生!") End Select fld.Key = "" fld.Width = fldWidth ' Added If False: If (t_sf.EditInsertField(fld, i) = False) Then ' False was returned! Something is preventing me from adding the field Dim msg As String = "フィールドが追加せきませんでした。" MsgBox(msg, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly, "Error") MsgBox(msg & ": " & t_sf.ErrorMsg(t_sf.LastErrorCode)) Return -999 Exit Function End If Return i End Function
重複するfieldのチェックを行った後に、t_sf.EditInsertField(fld, i)でdbfに追加します。
もし、追加できなかった場合は、戻り値として-999が返ってきます。
ここでは、CreateFieldのerrorはしていません。各自追加してみてください。
フィールドの削除
フィールドの削除のbutton click event発生時のcodingは、
Private Sub フィールド削除ToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles フィールド削除ToolStripMenuItem.Click Dim dlg As New frmDelField dlg.t_sf = t_sf If dlg.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then 'Check for existing name 'Table編集の開始 t_sf.StartEditingTable() '削除処理をここに書く RefreshGrid() '編集終了 t_sf.StopEditingTable() End If End Sub
この処理は各自付け加えて、Exerciseとして挑戦してください。
フィールド名の変更
フィールド名の変更のbutton click event発生時のcodingは、
Private Sub フィールド名変更ToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles フィールド名変更ToolStripMenuItem.Click Dim dlg As New frmRenField dlg.t_sf = t_sf If DataGridView1.CurrentCell.ColumnIndex > 0 Then dlg.CurrentIndex = DataGridView1.CurrentCell.ColumnIndex - 1 Else dlg.CurrentIndex = 0 End If If dlg.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then 'Check for existing name - CDM for bugzilla 136 For i As Integer = 0 To t_sf.NumFields - 1 If t_sf.Field(i).Name.ToLower() = dlg.txtNewName.Text.ToLower() Then MsgBox("フィールド名 : '" & dlg.txtNewName.Text & _ "' はすでに存在しています。フィールド名を変更してください。" & vbCrLf & _ "(Rename aborted)", MsgBoxStyle.Exclamation, "Field Already Exists") Exit Sub End If Next 'Table編集の開始 t_sf.StartEditingTable() 'Rename t_sf.Field(dlg.retval).Name = dlg.txtNewName.Text RefreshGrid() '編集終了 t_sf.StopEditingTable() End If End Sub
t_sf.Field(dlg.retval).Name = dlg.txtNewName.Textの部分がフィールド名の変更になります。
Programの実行
では、ex072を保存して実行してみましょう。
今回は、神奈川県のサンプルc14_regionDD.shpを読み込んだ後、属性値テーブル表示buttonをクリックして、属性値テーブル表示formを表示させます。
属性値テーブル表示画面
属性値テーブル表示の編集メニューのフィールド追加をclickします。
フィールド追加表示
属性値テーブル表示の編集メニューのフィールド名の変更をclickします。
フィールド名の変更表示
フィールド名のを”test”から”check”に変更した状態
フィールド名の変更後表示
属性値テーブル表示の編集メニューのフィールド削除をclickした時、field名がすべて表示されます。
フィールド削除初期画面表示
削除するfield名をチェックした時
フィールド削除選択後表示
削除後は、各自挑戦してくださいね。
今回のまとめ
では、今回のまとめを
-
別Formを作成して、属性値のテーブル編集の実装を行いました。
-
フィールド追加、フィールド名変更、フィールド削除(半分ですが。)の実装を行いました。
-
dbfの編集は、StartEditingTable()で始まり、StopEditingTable()で終わる。
次回[Chapter 7-3]では、メニューの属性検索をの実装を行い、検索・抽出の基本操作をやってみたいと考えています。
こんな感じの属性検索form
属性検索form例
vb.net2010だけでなく、C#でも、visual studio2008でも動作することができます。
簡単に自前のソフトウェアにちょっとしたGIS機能を付け加えるには良いと思います。
ex072のsource codeを公開しますので、活用してください。
ただし、あくまでの自分用のサンプルですので、バグなどがある可能性が高いので、原文のままの使用は避けてください。
サンプルコードおよびサンプルデータを使って、お使いのPCの不具合が生じても一切責任は持てませんので、あくまでも自己責任にて使用してください。
Exercise
今回のProgramを少し発展させて以下の項目を付け加えてみてください。
-
フィールド削除のcodeを追加する。
-
DataGridViewでdbfの値を変更した場合、その変更を上書き保存するcodeを追加する。
最近のコメント