忍者ブログ
バイオインフォマティックス技術者試験、情報処理試験など、IT系の試験を基礎から勉強します。また、Javaなどプログラミングを勉強します。

【VBA】ユーザー定義型(Type句)の使い方!Object(クラス)との決定的な違いと使い分けの極意

VBAでバラバラな変数を一つにまとめたいとき、真っ先に候補に上がるのが「ユーザー定義型(Type句)」です。しかし、中級者以上になると「クラスモジュール(Object)」との使い分けに悩むことも。今回は、基本の書き方から、実務で役立つObjectとの使い分け判断基準まで徹底解説します。

1. 基本文法:Typeステートメントで「型」を作る

ユーザー定義型は、標準モジュールの先頭(宣言セクション)で Type を宣言します。これにより、複数の異なるデータ型を「一つの変数」として扱えるようになります。

[ 構文 ]
Type UserType
    Id As Integer
    Name As String
End Type

2. 実践サンプル:データの代入と出力

ポイント:Dimで宣言するだけで「実体」ができる

ユーザー定義型は、Objectと違い Set や New を使う必要がありません。宣言した瞬間からメモリ上に領域が確保されるため、非常に軽量で高速です。

Sub Macro1()
  Dim User As UserType  ' Newは不要!
  
  User.Id = 1
  User.Name = "いけいけ理系NEO"
  
  Debug.Print User.Id
  Debug.Print User.Name
End Sub

3. 徹底比較:ユーザー定義型 vs Object(クラス)

どちらを使うべきか迷ったときは、以下の「エンジニアの判断基準」を参考にしてください。

比較項目ユーザー定義型 (Type)Object (Class)
生成コスト 極めて軽量・高速 Newが必要でやや重い
メソッド 持てない(データのみ) 持てる(処理も内包)
配列・連想配列 Collectionに入れられない Collection等に格納可能

4. まとめ:結局どっちを使えばいいの?

1. Typeを使うべき時: 「単純に値をセットで持ちたいだけ」の場合です。例えば座標(X, Y)や、一時的な構造データの保持など、メモリ消費を抑えて「いけいけ」なスピードで回したいループ処理に向いています。
2. Object(クラス)を使うべき時: 「そのデータに関連する独自の処理(メソッド)」を持たせたい時や、データを Collection や Dictionary に詰め込んで管理したい時です。Javaなどのオブジェクト指向的な設計が必要な大規模開発ではクラス一択です。
3. エンジニアの視点: ユーザー定義型は「構造体」、Objectは「インスタンス」と考えるとスッキリします。VBAでも「データ」と「振る舞い」を分離することで、コードの保守性は見違えるほど良くなります。


5. 最後に

初心者はまず、手軽な「ユーザー定義型」から始めてみましょう。変数が整理される快感を覚えたら、次は「クラスモジュール(Object)」に挑戦して、より高度な設計を目指してみてください。使い分けができるようになれば、あなたのVBAスキルはプロの領域です。





PR

【VBA】行挿入の鉄則!各行を2行ずつに複製(コピー)する安全なアルゴリズム

Excel VBAで「特定の行をコピーして2行に増やしたい」という場面はよくあります。しかし、単純に上から順に行を挿入すると、無限ループのような挙動やデータのズレに悩まされることになります。今回は、行操作の鉄則である「逆順ループ」を用いて、安全かつ確実にデータを複製する方法を解説します。

1. 仕様:各行を2行ずつに複製(コピー)する

シートにあるデータを、以下のように各行2行ずつに増やす処理を実装します。1行につき1行の空行を挿入し、そこに元の内容をコピーするイメージです。

[ 処理前 ]      [ 処理後 ]
1行目: A        1行目: A
2行目: B   →   2行目: A (コピー)
3行目: C        3行目: B
                4行目: B (コピー)
                5行目: C
                6行目: C (コピー)

2. アルゴリズム:なぜ「下の行から上へ」処理するのか?

重要ポイント:行挿入は「逆順ループ(Step -1)」が鉄則

上から処理すると、新しく挿入した行を「次の処理対象」として誤認してしまい、同じデータを延々とコピーし続ける不具合が起きやすくなります。これを避けるため、最終行から1行目に向かって処理を遡ります。

[ 具体的な動作フロー(3行の場合) ]

Step 1 (i = 3)
3行目の「C」を認識。その直下(4行目)に空行を挿入してコピー。
結果: 1:A, 2:B, 3:C, 4:C (※3行目より下が確定)

Step 2 (i = 2)
2行目の「B」を認識。その直下(3行目)に空行を挿入してコピー。
この時、下の「C」たちは自動的に押し出されますが、カウンタ「i」はすでに上(2)に移動しているため、データが重複することはありません。

