VBA関係

VBAのシステム管理してて困ったこととかサンプルコードとか書いてます。

VBA プロシージャの引数と戻り値

一応サンプルコード置いてますが、解説とかがメインです。

 

'メインプロシージャ(ByRef)

Sub test_sub()

    Dim a as Long

    Dim b as Long

    Dim c as Long

    

    b = 10

    c = 5

    a = test_calc(b,c)

    

    MsgBox("a=" & a)

    MsgBox("b=" & b)

    MsgBox("c=" & c)

End Sub

 

'計算するプロシージャ(ByRef)

Function test_calc(ByRef d as Long, ByRef e as Long) as Long

    d = 15

    e = 20

    test_calc = d * e

End Function

 

 

Functionで戻り値の型を指定する場合、閉じカッコの後に as Longを記述します。(as Dateなど他の型も可)

引数のByVal、ByRef、戻り値のas Longは省略可能ですが、エラーの温床になるのでお勧めしません。ByVal、ByRefを省略した場合、ByRefが書かれたことになります。

 

ByValは引数を生成する時に値をコピーし、ByRefはコピーせずにそのまま参照します。

なんかByValは値渡し、ByRefは参照渡しっていうらしいです。面倒だから専門用語増やすなと言いたい。

 

ByValを使った場合、引数をいじっても遷移元のプロシージャでは値は変わりません。

ByRefだと、引数いじったら変わります。

基本引数を変えたい場面ってないのでByValでいいと思いますが、値コピーだから、恐らくメモリ食ってるのかな?とか思ったりします。が、詳しくは知りません。

怖かったらByValを使っておいて、気になった時に調べればいいと思います。

VBA サンプルコード プロシージャの呼び出し方

'メインプロシージャ

Sub test_sub()

    Dim a as Long

    Dim b as Long

    Dim c as Long

    b = 10

    c = 5

    a = test_calc(b,c)

    MsgBox(a)

End Sub

 

'計算するプロシージャ

Function test_calc(ByVal d as Long, ByVal e as Long) as Long

    test_calc = d * e

End Function

 

 

引数のByValはByRefと書くこともあります。詳しくは下記にて解説。

VBA その辺に転がってるサンプルコードで気を付ける事とか

ウイルスになるようなコードが転がっている…というのを聞いた事はありますが、そういうのは探さないとむしろなさそうです。

 

正直、最近で怖いのはVBA特有のコード省略をフル活用した、短縮コードです。

ぶっちゃけ下記のコードは短くて超便利なんですが、VBA多用してる会社とかだと、複数のVBAを同時に動かしたりして、こういうコードでめっちゃ面倒な問題になることがあります。

Cells(1, "A") = Date

これ、Cellsだけしか書いてないんですが、実はActiveWorkbook.ActiveSheetというめっちゃ長いコードが省略されていて、全部書くとActiveWorkbook.ActiveSheet.Cellsになります。

このActiveWorkbook.ActiveSheetは、今開いているExcelファイルのシートを読み書きするもので、これを使うと、読み書きするシートがリアルタイムで変わってしまいます。

VBAが動いてる途中で別のExcelを開いたりすると、開いたExcelのシートを読み書きしてしまうので、下手すると関数壊しちゃったりします。

 

ちなみにVBAExcelのセルを書き換えた場合、元に戻す機能が使えないので、関数壊しちゃったのを戻したい場合は、保存せずに閉じるしかないです。

保存してなかったら諦めるしかありません。これが結構痛いです。

 

安定した挙動を確保する場合はWorkbooksとかWorksheetsとかでブックとシートを指定することを強くお勧めします。

また、エラーが良く出るVBAはこういう書き方してることが多く、開発者にシステムの挙動が聞けない環境だともう最悪です。

テストで動かす分には省略しても全く問題ありませんが、業務で広く使う場合、他の資料を破壊してしまうので、放置すると割と笑えない未来が待ってます。

VBA サンプルコード 日付の取得とか

主に日付関係のサンプルコードです。

 

'今日の日付と今の時間

