【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する

Outlookのフォルダ名を保存するテーブルを自動生成する

この記事では Microsoft Access 上で「Outlookのフォルダ名を保存するテーブルを自動生成するMakeFolderNameTableForOutlookというユーザー定義関数について紹介します。

この情報が読者のお役に立てば幸いです。

解決できること

Microsoft Accessで新しいテーブルを作成する際には、参照クエリ操作やSQL言語による作成、デザインビューでの作成、他のAccessファイルからのインポートする等いろいろなやり方があります。

しかしそれぞれ煩わしい手続きがあり、できればその手間を省きたいところです。

この記事では、Accessから「Outlookのフォルダ名を保存するテーブルを自動生成する」 MakeFolderNameTableForOutlook というユーザー定義関数を紹介します。

この関数を使うと、このテーブル作成に関わる煩わしい手続きを省ける上、Outlookのフォルダ配下のメール保存や添付ファイルの保存操作が簡単行うための準備ができます。

読んでほしい方

Microsoft Access VBAによるアプリケーションの開発に取り組んでいる方や、これまでVBAを使用してアプリケーションを開発してきた方々には、きっとこの記事はお役に立ちます。

特に、開発したツールを第三者に提供する際に、利用者個人に紐づいた環境差分をVBAのプログラムの中に直接書くことに抵抗を感じている方には、ぜひ読んでいただきたい内容です。

この記事では、環境差分をVBAのプログラムに持ち込まないための具体的な解決策やベストプラクティスを紹介しています。

これにより、より柔軟で拡張性、保守性の高いVBAアプリケーションを開発できるようになるでしょう。

MakeFolderNameTableForOutlook 関数 の紹介

説明

Outlook で使用しているメールの AccountName(アカウント名) 、InboxName(受信トレイの名前) 、NumberOfSubforuders(以降に続くサブフォルダの個数)SubFolder1SubFolder2…といった以下のフィールド定義を持つテーブルを自動作成します。

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する
【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する
しらかば堂

SubFolder1SubFolder2… は以下のようにお使いのOutlook上から受信トレイ配下のフォルダ作成状況を自動的に読み取って必要な個数分が自動的にフィールド定義されます。

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する

参照オブジェクト

このユーザー定義関数を利用するためにはこの関数の実行前に

データベースツール > Visual Basic > ツール > 参照設定
で以下の画面を表示し

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する

 

  • Microsoft Office 16.0 Access Database engine
  • Microsoft Outlook 16.0 Object Library
  • Microsoft ActiveX Data Object 6.1 Library

にチェックを入れる必要があります。

利用例

Access のマクロ定義例えば “M0000_Call_MakeFolderNameTableForOutlook” の中で

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する


以下のように

If MakeFolderNameTableForOutlook("OutLookFolderes")>0 Then
メッセージボックス ("OutLookFolderes" の作成に失敗しました。,はい,なし) 
If 文の最後


MakeFolderNameTableForOutlookを “OutLookFolderes” のようなパラメータを付けて呼び出します。ここに “OutLookFolderes” は作成されるテーブルの名前です。

そして Outlookを起動状態にして

この “M0000_Call_MakeFolderNameTableForOutlook” のでデザインビューを閉じて、この マクロをダブルクリックして実行すると

以下のように左側のナビゲーションウインドウの一番上に、今まで存在しなかった  “OutLookFolderes”  というテーブルが作成されます。

この”OutLookFolderes” を 「開く(O)」 で見ると以下のようにこのテーブル内にOutlookのフォルダ配下の構造が既に取り込まれています。

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する


また「デザインビュー(D)」でこのテーブルのフィールド定義を見ると

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する


のようになっており、期待どおりに自動生成されています。

【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する
しらかば堂

このツールの起動前にOutlookが起動していることを保証するための方法については必要に応じて以下の記事を参考にしてくださいね。

【Windows業務効率化】バッチファイルを使って未起動状態のアプリケーションを自動起動する

引数

属性 意味
テーブル名 文字型 作成するテーブルの名前を””で囲んだ文字列で関数のパラメータとして指定します。

戻り値

意味
0 正常終了
1 異常終了

VBAコード

MakeFolderNameTableForOutlook

