エクセレントな Office の冒険

David Shank
Microsoft Corporation

January 5, 2001

この記事は、MSDN Online Voices のコラム "Office Talk" からの再録です。

新年最初の週です。私たちが休日をどのように過ごしたかは別にして、今週中にやっておかなければならないことが少なくとも 2 つあります。1 つはオフィス (Office: このコラムでお話したいこと) に戻ることで、もう 1 つは先月贈り物やお祝いにかかった費用をどのように精算するかを考えることです。

私たちの多くは、数値の計算となると Microsoft Excel が頭に浮かびます。多くの読者がご存知のように、このコラムで Excel を使った作業についてお話したことはありませんでしたので、これがよい機会だと考えました。

今回は、Excel を使った作業に関する 2 部構成の説明の第 1 部です。今月のコラムでは、プログラムで Excel を使って作業をするために理解しておく必要がある基礎についてお話します。来月は、範囲、領域、およびセルを使った作業について、もう少し詳しく調べていこうと考えています。

Excel Application オブジェクト

Excel Application オブジェクトは、Excel オブジェクト モデルの最上位レベル オブジェクトです。Application オブジェクトを使って、アプリケーション レベルのプロパティの判定や指定、またはアプリケーション レベルのメソッドの実行を行います。さらに、Application オブジェクトは Excel オブジェクトの残りのオブジェクトのエントリ ポイントになります。

Excel 内から Visual Basic for Applications (VBA) を使用して、Application オブジェクトのプロパティやメソッドを扱う場合、特に指定しないでも Application オブジェクトを利用できます。これをオブジェクトの暗黙的参照と呼びます。別の Office アプリケーションから Excel オブジェクトを使って作業する場合は、まず Excel Application オブジェクトを表すオブジェクト変数を作成する必要があります。これをオブジェクトの明示的参照と呼びます。たとえば、次の 2 つのプロシージャは、現在アクティブな Worksheet オブジェクトの名前を返します。ShowNameFromInsideXL プロシージャは、Excel 内部から作業するように設計されており、Application オブジェクトへの暗黙的参照を使用します。つまり、Application オブジェクト自体を明示的に参照しないで、Application オブジェクトの ActiveSheet プロパティを参照します。ShowNameFromOutsideXL プロシージャは Excel の外部から実行されます。そのため、Application オブジェクトへの明示的参照を使用する必要があります。


Sub ShowNameFromInsideXL()
    MsgBox "'" & ActiveSheet.Name & "' is the active worksheet."
End Sub

Sub ShowNameFromOutsideXL()
    Dim xlApp As Excel.Application

    Const XL_NOTRUNNING As Long = 429

    On Error GoTo ShowName_Err
    Set xlApp = GetObject(, "Excel.Application")
    MsgBox "'" & xlApp.ActiveSheet.Name & "' is active."
    xlApp.Quit
    Set xlApp = Nothing

ShowName_End:
    Exit Sub
ShowName_Err:
    If Err = XL_NOTRUNNING Then
        ' Excel が現在実行中ではない。
        Set xlApp = New Excel.Application
        xlApp.Workbooks.Add
        Resume Next
    Else
        MsgBox Err.Number & " - " & Err.Description
    End If
    Resume ShowName_End
End Sub

ShowNameFromOutsideXL プロシージャでは、GetObject 関数を使って現在実行中の Excel のインスタンスへの参照を取得していることに注目してください。このプロシージャが呼び出されるときに Excel が実行中でないときは、エラーが発生します。エラー ハンドラでは、New キーワードを使って Excel の新しいインスタンスを作成後、新しい Workbook オブジェクトを追加します。ブックにはワークシートが少なくとも 1 つ含まれているので、 プロシージャ内の残りのコードは正しく実行されます。

メモ : New キーワードを使用する場合、ShowNameFromOutsideXL プロシージャを含むプロジェクトから、Excel オブジェクト モデルへの参照設定を追加する必要があります。

アクティブ オブジェクトへの Excel のショートカットについて

