VBAの勉強を始めてみた

タイトルの通りVBAの勉強を始めました。効率化と暇つぶしを兼ねています。ブログの書き方なんて知りません分かりません。

色んなプログラミング言語をやりたい・・・・・・やりたいよぅ(雑記-3)

こんにちは、永遠の黒歴史 好天です。今回は雑記です。

 

JavaScriptやりたい、C#もやりたい・・・
VBAだけではなく色んな言語をやってみたいのが本音です。・・・が、そこそこの年齢になってくると、悲しいかな何かを始める前に費用(時間)対効果があるのかないのか考えてしまいます。
具体的にはどういうことかというと、今やっている仕事はExcelをそこそこ使うのでルーチンワークVBAで自動化することに時間対効果があります。しかしJavaScriptC#を活用する場面はあまりありません。ソフトを自作するという手もありますが、まぁ正直、既存のフリーソフトなんかをダウンロードしたほうがよっぽど高性能で効率的です。社内システムに関しては、別途、専門の部署がありますし!それだったら、もっと別の勉強(プログラミング以外)でもしよーっと。

 

☆若いうちに色んなことをマスターしとけ。ただし・・・・・・
プログラミングに限ったことではありませんが、若いうちは時間がたっぷりあるので、色んなことを納得いくまでやっておくといいと思います。ただし、「時間をたっぷり使って納得いくまでやる」という体質は、ある時期から少しずつ変えていったほうがいいでしょう。(ある時期・・・は自分で見極める必要がありますが・・・)
年齢とともに責任のある仕事を任されるようになり、状況の変化に応じて臨機応変に対応することが求められるようになります。そこまでやってきたことを破棄して、方向転換を余儀なくされることもしばしば・・・。
そんな時に、時間をたっぷり使って納得のいくまで物事をやり遂げ、やり遂げなければ次のステップに行けない・・・という習慣が体に染み付いていると状況の変化に対応できません。習慣というのはそう簡単に矯正できるものではありません_| ̄|○

 