このコードは、Outlookのフォルダプロパティから現在定義されているフォルダ名を自動取得し、Accessデータベース内に新しいテーブルを作成後、これらのフォルダ名をこのテーブルに保存する関数です。この関数を呼び出すことで、Outlook で現在定義されているフォルダ名を Access データベースに自動的に取り込むことができます。

Function MakeFolderNameTableForOutlook(table_name As String) As Integer
    ' 成功、失敗の定数の定義
    Const C_SUCCESS As Integer = 0
    Const C_FAILURE As Integer = 1
    ' フォルダのレイヤー数、フォルダ数、フォルダ名の配列の宣言
    Dim numberOfFoldersLayers As Integer
    Dim numberOfFolders As Integer
    Dim foldersName() As Variant
    ' エラーハンドリング
    On Error GoTo exitWithFailure
    ' Outlookからフォルダプロパティを取得
    Call getFoldersPropertiesFromOutlook(numberOfFolders, numberOfFoldersLayers, foldersName)
    ' テーブル作成
    Call makeFolderNameTable(table_name, numberOfFolders, numberOfFoldersLayers, foldersName)
    ' フォルダ名をテーブルに挿入
    Call putFolderNameToFolderNameTable(table_name, numberOfFolders, numberOfFoldersLayers, foldersName)
    ' 成功を返す
    MakeFolderNameTableForOutlook = C_SUCCESS
    Exit Function
exitWithFailure:
    ' 失敗を返す
    MakeFolderNameTableForOutlook = C_FAILURE
End Function

MakeFolderNameTableForOutlookの簡単な説明

 

行番号 説明
1 関数名と関数の戻り値の型(Integer:整数型)、入力パラメータの名前、型(String:文字列型)を定義しています。
3-5 このプログラムの中で利用する定数C_SUCCESS(0:成功)、C_FAILURE(1:失敗)を定義しています。ここでは41行目でこの関数の戻り値が C_SUCCESS(0:成功)であるごとが明確にわかるようなコーディングの仕方になります。
7-10 この関数の中で利用される変数  numberOfFoldersLayers 、numberOfFoldersfoldersName  の定義をしています。
ここに numberOfFoldersLayers はこの関数が作成するテーブルのフィールド数を決めるためのもので.numberOfFolders はレコード数を決めるもの、foldersName はレコードを仮に保存する配列です。
これらの変数は実体をここで定義し、以降のプロシージャを呼び出す際に参照のパラメータとして引数指定されることで、値を更新をします。
12-13 この関数の実行中にエラーが発生したときの例外処理として、exitWithFailure にジャンプします。
15-16 起動中のOutlookからメール受信フォルダ内のフォルダに関するプロパティを取得して、number_of_foldersnumber_of_folders_layerfolder_name  を設定するプロシージャ getFoldersPropertiesFromOutlook をコールします。
18-19 取得したプロパティに従ってテーブル絵を作成するプロシージャ dd をコールします。
21-22 作成したテーブルにOutlookのメール受信フォルダ内のフォルダの実際の値をします。
24-26 この関数の戻り値に C_SUCCESS(0:成功) を設定して関数を終わります。
28-31 この関数の戻り値に C_FAILURE (1:失敗) を設定して関数を終わります。

getFoldersPropertiesFromOutlook

このコードは、起動中のOutlookからメール受信フォルダ内のフォルダに関するプロパティを取得し、参照型変数 number_of_folders 、number_of_folders_layer 、folder_name  に設定するサブルーチンです。

Sub getFoldersPropertiesFromOutlook(ByRef number_of_folders As Integer, ByRef number_of_folders_layer As Integer, ByRef folder_name As Variant)
' OutlookのApplicationオブジェクトとNamespaceオブジェクトを宣言
Dim objOutlook As Outlook.Application
Dim objNamespace As Outlook.Namespace
' Outlookのアカウントとフォルダを宣言
Dim objAccount As Outlook.Account
Dim objInbox As Outlook.Folder
' エラーハンドリング
On Error GoTo exitWithFailure
' 取得したフォルダ名を格納する配列を宣言
ReDim folder_name(0 To 100)
' 取得するフォルダの階層数を初期化
number_of_folders_layer = 1
' 取得するフォルダの数を初期化
number_of_folders = 0
' OutlookのApplicationオブジェクトとNamespaceオブジェクトを設定
Set objOutlook = Outlook.Application
Set objNamespace = objOutlook.GetNamespace("MAPI")
' すべてのアカウントに対して処理を繰り返す
For Each objAccount In objNamespace.Accounts
    
    ' 現在のアカウントのInboxフォルダを取得する
    Set objInbox = objNamespace.Folders(objAccount.DeliveryStore.DisplayName).Folders("受信トレイ")
    
    ' 取得したフォルダのプロパティを取得する
    Call getFolders(objInbox, number_of_folders, number_of_folders_layer, folder_name)
    