ほかの Office アプリケーション オブジェクト モデルと同様に、Excel Application オブジェクトも現在アクティブな Excel オブジェクトでの作業に使用できるプロパティをいくつか公開しています。たとえば、現在選択しているセル内の情報や現在アクティブなワークシートを使って作業するようにデザインされた VBA プロシージャを作成することがよくあります。Application オブジェクトは、ActiveCellActiveChartActivePrinterActiveSheetActiveWindow、および ActiveWorkbook プロパティを公開しています。このプロパティを使って、現在アクティブなセル、グラフ、プリンタ、シート、ウィンドウ またはブックへの参照を返すことができます。次の例は、これらのプロパティの一部を使用したさまざまな方法を示しています。


' ActiveWorkbook プロパティの例 :
Function SaveBookAs(strFileName As String) As Boolean
    ActiveWorkbook.SaveAs ActiveWorkbook.Path & "\" & strFileName
End Function

' ActiveCell プロパティの例 :
Function CustomFormatCell()
    With ActiveCell
        If IsNumeric(.Text) And .Formula < 0 Then
            With .Font
            .Bold = True
            .Italic = True
            .Borders.Color = 255
        End If
    End With
End Function

' ActiveSheet プロパティの例 :
Function ChangeName(strNewName As String) As Boolean
    ActiveSheet.Name = strNewName
End Function

ActiveWorkbook プロパティ以外にも、Application オブジェクトの Workbooks プロパティと Worksheets プロパティを使用して、同等の Excel オブジェクトを返すことができます。Workbooks プロパティは、現在開いているすべての Workbook オブジェクトを持つ Workbooks コレクションを返します。Worksheets プロパティは現在アクティブなブックに関連付けられている Sheets コレクションを返します。次の例は、Workbooks プロパティを使用して、ブックが既に開かれているかどうかを調べ、開かれていない場合はそのブックを開きます。


Function OpenBook(strFilePath As String) As Boolean
    ' このプロシージャは、strFilePath 引数に指定した
    ' ブックが開かれているかどうかを調べます。
    ' 開かれている場合、そのブックがアクティブになります。
    ' 開かれていない場合は、プロシージャがブックを開きます。
    Dim wkbCurrent       As Excel.Workbook
    Dim strBookName      As String

    On Error GoTo OpenBook_Err

    ' strFilePath 引数の名前の部分を調べます。
    strBookName = NameFromPath(strFilePath)
    If Len(strBookName) = 0 Then Exit Function
    If Workbooks.Count > 0 Then
        For Each wkbCurrent In Workbooks
            If UCase$(wkbCurrent.Name) = UCase$(strBookName) Then
                wkbCurrent.Activate
                Exit Function
            End If
        Next wkbCurrent
    End If
    Workbooks.Open strBookName
    OpenBook = True

OpenBook_End:
    Exit Function
OpenBook_Err:
    OpenBook = False
    Resume OpenBook_End
End Function

上記の例では、OpenBook プロシージャは NameFromPath というカスタム プロシージャを呼び出しています。このカスタム プロシージャは、strFilePath 引数で OpenBook プロシージャに渡されたフルパスとファイル名からファイル名の部分を返します。


