【VBAリファレンス】VBA練習問題練習問題25(各種VBA関数)

スポンサーリンク

概要

本稿では、Excel VBAにおける各種関数に焦点を当て、その活用方法と実践的なコーディングテクニックを詳解します。VBA関数は、データの操作、条件分岐、繰り返し処理など、VBAプログラミングの根幹をなす要素であり、これらの関数を自在に使いこなすことが、効率的で堅牢なVBAマクロを作成するための鍵となります。本稿では、特に頻繁に使用される文字列操作関数、数値関数、日付関数、論理関数、そしてExcelワークシート関数をVBAから呼び出す方法に焦点を当て、具体的な練習問題とその解答例を通じて、理解を深めていきます。これらの関数を習得することで、より複雑なデータ処理や自動化タスクを VBA で実現できるようになるでしょう。

詳細解説

VBAには、プログラムのロジックを構築し、データを処理するために不可欠な、多種多様な組み込み関数が用意されています。ここでは、特に実務で頻繁に利用される主要な関数群とその使い方について、具体的な例を交えながら解説します。

文字列操作関数

文字列操作関数は、テキストデータを加工・分析する際に極めて重要です。

* **Len(文字列)**: 指定した文字列の長さを返します。

Dim strText As String
strText = “Excel VBA”
MsgBox Len(strText) ‘ 9 を表示

* **Left(文字列, 文字数)**: 文字列の左端から指定した文字数分の文字列を返します。

Dim strText As String
strText = “Excel VBA”
MsgBox Left(strText, 5) ‘ “Excel” を表示

* **Right(文字列, 文字数)**: 文字列の右端から指定した文字数分の文字列を返します。

Dim strText As String
strText = “Excel VBA”
MsgBox Right(strText, 3) ‘ “VBA” を表示

* **Mid(文字列, 開始位置, 文字数)**: 文字列の指定した開始位置から、指定した文字数分の文字列を返します。

Dim strText As String
strText = “Excel VBA”
MsgBox Mid(strText, 7, 3) ‘ “VBA” を表示

* **InStr([開始位置], 文字列1, 文字列2, [比較方法])**: 文字列1の中に文字列2が出現する最初の位置を返します。見つからない場合は0を返します。

Dim strText As String
strText = “Excel VBA Programming”
MsgBox InStr(strText, “VBA”) ‘ 7 を表示

* **Replace(文字列, 検索文字列, 置換文字列, [開始位置], [文字数], [比較方法])**: 文字列中の指定した部分を別の文字列に置換します。

Dim strText As String
strText = “Excel VBA is powerful.”
MsgBox Replace(strText, “powerful”, “flexible”) ‘ “Excel VBA is flexible.” を表示

* **UCase(文字列)**: 文字列をすべて大文字に変換します。
* **LCase(文字列)**: 文字列をすべて小文字に変換します。
* **Trim(文字列)**: 文字列の前後の空白を削除します。
* **RTrim(文字列)**: 文字列の後ろの空白を削除します。
* **LTrim(文字列)**: 文字列の前方の空白を削除します。

数値関数

数値関数は、数値データを加工・計算する際に使用します。

* **Int(数値)**: 指定した数値以下の最大の整数を返します。

MsgBox Int(3.14) ‘ 3 を表示
MsgBox Int(-3.14) ‘ -4 を表示

* **Fix(数値)**: 指定した数値の整数部分を返します。正の数ではInt関数と同じですが、負の数では0に近づく方向への切り捨てとなります。

MsgBox Fix(3.14) ‘ 3 を表示
MsgBox Fix(-3.14) ‘ -3 を表示

* **Round(数値, [小数点以下の桁数])**: 指定した数値を指定した小数点以下の桁数で四捨五入します。小数点以下の桁数を省略すると、最も近い整数に丸められます。

MsgBox Round(3.14159, 2) ‘ 3.14 を表示
MsgBox Round(3.5) ‘ 4 を表示
MsgBox Round(2.5) ‘ 2 を表示 (偶数丸め)

* **Sgn(数値)**: 数値の符号を返します。正の数なら1、0なら0、負の数なら-1を返します。
* **Abs(数値)**: 数値の絶対値を返します。

日付関数

日付関数は、日付や時刻データの操作に不可欠です。

* **Date**: 現在の日付を返します。
* **Time**: 現在の時刻を返します。
* **Now**: 現在の日付と時刻を返します。
* **Year(日付)**: 日付から年を取り出します。
* **Month(日付)**: 日付から月を取り出します。
* **Day(日付)**: 日付から日を取り出します。
* **Hour(時刻)**: 時刻から時を取り出します。
* **Minute(時刻)**: 時刻から分を取り出します。
* **Second(時刻)**: 時刻から秒を取り出します。
* **DateAdd(間隔, 数, 日付)**: 指定した日付に、指定した間隔で指定した数を加算した日付を返します。