Next objAccount
' 取得したフォルダ名を格納する配列のサイズを更新
ReDim Preserve folder_name(0 To number_of_folders)
exitWithFailure:
    
' クリーンアップ
Set objOutlook = Nothing
Set objNamespace = Nothing
End Sub

getFoldersPropertiesFromOutlook の簡単な説明

行番号 説明
1 サブルーチン名 getFoldersPropertiesFromOutlook  と参照型変数 number_of_foldersnumber_of_folders_layerfolder_name の名前、型を定義しています。
3-9 このプログラムの中で利用する OutlookobjOutlook Outlook.Application オブジェクト、objNamespace  Outlook.Namespace オブジェクト、objAccount  Outlook.Account オブジェクト、objInbox  Outlook.Folder オブジェクトを宣言しています。
11-12 Outlook  が起動されていない等のエラーが発生したときの例外処理として、exitWithFailure にジャンプします。
14-15 参照型配列引数 foldersName  のサイズを(普通OutlookのINBOXフォルダ中にそんなにたくさんフォルダを作らないでしょという推定を元に) 1+100 に仮設定し、初期化しています。このサイズは処理後に実使用領域に合わせて正しく再調整されます。
17-21 取得するフォルダの最大階層数 number_of_folders_layer 、フォルダ数 number_of_folders  を初期化します。
23-25 起動中の Outlook を参照して objOutlookobjNamespace  オブジェクトを設定します。これにより Access からあたかも Outlook を直接参照しているような状態に見せることができます。
27-36 Outlook で使用している全てのメールアカウントを順に参照し
そのメールアカウント配下の受信トレイを起点として
配下のフォルダ名を取得するための  getFolders を呼び出します。
この処理は Outlook に複数プロバイダからのメールアカウント登録がされている場合に備えた処理です。
38-39 foldersName  のサイズを実使用領域に合わせて正しく再調整します。
ReDim ステートメント中の Preserve 指定は既に設定されているデータ領域を保存してサイズ調整するという意味です。
41 例外処理のジャンプ先を指定します。
43-45 ここで使用した objOutlookobjNamespace オブジェクト をメモリ開放します。
【Access VBA】Outlookのフォルダ名を保存するテーブルを自動生成する
しらかば堂

ご覧頂いているように Outlook のオブジェクト構造はなかなか複雑なので
必要に応じて以下の参考図書を参照されることをお勧めします。

getFolders

このVBAコードは、Outlook 内の指定フォルダを起点として配下のフォルダ名を再帰的に取得するためのサブルーチンです。

