VBAプログラミング

わずかな知識で VBA!

VBAプログラミング


 

ゲームで覚えるVBAプログラミング



  キーボードや、マウスの操作を記録するマクロも、
  中身は、VBAで書かれたプロシージャだということがわかったと思います。

  ここでは、いよいよVBAプログラミングという部分に入ります!

  コンピュータは、人間のように物事を柔軟には解釈してくれません。
 
 そのためにさまざまな規則がありますが、
  最初は簡単なものからはじめて、
  VBAプログラミングのスキルを少しずつアップしていけば、
  意外と簡単にマスターできると思います。
      

わずかな知識で
VBA!







  楽しみながらVBAプログラミングを理解していくために、ここでは、サイコロによる
  「ブラックジャック」ゲームを作成し、そのプロシージャを細かく説明してみようと思います。

  ゲームだからといって馬鹿にしないように。
  VBAプログラミングに必要な基礎的な知識の説明が十分に入っております。

  「ちょっと複雑にしすぎたかな?」と反省するくらいのものになってしまいました。


      

   
  ゲームの説明

  1. ゲーム参加者の名前を成績表の名前欄に入力し、「SET」ボタンにより初期化します。

  2. 2つのサイコロを振るか、1つのサイコロを振るかは、参加者が選択します。

  3. それぞれのボタンをクリックすると、1から6までの数字がランダムに選択され、
   左側にあるサイコロ欄に入力されます。

  4. 1順目は、左側の人から開始し、2順目以降は成績の低い人から上部に名前が表示されるので、
   その順番でサイコロを振ります。

  5. 21(ブラックジャック)になるか、または、それ以上になればその人のゲームは終了です。
    ただし、成績が20未満でも、4回までしかサイコロは振れません。4回振って合計が17以下は、ドボンと同じです。

  使用目的:職場などで、ジュース等を賭けてお楽しみいただけます。

  

 
 基本は表

  VBAプログラミングといっても、本質はExcelが持っている表計算などの機能にあり、
  表を作成する補助としてプロシージャを作成することが本来の使用方法だと思います。

  計算を含め、全てをマクロで行うのではなく、Excelの表計算の機能を使用して操作を自動化していきます。


  この例では、サイコロの目の集計と個人別成績の集計は「オートサム」で、
  成績判断は「Ifステートメント」で行わせています。

Download サイコロ.xls (圧縮 Saikoro.lzh 74Kバイト)

   *Excelの初期設定では、「マクロのセキュリティ」が「高」に設定されています。
     マクロを動作させるためにはこの設定を「中」以下に変更する必要があります。

  このゲームの様に、あらかじめ計算式等が入力されているシートを利用する場合は、
  注意しなければならないことがあります。

  それは、使用者による変更が出来ないように保護することです。

  これはとてもだいじなことで、自分だけが使用する場合には必要ないと思いますが、
  他人が使用する場合には必ず必要になります。

  計算式の書き換えや消去、ドラグアンドドロップによるセルの移動など、
  Excelには便利な機能がたくさんありますが、特に初心者の方は自覚なしにその操作を行いがちです。

  ユーザーの無意識(?)な操作により、たとえば、表にある何かしらのキーワードを元に入力位置を探しても、
  キーワードが見つからずにエラーとなったり、数式が消去されていたりなど、
  マクロがエラーとなる原因はたくさんあります。

  そこで、それらの予防手段として、シートに保護をかけます。

  では、マクロによる保護のかけ方を紹介します。


    


  1. 「Alt」+ 「F11」キーでVBEの画面を開きます。

  2. プロジェクトエクスプローラーで、マクロを登録したいブックの「ThisWorkbook」を選択して、
    「コードの表示」ボタンをクリックします。

  3. オブジェクトボックスで「Workbook」を選択し、プロシージャボックスで「Open」を選択します。

  4. 自動的に
    Private Sub Workbook_Open()

    End Sub


     が作成されます。
 
    この間に書かれたプロシージャは、ブックが開かれたときに実行されます。

     Private Sub Workbook_Open()
       With Worksheets("サイコロ")
.         Protect Password:="sheet85", _
               userinterfaceonly:=True          
1
         .Range("A1:M35").Name = "表示範囲"      
2
         .ScrollArea = "表示範囲"                
3
         .EnableSelection = xlUnlockedCells         
4
       End With
       Application.DisplayScrollBars = False          
