ラベル VBA の投稿を表示しています。 すべての投稿を表示
ラベル VBA の投稿を表示しています。 すべての投稿を表示

2021/03/14

業務効率化は「なぜ効率化するのか」が大事



こんにちは。tknria(@tknria0304)です。


大学院卒業後、新卒のときからずっと業務効率化をしてきて丸10年(2021年3月現在)になりました。

このブログだけでなく、効率化セミナーや相談会でも、業務効率化について発信し続けてこれたのは、みなさまのおかげです。

この場を借りて、お礼の言葉を述べさせていただきます。
本当にいつもありがとうございます。

今後も、tknria、億劫な細道ともに、よろしくお願いいたします。


さて、ここまでの10年で、様々な企業で、様々な職種の業務効率化に取り組んできました。

・精密機器メーカーの開発職
・IT企業のテレマーケティング営業職
・電機メーカーの技術営業職
・システムメーカーのシステム営業職
・ITベンチャーの営業職
・ITベンチャーのマネージャー職
・サービス系企業のwebマーケティング職
・サービス系企業の商品企画職
・サービス系企業の総務・労務職
・小売店のブランディング職

これらの業務を効率化してきて感じるのは、

「仕事が遅い人は、自分がやらなくても良い業務に時間を割きすぎている」

そして、

「そのことに意外と気づいていない」

ということです。

また、それに気づいて効率化をしようとしても、「効率化する目的・理由」がない場合が多いです。


自分がやらなくても良い業務をやらない


今取り掛かっているその業務、本当にあなたがやる必要がありますか。

実は後輩に任せてしまっても良いものなのではないでしょうか。

しかし、任せようと思うと教える必要があり、面倒なので自分でやってしまう。。

僕はそう考えて、自分でたくさんの業務を抱えてしまっていたことがありました。


ただ、それをいつまでも続けていても成長はなく、実績が変わらないので昇格もないと気づき、あるときを境にやめました。

最初はなかなかうまくいかないかもしれません。
任せたいと思っても、自分も忙しいからと断られることもあるでしょう。

それでも、その意志をはっきりと伝え、その代わり他でしっかり成果を出すと宣言して行動することが大事です。


効率化相談会で多くの人が抱える悩みのひとつはこれです。

そこも一緒に考えて、自分が本当にやるべき業務に集中できる環境を整えていきましょう。


そのために必要なのは、スキルや能力ではなく、効率化する理由です。


効率化で大事なのは効率化する理由


こう書くと、「業務時間を削減したいから、という理由があります」という方がいると思いますが、これは理由ではありません。


例えば、少し太っている方がダイエットしようとしても、なかなかうまくいきません。

それは理由がないからです。

理由がないため、ダイエットするのに必要な運動や食事制限という負荷に耐えられません。


業務効率化でも同じことが言えます。

特にVBAやGASで効率化するためには、スキルを身につけたり、コードを書いたりする時間を確保する必要があります。
そしてその時間を、慣れないことに費やす必要があります。

効率化したほうが良いのは全員わかっていますが、効率化する理由がそこまで強くないので、これらの負荷に耐えられません。


では、どのような理由が、理由になるのか。

ダイエットでいうと、ダイエットしたその先をイメージすることが重要です。

結婚式前の花嫁のダイエットは必ず成功します。

これは、ダイエットをしてこのドレスを着て結婚式に出る、という具体的なイメージと期日を決めているからです。
これが理由と呼べるものです。


効率化では、効率化することで浮いた時間を何に使うかを決める、ということになります。

ただ効率化しただけでは、その浮いた時間を有効に活用できず、ただ時間が空くだけになりがちです。

ですので、例えば、「その時間を資格試験の勉強に充てる」や「他の業務に充てて定時で帰るようにする」というイメージが重要です。


億劫なあとがき


いかがでしょうか。

「なぜ効率化するのか」

この重要性が伝われば幸いです。



関連記事

・これからGASを始めたい!という方にはこちらの記事がオススメ
 → 億劫な細道「GAS まずGASを使ってみたい」

・VBAやGASについてもっとざっくり知りたい方はこちらの記事がオススメ
 → 億劫な細道「VBAやGASを用いた業務効率化のススメ」

2018/09/15

VBAやGASを用いた業務効率化のススメ



こんにちは!日々さらなる業務効率化を探求しているtknriaです!

突然ですが、みなさんは業務効率化ときいて何を思い浮かべますか?

組織再編、業務フローの見直し、自動化ツールの作成、マクロ構築など・・・

ひと口に業務効率化といっても、目的も手段もさまざまです。


その中で僕がとりわけ好きなのが、VBAやGASといったプログラミング言語を用いた自動化です。

今日はその基本的な部分をご紹介していきます。



■ VBAとは??


VBAとはVisual Basic for Applicationsの略で、プログラミング言語の一つです。
Microsoft Office、特にExcelやAccessと組み合わせる使い方はよく取り上げられています。

Outlookでも活用することができ、メールに対する処理はもちろん、そのメールの内容によって他のOfficeと連携する(例えば、メールを受け取ったらExcelファイルを立ち上げて内容を自動で更新して保存する)といったことも実現可能です。

また、あまり活用例を見たことはありませんが、Wordに組み込むこともできます。
校正ルールや改行ルールにもとづいて自動で校正されるようプログラミングを組んでおくことで、文書作成者は書くことに専念できます。



■ GASとは??


続いてGASです。GASはGoogle Apps Scriptの略で、Javascriptをベースにしたプログラミング言語の一つです。

「VBAとは??」で触れたことを、スプレッドシートやドキュメントでできたらいいなーと思ったことありませんか??
それを実現してくれるのがGASです。

また、GASはスプレッドシートやドキュメントの機能を拡張するだけでなく、GmailやGoogle Calendarなど他のGoogleアプリとの連動性も高いのがポイントです。

GASについて勉強したいという方にオススメなのはコチラ!


