2011年11月20日日曜日

step4.5 添付ファイルを連番で保存

step4では、Outlookで受信した添付ファイルをとりあえず保存する方法を紹介しました。
これはこれで便利だと思います。
ただ、これは結構大ざっぱな作りです。

というのも、「SaveAs」は同一のファイル名のファイルが存在する場合上書き保存になってしまうからです。
ですので、一度に同一名ファイルのものを処理しようとすると最後に処理したファイルのみがポツンとフォルダに残った状態に。






NTTフレッツ光





いろいろ回避の仕方はありますが、その一つがファイルを連番で保存するというやり方です。
abc_2.csv、abc_3.csv、abc_4.csv、…、abc_n.csv (n = 2,3,4…)
という感じです。

こうした形式の保存方法のヒントはすでに文字列についてのエントリーで紹介済みです。
考え方としては、下のフローチャートのようになります。






















これであれば、100個でも200個でも大丈夫です。
さて、コードは以下の通り。

file_name = myfolder.Items(i).Attachments(j).DisplayName
If Dir(path & file_name) = "" Then
myfolder.Items(i).Attachments(j).SaveAsFile (path & file_name)
Else
'同じ名前のファイルが保管フォルダーにあるので、名前を変更
k = 2
While Dir(path & Replace(file_name, Right(file_name, 4), "") & "_" & k & Right(file_name, 4)) <> ""
k = k + 1
Wend
myfolder.Items(i).Attachments(j).SaveAsFile (path & Replace(file_name, Right(file_name, 4), "") & "_" & k & Right(file_name, 4))

コードの冒頭で読みやすくするために、file_nameという変数の中に添付ファイルのオリジナルのファイル名を突っ込んでいます。
これで可読性が上がり、自分に優しいコードになります。 簡単ですが、これで連番で保存することが出来るようになります。



PVランキング 人気ブログランキングへ

2011年11月17日木曜日

step4 添付ファイルを一括で自動保存

step3 送信者のアドレス、件名を習得できるようになりました
step3.5 文字列操作で必要な最低限の知識もカバーしました。

これで下準備は万全です。

今回は、早速メールに添付されているファイルを一括でマクロを使って保存する方法について整理しましょう。

これでほとんど目標に掲げたことをカバーできるようになります。




NTTフレッツ光






Sub Outlook_test()
Dim objOL As Object
Dim objNAMESPC As Object
Dim myfolder As Object

Set objOL = CreateObject("Outlook.Application")
Set objNAMESPC = objOL.GetNamespace("MAPI")
Set myfolder = objNAMESPC.GetDefaultFolder(olFolderInbox)
Debug.Print myfolder

myfolder.Items.Count
Debug.Print myfolder.Items.Count

Dim path As String
path ="C://abc/"  '保存先のフォルダ名

Dim i As Long
i = 1
Dim ItemNumber As Long
ItemNumber = myfolder.Items.Count
Do While i <= ItemNumber
   Debug.print "受信時間" & myfolder.Items(i).ReceivedTime & "アドレス" & myfolder.Items(i).SenderEmailAddress & "件名" & myfolder.Items(i).Subject

 If UCase(myfolder.Items(i).SenderEmailAddress) Like UCase("yamada[@]outlook[.]com") then
            Dim attm as Integer
       attm = myfolder.Items(i).Attachments.Count
          For j =1 to attm
              myfolder.Items(i).Attachments(j).SaveAsFile (path & myfolder.Items(i).Attachments(j).DisplayName)
          Next j