5
     End Sub


  1. シートサイコロに「Sheet85」というパスワードをつけて保護をかけています。

    また、保護をかけたままだとマクロからも操作できなくなるため、マクロからの操作はできるようにしておきます。
   それが、「userinterfaceonly:=True」です。

   この手のプロパティ値は、Trueが有効で、Falseが無効です。

  2,3. セル(A1)から(M35)の範囲に「表示範囲」という名前を付けて、
    スクロールエリア(ユーザーがスクロールして表示できる画面の範 囲)に設定しています。

  4. ユーザーが、選択できるセルをあらかじめエクセルの「オプション」から
    保護の「ロック」を解除したセルだけに設定しています。こうすると、保護のかかっているセルは、
    選択することも出来なくなります。

  5. 垂直、水平スクロールバーを画面から消してみました。
    (必ず必要な操作ではありません。ちょっとしたカッコづけです。)
    水平スクロールバーだけを非表示にする場合は、Windowsコレクションに対して

      Windows("Book1").DisplayHorizontalScrollBar = False

    同様に、垂直スクロールバーだけを非表示にする場合は

      Windows("Book1").DisplayVerticalScrollBar = False

    とします。

   このようにVBAでは、
   あるオブジェクトの中にある特定のオブジェクトのプロパティに対して何らかの値をセットする

   または、

   あるオブジェクトの中にある特定のオブジェクトに特定のメソッドを実行する。

   という形で命令を記述していきます。


  この作業に加えて、画面の罫線を消し、ツールバーも全て消して、大画面表示に変更すれば完璧?です。
  (必ず必要な操作ではありません。)

  これらの操作は「マクロの記録」で記録できるので、試してみるといいでしょう。
  ただし、ユーザーの画面には、どのツールバーが表示されているかわかりません。

  どうしたらいいのでしょうか?

  答えは、全てのツールバーを表示しないようにすればいいのです。

  エクセルでは、このように表示されていないものに対して、
  「表示しない」という操作を指示してもエラーにはならないからです。

  このへんの知識はやっていくうちにわかってきます。

  ここでちょっと注意
 
  マクロで、あまり凝ったものは作成しないようにしましょう。

  たとえば、画面の装飾に凝ったり、高度なテクニックを追求して使用したりすることです。
  販売目的や、仕事が暇なときにはいいですが、必要でない作業に多くの労力を注ぎこみすぎると、
  実際の仕事が進まなくなります。

  マクロ作成の主目的は、あくまでも作業を自動化することにあります。
  画面が汚くても仕事が進めばいいのです。マクロばかり改造していても 仕事は進みませんよ!(経験者談)


  全てのシートに保護をかける

  このゲームでは、一つのシートに保護をかけていますが、
  開いたブックの全てのシートに、保護をかける方法を説明しておきます。

  Private Sub Workbook_Open()

    Dim Wsheet As Worksheet             
1
    Application.ScreenUpdating = False       
2
    For Each Wsheet In Worksheets         
3
    Wsheet.Protect Password:="sheet85", _
       userinterfaceonly:=True
    Next Wsheet
    Application.ScreenUpdating = True        
4
  End Sub


  1.変数宣言行 「Wsheet」をワークシートオブジェク変数に宣言

  2.プロシージャが実行されると、リアルタイムに画面表示が更新されます。
   場合によっては画面がちらつくので、スクリーンの更新を止めるように設定する方法で

   Applicationオブジェクトに対しScreenUpdatingプロパティにFlseを設定します。

  3.ワークシートコレクションの中の全てのワークシートに同じ作業を繰り返す。

   ここでは、「For Each Next」ステートメントを用いて「Sheet85」というパスワードで保護をかけています。

   先ほどと同じように、保護をかけたままだとマクロからも操作できなくなるため、
   マクロからの操作はできるようにしておきます。 
     Wsheet.Protect Password:="sheet85", _
         userinterfaceonly:=True


   は、1行のステートメントですが、横に長いと見づらくなるので、
   「 _ 」(ブランク + 「Shift(ろ)」)で2行に分けています。

  4.先ほど無効にした画面更新を有効にします。

 

  全てのシートの保護を解除する

  シートを保護すると、保護を解除して直接手作業で修正したいときもあるので、
  シート全ての保護を解除する方法も書いておきます。

     Dim Wsheet As Worksheet
     Application.ScreenUpdating = False
     For Each Wsheet In Worksheets
     Wsheet.Unprotect Password:="sheet85"
     Next Wsheet
     Application.ScreenUpdating = True


  隠したツールバーを表示する。

  次に、先ほどスクロールバーを非表示にしたので、このまま「サイコロ.xls」を終了しますと、
  スクロールバーがない状態になっています。

  そのままでは次にExcelを使用する時に不便なので、
  「サイコロ.xls」を閉じる前にスクロールバーを表示するプロシージャを作成します。

   

   1.プロジェクトエクスプローラーで「ThisWorkbook」を選択し、オブジェクトボックスで「BeforeClose」を選択します。

   2.先ほどと同じように、自動的に作成されたプロシージャの宣言ステートメントの間に

     Private Sub Workbook_BeforeClose(Cancel As Boolean)
        Application.DisplayScrollBars = True
     End Sub


    上記のように記入すれば、ブックが閉じられる前にスクロールバーを表示して終了します。



  では、いよいよ本題に入ります。

  1.「Set」ボタンに登録するプロシージャの作成です。

    ここでは、入力表や、サイコロの値を消去して、名前欄の一番左の人を上部に表示する初期設定を行います。

      Sub syokisetto()
         Dim na1 As String                