この本、すごく参考になります。
ネットで解決策を探して改善しなかったエラーでも、この本を読めば解決する!ということも多々あります。


■ 億劫なあとがき


今回はひとまずここまで!
ざっくりとした紹介ですが、とにかくなんか便利そう!すごいことができそう!という感覚が伝われば幸いでございます。
実際の活用例は追々紹介させていただきます。

2014/03/13

【Outlook】メールを再送したい VBA編



こんにちは!「速いは美学!」がモットーのtknriaです!


メーラー「Outlook(読み:アウトルック)」の唯一の難点ともいえる、「再送信」のわかりにくさ。

これまでに2つ、その方法をお伝えしてきました。

今回は、最も速く再送信できる方法をお伝えします。

それはOutlook VBAを用いるものです。

これまでの2つに比べて前準備がとても複雑になっているので、覚悟をもってお進みください。



Outlook VBAで再送信するメリット


設定方法をお伝えする前に、この方法を用いることでどんなメリットがあるか、考えてみたいと思います。


従来の方法からこの方法に切り替えることで、1回の再送信あたり約2sec削減できるとします。

1日に1人が5回使えば、1日、1人あたり10secの削減。

この機能を100人規模の会社に導入し、1年間(240営業日)使用すると、

10sec/人・日 * 100人 * 240日 = 240,000sec/年 = 4,000min/年 = 66.7h/年 の削減になります。


1hあたり3,000円の利益を創り出しているとすると、年間20万円の増益。

この機能を実装するのに必要な工数は、100人に導入しても2h程度。


従って、0.6万円の利益創出を一旦止めることで、毎年、年間20万円のプラス。

このプラスが、実装した初年度だけでなく、Outlookを使い続ける限り続きます。


経営者として、これを見逃す手はないのではないでしょうか。

ここまでメリットをお伝えしてきたので、次はいよいよ方法をお伝えします。



Outlook VBAで再送信する方法


少し複雑で、8ステップもありますが、上記のメリットのために頑張ってチャレンジしてみましょう!


1.Outlookを起動した状態で、「Alt + F11」でVBEを開く。


2.以下のVBAコードをコピペして保存。


3.コード中のSAVE_PATHのパスと一致するように、必要であればフォルダを作成する。

  (パスのほうを変更しても問題ない)


4.リボン上で右クリックして、「リボンのユーザー設定」を選択。


5.「ホーム(メール)」内に新しいグループを作成し、名前を変更する。


6.作成したグループを選択しながら、左側の「コマンド選択」で「マクロ」を選択する。


7.2.で作成したマクロ(デフォルトだとマクロ名の終わりが「Resending」)を選択して追加。


8.追加したマクロの名前とアイコンを変更する。


'-------以下、ソース

Public Sub Resending()
    Const PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39fe001e""
    Const SAVE_PATH = "D:\temp_attach\"      ' 添付ファイルを一時保存しておくフォルダ
    On Error Resume Next
    Dim orgMail As MailItem
    Dim newMail As MailItem
    Dim orgRec As Recipient     'recipient は 宛先、受取人
    Dim newRec As Recipient
    Dim strAddress As String
    Dim strSmtp As String
   
    If TypeName(ActiveWindow) = "Inspector" Then
        Set orgMail = ActiveInspector.CurrentItem
    Else
        Set orgMail = ActiveExplorer.Selection(1)
    End If
   
    Set newMail = Application.CreateItem(olMailItem)
   
    newMail.Subject = orgMail.Subject
   
    Dim orgAttach As Attachment
    Dim strFileName As String
    For Each orgAttach In orgMail.Attachments
        strFileName = SAVE_PATH & orgAttach.FileName
        orgAttach.SaveAsFile (strFileName)
        newMail.Attachments.Add (strFileName)
        Kill (strFileName)
    Next
   
    newMail.Body = orgMail.Body
   
    For Each orgRec In orgMail.Recipients
        With orgRec
            If .AddressEntry.Type = "SMTP" Then
                strAddress = .Address
            Else
                strAddress = .AddressEntry.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
            End If
        End With

        If InStr(orgRec.Name, strAddress) = 0 Then
            Set newRec = newMail.Recipients.Add(orgRec.Name & "<" & strAddress & ">")
        Else
            Set newRec = newMail.Recipients.Add(orgRec.Name)
        End If
        newRec.Type = orgRec.Type
    Next
   
    newMail.Display
   
End Sub

'-------以上、ソース


さて、お疲れさまでした。

以上が設定です。


では、実際にOutlookでメールを再送してみましょう。



Outlook VBAで再送してみる


わざわざ章を分けていますが、それほど書くことがありません。

なぜか。

それは、再送信したいメールを選択した状態で、先ほど作成したボタンをクリックするだけだからです。



これだけ!

初級編に比べるととても速くなりました!!

ちなみに、再送する対象メールの添付ファイルが重いときは、さすがにちょっと遅くなってしまいます。



億劫なあとがき


いかがでしょうか。

VBAを使いますし、それぞれの状況に合わせてカスタマイズが必要なので、ちょっと苦手意識を持たれるかもしれません。

私自身もプログラミングは得意というレベルではないので、その気持ちがわかります。

しかし、チャレンジしてみて実装できたときの感覚が最高だということも知っています。

どちらを選択するかは、あなた次第です。



関連記事

・これからGASを始めたい!という方にはこちらの記事がオススメ
 → 億劫な細道「GAS まずGASを使ってみたい」

・VBAやGASについてもっとざっくり知りたい方はこちらの記事がオススメ
 → 億劫な細道「VBAやGASを用いた業務効率化のススメ」

2014/02/21

VBA セル内容とハイパーリンクが一致しているかを確認したい



こんにちは!ハイパーリンクしまくりのハイパーtknriaです!


みんな大好きハイパーリンク!

僕も仕事上、下図のように、URLデータを一覧にする作業があります。





