目次
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(以降に続くサブフォルダの個数)、SubFolder1、 SubFolder2…といった以下のフィールド定義を持つテーブルを自動作成します。
参照オブジェクト
このユーザー定義関数を利用するためにはこの関数の実行前に
データベースツール > Visual Basic > ツール > 参照設定
で以下の画面を表示し
- Microsoft Office 16.0 Access Database engine
- Microsoft Outlook 16.0 Object Library
- Microsoft ActiveX Data Object 6.1 Library
にチェックを入れる必要があります。
利用例
Access のマクロ定義例えば “M0000_Call_MakeFolderNameTableForOutlook” の中で
以下のように
If MakeFolderNameTableForOutlook("OutLookFolderes")>0 Then
メッセージボックス ("OutLookFolderes" の作成に失敗しました。,はい,なし)
If 文の最後
MakeFolderNameTableForOutlookを “OutLookFolderes” のようなパラメータを付けて呼び出します。ここに “OutLookFolderes” は作成されるテーブルの名前です。
そして Outlookを起動状態にして
この “M0000_Call_MakeFolderNameTableForOutlook” のでデザインビューを閉じて、この マクロをダブルクリックして実行すると
以下のように左側のナビゲーションウインドウの一番上に、今まで存在しなかった “OutLookFolderes” というテーブルが作成されます。
この”OutLookFolderes” を 「開く(O)」 で見ると以下のようにこのテーブル内にOutlookのフォルダ配下の構造が既に取り込まれています。
また「デザインビュー(D)」でこのテーブルのフィールド定義を見ると
のようになっており、期待どおりに自動生成されています。
このツールの起動前にOutlookが起動していることを保証するための方法については必要に応じて以下の記事を参考にしてくださいね。
引数
属性 | 意味 | |
---|---|---|
テーブル名 | 文字型 | 作成するテーブルの名前を””で囲んだ文字列で関数のパラメータとして指定します。 |
戻り値
値 | 意味 |
---|---|
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 、numberOfFolders 、foldersName の定義をしています。 ここに numberOfFoldersLayers はこの関数が作成するテーブルのフィールド数を決めるためのもので.numberOfFolders はレコード数を決めるもの、foldersName はレコードを仮に保存する配列です。 これらの変数は実体をここで定義し、以降のプロシージャを呼び出す際に参照のパラメータとして引数指定されることで、値を更新をします。 |
12-13 | この関数の実行中にエラーが発生したときの例外処理として、exitWithFailure にジャンプします。 |
15-16 | 起動中のOutlookからメール受信フォルダ内のフォルダに関するプロパティを取得して、number_of_folders 、number_of_folders_layer 、folder_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_folders 、number_of_folders_layer 、folder_name の名前、型を定義しています。 |
3-9 | このプログラムの中で利用する Outlook の objOutlook 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 を参照して objOutlook 、objNamespace オブジェクトを設定します。これにより Access からあたかも Outlook を直接参照しているような状態に見せることができます。 |
27-36 | Outlook で使用している全てのメールアカウントを順に参照し そのメールアカウント配下の受信トレイを起点として 配下のフォルダ名を取得するための getFolders を呼び出します。 この処理は Outlook に複数プロバイダからのメールアカウント登録がされている場合に備えた処理です。 |
38-39 | foldersName のサイズを実使用領域に合わせて正しく再調整します。 ReDim ステートメント中の Preserve 指定は既に設定されているデータ領域を保存してサイズ調整するという意味です。 |
41 | 例外処理のジャンプ先を指定します。 |
43-45 | ここで使用した objOutlook 、objNamespace オブジェクト をメモリ開放します。 |
ご覧頂いているように 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_folders 、number_of_folders_layer 、folder_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_string 、input_character の名前、型を定義しています。 |
3 | 文字列 input_string と input_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_folders 、number_of_folders_layer 、folder_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 | 新しいテーブルにフィールドを追加します。AccountName、InboxName、NumberOfSubFolders、および 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_folders 、number_of_folders_layer 、folder_name の名前、型を定義しています。 |
3-5 | テーブルへのデータ追加のため、 adodbConnestion という ADODB.Connection オブジェクト、recordSet という ADODB.Recordsetオブジェクトを宣言します。 |
7-15 | インデックス変数 intIndexRow 、intIndexColmn、 およびフォルダー名 strAbsoluteFoldersName 、 その分離用配列 strArray 、列名 strColmnName 、および列数 intNumberOfCulmn を宣言します。 |
29-43 | table_name で指定されたテーブル名でテーブルを開き folder_name 配列に保存された内容を”\”文字で分離して AccountName、 InboxName、NumberOfSubFolders、そして階層分のSubFolder(N:階層の番号)のレコードを順に追加してゆきます。そしてこれをフォルダーの数だけループを回して繰り返します。 |
45-46 | 最後に、Recordsetを閉じます。 |
48-50 | オブジェクト変数を解放します。 |
まとめ
この記事では Microsoft Access 上で「Outlookのフォルダ名を保存するテーブルを自動生成する」 MakeFolderNameTableForOutlookというユーザー定義関数について紹介しました。
この情報が読者のお役に立てば幸いです。
SubFolder1、 SubFolder2… は以下のようにお使いのOutlook上から受信トレイ配下のフォルダ作成状況を自動的に読み取って必要な個数分が自動的にフィールド定義されます。