i = i + 1
Loop
End Sub
さて解説です。
Dim path As String path ="C://abc/" '保存先のフォルダ名。
ここで、保存先フォルダを指定しています。 あとで、ファイル保存するとこれでも触れますが、最後に「/」(もしくは「\」)を付けて下さい。 これがないと、フォルダ名とファイル名がごっちゃになってしまい、保存できません。
If UCase(myfolder.Items(i).SenderEmailAddress) Like UCase("yamada[@]outlook[.]com") then Dim attm as Integer attm = myfolder.Items(i).Attachments.Count For j = attm myfolder.Items(i).Attachments(j).SaveAsFile (path & myfolder.Item(i).Attachments(j).DisplayName)
ここが本日のポイント。 やっていることは、 yamada[@]outlook[.]comから届いたメールのみを対象にして、添付してあるファイルを順番に、指定したフォルダに保存 です。 UCase関数で、すべて大文字にしてあげてます。 どの文字が大文字か事前に予想できない場合は、全て大文字化してしまえばスルーすることはないですし、個別に条件を追加しなくてもすみます。 <ここで、注意点!> 「@」「-」「_」「.」などは[]でくくって下さい。 くくらないとこれら記号は、文字列として処理できません。 ちなみに、ファイルが複数添付されていてもいいように、
attm = myfolder.Items(i).Attachments.Count
で添付ファイルの合計数を数えて、1番目からその合計数まで保存作業を繰り返させています。 保存作業はここですね。
myfolder.Items(i).Attachments(j).SaveAsFile (path & myfolder.Item(i).Attachments(j).DisplayName)
「SaveAsFile」で、保存 「DisplayName」が添付ファイルのファイル名を取得するメソッドです。 DisplayNameはDisplayとありますが、拡張子を非表示にしていても、拡張子付きでファイル名を返してくれます。 これで、添付ファイルは保存できるようになりました。 しかもファイルがいくつ添付されていようと対応可能です。 100個で200個でも問題なし!! ただ、安定したツールにするにはいくつかハードルが残っています。 ・保存フォルダに既に同一ファイル名があったらどうする? ・一つのアドレスしか指定してないけど、実際にはもっとたくさんある ・アドレスだけじゃなくて、もっと複数の条件で絞らないといらない添付ファイルまで保存してしまう。 などなど。 次のエントリーで、そうした問題を整理しながら回避する方法をまとめましょう。 PVランキング 人気ブログランキングへ

2011年11月14日月曜日

社内SEが本音で語るサラリーマンに必要なたった一つのプログラミング言語

このサイトを見てる人なら、一度はこんな風に考えた事ありますよね?

・仕事楽にしたいなぁ
・ルーティング作業なのにどうしして手でやってるんだろ?
・自動でできないかなぁ
・てゆーかめんどくさい







NTTフレッツ光







で、最近はやりのXXX HACK!的な本を立ち読みしてみたり、アマゾンでつい買ってみっちゃったり。

「自動」って言葉を聞くとプログラムって連想して、Google様に「自動化 プログラム」とかって聞いてみる。
そうすると、役に立ちそうでたたないページが山のように見つかる。
*今やってみましたら13,000,000件もひっかかりました。多すぎ!w

最近のはやりを見るとphpとか、iphone効果でObject-C。弾小飼にあこがれてperlを眺めてみたり。
でも普通のサラリーマンには不要です。

php:わざわざサーバーいじる必要ないですよ
java:どんだけ大規模な業務を自動化したいんですか?
Object-C:iphoneもipadも関係ないです。電車の中でブログを読むのに使ってるくらいです。
javascript:HTMLファイルに表示させる必要ないですから。

と気づくと自分の業務に関係してないプログラミング言語ばかりなことに気づきます。
なんかカッコいいし、使いこなせると世界が広がる感があるけど、要らないんです。
もちろんできるようになりたいけどね!!

で自分が何を使っているとデスクを見まわすと、
・エクセル
・Outlook
・パワポ
・ワード
・Internet Explorer
Office製品ばっかりじゃないかと気づきます。
そうあなたのデスクにはスティーブ・ジョブスはいないんです。

で、上記アプリで何をしているかというと
・表計算
・グラフ化
・データ入力
・メール
・資料作成
です。地味ですね。
僕には、Zenを意識したかっこいいパワポ資料を作るくらいしか刃向かう術を思いつけません。

やれやれと思いながら、データ入力が終わったファイルを別名で、今日の日付が名前になっているフォルダに保存と。
届いたメールに添付さているファイルをとりあえず作業用のフォルダにおいていつもの作業をするわけです。

で、以下のように思ったわけです。
ぼくは人生で何時間Microsoft社に囲まれて、Windowsで動く箱の中で作業をするんだろう?
もっとカッコよく楽な感じで過ごせないのかな