例えば、

 ・ある展示会に出展している企業名と、企業概要を示すURL

 ・関連ニュース、トピックスのタイトルと、そのソース

などですね。


こうやってまとめた情報を使おうと、あるリンクに飛んだときに、セルに表示しているURLとリンクされたURLが異なる場合があります。

URLをコピーして、セルにペーストして、さらにそのハイパーリンク先としても指定して…という作業を繰り返していると、たまにミスっちゃうんですよね。人間だもの。

かといって、ある程度データを蓄積してからまとめて確認するのも大変ですし、データを追加する度に確認するのも面倒です。

そこで、一括ポン!でチェックするマクロを実装します。



■ VBAコード例


'----- 以下、ソース -----

Const DATA_MAX = 500
Const posi_URL = 3
Const posi_TITLE = 2

Sub ハイパーリンク確認_Click()
    Dim i As Integer
    Dim add_str As String
    Dim error As String
   
    With Worksheets("Sheet1")
        For i = 1 To DATA_MAX
            If .Cells(i, posi_URL).Hyperlinks.Count > 0 Then
                add_str = .Cells(i, posi_URL).Hyperlinks(1).Address
                If add_str = .Cells(i, posi_URL) Then
                Else
                    error = error & vbCrLf & i & "行目:" & Left(.Cells(i, posi_TITLE), 15)
                End If
            Else
            End If
        Next i
    End With
   
    If error = "" Then
        MsgBox ("内容一致!")
    Else
        MsgBox ("以下のハイパーリンクが間違っています。" & vbCrLf & error)
    End If
End Sub

'----- 以上、ソース -----



■ 億劫なあとがき


今回はあくまでも、セル内容とリンク先が一致しているかを確認する機能です。

リンク切れかどうかを一括判定する機能も必要だと思うので、それも今後実装します。


2014/02/18

VBA With~End Withによる高速化



こんにちは!高速化ネタが大好きなtknriaです!


繰り返し処理をしたい場合にちょー頼りになるVBA。

仕事では120%お世話になりまくりです。


そんなVBAですが、たま~に「処理遅いな。。」と感じてしまうこともあります。

原因はいろいろありますが、解決策の一つとして考えられ、すぐにでも導入できるものを紹介します。

それが「With ~ End With」構文。



■ Withを使ってみる(コード例)


まず、Excelのsheet上に、2つボタンを用意してください。




これらのボタンに以下を割り当てます。


'----- 以下、ソース -----

Const YOKO_MAX = 100
Const TATE_MAX = 5000
Const heikin = 10


Sub ベタ更新_Click()
    Dim start As Double
    Dim finish As Double
    Dim time_total As Double
    Dim i As Integer
    Dim j As Integer
    Dim kaisuu As Integer
 
    time_total = 0
 
    For kaisuu = 1 To heikin
        Worksheets("Sheet1").Range("A1:KN10000").Clear
        start = Timer
        For i = 1 To TATE_MAX
            For j = 1 To YOKO_MAX
                Worksheets("Sheet1").Cells(j, i) = 1
            Next j
        Next i
        finish = Timer
'        MsgBox ("ベタ更新:" & finish - start & "sec")
        time_total = time_total + (finish - start)
    Next kaisuu
 
    Worksheets("Sheet2").Range("B10") = time_total / heikin
 
End Sub


Sub with更新_Click()
    Dim start As Double
    Dim finish As Double
    Dim time_total As Double
    Dim i As Integer
    Dim j As Integer
    Dim kaisuu As Integer
 
    time_total = 0
 
With Worksheets("sheet1")
    For kaisuu = 1 To heikin
        .Range("A1:AI100").Clear
        start = Timer
        For i = 1 To TATE_MAX
            For j = 1 To YOKO_MAX
                .Cells(j, i) = 1
            Next j
        Next i
        finish = Timer
'        MsgBox ("with更新:" & finish - start & "sec")
        time_total = time_total + (finish - start)
    Next kaisuu
End With

    Worksheets("Sheet2").Range("B10") = time_total / heikin
 
End Sub

'----- 以上、ソース -----


n行、100列の幅に1を代入するというマクロですが、代入にかかった時間を計測しています。
また、今回は10回の試行の平均時間で比較します。



■ Withの効果!


横軸にn行、縦軸に平均時間secをとったグラフが以下の通り。



データ数10万個(1000行、100列)ともなると、約10%の時間削減効果が出てきています。

10%の時間削減は、その作業にかかる人件費の10%削減に繋がります!



■ 何で差が出るの?


この差はどうして生じるかというところですが、

        For i = 1 To TATE_MAX
            For j = 1 To YOKO_MAX
                Worksheets("Sheet1").Cells(j, i) = 1
            Next j
        Next i

だと、Worksheets("Sheet1")→Cells(j,i)→i,jをインクリ→
        Worksheets("Sheet1")→Cells(j,i)→i,jをインクリ→…
と処理されていくところが、


        With Worksheets("Sheet1")
            For i = 1 To TATE_MAX
                For j = 1 To YOKO_MAX
                    .Cells(j, i) = 1
                Next j
            Next i
        End With

だと、Worksheets("Sheet1")→Cells(j,i)→i,jをインクリ→Cells(j,i)→インクリ→Cells(j,i)→…
と処理されるためです。

家族の紹介をするときに、「○○家」ということを最初に伝えて、名前だけ紹介するのと同じ感覚でしょうか。
中学校の理科でいうと、信号を脳まで送らずに脊髄で処理する「反射」と同じ?



■ 億劫なあとがき


実験や評価の自動化ツールとしてExcel VBAを用いる人も多いと思うので、遅いと感じる人は見直してみてはいかがでしょうか。


2014/01/31

Outlook メール受信時に自動で添付ファイルを印刷する



こんにちは!承認しまくりのtknriaです!


役職が上がり、承認の権限を持つようになると、もちろん部下から承認依頼があります。