Step 3 (i = 1)
1行目の「A」を認識。その直下(2行目)に空行を挿入してコピー。
最終結果: 1:A, 2:A, 3:B, 4:B, 5:C, 6:C

3. サンプルコード(そのままコピーOK)

実務でもそのまま使える、高速化設定(ScreenUpdating)を組み込んだコードです。

Sub DoubleRows()
    Dim lastRow As Long
    Dim i As Long

    ' A列の最終行を取得
    lastRow = Cells(Rows.Count, "A").End(xlUp).Row

    ' 画面更新を停止して処理を高速化
    Application.ScreenUpdating = False

    ' 下の行から順に処理(逆順ループ)
    For i = lastRow To 1 Step -1
        ' 現在の行の下に1行挿入
        Rows(i + 1).Insert Shift:=xlDown

        ' 現在の行をコピーして、挿入した空行に貼り付け
        Rows(i).Copy Destination:=Rows(i + 1)
    Next i

    ' 画面更新を再開
    Application.ScreenUpdating = True

    MsgBox "処理が完了しました!"
End Sub

1. 技術的な補足: 行の削除や挿入を伴う処理では、Step -1(デクリメント)を使うのがVBAのセオリーです。上から処理して「行番号がズレる」というバグは、初心者が最もハマりやすい落とし穴の一つです。
2. エンジニアの視点: この「データの末尾から処理を確定させる」という考え方は、データベース移行(Migration)やスタックの操作など、IT全般に通ずる論理的なアプローチです。シンプルですが、非常に「堅牢(ロバスト)」なコード構造と言えます。


4. まとめ

「行を操作するなら下から上へ」。このルールを一つ覚えるだけで、VBAでのデータ加工の幅は大きく広がります。実行速度を意識した ScreenUpdating の制御と合わせて、ぜひ自身のツールに組み込んでみてください。





【VBA】Do While...Loopの使い方!条件を満たす間処理を繰り返す基本構造

VBAで繰り返し処理を行う際、For...Next と並んでよく使われるのが Do While...Loop です。「変数が10未満の間」や「セルが空欄でない間」といった、柔軟な条件指定ができるため、実務でのデータ処理において非常に重宝します。

1. 基本文法:Do While...Loop

ループの開始時に条件を判定し、その条件が True(真) である間、中の処理を繰り返し実行します。条件が False になった瞬間にループを抜けます。

[ 構文 ]
Do While 条件式
    ' 繰り返したい処理
Loop

2. 実践サンプル:1から10までカウントアップ

ポイント:ループ内で条件に関わる変数を更新する

以下の例では、変数 i が10になるまで処理を繰り返します。ループの中で i = i + 1 を忘れると、条件がいつまでも満たされたままになり、無限ループに陥るため注意が必要です。

Sub MySub()
  Dim i As Integer
  
  i = 0  ' 初期化
  
  ' i が 10 より小さい間は繰り返す
  Do While i < 10
    i = i + 1
    Debug.Print i
  Loop
End Sub

3. 実行結果

イミディエイトウィンドウに、1から10までの数値が順番に出力されます。

1
2
3
4
5
6
7
8
9
10

4. エンジニアの視点:For文との使い分けと「無限ループ」対策

1. 使い分けの基準: 回数が決まっている時は For...Next、回数が決まっておらず「データが終わるまで」のような動的な条件の時は Do While を使います。特に、外部ファイル(CSVやDBのレコード)を1行ずつ読み込むような「いけいけ」な処理には Do While が最適です。
2. 無限ループの回避: 条件式が常に True になってしまうと、Excelがフリーズします。もし止まらなくなったら [Ctrl] + [Pause/Break] キーで中断しましょう。開発中は、念のためループ内に DoEvents を入れておくと、強制終了しやすくなるのでおすすめです。
3. 条件判定のタイミング: Do While は最初に判定しますが、Loop While と書くと最後に判定(一度は必ず実行)するようになります。このあたりの制御を使いこなせるようになると、IT技術者としてより緻密なロジックが組めるようになります。


5. まとめ

「条件が整っている間、ひたすら回す」。このシンプルな考え方が、複雑な業務自動化を支えます。変数の更新タイミングと条件式の関係をしっかりマスターして、自由自在にループを操れるようになりましょう。

【VBA】数値判定(IsNumeric)の使い方!計算エラーを未然に防ぐデータバリデーション

VBAで計算処理を行う際、変数の中身が数値ではないのに計算しようとすると「型が一致しません」というエラーが発生してしまいます。IsNumeric関数を使えば、対象のデータが数値として扱えるかどうかを事前に判定できるため、安全なプログラムを書くことが可能になります。