1
          Range("O5:P12").ClearContents      
2
         Range("C15:J19").ClearContents      
3
         narabi                        
4
         Set setna = Range("O5")           
5
         na1 = setna.Value                
6
         If na1 = "" Then
            MsgBox "名前を入力して下さい!", vbInformation, "ゲーム開始方法"
            Exit Sub
         End If
         Range("E2").Value = na1 & "さんの番です!" 
7
         Range("E2").Font.ColorIndex = 5          
8
         
'Range("E2").Speak                  9
         Range("C5").Value = ""              
10
         Range("C7").Value = ""             
  11

      End Sub


    1. 変数宣言行 「na1」:文字列変数

    2.点数順に並べるテーブルを消去
     2順目以降は、成績の悪い順になるため、そのために「O5:P12」に作成してあるテーブルを消去。

    3.点数表消去

    4.並び替えプロシージャ
     同じ作業を他のプロシージャでも何度も行うため、別のプロシージャにして、
     ここでそれを呼び出しその操作を行っています。

     このように、プローシージャの中からも、他のプロシージャを名前で呼び出して使用できます。

    5.Setステートメントです。非常に便利で、多用しています。
     参照セルを他のブックやシートのセルに設定することができ、
     Offsetプロパティと組み合わせれば、データベースの検索も自由自在に行えます。

     ここでは、「narabi」サブルーチンで、順番テーブルを作成しているので、
     そのテーブル一番上の名前のセルに参照セル(setna)をセットして、今後の操作に備えます。

     「setna」は、他のプロシージャでも共用しているため、このプローシージャ内では変数宣言していません。
     「変数」の詳細は「変数」の章で説明します。

    6.変数「na1」に参照セルに入力されている名前を代入しています。
     Ifステートメントで名前が入力されていない場合の処理を設定しています。
  
     名前が入力されていない場合はMsgBox関数でメッセージを表示して「Exit Sub」で処理を終了します。

                   

       Setステートメント
       Ifステートメント
       MsgBox関数

    名前が何も入力されていない状態で実行すると、エラーとなる操作もあるので、
    このボタンだけでなく、それぞれのボタン全てに同じような処理を加えています。
     どこにでもいる(?) 何も考えずにボタンをクリックする足が8本もある人の、操作に備えています。


    7.次に、ゲームをする人の名前に「**さんの番です!」を付けて、上部セルに入力します。
     これで、ゲームの参加者に、次は誰がサイコロを振ればいいか知らせます。

    8.ゲームが終了すると、順番の表示欄のフォントの色を「赤」に設定し「ゲームの終了」を表示しているため、
     フォントの色を「青」に戻しておきます。

    9.行頭に「’」(シングルコーテーション)を付けて眠らせていますが、エクセルに名前を読ませます。
     (あなたのエクセルに読み上げ機能が付いている場合は、シングルコーテーションを消去してください。)

    10,11 さいの目の値が表示されるセルの値を消去しています。消去の順番に意味はありません。


  2.サイコロを振る順番を決めるためのプロシージャです。

    行っていることは、順番テーブルに名前と合計点数を記入し、
    点数の低い順にソートして、順番に並べ替えています。

    これは、SubではなくてFunctionプロシージャにしていますが、
    Functuionにすると、ツールバーの「マクロ」の一覧には表示されないので、ここでは使ってみました。
    確認してみてください。

    Functionプロシージャは、ユーザー設定関数を作成するときに主に使います。

    Functionプロシージャは、関数と同じように値を返すことができ、
    Subと違って関数として使用する場合は、戻り値のデータ型はプロシージャ名の後ろにAsに続けて指定します。

      Function bunruihou(Number As Integer) As String
         Dim bunrui As String
         Select Case Number
         Case 1
            bunrui = "郵便"
         Case 2
            bunrui = "宅配便"
         Case 3
            bunrui = "自社便"
         Case Else
            bunrui = "持参"
         End Select
         bunruihou = bunrui

      End Function


    Functionの場合は、End subではなくてEnd Functionで終わります。

    この関数では、Select Caseステートメントを使い、

      Numberが「1」なら、「郵便」、

      「2」なら「宅配便」と分類しています。

    Select Caseステートメントは、単純な条件分岐でよく使う構文で、複雑な条件の場合には、

    「If *** Then***」のIfステートメントを使います。

    この関数の使用方法は、エクセルの他の関数と同じで、

    セルC5に番号記入欄を設けている場合
    どこかのセルに 「= bunruihou(C5)」と入力すれば、セルC5の値によって
    あなたが設定した分類方法が表示されます。

    これがユーザー設定関数の例です。

    ユーザー定義関数もマクロと同じで、使用する場合には、
    Functionプロシージャが登録されているBookが開かれている状態でなければなりません。
    たえず使いたい場合はアドインとしてエクセルに登録する方法がお勧めです。

   

  Offsetプロパティ
   
   ここでは、Offsetプロパティを使用して、参照セルの移動や、参照セル近辺のデータを取得しています。

   参照セル.Offset(1、0)は、参照セルの1つ下のセルを指します。

   参照セル.Offset(0、1)は、参照セルの1つ右のセルの指します。

   Value は値を意味します。

   セルB5に値(100)を入力するときは、  Range(“B5”).Value = 100
   セルB5の値を変数(atai)に代入するときは、  Atai = Range(“B5”).Value  です。
  
    Valueプロパティは、値の取得、及び、値と計算式の入力もできますが、
   セルに入力されている計算式を取得することは出来ません。

   計算式を取得したい場合は、 Formulaプロパティを使用してください。

   セルB5に入力されている計算式を変数(Atai)に代入するときは

      Atai = Range(“B5”). Formula   です。




   繰り返し作業を行う Do Loopステートメント

      Function narabi()
         Dim na1 As String
         Dim seth As Range

         '名前取得
         na1 = Range("C14").Value

         '順番テーブル("O5:P12")の入力値を消去
         Range("O5:P12").ClearContents
         'カウンターの初期化
         cntna = 0
         '名前を取得するための参照セル(seth)を点数表にセット
         Set seth = Range("C14")
         '順番テーブルに参照セル(setna)をセット
         Set setna = Range("O5")
         '空白セルに備え、カウンターが8(表の入力可能範囲全てを検索)になるまで
          Do Loopステートメントで繰り返します。

          Do Until Loopステートメントは、条件が揃うまで、繰り返し作業を行います。
      
         ここでは、0に設定したカウンター値が8になるまで続けます。
         なぜ「8」までかというと、名前の記入欄が8個だからです。
      
         ゲームは勝ち抜け戦で行っていき、勝った人から抜けていきます。
         その時に勝った人の名前を消すだけで、次のゲームが始められるよう
         にするため、名前の記入欄すべてをチェックしています。

         Do Until cntna = 8

        '名前が入力されていて、合計欄の点数が20以下の場合にテーブルに名前を入力します。
        21以上は「ブラックジャック」か「ドボン」で、ゲームが終了しているからです。

           If seth.Value <> "" And seth.Offset(6, 0).Value < 21 Then
  
              'na1へ名前を代入」
              na1 = seth.Value
  
              '順番テーブルにある参照セル(setna)に「na1」を入力
              setna.Value = na1
  
              '参照セル(seth)の6行下の合計値を取得
              suuti = seth.Offset(6, 0).Value
    
              順番テーブルにある参照セル(setna)のひとつ右側のセルに合計値を入力
              setna.Offset(0, 1).Value = suuti

              '順番テーブルの下のセルへ参照セル(setna)をセット
              Set setna = setna.Offset(1, 0)
          End If
          cntna = cntna + 1

  
          '次の名前を取得するため、点数表の一つ右側のセルに参照セル(seth)をセット
          Set seth = seth.Offset(0, 1)
       Loop


    名前のチェックが完了し、該当者が一人もいなくなったとき(ゲーム終了時)のチェックが次の作業です。
       If Range("O5").Value = "" Then
          misu = "終了"
          Exit Function
       End If


    順番テーブルの先頭欄が空白の場合はゲームの終了時です。
    その時には「misu」という変数に「終了」を代入してFunctionから抜けています。


    プロシージャの途中で、このように違うプロシージャを実行した場合、正常に最後まで実行された場合でも、
    このように途中で終了した場合でも、呼び出した側のプロシージャは、
    何もわからずにそのまま次のステートメントを実行してしまいます。

    ゲームが終了しているにも関わらず、次の操作に入ってしまうのを防ぐために、
    その判断基準となる変数(フラグ)を設定し、このプロシージャを呼び出した側のプロシージャに戻った時に、
    その変数の内容を基に処理を変えます。

       narabi
       If misu = "終了" Then
         misu = ""
         GoTo 100
       End If


    ここでは、narabiのプロシージャが終了した後に、変数「misu」が「終了」なら、「misu」を空白にし、
    100番へ飛ばせています。100番は終了処理のはじめの行です。



       Range("O4:P12").SortKey1:=Range("P5"),Order1:=xlAscending,Leader:=xlGuess, _
         OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, SortMethod :=xlPinYin


       順番テーブルの先頭のセルに参照セル(Setna)をセット
       Set setna = Range("O5")
    End Function


    '名前と合計点数の入力された順番テーブルを点数の低い順にソート
    ここは、「マクロの記録」でソート操作をソースコードにし、それを編集した部分です。

   このように、マクロは、単純な作業を飽きずにひとつひとつ繰り返し行います。


  3.「サイコロを振る」ボタンの説明です。

       

    「2個のサイコロを振る」と「1個のサイコロを振る」のプロシージャの違いは、
    サイコロの数だけなので、作成時もコピーして作成しましたが、

     「misu」と同じような変数を使用して、同じプロシージャを利用する方法もあります。

    まず、Module1のプロシージャの外に記述した内容です。

       


     Option Explicit
     Public setna As Range
     Public misu As String
     Dim cnta As Long
     Dim setnyu As Range