メールや電話で済む承認もありますが、見積書などに押印する承認もあります。


しかし、それ以外の仕事に追われて、部下から催促があるまで忘れてた!というケースもあるかと思います。

メールベースだと未読にしておかないと忘れるし、未読にしていても埋もれてしまうことがありますよね。

それよりかは、押印すべき書類を先に印刷しておけば、まだ管理しやすいのではないでしょうか。



■ 承認依頼内容を印刷しちゃう!


今回想定しているのは、メールの件名に「承認依頼」の文字が含まれていて、そのメールに添付ファイルがある場合です。

そのメールを受信したときに、その添付ファイルを自動で印刷する、という機能を実装します。


' ----- 以下、ソース -----

Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
        (ByVal hWnd As Long, ByVal lpsz0p As String, ByVal lpszFile As String, _
         ByVal lpszParams As String, ByVal lpszDir As String, _
         ByVal FsShowCmd As Long) As Long


Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
    Dim objItem As Variant
    Set objItem = Session.GetItemFromID(EntryIDCollection)
    If TypeName(objItem) = "MailItem" Then       
        ' ここに、メールを受信したときに行いたい処理を記載
        ' 添付ファイルを自動印刷
        Call PrintAttachments(objItem)
    End If
End Sub


Public Sub PrintAttachments(ByVal objMail As MailItem)
    Const ATTACH_PATH = "C:\temp_attach\"   ' 添付ファイルを保存するフォルダを指定
    Const MyAddress = "tknria@okku.com"   ' 自分のメールアドレス
    Dim objAttach As Attachment
    Dim strFileName As String
   
    If InStr(objMail.Subject, "承認依頼") > 0 Then
        ' 件名に「承認依頼」が入っているかを判定
        If objMail.To = MyAddress Then
            ' 自分宛のメールかどうかを判定
        Else
            Exit Sub
        End If
    Else
        Exit Sub
    End If
   
    If objMail.Attachments.Count > 0 Then
        For Each objAttach In objMail.Attachments
            ' 添付ファイルを指定フォルダに保存
            strFileName = ATTACH_PATH & objAttach.FileName
            objAttach.SaveAsFile (strFileName)
            ' 保存したファイルを印刷する
            Call ShellExecute(0, "print", strFileName, 0, ATTACH_PATH, 0)
        Next
    Else
    End If
   
End Sub

' ----- 以上、ソース -----



■ 億劫なあとがき


これで、部下から恐る恐る「承認まだでしょうか・・・?」などと急かされることはないはず!

もちろん、会社の規模にもよりますが、そもそもそこまで細分化された承認体制が必要か、というところから見直す必要はありますよね。


2014/01/24

Outlook 注文メール受信時に、担当者に自動転送したい



こんにちは!受信メールを関係者に転送しまくってるtknriaです!


OUTLOOKには「転送」ボタンがあるので、転送先を指定すればすぐ転送できるのですが、如何せん手間!

しかも転送してるメールも、転送先も、毎回同じやし!


ってことで、特定のメールを受信したときに、特定の人に毎回転送する作業を自動化しちゃいます。



■ 自動転送してみる


以下にVBAコード例を挙げます。


転送する際に、

・転送対象のメールの件名はorder_sub
・Toに入れる人の名前はname_JUCHU
・Toに入れる人のメールアドレスはaddress_JUCHU
・Ccに入れる人の名前はname_HASSOU
・Ccに入れる人のメールアドレスはaddress_HASSOU
・本文冒頭に入れる文章はfw_scrp

に従って、メールがつくられます。


今回は、「注文メール」という件名のメールを受信したときに、指定した2名に自動転送するという設定にしています。


' ----- 以下、ソース -----

Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
    Dim objItem As Variant
    Set objItem = Session.GetItemFromID(EntryIDCollection)
    If TypeName(objItem) = "MailItem" The
        ' 関係各位に自動転送
        Call ForwardOrderMail(objItem)
    End If

End Sub


Public Sub ForwardOrderMail(ByVal objMail As MailItem)
    Const name_JUCHU = "tknr1さん"  ' 受注管理者名
    Const address_JUCHU = "okku@hosomichi.com"   ' 受注管理者アドレス
    Const name_HASSOU = "tknr2さん" ' 発送担当者名
    Const address_HASSOU = "hosomichi@okku.com"  ' 発送担当者アドレス
    Const order_sub = "注文メール"  ' 注文メールかどうかを判別する件名
    Const fw_scrp = "自動転送しています。"  ' 転送メールの冒頭に追記する文
   
    If objMail.Subject = order_sub Then
        Dim fwMail As MailItem
        Set fwMail = objMail.Forward
       
        Dim Rec As Recipient
        Set Rec = fwMail.Recipients.Add(name_JUCHU & "<" & address_JUCHU & ">")
        Rec.Type = olTo
        Set Rec = fwMail.Recipients.Add(name_HASSOU & "<" & address_HASSOU & ">")
        Rec.Type = olCC
        Rec.Resolve
       
        fwMail.Body = fw_scrp & vbCrLf & vbCrLf & fwMail.Body
        fwMail.Send
    Else
    End If
End Sub

' ----- 以上、ソース -----



■ 億劫なあとがき


これで自動転送は完璧!

自分宛にテストしようとすると、自分宛に送信して自分で受信して自分宛に自動転送されて自分で受信する形になって、自分大好きなんですね!って言われちゃいます。

是非友達や同僚の方に頼んでみてください。


2014/01/21

Outlook 注文メール受信時に、注文管理表を自動更新したい



こんにちは!いつも何かしらの管理表を管理していて、管理しているのか管理されているのかがわからなくなっているtknriaです!


管理表の管理といっても、更新よろしくっていうメールを受けたときに、その内容を反映して更新保存するっていうだけですけどね。

でもこれが非常に面倒!

管理表に管理されてる!


ってことで、以前、メール受信時に自動処理するという記事を書きましたが、