MsgBox DateAdd(“yyyy”, 1, #2023/10/27#) ‘ 2024/10/27 を表示
MsgBox DateAdd(“m”, 3, #2023/10/27#) ‘ 2024/01/27 を表示
MsgBox DateAdd(“d”, 7, #2023/10/27#) ‘ 2023/11/03 を表示

* **DateDiff(間隔, 開始日, 終了日, [第一曜日], [週の開始])**: 二つの日付の差を指定した間隔で返します。

MsgBox DateDiff(“yyyy”, #2023/10/27#, #2024/10/27#) ‘ 1 を表示
MsgBox DateDiff(“m”, #2023/10/27#, #2024/01/27#) ‘ 3 を表示
MsgBox DateDiff(“d”, #2023/10/27#, #2023/11/03#) ‘ 7 を表示

論理関数

論理関数は、条件判定や真偽値の操作に使用します。

* **If(条件式, 条件が真の場合の値, 条件が偽の場合の値)**: 条件式を評価し、真なら第一引数、偽なら第二引数の値を返します。

Dim score As Integer
score = 80
MsgBox IIf(score >= 60, “合格”, “不合格”) ‘ “合格” を表示

* **IsEmpty(変数)**: 変数が初期化されている(値が設定されていない)場合にTrueを返します。
* **IsNull(値)**: 値がNullである場合にTrueを返します。
* **IsNumeric(式)**: 式が数値または数値に変換可能な文字列である場合にTrueを返します。

Excelワークシート関数の利用

VBAからは、Excelのワークシート関数も `Application.WorksheetFunction` オブジェクトを通じて利用できます。これにより、VBAで直接実装するのが煩雑な関数も簡単に利用できます。

* **Application.WorksheetFunction.Sum(範囲)**: 指定した範囲の合計を計算します。

Dim rng As Range
Set rng = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:A10”)
MsgBox Application.WorksheetFunction.Sum(rng)

* **Application.WorksheetFunction.VLookup(検索値, 範囲, 列番号, 検索方法)**: 指定した範囲の左端列で検索値を検索し、同じ行の指定した列番号の値を返します。

Dim lookupValue As Variant
Dim tableArray As Range
lookupValue = “商品A”
Set tableArray = ThisWorkbook.Sheets(“Sheet1”).Range(“A1:B10”)
MsgBox Application.WorksheetFunction.VLookup(lookupValue, tableArray, 2, False)

**注意**: ワークシート関数がエラーを返す場合、VBAでは実行時エラーが発生します。これを避けるためには、`On Error Resume Next` を使用するか、`Application.VLookup` のように `WorksheetFunction` を付けないで呼び出す方法があります。後者の場合、エラー時には `Error` 型の値が返されます。

サンプルコード

以下は、上記で解説した関数の一部を組み合わせて、簡単なデータ処理を行うVBAコードの例です。

Sub FunctionPractice()

Dim strFullName As String
Dim strFirstName As String
Dim strLastName As String
Dim numScore As Double
Dim dtBirthDate As Date
Dim daysUntilBirthday As Long
Dim ws As Worksheet

‘ —————————————-
‘ 文字列操作の例
‘ —————————————-
strFullName = “山田 太郎”

‘ 名と姓を分割する
Dim spacePos As Integer
spacePos = InStr(strFullName, ” “)

If spacePos > 0 Then
strFirstName = Left(strFullName, spacePos – 1)
strLastName = Mid(strFullName, spacePos + 1)
MsgBox “姓: ” & strLastName & “, 名: ” & strFirstName
Else
MsgBox “氏名にスペースが含まれていません。”
End If

‘ 特定の文字列を置換する
Dim strMessage As String
strMessage = “このメールはテストです。重要なお知らせではありません。”
strMessage = Replace(strMessage, “テスト”, “重要”)
MsgBox strMessage ‘ “このメールは重要です。重要なお知らせではありません。”

‘ —————————————-
‘ 数値操作の例
‘ —————————————-
numScore = 75.8

‘ 点数を整数に変換(切り捨て)
Dim scoreInt As Integer
scoreInt = Int(numScore)
MsgBox “点数(整数部): ” & scoreInt ‘ 75

‘ 点数を四捨五入
Dim scoreRounded As Double
scoreRounded = Round(numScore, 0)
MsgBox “点数(四捨五入): ” & scoreRounded ‘ 76

‘ —————————————-
‘ 日付操作の例
‘ —————————————-
dtBirthDate = #1990/10/27#
Dim today As Date
today = Date

‘ 誕生日からの経過年数を計算
Dim yearsElapsed As Long
yearsElapsed = DateDiff(“yyyy”, dtBirthDate, today)
MsgBox “誕生から” & yearsElapsed & “年経過しました。”

‘ 来年の誕生日を計算
Dim nextBirthday As Date
nextBirthday = DateAdd(“yyyy”, 1, dtBirthDate)
MsgBox “来年の誕生日は: ” & Format(nextBirthday, “yyyy/mm/dd”)

‘ 今日から誕生日までの日数を計算(来年の誕生日を基準とする)
daysUntilBirthday = DateDiff(“d”, today, nextBirthday)
MsgBox “来年の誕生日まであと ” & daysUntilBirthday & ” 日です。”

‘ —————————————-
‘ 論理関数とワークシート関数の例
‘ —————————————-
Set ws = ThisWorkbook.Sheets(“Sheet1”) ‘ 実際のシート名に変更してください

‘ セルA1からA10の合計を計算
Dim sumRange As Range
On Error Resume Next ‘ エラー発生時に処理を続行
Set sumRange = ws.Range(“A1:A10”)
If Err.Number = 0 Then ‘ エラーが発生しなかった場合
Dim totalSum As Double
totalSum = Application.WorksheetFunction.Sum(sumRange)
MsgBox “A1:A10の合計は: ” & totalSum
Else
MsgBox “A1:A10の範囲に数値が含まれていないか、範囲が存在しません。”
Err.Clear ‘ エラー情報をクリア
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す

‘ セルB1の値が60以上なら「合格」、そうでなければ「不合格」を表示
Dim studentScore As Variant
studentScore = ws.Range(“B1”).Value ‘ B1セルに点数が入っていると仮定

If IsNumeric(studentScore) Then
Dim result As String
result = IIf(CDbl(studentScore) >= 60, “合格”, “不合格”)
MsgBox “評価: ” & result
Else
MsgBox “B1セルに有効な点数を入力してください。”
End If

End Sub

### 実務アドバイス

1. **エラーハンドリングの徹底**: VBA関数、特にワークシート関数を利用する際は、予期せぬエラー(例: ワークシート関数での#N/Aエラー、存在しないシートへのアクセスなど)が発生する可能性があります。`On Error Resume Next` や `On Error GoTo` を適切に使用し、エラー発生時にもプログラムが停止しないように、また、エラーの原因を特定できるようにコーディングすることが重要です。
2. **データ型の適切な選択**: 変数宣言時に適切なデータ型(String, Integer, Double, Date, Booleanなど)を選択することで、メモリの効率的な使用、予期せぬ型の不一致によるエラーの防止、コードの可読性向上に繋がります。特に、数値計算には `Double`、日付・時刻には `Date` 型を使いましょう。
3. **ワークシート関数 vs VBA関数**: 同じような機能を持つワークシート関数とVBA関数が存在する場合があります。一般的に、VBA組み込み関数の方が処理速度が速い傾向がありますが、ワークシート関数の方が機能が豊富で、Excelの強力な計算能力を直接利用できるメリットがあります。どちらを使うべきかは、処理内容、パフォーマンス要件、コードの可読性を考慮して判断しましょう。例えば、複雑な統計計算や財務計算などは `Application.WorksheetFunction` を利用する方が効率的です。
4. **文字列操作の注意点**: `InStr` 関数で検索文字列が見つからなかった場合、0が返されます。また、`Mid` 関数などで指定する開始位置や文字数は、文字列の範囲を超えないように注意が必要です。`Len` 関数で文字列長を確認したり、`Trim` 関数で前後の不要な空白を削除してから処理を行うことで、意図しない結果になることを防げます。
5. **日付・時刻の扱い**: VBAにおける日付・時刻は内部的には数値として扱われます。`#YYYY/MM/DD#` のようなリテラル形式で直接指定できますが、変数に格納したり、他の日付との差を計算したりする際には、`Date` 型を使用することが必須です。`DateAdd` や `DateDiff` 関数は非常に強力ですが、間隔の指定(”yyyy”, “m”, “d”など)を正確に行うことが重要です。
6. **可読性の向上**: 関数を多用するコードは、一見すると複雑になりがちです。変数名を分かりやすくする、コメントを適切に記述する、処理を小さなプロシージャに分割するなどの工夫により、コードの可読性と保守性を高めることができます。

### まとめ

本稿では、Excel VBAにおける各種関数、特に文字列操作関数、数値関数、日付関数、論理関数、そしてExcelワークシート関数について、その基本的な使い方から実践的な応用例までを詳解しました。これらの関数は、VBAプログラミングにおいてデータの加工、条件判定、計算処理など、あらゆる場面で不可欠なツールです。

`Len`, `Left`, `Mid`, `InStr`, `Replace` といった文字列操作関数は、テキストデータの整形や抽出に役立ちます。`Int`, `Fix`, `Round` などの数値関数は、計算結果の丸めや整数化に利用されます。`Date`, `Time`, `Now`, `DateAdd`, `DateDiff` などの日付関数は、日々の業務で発生する日付・時刻に関する処理を効率化します。また、`IIf` 関数のような論理関数は、条件分岐を簡潔に記述するのに便利です。

さらに、`Application.WorksheetFunction` を介してExcelの強力なワークシート関数をVBAから呼び出すことで、より高度で複雑な処理も容易に実現できます。ただし、ワークシート関数の利用時にはエラーハンドリングが重要であることを忘れてはなりません。

これらの関数を効果的に組み合わせ、適切なデータ型を選択し、エラーハンドリングを徹底することで、より堅牢で、効率的、かつ保守性の高いVBAマクロを作成

タイトルとURLをコピーしました