Visual Basic 中学校 掲示板 投稿内容
タグのない投稿を抽出 統計 RSS

Visual Basic 中学校 > 投稿一覧 >

ifの中で決めた変数をEnd Ifの下でつかいたい 解決済み

基本構文 タグの編集...

投稿者 イヨ   (社会人)   投稿日時 2020/10/9 11:21:31
いつもお世話になっております。
疑問に思ったので質問します。
if の中で 変数a に PictureBox1を渡しますが End If の下で a を使おうとすると a に
「'a' は宣言されていません。アクセスできない保護レベルになっています。」とエラーが出てきます

私はaに if の中でフラグに応じたPictureBox名を渡したいのですが
End If の下で a を使うことはできないのでしょうか?

投稿者 魔界の仮面弁士   (社会人)   投稿日時 2020/10/9 11:42:42
変数の宣言箇所を間違えているのではないでしょうか。
実際のコードと VB のバージョンを教えてください。

Dim a As Integer = 123
'① 
If a > 100 Then
    Dim b As Integer = 345
    '② 
Else
    Dim c As Integer = 567
    '③ 
End If
Dim d As Integer = 789
'④ 



たとえば上記の場合、それぞれの箇所で
このような動作になります。

① 変数 a が使える。b, c, d は利用できない。
② 変数 a, b が使える。c, d は利用できない。
③ 変数 a, c が使える。b, d は利用できない。
④ 変数 a, d が使える。b, c は利用できない。

投稿者 イヨ   (社会人)   投稿日時 2020/10/9 15:21:19
魔界の仮面弁士様
いつもお世話になっております。

下記コードはバーコードを作るコードになります
やりたいことはコンボボックスのフラグに応じたピクチャーボックスにバーコードを表示したいです。
動かすと変数aのところがエラーになります。

参考にしたサイトはこちらです→https://hack.jp/?p=801

使っているバージョンは
一か月以内にビジュアルスタジオをダウンロードしたので最新だと思います。
見方がわからないので、画像置きます。。
宜しくお願いいたします。

