🦔

VB.NETとSQLサーバを用いた開発(実践編)

に公開

はじめに

今回は、前回 https://zenn.dev/nbs_tokyo/articles/deb5e202be7fb1 やった内容が、具体的にどういうふうに使われて、Formのページが作られているのか、具体的にやっていこうと思います。

指示書作成

ワイヤフレーム作成

https://n-works.link/blog/webdesign/wire-frame

やっぱり最初はワイヤフレームがないと始まりません。
「こういうページを作れ」って指示書が最初に上から提示されて、そのとおりに作ることになります。
今回は、デザイナで直接作りますが、それをワイヤフレーム代わりにして説明します。

というわけで、ワイヤフレームみたいなのを作ってみました。

しかし、これだけでは当然何をすればいいのかわからないので、より詳しい指示書を作っていきます。

この段階で今のうちに、各コントロールの名称に、命名規則に沿って名付けましょう。


例えば、年度関係のLabelであったら「Label_年度」、県関係のComboBoxだったら「ComboBox_県」みたいに。
「コントロールの属性_(やりたいこと)」みたいな感じです。
これを大まかでいいのできちんとやらないと、面倒なことになる。

説明追加

上の画像を基に、より詳しく説明を加えていきます。
指示書というものは、だいたいワイヤフレームと一緒にこの説明もついてきます。

・ユーザ名→今この画面を操作しているユーザのこと
・役職→その「ユーザ」の「登録担当」「閲覧担当」の2通り
・年月日→Now()のものを使用。ただし年号は和暦を利用すること。

・都道府県→「神奈川県」「埼玉県」「千葉県」の3県のみとする
・市町村→
「神奈川県」なら「横浜市」「川崎市」
「埼玉県」なら「さいたま市」「浦和市」
「千葉県」なら「千葉市」「成田市」

・「本人確認」がなければ登録することができない。
・「閲覧担当」は、登録者名簿しか確認することができない。
・「登録者名簿」は、ReadOnlyとする。
また、何らかの手段で県単位、市単位で絞り込めるようにする。
「県まで絞る」「何も絞らない」用の機能もつくる。

実際に作っていく

まず、簡単なものから作っていきます。

ギミックとかが不要なラベル

Labelの中で、操作とかが入らなさそうなやつを消していきます。

今マーカーをつけた部分は、操作不要でしょう。
本来はもうちょいフォントとかサイズとか位置とか凝ったほうがいいんですが、そんなのあとからできます。放置。

戻る

一番簡単な実装は「戻る」です。
デザイナの「戻る」をダブルクリックすると、ソースコードに

   Private Sub Button_戻る_Click(sender As Object, e As EventArgs) Handles Button_戻る.Click
   End Sub

こんなのが出てくると思うんですが、そこに「Me.Close()」と書くだけです。
「Me.Close()」とは「今の画面を閉じる」という意味です。

   Private Sub Button_戻る_Click(sender As Object, e As EventArgs) Handles Button_戻る.Click
       Me.Close()
   End Sub

たったこんだけ。
今回は「登録ページを新しく開いた」という体でやっていきたいので、それでいいです。
ページを閉じちゃ駄目な場合でも、初めて仕事をするときは手直しや既存のFormの類似機能の作成なので、すでに「戻る」ためのソースコードがどっかにあると思います。
なので、そこから探せばいいです。

年度の実装

「今の時間」を基準に、年度を作っていきます。
これも、理屈自体は単純です。

最初に、年号と西暦の対応です。

Dim dt1 As DateTime = DateTime.Now

まず「dt1」というDataTime型の変数を仮置きします。(DataTime型とは、日時の記述に特化した変数型のことです。)
DataTime.Now(今の時間)を基準に設定してやりましょう。

「今は令和何年?」というのを示す変数reiwaを作ってやるために「(今の年)-2018」の整数型をとってやると、こんな感じになります。

Dim reiwa As Integer = CInt(dt1.ToString("yyyy")) - 2018

datatime型の変数「dt1」から年数を取り出すために、dt1.ToString("yyyy")としてやります。
そして、それをInt型として計算できるように、CIntで括ります。
最終的に、Integer型の変数reiwaは、2025年であれば「7」と定められます。
令和7年というわけです。

最後に、ラベル「年度」のテキストに書き込んでいきます。
Integer型のreiwaをCStr()でString型に変換したり
さっきの「年」を取り出した要領で「dt1.ToString("MM")」「dt1.ToString("dd")」を使って、dt1からString型の月日を取り出す。
そして、これらを全部「Label_年度.Text」に加えてやるだけです。