それを応用して、注文メールを受信したときに、注文管理表を自動で更新してみます。



■ 管理表を自動更新!


注文管理表は、ここでは、csvファイルを想定しています。




1行目に「注文日,型番,数量,ユーザー」と入力して保存し、そのフルパスを変数orderに格納します。


また、処理開始のトリガとなるメールは、以下のフォーマットとしています。




こんな設定だと、コードはこんな感じでいけます。


'----- 以下、ソース -----

Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
    Dim objItem As Variant
    Set objItem = Session.GetItemFromID(EntryIDCollection)
    If TypeName(objItem) = "MailItem" Then
        ' 注文管理表を更新
        Call OrderEntry(objItem)
    End If
End Sub


Public Sub OrderEntry(ByVal objMail As MailItem)
    Const order = "C:\Users\○○"     ' 管理表のフルパス
    Const order_sub = "注文メール"      ' 注文メールかどうかを判別する件名
    Dim str_start As Integer
    Dim str_end As Integer
    Dim today As String
    Dim kataban As String
    Dim suuryou As Integer
    Dim user As String
    ' ----------------------------------
    ' 注文メールフォーマット
    ' ----------------------------------
    ' Subject   :注文メール
    ' Body      :型番:AA
    '               数量:12
    '               ユーザー:hoge
   
    If objMail.Subject = order_sub Then
        ' 必要な情報を抜き出す
        today = Format(Date, "yyyy/mm/dd")
       
        str_start = InStr(objMail.Body, "型番:") + Len("型番:")
        str_end = InStr(str_start, objMail.Body, vbCrLf)
        kataban = Trim(Mid(objMail.Body, str_start, str_end - str_start))
       
        str_start = InStr(objMail.Body, "数量:") + Len("数量:")
        str_end = InStr(str_start, objMail.Body, vbCrLf)
        suuryou = CInt(Trim(Mid(objMail.Body, str_start, str_end - str_start)))
       
        str_start = InStr(objMail.Body, "ユーザー:") + Len("ユーザー:")
        str_end = InStr(str_start, objMail.Body, vbCrLf)
        user = Trim(Mid(objMail.Body, str_start, str_end - str_start))
   
        ' orderファイルを開く
        Open order For Append As #1
        Write #1, today, kataban, suuryou, user
        Close #1
    Else
    End If
End Sub

'----- 以上、ソース -----



ちなみに、「注文メール」がフォーマット通りでない場合はエラーで止まってしまうので、そこのケアは必要です。



■ 億劫なあとがき


これで、メールをトリガにしたファイルの自動更新はおっけー!

単純に次々追加するわけではないのでちょっと複雑になりますが、スケジュール更新なんかもできるはずですね。

充実した自動更新ライフを☆


2014/01/20

【Outlook】メールを一括削除したい



こんにちは!メールが溜まりまくってるtknriaです!


仕事やプライベートに限らず、毎日膨大な量のメールを処理する時代になりましたが、どんどん溜まっていきますよね。

受信メールは全部見た上で、削除したり仕分けしたりしていますけど、送信済みボックスや削除済みボックスの中は溜まりまくり。


削除しようとしても、膨大すぎて選別するのが大変ですよね。


そこで、条件に合致する不要なメールを、一括で完全削除してしまう機能を実装します。


私は、メーラーはOutlook(読み:アウトルック)を愛用しているので、VBAを用いた方法をご紹介します。


メールを気持ちよく一括削除!


ここでは簡易的に、件名に「ウイルス」という文字が含まれていたら削除する、という条件にしています。


'----- 以下、ソース -----


Public Sub DeleteMails()
    ' 受信トレイ内のメールを削除
    Call DeleteItems(Session.GetDefaultFolder(olFolderInbox))
       
    ' 送信済みアイテム内のメールを削除
    Call DeleteItems(Session.GetDefaultFolder(olFolderSentMail))
       
    ' 削除済みアイテム内のメールを削除
    Call DeleteItems(Session.GetDefaultFolder(olFolderDeletedItems))
       
    MsgBox ("削除完了")
End Sub


Public Sub DeleteItems(objMailBox As Folder)
    Dim i As Integer
   
    For i = objMailBox.Items.Count To 1 Step -1
        With objMailBox.Items(i)
                If InStr(.Subject, "ウイルス") > 0 Then
                    .Delete      ' 問答無用で削除するので注意
                Else
                End If
        End With
    Next i
End Sub


'----- 以上、ソース -----



条件のところはカスタマイズしてください。

ソース中にも注意書きしていますが、本当に問答無用で削除されるので、デバッグのときには気をつけてください。


対象のフォルダも指定でき、
Call DeleteItems(Session.GetDefaultFolder(olFolderDeletedItems))
の、
olFolderDeletedItems
の部分をいろいろ変更することで、設定できます。

「受信トレイ」、「送信済みアイテム」、「削除済みアイテム」については上記ソースの通りです。



キレイにしていく順番が大事!


「削除済みアイテム」内の処理を最後にするのがポイントで、上記ソースでは、

・「受信トレイ」から「削除済みアイテム」に移動
  ↓
・「送信済みアイテム」から「削除済みアイテム」に移動
  ↓
・「削除済みアイテム」から完全削除

という処理になります。


ここで、「送信済みアイテム」と「削除済みアイテム」の順番を入れ替えると、

・「受信トレイ」から「削除済みアイテム」に移動
  ↓
・「削除済みアイテム」から完全削除
  ↓
・「送信済みアイテム」から「削除済みアイテム」に移動

という処理になり、「送信済みアイテム」内にあった不要アイテムが「削除済みアイテム」に残されたままになるので注意ですね。


掃除は上から!と同じですね。



億劫なあとがき


全てのメールチェックをするのは当然として、その仕分けも膨大な量になりますよね。

閲覧や分別はこまめにしたほうが良いですけど、削除はこの機能はまとめてすっきりしちゃいましょう!


