お客様IDが入力されたら伝票番号を生成してラベル“lblSlipNumber”に表示し、併せて「顧客_mr」から顧客のレコードを検索~抽出して氏名などを表示します。
- ID未入力時のエラーについて -
この処理は、お客様IDを入力するテキストボックス“txtCstmId”がフォーカスを失ったとき(LostFocusイベント発生時)に実行します。
このサンプルでは、テキストボックス“txtCstmId”が空白のときにはエラーメッセージを出すようにしています。そのため、“txtCstmId”が空白のまま[終了]ボタンをクリックしようとしたときにもLostFocusイベントが発生してエラーメッセージが表示されます。
このサンプルは、OCRカードなどから連続で読み込むことを前提とし、処理の過程が分かるようデータ入力部分をユーザーの手入力に置き換えたものです。そのため、上記のような状態になることを防ぐ仕組みは用意していません。
[終了]ボタンをクリックしたときに「お客様IDを入力してください」というエラーメッセージが表示されたら、txtCstmIdに取り敢えず何らかの数値を入力し、その後もう一度[終了]ボタンをクリックすればアプリケーションは終了します。サンプルを試すときには、この点に注意してください。
- 伝票番号の生成と表示~txtCstmId_LostFocus -
このプロシージャでは実際のレコード検索は行わず、後述する下請けプロシージャ“SearchCustomer”に委ねています。そのため、下請けプロシージャに渡すSQL文字列と伝票番号生成用のレコード件数を受け取る変数の2つを準備するだけです。
|
Private Sub txtCstmId_LostFocus _ |
|
|
(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles txtCstmId.LostFocus |
|
|
|
Dim strSql As String ----------- 下請けプロシージャに渡すSQL Dim intSlipCount As Integer ---- レコード件数を保存 |
先に紹介したFunctionプロシージャGetSlipCountを呼び出し、現在の「売上ヘッダ」のレコード件数を変数“intSlipCount”に受け取ります。
intSlipCount = GetSlipCount()
このとき「-1」が返ってきたらエラーとし、メッセージを表示してプロシージャを抜けます。エラー発生の原因としては、例えば、他のアプリケーションが「売上ヘッダ」に排他アクセスしているような場合などが考えられます。しばらくしてからやり直せばよいので、アプリケーション自体は終わらせません。
|
If intSlipCount = -1 Then MessageBox.Show _ |
|
|
("データベースエラーのため伝票番号を生成できませんでした。" & _ vbCrLf & _ "お客様番号の入力からやり直してください。", _ "伝票番号エラー", _ MessageBoxButtons.OK, MessageBoxIcon.Error) |
|
txtCstmId.Select() Exit Sub End If |
無事レコード件数が取得できたらそれに1を加算した値を、テキストボックス“txtDate”に表示されている日付の後に付け足して伝票番号とします。この値は、グローバル変数“strSlipNumber”に保存すると共にラベル“lblSlipNumber”にも表示します。
|
strSlipNumber = _ |
|
|
Format(CDate(txtDate.Text), "MMdd") _ ---- 日付を書式化 Format(intSlipCount + 1, "000#") ----------- 連番を書式化 |
|
lblSlipNumber.Text = strSlipNumber |
伝票番号の生成が終わったら、顧客情報の検索SQLを引数にして下請けプロシージャ“SearchCustomer”を呼び出します。
|
↓顧客情報の検索用SQL strSql = _ "SELECT 氏名, 郵便番号, 住所1, 住所2, 電話 FROM 得意先_mr " & _ "WHERE お客様ID = "
↓テキストボックスの未入力チェック If Me.txtCstmId.Text = "" Then |
|
|
MessageBox.Show("お客様IDを入力してください。", _ "入力エラー", MessageBoxButtons.OK, MessageBoxIcon.Error) |
|
Else ↓下請けプロシージャを呼び出して検索 |
|
|
strSql = strSql txtCstmId.Text SearchCustomer(strSql) |
ここまでの処理を終えたらこの顧客の受注は確定され、あとは個々の商品を特定して数量を入力する処理(フォームの右側)に移行します。そのため、この段階で「売上ヘッダ」に伝票番号・日付・お客様IDなどの値を記録したレコードを1件追加します。
この処理は、後述する“AddHeader”という下請けプロシージャで行います。“AddHeader”はFunctionプロシージャで、戻り値から成功と失敗を判別できるようにしていますが、処理を簡略化するため戻り値は利用していません。
End Sub
- 顧客情報の取得と表示~SearchCustomer -
顧客情報を取得して表示する下請けプロシージャの処理は、これまでに紹介してきたレコード抽出と同じ仕組みなので、本質的には非常にシンプルです。
ただ、テーブル「顧客_mr」はこれまでに扱ってきた商品の情報(テーブル「商品_mr」、サンプルでは「商品_dmy」を使用)とは異なり、すべてのフィールドに値が記録されているわけではありません。特に、「住所1」と「住所2」の2つのフィールドに分かれている住所の情報は、短い住所の場合「住所2」フィールドが未入力となっており、そこはNull値のままとなっています。このNull値の扱いに対処するため、単純なレコード抽出に比べてソースはやや長くなります。
データベースを扱うオブジェクト変数と、SQLを保存する文字列変数を準備します。
Private Sub SearchCustomer(ByVal strSql As String)
|
Dim objConnect As New SqlConnection Dim objCommand As New SqlCommand Dim objDataReader As SqlDataReader |
接続文字列の指定からSQLの設定までは、これまでに紹介した流れとまったく同じなので省略します。
|
Try |
|
|
objConnect.ConnectionString = _
: objCommand.CommandText = strSql |
SQLの発行結果を受け取った後、フィールド名を引数にしてDataReaderからフィールドの値を読み出し、対応する各ラベルにそれを表示します。すべて文字列なので型の変換は不要ですが、フィールドが空でNull値が返ってきた場合には、それを空文字列("")に変換しなければなりません。この処理を、表示するフィールドの数だけ実行することになります。
フィールドのNull値(データベースのNull)はプログラミング言語のNullとは異なり、ソース上では“DBNull”という記号定数で扱います。値がDBNullかどうかは、IsDBNull関数で判断します。引数にフィールドの値を与えて呼び出し、それがDBNullならTrueが返ってきます。従って、以下のようなIf文の連続となります。
|
↓SQLを発行 objDataReader = _ |
|
|
objCommand.ExecuteReader(CommandBehavior.SingleRow) |
|
↓検索に成功した場合 If objDataReader.Read() Then |
|
↓値がNullなら""に変換する If Not IsDBNull(objDataReader("氏名")) Then |
|
|
lblCstmName.Text = objDataReader("氏名") |
|
Else |
|
|
lblCstmName.Text = "" |
|
End If If Not IsDBNull(objDataReader("郵便番号")) Then |
|
|
lblCstmZip.Text = objDataReader("郵便番号") |
|
Else |
|
|
lblCstmZip.Text = "" |
|
End If |
|
|
: (以下略) |
ラベルに表示した文字列(顧客の氏名や住所)は、最初に宣言した構造体structMemberInfo型の変数Customerの各メンバにも代入しておきます。
|
With Customer |
|
|
.strDate = txtDate.Text .strName = lblCstmName.Text .strZip = lblCstmZip.Text .strAddr1 = lblCstmAddr1.Text .strAddr2 = lblCstmAddr2.Text .strPhone = lblCstmPhone.Text |
|
End With |
これ以降の例外処理と接続を閉じる処理は、既に紹介してきたものと同じなので省略します。
|
|
|