できたのがこちら

Dim dt1 As DateTime = DateTime.Now
Dim reiwa As Integer = CInt(dt1.ToString("yyyy")) - 2018

Label_年度.Text = "令和" + CStr(reiwa) + "年度 " + dt1.ToString("MM") + "月" + dt1.ToString("dd") + "日"

ユーザと役職

年号あたりまではSQLを使わずとも話が進む、簡単な話でしたが、ここからとうとうSQLの使用から逃げられなくなります。

まずはSSMS(SQLサーバ)にて「ユーザ名」「役職」「ID」の列があるテーブル「職員」を、以下のような感じで作ります。

テーブル名「職員」

次に、SQLサーバの「職員」テーブルと、VBのユーザ名等とどう結びつけるかです。

これに、SQLの職員情報が書き込まれるようにしたい。

まずはログインに使ったIDを渡せばいいわけですが、今回はログインがどうとか作ってないので、冒頭にMessageBoxのYesNo形式で表示させて、その選択肢によってIDを決めていきます。

        ' 取得したいID
        Dim id As Integer
        ' メッセージボックスを表示
        Dim result As DialogResult = MessageBox.Show("登録担当としてログインしますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question)

        ' 選択によって id を設定
        If result = DialogResult.Yes Then
            id = 1
        ElseIf result = DialogResult.No Then
            id = 2
        End If


これで「はい」ならid=1として「いいえ」ならid=2としてログインします。

この「id」の情報を、ストアドに入れていきます。
現場のコードを覚えてないので、ここはGPTに書いてもらいました。

        ' SQL Server接続(Windows認証)
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

        Try
            Using conn As New SqlConnection(connectionString)
                Using cmd As New SqlCommand("職員_抽出", conn)
                    cmd.CommandType = CommandType.StoredProcedure
                    cmd.Parameters.AddWithValue("@ID", id) ' IDをストアドに渡す

                    conn.Open()
                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        If reader.Read() Then
                            Dim userName As String = reader("ユーザ名").ToString()
                            Dim roleName As String = reader("役職").ToString()

                            ' Label_ログイン情報 に表示
                            Label_ログイン情報.Text = "ユーザ名:" & userName & "、役職名:" & roleName
                        Else
                            Label_ログイン情報 = "該当するユーザが見つかりません"
                        End If
                    End Using
                End Using
            End Using

        Catch ex As Exception
            MessageBox.Show("エラー: " & ex.Message)
        End Try

どこから話せばいいのか…
まずは、SQLと接続しましょう。
なんか、こう書いてるやつがあるんだけど

' SQL Server接続(Windows認証)
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;


サーバ名はSSMSの、矢印の「Server Name」のやつを書けばおk


データベース名はこれの青で隠してるやつ

Trustなんとかってやつ2種は、青矢印で示したようなWindows認証の場合につけます。
これでできたということにしましょう。

次に、ストアド[職員_抽出]とテーブルを見ていきます。


パラメータ定義部に、@IDがあって
処理部のWHEREにも、ID=@IDがあって
VB.NETにも以下のような記述があるんだけど

cmd.Parameters.AddWithValue("@ID", id) ' IDをストアドに渡す

まず、VB.NET側から@IDの情報を送ってます。
さっきid=1って定義したから、ストアドのパラメータ定義部の@IDに「1」が代入されたわけです。
で、ストアド側のWhereで、テーブル[職員]の中から「ID=1」になっているデータを取り出すわけです。

これはVB.NET側の実際の動作ではないんですが、SSMSでストアドを直接実行した時の結果です。
ID=1のデータが取り出せてますね。

で、

conn.Open()
                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        If reader.Read() Then
                            Dim userName As String = reader("ユーザ名").ToString()
                            Dim roleName As String = reader("役職").ToString()

                            ' Label_ログイン情報 に表示
                            Label_ログイン情報.Text = "ユーザ名:" & userName & "、役職名:" & roleName
                        Else
                            Label_ログイン情報.Text = "該当するユーザが見つかりません"
                        End If

この辺りで、SSMS側から戻ってきた情報を読み込んでいます。
先程の、ユーザ名:ああああ、役職名:登録担当が、ここでラベル「ログイン情報」に書き込まれたわけです。

こんな感じで、Formのユーザの情報も表示されました。

権限による操作周り

・「閲覧担当」は、登録者名簿しか確認することができない。
とのことなんだけど、この段階で「閲覧担当」の操作に制限を加えたい。
簡単な話、ログイン状態を見てEnabled=False、Visible=False、ReadOnly=Trueのいずれかにしてやるだけです。

idの値が2(閲覧担当)なら、登録のButtonをEnabled=False、本人確認のCheckBoxをVisible=False、名前のTextBoxをReadOnly=Trueとでもしてやりましょう。

                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        If reader.Read() Then
                            Dim userName As String = reader("ユーザ名").ToString()
                            Dim roleName As String = reader("役職").ToString()

                            ' Label_ログイン情報 に表示
                            Label_ログイン情報.Text = "ユーザ名:" & userName & "、役職名:" & roleName
                            '▼▼ここに差し込む
                            If roleName = "閲覧担当" Then
                                Button_登録.Enabled = False
                                CheckBox_本人確認.Visible = False
                                TextBox_名前.ReadOnly = True
                            End If
                            '▲▲ここに差し込む
                        Else
                            Label_ログイン情報.Text = "該当するユーザが見つかりません"
                        End If
                    End Using

役職をヘッダに書き込むと同時に権限周りの操作を行った
行儀の悪い書き方ではある。

ってことで、名前には書き込めず、登録ボタンは陥没して、CheckBoxは消えました。

都道府県、市を読み込む

都道府県、市に関しても、テーブルを作っていきます。

・都道府県→「神奈川県」「埼玉県」「千葉県」の3県のみとする
・市町村→
「神奈川県」なら「横浜市」「川崎市」
「埼玉県」なら「さいたま市」「浦和市」
「千葉県」なら「千葉市」「成田市」
なんか、こう言われたので、これを登録していきます。

テーブル名「都道府県」

テーブル名「住所」
都道府県と市町村のテーブルを作った。
多分もっといい方法あるけど、今回はこれでいく。

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        (略)
        LoadPrefectures()
    End Sub

Form1_Loadの中に、LoadPrefectures()を入れます。
これで、その関数を呼び出す場所を作ってます。
それの中身はこんな感じ。

    Private Sub LoadPrefectures()
        ' SQL Server 接続文字列
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

        Try
            Using conn As New SqlConnection(connectionString)
                Using cmd As New SqlCommand("都道府県_抽出", conn)
                    cmd.CommandType = CommandType.StoredProcedure

                    conn.Open()

                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        Dim prefList As New List(Of String)

                        While reader.Read()
                            ' 仮に列名が「都道府県」の場合
                            prefList.Add(reader("都道府県").ToString())
                        End While

                        ' ComboBox にセット
                        ComboBox_登録県.DataSource = prefList
                    End Using
                End Using
            End Using

            ' 市は最初は無効
            ComboBox_登録市.Enabled = False

        Catch ex As Exception
            MessageBox.Show("エラー: " & ex.Message)
        End Try
    End Sub

色々やってるけど、要するにこれで「都道府県」テーブルから引っ張ってきた都道府県を1県ずつComboBoxにセットしてます。

USE [DB名]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- プロシージャ定義部
ALTER PROCEDURE [dbo].[都道府県_抽出]
AS

-- 処理部
SELECT *

FROM [dbo]. [都道府県]

抽出用のストアドはこれ。

県はこの段階ではデフォ値なんで、市は操作不可にしましょう。

次に、県を選択したら、市が出るようにします。

Private Sub ComboBox_登録県_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox_登録県.SelectedIndexChanged
    ComboBox_登録市.Enabled = True
    ComboBox_登録市.Items.Clear()

    ' 選択された県
    Dim selectedPref As String = ComboBox_登録県.SelectedItem.ToString()

    ' SQL Server 接続文字列
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

    Try
        Using conn As New SqlConnection(connectionString)
            ' ストアドプロシージャ名は市町村抽出用に用意しているもの
            Using cmd As New SqlCommand("市町村_抽出", conn)
                cmd.CommandType = CommandType.StoredProcedure
                ' 県をパラメータとして渡す
                cmd.Parameters.AddWithValue("@県", selectedPref)

                conn.Open()

                Using reader As SqlDataReader = cmd.ExecuteReader()
                    While reader.Read()
                        ' 列名が「市」の場合
                        ComboBox_登録市.Items.Add(reader("市町村").ToString())
                    End While
                End Using
            End Using
        End Using
    Catch ex As Exception
        MessageBox.Show("エラー: " & ex.Message)
    End Try
    ComboBox_登録市.SelectedIndex = 0
End Sub
USE [DB名]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- プロシージャ定義部
ALTER PROCEDURE [dbo].[市町村_抽出]


@県 nvarchar(10)
AS

-- 処理部
SELECT [市町村]

FROM [dbo]. [住所]
WHERE 都道府県=@県

ストアドに県が渡されてて、列に市町村が指定されてる以外、ほぼ同じ感じ。

で、完成したのがこちら

最初は都道府県だけがセットされて

都道府県を選択すると、市町村もセットされたので、選択してみた。

テーブルに情報を登録

ここからが本番です。
都道府県と名前の情報をテーブルに登録します。
…忘れてた。その前に、本人確認にチェックしないと駄目な仕様にしましょう。
あんまり意味ない気もしますが、タバコの年齢確認や、利用規約みたいなものだと思ってください。

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    (略)
    CheckBox_本人確認.Checked = False
    Button_登録.Enabled = False
End Sub

初期状態は登録不可

    Private Sub 本人確認_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox_本人確認.CheckedChanged
        If CheckBox_本人確認.Checked = True Then
            Button_登録.Enabled = True
        Else
            Button_登録.Enabled = False
        End If
    End Sub


本人確認OFF

本人確認ON

最後に、今までの情報を登録します。

テーブル名「登録情報」

    Private Sub 登録_Click(sender As Object, e As EventArgs) Handles Button_登録.Click
        ' SQL Server 接続文字列
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

        Try
            Using conn As New SqlConnection(connectionString)
                ' ストアドプロシージャ名は市町村抽出用に用意しているもの
                Using cmd As New SqlCommand("登録情報_追加", conn)
                    cmd.CommandType = CommandType.StoredProcedure
                    ' 県をパラメータとして渡す
                    cmd.Parameters.AddWithValue("@県", ComboBox_登録県.Text)
                    cmd.Parameters.AddWithValue("@市", ComboBox_登録市.Text)
                    cmd.Parameters.AddWithValue("@名前", TextBox_名前.Text)
                    conn.Open()
                    cmd.ExecuteNonQuery()  ' ←データベースに登録
                End Using
            End Using
            MessageBox.Show("登録が完了しました!")
        Catch ex As Exception
            MessageBox.Show("エラー: " & ex.Message)
        End Try
    End Sub

登録はこんな感じ
ConboBoxで県とか呼び出したのと同じ要領で。
データベースに登録するために「cmd.ExecuteNonQuery()」があることくらいですかね。
登録と抽出で、VB側の書き方があんまり変わらないのも、ストアドを作る利点です。
データベースに登録できたのを明示するために、MessageBoxもつけときましょう。

そのストアドはこんな感じ

USE [DB名]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- プロシージャ定義部
ALTER PROCEDURE [dbo].[登録情報_追加]


@県 nvarchar(10),
@市 nvarchar(10),
@名前 nvarchar(10)
AS

BEGIN
    SET NOCOUNT ON;

    -- INSERT 文でデータを追加
    INSERT INTO [dbo].[登録情報] (県, 市, 名前)
    VALUES (@県, @市, @名前);
END

抽出時のSELECTじゃなくて、書き込みのINSERT文を使ってますね。
このままだと、登録情報が被った時の挙動が危ないので、もうちょっとちゃんと作ったほうがいいです。
ともかくとして、これで登録出来るかやってみます。

ちゃんと全部埋まってますね。
じゃあ登録

「登録が完了しました!」だと?本当かよ?(いつも思ってること)

本当だ。よかったね

登録情報を呼び出す

最後に、登録者情報を呼び出す機能を追加します。

こんな感じで適当にリストを埋めたら、まずは、登録者を抽出するストアドを作りましょう。

USE [DB名]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- プロシージャ定義部
ALTER PROCEDURE [dbo].[登録情報_抽出]


@県 nvarchar(10),
@市 nvarchar(10)
AS

-- 処理部
SELECT *

FROM [dbo]. [登録情報]
WHERE 県=@県 and 市=@市

こんな感じのを作って

こんなもんでしょ。

これを扱う上で、データの絞り込みを行う部分がどっかで要るので、新しいComboBoxが必要だなと思いました。なので、今からComboBoxも追加していきます。
こういう時「これを実装するときはこういう機能が必要だと思うのですが…」と、必ず上長に報告してください。

こんな感じ?

これに対応したComboBoxを作ります。
基本的にさっき作った登録用のやつと同じ

    Private Sub LoadPrefecturesToroku()

        ' 全ての選択肢を追加
        ComboBox_名簿県.Items.Add("全て")
        ' SQL Server 接続文字列
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

        Try
            Using conn As New SqlConnection(connectionString)
                Using cmd As New SqlCommand("都道府県_抽出", conn)
                    cmd.CommandType = CommandType.StoredProcedure

                    conn.Open()

                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        While reader.Read()
                            ' 仮に列名が「都道府県」の場合
                            ComboBox_名簿県.Items.Add(reader("都道府県").ToString())
                        End While
                    End Using
                End Using
            End Using

            ' 市は最初は無効
            ComboBox_名簿市.Enabled = False

        Catch ex As Exception
            MessageBox.Show("エラー: " & ex.Message)
        End Try
    ComboBox_名簿県.SelectedIndex = 0
    ComboBox_名簿市.SelectedIndex = 0
    End Sub

県に関しては、本当に"全て"をプルダウンに追加しただけですね。

Private Sub ComboBox_名簿県_SelectedIndexChangedu(sender As Object, e As EventArgs) Handles ComboBox_名簿県.SelectedIndexChanged
    ComboBox_名簿市.Enabled = True
    ComboBox_名簿市.Items.Clear()
    ' 全ての選択肢を追加
    ComboBox_名簿市.Items.Add("全て")

    If 登録者県.Text = "全て" Then
        ComboBox_名簿市.Enabled = False
    Else
        ' 選択された県
        Dim selectedPref As String = ComboBox_名簿県.SelectedItem.ToString()

        ' SQL Server 接続文字列
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

        Try
            Using conn As New SqlConnection(connectionString)
                ' ストアドプロシージャ名は市町村抽出用に用意しているもの
                Using cmd As New SqlCommand("市町村_抽出", conn)
                    cmd.CommandType = CommandType.StoredProcedure
                    ' 県をパラメータとして渡す
                    cmd.Parameters.AddWithValue("@県", selectedPref)

                    conn.Open()

                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        While reader.Read()
                            ' 列名が「市」の場合
                            ComboBox_名簿市.Items.Add(reader("市町村").ToString())
                        End While
                    End Using
                End Using
            End Using
        Catch ex As Exception
            MessageBox.Show("エラー: " & ex.Message)
        End Try
    End If
    ComboBox_名簿市.SelectedIndex = 0

End Sub

市に関しても、選択肢に"全て"を加えました。
県に"全て"が指定されている場合、市もまた"全て"を指定するようにしました。
それ以外はやはり、上のConboBoxで人を登録したときと同じ。

出来たのがこんな感じです。

都道府県「全て」だと、市町村は「全て」で固定


県を指定してやると、市町村は「全て」か「〇〇市」が選択できる。

DataGridViewが出力されるタイミングは、都道府県選択時、または市町村選択時にしておきます。

    Private Sub ComboBox_名簿県_SelectedIndexChangedu(sender As Object, e As EventArgs) Handles ComboBox_名簿県.SelectedIndexChanged
        (略)
        ComboBox_名簿市.SelectedIndex = 0
        LoadDataGridView()'←ここで呼び出し
    End Sub

市のComboBoxの挙動も作っておきます。

    Private Sub ComboBox_名簿市_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox_名簿市.SelectedIndexChanged
        LoadDataGridView()'←ここで呼び出し
    End Sub

ここまでやって、ようやくDataGridViewに登録情報を入れるコードを作成します。

    Private Sub LoadDataGridView()
        Dim connectionString As String = "Server=「サーバ名」;Database=「データベース名」;Trusted_Connection=True;TrustServerCertificate=True;"

        Try
            Using conn As New SqlConnection(connectionString)
                Using cmd As New SqlCommand("登録情報_抽出", conn)
                    cmd.CommandType = CommandType.StoredProcedure
                    cmd.Parameters.AddWithValue("@県", ComboBox_名簿県.Text)
                    cmd.Parameters.AddWithValue("@市", ComboBox_名簿市.Text)

                    conn.Open()
                    Using reader As SqlDataReader = cmd.ExecuteReader()
                        ' 既存の行をクリア
                        DataGridView_名簿リスト.Rows.Clear()

                        ' データを1行ずつ追加
                        While reader.Read()
                            Dim rowIndex As Integer = DataGridView_名簿リスト.Rows.Add()
                            ' reader の列順に従って DataGridView の列に代入
                            For i As Integer = 0 To reader.FieldCount - 1
                                ' DataGridView の列数に収まるようにチェック
                                If i < DataGridView_名簿リスト.Columns.Count Then
                                    DataGridView_名簿リスト.Rows(rowIndex).Cells(i).Value = If(reader(i) Is DBNull.Value, "", reader(i))
                                End If
                            Next
                        End While
                    End Using
                End Using
            End Using

        Catch ex As Exception
            MessageBox.Show("エラー: " & ex.Message)
        End Try
    End Sub

いろいろ書いてありますが、要するに、読み込んだものを1つ1つDataGridViewのセルに入れていっているだけです。

これで登録者名簿が追加もできました。
あとは、都道府県、市町村が「全て」だった時の挙動を作ります。
色々方法はあるんですが、今回は直感的にストアド側で実装するのが楽そうに感じました。

さっき作った登録情報抽出のストアドがこちら

USE [DB名]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- プロシージャ定義部
ALTER PROCEDURE [dbo].[登録情報_抽出]
@県 nvarchar(10),
@市 nvarchar(10)
AS
-- 処理部
SELECT *
FROM [dbo]. [登録情報]

WHERE 県=@県 and 市=@市

このWHERE句の部分を

WHERE (@県 = '全て' OR 県 = @県)
      AND (@市 = '全て' OR 市 = @市)

こう書いてやるだけです。
・県が "全て" のとき → @県 = '全て' が真になり、県条件は無視される
・市が "全て" のとき → @市 = '全て' が真になり、市条件は無視される
・両方 "全て" の場合 → WHERE は常に真 → 全件取得
という理屈です。

実際の挙動を見ていきます。

都道府県「全て」、市町村「全て」


都道府県「神奈川県」、市町村「全て」
出来てますね。

終わりに

かなり長編になってしまいました。
2万文字って何…?
しかしこれで最低限、VB.NETとSQLを用いたアプリって何がしたいねん?!ってところはわかって頂けたと思います。
ということでまず、今回使った技術の活用法を紹介していきます。

今回使ったコントロール

・Label
・タイトル(住所の登録)
・ComboBoxなどの説明(都道府県、名前(フルネーム)等)
・ログイン中のユーザのステータス、および日付の表示

・TextBox
・名前(フルネーム)の記述

・ComboBox
・都道府県、市町村の選択

・CheckBox
・本人確認

・Button
・登録ボタン、戻るボタン

・DataGridView
・登録情報の表示

前回紹介したコントロールを全部使ってみました。
逆に言うと、その他のコントロールは使わずに、これだけのものが作れるわけです。

利用した基礎的なプロパティなど

・.Enabled
・本人確認を行ってない際の「登録」ボタン不活性化
・都道府県未入力時の「市町村」コンボボックス不活性化

・.ReadOnly
・「閲覧担当」ユーザーに対する、名前入力のテキストボックスの記入不可

・.Visible
・「閲覧担当」ユーザーに対する、本人確認用チェックボックスの不可視化

・.Text
・年号やログイン情報、都道府県の情報など、様々なコントロールの書き換え

・.Value
・ストアドから送られてきた名簿テーブルを、DataGridViewに書き込む

・.Count
・ストアドから送られてきた名簿テーブルの行、列を数えて、何回ループさせるか決める

・.Clear
・コンボボックスの初期化等

・.Add
・コンボボックスやDataGridViewの項目追加

・.SelectedIndex
・コンボボックスの初期化

その他の必須項目

・MessageBox
・ログイン前の権限確認
・データ登録時の確認
・例外時のエラー

・Me.Close
・Formを閉じる

・CInt()、CStr()
・変数型をInt型、Str型に変更する。

使用した言語およびツール

・VB.NET
VisualStudio2022
(VSCodeでは職場での環境を再現出来ませんでした…)

今回作成したプログラムのアウトライン
大きく分けて、3部構成になっている。
・初期設定および戻る
・人物登録処理
・名簿表示処理

・SQL
SQL Server Management Studio 21(SSMS)

作成したテーブルと、ストアドプロシージャ

考えられる修正点

現状は、指示書がこれでいいって言ってるんですが
・レイアウト変更(フォント、サイズ、色など)
・テーブル名、コントロール名などを、よりわかりやすく本質的な名前に変更
・データベースに保存されたデータの削除
・操作する職員の追加、ログイン用にIDとパスワードを記入するFormの作成
・すでに同じ情報が登録されていた場合の、二重登録防止措置
・登録時テーブルへの、登録(更新)日時の記述追加
・DataGridViewのCSV出力
などなど、要件の追加が舞い込んでくることが予想されます。
出来たらやってみてください。
それこそ、ChatGPTとか使って!(職場ではインターネット禁止だった)

ネイバーズ東京

Discussion