そこでたどり着いたのが、VBAですよVBScriptですよ。
普通のサラリーマンには、phpもRubyも要りません。
Object-Cは家でやって下さい。
仲良くなるべき相手は、スティーブじゃなくて、ビルです。ゲイツです。

驚きましたか?
残念ですか?
悔しいですが、これが現実なんです。















というわけで、Office製品代表格のひとつであるOutlookを少しでも楽に使いましょうよ!



コメントし忘れましたが、たまにアクセス使えると便利ですよね。たまにしか使わないけど…。
PVランキング 人気ブログランキングへ

step3.5 これだけは押さえておきたい文字列操作の3パターン

どんな関数を調べていくと一見、絶対使わないような関数が出てきます。
普段エクセルで表計算とかしている分だとほとんど使わないのがおそらく文字列操作に関連するものでしょう。
半角文字を全角に変換する関数とかもあります。
多分、一生使わない人が大半でしょう笑
(↑笑っておきながら、最近使いました。。。どんだけ人がやらないことやらされてるんだ orz)


今回は、目標であるプログラムを作成するにあたって絶対必要なものを3パターン計8個ピックアップします。





NTTフレッツ光






NTTフレッツ光





1.大文字、小文字に変換
相手のメールアドレスは本当に全部小文字ですか?
最初の一文字だけ大文字だったりしませんか?
ほとんどの場合全部小文字だけど、たまに特定の人だけ大文字混じりで届いたりしませんか?
安全な業務ツール作成するには、いちいちこんなことを考えるのは面倒なので、関数を使って大文字か小文字のどちらかに統一した方が楽です。


大文字化→ Upper(文字列)
小文字化→ Lower(文字列)


2.左から○○文字抜き出す、右からXX字抜き出す
ファイル名を指定するときに、こうした関数を使うことになります。
「特に右から4字抜き出す」はよく使ってます。

左から文字を書くのになんで、右からでしょう?
それは拡張子だけ分離したいときがよくあるからです。

左から○○文字抜き出す→ Left(文字列, ○○)
右からXX字抜き出す→ Right(文字列, XX)

右、左の両方とも使えるようになると、「左のXX目から、○○目まで」っていうのも気になりますよね。

左のXX目から、○○目まで→ Mid(文字列, XX, ○○)

ただこれは実は使うのが難しいケースが多いんです。
というのも、「文字列」が全部で何文字か予め分からないケースが多いから。
経験上、「何文字目から何文字目まで」抜き出すというより、「左からXX字目から、右から数えて○○字まで」抜き出したいことの方が多かった気がします。
こういうときは、全体で何文字あるか分からないとまずい。
出たとこ勝負ってわけにもいかないので、文字列の長さを数える必要があります。

文字列の長さを数える→ Len(文字列)

合わせ技で、こんな感じになります

Mid(文字列, XX, Len(文字列) - ○○)

これができると、予め何文字あるか知らないときでも何とかなります。


3.置換
ある文字を他の文字に置き換えるやつです。
むしろ、ある文字だけを消去したいときに便利な気がします。
今までやってきた範囲では、日付型ではない日付データに含まれているスラッシュ「/」を消して、yymmdd形式にしたりするっていうのに使いました。
*11/01/30→110130 とか。ファイル名、フォルダ名に日付を使うときによく使います。

XXを○○に置換→ Replace(文字列, XX, ○○)


しれっと「日付型」って言葉が出てきましたね。
プログラミングをする上で避けて通れないのが、「データの型」の理解です。
慣れないとややこしい上に、バグの原因になる…
初めのころはこれで相当苦労しました。
次のエントリーで最低限知っておくべきデータ型についてまとめますね。
step数がなかなか増えませんが、このへんを押さえていれば結構なんでも応用が効きますのでがんばりましょう!


今回は以下のサイトにお世話になりました。
エクセル関数のサイトですが、今回紹介した関数はそのままVBAでも使えます。
Excel(エクセル)基本講座
URL:http://www.eurus.dti.ne.jp/yoneyama/Excel/kansu/moji_1.htm


PVランキング 人気ブログランキングへ

2011年11月13日日曜日

step1.5 受信トレイ以外のフォルダを指定