Function NameFromPath(strPath As String) As String
    ' このプロシージャはファイルのパスを受け取り、
    ' ファイル名の部分を返します。
    Dim lngPos          As Long
    Dim strPart         As String
    Dim blnIncludesFile As Boolean

    ' これがファイル パスかどうかを調べます。
    ' パスの最後の区切り文字を探します。
    lngPos = InStrRev(strPath, "\")
    ' 最後の円記号の後に続く文字列にピリオドが
    ' 含まれているかどうかを調べます。
    blnIncludesFile = InStrRev(strPath, ".") > lngPos
    strPart = ""

    If lngPos > 0 Then
        If blnIncludesFile Then
            strPart = Right$(strPath, Len(strPath) - lngPos)
        End If
    End If
    NameFromPath = strPart
End Function

Excel Workbook オブジェクト

Excel オブジェクト モデルでは、Workbook オブジェクトは Application の直下に位置します。Workbook オブジェクトは Excel の .xls ブック ファイルまたは .xla ブック ファイルを表します。Workbook オブジェクトは単一の Excel ブックで作業する場合に使用します。現在開いているすべての Workbook オブジェクトを使って作業する場合は Workbooks コレクションを使用します。

また、Application オブジェクトの ActiveWorkbook プロパティを使用して、現在アクティブなブックへの参照を返すこともできます。Workbooks コレクションには Count プロパティがあります。このプロパティを使用して、表示および非表示でいくつのブックが開かれているかを調べることができます。一般的に、Excel は特に指定しない限り Personal.xls という非表示のブックを 1 つ持っています。Excel はマクロを保存する既定の場所として Personal.xls ブックを使用します。非表示の Personal.xls ブックが開いている唯一のブックである場合、ActiveWorkbook プロパティは Nothing を返しますが、Workbooks コレクションの Count プロパティは 1 を返します。非表示または表示で開かれているブックが存在しない場合のみ、Workbooks コレクションの Count プロパティは 0 を返します。

Workbook オブジェクトを使った作業

Workbooks コレクションの Add メソッドを使って、新しい Workbook オブジェクトを作成できます。Add メソッドは新しいブックを作成するだけでなく、作成後すぐにそのブックを開きます。また、Add メソッドは、作成されたばかりの新しいブックを表すオブジェクト変数も返します。新しいブックには、[ツール] メニューの [オプション] ダイアログ ボックス の [全般] タブにある [新しいブックのシート数] ボックスで指定されているワークシートの数が含まれます。Application オブジェクトの SheetsInNewWorkbook プロパティを使用して、新しいブックが保持するシート数を指定することもできます。

Workbook オブジェクトの SaveAs メソッドを使用し、保存するブックの名前を指定して、新しいブックを保存できます。同じ名前のブックが既に存在する場合、エラーが発生します。SaveAs メソッドを使ってブックを保存後に加えた変更を、Workbook オブジェクトの Save メソッドを使って保存できます。SaveCopyAs メソッドを使って、既存のブックの複製を別のファイル名で保存することもできます。SaveAs メソッドまたは SaveCopyAs では、使用するファイル名を指定できます。また、Application オブジェクトの GetSaveAsFileName メソッドを使って、ブックの保存に使用する名前をユーザーに指定させます。ユーザーが [ファイル名を付けて保存] ダイアログ ボックスで [キャンセル] をクリックすると、GetSaveAsFileName メソッドは False を返します。

SaveAs メソッドを使って新しいブックを保存するまでは、Workbook オブジェクトの Name プロパティの設定は Excel が割り当てる Book1.xls などの値になっています。ブックを保存後、Name プロパティには SaveAs メソッドの Filename 引数に指定した名前が設定されます。Name プロパティは読み取り専用です。そのためブック名を変更する場合は、SaveAs メソッドを再度使用して、Filename 引数に別の値を渡す必要があります。

メモ : Workbook オブジェクトの FullName プロパティは、オブジェクトのパスとファイル名を持っています。それに対して Path プロパティは、現在のブックに保存したパスだけを持っています。新しいブックを保存する以前は、FullName プロパティと Name プロパティは同じ値を持ち、Path プロパティは値を持っていません。

Workbooks コレクションの Open メソッドは、既存のブックを開きます。Open メソッドを使ってブックを開くと、そのブックがアクティブなブックになります。Open メソッドに使用するファイル名を指定するか、または Application オブジェクトの GetOpenFileName メソッドを使って、開くブックをユーザーに選択させることができます。ユーザーが [ファイルを開く] ダイアログ ボックスで [キャンセル] をクリックすると、GetOpenFileName メソッドは False を返します。

開いているブックを閉じるには、Workbook オブジェクトの Close メソッドを使用します。オブジェクトを閉じる前に、保留中の変更をブックに保存する必要があるかどうかを指定するには、SaveChanges 引数を使用します。SaveChanges 引数を省略すると、保留中の変更を保存するかどうかがユーザーに問い合わせられます。また、Workbooks オブジェクトの Close メソッドを使用して、開いているすべてのブックを閉じることもできます。このメソッドを使用していて、開いているブックに保存していない変更がある場合、変更を保存するかどうかがユーザーに問い合わせられます。ユーザーが [変更を保存しますか] ダイアログ ボックスで [キャンセル] をクリックすると、コードで処理するする必要があるエラーが発生します。Close メソッドを実行する前に、Application オブジェクトの DisplayAlerts プロパティを False に設定すると、[変更を保存しますか] ダイアログ ボックスを表示しません。この方法で Workbooks オブジェクトの Close メソッドを使用する場合、開いているブックで保存されていない変更はすべて失われます。Close メソッドの実行後に、DisplayAlerts プロパティを True に設定することを忘れないでください。

メモ : Open または Close メソッドを使用してブックを開いたり閉じたりするときは、Auto_Open イベント プロシージャおよび Auto_Close イベント プロシージャは無視されます。Workbook オブジェクトの RunAutoMacros メソッドを使用して、これらのプロシージャを強制的に実行できます。ブックの Open および BeforeClose イベント プロシージャ内の VBA コードは、Open または Close メソッドを使ってブックを開いたり閉じたりするときに実行されます。

次の例は、新しいブックを作成する方法とそのブックが保持するワークシートの数を指定する方法を示しています。


Function CreateNewWorkbook(Optional strBookName As String = "", _
         Optional intNumSheets As Integer = 3) As Workbook
    ' このプロシージャは、strBookName 引数で指定された 
    ' パスと名前を使って、新しいブック ファイルを作成し、 
    ' 保存します。ブック内のワークシート数を指定するには、
    ' intNumsheets 引数を使用します。既定値は 3 です。

    Dim intOrigNumSheets      As Integer
    Dim wkbNew                As Excel.Workbook

    On Error GoTo CreateNew_Err

    intOrigNumSheets = Application.SheetsInNewWorkbook
    If intOrigNumSheets <> intNumSheets Then
        Application.SheetsInNewWorkbook = intNumSheets
    End If
    Set wkbNew = Workbooks.Add
    If Len(strBookName) = 0 Then _
        strBookName = Application.GetSaveAsFilename
    wkbNew.SaveAs strBookName
    Set CreateNewWorkbook = wkbNew
    Application.SheetsInNewWorkbook = intOrigNumSheets

CreateNew_End:
    Exit Function
CreateNew_Err:
    Set CreateNewWorkbook = Nothing
    wkbNew.Close False
    Set wkbNew = Nothing
    Resume CreateNew_End
End Function

Workbook オブジェクトの Saved プロパティは、ブックが保存されたかどうかを示す Boolean 値です。Saved プロパティは、新規のブックまたは変更がない開いているブックでは True になり、保存されていない変更があるブックでは False になります。Saved プロパティを True に設定できます。これを行うと、Save メソッドを使ってブックを最後に保存してから行われた変更を実際には保存していない場合でも、ブックを閉じるときに、変更を保存するかどうかをユーザーに問い合わせなくなります。

オートメーションを使用したブックでの作業に関するメモ

Excel ブックの編集で、オートメーションを使用している場合は、次のことに注意してください。

Excel の新しいインスタンスを作成し、ブックを開くと、Excel のインスタンスは非表示になり、ブックのインスタンスも非表示になります。そのため、そのブックを編集し、保存する場合、ブックは非表示として保存されます。次回ユーザーが手動で Excel を開くときに、そのブックは非表示になっているので、ユーザーは [ウィンドウ] メニューの [再表示] をクリックして、ブックを表示することになります。

この現象を回避するには、ブックを編集、保存する前に、オートメーション コードがブックを再表示する必要があります。ただし、Excel 自体が表示されるという意味ではないことに注意してください。

Excel Worksheet オブジェクト

Excel での大部分の作業は、ワークシートのコンテキスト内で行います。ワークシートには、データを使った作業に使用できるセルのグリッド、およびワークシート内のデータを使った作業に使用できる数多くのプロパティ、メソッド、およびイベントがあります。

ワークシート内のデータ、セル内のデータ、またはセル範囲内のデータを使って作業するために、Range オブジェクトを使用できます。Worksheet および Range オブジェクトは、Excel 内でカスタム ソリューションを作成するときに、最も基本的で、最も重要なコンポーネントです。来月のコラムで、Range オブジェクトについて詳しくお話しするつもりです。

Workbook オブジェクトの Worksheets プロパティは、ブック内のすべてのワークシートのコレクションを返します。Workbook オブジェクトの Sheets プロパティは、ブック内のすべてのワークシートとグラフ シートのコレクションを返します。

各 Excel ブックは、1 つ以上の Worksheet オブジェクトを持っていて、同様に 1 つ以上のグラフ シートを持つことができます。Excel のグラフは、ワークシートに埋め込まれるか、またはグラフ シートに含まれます。グラフ シートには 1 つのグラフしか保持できませんが、ワークシートには複数のグラフを保持できます。ワークシートに埋め込まれた各グラフは、Worksheet オブジェクトの ChartObjects コレクションのメンバです。Worksheet オブジェクトは、Worksheets コレクションに含まれ、Workbook オブジェクトの Worksheets プロパティを使ってアクセスできます。VBA を使って新しいブックを作成する場合、Application オブジェクトの SheetsInNewWorkbook プロパティを使って、ブックに何枚のワークシートを含むかを指定できます。

ワークシートの参照

Worksheet オブジェクトは、Worksheets コレクションのメンバとして存在するので、その名前やインデックス値でワークシートを参照します。次の例では、どちらのオブジェクト変数もブック内の最初のワークシートを参照ています。


Sub ReferToWorksheetExample()
    ' このプロシージャは、プログラムでワークシートを参照する方法を
    ' 示しています。
    Dim wksSheetByIndex     As Excel.Worksheet
    Dim wksSheetByName      As Excel.Worksheet

    With ActiveWorkbook
        Set wksSheetByIndex = Worksheets(1)
        Set wksSheetByName = Worksheets("Main")
        If wksSheetByIndex.Index = wksSheetByName.Index Then
            MsgBox "The worksheet indexed as #" _
                & wksSheetByIndex.Index & vbCrLf _
                & "is the same as the worksheet named '" _
                & wksSheetByName.Name & "'", _
                vbOKOnly, "Worksheets Match!"
        End If
    End With
End Sub
ワークシートを使った作業

Worksheets コレクションの Add メソッドを使って、コレクションに 1 つ以上のワークシートを追加できます。Add メソッドは、新しい Worksheet オブジェクトを返します。複数のワークシートを追加した場合、Add メソッドは Worksheets コレクションに最後に追加されたワークシートを返します。Add メソッドの Before または After 引数を省略した場合、新しいワークシートは現在アクティブなワークシートの前に追加されます。次の例は、ワークシートの現在のコレクションでアクティブなワークシートの前に新しいワークシートを追加しています。


Dim wksNewSheet As Excel.Worksheet

Set wksNewSheet = Worksheets.Add
With wksNewSheet
    ' ここで、新しいワークシートのプロパティやメソッドを
    ' 使った作業を行います。
End With

Worksheet オブジェクトの Delete メソッドを使って、Worksheets コレクションからワークシートを削除できます。プログラムでワークシートを削除すると、Excel はメッセージ (警告) を表示します。メッセージを表示しないようにするには、次の例で示すように、Application オブジェクトの DisplayAlerts プロパティを False に設定する必要があります。


Function DeleteWorksheet(strSheetName As String) As Boolean
    On Error Resume Next

    Application.DisplayAlerts = False
    ActiveWorkbook.Worksheets(strSheetName).Delete
    Application.DisplayAlerts = True
    ' エラーが発生しなかった場合は True を返します。
    ' それ以外の場合は False を返します。
    DeleteWorksheet = Not CBool(Err.Number)
End Function

メモ : DisplayAlerts プロパティを False に設定した場合は、プロシージャの実行終了前に、上記の例で示したように、必ずその設定を True に戻します。

Worksheet オブジェクトの Copy メソッドを使用して、ワークシートをコピーできます。コピー元のワークシートと同じブックにワークシートをコピーするには、Copy メソッドの Before 引数または After 引数のいずれかを指定する必要があります。Worksheet オブジェクトの Move メソッドを使って、ワークシートを移動できます。以下にその例を示します。


Worksheets("Sheet1").Copy After:=Worksheets("Sheet3")
Worksheets("Sheet1").Move After:=Worksheets("Sheet3")

次の例では、ワークシートがブック内の最後のワークシートになるように移動する方法を示しています。


Worksheets("Sheet1").Move After:=Worksheets(Worksheets.Count)

メモ : Copy または Move メソッドのいずれかを使用する場合に、Before 引数または After 引数をどちらも指定しなかったときは、Excel は新しいブックを作成し、指定されたワークシートを新しいブックにコピーします。

詳細情報の入手場所

このコラムで説明した技法は、プログラムで Excel を使用する場合の初歩的な考え方です。詳細情報については、次の資料をご覧ください。

David Shank は、Office チームのプログラマ/ライターであり、主に開発者向け文書を専門としています。うわさによると、彼は Redmond 東の山頂に住んでおり、今でも北西部に住んでいる数少ない北西部出身者の 1 人であるとのことです。