下記ではユーザーフォームから入力した値をテーブルに追加する方法である。
しかし、実際の業務では入力したデータを更新、訂正することよくある。
この記事は、テーブルにデータを追加するだけでなく、更新する方法を追加した。
仕様は次の通りです。
- テーブルのデータ追加はユーザーフォームのみできる(シートには保護をかけて編集できないようにする)
- 空のデータは追加できないようにする
- 既に入力されているデータは追加できないようにする
- ユーザーフォームで入力されている情報を製品IDで検索する
- ユーザーフォームで製品IDを指定してデータを更新する
太字がテーブルにデータを追加する方法から追加された仕様である。
仕様の詳細
テーブルおよびユーザーフォームは下図のようになる。
テーブル
テーブルは「製品ID」と「製品名」と「価格(円)」の3項目で構成されている。
ユーザーフォームを表示させるボタンは、項目の横に設定している。
ユーザーフォーム
新規登録
ユーザーフォーム(商品登録フォーム)では商品名と価格を入力できる。
価格は数字しか入力できない。
製品IDは登録順に追番で登録される仕様となっている。
新規登録時は「商品名」と「価格(円)」が入力されていない場合は「商品名 and/or 商品価格を入力してください。」とエラーメッセージが表示され新規登録できない。
商品名が既に登録されていた場合は、「○○は登録済なので登録席ません。」とエラーメッセージが表示され、新規登録、訂正ができない。
検索・訂正
商品IDは検索時のみ使用できる。
商品IDを入力して新規登録してもテーブルの製品IDには反映されない。(前述したように追番が自動で振り当てられる。)
例えば、テーブルが下記の場合、製品IDに「2」を入力して「検索」をクリックすると、商品名に「B商品」、価格(円)に「3000」が表示される。
例えば、価格をユーザーフォームで「3000」から「2000」変更して「訂正」をクリックすると、テーブルの商品Bの価格(円)が「2000」に変更される。
商品名が既に登録されていた場合は、「○○は登録済なので登録席ません。」とエラーメッセージが表示され、新規登録、訂正ができない。
テーブルの作成
テーブルはテーブルにデータを追加する方法と同じテーブルを使用しているので、こちらを参照。
フォームを呼び出すボタンの作成
ボタンはテーブルにデータを追加する方法と同じボタンを使用しているので、こちらを参照。
ユーザーフォームの作成
ユーザーフォームはテーブルにデータを追加する方法をベースに部品を追加する。
ユーザーフォームの作成や部品の追加方法はこちらも参照。
VBE(Visual Basic Editor)は「開発」→「Visual Basic」から起動できる。
「VBAProject」 →「挿入」→「ユーザーフォーム」を選択する。
ユーザーフォームができる。
ユーザーフォームができる。
必要な部品を下の「ツールボックス」の「コントロール」から選んで配置していく。
今回使うのは「ラベル」「テキストボックス」「コマンドボタン」の3つである。
ユーザーフォームは下記のように作成する。
プログラムを見やすくするために、オブジェクト名を下記のように設定する。
Label‗商品名:「商品名」と表示する
Label‗価格:「価格(円)」と表示する
Label_エラーメッセージ:初期状態では空白とし、エラーがあればエラーメッセージが表示される
Label_注記:初期状態では空白とし、エラーがあればエラーメッセージが表示される
TextBox‗商品ID:商品名を入力する
TextBox‗商品名:商品名を入力する
TextBox‗価格:価格(円)を入力する
Button‗新規登録:クリックすると登録の処理を実行する
Button‗検索:クリックすると商品IDから商品名と価格の情報をユーザーフォームに取得する
Button‗訂正:クリックすると商品IDのテーブルの情報をユーザーフォームに入力されているものに変更する
Button‗閉じる:クリックするとユーザーフォームを閉じる。
オブジェクト名の設定は、プロジェクトの下のプロパティのドロップボックスで該当の項目を選択し、(オブジェクト名)を変更することでできる。
また、「ユーザーフォーム」「ラベル」「コマンドボタン」の表示はプロパティのCaptionで設定する。
「TextBox_商品ID」と「TextBox_価格」
プロジェクトの下のプロパティで「TextBox_商品ID」とTextBox_価格」で下記の設定をする。
「IME Mode」を「3-fmIME ModeDisable」に変更する。
IMEをオフにすることができる。さらに半角の数字のみを入力するためのプログラムを後で設定する。
タブオーダーの設定
タブを押すとユーザーフォーム内の項目のフォーカスを次の項目へ移動させることができる。
タブオーダーの設定は設定したいユーザーフォームを表示させ「表示」→「タブオーダー」を選択
下の順番にフォーカスが変わるように設定する。
①商品IDのテキストボックス
②商品名のテキストボックス
③価格のテキストボックス
④新規登録のコマンドボタン
⑤検索のコマンドボタン
⑥訂正のコマンドボタン
⑦閉じるのコマンドボタン
タブオーダーの画面で「上に移動」「下に移動」ボタンで項目を下図のように変更する。
Subプロシージャの作成
VBAの中身を作成する。作成するプログラムは4つ。
- 入力フォームの表示ボタンをクリックたときに実行されるプログラム
- 商品ID、価格(円)の入力時に実行されるプログラム
- 入力フォーム内の閉じるボタンをクリックしたときに実行されるプログラム
- 入力フォーム内の新規登録ボタンをクリックしたときに実行されるプログラム
- 入力フォーム内の検索ボタンをクリックしたときに実行されるプログラム
- 入力フォーム内の訂正ボタンをクリックしたときに実行されるプログラム
入力フォームの表示ボタンをクリックたときに実行されるプログラム
ボタンはテーブルにデータを追加する方法と同じボタンを使用しているので、こちらを参照。
商品ID、価格(円)の入力時に実行されるプログラム
「VBAProject」→「フォーム」→「UserFrom1」を右クリックし「コードの表示」を選択する
下のコードをコピー&ペーストする。
'数字以外入力不可の設定(価格)
Private Sub TextBox_価格_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If Not Chr(KeyAscii) Like "[0-9]" Then
KeyAscii = 0
End If
End Sub
'数字以外入力不可の設定(商品ID)
Private Sub TextBox_商品ID_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If Not Chr(KeyAscii) Like "[0-9]" Then
KeyAscii = 0
End If
End Sub
このコードはに半角の数字以外のキーが押されたら何も入力されないというプログラムである。
価格と商品IDは数字のみで構成されるため、このような仕様としている。
入力フォーム内の閉じるボタンをクリックしたときに実行されるプログラム
前項と同じUserForm1の「コードの表示」させたところにプログラムを書く。
下記をコピー&ペーストする。すでに「Sub Button_閉じる_Click()」があれば、上書きする。
'ユーザーフォームを閉じる
Private Sub Button_閉じる_Click()
Unload UserForm1
End Sub
入力フォーム内の新規登録ボタンをクリックしたときに実行されるプログラム
UserForm1の「コードの表示」させたところにプログラムを書く。
下記をコピー&ペーストする。すでに「Sub Button_新規登録_Click()」があれば、上書きする。
'新規登録ボタンがクリックされた時の処理
Private Sub Button_新規登録_Click()
'変数の宣言
Dim RowNunber As Long '登録しようとした製品がある行数を登録する
Dim TableName As String 'テーブル名
'変数の初期化
RowNunber = 0
TableName = "テーブル1"
'入力した商品名がテーブルにあるかチェックする
For i = 1 To ActiveSheet.ListObjects(TableName).Range.Rows.Count
'データがある場合
If ActiveSheet.ListObjects(TableName).Range(i, 2) = TextBox_商品名.Value Then
Rownumber = i '商品名が見つかった時はテーブルの行数を保存
Exit For 'ループを終了
End If
Next
If TextBox_商品名.Value = "" Or TextBox_価格.Value = "" Then '必須項目が入力されていない時の処置
Label_エラーメッセージ.Caption = "商品名 and/or 商品価格 を入力してください。"
ElseIf Rownumber <> 0 Then '既に商品が登録されている場合の処置
Label_エラーメッセージ.Caption = TextBox_商品名.Value & "は登録済なので登録できません。"
Else '必須項目が入力されているときの処置
'シートの保護を解除
ActiveSheet.Unprotect
With ActiveSheet.ListObjects(TableName)
'行を追加
.ListRows.Add
'最終行に値を入力
.Range(.Range.Rows.Count, 1) = .Range(.Range.Rows.Count - 1, 1) + 1
.Range(.Range.Rows.Count, 2) = TextBox_商品名.Value
.Range(.Range.Rows.Count, 3) = TextBox_価格.Value
End With
'シートの保護
ActiveSheet.Protect
End If
End Sub
まずは、入力された商品名がすでに登録されていないかを確認している。
その後、入力された内容によって、処理を3パターンに分けている。
1パターン目は、商品名または価格がだったらLabel‗エラーメッセージにエラーメッセージを表示させる。
2パターン目は、商品が既に登録されていたらLabel‗エラーメッセージにエラーメッセージを表示させる。
3パターン目は、テーブルの最終行にユーザーフォームで入力した値を追加ている。
シートの保護された状態ではテーブルへの書き込みができないので保護を解除している。
その後、テーブルに行を追加し、追加した行に商品名と価格を追加している。
最後は再びシートに保護の処置をしている。
入力フォーム内の検索ボタンをクリックしたときに実行されるプログラム
UserForm1の「コードの表示」させたところにプログラムを書く。
下記をコピー&ペーストする。すでに「Sub Button_検索_Click()」があれば、上書きする。
'製品IDから情報を取得
Private Sub Button_検索_Click()
'変数の宣言
Dim TableName As String 'テーブル名
'変数の初期化
TableName = "テーブル1"
For i = 1 To ActiveSheet.ListObjects(TableName).Range.Rows.Count
'データがある場合
If CStr(ActiveSheet.ListObjects(TableName).Range(i, 1).Value) = TextBox_商品ID.Value Then
TextBox_商品名.Text = ActiveSheet.ListObjects(TableName).Range(i, 2).Value
TextBox_価格.Text = ActiveSheet.ListObjects(TableName).Range(i, 3).Value
Exit For 'ループを終了
End If
Next
End Sub
Forで入力した商品IDが存在するか検索し、存在すれば、その商品IDの商品名と価格をユーザーフォームに表示させる。
入力フォーム内の訂正ボタンをクリックしたときに実行されるプログラム
UserForm1の「コードの表示」させたところにプログラムを書く。
下記をコピー&ペーストする。すでに「Sub Button_訂正_Click()」があれば、上書きする。
'テーブルの情報の訂正
Private Sub Button_訂正_Click()
'変数の宣言
Dim TableName As String 'テーブル名
'変数の初期化
Dim RowNunber As Long '登録しようとした製品がある行数を登録する
TableName = "テーブル1"
'変数の初期化
RowNunber = 0
TableName = "テーブル1"
'入力した商品名がテーブルにあるかチェックする
For i = 1 To ActiveSheet.ListObjects(TableName).Range.Rows.Count
'データがある場合
If ActiveSheet.ListObjects(TableName).Range(i, 2) = TextBox_商品名.Value Then
Rownumber = i '商品名が見つかった時はテーブルの行数を保存
Exit For 'ループを終了
End If
Next
If TextBox_商品名.Value = "" Or TextBox_価格.Value = "" Then '必須項目が入力されていない時の処置
Label_エラーメッセージ.Caption = "商品名 and/or 商品価格 を入力してください。"
ElseIf TextBox_商品ID.Value = "" Or CInt(TextBox_商品ID.Value) > ActiveSheet.ListObjects(TableName).Range.Rows.Count Then '商品IDが空白もしくは表の行数より大きい場合
Label_エラーメッセージ.Caption = "登録済の商品IDを入力してください。"
ElseIf Rownumber <> 0 Then '既に商品が登録されている場合の処置
Label_エラーメッセージ.Caption = TextBox_商品名.Value & "は登録済なので登録できません。"
Else
'シートの保護を解除
ActiveSheet.Unprotect
i = TextBox_商品ID.Value 'テーブルの行と商品IDが一致する仕様のためこのような仮定ができる。
'情報の更新
ActiveSheet.ListObjects(TableName).ListRows(i).Range(2) = TextBox_商品名.Value
ActiveSheet.ListObjects(TableName).ListRows(i).Range(3) = TextBox_価格.Value
'シートの保護
ActiveSheet.Protect
End If
End Sub
まずは、ユーザーフォームに入力された商品IDが存在しているか確認する。
その後、入力された内容によって、処理を4パターンに分けている。
1パターン目は、商品名または価格がだったらLabel‗エラーメッセージにエラーメッセージを表示させる。
2パターン目は、商品が既に登録されていたらLabel‗エラーメッセージにエラーメッセージを表示させる。
3パターン目は、商品IDが存在しなければLabel‗エラーメッセージにエラーメッセージを表示させる。
4パターン目は、商品IDの行数のデータをユーザーフォームの記載データに上書き保存している。
シートの保護された状態ではテーブルへの書き込みができないので保護を解除している。
その後、テーブルに行を追加し、追加した行に商品名と価格を追加している。
最後は再びシートに保護の処置をしている。