[一覧]
[入門編1]
[入門編2]
[入門編3]
[実践編]
[トラブル編]
オブジェクトについて
オブジェクトの中にはデータとそれを操作するためのコマンドが入っています。このコマンドをVBAでは「メソッド」「プロパティ」と呼びます。プログラムでオブジェクトを操作するということは、「XXXXオブジェクトのXXXXメソッドを実行する」「XXXXオブジェクトのXXXXプロパティに値を設定する」といったことになります。
例えば、Sheet1というワークシートを選択するには、「Sheet1オブジェクトのSelectメソッドを実行」します。Sheet1の名前を変更するには、「Sheet1オブジェクトのNameプロパティに値を設定」します。
例えば、MyObjectというオブジェクトにMyMethodというメソッドとMyPropertyというプロパティがあるとき、MyObject.MyProperty = 100 という使い方はできますが、MyObject.MyMethod = 100 という使い方はできません。
インスタンスはオブジェクトの「実体」という意味です。オブジェクトのインスタンスはオブジェクトのクラスの定義(設計図)に基づいて作成されます。
例えば、Excelにはワークシートクラスの定義があり、それに基づいてSheet1というインスタンスが作成されます。
では、どうやってオブジェクトへの参照を取得するかと言うと、関連するメソッドやプロパティを使います。例えば、A1:C3のセル範囲のオブジェクトへの参照を取得するには Range("A1:C3") などとします。Rangeプロパティ(Excel5.0/95ではRangeメソッド)は対象オブジェクトを省略するとApplicationオブジェクトのプロパティとして解釈され、アクティブシート上の、指定されたRangeオブジェクトへの参照を返します。
オブジェクトへの参照は、その中身を直接見ることはできませんが、変数に格納し、オブジェクトへの参照を返すプロパティやメソッドの代わりに使用することができます。オブジェクトへの参照を変数に格納するにはSetステートメントを使います。
例えば、アクティブシートのA1:C3のRangeオブジェクトへの参照をobjという変数に格納するには、Set obj = Range("A1:C3") とします。このようにすると、Range("A1:C3").Clear の代わりに、obj.Clearとすることができます。
コレクションはオブジェクトへの参照を取得するときによく使います。例えば、アクティブブックのSheet1というワークシートのオブジェクト参照を取得するには、「アクティブブックのワークシートコレクションの中の、Sheet1という名前のシート」という指定をします。
コードでは ActiveWorkbook.Worksheets.Item("Sheet1") と書きます。
「ActiveWorkbook.Worksheets」の部分が「アクティブブックのワークシートコレクション」オブジェクトへの参照を返します。「.Item("Sheet1")」が「コレクションの中の、Sheet1という名前のシート」のオブジェクトへの参照を返します。
このItemプロパティ(Excel5.0/95ではItemメソッド)は、Worksheetsコレクションオブジェクトの既定のプロパティであるため、省略して、ActiveWorkbook.Worksheets("Sheet1") と書くことができます。
Itemには名前の他にインデックス番号を指定することもできます。例えば、左から2番目のワークシートを指定するには、ActiveWorkbook.Worksheets(2) とします。
コレクションには必ずCountプロパティがあります。アクティブブックのワークシートの数を取得するには、ActiveWorkbook.Worksheets.Count とします。
RangeプロパティはApplicationオブジェクト、Worksheetオブジェクト、Rangeオブジェクトのプロパティです。Rangeオブジェクトへの参照を返すという点は同じですが、オブジェクトによって機能が異なります。オブジェクトが省略された場合は、ApplicationオブジェクトのRangeプロパティと解釈されます。(ただし、Excel5.0/95、Excel97の標準モジュールの場合です。)ApplicationオブジェクトのRangeプロパティは、アクティブシートの指定された範囲のRangeオブジェクトへの参照を返します。
Applicationプロパティは多くのオブジェクトにあり、そのオブジェクトを管理するアプリケーションオブジェクトへの参照を返します。ExcelVBAの中でオブジェクトが省略された場合は、Applicationオブジェクト(ExcelVBAではExcelのことになります)のApplicationプロパティと解釈されます。ApplicationオブジェクトのApplicationプロパティはApplicationオブジェクトへの参照を返します。
ワークシートを追加すると、例えば、Sheet1というクラスと、クラス名と同名のSheet1というインスタンスが自動的に作成されます。Sheet1クラスは複数のインスタンスを作成することはできません。
UserForm1の場合もほぼ同様ですが、ユーザフォームを追加したとき、UserForm1というインスタンスは名前が割り当てられるだけで、作成はされません。実際に作成されるのは、マクロ実行時にロード(Load)されたときです。ロードにはLoadステートメントを使いますが、これを使わなくても、UserForm1という名前を使えば自動的にロードされます。UserForm1クラスは複数のインスタンスを作成することができます。
Excel97ではワークシートもVBプロジェクトの一部です。ワークシートを追加、削除、変更することはプロジェクトを変更することであり、プロジェクト全体が初期化されることもあるようです。
実行制御
通常のExcelファイルです。
自動起動フォルダ(XLStart)に作成され、Excel起動時に自動的に開かれます。なおExcel起動時に自動的に開かれるファイルの場合、マクロ警告のメッセージは表示されません。マクロを含むファイルが開かれていてもユーザは気が付かない可能性があります。
非表示のファイルとして作成されます。再表示するにはメニューの[ウィンドウ]-[ウィンドウ再表示]を使います。
Excelのマクロウィルスとして有名なLaroux(ラルー)が自動作成し、感染、潜伏するファイルです。Larouxには、Personal.xlsが既に存在する場合は感染に失敗するというバグ(?)がありました。現在のマクロウィルスには多数のバリエーションがあり、Personal.xls以外のファイルに潜伏するものもあります。
アクティブシートに「集計結果」という名前を付けるサンプルです。すでに同じ名前のシートがあるとエラーが発生しますが、その場合はErrorHandlerというラベルへジャンプし、メッセージを表示してプロシージャを終了させます。
Sub Sample_SetSheetName() Dim sName As String sName = "集計結果" 'エラートラップを設定します 'エラーが発生するとErrorHandlerというラベルへジャンプします On Error GoTo ErrorHandler 'シート名を変更します ActiveSheet.Name = sName 'エラートラップを解除します On Error GoTo 0 'エラー処理へ行かないように、処理の最後には '必ずExit Subを書きます Exit Sub 'エラー処理のラベル ErrorHandler: 'エラーメッセージの表示 MsgBox sName & " は既にあります。", vbExclamation Exit Sub End Sub
EnableEventsプロパティを使い、イベントを発生しないようにできます。EnableEventsプロパティを使用する場合は、エラートラップ処理を行い、マクロ終了後に必ずイベントが有効になるようにします。これを行わないとそれ以降イベントプロシージャが起動しなくなってしまいます。
Private Sub Worksheet_Change(ByVal Target As Excel.Range) '(処理) On Error GoTo ErrorHandler Application.EnableEvents = False Target.Value = 0 Application.EnableEvents = True Exit Sub ErrorHandler: MsgBox Error(Err), vbExclamation Application.EnableEvents = True End Sub
Excelの機能の利用
Application.関数名 として使います。ただしすべての関数が使えるわけではありません。また、ワークシート関数のDATE()とVBA関数のDate()のように名前が同じで機能が異なるものもありますので、区別して使う必要があります。
パラメータにセル参照を指定するにはRangeオブジェクトへの参照を指定します。
a = Application.Sum(ActiveSheet.Range("A2:A100"))
ActiveChart.Export "C:\My Documents\Chart1.gif"
プログラミング
Sheets(Array("Sheet1", "Sheet2")).Selectしかし、選択したいシート数が決まっていない場合は、この方法は使えません。Array関数の代わりに通常の配列変数を使います。
Sub Sample_SheetsSelect() Dim sNameArray() As String '動的配列を割り当てます ReDim sNameArray(1 To 3) 'シート名を設定します sNameArray(1) = "Sheet1" sNameArray(2) = "Sheet2" sNameArray(3) = "Sheet3" 'Array関数の代わりに配列変数を指定します Sheets(sNameArray).Select End Sub
コントロールの名前を利用して、 Me.Controls("TextBox" & i) のような参照方法は可能です。
複数のコントロールでイベントプロシージャを共有するには、クラスモジュールを利用します。
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode = vbFormControlMenu Then Cancel = True End If End Sub
印刷
以下のサンプルでは、ページヘッダーに、アクティブブックのフルパス名、シート名、1月23日(月) の形式の日付、時刻を設定します。このマクロはシートを印刷する前に毎回実行する必要があります。
Sub Sample_SetPageHeader() With ActiveSheet.PageSetup .LeftHeader = _ ActiveWorkbook.FullName & _ " &A " & _ Format$(Date, "m""月""d""日(""aaa"")""") & _ " &T" .CenterHeader = "" .RightHeader = "" .LeftFooter = "" .CenterFooter = "&P / &N" .RightFooter = "" End With End Sub
Sub Test_PageCount() Dim iPageCount As Integer Sheets("Sheet1").Select iPageCount = Application.ExecuteExcel4Macro("GET.DOCUMENT(50)") MsgBox CStr(iPageCount) End Sub
マイクロソフトサポート技術情報にはHPageBreaksとVPageBreaksを使う方法も紹介されていますが、この方法では、最終行または最終列にデータがある場合に正しい結果になりません。もしかしたらExcel97ではGET.DOCUMENT(50)が正しい結果を返さないのかもしれませんが、今のところそのような話は聞いていません。
ダイアログボックス
Sub Sample_Alert() Dim iRet As Long 'ダイアログボックスを表示し、押されたボタンの種類を変数に入れます iRet = MsgBox("処理を実行します。", vbOKCancel Or vbExclamation) 'キャンセルボタンが押された場合は終了します If iRet = vbCancel Then MsgBox "キャンセルされました。", vbInformation Exit Sub End If 'ここに処理を書きます '終了メッセージを表示します MsgBox "処理を実行しました。", vbInformation End Sub
Sub Sample_InputRange() Dim oRange As Range Set oRange = Nothing On Error Resume Next Set oRange = Application.InputBox( _ prompt:="セル範囲を選択してください。", _ Title:="セル範囲の選択", _ Type:=8) On Error GoTo 0 If oRange Is Nothing Then MsgBox "キャンセルされました。", vbInformation Exit Sub Else MsgBox oRange.Address(external:=True) & _ " が選択されました。", vbInformation End If End Sub
同様のメソッドに、GetSaveAsFilenameがあります。
Sub Input_FileName() Dim vFileName As Variant Dim sDefaultPath As String 'デフォルトパスの設定(必要に応じて) sDefaultPath = "C:\My Documents\" ChDrive sDefaultPath ChDir sDefaultPath 'Excelファイル名の入力(単一選択) vFileName = Application.GetOpenFilename( _ fileFilter:=StrConv("Microsoft Excel ファイル (*.x*),*.x*," & _ "すべてのファイル (*.*),*.*", vbNarrow), filterIndex:=1, _ MultiSelect:=False) 'キャンセルされたかチェック If VarType(vFileName) = vbBoolean Then MsgBox "キャンセルされました。" Exit Sub End If MsgBox vFileName & " が選択されました。" End Sub
Excel5.0/95ダイアログシート、フォームコントロール
その他
アドインの作成は、モジュールシートのメニューで[ツール]-[アドインの作成]です。
Excel97では Visual Basic Editor でプロジェクトを選択し、[ツール]-[VBAProjectのプロパティ](VBAProjectは実際には選択したプロジェクト名になります)[保護]で [プロジェクトを表示用にロックする]をチェックしてパスワードを設定、ブックを保存して閉じます。バックアップ管理、パスワード管理をしっかり行いましょう。
アドインを作成するには、Excelのメニュー[ファイル]-[名前を付けて保存]で[ファイルの種類]にMicrosoft Excelアドイン(*.xla) を選択して保存します。
ただし、Excelの保護機能はユーザインタフェースの機能であり、機密保護の機能ではないことに注意してください。保護を解除したりアドインをブックに復元する方法は 実際には存在します。例えば、Excel97はExcel5.0/95で作成したモジュールの保護を解除します。同様に、Excel97で設定した保護が将来のバージョンで解除される可能性もあります。
同様に、Excel97で作成したマクロが将来のバージョンでそのまま動作するとは限りません。