またまた前回からの続きです。
ExcelのPowerQueryではなくAccessに食わせるようにしました。
Accessの方が楽なので今後はAccessで作り込んでいこうと思います。
PowerShell
前回からの変更点
csv1行目の"TYPE System.Management.Automation.PSCustomObject"
を消すようにした
Accessにインポートする際に、1行目の非テーブル行が邪魔なので
- 最初の書き出しをテンポラリーファイルにして
- パイプ処理で1行目をスキップして別名保存
- テンポラリーファイルを削除
という工程を追加しました。
PowerQueryに食わせる場合でもこの処理をやっておくとクエリの編集で1行目を削除したりフィールド名設定が不要になります。
EntryID
プロパティを追加
Outlookでメールアイテムを開くのに必要なので列を追加
コード:PowerShell
# Outlookのフォルダからメール一覧を作成、CSVに吐き出す
# 参考(Outlook取得):https://www.itlab51.com/?p=6171
# 参考(CSV出力):https://use-computer.net/powershell/powershell-course-5
# 参考(列挙型):https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_enum?view=powershell-7.2
$oOutlook = New-Object -ComObject Outlook.Application
$oNamespace = $oOutlook.GetNamespace("MAPI")
# フォルダIndexの配列を作成
$arr_oFolders = @(5,6)
#$olFolderInbox = 6 #受信トレイ
#$olFolderSentMail = 5 #送信済みトレイ
# ループ回数の上限を設定(CSVに書き出すメール数)
$LimLoopCnt=10000
# 取得する文字数に制限をかける
$LimLenStr=10000
# 変数の初期化
$CsvData = @()
$rr=0
# $ary_namesの要素を 1 つずつ $oFolder に格納してループする
for($fld = 0; $fld -lt $arr_oFolders.Count; $fld++){
$oFolder = $oNamespace.GetDefaultFolder($arr_oFolders[$fld])
# $oFolder内の全アイテムを巡回して1レコードずつCSV出力用の変数に格納していく
foreach($oItem in $oFolder.Items){
# 取得する文字数に制限をかける(文字数が多すぎるとセルをはみ出してテーブル構造が崩れるため)
$Str = $oItem.Body
$LenStr = ($oItem.Body).Length
if ( $LenStr -gt $LimLenStr)
{$Str = $Str.Substring(0,$LimLenStr)}
# 添付ファイルリストを取得
$attList=""
foreach($att in $oItem.Attachments){
$attList += ";" + $att.FileName
}
# 1レコードずつCSV用の変数につぎ足していく
$CsvData += [PSCustomObject]@{
No = $rr+1 # 0始まりのため出力は1始まりにする
件名 = $oItem.Subject
本文 = $Str.Replace("`r`n","") #改行殺し
受信日時 = $oItem.ReceivedTime
受信者名 =$oItem.To #ReceivedByNameだと自分以外が空白になる
送信者名 =$oItem.SenderName
CC = $oItem.CC
ConversationID = $oItem.ConversationID
添付ファイル = $attList
}
# ループ脱出
$rr = $rr + 1
if( $rr -gt $LimLoopCnt){break}
}
}
# CSVに吐き出す
$CsvData | ft -AutoSize
$path = "C:\Users\●●●\●●●\"
$tmp = "temp.csv"
$csvName1 = "ol_受信BOX_Items.csv"
#テンポラリーファイル(csv)に書き出す
$CsvData | Export-Csv -Path $path$tmp -Encoding Default
#1行目を消して別名保存する( これ→ "TYPE System.Management.Automation.PSCustomObject")
Get-content $path$tmp | Select-Object -Skip 1 | Set-Content $path$csvName
#テンポラリーファイルを削除する
Remove-Item $path$tmp
Access
csvを取り込む
PowerShellで吐き出したcsvファイルを選択します。
フォームの作成
最終的には
- 検索ボックス
- メール一覧
- メール詳細
を同時に並べたいところですが、まずは
- 最低限のフォームを作成
- 表示中のメールアイテムをOutlookで開く
だけを作ります。
リボンからフォームを作成します。
このボタン1つでフィールドに合わせたフォームが自動生成されます。
(ExcelやOutlookでユーザーフォーム作ろうと思ったらここがもう面倒)
作成したフォームをデザインビューで開いてボタンを追加します。
ボタンに適宜名前をつけて、プロパティシートからクリック時イベントを追加します。
以下コードを貼り付けます。
コード:Access
GetNamespace("MAPI").GetItemFromID(EntryID)
で指定したメールアイテムを表示(Display
)するだけの超簡単なコードです。
Option Compare Database
Option Explicit
Private Sub btnアイテムをolで開く_Click()
Call EntryIDからメールを開く(EntryID.Value)
End Sub
Sub EntryIDからメールを開く(EntryID As String)
'appOLを呼び出す
Dim appOL As Outlook.Application
Set appOL = New Outlook.Application
Dim objMailItem As MailItem 'GetItemFromIDメソッドでEntryIDからメールアイテムを抽出する
Set objMailItem = appOL.GetNamespace("MAPI").GetItemFromID(EntryID)
objMailItem.Display
'オブジェクトをNothingしておく
Set appOL = Nothing
Set objMailItem = Nothing
End Sub
以上です。
残課題
Accessを開いたままPowerShellからcsvを更新したい
csvインポート時に「リンク」を選ぶと、PowerShellでcsvを更新したものがAccess側で自動でテーブルが更新されます。
が、Accessを開いたままでPowerShellを実行すると
Set-Content : 別のプロセスで使用されているため、プロセスはファイル 'C:\Users\●●●\●●●\ol_受信BOX_Items.csv' にアクセスできません。
とエラーが出ます。
リンクせずに取り込んでおいて、csvを読み直すのは別処理をすればいけるのかな?
メールアイテムの検索クエリを追加していく
クエリでテーブル抽出ができることは既知なので、メールアイテムをOutlookで開くことができるかの確認と、PowerShellの出力にEntryIDが必要と知ることが先だと思い、スモールステップで作りました。
次回は選択クエリの復習も兼ねてここやっていこうかな。