Outlook 環境依存文字をチェックしたい



こんにちは!メールすると大体文字化けしているtknriaです!


文字化けの原因となっているのは「環境依存文字」「機種依存文字」で、

・(株)が一文字になったもの
・半角カタカナ
・キロ、kmなどの単位が一文字になったもの

などがあります。


メールが普及し始めた頃は、バイト数によって通信費も変わっていたので、こういった文字が重宝されました。

しかし、パケット定額が常識となった今では、ただ文字化けの原因でしかありません。


そこで、メールを作ったときに環境依存文字を使っていないかをチェックするマクロを実装しちゃいましょう!



■ 環境依存文字をチェック!


Outlookは、半角カタカナを自動で全角に変換してくれるので、半角カタカナはチェックする必要はありません。

今回は、それ以外の文字をチェックする機能を、VBAで実装します。


'----- 以下、ソース -----

Public Sub CheckNotJIS()
    Dim checkMail As MailItem
    Dim strBody As String
    Dim char As String
    Dim code_char As Integer
    Dim i As Integer
    Dim strNotJIS As String
    Dim strUnicode As String

    If TypeName(ActiveWindow) = "Inspector" Then
        Set checkMail = ActiveInspector.CurrentItem
    Else
        Set checkMail = ActiveExplorer.Selection(1)
    End If
   
    strBody = checkMail.Body
   
    For i = 1 To Len(strBody)
        char = Mid(strBody, i, 1)
        code_char = Asc(char)
        If code_char < 0 Then
            If code_char < &H8140 Or (code_char >= &H8740 And code_char < &H889F) Or code_char >= &HEB40 Then
                strNotJIS = strNotJIS & char
            ElseIf code_char >= &HA1 Then
                strNotJIS = strNotJIS & char
            ElseIf code_char = &H3F And char <> "?" Then
                strUnicode = strUnicode & char
            Else
            End If
        Else
        End If
    Next i
   
    If strNotJIS = "" And strUnicode = "" Then
    Else
        MsgBox ("以下の文字が含まれています。" & vbCrLf & _
                " 機種依存文字:" & strNotJIS & vbCrLf & _
                "  Unicode文字:" & strUnicode)
    End If
End Sub

'----- 以上、ソース -----


これをボタンに割り当てれば、送信前にチェックすることができます。


さらに、送信時に自動でチェックして、環境依存文字が含まれていれば送信を取り止めるようにするには、以下のように変更します。


'----- 以下、ソース -----

Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
    ' 機種依存文字をチェック
    Call CheckNotJIS(Item, Cancel)
End Sub


Public Sub CheckNotJIS(ByVal objItem As Object, boolCancel As Boolean)
    Dim strBody As String
    Dim char As String
    Dim code_char As Integer
    Dim i As Integer
    Dim strNotJIS As String
    Dim strUnicode As String
   
    strBody = objItem.Body
   
    For i = 1 To Len(strBody)
        char = Mid(strBody, i, 1)
        code_char = Asc(char)
        If code_char < 0 Then
            If code_char < &H8140 Or (code_char >= &H8740 And code_char < &H889F) Or code_char >= &HEB40 Then
                strNotJIS = strNotJIS & char
            ElseIf code_char >= &HA1 Then
                strNotJIS = strNotJIS & char
            ElseIf code_char = &H3F And char <> "?" Then
                strUnicode = strUnicode & char
            Else
            End If
        Else
        End If
    Next i
   
    If strNotJIS = "" And strUnicode = "" Then
    Else
        MsgBox ("以下の文字が含まれるため送信を中止します。" & vbCrLf & _
                " 機種依存文字:" & strNotJIS & vbCrLf & _
                "  Unicode文字:" & strUnicode)
        boolCancel = True
    End If
End Sub

'----- 以上、ソース -----


これでもう文字化けに悩まされて眠れない日々とはサヨナラですね!



■ 億劫なあとがき


署名に、環境依存文字verの「(株)」を使っている人には、修正を促したほうが良いです。

また、フリーのメーリングリストを多用する場合は、特に導入しておいたほうが良いですね。


2014/01/17

Outlook メール送信時に自動処理したい



こんにちは!自動化大好きtknriaです!



Outlook2010を使っていて、メール送信と同時に処理を行いたいことがあります。

例えば、条件を満たしていなければアラートを出したり、メール内容をtxtファイルにコピーして一括管理したかったり。
件名と宛先を表示して確認を促したりもしたいですね。

もちろん、仕分けルールでもできないことはないです!

でも、もっと細かく、もっと複雑な処理をしたかったりもするのが人情ってもんです。



■ メール送信時に自動処理!


VBAで実装します。


'-------ここからソース-------
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)

    ' ここに行いたい処理

End Sub
'-------ここまでソース-------


もともとApplicationとして用意してもらっているので簡単ですね。



■ 億劫なあとがき


とはいえ、仕分けルールを作成すれば済むレベルの処理であれば、そちらを使ったら良いと思います。

使い分け大事!


2014/01/16

VBE 背景色を変えたい



こんにちは!黒背景大好きなtknriaです!


Excel(読み:エクセル)やOutlook(読み:アウトルック)において、VBAを用いていろんな機能を実装することが多いのですが、
そのエディター「Visual Basic Editor(VBEと略します)」の背景は黒がベストだと思っています。

ということで設定変更しました。



VBEの背景を黒にする!


ExcelやOutlookを立ち上げた状態で「Alt + F11」
  ↓
VBEが立ち上がるので「ツール」→「オプション」
  ↓
「エディターの設定」タブ


ここで個別に設定します。


ちなみに、私の設定は、

・標準コード  前景:白   背景:黒  インジケーター:自動
・ コメント   前景:黄緑 背景:黒  インジケーター:自動
・キーワード  前景:水色 背景:黒  インジケーター:自動
・識別子    前景:白   背景:黒  インジケーター:自動

