SEのネタ帳

発見したことや気付いた内容を書き留めたり、作った便利ツールなどを置いておく場所。主に仕事関係のことを書きます。

【VBA】OutlookのVBA

OutlookのVBAマクロを使ってみた。

 

Outlookの仕訳ルールに、メール受信時に下記のプロシージャを実行するように設定しておくだけ。Mailオブジェクトの中身には本文も含まれてるので、何でもできる。(MSDNで調べれる)

Sub AddTicket(ByRef Mail As MailItem)
 Msgbox "件名" & Mail.Subject
 Msgbox "受信日時" & Mail.ReceivedTime
End Sub

 

これを使えば、特定の文字が記載されているメールを受信したら、特定の場所のファイルを開いて、メールの中身によって内容を書き込むとか、色々できる。

あとは、PC立ち上げっぱなしで帰宅して、家からメール送ったらソースマージしてコンパイラかけて単体テストまで完了させて・・・といった在宅ワークなプレイも可能。

【VB Script】SJIS形式のファイルをUTF-8形式に変換して保存する

文字コード変換について。

nkfコマンドが使えれば一番てっとり早いが、VB Scriptでの変換方法も見つけたのでメモ。

少々面倒だが、ある文字コード専用の"ADODB.Stream"を作って、これらの間で文字をやり取りすることで変換を行う。

なお、Shift_JISUTF-8に限らず、システム(筆者はWindowsXP)が扱える文字セットなら使用できる。

 

' SJISUTF-8用の"ADODB.Stream"オブジェクトを得る

Set objSJIS = CreateObject("ADODB.Stream")
Set objUTF8 = CreateObject("ADODB.Stream")

 

' SJIS形式のファイルを開く

objSJIS.Type = 2  ' adTypeText
objSJIS.Charset = "Shift_JIS"
objSJIS.Open
objSJIS.LoadFromFile "C:\Documents and Settings\h3537\My Documents\sjis.txt"

 

'UTF-8形式に変換して保存する

objUTF8.Type = 2  ' adTypeText
objUTF8.Charset = "UTF-8"
objUTF8.Open

objSJIS.CopyTo objUTF8  ' ここがポイント。文字を移しかえることで、文字コードの変換を行っている。
objUTF8.SaveTofile "C:\Documents and Settings\h3537\My Documents\utf8.txt"

 

objSJIS.Close
objUTF8.Close

 

上記では、LoadFromFile やSaveTofileを使ってファイル単位で変換しているが、

ReadTextやWriteTextを使って文字列単位での変換も出来る。

【VBA】Word、Excelの改行コードについて

VBAで文字列比較のコード書いてて、Wordの改行コードで少しハマった。

 if str = "なんちゃらかんちゃら" then

がヒットしない。ウォッチしてみても、strにはちゃんと正しい文字は入っている。

VBAは文字列比較が「=演算子」で出来るはず。

(ちなみにC言語では無理。まぁ無理で当たり前なのだけど、新人さんはその理由をちゃんと理解しとこう。)

 

とりあえず、文字列比較関数を使って比較してみることに。

 if Strcomp(str, "なんちゃらかんちゃら") = 0 then

ヒットしない。ファッキン。

「・・・なるほど。改行コードやな。そんな初歩のトラップにひっかかるかいな♪」

 

VBAのウォッチ式には改行が表示されなかったが、文字列の最後にはついてるはず。

てことで、Windowsの改行コードであるCRLFをくっつけて再度比較。

 if Strcomp(str, "なんちゃらかんちゃら" & vbCrLf) = 0 then

ヒットしない。・・・小僧!!

少しイラっとしたので、デバッグ形態に変身することに。

 

「とりあえず困ったらダンプすべし!」が僕のスタイルなので、strをダンプしてみることに。

 (前半部分は省略) 0x0D

え?最後CR(0x0D)だけ?LF(0x0A)いらんの?

どうやらWordの改行コードはCRのみらしい。

 

WindowsはCRLFなんだし、Microsoftさんの製品同士やのに統一してくれよ(-_-メ)

ちなみにExcelはLFのみである。。なんで全部バラバラなん!!

 

ということで改行コードについてまとめると以下の通り。

 ・Wordは「CR」

 ・Excelは「LF」

VBAで文字列を扱う場合は要注意。

 

PS.

Wordの文字列の最後に表示される改行アイコンが「直角に曲がった矢印」だったので、CRLFであることを疑わなかったというのもある。

というのも、Sakuraエディタで表示される改行アイコンは、種類によって見た目が異なる。これは何気に便利な機能なのである。

 CRLF : 直角に曲がった矢印

 CRのみ: ←

 LFのみ : ↓

どっかの団体がこの辺を規定してくれるとええなぁ。

【計算】7時間45分や8時間半を、7.75や8.5に変換する方法

今回はプログラミングとは関係ないが、知っておくと便利な内容をメモしておく。

 

勤怠の管理はExcelで行うことが多いと思うが、労働時間をどうやって計算するか?