[IMAGEhttps://subarujapan-my.sharepoint.com/:i:/g/personal/sbr000105_subaru_co_jp/ETe7vnv6yX5MnWOBAfH416oBsIvB93c7cCrvO6JrnGEDCA]

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            Dim aa As String = $"*{TextBox2.Text}{TextBox3.Text}{TextBox3.Text}{TextBox4.Text}{TextBox5.Text}*"
            If ComboBox1.SelectedItem = Nothing Then
                Label1.Text = "選択されていません。"
            ElseIf ComboBox1.SelectedItem = 1 Then
                Dim a As Object = PictureBox1
            ElseIf ComboBox1.SelectedItem = 2 Then
                Dim a As Object = PictureBox2
            ElseIf ComboBox1.SelectedItem = 3 Then
                Dim a As Object = PictureBox3
            ElseIf ComboBox1.SelectedItem = 4 Then
                Dim a As Object = PictureBox4
            End If

            If TextBox1.TextLength > 0 Then
                    Dim maxheight As Integer = 40
                    Dim barcode39 As Code39BarcodeDraw = BarcodeDrawFactory.Code39WithChecksum
                    Label1.Text = aa
                    Dim img As Image = barcode39.Draw(aa, maxheight, 2)
                    a.Image = img
                End If
        Catch aex As Exception
            MsgBox("例外が発生しました。" & vbNewLine & aex.Message)
        End Try
    End Sub




投稿者 魔界の仮面弁士   (社会人)   投稿日時 2020/10/9 16:42:49
「a」とか「aa」といった変数名だと、後で見た時に、
それが何を意味しているのか把握しにくくなります。

後半の「maxheight」や「barcode39」の方は、きちんとした名前を
付けておられるようですし、同じように意味のある変数名を付けるようにしましょう。


> 見方がわからないので、画像置きます。。
一般公開されていないのか、私のアカウントでは閲覧できませんでした。


> 動かすと変数aのところがエラーになります。
Try にせよ If にせよ、それぞれのブロック内で Dim した変数は、
そのブロックの外側では使えません。

それぞれのブロック内で a を宣言するのではなく、
変数 aa のように、それよりも前で宣言すれば OK です。


ただし提示頂いたコードだと、もしも a を使えるようにしたとしても、
この場合、『Label1.Text = "選択されていません。"』 の時には、
a がどの PictureBox を指し示すのか不明瞭になりますので、
その点も見直した方が良いですね。

Dim a As PictureBox = Nothing   'If ブロックの外側で変数を宣言し、最初に Nothing を入れておく 
If ComboBox1.SelectedItem = 1 Then
    a = PictureBox1   'それぞれのブロック内で PictureBox をセット 
ElseIf ComboBox1.SelectedItem = 2 Then
    a = PictureBox2
ElseIf ……
    :
End If

If a IsNot Nothing Then
    a.Image = img   ' a が Nothing では無かった場合は画像を差し替え 
End IF


投稿者 魔界の仮面弁士   (社会人)   投稿日時 2020/10/9 17:02:07
1, 2, 3 …といった番号で処理したいのであれば、TextBox や PictureBox を
配列や List や Dictionary で管理することも検討した方が良いかもしれません。

今の実装だと、コントロールが増えた時のコードが冗長的ですし、
記述ミスの可能性も増えてしまいますので。

たとえば先のコードだと、変数 aa 内に TextBox1 がなく、
代わりに TextBox3 が 2 回あるようですが、大丈夫ですか?



それともう一つ。Try~Catch の範囲がいくら何でも広すぎるように思えます。
これでは例外が発生した場合に、どこに問題があったのか把握しづらくなってしまいます。

どの場所でどのような例外が起きる可能性があるのかを、事前に想定できていますか?

Try は処理全体を広く囲うように使うのではなく、できるだけ狭い範囲に対して、
局所的に適用することが望ましいです。(そして闇雲に使うようなものでもありません)

今のコードだと、引数の指定ミスなどによって引き起こされるエラーの類、
たとえば IndexOutOfRangeException や NullReferenceException や
DivideByZeroException などまでも握りつぶされてしまい、
バグの発生箇所を特定しにくくなります。

自身のバグによって引き起こされる例外については、Catch するのではなく、
そもそもそれらが発生しないよう、プログラムを見直すことが肝要です。

例外処理は、事前にチェックするのが難しい異常状態に対処するために使うようにしましょう。
(たとえばファイルの読み書きなど)

投稿者 イヨ   (社会人)   投稿日時 2020/10/12 17:27:49
 魔界の仮面弁士様
返信ありがとうございます。
すいません画像みれなかったのですね


>それぞれのブロック内で a を宣言するのではなく、
>変数 aa のように、それよりも前で宣言すれば OK です。
できました!
Dim a As PictureBox = Nothing のように
先に宣言しておいてからifの中でセットする
とっても参考になりました ありがとうございます


>1, 2, 3 …といった番号で処理したいのであれば、TextBox や PictureBox を
>配列や List や Dictionary で管理することも検討した方が良いかもしれません。
せっかく教えてもらいましたが配列というものがどういう感じで使うのがベストなのかわからなかったのでいろいろコードいじって勉強します


>たとえば先のコードだと、変数 aa 内に TextBox1 がなく、
>代わりに TextBox3 が 2 回あるようですが、大丈夫ですか?
ミスです。。 
Dim barcode As String = $"{TextBox2.Text}{TextBox3.Text}{TextBox4.Text}{TextBox5.Text}{TextBox6.Text}"になります
aaはbarcodeとしました。


>それともう一つ。Try~Catch の範囲がいくら何でも広すぎるように思えます。
>これでは例外が発生した場合に、どこに問題があったのか把握しづらくなってしまいます。
Subブロックごとに Try~Catchはとりあえず付けとくという認識でした
仰る通り、たしかに大きく囲うと、どこにどんなエラーが出てるか見つけずらいです。。
闇雲に使わず局部的に使っていきたいと思います。


こんな感じで書き直したらうごきました
ありがとうございますmom

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim barcode As String = $"{TextBox2.Text}{TextBox3.Text}{TextBox4.Text}{TextBox5.Text}{TextBox6.Text}"
        Dim PictureBox As PictureBox = Nothing
        Dim maxheight As Integer = 40
        Dim barcode39 As Code39BarcodeDraw = BarcodeDrawFactory.Code39WithoutChecksum
        Dim img As Image = barcode39.Draw(barcode, maxheight)


        If barcode.Length = 15 Then 'バーコードに反映させる文字数確認15文字なら 
            If ComboBox1.SelectedItem = 1 Then 'コンボボックスで1が選ばれてたら 
                PictureBox = PictureBox1    'それぞれのブロック内で PictureBox をセット  
                If TextBox2.TextLength > 0 Then 'TextBox2に何か値が入っていたら 
                    PictureBox.Image = img 'PictureBoxにimgをセット 
                    LabelVal1.Text = barcode
                End If

            ElseIf ComboBox1.SelectedItem = 2 Then
                PictureBox = PictureBox2
                If TextBox2.TextLength > 0 Then
                    PictureBox.Image = img
                    LabelVal2.Text = barcode
                End If

            ElseIf ComboBox1.SelectedItem = 3 Then
                PictureBox = PictureBox3
                If TextBox2.TextLength > 0 Then
                    PictureBox.Image = img
                    LabelVal3.Text = barcode
                End If

            ElseIf ComboBox1.SelectedItem = 4 Then
                PictureBox = PictureBox4
                If TextBox2.TextLength > 0 Then
                    PictureBox.Image = img
                    LabelVal4.Text = barcode
                End If
            End If
        Else
            MsgBox("全15文字で入力してください")
        End If

        If PictureBox IsNot Nothing Then
            MsgBox("ないです><")
            PictureBox.Image = img   ' a が Nothing では無かった場合は画像を差し替え  
        End If
    End Sub