――――――――――――――――――――――――――――――――――――――――――――

  変数の宣言

  変数は、「Dim」ステートメントを使ってデータの型と共に宣言します。

  変数の宣言は、通常は、プロシージャ定義の先頭行で行います。
  Sub・・・ あるいは、Function・・・と書かれたすぐ下です。

    例
     Sub nyuryokuiti()
       Dim na1 As String

 

  変数というのは物をいれておく箱みたいなもので、
  実際の処理に入る前に、その中で使う変数を全て宣言しておきます。
   詳しくは、変数の章をご覧ください。

  実際には特に宣言をしなくて、ソースの中でいきなり使用してもエラーにはなりません。
  
  それは、VBAには、「Variant型」という「どんな型のデータでも受け入れてくれる」
  便利(?)なデータ型があるからですが、宣言なしで使用された変数は、
  すべてこの型に設定されてしまいます。
 
  ですが、このような使い方はできるだけ避けるようにします。
  というのは、変数は、名前を付けられたメモリー領域のことだからです。  

  どんな型のデータも入るようにするため、「Variant型」の変数は、
  他の変数に比べ非常に多くのメモリーを必要とし、
  Variant型の変数の多用は、処理速度の低下も招きます。
 
  このVariant型の存在が、プログラムミスの原因となることがあります。
  
  ソースの先頭行で正しく変数を宣言したとしても、変数名を入力したときにスペリングミスを犯すと、
  その変数は宣言した変数とは違うVariant型の変数とみなされてしまうからです。

  宣言したはずの変数に代入されるはずのものが、
  スペリングミスのせいで他の変数に代入されてしまいます。

  VBAには、構文エラーを見つける「プロジェクトのコンパイル」という機能がついていますが、
  それを実行しても正常終了してしまいます。
 
  スペリングミスは手作業で入力していくため、防げませんが
  スペリングミスを容易に発見することはできます。
 
  それが、「Option Explicit」ステートメントです。

  このステートメントを各Moduleの先頭で宣言すると、宣言した変数以外は使用できなくなります。
  つまり、実行時にエラーと判断されるわけです。

  また、「プロジェクトのコンパイル」でスペリングミスをした変数を見つけることができ、大変便利です。

  新しくモジュールを作成するたびに、
  「Option Explicit」ステートメントを自動的に挿入されるようにすることもできます。
 
  VBEのメニューから「ツール(T)」⇒「オプション(O)」を選択し、
  表示されたダイアログボックスの「変数の宣言を強制する(R)」チェックボックスにチェックマークを入れます。


       

  変数の通用範囲

    変数の宣言は、通常は、プロシージャ定義の先頭行、
    Sub・・・ あるいは、Function・・・と書かれたすぐ下で行うと書きました。

    つまり、
    そのプロシージャ内で宣言したことになります。
    この場合、宣言された変数は、そのプロシージャの中だけで利用できるようになります。

    プロシージャが終了してしまうとその変数も消えてしまい、
    当然、代入も、その値を参照することもできなくなります。
  
    しかし、同じ変数を複数のプロシージャで利用したい場合もあります。
    そのような場合は、プロシージャの外、コードウィンドウの一番上で宣言します。
    マウスでカーソルを置いて「Enter」キーを押し、空白行を作ってそこに入力します。
    そこにDimステートメントで宣言した変数は、そのモジュール内の全てのプロシージャで利用できます。

    また、全てのモジュール内のプロシージャで利用したい変数もあります。
    その場合は「Public」ステートメントを使って宣言します。

    ただし、Publicステートメントで宣言した変数は、どのプロシージャからも変更が可能なため、
    プログラミングする上では、注意が必要です。
    また、宣言する場所もモジュール1に限定するなどして、わかりやすくしておくべきでしょう。
 
    エクセルでは、ワークシート上のセルを利用すれば、
    Publicステートメントで宣言する変数はあまり必要ないと思います。
  
    このゲームの変数で、「setna」と「misu」はPublicステートメントで宣言していますが、
    実際には、モジュール2に書かれているプロシージャをモジュール1に書けば、
    Dimステートメントで宣言すればいいようになります。


  
  変数の型

    簡単にここで使用している変数の型を説明します。

    Long   長整数型   大きな桁の整数値を保存します。
    String  文字列型   文字列を保存します。
    Range  Object型   オブジェクトへの参照を保存します。

  -----------------------------------------------------------------------------------


  4.プロシージャ内から呼び出すもう一つのプロシージャの説明です。

    このプロシージャは、それぞれの「サイコロを振る」ボタンがクリックされたときに、
    その数値の入力位置を探す操作です。

    他のプロシージャの操作で、セルE2にサイコロを振る人の名前が表示されています。
    その名前を取得して、点数の入力位置を探していきます。

      


    これも、「Function」にしていますが、私がサブルーチンをFunctionにしているだけで、
    特別な意味はありません。

    Functionも、戻り値を設定しなければ、Subと同じように使用できます。
    また、マクロの一覧に表示されないという利点(?)もあります。

      Function nyuryokuiti()
         Dim na1 As String

        ‘変数「misu」の初期化
         misu = “”
         セルE2に表示されている名前を取得します。
         na1 = Range("E2").Value
  
       名前は「**さんの番です!」となっているので、その文字を取って名前だけにします。
       「Replace関数」を使用して「さんの番です!」を空白と置き換えてその操作を行っています。
       後ろの「, 1, -1, 1」は引数で省略可能です。

         na1 = Replace(na1, "さんの番です!", "", 1, -1, 1)
  
       '参照セルを表の名前欄へセットして、
       Do Loop Untilステートメントを使用して、
       同じ名前の欄まで一つずつ右に参照セルを送る作業を繰り返します。
        Set setnyu = Range("C14")
        Do Until setnyu.Value = na1
           On Error GoTo 1000
           Set setnyu = setnyu.Offset(0, 1)
           On Error GoTo 0
        Loop


    エラーに備える

      順番テーブルを作成した後に、名前が書き換えられた場合、
      順番テーブルの名前と入力表の名前が異なってしまいます。

      その場合でもエクセルは、同じ名前になるまで参照セルを一つずつ右に送り続け、
      列が無くなったところでエラーとなります。

      そのエラーを予測してトラップをしかけています。

      エラーが起きそうなソースの前に、「On Error GoTo」ステートメントを記述し、
      エラーになったら1000番地にとばします。

      そのエラーとなりそうなソースが終了したら「On Error GoTo 0」で無効化します。

      これを行わないと、「On Error GoTo」ステートメント以降で起こったエラーは、
      全て1000番地に飛んでしまい、違う理由で起きたエラーも同じ処理になってしまいます。

      「On Error GoTo」ステートメントの他に、「On Error Resume Next」ステートメントがあり、
      こちらはエラーを無視して次の行のソースを実行します。
 
     別のやり方として、カウンター値を利用する方法もあります。
     その場合は、Do Loop Untilステートメントが終了したときにカウンター値をチェックし、
     エラーの場合はエラー処理へ飛ばします。

    
     同じ名前の欄に来たら、こんどはその列の空白のセルを下方へ捜していきます。

       Set setnyu = setnyu.Offset(1, 0)
       cnta = 0

       'あいている欄までループ
       Do Until setnyu.Value = "" Or cnta = 4
          Set setnyu = setnyu.Offset(1, 0)
          cnta = cnta + 1
       Loop
       Exit Function


     1000番地以降はエラー処理のため、ここで「Exit Function」で終了処理を記述します。
     そうしないと、通常終了したものまで、エラー処理に移ってしまうからです。
  
  1000
       MsgBox "ゲーム中に名前が変更されました。「SET」ボタンを押してゲームをやり直してください!",  _
             64, "操作手順!"
       misu = “set”
     End Function


   このエラー処理では、MsgBox関数を使ってエラーが起きた時の処理方法を促しています。

   また、変数「misu」に「set」を代入し、
   呼び出し元のプロシージャへエラーがあったことを伝えるキーワードとしています。

   このゲームのプログラムで、エラー処理や間違った操作に対処する処理がいくつかありますが、
   最初からすべてを予測するのはとても難しく、動作確認を重ねてエラーとなる操作を捜し、
   それらに対処していきます。

   MsgBox関数の詳細は別の章で説明しますが簡単に説明しておきます。

   最初に“”(ダブルコーテーション)で囲まれた部分がメッセージで、次の64は組み込み定数の値です。
   クイックヒントでは、「vbinformation」と表示されますが、知っていれば64と入力する方が楽です。

   最後の“”(ダブルコーテーション)で囲まれた部分が、
   表示されるダイアログボックスのタイトルになります。

   この部分を省略すると、タイトル部分には、「Microsoft Excel」が表示され
   オリジナルのシステム風にしていても、おもいっきりExcelだとバレます。

   また、プログラミング中の変数の中身を知りたいときなど、ソースの途中に

      MsgBox misu  

   の様に MsgBox に続けて、内容を知りたい変数名を記述すれば、
   その時の変数の内容を確認する手段ともなります。

 

  5.「2このサイコロを振る」ボタンに登録したプロシージャです。

   ここまで、読まれてきた方なら簡単に理解できると思います。



    

    Sub saikoro()
       変数の宣言行
       Dim sainome As Long
       Dim i As Integer
       Dim na1 As String

        変数「i」の初期化
       i = 0
       名前の取得
       na1 = Range("E2").Value
       名前が空白ならエラー処理を行い、このプロシージャの処理をやめます。
       If na1 = "" Then
          MsgBox "名前を入力して「Set」ボタンを押して下さい!", vbInformation, "ゲーム開始方法"
          Exit Sub
       End If

       '初期設定 それぞれの入力値を消去します。
       Range("C5").Value = ""
       Range("C7").Value = ""

       '表示されるのが1回の結果だけだと一瞬で終わってしまい、面白くありません。
       サイコロが転がっているように見せるため、同じ作業を10回くりかえしています
       Do Until i = 10
         'サイの目1
         sainome = Int(6 * Rnd + 1)
         Range("C5").Value = sainome

         'サイの目2
         sainome = Int(6 * Rnd + 1)
         Range("C7").Value = sainome
         i = i + 1

       Loop

   VBAでランダムな数字を選出する関数は「Rnd」です。
   このようなVBA独自に搭載されている関数を「VBA関数」といいます。

  Excelに搭載されている関数は、「ワークシート関数」といいます。

  Excelのワークシート関数には、同じく乱数を発生させる「RAND」関数があります。
  このように、VBA関数は、ワークシート関数と機能は同じでも、スペリングが違っているものもありますが、
  使用頻度の高いものは、ワークシート関数と同じものが用意されています。

  別の方法として、VBAで、「ワークシート関数」を使用する方法もあります。
  下の例のように、「Application.WorksheetFunction」を使用して記述すればいいのです。

  VBA関数を知らなくても、ワークシート関数を知っていれば求める値が得られます。

     M = 8.2
     I = Application.WorksheetFunction.Round(M,0)

  とっても便利なようですが、全てのワークシート関数が使用できるわけではなく、
  約300個強のうちの174個しか使用できません。

  今回、使用した「RAND」はその174個には入っていません。

       

  そこで、最後(最初?)の手段として、ワークシートを利用して答えを導く方法もあります。
  ワークシートの任意のセルに「RAND」関数を使用した数式を記入して、そのセルの値を取得すればいいのです。

    Range("AA1").FormulaR1C1 = "=TRUNC(RAND()*(7-1)+1,0)"
    sainome = Range("AA1").Value
    Range("AA1").Value = ""


  理想は違うのかもしれませんが、知っている方法があれば、わざわざ難しい方法や知らない方法を探さなくても、
   プログラミングは可能です。

  自分の知識の範囲内で作成していけばいいのです。


       nyuryokuiti
       If misu = “set” Then Exit Sub


      入力位置を捜すプロシージャを呼び出し、
      そのプロシージャの終了後に、プロシージャ内においてミスがあったかどうかを
      Ifステートメントで判断し処理しています。

      ' nyuryokuitiで見つけたセルに数値を入力します。
      setnyu.Value = Range("C9").Value

      '次の名前に参照セル(setna)を移動させます。
      Set setna = setna.Offset(1, 0)

      '参照セルの値が空白なら名簿の最後まできたということなので、
      順番テーブルの並びかえ処理か、回数のチェックを行い4回振っていたら終了処理を行います。

      If setna.Value = "" Then
     '4回までしかフレない
     cnta = cnta + 1
     If cnta = 4 Then
        Range("E2").Value = "ゲーム終了!"
        Range("E2").Font.ColorIndex = 3
        MsgBox "ゲーム終了です!「set」ボタンを押してください。", 64, "プレイ方法!"
        Set setna = Nothing

   
       「setna」用に確保していたメモリーを解放します。
       別に、解放しなくてもエラーとはなりませんが、
       不要なメモリー領域は解放するクセをつけておいたほうがいいと思います。
     
       Exit Sub
     End If

     