☆寿命が150年くらいあるならやってもいい
寿命が150年くらいあって「老人」と言われはじめるのが120歳くらいからなら、あらゆるプログラミング言語を納得いくまでやってみたい!(笑)でも、標準的に150年の寿命であるなら、たぶん、「まだ先は長いから、もうちょっとあとでやろう(´_ゝ`)」と言うのは目に見えている・・・。

 

☆まとめ
人生は長いようで短い。費用(時間)対効果を考えるクセを身につけるのは大事です。
かける費用(時間)よりも効果が下回るのであれば、やめるべきです。

 

ではまた。

EXCEL表をTableタグ(HTML)に変換する 其の弐

前回、エクセルの表をHTML(Tableダグ)に変換するという勉強をしましたが、あとから文字の水平位置くらいは指定できたほうがいいんじゃね?と思ったので、今回は前回のコードを改良し、見出し以外の文字の水平位置を指定できるようにしました。

 

前回の記事はこちら

kouten0430.hatenablog.com

 

プラスαで、当ブログを読んでくれる人の中には、エクセルを便利に使いたいけれどもプログラミングには興味が無く「参照設定ってなに?おいしいの?(゜ρ゜) 」という人も少なからずおられると思うので・・・事前に参照設定を行わなくてもマクロを使えるようにしました。(これについては後日、別途記載したいと思います)
となれば過去に掲載した参照設定ありきのマクロを全部修正したくなりましたが、やはり事前に参照設定を済ませておくほうが処理速度としては速いので当面そのままにします。(面倒くさいとも言い換えることができる)

今回のマクロ(末尾に掲載)を使って出力したHTMLコードを、はてなブログであれば「HTML編集モード」でお好きな位置にペーストして下さい。f:id:kouten0430:20171014135517j:plain

 

表の大きさや、文字の大きさ・色・太さなどは「見たまま編集モード」で変更できるので、マクロの処理対象外とします。

 

見出しなし左寄せの場合(初期値)

Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test

 

見出しなし中央揃えの場合

Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test

 

見出しなし右寄せの場合

Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test
Test Test Test Test Test

 

----------------------

Sub 選択範囲をTableタグに変換しクリップボードに出力其の弐()
    '正方形または長方形のような連続した選択範囲とする
    Dim i As Long
    Dim j As Long
    Dim V As String
    Dim rh As Integer
    Dim ch As Integer
    Dim mi As Integer
    Dim Alg As String
    Dim myLib As Object
    Set myLib = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")  '参照設定なしでDataObjectのインスタンスを生成する
   
    rh = MsgBox("選択範囲の上端の行を" & vbCrLf & "見出しにしますか?", vbYesNo)
    ch = MsgBox("選択範囲の左端の列を" & vbCrLf & "見出しにしますか?", vbYesNo)
    mi = Application.InputBox(Prompt:="見出し以外の文字の水平位置を指定できます。" & vbCrLf & _
    "1:中央揃え" & vbCrLf & "2:右寄せ" & vbCrLf & "3:両端揃え" & vbCrLf & "キャンセル:左寄せ(初期値)", Type:=1)
        If TypeName(mi) = "Boolean" Then
            Alg = ""
        ElseIf mi = 1 Then
            Alg = " align=""center"""
        ElseIf mi = 2 Then
            Alg = " align=""right"""
        ElseIf mi = 3 Then
            Alg = " align=""justify"""
        End If
   
    V = "<table>" & vbCrLf

    For i = Selection.Row To Selection.Rows(Selection.Rows.Count).Row
        For j = Selection.Column To Selection.Columns(Selection.Columns.Count).Column
            If i = Selection.Row And rh = 6 Then '見出し行の処理。データを<th></th>で囲む
                If j = Selection.Column Then    '選択範囲の左端であれば冒頭に<tr>を追加
                    V = V & "<tr>" & vbCrLf & "<th>" & Cells(i, j).Value & "</th>"
                ElseIf j = Selection.Columns(Selection.Columns.Count).Column Then   '選択範囲の右端であれば末尾に</tr>を追加
                    V = V & "<th>" & Cells(i, j).Value & "</th>" & vbCrLf & "</tr>" & vbCrLf
                Else    '左端と右端以外の処理
                    V = V & "<th>" & Cells(i, j).Value & "</th>"
                End If
            Else '見出し行以外の処理
                If j = Selection.Column Then    '選択範囲の左端であれば冒頭に<tr>を追加
                    If ch = 6 Then  '見出し列の処理。データを<th></th>で囲む
                        V = V & "<tr>" & vbCrLf & "<th>" & Cells(i, j).Value & "</th>"
                    Else    '見出し列以外の処理。データを<td></td>で囲む
                        V = V & "<tr>" & vbCrLf & "<td" & Alg & ">" & Cells(i, j).Value & "</td>"
                    End If
                ElseIf j = Selection.Columns(Selection.Columns.Count).Column Then   '選択範囲の右端であれば末尾に</tr>を追加
                    V = V & "<td" & Alg & ">" & Cells(i, j).Value & "</td>" & vbCrLf & "</tr>" & vbCrLf
                Else    '左端と右端以外の処理
                    V = V & "<td" & Alg & ">" & Cells(i, j).Value & "</td>"
                End If
            End If
        Next j
    Next i
   
    V = V & "</table>"
   
    myLib.SetText V  '変数の値をDataObjectに格納する
    myLib.PutInClipboard 'DataObjectのデータをクリップボードに格納する
   
    MsgBox "HTMLをクリップボードに" & vbCrLf & "出力しました!" & vbCrLf & vbCrLf & _
    "ブログなどでお好みの位置にペースト" & vbCrLf & "して下さい。"
   
End Sub

----------------------
※SubからEnd Subまでをコピーし、標準モジュール等に貼り付けて使用して下さい。なお、マクロで実行した処理は「元に戻す」ことができません。実行前に一旦保存しやり直しのできる状態にしておいて下さい。標準モジュールにコードを貼り付けてマクロを使用する方法はこちら

Round関数の戻り値が違う?(ワークシート関数とVBA関数の違い)

Round関数が返す値はVBA関数とワークシート関数(俗に言うEXCEL関数)で違います。EXCELでのRound関数はご存知のとおり、引数で指定した桁数で四捨五入を行うものですが、VBAでは偶数丸め(ISO丸め、銀行丸めなどとも呼ばれる)という処理を行います。

具体的にはどういうことかというと、例えば「2.5」という数値を小数第1位以下で四捨五入すると「3」になります。これが、EXCELでのRound関数です。
しかしVBAで同じ処理をRound関数を使って行うと「2.5」は「2」になります。「1.5」は「2」になります。これは端数がちょうど0.5の場合に、繰り上げて偶数となる場合は繰り上げ、繰り上げて奇数となる場合は繰り上げしない(切り捨て)といった処理をしているからです。
0.1~0.4は切り捨て、0.6~0.9は切り上げることに関してはEXCEL関数と変わりません。イメージを掴みやすいように、下の表をご覧下さい。

 

Round関数の戻り値の違い

元の値 EXCEL VBA
0.1 0 0
0.2 0 0
0.3 0 0
0.4 0 0
0.5 1 0
0.6 1 1
0.7 1 1
0.8 1 1
0.9 1 1
1 1 1
1.1 1 1
1.2 1 1
1.3 1 1
1.4 1 1
1.5 2 2
1.6 2 2
1.7 2 2
1.8 2 2
1.9 2 2
2 2 2
2.1 2 2
2.2 2 2
2.3 2 2
2.4 2 2
2.5 3 2
2.6 3 3
2.7 3 3
2.8 3 3
2.9 3 3


ではなぜ、EXCELVBAでRound関数の仕様が違うのか?・・・は、実は分かりません(知りません)。が、偶数丸めにすると何か違いがあるのでしょうか・・・少し紐解いてみたいと思います。

まず、通常の四捨五入では端数0.5の繰り上がりによって、繰り上がり側に偏りが発生します。なので、データが多いほど繰り上がりによるプラス誤差が増えていきます。

偶数丸めは「銀行丸め」とも言われるくらいですから、誤差を小さく抑えることを目的としています。・・・どういうことかというと奇数と偶数で0.5の繰り上がりを相殺しているので、データが多くなっても誤差を小さく抑えることができるのです。

 

試しに、1.0~9.9の乱数を5,000個用意して、それぞれEXCELVBAのRound関数で処理したものを合計して、その誤差を見てみます。

f:id:kouten0430:20171007171955j:plain

 

次に乱数を10,000個まで増やして同じことをやってみます。四捨五入に関しては着実に誤差が増えていくのに対し、偶数丸めのほうは誤差が小さくおさまっています。

f:id:kouten0430:20171007172031j:plain

 

注意したいのは、Round関数で違いが生じるのは端数がちょうど「5」になる場合だけです。例えば「2.50000000000001」のような数値を小数第1位以下で四捨五入または偶数丸めを行っても結果は「3」になります。

1.00000000000000~9.99999999999999の乱数を5,000個用意して、小数第1位以下をRound関数で処理した結果の違いを見てみます。

f:id:kouten0430:20171007172149j:plain

合計はEXCELVBAで同じになります。なぜなら、5,000個程度の乱数では「2.50000000000000」のような偶数丸めの対象になるデータが皆無だからです。

 

でわまた('ω')ノ

エクセルでどんなことがしたい?(雑記-2)

エクセル素人研究室室長の好天です。('ω')ノ今回はちょっとした雑談です。

 

・エクセルでやりたいことは千差万別
エクセルで何をどうしたいかは、人によって、さらに状況によって千差万別だと思うので、当ブログに記載しているようなガベージなマクロは使う場面がなければ無用の長物です。
そういう場面に出くわした時に、思い出していただくか、グーグルなどから飛んで来ていただければ、室長はよろこびます。

 

プログラマーでなくとも最低限の知識はもつべき
小学校でもプログラミングが必修科目となるようですが、VBAなどは比較的難易度が低く(たぶん)、プログラムをちょっと覚えてみようかなぁと思っている人にはうってつけのような気がします。
エクセルでやりたいことに合わせて、サーチエンジンなどの検索から、適当なマクロを拾ってくるのもひとつの手ですが、一番確実なのは自分のやりたいことに合わせて、その都度自分でコーディング(もしくはカスタマイズ)するのがてっとり早いと思います。とはいえ、効率化がマクロの主目的なのに、その都度目的に合わせてコーディングすることに時間がかかるようではナンセンスな気もします。

 

・汎用的なマクロを目指す
そういう意味で、多目的に使える汎用的なマクロに仕上げていくことに時間をかけることには意味があるのかなぁ・・・と思ったりします。
あとは、どこまでを趣味と割り切れるかのセンスも重要かな・・・と最近思うのです。あくまでアマチュアの場合の話です。


でわまた('ω')ノ

同じ文字を下方向へnセル分貼り付ける

例えばこんな文字がクリップボードにあります。

f:id:kouten0430:20170927223308j:plain

 

これをアクティブセルから下方向にnセル分貼り付けるマクロを作ってみました。

アクティブセルから下方向に123セル分貼り付けてみます。マクロを実行したあとに表示されるInputBoxに「123」を入力しOK。

 

このようにアクティブセルがA1ならA123までクリップボードの文字が貼り付けられました。

f:id:kouten0430:20170927223357j:plain

 

結合セルにも貼り付けできます。(結合セルを1セルとみなす)

f:id:kouten0430:20170927223450j:plain

 

非表示セルは飛ばして貼り付けします。(可視セルのみ貼り付ける)

f:id:kouten0430:20170927223548j:plain

 

コードを少し変えれば右方向、左方向、上方向になりますが、今のところ使う場面がないのでやめときます。

 

----------------------

Sub 同じ文字を下方向へnセル分貼り付ける()
    'Microsoft Forms 2.0 Object Libraryを参照設定して下さい
    'クリップボードのデータを丸ごと1セルに貼り付ける処理をn回繰り返します
    '結合セルは1セルとしてカウントします
    '非表示セルは1セルとしてカウントしません(つまり可視セルのみに貼り付け)

    Dim Dobj As DataObject
    Dim V As Variant
    Dim i As Integer
    Dim Y As Integer
    Dim X As Integer
    Dim YE As Variant
   
    YE = Application.InputBox(Prompt:="下方向へ何セル分貼り付けますか?", Type:=1)
        If TypeName(YE) = "Boolean" Then
            Exit Sub
        End If
   
    Set Dobj = New DataObject
    With Dobj
        .GetFromClipboard
        On Error Resume Next
        V = .GetText
        On Error GoTo 0
    End With
   
    If Not IsEmpty(V) Then
        i = 1
        Y = ActiveCell.Row
        X = ActiveCell.Column

        Do While i <= YE
            If Cells(Y, X).Address = Cells(Y, X).MergeArea(1).Address _
            And Rows(Y).Hidden = False Then
                Cells(Y, X).Value = V
                Y = Y + 1
                i = i + 1
            Else
                Y = Y + 1
            End If
        Loop
    Else
        MsgBox "クリップボードにデータがありません!"
    End If

End Sub

----------------------
※SubからEnd Subまでをコピーし、標準モジュール等に貼り付けて使用して下さい。なお、マクロで実行した処理は「元に戻す」ことができません。実行前に一旦保存しやり直しのできる状態にしておいて下さい。標準モジュールにコードを貼り付けてマクロを使用する方法はこちら

※上記のマクロは外部ライブラリを使用します。VBEでMicrosoft Forms 2.0 Object Libraryを参照設定して下さい(ツール→参照設定→参照からWindows\System32\FM20.DLLを選択)。参照設定の方法はこちら

EXCEL表をTableタグ(HTML)に変換する

HTMLで表(Tableタグ)を記述するのは、結構骨の折れる作業です。はてなブログでは視覚的に作表する機能がありませんので、地道にHTMLで記述する(または、はてな記法で記述する)しかありません。
そもそもHTMLエディターにしたって、表作成には特化していないのですから、結構面倒だと思います。(各種計算やオートフィル等の機能がないため)
なので、HTML作成において表(Table)作成の部分だけでもEXCELでやってしまおうというのが今回の記事の趣旨です。

 

まず、下記のマクロをコピペして標準モジュール等に貼り付けして下さい。あと、クリップボードとデータのやり取りを行うのでVBEでMicrosoft Forms 2.0 Object Libraryを参照設定しておいて下さい。(詳細なやり方は記事末尾のリンクからどうぞ)

----------------------

Sub 選択範囲をTableタグに変換しクリップボードに出力()
    'Microsoft Forms 2.0 Object Libraryを参照設定して下さい
    '正方形または長方形のような連続した選択範囲とする
    Dim i As Long
    Dim j As Long
    Dim V As String
    Dim rh As Integer
    Dim ch As Integer
    Dim myLib As New DataObject
   
    rh = MsgBox("選択範囲の上端の行を" & vbCrLf & "見出しにしますか?", vbYesNo)
    ch = MsgBox("選択範囲の左端の列を" & vbCrLf & "見出しにしますか?", vbYesNo)
   
    V = "<table>" & vbCrLf

    For i = Selection.Row To Selection.Rows(Selection.Rows.Count).Row
        For j = Selection.Column To Selection.Columns(Selection.Columns.Count).Column
            If i = Selection.Row And rh = 6 Then '見出し行の処理。データを<th></th>で囲む
                If j = Selection.Column Then    '選択範囲の左端であれば冒頭に<tr>を追加
                    V = V & "<tr>" & vbCrLf & "<th>" & Cells(i, j).Value & "</th>"
                ElseIf j = Selection.Columns(Selection.Columns.Count).Column Then   '選択範囲の右端であれば末尾に</tr>を追加
                    V = V & "<th>" & Cells(i, j).Value & "</th>" & vbCrLf & "</tr>" & vbCrLf
                Else    '左端と右端以外の処理
                    V = V & "<th>" & Cells(i, j).Value & "</th>"
                End If
            Else '見出し行以外の処理。データを<td></td>で囲む
                If j = Selection.Column Then    '選択範囲の左端であれば冒頭に<tr>を追加
                    If ch = 6 Then  '見出し列の処理。データを<th></th>で囲む
                        V = V & "<tr>" & vbCrLf & "<th>" & Cells(i, j).Value & "</th>"
                    Else    '見出し列以外の処理。データを<td></td>で囲む
                        V = V & "<tr>" & vbCrLf & "<td>" & Cells(i, j).Value & "</td>"
                    End If
                ElseIf j = Selection.Columns(Selection.Columns.Count).Column Then   '選択範囲の右端であれば末尾に</tr>を追加
                    V = V & "<td>" & Cells(i, j).Value & "</td>" & vbCrLf & "</tr>" & vbCrLf
                Else    '左端と右端以外の処理
                    V = V & "<td>" & Cells(i, j).Value & "</td>"
                End If
            End If
        Next j
    Next i
   
    V = V & "</table>"
   
    myLib.SetText V  '変数の値をDataObjectに格納する
    myLib.PutInClipboard 'DataObjectのデータをクリップボードに格納する
   
    MsgBox "Tableタグ(HTML)をクリップボードに" & vbCrLf & "出力しました!" & vbCrLf & vbCrLf & _
    "ブログなどでお好みの位置にペースト" & vbCrLf & "して下さい。"
   
End Sub

----------------------

 

マクロを使用する準備が終わったら、Tableタグに変換したい表を選択してマクロを実行します。

f:id:kouten0430:20170923171849j:plain

 

こんな感じでクリップボードにHTMLが出力されるので、試しにはてなブログに貼り付けてみましょう。

f:id:kouten0430:20170923171922j:plain

 

「例えばここにTableを貼り付ける↓」という文字の下に、Tableタグを貼り付けてみます。HTML編集モードに切り替えて、マクロから出力したTableタグをペーストします。

f:id:kouten0430:20170923172156j:plain

f:id:kouten0430:20170923172305j:plain

 

見たまま編集モードに戻すと、このように表が挿入されていることが確認できます。

f:id:kouten0430:20170923172359j:plain

 

見たまま編集モードでは表の大きさを変更(表の四隅をドラッグ)したり、文字色・文字の大きさ等を変更できます。

f:id:kouten0430:20170923172436j:plain

f:id:kouten0430:20170923172516j:plain

 

表の中に画像を挿入することもできます。

f:id:kouten0430:20170923172847j:plain

f:id:kouten0430:20170923172847j:plain

 f:id:kouten0430:20170923172847j:plain

f:id:kouten0430:20170923172847j:plain

f:id:kouten0430:20170923172847j:plain

 f:id:kouten0430:20170923172847j:plain
 f:id:kouten0430:20170923172847j:plain

f:id:kouten0430:20170923172847j:plain

f:id:kouten0430:20170923172847j:plain

 

ちなみにマクロから出力したTableには罫線などの装飾が入っていませんが、ブログ側のスタイルの定義によって罫線等が自動的に入ります。

マクロから出力したTableタグをメモ帳などに貼り付け、拡張子を.htmlで保存したものをブラウザで開くと、プレーンなTableが表示されるのみです。(言い換えればプレーンなTableを提供するマクロだと思って下さいませ)

f:id:kouten0430:20170923173546j:plain

最小限の機能として、見出しの有無のみを選択できるようにはしました。

 

上端の行と左端の列を見出しにした場合はこんな感じ

Test Test Test Test
Test Test Test Test
Test Test Test Test
Test Test Test Test

 

上端の行のみ見出しにした場合はこんな感じ

Test Test Test Test
Test Test Test Test
Test Test Test Test
Test Test Test Test

 

左端の列のみ見出しにした場合はこんな感じ

Test Test Test Test
Test Test Test Test
Test Test Test Test
Test Test Test Test

 

 マクロの標準モジュールへの貼り付け方法はこちら

kouten0430.hatenablog.com

 

参照設定の方法はこちら 

kouten0430.hatenablog.com

CSV形式でクリップボードにコピーする

今回は、選択した範囲のデータをCSV形式にしてクリップボードへコピーするマクロを作ってみました。
こんな感じです。

CSV形式でコピーしたい範囲を選択し、マクロを実行します。

f:id:kouten0430:20170914221826j:plain


こんな感じでCSV形式でコピーされます。

f:id:kouten0430:20170914222050j:plain


メモ帳などに貼り付けて、拡張子を.csvとして保存すればCSVファイルとして保存することもできます。

 

しかし・・・・・・、それだけでは面白みがないので結合セルのデータに対しても同様にCSV形式でコピーできるようにしてみました。

f:id:kouten0430:20170914222419j:plain

f:id:kouten0430:20170914224601j:plain

このように余分な空白、改行の無い状態でクリップボードへコピーできます。

 

単一セルと結合セルが混在した範囲ではデータがいびつになるので、単一セルのみ、または結合セルのみの範囲で使用していただければ幸いです。

 

***************************************

Sub CSV形式でクリップボードに格納()
    'Microsoft Forms 2.0 Object Libraryを参照設定して下さい
    '正方形または長方形のような連続した選択範囲とする
    '結合セルも単一セル同様のCSV形式にします(ただし、結合セルと単一セルを混在すると歪になります)
    Dim i As Long
    Dim j As Long

    For i = Selection.Row To Selection.Rows(Selection.Rows.Count).Row
        For j = Selection.Column To Selection.Columns(Selection.Columns.Count).Column
            If Cells(i, j).Address = Cells(i, j).MergeArea(1).Address And _
            Rows(i).Hidden = False And Columns(j).Hidden = False Then '結合セルの場合は左上の値のみ取り出す。非表示セルは処理しない
                If Cells(i, j).MergeArea(1).Address = Cells(i, Selection. _
                Columns(Selection.Columns.Count).Column).MergeArea(1).Address Then
                '選択範囲の最終列(最終列を含む結合セル)であれば末尾に改行を追加
                    V = V & Replace(Cells(i, j).Value, vbLf, "") & vbCrLf
                Else
                '選択範囲の最終列(最終列を含む結合セル)以外は末尾にカンマを追加
                    V = V & Replace(Cells(i, j).Value, vbLf, "") & ","
                End If
            End If
        Next j
    Next i
   
    V = Left(V, Len(V) - 2) '最終行の改行区切りを取り除く(CrLfは2文字)
   
    With New MSForms.DataObject
        .SetText V  '変数の値をDataObjectに格納する
        .PutInClipboard 'DataObjectのデータをクリップボードに格納する
    End With
   
End Sub

***************************************
※SubからEnd Subまでをコピーし、標準モジュール等に貼り付けて使用して下さい。なお、マクロで実行した処理は「元に戻す」ことができません。実行前に一旦保存しやり直しのできる状態にしておいて下さい。標準モジュールにコードを貼り付けてマクロを使用する方法はこちら

※上記のマクロは外部ライブラリを使用します。VBEでMicrosoft Forms 2.0 Object Libraryを参照設定して下さい(ツール→参照設定→参照からWindows\System32\FM20.DLLを選択)。参照設定の方法はこちら