MENU

VBAの基礎

VBA共通の基本的な使い方をまとめました。

目次
----
VBE
演算子
変数
制御分
プロシージャ
モジュール
プロジェクト


===================================
..VBE
===================================

よく使うショートカット
F5             実行(継続)
F8             ステップイン
Shift + F8     ステップオーバー
Ctrl           + F8 カーソル行まで実行
F9             ブレークポイント設定
F1             ヘルプ(調べたい語句に文字カーソルを置いて)
F2             オブジェクトブラウザ

Alt + F11      VBE起動
Alt + F8       マクロ実行ダイアログを開く
Ctrl + Space/J 入力候補、自動メンバー表示
               tab space . ( =で確定、enterは改行
               ただし、(数字).の後ではこの機能が働かない
Ctrl + I       クイックヒント
Ctrl + Shift + I パラメータヒント
Ctrl + F3      次を検索(検索ダイアログを閉じた後)
Shift +(Ctrl)+F3 前を検索
Shift + F2     定義元へジャンプ(関数へ)
Ctrl + Shift + F2 元表示していた個所に戻る

Ctrl + ↑、↓  前、後のプロシージャ―へ移動
Ctrl + ←、→  前、後の単語へ移動

Ctrl + Y       1行削除(カット)
Ctrl + Delete  単語の最後まで削除

Atl + R->R     マクロ実行のリセット
Ctrl + Break   プロシージャの強制終了


コメントアウトにアクセスキーを設定
  Alt + /      コメントアウト
  Alt + \      解除
  (設定方法)
    ツールバー->右クリック->ユーザー設定->編集のコメントブロック、非コメントブロックをツールバーへドラッグ
    アイコンをクリック->選択したボタンの編集
      名前=(&/)
      イメージとテキストを表示=True

Option
Option Base 1   配列の添え字を1から始める(デフォルトでは0から)
Option Explicit 変数宣言の強制

 _              改行して記述を続ける場合、半角スペース+アンダーバー(行連結文字)

大文字と小文字の区別はない

'コメント
コメントの例
'--------------------
'関数の機能
'引数:i/説明、s/説明
'戻り値:説明
'--------------------
'***** ブロックの説明 *****


デバッグモードに入る方法
  ブレークポイントを設定する
  コードに Stop を記述する方法
    If i = 5 Then Stop
  コードに Debug.Assert を記述する方法
    Debug.Assert i <> 5 'Falseの場合にデバッグモードに入る
  ウォッチウィンドウに記述する方法
    式がTrueの時に中断
      式に「i > 10」と記入
    式の内容が変化したときに中断
      式に「i」と記入

イミディエイトウィンドウ
  Debug.Print "a"
  Debug.Print i; ' 改行せずに出力
  Debug.Print i, ' タブ区切りで出力

  a=1 : ?a ' 複数の文を1行に記述
  a=1      ' 変数の宣言は不要(不可)、宣言せずに使える
  ?1+1
  ?F1(1) ' 関数の実行
  sub1   ' プロシージャの実行

ローカルウィンドウ

ウォッチウィンドウ
  式i=3
  ウォッチの種類:式がTrueのときに中断

呼び出し履歴
  ローカルウィンドウの左上の「...」ボタンを押すと表示される
  中断モードでのみ表示可
  上にある履歴ほど新しい
  過去に呼び出されたプロシージャ―で使用中の変数を、ローカルウィンドウに表示できる

オブジェクトブラウザ
  F2
  オブジェクトのメソッドやプロパティを調べることができる
  検索文字列は大文字小文字を区別しない

1行に複数のステートメントを記述
i=1:i=2

無限ループをストップさせる方法
  ESC
  Ctrl+Break(連打、長押し)
  必ず中断できるとは限らない
  上記で止まらない場合
    ESCを押しながら、タスクバーのエクセルをクリックする(10回程度)
    ダメなら、Ctrl+Breakを押しながらウィンドウを切り替える
  それでも止まらなければ強制終了(Ctrl+Alt+Del)

Microsoft公式ドキュメントの表記規則
  Sub(先頭が大文字、太字)→VBA固有のキーワード
  a(斜体)→ユーザーが入力
  [a](角かっこ)→省略可能
  {a|b}(波かっこ、パイプ文字)→いずれかを選択
  [a|b](角かっこ、パイプ文字)→いずれかを選択するか、両方とも省略可能


===================================
..演算子
===================================

演算子の優先順位
  算術演算子
  連結演算子
  比較演算子
  論理演算子

算術演算子
  ^   べき乗
  *
  /
  \   割り算の商
  Mod 割り算の余り(剰余)
  +
  -

関数Modとの違い
  10 Mod -3   除算の余り
    両方が正でない場合、下記の2つの結果は異なる
      10 Mod -3→1
      =Mod(10,-3)→-2

連結演算子
  &
  + 算術演算子と区別が難しいため使わないほうがよい
      Debug.Print "10"+"10" →1010

比較演算子
  =
  <>
  <
  >
  <=
  >=
  Is
  Like

Is演算子
  2つのオブジェクト型の参照が等しいかを判定する
    obj1 Is Obj2
    obj1 Is Nothing
    obj1 = Obj2 '不可
  Rangeには使えない
    Rangeは取得するたびに別のアドレスに格納されるため
    Addressプロパティを使って比較する

Like演算子
  "abc" Like "*c"
  a?b   任意の1文字
  *c    0文字以上の文字
  1#    任意の1桁の数字(全角数字を含む)
  [abc] abcの任意の1文字
  [!abc]abc以外の任意の1文字
  [a-z] a~z

論理演算子
  Not
  And
  Or
  Xor
  Eqv
  Imp

A Xor B
  排他的論理和
  AとBの片方のみがTrueのときTrueを返す

A Eqv B
  論理等価
  AとBの両方がTrue、または、両方がFalseのときTrueを返す
  A←→B、AとBは同値

A Imp B
  論理包含、implication
  AがFalse、または、BがTrueのときTrueを返す
  AがTrue、かつ、BがFalseのときFalseを返す
  A→B、AならばB、AがBに含まれている

ビット演算子
  And
  Or
  Not
  Xor
(ビット演算子の例)
If(1 And 3) Then → True(非0)となる
And
    1= 0 0 0 1
  1+2= 0 0 1 1
  結果 0 0 0 1


===================================
..変数
===================================

変数名の記述法
  キャメル記法
    userName
    ローカル変数
  パスカル記法
    UserName
    グローバル変数、プロシージャ
  スネーク記法
    user_name
  大文字記法(アッパースネーク記法)
    USER_NAME
    定数
  ハンガリアン記法
    strUserName
  その他
    ラベル Error_Handler:

変数名の方針
  英単語を使う
  変数は名詞、プロシージャは動詞で始める
  配列は複数形

識別子(変数、定数、プロシージャなどの名前)の名目規則
  数字、記号で始めることはできない
  記号(!、ピリオド)、スペースは使えない
  255文字以内

PrivateとPublic
  省略時の既定
    Private扱い
      外部変数(Dimで宣言した場合)、Const
    Public扱い
      プロシージャ(Sub、Function)
    Typeの定義は標準モジュールではPublic扱い。それ以外のモジュールではPrivate扱い。
  標準Moduleでしか宣言できない
    Public
      定数、配列、ユーザー定義型の変数、ユーザー定義型の定義(Type)

外部変数(パブリック変数、モジュールレベル変数)
  宣言セクションに記述
  Public s As String      全モジュールで有効
  Private s As String     モジュール内で有効
  Dim s As String         Private扱い(一般的には、Dimはプロシージャー内で使う)
  外部変数はマクロが終了しても初期化されない
    Endステートメントで終了したときに初期化される
    Endステートメントはすべてのコードの実行を強制終了する(通常は使わない)

ローカル変数(プロシージャレベル変数)
  Dim s1 As String,s2 As String
  Static s As String   実行後も値が保持される(宣言セクションでは使えない)
  Dim s As String : Set s = "abc"
  Dim x      データ型を省略するとVariant型

変数の型
  Byte      0~255
  Integer   -32,768~32,767
  Long      -21億~21億(4byte)
  Single    4byte
  Double    8byte
  Variant   16byte(数値、文字列、日付型など何でも入れられる)
  Currency  通貨型、小数点の左側に15桁、右側に4桁の固定小数点数
            小数点以下が4桁以内なら演算誤差は出ない
            書式設定されていないセルに出力すると通貨記号が付く
  Date
  String
  Object    オブジェクトへの参照を格納する、If obj1 Is Nothing Then

初期値
  0         Byte、Integer、Long、Single、Double、Currency
            Date(1899/12/30 00:00:00)
            Boolean(False)
  Empty     Variant
            Nothing Object、Range
  ""        String型の初期値vbNullStringとほぼ同じ
  Null      Variant(ほとんど使われない)

小数以下の演算誤差
  コンピューターでは小数点以下を正しく計算できない
  VBAでは、Double、Singleを使った場合に演算誤差が発生する
  理由
    10進数の0.1は、2進数では0.0001100110011・・・と表現できない
  例
    d1 = 1
    d2 = 0.1
    d3 = d1-d2 →d3は0.9とならない
  対応策
    Currency型を使う(小数点以下が4桁以内の場合)→簡単で確実
    必要な桁数で丸める(誤差はずっと小さい小数で発生しているため
      d3 = round(d1-d2,1)
      d3 = format(d1-d2,"0.0")
    Dicimal型を使う→型宣言できないため扱いづらい
      変数はVariantで宣言
      CDec関数を使う
  数値リテラルに型宣言文字を付与する
    @0.9 = @1 - @0.1 'True
    型宣言文字
      % Integer
      & Long
      ! Single
      # Double
      @ Currency

定数
  Private Const A = 10
  Private Const A As Integer = 10
  Public Const A  = "abc" 
  Const A = "abc"
  Publicは標準モジュールの宣言セクションでのみ可
  宣言セクションで省略した場合はPrivate扱い
  プロシージャ内で使う場合はPrivate、Publicを付けない
  定数の配列は不可
  定数の宣言は、値の代入を兼ねる
  右辺はリテラル、他の定数。右辺に変数や関数は使えない
  Object型変数は定数とすることができない

静的変数
  Static s As String
  プロシージャ内で宣言する、プロシージャ―が終了しても保持される

列挙型
  Private Enum e
    i1 = 1
    i2 = 4
  End Enum
  Debug.Print e.a
  Const定数をまとめたもの
  列挙型のメンバーが持てる値は整数値のみ

ユーザー定義型(他の言語では構造体と呼ばれる)
  Private Type Type1
    s As String
    i As Integer
  End Type
  Sub Sub1()
    Dim t1 As Type1
    t1.s = "abc"
  End Sub
  Sub Sbu2()
    Dim t1() As Type1
    Dim i As Integer
    For i = 1 to 10
      Redim Preserve t1(i)
      t1(i).s = "a"
    Next
  End Sub
  宣言セクションで定義
  標準モジュールでは既定でPublic、それ以外のモジュールではPrivateとなる
  Publicは標準モジュールでのみ定義可
  要素を配列で宣言できない
  要素のデータ型を指定する必要がある
  参照渡しのみ
  Variant、Collection、Dictionaryに入れられない
  1つの変数に複数の異なるデータ型の値を格納できる
  クラスを使っても同様のことができる

配列
  Dim i(2) As Integer  固定配列、i(0)~i(2)
                       Option Base 1ではi(1)~i(2)
  Dim i(2 to 4) As Integer  i(2)~i(4)
  Dim i(2,2)           二次元配列、最大60次元まで
  Dim i() As Integer   動的配列
    ReDim i(2)         既存データは初期化される
                       インデックスの下限の変更可 ReDim i(3 To 5)
                       二次元以上の配列の変更可
                       次元数の変更可
    ReDim Preserve i(2)既存データを保持したまま要素数を変更
                       インデックスの下限の変更は不可 ×ReDim Preserve i(3 To 5)
                       2次元以上の配列では最終次元のみ変更可
                         それ以外の次元を変更しようとするとエラー発生
                       →Collectionオブジェクトを使う
                         worksheetFunction.transpose()を使う
                       次元数の変更は不可(2次元→3次元など)
  Dim i As Integer  動的配列(省略)
    ReDim i(100)

配列の初期値のセット
  Dim v As Variant
  v = Array("A", "B", "C")
  v = Array(0,1,5)
  
  Dim v(1,2) As Variant
  v = Array(Array(1,1,1),Array(1,1,1),Array(1,1,1))
  
  Dim ss() As String '動的配列、または、Variant型で宣言
  Dim v As Variant
  ss = Split("a,b,c", ",")'戻り値の配列の添え字の下限値は常に0(Option Baseに関わらず)
  v = Split("a,b,c", ",")

配列の出力
  Debug.Print Join(ss) 'a b c
  Debug.Print Join(ss,",") 'a,b,c
  Debug.Print Filter(ss,"b")(0) 'b(bを含む要素を抽出)、Filterの添え字の下限値は常に0(Option Baseに関わらず)

配列の初期化と解放
  Erase i
    固定配列の場合、要素が初期化される。メモリは解放されない
    動的配列の場合、メモリが解放される。再使用する場合は、Redimを使う

UBound
  配列で使用できるインデックスの最大値(Option Base 0の場合は要素数ではない)
  For i = 0 To UBound(v)
  For i = 0 To UBound(v,2) 2次元目、2次元目がない配列の場合はエラー
  For i = LBound(v) To UBound(v)
  
  i = WorksheetFunction.sum(v) '配列の合計

多次元配列への代入
  Dim v(5, 10) As string
  For i = 1 To 5
    For j = 1 To 10
      v(i, j) = "abc"
    Next
  Next

配列から配列への代入
  Dim ss1() as String
  Dim ss2() as String
  Dim ss3(2) as String
  ss1 = ss2  動的 = 動的(可能)
  ss1 = ss3  動的 = 静的(可能)
  型が一致していないと代入できない
  静的配列には代入できない

配列の結合
  v1 = Split(Join(ss1,",") & "," & Join(ss2,","), ",") 'ただし配列内に,を含まない
  Joinは二次元配列では使えない

配列の代わりにDictionaryやCollectionを使ったほうがよい場合も多い

配列とRange
  Dim ss(5,5) As string
  Dim ss(5) As string
  r = ss
  rの範囲内のみに代入
  代入する値が配列にない場合は「#N/A」(2次元配列)か「0」(1次元配列)が代入される
  
  r(1).Resize(UBound(ss,1),UBound(ss,2) = ss

  Dim v()  As Variant
  v = r
  vのサイズはrの範囲に応じて自動的に決定される
  Option Baseに関わらず添え字の下限値は1

連想配列
  DictionaryとCollectionの違い
  Dictionary(こちらを使う方がよい)
    多くの点でCollectionの上位互換となっている
  Collection
    Keyに日付、数値を格納できない
    Keyは省略可
    異なるデータ型を格納できる
    Addメソッドの引数が多い(Before、Afterがある)

Dictionary(辞書型)
  Dim obj1 As Object
  Set obj1 = CreateObject("Scripting.Dictionary") 参照設定不要
  obj1.Add "key1", 10  格納される項目(値)は任意の型
  obj1.Count
  obj1.Item("key1")
  obj1("key1")
  obj1.Key("key1") = "key2" keyの変更
  obj1.Add("key1", 20)  代入
  If obj1.Exists("key1") Then
  v = obj.Items  配列vに項目(値)返す
  v = obj.Keys   配列vにkeyを返す
  obj1.Remove("key1") keyと項目(値)の削除
  obj1.RemoveAll      全削除
二次元のDictionary
  Dim dic1 As Object
  Dim dic2 As Object
  Set dic1 = CreateObject("Scripting.Dictionary")
  Set dic2 = CreateObject("Scripting.Dictionary")
  dic2.Add "key2_1","a"
  dic2.Add "key2_2","b"
  dic1.Add "key1_1",dic2
  Set dic2 = CreateObject("Scripting.Dictionary")
  dic2.Add "key2_1","c"
  dic2.Add "key2_2","d"
  dic1.Add "key1_2",dic2
  Dim v1 As Variant
  Dim v2 As Variant
  For Each v1 In dic1.keys
    For Each v2 In dic1(v1).keys
      Debug.Print dic1(v1)(v2)
    Next
  Next

Collection
  Dim collection1 As Collection
  Set Collection1 = New Collection
  または、 Dim Collection1 As New Collection
  collection1.Add 10, "key1"
  collection1.Add "a", "key2" '辞書型とは異なり、異なるデータ型を格納できる
  collection1.Count
  collection1("key1")
  collection1(1)
  For Each v In collection1
  If isExists(collection1,"a")
  collection1.Remove "key1"

配列の次元数を返す関数
Public Function GetArrayDimension(ByVal v As Variant) As Long
  On Error GoTo ENDPOINT
  Dim i As Long, tmp As Long
  For i = 1 To 100
    tmp = LBound(v, i)
  Next
  GetArrayDimension = 0
  Exit Function

  ENDPOINT:
  GetArrayDimension = i - 1
End Function

Set
  オブジェクトへのポインタを取得する
  Dim book1 As Workbook
  Set book1 = Workbooks("Book1.xls")
  Set book1 = Nothing

特殊な文字列を表す組み込み定数
  vbCrLf Chr(13) & Chr(10) Windowsで一般的に使われる改行
  vbCr   Chr(13) キャリッジリターン
  vbLf   Chr(10) ラインフィード
  vbTab  Chr(9)
  vbNewLine     vbCrLfと同じ
  vbNullString  文字列型の初期値

改行コードを調べる方法
  Hex(AscB(MidB(s1, 1, 1)) 
    0A →LF
    0D 0A →CRLF

Officeでの改行
  Accessの改行(関数内で使用)
    chr(13) & chr(10)
  Excelのセル内改行(ワークシート関数内で使用)
    CHAR(10)
    LF(Alt+Enter)
    Excelの検索 Ctrl+Jで検索置換できる

Excelの改行を Accessの改行に変更するマクロ
  Cells.Replace What:=Chr(10), Replacement:=vbCrLf
Excelの改行を Accessの改行に変更するクエリ
  Replace([F1], chr(10), chr(13) & chr(10))

コントロールを変数を使って参照する方法
  コントロール名、オブジェクト名による変数の参照
  Set obj1 = Me.Controls("a")
  Me.Controls("a" & i).Value 


===================================
..制御文
===================================

If
--
  If i=1 Then
    Debug.Print "1"
  ElseIf i=2
    Debug.Print "2"
  Else
    Debug.Print "3"
  End [If]

  If i=1 Then Debug.Print "1" Else MsgBox Debug.Print "2"
  
  すべての判定処理が実行される
    If(A And B) Then
      AがFalseでも、Bも実行(判定)される

Select
------
  Select Case s
    Case "a"
      Msgbox "a"       '実行後にSelect Caseを抜ける
    Case "b","c","d"
      Msgbox "bかcかd"
    Case Else
      MsgBox "その他"
  End Select

  Select Case i
    Case Is >= 10
      Msgbox "10以上"
    Case 5 To 9
      Msgbox "5-9"
  End Select

For
---
  Dim i As Integer
  For i = 1 to 100
    Exit For
  Next
  
  抜けた後はi=101となる
  Exit For は For が入れ子構造になっている(ネストされている)と、内側の1個だけ抜ける
    2個抜けるにはフラグを立てる、または、外側をDo whileにしてExit Doで抜ける
  iをループの中で変えることは可(無限ループに注意する)
  For i = 1 to iEnd として、ループ中でiEnd=2としても、当初のiEndまでループされる
  
  For i = 100 To 1 Step -1
  For i = 1 To 10 Step 2
  skipやcontinueに相当するコマンドはない。if、または、GoToを使う


For Each
--------
  For Each sheet1 In ActiveWorkbook.Worksheets '全シート
  For Each sheet1 In ActiveWindow.SelectedSheets ' 選択されているシート
    ループ内で選択シートが変更されても、当初選択されていたシート全て繰り返される
  
  In Selection '行→列
  In Worksheets
  In Range("A1:A3")
  In Cells
  In Rows
  In Columns
  In Names  '名前範囲
  
  For Each shape1 In sheet1.Shapes 'グループ化されている図形も1つの図形と見なされる
  For Each shape2 In shape1.GroupItems 'グループ化されている図形内の個々の図形
  For Each con1 In Me.Controls ' フォーム上のコントロール全て

配列の繰り返し処理
  Dim v1 As Variant '配列の繰り返しはVariant型
  For Each v1 As ss 'ssは二次元配列でも可
    Debug.Print v1
  Next


While
-----
  While i < 10
  Wend
  
  Do While i < 10
    Exit Do
  Loop
  
  Do Until i = 10
  Loop
  
  Do
  Loop Until i = 10
  
  無限ループ(Ctrl+Break、または、Escで中断)
  Do
  Loop


エラー処理
----------
一般的なエラー処理
  Sub Sub1()
  On Error GoTo Err_error1
    i = 100 / 0
    Exit sub
  Err_error1:
    MsgBox "エラー番号:" & Err.Number & "エラー内容: " & Err.Description 
  End Sub

エラーが発生してもプログラムを中断せず、エラーが発生した箇所の次の処理から継続して実行する。
  Sub Sub1()
  On Error Resume Next
    i = 100 / 0
    Debug.Print Err.Number '11が表示される(エラーなしの場合は0)
  End Sub

エラー処理を無効にする
  Sub Sub1()
  On Error Resume Next
    i = 100 / 0
  On Error GoTo 0 'エラー処理を無効にする(上記の「On Error Resume Next」が機能する範囲を終了する)
  End Sub

エラーが発生したステートメントに処理を戻す
  Sub Sub1()
  On Error GoTo Err_error1
    i0 = 0
    i = 100 / i0
    Exit sub
  Err_error1:
    i0 =10
    Resume '上記の「i = 100 / i0」に戻る
  End Sub

エラーが発生した次の行のステートメントに処理を戻す
  Sub Sub1()
  On Error GoTo Err_error1
    i0 = 0
    i = 100 / i0
    Exit sub
  Err_error1:
    Resume Next '上記の「i = 100 / i0」の次に戻る
  End Sub

行ラベルに処理を戻す
  Sub Sub1()
  label1:
  On Error GoTo Err_error1
    i0 = 0
    i = 100 / i0
    Exit sub
  Err_error1:
    Resume label1 'label1に戻る
  End Sub

エラーの種類
  コンパイルエラー
  実行時エラー
  論理エラー
    コンパイルエラー、実行時エラーが発生しないが、プログラムが意図通りに動作しないこと
    例えば、小数が必要な変数を、Integerで宣言しているなど


With
----
  With sheet1
    .[A3] = "a"
  End With
  
  Withを使うと、オブジェクト参照の回数を減らせる
  Forと組み合わせる場合は、Forの前にWithを使うほうが、実行速度が速くなる


制御分その他
------------

GoTo Label1
Label1:  

try-catch-finallyの代わり(終了処理の共通化)
If A Then
  Goto Finish
End If
Finish:
  Set b = Nothing




===================================
..プロシージャ
===================================
Sub、Functionをプロシージャという

プロシージャの基本
  Private Function func1(i as integer, s as string) As String
    If(i=1) Then
      func1 = "a"     ' 戻り値
      Exit Function
    End If
    func1 = "b"
  end functin

Public、Private
  Public Function func1(i) As String
    標準Moduleに記述した場合は、全モジュールから、func1のみで呼び出せる
    シートやフォームに記述した場合は、Form1.func1のように呼び出す
  Private Function func1(i) As String  モジュール内で有効
  Function func1(i) As String
    省略した場合はPublic扱い
    Subも同じ

マクロの実行メニューに表示させない方法
  Privateは表示されない
  Public Function func1(Optional void = 0) ' 引数がある関数は表示されない

Optional
  Sub func1(i1 As Integer, Optional ByVal i2 As Integer)
    If IsMissing(i2) Then msgbox "省略されています"
  Sub func1(i1 As Integer, Optional i2 As Integer = 5)' 引数省略指定

Functionの呼び出し方(Subも同じ)
  Call func1(a,b)   この形式に統一するのがよい
  func1 a,b         この形式でも可
  i = func1(a,b)    戻り値を引き取る場合
  func1(a)          引数が1つであればCallを省略できるが、値渡しなる。わかりにくいため、使わないほうがよい
  func1(a,b)        不可
  Call func1 a,b    不可
  i = func1 a,b     不可
  MsgBox title:="タイトル", prompt:="a"  (名前付き引数による呼び出し)
  Application.Run "Book2!Test2"(他のブックのマクロを呼び出す)

ByRef、ByVal
  Sub、Function の引数につけることができる
  引数はデフォルトで参照渡し
    ByRef  参照渡し
      Sub sub1(i As integer) 
      Sub sub1(ByRef i As integer) 
    ByVal  値渡し
      Sub sub1(ByVal i As integer) 
    値渡しと参照渡しの混在
      Function myF(ByVal i1, i2)
      Function myF(ByVal i1, ByRef i2)
  呼び出し方による違い
    参照渡し
      sub1 i
      Call sub1(i)
    値渡し
      sub(i)

配列を引数として渡す
  Sub Sub1()
    Dim ss(3,3) As String
    Dim v1 As Variant
    Call Sub2(ss)
    v = ss
    Call Sub3(v)
  End Sub
  Sub Sub2(byRef ss() As String) '動的配列で受け取る、byValは不可、固定配列は不可
    ss(1,1) = "a"
  End Sub
  Sub Sub3(byVal v As Variant) 'Variant型で受け取る、byVal可
    MsgBox( v(1,1) )
  End Sub
  ※配列をVariantで宣言してArrayで初期値を代入した場合は、関数間もVariantで渡す(Variantの()なし)
  ※配列をOptionalで渡したい場合は、Variant型を使う
      func1(Optional vars)
  ※パラメーター配列を使うと、任意の数の引数を配列として受け取ることができる

ユーザー定義型を引数として渡す
  Sub Sub1(ByRef type1 As Type) 'byValは不可
  値で渡したい場合は、要素の1つずつを引数で渡す

オブジェクトを戻す
  Private Function func1() As Object
    Set func1 = obj1 '戻す側にもSetが必要
  End Function
  Private Sub Sub1()
    Set obj1 = func1()
  End Sub

配列を戻す
  Private Function func1() As  Variant
    Dim vs() As Variant
    func1 = vs
  End Sub
  Private Sub Sub1()
    Dim s() As Variant
    s = func1()
  End Sub

変数にプローシージャ名を入れて実行する
  Application.Run "func1"
  Application.Run "Sheet1.func1" ' モジュールを指定(func1はPrivateで構わない)
  Application.Run "Book2!func1" ' Book2は開いている状態
  Application.Run "call_" & func1", 10, "abc" ' 引数のある場合

Functionの戻り値は複数回配置でき、最終的な戻り値が戻される
  Private Function func1() As Integer
    func1=1
    func1=2 ' 最終的に2が戻る
  End Function
  Private Function func1() As Integer
    Dim i As Integer
    For i = 1 To 5
      func1 = func1 & i 'プロシージャ―名は変数と同じように利用できる
    Next
  End Function


===================================
..モジュール
===================================

標準モジュール、オブジェクトモジュール
--------------------------------------
モジュールの2種類
  標準モジュール
  オブジェクトモジュール
    シートモジュール
    ブックモジュール
    フォームモジュール
    クラスモジュール

標準モジュール、オブジェクトモジュールの違い
  他のモジュールからPublic変数、プロシージャを呼び出す
    標準モジュール
      他のモジュールから、モジュール名を省略して呼び出せる
    オブジェクトモジュール
      他のモジュールから呼び出すには、「モジュール名(オブジェクト名).」が必要
  
  Meキーワード
    標準モジュール
      使用不可
    オブジェクトモジュール
      使用可
  
  Public Constの宣言
    標準モジュール
      宣言可
    オブジェクトモジュール
      宣言不可


クラスモジュール
----------------
オブジェクトを生成することをインスタンス化、生成されたオブジェクトをインスタントという

Dim c1 As Class1    '変数の宣言
Set c1 = New Class1 'クラスのインスタンス化

Dim c1 As New Class1 '変数の宣言と、クラスのインスタンス化を1行で記述。分かりにくいので2行に分けたほうがよい


===================================
..プロジェクト
===================================

参照設定
--------
参照設定する場合(事前バインディング、アーリーバインディング)
  Dim cn As New Connection
  Dim rs As New Recordset

参照設定しない場合(実行時バインド、遅延バインディング、レイトバインディング)
  CreateObject関数を使う
    Dim cn As Object
    Dim rs As Object
    Set cn = CreateObject("ADODB.Connection") 
    Set rs = CreateObject("ADODB.Recordset")
  GetObject関数を使う(開かれているファイルや実在するインスタンスを取得)
    Dim doc1 As Object
    Set doc1 = GetObject(path)

備考
  開発環境で参照設定したライブラリが、実行環境にも存在すれば、マクロは動く
  開発環境と実行環境で、ライブラリのバージョンが違うとエラーとなる
    →実行環境でVBEを開いて手作業で参照設定するか、開発時にVBAコードで参照設定する
  
  互換性重視であれば、参照設定をした状態で開発を進め、完成直前に参照設定を解除してCreateObjectに変更するという考え方もある
  そのような面倒をさけるため、参照設定しないという考え方もある
    CreateObjectを使えば、実行環境にインストールされているバージョンのライブラリが使われる
  
  参照設定は、Bookごとに保持されている。book1とbook2を同時に開いた場合、それぞれの参照設定が適用される
  そもそも、実行環境にライブラリが存在しない場合は、実行時バインドでも動かない


アドイン
--------


ライブラリ
----------
初期設定で参照設定されているライブラリ
  Excel(Microsoft Excel Object Library)
  Office(Microsoft Office Object Library)
  stdole(OLE Automation)
  VBA(Visual Basic For Application)
  MSForms(Microsoft Forms  Object Library)

オートメーション
  別のアプリケーションのオブジェクトを操作する仕組み

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAの学習中です。

目次