フォント:MSゴシック(日本語)
サイズ:10

です。



億劫なあとがき


個人的には、黒背景に黄緑コメントが見やすくて好きです。

好みはそれぞれあると思うので、VBEをあなた色に染めてあげましょう。


2014/01/08

Excelゲーム サイコロ野球



こんにちは!サイコロが好きすぎるtknriaです!


サイコロって美しい!特に、表裏面を足したら7になるあたりとか!


小さい頃からなぜかサイコロが好きで、一人遊びの時期にもよくサイコロを使っていました。

そのときに考案したゲームの一つに「サイコロ野球」というものがあり、ふとこれを思い出しました。



■ サイコロ野球とは!


遊び方は単純で、いくつかのルールに従ってサイコロを振りまくるだけ。


1.サイコロを1つ振る。・・・Aとする

2.Aが「1」「2」なら5.に進み、それ以外なら3.に進む。

3.もう1度サイコロを1つ降る。・・・Bとする

4. A-B-1≧1なら、その回の得点にA-B-1を足す。

5.もう1度サイコロを1つ降り、「1」「6」なら1.に戻る、それ以外なら攻守交代。


この作業を1回表から順に繰り返します。

この1.~4.の一連の作業で得られる最大得点はA=6、B=1のときの4点で、これが満塁ホームランにあたるので、すなわちB=1ならホームラン。

5.で「1」「6」が出続ければ、どこまでも1イニングの得点を増やせます。


小学生ながら、よく考えられていたと思っています。


これをいつまでもサイコロでやっていたら成長がないので、Excel VBAで実装します。



■ Excel VBAでサイコロ野球!





写真のようにsheetを設定し、command buttonを一つ用意します。

ここで大事なのは、

 ・A1~A3は初期設定で1,1,0としておくこと

 ・F2~Q3は初期設定で空白にしておくこと

 ・R2は「=SUM(F2:Q2)」

 ・R3は「=SUM(F3:Q3)」


このボタンに以下のマクロを割り当てます。


' -----以下、ソース-----

Sub play()
    Const OMOTE As Integer = 1
    Const URA As Integer = 2

    Dim inning As Integer
    Dim uraomote As Integer
    Dim gameset_flg As Integer
    inning = Cells(1, 1)
    uraomote = Cells(2, 1)
    gameset_flg = Cells(3, 1)

    Dim a As Integer
    Dim b As Integer
    Dim point As Integer
 
    If gameset_flg = 1 Then
        MsgBox ("ゲームセット!")
     
        '初期化
        gameset_flg = 0
        Range(Cells(2, 6), Cells(3, 17)).ClearContents
        Cells(1, 1) = 1
        Cells(2, 1) = 1
        Cells(3, 1) = 0
    Else

more:
        Randomize
     
        a = Int(6 * Rnd + 1)
'MsgBox (a)
        If a <= 2 Then
            GoTo nxt
        Else
            b = Int(6 * Rnd + 1)
'MsgBox (b)
            If a - b >= 1 Then
                point = point + (a - b - 1)
                If inning >= 9 And uraomote = URA Then
                    If Cells(2, 18) < Cells(3, 18) + point Then
                        Cells(uraomote + 1, inning + 5) = point
                        gameset_flg = 1
                        GoTo gameset
                    Else
                    End If
                Else
                End If
            Else
            End If
        End If
     
nxt:
        a = Int(6 * Rnd + 1)
'MsgBox (a)
        If a = 1 Or a = 6 Then
            GoTo more
        Else
            Cells(uraomote + 1, inning + 5) = point
            If uraomote = OMOTE Then
                Cells(2, 1) = URA
                If inning = 9 Then
                    If Cells(2, 18) < Cells(3, 18) Then
                        uraomote = URA
                        Cells(uraomote + 1, inning + 5) = "X"
                        gameset_flg = 1
                        GoTo gameset
                    Else
                    End If
                Else
                End If
            Else
                Cells(1, 1) = inning + 1
                Cells(2, 1) = OMOTE
                If inning >= 9 And inning <= 11 Then
                    If Cells(2, 18) <> Cells(3, 18) Then
                        gameset_flg = 1
                        GoTo gameset
                    Else
                    End If
                ElseIf inning = 12 Then
                        gameset_flg = 1
                        GoTo gameset
                Else
                End If
            End If
        End If
 
    End If
gameset:
    Cells(3, 1) = gameset_flg
 
End Sub

' -----以上、ソース-----


いや、成長ですね。



■ 億劫なあとがき


遊びまで効率化!

ただ、遊びを効率化しちゃうと、本当にただの作業になってしまうという現実も知りました。。


2013/12/25

Excel VBA CSVデータを処理したい



こんにちは!データ処理が大好きなtknriaです!

特に、実験データなどはCSVファイルにまとめられることが多く、それをExcelでスマートに処理できたりするとカッコいい!

なんか仕事デキる人みたい!


そんな、カッコよく仕事がデキるようになるマクロを紹介します。



■ Excel VBAでCSVデータを一括高速処理!


Excelシート上に、CommandButtonを一つ用意して、 次の関数を割り当てます。



' ----- 以下、ソース -----

Sub データ取り込み_Click()
    Dim OpenFileName As String
    Dim nowbook As Workbook
    Dim nowsheet As Worksheet
   
    Set nowbook = ThisWorkbook
    Set nowsheet = nowbook.ActiveSheet
   
    Dim adoSt As New ADODB.Stream
   
    ' ファイルオープンダイアログの初期ディレクトリを設定
    ChDrive "D"
    ChDir "D:\"
   
    ' csvファイルを開く
    OpenFileName = Application.GetOpenFilename("データ,*.csv")
    If OpenFileName = "False" Then
        MsgBox ("キャンセルされました")
        GoTo job_end
    Else
       
        ' 全てのデータを網羅
        Dim temp_data As String
        Dim str_data() As String
     
        With adoSt
            .Type = adTypeText
            .Charset = "UTF-8"
            .Open
            .LoadFromFile (OpenFileName)

        Do Until .EOS
            temp_data = .ReadText(adReadLine)
            str_data = Split(temp_data, ",")

            ' ---------------------
            ' ここに必要な処理を記述
            ' ---------------------

        Loop
       
        ' csvファイルを閉じる
            .Close
        End With
    End If
   
