-
今回は日付型データの比較を取り扱います。日付型データはその変数名を使って直接 If 文等で比較することが出来ます。 数値データの様に日付型データを比較演算子で結んで値の大小等が比較できます。
以下の例は2個の日付型データに 2019/02/01 と 2019/02/02 の異なる日付を設定し、等しいかどうかの判定を If 文で行っています。簡単な日付型(Date)データの比較
Dim dateWK1 As Date = New DateTime(2019, 2, 1) '2019/02/01 Dim dateWK2 As Date = New DateTime(2019, 2, 2) '2019/02/02 '2個の日時の比較 If dateWK1 = dateWK2 Then Console.WriteLine("dateWK1 と dateWK2 は等しい") Else Console.WriteLine("dateWK1 と dateWK2 は異なる") End If Console.WriteLine("dateWK1:" & dateWK1.ToString("yyyy/MM/dd HH:mm:ss")) Console.WriteLine("dateWK2:" & dateWK2.ToString("yyyy/MM/dd HH:mm:ss"))
実行結果は当然、2個の日付型データが異なっていることが分かります。
dateWK1 と dateWK2 は異なる dateWK1:2019/02/01 00:00:00 dateWK2:2019/02/02 00:00:00
上の例では問題無く判定が行われましたが、以下の例を見て下さい。 上の例の様に、2個の日付型データは変数を Date として宣言し、 最初の変数に Now() 関数で現在日時を設定し、さらにその後10秒待った後で、2個目の変数に現在日時を設定しています。 その後、2個の変数を比較すると、やはり異なっているとの判定がされます。
2個の変数の中身を表示してやれば、最初の時刻から10秒経過した時刻が設定されていることが分かります。
これは当然と言えばそうなのですが、変数が Date 型だからと勘違いして、日付部分しか比較しないのかと考えると ミスが発生します。お恥ずかしい話、私自身も以前にはこれでバグを発生させたことがありました。日付型(Date)データの比較
'現在日時を取得 Dim dateWK1 As Date = Now() '10秒待つ System.Threading.Thread.Sleep(10 * 1000) '現在日時を取得 Dim dateWK2 As Date = Now() '2個の日時の比較 If dateWK1 = dateWK2 Then Console.WriteLine("dateWK1 と dateWK2 は等しい") Else Console.WriteLine("dateWK1 と dateWK2 は異なる") End If Console.WriteLine("dateWK1:" & dateWK1.ToString("yyyy/MM/dd HH:mm:ss")) Console.WriteLine("dateWK2:" & dateWK2.ToString("yyyy/MM/dd HH:mm:ss")) '日付型データの比較関数 Console.WriteLine("Date.Compare(dateWK1, dateWK2):" & Date.Compare(dateWK1, dateWK2))
上記の処理を実行すると以下の様な表示が、「出力」ウインドウに表示されます。
dateWK1 と dateWK2 は異なる dateWK1:2019/02/06 18:16:49 dateWK2:2019/02/06 18:16:59 Date.Compare(dateWK1, dateWK2):-1
Date 型にはプロパティとして Date というものを持っているのでこれを使うと 純然たる日付のみのデータが取得できますので、日付のみの比較が正しく行えます。 以下のソースは If 文の部分を変更して実行してみました。日付型(Date)データの日付のみの比較
'現在日時を取得 Dim dateWK1 As Date = Now() '10秒待つ System.Threading.Thread.Sleep(10 * 1000) '現在日時を取得 Dim dateWK2 As Date = Now() '2個の日時の比較 If dateWK1.Date = dateWK2.Date Then Console.WriteLine("dateWK1 と dateWK2 は等しい") Else Console.WriteLine("dateWK1 と dateWK2 は異なる") End If
上記の処理を実行すると以下の様な表示が、「出力」ウインドウに表示されます。
dateWK1 と dateWK2 は等しい
さらに日付型の Compare メソッドを使って比較処理ができます。
Date.Compare( para1, para2 ) ... 「-1, 0, 1」のInteger型の値を返します。 結果の値の意味は以下の通りです。 ・[-1] : para1 < para2 ・[ 0] : para1 = para2 ・[ 1] : para1 > para2
日付型の Compare メソッドでの比較
Dim date0 As New DateTime(2019, 8, 27, 10, 30, 0) Dim date1 As New DateTime(2019, 8, 26, 10, 10, 0) Dim date2 As New DateTime(2019, 8, 27, 10, 15, 0) Dim date3 As New DateTime(2019, 8, 28, 10, 20, 0) ' 日付のみで比較 Console.WriteLine("Compare(date1.Date, date0.Date) = {0}", Date.Compare(date1.Date, date0.Date)) Console.WriteLine("Compare(date2.Date, date0.Date) = {0}", Date.Compare(date2.Date, date0.Date)) Console.WriteLine("Compare(date3.Date, date0.Date) = {0}", Date.Compare(date3.Date, date0.Date)) ' 日付の時刻を含み比較 Console.WriteLine("Compare(date1, date0) = {0}", Date.Compare(date1, date0)) Console.WriteLine("Compare(date2, date0) = {0}", Date.Compare(date2, date0)) Console.WriteLine("Compare(date3, date0) = {0}", Date.Compare(date3, date0))
上記の処理を実行すると以下の様な表示が、「出力」ウインドウに表示されます。
Compare(date1.Date, date0.Date) = -1 Compare(date2.Date, date0.Date) = 0 Compare(date3.Date, date0.Date) = 1 Compare(date1, date0) = -1 Compare(date2, date0) = -1 Compare(date3, date0) = 1
DateTime型の CompareTo メソッドを使っても同様の結果が得られます。
DateTime型の CompareTo メソッドでの比較
Dim date0 As New DateTime(2019, 8, 27, 10, 30, 0) Dim date1 As New DateTime(2019, 8, 26, 10, 10, 0) Dim date2 As New DateTime(2019, 8, 27, 10, 15, 0) Dim date3 As New DateTime(2019, 8, 28, 10, 20, 0) ' さらにDateTime型のCompareToを利用 Console.WriteLine("date1.Date.CompareTo(date0.Date) = {0}", date1.Date.CompareTo(date0.Date)) Console.WriteLine("date2.Date.CompareTo(date0.Date) = {0}", date2.Date.CompareTo(date0.Date)) Console.WriteLine("date3.Date.CompareTo(date0.Date) = {0}", date3.Date.CompareTo(date0.Date))
関連する記事
⇒日付型データの使い方 :[Date,DateTime]
⇒日付型データの使い方(月末、年末の日付取得)
PR -
日付を取り扱う処理は多いもので、請求処理や月締処理などで対象月の月末の日付を計算する場合があります。 また、年度の替わりが年末である場合には年末の日付を計算する必要があります。
月末で問題なのは2月で、うるう年の月末は29日のため、そのことを考える必要があります。
月末の取得は、私がよく使っているのですが指定された年月での月の最初日から翌月の最初日を計算し、 その結果の1日前を計算しています。 また、DateTime の DaysInMonth メソッドを使って該当年月の日数を使うことでも可能です。
それでは、指定された年月日に対応する月末の日付を取得する方法と、年末の日付を取得する方法を以下に示します。月末、年末の日付取得
'月末の取得 Dim dateWK As DateTime dateWK = Now() Console.WriteLine("現在:" & dateWK.ToString("yyyy/MM/dd")) dateWK = New Date(dateWK.Year, dateWK.Month, 1) '指定年月での最初日 dateWK = dateWK.AddMonths(1).AddDays(-1) '次月の1日前を計算 Console.WriteLine("月末の取得1:" & dateWK.ToString("yyyy/MM/dd")) '[DateTime.DaysInMonth]メソッドによる方法 dateWK = Me.DateTimePicker1.Value dateWK = New Date(dateWK.Year, dateWK.Month, DateTime.DaysInMonth(dateWK.Year, dateWK.Month)) Console.WriteLine("月末の取得2:" & dateWK.ToString("yyyy/MM/dd")) '年末の取得(直接12月31日指定) dateWK = Me.DateTimePicker1.Value dateWK = New Date(dateWK.Year, 12, 31) '指定年での最終日(直接12月31日指定) Console.WriteLine("年末の取得の取得1:" & dateWK.ToString("yyyy/MM/dd")) '年末の取得(指定年の翌年の元旦の1日前の計算) dateWK = Me.DateTimePicker1.Value dateWK = New Date(dateWK.Year, 1, 1) '指定年での最初日(元旦) dateWK = dateWK.AddYears(1).AddDays(-1) '次年の1日前を計算 Console.WriteLine("年末の取得の取得1:" & dateWK.ToString("yyyy/MM/dd"))
上記の処理を実行すると以下の様な表示が、「出力」ウインドウに表示されます。
現在:2019/02/01 月末の取得1:2019/02/28 月末の取得2:2019/02/28 年末の取得の取得1:2019/12/31 年末の取得の取得1:2019/12/31
ところで、年の加算を行った場合にうるう年を跨いだ場合にどうなるのかが少し気になりましたので、 以下の様なソースで実行してみました。1年後の計算(AddYearsメソッド)
'1年後の計算(AddYearsメソッド) dateWK = New Date(2019, 2, 28) '指定年月:2019/02/28 dateWK = dateWK.AddYears(1) Console.WriteLine("うるう年では無い年の1年後:" & dateWK.ToString("yyyy/MM/dd")) dateWK = New Date(2020, 2, 28) '指定年月:2020/02/28 dateWK = dateWK.AddYears(1) Console.WriteLine("うるう年の場合の年の1年後:" & dateWK.ToString("yyyy/MM/dd")) dateWK = New Date(2020, 2, 29) '指定年月:2020/02/29 dateWK = dateWK.AddYears(1) Console.WriteLine("うるう日からの1年後:" & dateWK.ToString("yyyy/MM/dd")) dateWK = New Date(2019, 3, 1) '指定年月:2019/03/01 dateWK = dateWK.AddYears(1) Console.WriteLine("うるう日を挟む場合の1年後:" & dateWK.ToString("yyyy/MM/dd"))
上記の処理を実行すると以下の様な表示が、「出力」ウインドウに表示されます。
2019/02/28 を指定した場合、2019年はうるう年では無いので、1年後の計算は当然 2020/02/28 になります。
2020/02/28 を指定した場合、2020年はうるう年なので 2020/02/29 があるので1日ずれるかと思いきや、1年後の計算は当然 2021/02/28 になります。 これはうるう日を特別に計算しているのか、もしくはただ単に年の数値を1加算しているのかはわかりません。
2020/02/29 を指定した場合でも結果は 1年後の計算は当然 2021/02/28 になります。やはり、うるう日を加味されている様です。
このことは、ある指定日からの1年間を計算する場合に問題になるかもしれません。 1年は365日とするのかそれともうるう日を含めるのかはその時々の仕様によると思います。うるう年では無い年の1年後:2020/02/28 うるう年の場合の年の1年後:2021/02/28 うるう日からの1年後:2021/02/28 うるう日を挟む場合の1年後:2020/03/01
関連する記事
⇒日付型データの使い方 :[Date,DateTime]
⇒日付型データの比較について
⇒文字列から数値型への変換(parse - tryparse)
⇒オブジェクト型から数値型への変換(TryParse)
-
以前、以下の記事でテキストボックスの入力される文字を数字のみに限定するコントロールについて記述しましたが、 このコントロールは数値入力には適さないので、今回は少し使える様に入力の見た目は電卓の感じにしてみました。 (数字が1の位から左側へシフトしていきます。)
今回のコントロールの動きは以下の様になります。- 数値の表示は3桁毎にカンマ編集での表示とする。
- カーソル(キャレット)は常にコントロールの右端に存在し動かない。 (矢印キーは動作しない)
- マイナス値は「-」(マイナスキー)を押下することで数値をプラスとマイナスを反転する。
- 「BackSpace」キーで最終文字を削除する。
- クリップボードからのペーストは出来ない様にする。
前回のコントロールでは KeyPress イベントで入力されたキーの制御をしていましたが、 今回はほとんどの処理を KeyDown イベントで行い、 KeyPress イベントでの処理は全て行わない様にします。
今回の処理ではテキストボックスの Text プロパティへの再表示を自分で強制的に行っているため、 KeyPress イベントでの処理をスキップしないと表示がおかしくなるためです。 (文字がダブって表示されたりします)
今回の処理で肝となる KeyDown イベントでは以下のキー処理を行います。- [Enter]:[Ctrl]キーが押下されていない場合、自分の親のコントロールの次のフォーカスへ移動
- [↑][↓][←][→]:矢印キーは処理無し(キーを捨てる)
- [0]~[9]:入力文字列が数値桁数を超えない場合にカンマ編集表示
- [-]:数値のプラス、マイナスの反転処理
- [BackSpace]:最終文字を削除
- その他のキー:処理無し(キーを捨てる)
尚、クリップボードからのペースト処理をしない様に WndProc をオーバーライドしペーストのメッセージを処理しない様にしています。
テキストボックスの電卓の様な入力コントロールクラス
Public Class ClsNumTextBox3 Inherits TextBox '数値桁数("-",","を含まない数値の桁数) Private _NumericUnits As Integer = 9 '数値マイナスフラグ Private _fMinus As Boolean = False 'クリップボード貼付メッセージ Const WM_PASTE As Integer = &H302 '''
''' コンストラクタ ''' Public Sub New() MyBase.New() 'IMEを無効にする MyBase.ImeMode = ImeMode.Disable 'MaxLengthは取り敢えず16を設定 Me.MaxLength = 16 'テキストは右寄せ Me.TextAlign = HorizontalAlignment.Right End Sub '''''' WndProc メソッド(クリップボード処理の為) ''' ''' <param name="m">メッセージ</param> Protected Overrides Sub WndProc(ByRef m As Message) Select Case m.Msg Case WM_PASTE 'クリップボードからのコピーは処理しない Return End Select 'メッセージのデフォルト処理を呼出す MyBase.WndProc(m) End Sub '''''' 数値桁数プロパティ ''' Public WriteOnly Property NumericUnits As Integer Set(value As Integer) Me._NumericUnits = value '退避値に設定 End Set End Property '''''' 数値での取得設定プロパティ ''' '''設定値 '''取得値 Public Property Value As Decimal Set(value As Decimal) Dim strNum As String = Math.Abs(value).ToString If strNum.Length > Me._NumericUnits Then MsgBox("ERR:数値桁数 " & Me._NumericUnits & " より大きい値が設定された") Else Me._fMinus = (value < 0) 'マイナスフラグ設定 Me.Text = strNum '取敢えず数値文字列設定 Call Me.RepairNumString("", Me._fMinus) End If End Set Get '文字列からカンマ除去 Dim strNum As String = Me.Text.Replace(",", "") 'Decimal変換値を返す Return ToDec(strNum) End Get End Property '''''' KeyDownイベントの処理 ''' Protected Overrides Sub OnKeyDown(e As KeyEventArgs) MyBase.OnKeyDown(e) Dim strAdd As String = "" Dim fEdit As Boolean = False 'キーコードによる処理 Select Case e.KeyCode Case Keys.Enter If e.Control = False Then '[Ctrl]キーが押下されていない場合、自分の親のコントロールの次のフォーカスへ移動 Me.Parent.SelectNextControl(Me, Not e.Shift, True, True, True) End If Case Keys.Up, Keys.Down, Keys.Left, Keys.Right e.Handled = True Case Keys.D0 To Keys.D9, Keys.NumPad0 To Keys.NumPad9 'キーが [0]~[9] '入力文字列が数値桁数を超えないかチェック Dim strNum As String = Me.Text.Replace("-", "").Replace(",", "") If strNum.Length >= Me._NumericUnits Then e.Handled = True Else Select Case e.KeyCode Case Keys.D0 To Keys.D9 strAdd = "0123456789".Substring(e.KeyCode - Keys.D0, 1) Case Keys.NumPad0 To Keys.NumPad9 strAdd = "0123456789".Substring(e.KeyCode - Keys.NumPad0, 1) End Select fEdit = True '編集表示フラグON e.Handled = True End If Case Keys.Subtract 'キーが [-] Me._fMinus = Not Me._fMinus 'マイナスフラグ反転 fEdit = True '編集表示フラグON Case Keys.Back '最後尾1文字削除 RepairNumString("", Me._fMinus, True) Me.SelectionStart = Me.Text.Length If Me.Text.Length = 0 Then '文字列が空になった場合はマイナスフラグOFF Me._fMinus = False End If e.Handled = True Case Else e.Handled = True End Select If fEdit = True Then '編集表示フラグONの場合、編集表示 Call Me.RepairNumString(strAdd, Me._fMinus) Me.SelectionStart = Me.Text.Length End If End Sub '''''' KeyPressイベントの処理 ''' Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs) MyBase.OnKeyPress(e) '全ての文字をイベントをキャンセル e.Handled = True End Sub '''''' MouseDownイベント処理 ''' Protected Overrides Sub OnMouseDown(e As MouseEventArgs) MyBase.OnMouseDown(e) If Not (Me.SelectionStart = Me.Text.Length) Then 'カーソル位置を最後尾に強制移動 Me.SelectionStart = Me.Text.Length End If End Sub '''''' 文字列の編集表示 ''' ''' <param name="strAdd">最後尾付加文字</param> ''' <param name="fMinus">数値マイナスフラグ</param> ''' <param name="fBackSpace">BACKSPACEフラグ</param> '''文字列を3桁ごとにカンマ編集する Private Sub RepairNumString(ByVal strAdd As String, ByVal fMinus As Boolean, Optional fBackSpace As Boolean = False) '文字を最後に追加する Dim strNum As String = Me.Text.Replace("-", "").Replace(",", "") & strAdd If fBackSpace = True Then 'BackSpaceの指定の場合、最後の文字を削除 If strNum <> "" Then strNum = strNum.Substring(0, strNum.Length - 1) End If End If '3桁ごとのカンマ表示 Dim str As String = Me.ToDec(strNum).ToString("#,###") 'マイナスの場合は"-"付加 If fMinus = True Then If str <> "" Then str = "-" & str End If End If Me.Text = str 'マイナスの場合は赤色設定 If fMinus = True Then If Not Me.ForeColor = Color.Red Then Me.ForeColor = Color.Red End If Else If Not Me.ForeColor = Color.Black Then Me.ForeColor = Color.Black End If End If End Sub '''''' 文字列をDecimal数値変換 ''' ''' <param name="str">文字列</param> '''変換後の数値 Private Function ToDec(ByVal str As String) As Decimal Dim dec As Decimal = 0 Try If str <> "" Then dec = CDec(str) End If Catch ex As Exception End Try Return dec End Function End Class今回のコントロールを2個とボタンをフォームに張り付け、 そのボタンで1個目の数値を2個目の数値コントロールにコピーを行う例を以下に示します。
電卓風数値入力コントロールの例
Public Class frmTextBox3 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try Dim dec As Decimal = Me.NumTextBox1.Value Me.NumTextBox2.Value = dec Catch ex As Exception End Try End Sub End Class
ボタンを押下することで、上のコントロールの Value プロパティから値を取得し、 その値を下のコントロールの Value プロパティに設定します。 その結果、値がコピーされたことが分かります。 (上の画像は先にマイナス値をコピーした後で、上のコントロールで「-」キーを押下した様子です)関連する記事
⇒テキストボックスの入力を数字のみにする方法
⇒テキストボックス拡張クラスにプロパティを追加する方法
⇒テキストボックスの Leave イベントでのエラー処理でフォーカス強制移動する方法について
-
通常、長い処理を行うプログラムの場合、処理を行っている間にマウスカーソルを待機状態にして、現在処理中であることをユーザに示します。 これを行うにはフォームの Cursor プロパティを Cursors.WaitCursor に設定します。
また、元に戻す時は Cursor プロパティを Cursors.Default に設定します。フォームのマウスカーソルを待機状態する方法
Public Class frmCursor Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'フォームのカーソルを待機状態にする Me.Cursor = Cursors.WaitCursor '10秒待つ(長い処理の代わりにSleep関数を用いる) System.Threading.Thread.Sleep(10000) 'フォームのカーソルを元に戻す Me.Cursor = Cursors.Default End Sub End Class
上のプログラムで「長い処理の代わり」と書きましたが、実際にはデータベース処理など時間の掛かる処理を書くわけですが、 その中でエラーの対応の為に Try ... Catch ... End でエラー処理を記述すると思います。
このエラー処理の中で適切にカーソルを元に戻してやらないと、カーソルが待機状態のままになってしまいます。
(これは明らかなバグで、フォーム上の処理はできるが、カーソルが矢印に戻ってないので変な感じになります)
これを回避するためにも、カーソル設定処理は Try ... Catch ... End の外側で行うか、 もしくは以下のソースの様に Try の Finnaly の中で行うと良いと思います。
カーソル処理を Finally ブロックで行う方法
Public Class frmCursor Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try 'フォームのカーソルを待機状態にする Me.Cursor = Cursors.WaitCursor '10秒待つ(ここでは通常の処理においてエラーが発生するかもしれない) System.Threading.Thread.Sleep(10000) Catch ex As Exception 'ここに例外処理を記述する Finally 'フォームのカーソルを元に戻す Me.Cursor = Cursors.Default End Try End Sub End Class
関連する記事
⇒フォームクラス生成時に設定値を同時に渡す方法
⇒フォーム上の複数のコントロール(TextBox)の入力変化を確認する方法について
⇒フォームのマウスカーソルを待機状態する方法について
⇒フォームクラスの継承の方法について
-
何かのデータをデータベースから読込み TextBox 等に表示し、それぞれ TextBox のいずれかに入力の変更が在ったかどうかを判断する方法を示します。
以下のソースではフォームロードイベント時に仮のデータを初期値として、フォーム上の5個の TextBox に設定しています。 さらに、TextBox の TextChanged イベントで入力が在ったことを処理するため、内部の変更フラグをONしていますが、 そのイベント処理ハンドラを AddHandler により各 TextBox に関連付けています。
仮に【登録】【終了】ボタンを設置し、【登録】ボタン処理では実際の登録はしないのですが、 登録したものとして、変更フラグをOFFとして再初期化しています。 また、【終了】ボタン処理ではフラグを確認して、確認メッセージを表示する様にしています。フォーム上の複数の TextBox の入力変化を確認する処理
Public Class frmInpCheck 'データに変更が在った証拠のフラグ Private fDirty As Boolean = False '【登録】ボタンクリックイベント処理 Private Sub btnWrite_Click(sender As Object, e As EventArgs) Handles btnWrite.Click MsgBox("登録します。") '登録処理を以下に記述... 'フラグをOFF Me.fDirty = False End Sub '【終了】ボタンクリックイベント処理 Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click If Me.fDirty = True Then If MsgBox("データが変更されています。終了してもよろしいですか?", _ MsgBoxStyle.Question + MsgBoxStyle.YesNo, "TEST") = MsgBoxResult.No Then 'いいえの場合は処理を取止め Exit Sub End If End If '自分を閉じる Me.Close() End Sub 'フォームロードイベント時処理 Private Sub frmInpCheck_Load(sender As Object, e As EventArgs) Handles Me.Load 'フォームロード時に画面のTextBoxを初期化する '(一般的にはデータベース等からデータを取得し表示する...) Me.TextBox1.Text = "A1234" Me.TextBox2.Text = "BBBB" Me.TextBox3.Text = "C120000" Me.TextBox4.Text = "DDDDDD" Me.TextBox5.Text = "EEE" 'フォームに属するコントロールがTextBoxの場合、TextChangedイベントの処理を関連付ける For Each ctrl As Control In Me.Controls If TypeOf ctrl Is TextBox Then AddHandler CType(ctrl, TextBox).TextChanged, AddressOf event_TextChanged End If Next End Sub 'TextBoxの内容変化イベント処理 Private Sub event_TextChanged(sender As Object, e As EventArgs) 'データの変更フラグON!! Me.fDirty = True End Sub End Class
これを実行すると以下の様な表示になります。
TextBox のデータ4を変更し、【終了】ボタンをクリックすると以下の表示になります。
尚、 AddHandler でイベントを関連付けているところを、 イベント処理の Subプロシージャ で Handlesキーワードの後ろに5個分の TextBox を以下の様に記述しても同じことができます。
TextChangedイベント処理について
'通常の方法でのTextBoxの内容変化イベント処理 '(Handles の後ろに必要なコントロールを全て記述することで AddHandler と同様になる) Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles _ TextBox1.TextChanged, TextBox2.TextChanged, TextBox3.TextChanged, _ TextBox4.TextChanged, TextBox5.TextChanged 'データの変更フラグON!! Me.fDirty = True End Sub
この方法は見た目にも余りかっこよくないですし、仮に TextBox が増えたりした場合には変更が面倒なのでお勧めしません。 ただ、こんな方法もあるということを示しました。
今回は TextBox のみを例にしましたが、実際は日付入力や CheckBox などもありますので それぞれのコントロールで値が変更されたイベントのタイミングでフラグをONしてやればよいと思います。
(CheckBox の場合は、 CheckedChangedイベント)関連する記事
⇒フォームクラス生成時に設定値を同時に渡す方法
⇒フォーム上の複数のコントロール(TextBox)の入力変化を確認する方法について
⇒フォームのマウスカーソルを待機状態する方法について
⇒フォームクラスの継承の方法について