1. 基本文法:IsNumeric関数

引数に指定した値が、数値として認識できる場合は True、認識できない場合は False を返します。整数だけでなく、小数や「数値として解釈可能な文字列」も判定対象となります。

[ 構文 ]
IsNumeric( 判定したい値 )

2. 実践サンプル:データの数値判定

ポイント:文字列の「"123"」もTrueになる柔軟な判定

数値そのものはもちろん、計算可能なデータであれば True を返す特性を理解しておきましょう。

Sub Macro1()
  Debug.Print IsNumeric(1)        ' 結果: True (整数)
  Debug.Print IsNumeric(0.5)      ' 結果: True (小数)

  Dim str1 As String
  str1 = "aa"
  Debug.Print IsNumeric(str1)    ' 結果: False (アルファベット)
End Sub

3. 実行結果

イミディエイトウィンドウには、判定結果が論理値で表示されます。

True
True
False

4. エンジニアの視点:IsNumericの「癖」に注意

1. 意外な判定結果: IsNumeric は非常に柔軟です。例えば IsNumeric("1,234") や IsNumeric("&HFF")(16進数)も True を返します。厳密に「数字だけ」を許可したい場合は、他のチェックとの併用も検討しましょう。
2. 実務での活用法: ユーザーに入力させた値が数値でない場合に、「数値を入力してください」と警告(MsgBox)を出すガード句として使うのが一般的です。これにより、マクロが途中で落ちるという「いけいけ」でない状況を防げます。
3. データクリーニング: データベース(PostgreSQLやOracle等)へデータを移行する前の事前チェックとしても有効です。型エラーによるインポート失敗を防ぐために、VBA側で IsNumeric を使ってエラー行を抽出するロジックは非常に「理系」的で効率的です。


5. まとめ

「計算する前に、まず IsNumeric」。この習慣をつけるだけで、マクロの信頼性は飛躍的に向上します。外部から来る不確定なデータを扱う際こそ、この関数でデータの正当性をしっかりと見極めていきましょう。



【VBA】乱数(Rnd)の使い方!ランダムな数値を生成して処理に変化を持たせる方法

プログラムの中で、実行するたびに異なる数値を使いたい場面があります。VBAでは Rnd関数 を使うことで、0以上1未満の乱数を発生させることができます。ゲームの要素だけでなく、データのサンプリングやテストデータの自動生成など、実務でも幅広く活用される機能です。

1. 基本文法:Randomize と Rnd

乱数を使用する際は、必ず Randomize ステートメントを先に実行するのが鉄則です。これを行わないと、マクロを起動し直した際に「毎回同じパターンの乱数」が発生してしまい、本当の意味でのランダムになりません。

Randomize
乱数ジェネレータをシステムタイマーの値で初期化します。

Rnd()
0以上、1未満の範囲(0.000... ~ 0.999...)の小数を返します。

2. 実践サンプル:乱数の発生と出力

ポイント:実行前に必ず「Randomize」で初期化する

最もシンプルな、0から1の間の小数をイミディエイトウィンドウに出力するコードです。

Sub Macro1()
  ' 乱数系列を初期化(これ重要!)
  Randomize

  ' 0以上1未満の乱数を発生させて出力
  Debug.Print Rnd()
End Sub

3. 実行結果

実行するたびに、以下のようなランダムな小数が出力されます。

0.7055475
0.533424
0.2869222

4. エンジニアの視点:実務で使える「整数の乱数」の作り方

1. 範囲指定のテクニック: 実務では「1から100までの整数」が欲しい場合が多いです。その場合は、以下の公式を使います。
Int((最大値 - 最小値 + 1) * Rnd + 最小値)
例えば1〜100なら、Int(100 * Rnd + 1) と記述すればOKです。
2. Randomizeのタイミング: Randomize は一つのマクロ処理の中で一度だけ実行すれば十分です。ループの中で何度も実行すると、逆にランダム性が損なわれることがあるため注意しましょう。
3. 再現性の確保: あえて Randomize を使わずに、Rnd(-1) などの引数を与えて「決まったパターンの乱数」を出すこともあります。これはデバッグ時に「前回と同じ乱数でバグを再現したい」といった場合に役立つ「いけいけ」な高等テクニックです。


5. まとめ

「まずは Randomize、次に Rnd」。このセットを覚えるだけで、VBAに「偶然」の要素を取り込むことができます。データのシャッフルや抽選ツールなど、乱数を使いこなして一味違うツール作成に挑戦してみてください。


        
  • 1
  • 2
  • 3