Sub test1()

    Dim d as Date

    d = Now

    Call MsgBox(d)

End Sub

 

'今日の日付

Sub test2()

    Dim d as Date

    d = Date

    Call MsgBox(d)

End Sub

 

'今の時間

Sub test3()

    Dim d as Date

    d = Time

    Call MsgBox(d)

End Sub

 

'文字列から日付を生成

Sub test4()

    Dim d as Date

    d = CDate("2024/3/19")

    Call MsgBox(d)

End Sub

 

'翌年の今日を取得

Sub test5()

    Dim d as Date

    d = DateAdd("yyyy", 1, Date)

    Call MsgBox(d)

End Sub

 

'翌月の今日を取得

Sub test6()

    Dim d as Date

    d = DateAdd("m", 1, Date)

    Call MsgBox(d)

End Sub

 

'明日を取得

Sub test7()

    Dim d as Date

    d = DateAdd("d", 1, Date)

    Call MsgBox(d)

End Sub

 

'任意の日を取得

Sub test8()

    Dim d as Date

    d = DateSerial(2024, 3, 19)

    Call MsgBox(d)

End Sub

 

'年を取得

Sub test9()

    Dim y as Long

    y = Year(Date)

    Call MsgBox(y)

End Sub

 

'月を取得

Sub test10()

    Dim m as Long

    m = Month(Date)

    Call MsgBox(m)

End Sub

 

'日を取得

Sub test11()

    Dim d as Long

    d = Day(Date)

    Call MsgBox(d)

End Sub

 

'Formatで文字列に変換

Sub test12()

    Dim s as String

    s = Format(Date, "yyyy年m月d日")

    Call MsgBox(s)

End Sub

 

Formatについては色々な使い方があるっぽいです。「VBA Format関数」で検索すると出てきますので、興味がある方はぜひ。

やりたいこと

なんか仕事してて、欲しい機能のコード探す時に、ダラダラと仕組みの解説とかを見てると激烈に不快になる病気になってしまったので、とりあえず実現するためのサンプルコードを置いてるだけの記事欲しいなぁ。あったらいいなぁ。書くか。

ということで、適当に書くことにした。

 

解説とかは後から興味がわいた時に知れればいいと思っているので、実現するために必要な情報以外は別だと非常に助かるんだが…早くしろと言われることが多いプログラマ初心者に、実現とは無関係な文章が多いのは不親切にもほどがあるというのを、本とか記事とか読んでて思う。上級者向けの記事なら、無関係なことでも多少は読む余裕ありそうだが…上級者の気分は知らん。

 

仕事で使うことが多いプロシージャとかをサンプルで実行できる形で気が向いた時に書く予定。

困った時に勝手に使えばいいし、使えなければ、そっ閉じすればいいと思う。

以上。

VBA サンプルコード セルの値を取得 & 最終行、最終列の取得

サンプルコードだけ並べます。

Excelの表からデータ拾ってVBAで集計する仕事だと、ここのコードしってるとめっちゃ便利です。

 

※事前にSheet1という名前のシートを作っておく必要があります。

 

'CellsでA1セルの値を取得

Sub test1()

    Dim val as Variant

    val = ThisWorkbook.Worksheets("Sheet1").Cells(1,"A").Value

    Call MsgBox(val)

End Sub

 

 'RangeでA1セルの値を取得

Sub test2()

    Dim val as Variant

    val = ThisWorkbook.Worksheets("Sheet1").Range("A1").Value

    Call MsgBox(val)

End Sub

 

'A列の最終行を取得

Sub test3()

    Dim endR as Long

    Dim sh as Worksheet: Set sh = ThisWorkbook.Worksheets("Sheet1")

   endR = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row

    Call MsgBox(endR)

End Sub

 

 

'1行目の最終列を取得

Sub test4()

    Dim endC as Long

    Dim sh as Worksheet: Set sh = ThisWorkbook.Worksheets("Sheet1")

   endC = sh.Cells(1, sh.Columns.Count).End(xlToLeft).Column

    Call MsgBox(endC)

End Sub