この記事では、私がこれまでVBAを使用してきた中で「これは使える」と思ったコードを抜粋したものです
目次
フォルダ選択
ファイルを保存するための保管フォルダを指定するダイアログボックスを表示します
Application.FileDialog プロパティを使用します
以下が一連のコードです
Sub folderSelect()
Dim str保存フォルダ名 As String
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = 0 Then
MsgBox “フォルダ選択してください”
Exit Sub
Else
str保存フォルダ名 = .SelectedItems(1)
End If
End With
MsgBox str保存フォルダ名
End Sub
「.show=0」でフォルダが選択されていない場合は別途メッセージを表示します
ファイル保存
エクセルシートのCSV出力
出力したいシートをコピーして、新しいファイルを作成し、ファイル名を指定して保存します
ThisWorkbook.Worksheets(“出力”).Copy
ActiveWorkbook.SaveAs “D:\TEST.csv”, FileFormat:=xlCSV
ActiveWorkbook.Close
文字列操作
分割
文字列の分割にはSplitを使用します
Variant型で設定した変数をSplitで分割し、変数(0)、変数(1)、変数(2)で受け取ります
例えば、シートのB1セルに「600-1」の文字列があるとします
こちらの文字列を「-」で分割し、それぞれをメッセージで表示するとします
その場合は、次のコードで実現できます
Dim mySTRING As Variant
Dim myWORD As Variant
Dim myYEAR As String
Dim myMONTH As String
mySTRING = Worksheets(“Sheet1”).Range(“B2”).Value
myWORD = Split(mySTRING, “-“)
myYEAR = myWORD(0)
MsgBox myYEAR
myMONTH = myWORD(1)
MsgBox myMONTH
まず、myWORD(0)で600を取りだします
次にmyWORD(1)で1を取り出します
固定文字が含まれているかを判断する
Instr関数を使用し、0以上なら含まれていると判断します
Dim myCountWaritsuke As Long ‘固定の文字が含まれいる位置
myCountWaritsuke = InStr(“myTEST1”, “TEST”)
MsgBox myCountWaritsuke
上のコードの場合は、myTESTの文字列の3文字目にTESTの文字列が含まれているので3とメッセ―ジが出力されます
文字列への変換
数値の文字列への変換にはStr関数を使用します
Str関数を交えた下のコードを実行してみます
Dim myVal As Long
myVal = 1
Worksheets(“Sheet1”).Range(“B2”).Value = “A-” & Str(myVal)
するとB2セルに以下のような文字列が入力されます
ここで1点問題があります
半角の空白がStr関数で変換した文字列に入ってしまっています
こちらが気になる場合はCstr関数を使用します
Worksheets(“Sheet1”).Range(“B2”).Value = “A-” & CStr(myVal)
これで空白は入らないようになります
数値への変換
こちらはVal関数を使用します
Dim myVal As String
myVal = “1”
Worksheets(“Sheet1”).Range(“B2”).Value = Val(myVal) + 1
上のコードを実行すると「2」がB2セルに入力されます
数値かどうかの判定
対象の’文字’が数値かどうかの判定は「IsNumeric」を使用します
試しに次のコードを実行してみます
MsgBox IsNumeric(123)
そうすると次の画像のようにTRUEが出力されます
次に以下のコードを実行してみます
MsgBox IsNumeric(“TEST”)
この場合はFALSEが出力されます
注意して頂きたいのは、次の場合はTRUEが出力されます
MsgBox IsNumeric(“123”)
これはあくまで123が数値文字だからです
メール関連
表をメールの本文に入れる
シート内の表の内容をHTMにするのがポイントです
***HTMLの作成***
With Worksheets(“MAIL”)
myLast = .Cells(Rows.Count, 2).End(xlUp).Row
For i = 6 To myLast
myProduct = .Cells(i, 2).Value
myQuantity = .Cells(i, 3).Value
myPrice = .Cells(i, 4).Value
myData = myData & “” & “” & myProduct & “” & myQuantity & “” & myPrice & “”
Next
************
そして、作成したHTMLをメールの本文に入れます(メールは送付せず、表示のみにしています)
*正確には事前に見出しを作成しておき、中身を変数で付け加える形です
‘メールの作成
'OutlookのMailitemオブジェクトを取得する
Dim objOutlook As New Outlook.Application
Dim objMailitem As Outlook.MailItem
Set objMailitem = objOutlook.CreateItem(olMailItem)
'メールの各種設定をする
With objMailitem
.To = "analytic@analytic-vba.com" '宛先
'.CC = myCc 'CC
.Subject = "TEST"
'.SentOnBehalfOfName = mySenderAddress
.HTMLBody = "<font face=""遊ゴシック""><font size=""2.5"">" & _
"<body><table border=1><tr>" & "<th>Product</th><th>Quantity</th><th>Price</th>" & "
</tr>" & _
myData & "</font></table></body>"
.Display '新規メール画面を表示
End With 'objMailitem
これでエクセルシート内の表がメールの本文に入ります
ファイルを添付して送付
.Attachments.Add+ファイル名の一文を上記のコードに追加します
Dim objMailitem As Outlook.MailItem
Set objMailitem = objOutlook.CreateItem(olMailItem)
'メールの各種設定をする
With objMailitem
.To = "analytic@vba.com" '宛先
(省略)
.Attachments.Add "C:\Users\***\Downloads\download.csv"
.Display '新規メール画面を表示
End With 'objMailitem
ユーザーフォーム
ユーザーフォームについてはこちらの記事もご参考にしてください
処理中表示
マクロの処理に時間がかかる場合は「処理中」の表示をしておきたい場合があります
こちらの表示にはユーザーフォームを使いたいところですが、ユーザーフォームを表示すると後続処理が止まってしまいます
ですので、以下のように「vbModeless」「Repaint」を使用します
Sub test()
UserForm1.Show vbModeless
UserForm1.Repaint
MsgBox “TEST”
Unload UserForm1
End Sub
上記のコードであれば、ユーザーフォームを表示しながらメッセージボックスも表示されます
ファイルの扱い
ファイルパスを指定して開く
Openメソッドを使用します
Dim myFileNameBefore As String
myFileNameBefore = “D:\Copy元.xlsx”
Workbooks.Open myFileNameBefore
ファイルを別名保存(コピー)する
SaveAsメソッドを使用します
Dim myFileNameBefore As String
Dim myFileNameAfter As String
myFileNameBefore = “D:\Copy元.xlsx”
myFileNameAfter = “D:\Copy先.xlsx”
Workbooks.Open myFileNameBefore
ActiveWorkbook.SaveAs Filename:=myFileNameAfter
ActiveSheet.Range(“B2”).Value = “TEST”
重複削除
重複削除を行うにはRemoveDuplicatesを使用します
複数列をキーに重複削除を行う際には、第二引数のArrayの中に列番号を複数指定します
例えば、次の表を「A」「B」の2列で重複削除を行うとします
この場合は、次のようなコードを書きます
Dim myLast As Long ‘最終行
myLast = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
Range(“A1:C” & myLast).RemoveDuplicates (Array(1, 2))
これで次のように削除されます
シート操作
全ページ操作
ファイル内の全シートを一律に操作するには「For Each ~ in ~ Next」構文を使用します
次の画像では、各シートのA1セルに値が入っています
そして、シートB以外はA1セルの値を読んでメッセージを表示するようにします
コードは一度、シート変数:wsTESTを宣言した後に次のように書きます
For Each wsTEST In Worksheets
If wsTEST.Name <> “B” Then
wsTEST.Activate
MsgBox Range(“A1”).Value
End If
Next
ちなみにSheet変数.nameでシート名が取得できます
印刷設定
印刷範囲設定
Dim myLast As Long
‘最終行取得
myLast = Worksheets(“Sheet4”).Cells(Rows.Count, 1).End(xlUp).Row
With Worksheets(“Sheet4”).PageSetup
‘印刷範囲設定
.PrintArea = “A1:M” & myLast
End with
全列を全て印刷
Application.PrintCommunication = False
With Worksheets(“Sheet4”).PageSetup
‘*全ての列を印刷
.Zoom = False
.FitToPagesWide = 1
.FitToPagesTall = False
End With
Application.PrintCommunication = True
改ページプレビューに設定
ActiveWindow.View = xlPageBreakPreview
集約集計(Dictionary使用)
Dictionaryオブジェクトを使用すると、エクセル関数で言えばSUMIFSと同じ集計を簡単に行えます
このDictionaryオブジェクトの概要をまずは解説します
Addメソッド
Dictionaryは要は箱です
Addで物を仕分けながら箱に入れます
Existsメソッド
Existsメソッドを使用することで箱に入れるものの重複を確認しながら、箱の中に用意する仕分け用スペースを用意できるようになります
上記2つのメソッドを使用したのが次のサンプルコードです
***Sample***
Sub testDic_1201()
Dim myDic As Variant
Set myDic = CreateObject(“scripting.dictionary”)
myDic.Add “A”, 100
myDic.Add “B”, 150
myDic.Add “C”, 200
MsgBox “B ” & myDic.Exists(“B”) & ” 値:” & myDic(“B”)
End Sub
***Sample***
上記のコードを実行すると次のようなメッセージが表示されます
ここからサンプルコードについて詳細を解説します
Set myDic = CreateObject(“scripting.dictionary”)で箱を作成します
そしてAddメソッドで名前(Key)と値を組み合わせて箱に入れます
myDic.Add “A”, 100
myDic.Add “B”, 150
myDic.Add “C”, 200
名前(Key)があるので、箱の中で他の名前のものと区分されて仕分けられるイメージです
そして、myDic.Exists(“B”)によりBが箱にあるかどうかを判定します(⇒True)
Bの値についてはmyDic(“B”)でmyDicの箱から取り出します
ここから本題の集計集約について解説します
題材は以下の画像の表です
この表から次のような集約集計を行えるようにします
***Sample***
Dim myDic As Variant
Set myDic = CreateObject(“Scripting.Dictionary”)
Dim myData As Variant
myData = Worksheets(“Sheet4”).Range(“A1”).CurrentRegion
Dim i As Long
For i = 2 To UBound(myData)
①If Not myDic.Exists(myData(i, Dic列.名前)) Then
myDic.Add myData(i, Dic列.名前), myData(i, Dic列.値)
Else
②myDic(myData(i, Dic列.名前)) = myDic(myData(i, Dic列.名前)) + myData(i, Dic列.値)
End If
Next i
Dim myKey As Variant
③myKey = myDic.keys
④For i = 0 To UBound(myKey)
Worksheets(“Sheet4”).Cells(i + 1, 7).Value = myKey(i)
Worksheets(“Sheet4”).Cells(i + 1, 8).Value = myDic(myKey(i))
Next i
***Sample***
「①If Not myDic.Exists(myData(i, Dic列.名前)) Then」により名前:Keyが箱にあるかを判定し、名前から追加するか、それとも該当の名前に値を追加するかを選択します
該当の名前に値を追加する場合は以下で行えます
②オブジェクト(キー)=オブジェクト(キー)+値
これでmyDicという箱ができました
ここから箱の中の名前別に値を抽出します
まずは箱の中の名前の一覧を取得します
Dim myKey As Variant
③myKey = myDic.keys
そして、名前を一つ一つ処理していきます
④For i = 0 To UBound(myKey)
Worksheets(“Sheet4”).Cells(i + 1, 7).Value = myKey(i)
Worksheets(“Sheet4”).Cells(i + 1, 8).Value = myDic(myKey(i))
Next i
コメントを残す