並びかえプロシージャを呼び出します。
     narabi


 
     Set setna = Range("O5")
     参照セル(setna)を順番テーブルの先頭行にセットします。

     End If
     na1 = setna.Value
     Beep

     パソコンにビープ音を鳴らせます。

     Range("E2").Value = na1 & "さんの番です!"
     'Range("E2").Speak

     End Sub


  「一つのサイコロを振る」ボタンもサイコロの数が違うだけで、ほぼ同じプロシージャです
  もう少し手を加えれば、同じ部分を一つにまとめて簡略化できますが、
  この程度のマクロならば、コピーペーストして必要箇所を修正したほうが楽なので、これ位で十分です(?)

  どうですか? 一通り説明してきましたが、間に余分な説明が入ったりしてわかりづらかったでしょうか?

  VBAに限らないとは思いますが、さまざまなオブジェクトとそれらを制御するメソッドやプロパティ、関数など、
  さらに、プログラムの実行を制御するたくさんのステートメントや、定数、引数、演算子も用意されていて、
  ウンザリなんて方もいるのではないでしょうか?

  でも、でもです。そんなものは全部覚える必要はありません!(←ちょっと自信ないですが)

  実際に使用するオブジェクトやコントロール、ステートメントの種類はそんなに多くないのです。
  この「ブラックジャック」のプログラムでも、使用しているメソッドやプロパティ、ステートメントは同じものばかりで、
  同じような操作をあちこちで繰り返し使っているだけなのです。

  覚えなければいけないことは、あなたが想像する以上に少ない、ん?、想像以下に少ない(?)、
  意外に少ないのです!


        


  わずかな知識でVBA!       TOP

  マクロで何ができる?   ユーザーインターフェース    マクロの記録   マクロの登録
 
  イベントについて      マクロの編集とデバッグ    ゲームで覚えるVBAプログラミング
 
  オブジェクトの操作     セルの操作            MsgBox関数・InputBox関数
 
  変数の型           ヘルプの活用          イミディエイトウィンドウ  
 
  Withステートメント      Setステートメント
 
  条件分岐のステートメント   If Then Else,Select Case
 
  繰り返しのステートメント   Do Loop
 
  繰り返しのステートメント   For Next
  
  ダイアログボックスを作ってみよう1              ダイアログボックスを作ってみよう2 【実践編】
  
  ActiveXコントロール    各コントロールのプロパティ      文字列の操作        Endプロパティ

  リンク・検索   相互リンク    マイプロフィール       YouTubeの部屋 

Copyright (C) わずかな知識でVBA! All Rights Reserved