step1では、デフォルトで指定されているフォルダ(受信トレイ)を指定先としてオブジェクトを作りました。
当たり前ですが、このままコードを書きすすめていくと、受信トレイにあるメールしかマクロで動かせません。
他のフォルダのメールも操作したいですよね?
という要望があるはずなので、ここでは番外編として好きなフォルダを指定する方法をまとめておきます。


ここでは試しに、受信トレイ直下にある「TEST」というフォルダを指定してみましょう。
Outlook上ではこんな感じの表示なっている状態です。



















コードは以下のようになります。

Set objOL = CreateObject("Outlook.Application")
Set objNAMESPC = objOL.GetNamespace("MAPI")
Set myfolder = objNAMESPC.Folders(olFolderInbox).Folders("TEST")
Debug.Print myfolder



イミディエイト・ウィンドウにTESTって表示されましたか?
objNAMESPC.Folders(olFolderInbox)で受信トレイまでたどり着いているので、その傘下にあるFolderを名前で指定してあげいるわけですね。



では、TESTフォルダーの下にある子TESTを指定したいときはどうするのでしょう?
こういう状態ですね。




















答えはこうですよね
Set objOL = CreateObject("Outlook.Application")
Set objNAMESPC = objOL.GetNamespace("MAPI")
Set myfolder = objNAMESPC.Folders(olFolderInbox).Folders("TEST").Folders("子TEST")
Debug.Print myfolder


ここまでやるとどれだけ下層のフォルダーでも指定できますね! ってそんな深くフォルダを作る人はいない気がしてきたが↓


PVランキング 人気ブログランキングへ

Outlook VBAの便利なサイト集

先人たちの知恵をここから学びに行きましょう!

三流君

ここがすごいのは、動画も一緒にアップしてくれているのでホントに「見て」分かります。






NTTフレッツ光





Outlook研究所

読者投稿に応えてエントリーを増やしたりしていてインタラクティブなサイトです。
エントリー数が多くて参考になる記事が多いのが特徴。







Outlook VBA Sample

シンプルな作りで、必要なパーツ毎にまとめられています。
コピペプログラマー向きなサイトです。






見つけたらまた追加していきます!
PVランキング 人気ブログランキングへ

step3 Outlook アドレス、件名、受信時間を調べる

前回は届いていたメールの総数を数えました。(step2
いよいよ個別メールの情報を調べていきましょう。
これが自在にできれば、目標にかなり近づきます!!
コードは↓のような感じ

Sub Outlook_test()
Dim objOL As Object
Dim objNAMESPC As Object
Dim myfolder As Object

Set objOL = CreateObject("Outlook.Application")
Set objNAMESPC = objOL.GetNamespace("MAPI")
Set myfolder = objNAMESPC.GetDefaultFolder(olFolderInbox)
Debug.Print myfolder

myfolder.Items.Count
Debug.Print myfolder.Items.Count

Dim i As Long
i = 1
Dim ItemNumber As Long
ItemNumber = myfolder.Items.Count
Do While i <= ItemNumber
   Debug.print "受信時間" & myfolder.Items(i).ReceivedTime & "アドレス" & myfolder.Items(i).SenderEmailAddress & "件名" & myfolder.Items(i).Subject

i = i + 1
Loop
End Sub
動きましたか? やってることは 「myfolderにあるi番目のアイテム(メールのこと)の受信時間(ReceivedTime)、アドレス(SenderEmailAddress)、件名(Subject)を表示する」 という作業をItemNumber(受信メール総数)回だけ繰り返す ということです。

NTTフレッツ光

ちなみに、プチネタですがプログラムを少し早く動かすために工夫があります。 ItemNumber = myfolder.Items.Count Do While i <= ItemNumber の部分です。 次のエントリーではいよいよ添付ファイルの情報を調べるやり方について書きます。 これって Do While i <= myfolder.Items.Count と書いても同じ意味ですよね? 変数も一つ減るし楽な感じがします。 でも、実はこの書き方の方が実行速度は落ちます。 なぜかというと、毎回myfolderにあるアイテムの数を数えているからです。 件数が少なければ大したことありませんが、1,000件も10,000件も溜っているメールボックスの情報を取る場合は目に見える差が出ます!! まぁちょっとしたこだわりです。 別に気にしなくても構いません。笑 PVランキング 人気ブログランキングへ