例えば、以下の場合、労働時間は7時間45分となるが、

勤怠を計算する上では7.75とか8.50といった、15分刻みや30分刻みで扱うことが多い。

 9:00 ~ 17:30(休憩45分)

 

そこで、X時間XX分をX.XXという時間に変換する方法を以下に記載する。

 

まず、Excelは1日(24時間)を1.0として扱っている。

これは、24:00とセルに入力した後、セルの書式設定を標準にしてみると、1.0と表示されることからわかる。(12:00だと0.5と表示される)

 

ということは、以下の割合を使って変換後の時間を算出できる。

 1 : 24 = Excelで扱う時間 : 変換後の時間(X.XX)

 

試しに、7時間45分を変換してみる。

 1:24 = 0.322916667(7:45とセルに入力した値) : X

 X = 0.322916667 × 24

 X = 7.75

となり、正しく変換できている。

【VBA】Word文書中の単語一覧をExcelに出力する

Word文書内で使われている単語の一覧をExcelに出力するマクロ。

同じ意味でも表記が違うとかで混乱する時があるので、用語は管理しとくべき。

 

以下、Word文書内のVBAコード。

 

Sub 単語一覧取得()
    Set excel = CreateObject("Excel.Application")
    Set book = excel.workbooks.Add

    Dim i As Long
    i = 1
    Dim tmp As Variant

 

    With excel.workbooks(book.Name).worksheets(1)

        ' Word文書内の全ての単語をtmpに格納する

        tmp = .Range(.Cells(1, 1), .Cells(ActiveDocument.Words.Count, 1))

        For Each w In ActiveDocument.Words
            tmp(i, 1) = w.Text
            i = i + 1
        Next

 

        ' tmpの中身をExcelに出力する。

        ' 1単語ずつExcelに出力するよりも、このように変数に格納しおいて最後にドンと書き出す方が断然高速である。

        Range(.Cells(1, 1), .Cells(ActiveDocument.Words.Count, 1)) = tmp
   

         ' 出力した単語をソートする。
        .Range(.Cells(1, 1), .Cells(ActiveDocument.Words.Count, 1)).Sort Key1:=.Range("A1"), _
            Order1:=1, Header:=0, _
            OrderCustom:=1, MatchCase:=False, Orientation:=1, SortMethod:=1, DataOption1:=0

 

        ' 出力した単語の重複を省く。
        .Range(.Cells(1, 1), .Cells(ActiveDocument.Words.Count, 1)).AdvancedFilter Action:=1, Unique:=True
   
    End With
   

    ' 単語を出力したExcelを保存する。
    excel.workbooks(book.Name).SaveAs "C:\WordList.xls"
    book.Close
    excel.Quit
End Sub

【バッチファイル】カレントフォルダのファイルパス一覧を取得する

あるフォルダの中のファイル一覧を取得する時に便利。

いちいちファイル名をコピペするのはめんどくさいので。

 

以下のコマンドをコマンドプロンプト上で実行する。

 dir /b > ファイルパス一覧.txt

これをバッチファイルとかにしておけば、ファイルクリックするだけで一覧が出力されるので便利。ただし、ネットワーク上のフォルダには対応してないので注意。

 

こういう地味な作業が積もり積もると結構な工数になってたりする。

しかも日報とか週報には表れない数字なので、タチが悪い。

業務効率化を唱えるなら、まずはこういう単純作業から効率化してくべき。

【VBA】Word文書中に埋め込んだOLEオブジェクト内のVBAを呼び出す方法

あまり使う場面は無いが、例えばWord文書内にExcelの表やVisioで描いた図などがOLE形式で貼り付けてあると、Ctrl+Fの検索ではそれらの中身までは検索されない。

 

それらの中身を検索するには、表や図をダブルクリックして編集状態にしてから検索する必要がある。

それは面倒なので、Word文書のVBAからOLEオブジェクトのVBAを呼び出し、OLEオブジェクト内を検索するコードを考えた。

 

以下、Word文書のVBAのコード。

 

' 検索対象のOLEオブジェクトをアクティブにする。

' ※これが重要。これをしないとオブジェクトが参照できずに実行時エラーとなる。

ActiveDocument.InlineShapes(1).Activate

 

' OLEオブジェクトのメソッドを呼び出す。

' この例ではExcelのオブジェクトを対象としている為、Excelのメソッドを呼び出しているが、ClassTypeによって呼ぶメソッドは異なるかもしれないので適宜書き換えること。

Set ret = ActiveDocument.InlineShapes(1).OLEFormat.Object.worksheets(1).Cells.Find("めろん")
    If ret Is Nothing Then
        MsgBox "見つからない"
    Else
        MsgBox ret.Value & " は " & ret.Column & " 列目の " & ret.Row & " 行目に見つかった。"
    End If

 

上記の場合だとActiveDocument.InlineShapes(1).OLEFormat.Object がWorkbookオブジェクトのことだと理解してしまえば、あとはExcelのVBAを記述するだけである。