job_end:
    nowbook.Activate
    nowsheet.Activate
    MsgBox ("データ処理完了")
End Sub

' ----- 以上、ソース -----



関数の意味をググったりすれば、応用はできると思うので、細かい説明はしません。

大きくは、
・csvファイルを選択して読み込む
・データを処理する
・csvファイルを閉じる
ということをしています。


仕事でCSVファイルに触れる機会が多い人は、是非使ってみてください!



■ 億劫なあとがき


こういう処理こそ、Excel VBAの真骨頂ですよね!


2013/11/26

Outlook メール受信時に自動処理したい



こんにちは!自動処理大好きなtknriaです!

特に、メールを受信したときに決まった処理をしたいっていうことが多いです。


例えば、

・注文メールが届いたら、在庫管理担当者と発送担当者に転送する

・特定の取引先からのメールは全て、関係者各位に展開する

・スケジュール依頼メールが届いたら、スケジュール管理表を更新する

などですね。


これらをOutlook(読み:アウトルック)で実装するためには、まず受信したときにそれを検知する必要があります。

今回はそのためのVBAコードをご紹介します。



メール受信時に自動処理!


' ----- 以下、ソース -----

Public Sub ApplicationNewMail(ByVal EntryIDCollection As String)
    Dim objItem
    Set objItem = Session.GetItemFromID(EntryIDCollection)
    If TypeName(objItem) = "MailItem" Then
        ' ここに、メールを受信したときに行いたい処理を記載
       MsgBox (objItem.Subject)
    End If
End Sub

' ----- 以上、ソース -----



今回は、受信したメールの件名を表示させるだけの処理ですが、この部分に行いたい処理を記述すればOKです。



億劫なあとがき


今後、「メールを受信したときにこういう処理をする!」といったVBAコードもつくってみます。

乞うご期待!


2013/10/03

Outlook VBAマクロを導入したい



こんにちは!VBAと結婚したいtknriaです!

そんな愛すべきVBAは、Outlookでの仕事も効率化できちゃうので感動ものです!


あなたにも、この感動を。



■ OutlookにVBAマクロを導入したい!


お兄さんについてきてねっ!


手順1.自己署名入りデジタル証明書を作成する



  スタート→すべてのプログラム→Microsoft Office
        →Microsoft Officeツール→「VBAプロジェクトのデジタル証明書」をクリック



  「デジタル証明書の作成」の「証明書の名前」に自分の名前を入力し、OKをクリック


手順2.VBAコードを記述


  Outlookを起動している状態で、「Alt」+「F11」を同時押し

  VBEが立ち上がるので、情熱的にコードを打ち込んでください!!


手順3.マクロを実行(2種類ある)


  A.リボンの「マクロ」から実行


    「開発」タブの「マクロ」をクリックし、登録マクロ一覧から選択する


  B.ツールバーにボタンを追加して実行


    リボン(図の赤丸近辺)を右クリックし、「リボンのユーザー設定」をクリック



    「コマンドの選択」の下のドロップボタンから「マクロ」を選択し、登録するマクロを選択



    右側のリボンタブから、マクロを追加したいタブを選択し、「新しいグループ」を作成
     (ここでは、「ホーム」タブに追加します)



    必要に応じて「名前の変更」をクリックして、このグループの名前やアイコンを変更
     (ここでは、名前を「水樹奈々」に、アイコンを「マイク」に変更します)



    「追加>>」をクリックし、新しいグループの下にマクロが追加されたことを確認




    必要に応じて「名前の変更」をクリックして、このマクロの名前やアイコンを変更
     (ここでは、名前を「POP MASTER」に、アイコンを「マイク」に変更します)

    OKをクリック



    これで追加されました!



■ 億劫なあとがき


慣れないうちは面倒ですけど、一旦やり方を覚えちゃったら簡単です!

個人的にはボタンを登録してしまったほうが使いやすく感じます。


2013/10/02

Outlook VBAについて知りたい



こんにちは!VBAを愛してやまないtknriaです!

Microsoft Officeを使った事務作業を効率的に行うにはVBAが必須だと感じているくらい!


とはいえ、あまりプログラミングの経験がないのでGoogle先生に教わってます。

実際調べてみると、Excel VBAの解説サイトは数多くあるんですけど、Outlook VBAについて書かれているものはあまりないんですよね。



■ Outlook VBAの神!


そんな少数精鋭の中でお世話になりまくっているのがこのサイト!


【Outlook 研究所】 

Outlook VBAについての情報を扱っている数少ないサイト様で、ホントにすごいです!


Outlook VBAのことだけでなく、メモや予定表も含めて、Outlookに関するあらゆることを網羅しまくっています。

仕事の合間にボーッと記事をスクロールしているだけで仕事になっちゃってます。



■ 億劫なあとがき


マクロを作成していて思うんですけど、「やりたいことをどうすれば実現できるのかわからない」という以前に、
そもそも、「どこかに問題がないか?」「どうすれば効率的にできるか?」という視点を持っていることが大事なんですよね。

いわゆる、「問題解決力」よりも「問題発見力」「問題発掘力」というやつでしょうか!


例えば、Outlookを使い始めて、まず実装したのが「再送信」機能。

何段かの手順を踏めばできないこともないんですけど、毎回同じ動きしているしできればワンクリックでメール編集画面を開きたい・・・!って思っちゃったんです。


こういう小さな効率化を積み重ねて、もっと大事なことに時間を割きたいですよね!