Sub getFolders(ByVal objParentFolder As Outlook.Folder, ByRef number_of_folders As Integer, ByRef number_of_layer As Integer, ByRef folder_name As Variant)
    Dim objSubfolder As Outlook.Folder
    Dim intCurrentLayers As Integer
    
    number_of_folders = number_of_folders + 1
    folder_name(number_of_folders) = objParentFolder.FolderPath
    ' 全てのサブフォルダに対して再帰的にフォルダ名を取得する
    For Each objSubfolder In objParentFolder.Folders
        ' 現在のフォルダの深さを計算する
        intCurrentLayers = countCharacter(objSubfolder.FullFolderPath, "\") - 1
        Debug.Print objSubfolder.FullFolderPath, intCurrentLayers
        ' 最大の深さを記録する
        If number_of_layer < intCurrentLayers Then number_of_layer = intCurrentLayers
        ' サブフォルダに再帰的にフォルダ名を取得する
        Call getFolders(objSubfolder, number_of_folders, number_of_layer, folder_name)
        
    Next objSubfolder
End Sub

getFoldersの簡単な説明

 

行番号 説明
1 サブルーチン名 getFolders と値渡型変数 objParentFolder、参照型変数 number_of_foldersnumber_of_folders_layerfolder_name の名前、型を定義しています。
3-4 このプログラムの中で利用する Outlook.Folder 型の objSubfolder intCurrentLayers  を宣言しています。
6-7 呼び出し時の objParentFolder をもとに number_of_folders  をカウントアップし、folder_name 配列にフォルダのフルパス名を追加します。
9-22 objParentFolder 配下のサブフォルダを getFolders 自身を再帰的に呼び出すことで順にたどり、そのフルパス名の深さつまり intCurrentLayers を”\”の出現回数をcountCharacter 関数を使って求め、 もし number_of_layer よりも大きかったら  number_of_layer  を更新します。

countCharacter

このVBAコードは、指定された文字列内に指定された文字が出現する回数をカウントする関数です。

Function countCharacter(ByVal input_string As String, ByVal input_character As String) As Integer
     
    countCharacter = Len(input_string) - Len(Replace(input_string, input_character, ""))
 
End Function

countCharacterの簡単な説明

 

行番号 説明
1 関数名 countCharacterと関数の戻り値の型(Integer:整数型)、値渡型変数 input_stringinput_character の名前、型を定義しています。
3 文字列 input_stringinput_string 中にある 文字 input_character を””で置き換えた文字列との長さの差を求めることで、input_character  の出現回数を求めています。

makeFolderNameTable

このVBAコードは、Access データベース内にフォルダ名を格納するためのテーブルを作成するサブルーチンです。

Sub makeFolderNameTable(ByVal table_name As String, ByRef number_of_folders As Integer, ByRef number_of_folders_layer As Integer, ByRef folder_name As Variant)
    ' 変数の宣言
    Dim newTable As DAO.TableDef
    Dim dataAccessObject As DAO.Database
    Dim tableDefinition As Variant
    Dim index As Integer
    ' エラーハンドリング
    On Error GoTo exitWithFailure
    ' Accessデータベースの取得
    Set dataAccessObject = CurrentDb
    ' テーブルの存在確認と削除
    For Each tableDefinition In dataAccessObject.TableDefs
        If (tableDefinition.Name = table_name) Then
            DoCmd.DeleteObject acTable, tableDefinition.Name
        End If
    Next
    ' テーブルの作成
    Set newTable = dataAccessObject.CreateTableDef(Name:=table_name)
    ' フィールドの追加
    With newTable.Fields
        .Append newTable.CreateField("AccountName", dbText)
        .Append newTable.CreateField("InboxName", dbText)
        .Append newTable.CreateField("NumberOfSubFolders", dbInteger)
        For index = 3 To number_of_folders_layer
            .Append newTable.CreateField("SubFolder" & CStr(index - 2), dbText)
        Next index
    End With
    ' テーブルの追加とクローズ
    dataAccessObject.TableDefs.Append newTable
    dataAccessObject.Close
    
    ' Accessデータベースウィンドウの更新
    Application.RefreshDatabaseWindow
exitWithFailure:
    ' 変数の解放
    Set newTable = Nothing
    Set dataAccessObject = Nothing
End Sub

makeFolderNameTableの簡単な説明

 

行番号 説明
1 サブルーチン名 makeFolderNameTable と値渡型変数 table_name、参照型変数 number_of_foldersnumber_of_folders_layerfolder_name の名前、型を定義しています。
3-7 新しいテーブルを表す DAO.TableDef オブジェクト newTable 、Accessデータベースを表す DAO.Database オブジェクト(注1) dataAccessObject 、テーブルの定義情報を表す Variant 型変数 tableDefinition 、および整数型変数 index を宣言します。
9-10 エラーハンドリングの設定。処理中にエラーが発生した場合、exitWithFailure ラベルで指定された行にジャンプして処理を終了します。
12-13 Accessデータベースを取得し、dataAccessObject 変数に代入します。
15-20 テーブルがすでに存在する場合は、そのテーブルを削除します。
22 新しいテーブルの DAO.TableDef オブジェクトを作成し、newTable 変数に代入します。
25-33 新しいテーブルにフィールドを追加します。AccountNameInboxNameNumberOfSubFolders、および folder_name 配列の要素に対応する SubFolder1 から SubFolder(number_of_folders_layer-2) までのフィールドを追加します。
35-37 table_name  で指定された新しいテーブルを Access データベースに追加し、クローズします。
39-40 新しくできた table_name を表示状態にするため、Access のナビゲーションウィンドウを更新します。
44-46 オブジェクト変数を解放します。

(注1) DAO(Microsoft Data Access Objects) : ソフトウェアからデータベースへの接続、データの読み書きなどの操作を行うためのプログラム部品およびその呼び出し規約(API)の一つ。マイクロソフト社が提供する同社のデータベースソフト「Microsoft Access」での利用に最適化されている。ソフトウェア開発者はDAOを呼び出して処理を依頼することにより、簡潔なコードでデータベースへのアクセスを実現することができます。

putFolderNameToFolderNameTable

このVBAコードは、Outlookのフォルダー構造の情報をAccessのテーブルに格納するためのものです。

Sub putFolderNameToFolderNameTable(ByVal table_name As String, ByRef number_of_folders As Integer, ByRef number_of_folders_layer As Integer, ByRef folder_name As Variant)
    ' ADODB.ConnectionとADODB.recordSetを宣言
    Dim adodbConnestion As New ADODB.Connection
    Dim recordSet As New ADODB.recordSet
    ' インデックス変数の宣言
    Dim intIndexRow As Integer
    Dim intIndexColmn As Integer
    ' フォルダ名の配列、列名、列数の宣言
    Dim strAbsoluteFoldersName As String
    Dim strArray() As String
    Dim strColmnName As String
    Dim intNumberOfCulmn As Integer
    ' テーブルを開く
    Set adodbConnestion = CurrentProject.Connection
    recordSet.Open table_name, adodbConnestion, adOpenDynamic, adLockOptimistic
    ' データをループしてレコードを挿入
    For intIndexRow = 1 To number_of_folders
        strAbsoluteFoldersName = folder_name(intIndexRow)
        intNumberOfCulmn = countCharacter(strAbsoluteFoldersName, "\")
        strArray = Split(strAbsoluteFoldersName, "\")
        ' レコードの新規追加
        recordSet.AddNew
        recordSet("AccountName") = strArray(2)
        recordSet("InboxName") = strArray(3)
        recordSet("NumberOfSubFolders") = intNumberOfCulmn - 3
        ' サブフォルダの列をループしてレコードに追加
        For intIndexColmn = 4 To intNumberOfCulmn
            strColmnName = "SubFolder" & CStr(intIndexColmn - 3)
            recordSet(strColmnName) = strArray(intIndexColmn)
        Next intIndexColmn
        ' レコードの更新
        recordSet.Update
    Next intIndexRow
    ' レコードセットを閉じる
    recordSet.Close
    ' クリーンアップ
    Set recordSet = Nothing
    Set adodbConnestion = Nothing
End Sub

putFolderNameToFolderNameTableの簡単な説明

行番号 説明
1 サブルーチン名 putFolderNameToFolderNameTable と値渡型変数 table_name、参照型変数 number_of_foldersnumber_of_folders_layerfolder_name の名前、型を定義しています。
3-5 テーブルへのデータ追加のため、 adodbConnestion  という ADODB.Connection オブジェクト、recordSet  という ADODB.Recordsetオブジェクトを宣言します。
7-15 インデックス変数 intIndexRowintIndexColmn、 およびフォルダー名 strAbsoluteFoldersName 、 その分離用配列 strArray 、列名 strColmnName  、および列数 intNumberOfCulmn  を宣言します。
29-43 table_name で指定されたテーブル名でテーブルを開き
folder_name 配列に保存された内容を”\”文字で分離して
AccountNameInboxNameNumberOfSubFolders、そして階層分のSubFolder(N:階層の番号)のレコード
を順に追加してゆきます。そしてこれをフォルダーの数だけループを回して繰り返します。
45-46 最後に、Recordsetを閉じます。
48-50 オブジェクト変数を解放します。

 

まとめ

この記事では Microsoft Access 上で「Outlookのフォルダ名を保存するテーブルを自動生成する」 MakeFolderNameTableForOutlookというユーザー定義関数について紹介しました。

この情報が読者のお役に立てば幸いです。

ライブラリ一覧