2023/09/19
【ExcelVBA】表の最終行の行番号を取得する方法

【ExcelVBA】表の最終行の行番号を取得する方法

VBAで何かを開発する際に、表の最終行の行番号を取得することが結構あります。
そんな最終行の取得方法には色んな方法があります。

こちらでは、4パターンをお伝えし、それぞれのメリット・デメリットをまとめています。

最終行の取得方法は、以下のlastRow1からlastRow4などの方法があります。
これ以外にも色んな方法がありますが、今回はこちらの4パターンについて触れていきます。
※こちらのファイルは配布しています。

では、順番にメリット・デメリットをまとめていきます。


・lastRow1

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

こちらは、A列のシートの最後のセル「A1048576※最後の行番号はバージョンによって異なる」から「Ctrl+↑(カーソルキー)」で移動した先のセルの行番号を取得するという方法です。
「Ctrl+↑」で、次に値の入力されているセルまで移動することができます。

メリットは、必ず値の入力されている項目がある場合は、その項目の列を基準に正しい最終行の行番号を取得することができます。
表の間に空白行があったとしても、最終行を取得することができます。

デメリットは、必ず値の入力されている項目がない場合は、正しい最終行の行番号を取得することができないことです。
例えば、以下の表の場合、A列を基準に最終行の行番号を取得すると「11」になってしまいます。

Excel本紹介

・lastRow2

lastRow2 = Range("A1").End(xlDown).Row

こちらは、A列の先頭「A1」から「Ctrl+↓(カーソルキー)」で移動した先のセルの行番号を取得するという方法です。

メリットは、単純にコードを短く書くことができます。

デメリットは、データが0件の場合や、空白行がある場合に正しい行番号を取得することができません。
0件の場合は、「Ctrl+↓」ですと、次に値が入力されているセルが見つからないため、シートの最後の行番号が取得されてしまいます。


・lastRow3

lastRow3 = Range("A1").SpecialCells(xlLastCell).Row

こちらは、シート上で使用されたことがあるセル範囲の最後の行番号を取得するという方法です。
使用されたことがあるセル範囲は、セルA1を基準に「Ctrl + Shift + End」で選択される範囲になります。

メリットは、必ず値の入力されている項目がなくても、最終行の行番号を取得することができます。

デメリットは、”使用されたことがあるセル範囲”のため、データが削除された場合に、正しい最終行の行番号を取得することができません。


・lastRow4

lastRow4 = Range("A1").CurrentRegion.Rows.Count

こちらは、現時点で使用されているセル範囲から行数を取得するという方法です。
表の中を選択し、「Ctrl+A」で選択される範囲の行数を取得しています。

メリットは、lastRow3と同様に、必ず値の入力されている項目がなくても、最終行の行番号を取得することができます。

デメリットは、空白行がある場合には、正しい最終行の行番号を取得することができません。


それぞれにメリットとデメリットがあるため、それらを理解した上で、活用するのが良いです。
個人的には、lastRow1とlastRow4の方法がオススメになります。

▼サンプルファイル▼

2023/08/31
【ExcelVBA】マークされた行を削除する

【ExcelVBA】マークされた行を削除する

以下の表のように、マークされた行を瞬時に削除するマクロの開発方法について解説していきます。
※完成ファイルは配布しています。

このような仕組みをVBAで開発するには、どのような処理で実現するのかを考える必要があります。
今回の場合は、以下のような処理で実現できるかと思います。
※このような処理の流れを表現した図をフローチャートと呼びます。

処理を上記のように分解することができましたら、1つ1つVBAで実現していきます。

まずは、[開発]タブより[マクロ]を選択し、好みの名前(こちらでは”対象行の削除”)を入力し、[作成]を選択します。

表示された「Sub 対象行の削除()」内に以下のようなコードを記述します。
※「’」から始まっている緑の文字はコメントアウトと呼び、処理には関係のないメモ書きになります。

Sub 対象行の削除()
    
    Dim lastRow As Long
    
    'B列の最終行(≒150万行目)から「Ctrl+↑」で移動して止まった位置の行番号
    '⇒B列に●が入力されている一番下の行番号
    lastRow = Cells(Rows.Count, "B").End(xlUp).Row
    
    Dim i As Long
    
    '行を削除すると、行番号がずれてしまうため、下から上へと対象行を削除する
    For i = lastRow To 3 Step -1
        
        'B列のi行目のセルに値が入力されている場合
        '※「….Value = "●"」でも可
        If Cells(i, "B").Value <> "" Then

            'i行目を削除する
            Rows(i).Delete
            
        End If
        
    Next i
    
End Sub

上記のコードの解説をします。

Dim lastRow As Long

Dim と書かれているものは変数宣言と呼び、プログラム内で一時的に使用する値を格納する部屋(変数)を用意しています。
As の後に部屋(変数)の種類を定義しています。
Long は整数を格納する専用の部屋(変数)を指します。

lastRow = Cells(Rows.Count, "B").End(xlUp).Row

Rows.Count で対象のシートの最大の行番号(1048576)を取得できます。
Cells(Rows.Count, “B”) でセルB1048576を指定し、 .End(xlUp) でCtrlキーと↑キーを押した先に移動しています。
Ctrlキーと↑キーを同時に押すと、対象列の次に値が入力されているセルまで移動することができます。
その移動した先のセルの行番号を .Row で取得しています。

For i = lastRow To 3 Step -1 ~ Next i

For ~ Next 間を、先ほど取得した行番号から3まで-1刻みで繰り返します。
変数(i)が先ほど取得した行番号から3まで-1刻みで変化して、For ~ Next の中の処理が繰り返し実行されます。

If Cells(i, "B").Value <> "" ThenEnd If

If ~ End If の中の処理に関して、 Cells(i, “B”).Value <> “” の条件を満たした場合のみ実行します。
Cells(i, “B”).Value は対象のi行目のB列のセルを指しており、 .Value でそのセルの値を取得しています。
<> は等しくないという意味を表しており、 <> “” で空白でないという意味になります。

Rows(i).Delete

Rows(i) でi行目の全体を指定し、 .Delete で削除しています。

上記の内容を記述し、エディタ内の実行ボタン、もしくは、[マクロ]の実行ボタンにて実行すると、B列に値が入力された行全体が削除されます。

※マクロを実行すると、実行前の状態に戻すことができなくなるため、動作確認をする前に、保存をしておくと良いです。

▼サンプルファイル▼

2023/08/08
【ExcelVBA】合格者だけに合格証を発行

【ExcelVBA】合格者だけに合格証を発行

下記の成績一覧表を元に、点数が60点以上の方のみに合格証のシートを発行する方法について解説していきます。

発行する合格証のテンプレートは以下になります。

こちらでは、VBAを用いて開発していきます。
VBAに関して、一度も開発したことがない場合は、下記よりVBAの基礎をご確認ください。

>VBAの基礎(4-04くらいまでの理解が必要です)

では、開発していきます。
[開発]タブの中の[マクロ]から”合格証発行”という名前で以下のように開発します。

Option Explicit '省略可 変数の宣言を強制する

Sub 合格証発行()
    
    Dim ws1 As Worksheet, ws2 As Worksheet
    Set ws1 = Worksheets("成績一覧")
    Set ws2 = Worksheets("合格証")
    
    Dim lastRow As Long
    lastRow = ws1.Cells(ws1.Rows.Count, "B").End(xlUp).Row
    
    Dim i As Long
    For i = 3 To lastRow
        '発行条件
        If ws1.Cells(i, "D").Value >= 60 Then
            ws2.Copy After:=Worksheets(Worksheets.Count) '合格証発行
            With Worksheets(Worksheets.Count)
                .Name = ws1.Cells(i, "C").Value 'シート名
                .Range("C4").Value = ws1.Cells(i, "C").Value & " 様" '合格者名
            End With
        End If
    Next i
    
End Sub
1)[ws1,ws2]:シート情報を格納する用の変数を用意し"成績一覧"シートと"合格証"シートを設定する

2)[lastRow]:"成績一覧"シートの表のデータが入力されている最後の行番号を取得する
→「ws1.Cells(ws1.Rows.Count, "B")」で"成績一覧"シートのB列の最終行を選択し、「.End(xlUp)」で「Ctrl+↑」して移動して止まった位置の行番号「.Row」を取得する

3)[For~Next]:"成績一覧"シートのD列(点数)の値が60点以上のデータを3行目から「2)」で取得した行数まで確認する
→60点以上の場合は、「ws2.Copy After:=Worksheets(Worksheets.Count)」で"合格証"シートをコピーし、最後尾にシートを追加する
→コピーした最後尾のシート名を「.Name = ws1.Cells(i, "C").Value」で合格者の名前に変更し、合格証の合格者の名前を「Range("C4").Value = ws1.Cells(i, "C").Value」で"○○様(○○は合格者名)"という値に変更する

こちらの内容を実行すると、以下のように合格者にだけ合格証のシートが作成されます。

[補足] 発行されたシートのみを全て印刷したい場合は、合格証の最初のシート「増井星輝」を選択し、Shiftキーを押しながら最後のシート「野上将文」を選択します。
そのようにすると、以下のように一括で複数シートを選択することができます。

この状態で「Ctrl+P」などで印刷画面に移り、[設定]にて「作業中のシートを印刷」を選択することで、一括で印刷することができます。

2023/07/10
【ExcelVBA】ON・OFFボタンを開発

【ExcelVBA】ON・OFFボタンを開発

セルB2:C2に、以下のような「ON・OFFボタン」を開発してみました。

セルB2:C2のどちらかを選択すると、ONとOFFが切り替わるようになっています。
「ONの時にどうなるのか」といった機能は割り当てていませんが、上記の場合、「セルB2にONという文字が入力されている場合」という条件を使うことで、好みの機能を割り当てることはできます。

では、ON・OFFボタンの開発方法について解説していきます。

特定のシート上の特定のセルを操作した際に自動で処理を実行するには、シートモジュール上にコードを記述する必要があります。

>5つのモジュールの違いと使い分け

まず初めに、[開発]タブの中の[Visual Basic]を選択します。

開かれたエディター画面にて、[プロジェクト]から実装したいシートモジュールを選択します。
※「Option Explicit」は設定によっては表示されていないかと思いますが、特に問題ございません。
 プロジェクトウィンドウが表示されていない場合は、[表示]タブから表示できます。

次に、特定のセルを選択した際に、自動で処理を実行するためのイベントプロシージャを用意します。
下記のリストから[Worksheet]を選択します。

[Worksheet]を選択すると、以下のようなプロシージャが表示されるかと思います。
※他のプロシージャが表示される場合は、右側のリストより[SelectionChange]を選択してください。

このプロシージャが、該当するシート上のセルの選択が変更された際に自動で処理が実行されるイベントプロシージャになります。
実行時に選択されていたセルの情報は、引数のTargetに渡されます。

その情報を活用して開発していきます。

以下のように、記述します。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
    '1つのセルのみが選択されている場合
    If Target.CountLarge = 1 Then
        
        'セルB2もしくはC2が選択された場合
        If Target.Row = 2 And _
            (Target.Column = 2 Or Target.Column = 3) Then
            
            'セルB2の背景色が白色の場合
            If Range("B2").Interior.Color = RGB(255, 255, 255) Then
                Range("B2").Value = "ON"
                Range("C2").ClearContents
                Range("B2").Interior.Color = RGB(0, 255, 0)
                Range("C2").Interior.ColorIndex = 0
            Else
                Range("B2").ClearContents
                Range("C2").Value = "OFF"
                Range("B2").Interior.ColorIndex = 0
                Range("C2").Interior.Color = RGB(255, 0, 0)
            End If
            
        End If
    End If
    
End Sub

上記の内容は、以下のような処理になります。

1.選択されているセルが1つのみの場合に、次の処理を実行
2.選択されているセルの行番号が2で、列番号が2もしくは3の場合に、次の処理を実行
3.セルB2の背景色が無色(白色)の場合に、3-1の処理を実行、異なる場合は、3-2の処理を実行
3-1.セルB2の値を"ON"にし、セルC2の値を削除し、セルB2の背景色を緑色にし、セルC2の背景色を白色にする
3-2.セルB2の値を削除し、セルC2の値を"OFF"にし、セルB2の背景色を白色にし、セルC2の背景色を赤色にする

※無色と白色は異なります。無色にしたい場合は、以下のように記述します。

Range("XX").Interior.ColorIndex = 0

上記のコードを記述することで、ON・OFFを切り替えられるボタンを実装することができます。

▼サンプルファイル▼

2023/06/30
【Excel】クイックアクセスツールバーをブック単位で設定

【Excel】クイックアクセスツールバーをブック単位で設定

クイックアクセスツールバーとは、よく使う機能をすぐに使えるように自由に登録できるツールバーになります。
リボンの上もしくは下に表示されます。

以下の画面の場合は、上部に表示されています。

下部に表示したい場合は、クイックアクセスツールバー上で右クリックすると表示されるメニューより「クイックアクセスツールバーをリボンの下に表示」を選択します。

クイックアクセスツールバーが表示されていない場合は、リボン上で右クリックすると表示されるメニューより「クイックアクセスツールバーを表示する」を選択することで表示されます。

このクイックアクセスツールバーには、基本的な機能はもちろん、開発したマクロなども追加することができます。
基本はExcel自体に個々でカスタマイズするイメージが強いのですが、それぞれのExcelファイルに相応しいツールバーを設定することもできます。

クイックアクセスツールバーに追加したい機能は、リボン上の機能を右クリックすることでも追加することができますが、細かな機能の追加は、以下のメニューより「その他のコマンド」を選択することで追加できます。

選択することで、以下のようなExcelオプションの画面が表示されます。
この画面の左側に、存在する全ての機能一覧、右側に、クイックアクセスツールバーに追加されている機能一覧があります。

この画面の右側に関して「すべてのドキュメントに適用(既定)」と書かれた場所があります。
この設定内容が操作しているパソコンのExcel自体に設定されるツールバーになります。

ここで設定した内容は個々のパソコンのExcelのみの設定となるため、他のパソコンで開いた場合には同じ内容は表示されません。


実は、この「すべてのドキュメントに適用(既定)」という設定に関して、ブック単位の設定に変更することができます。
「すべてのドキュメントに適用(既定)」の部分を選択すると、リストになりブックが選択できるかと思います。

ブック単位で設定した機能は、それぞれのパソコンのExcelでの既定のクイックアクセスツールバーに加えて、全ての環境で表示されるようになっています。
そのため、「このExcelファイルでは、この機能をよく使う」などの場合は、対象のブック自体に設定すると便利です。

細かな機能やマクロの機能を追加したい場合は、左側の[基本的なコマンド]を選択し、リストから[すべてのコマンド]や[マクロ]などを選択することで設定することができます。

[マクロ]に関しては、開いているブック上に存在するプロシージャが表示されます。
以下の画面の場合は、シートモジュールに書かれたTest3、ブックモジュールに書かれたTest2、標準モジュールに書かれたTest1とTest4を設定することができます。
※モジュール自体に「Option Private Module」が設定されている場合や、Privateで定義されたもの、Functionで定義されたもの、引数が必要なものに関しては表示されません。

2023/06/28
【Excel】VBAとOfficeスクリプトのコードを比較(対象行の削除)

【Excel】VBAとOfficeスクリプトのコードを比較(対象行の削除)

Excelのマクロ開発に使われるプログラミング言語には、VBAとOfficeスクリプトがあります。
Officeスクリプトに関しては、2021年5月27日に一般公開された比較的新しい言語になります。

デスクトップ版のExcelでは、VBAでマクロ開発ができるのですが、Web版ではVBAを使うことができません。
そこでWeb版のExcelのマクロ開発用として登場したのが、Officeスクリプトになります。

現時点では、デスクトップ版のExcelでもOfficeスクリプトを使用することができるのですが、スクリプトファイルはExcelファイルとは別で、OneDrive上で管理する必要があります。
そのため、ネットに繋がっていないパソコンのExcelでは実行することができません。(2023年6月22日時点)

Officeスクリプトが使用できるライセンスは現時点では以下になります。

・Microsoft 365 Apps for business
・Microsoft 365 Business Standard
・Microsoft 365 Apps for enterprise
・Office 365 ProPlus for Devices
・Office 365 Enterprise E3
・Office 365 Enterprise E5
・Office 365 A3
・Office 365 A5

365でも家族向けのFamilyやPersonalではなく、一般法人向けである必要があるので、新規で登録する場合は注意する必要があります。

OfficeスクリプトはWeb業界では一般的なプログラミング言語「JavaScript」をベースとしています。
もう少し細かく解説すると、「JavaScript」をベースにMicrosoft社によって2014年頃に発表された「TypeScript」をベースとした言語になっています。

VBAを理解している方の場合は、比較的、簡単にOfficeスクリプトを理解できるかと思います。

こちらでは、そんなVBAとOfficeスクリプトのコードの違いを簡単に比較していきたいと思います。

今回、VBAとOfficeスクリプトで作成する内容は以下になります。

・A列に〇が入力されている行を削除する

VBAで開発した内容とOfficeスクリプトで開発した内容は以下になります。
アルゴリズム(仕組み)をVBAに寄せてOfficeスクリプトで開発しています。

処理の流れは以下になります。

1.アクティブシートの情報を取得(ws)
2.A列に〇が入力されている最終行の行番号を取得(lastRow)
→シート上のA列の最終行を選択し、「Ctrl+↑」で移動して選択した位置にあるセルの行番号を取得
3.対象の表の範囲を取得(rng)
4.繰り返し文(for)で、手順2で取得した最終行から表の先頭行までを繰り返し、A列に値が入力されている場合は、対象行(A列からC列)を削除して上に詰める

※あくまで一例のため、他の方法でも実現は可能になります。

比較すると、書き方は大きく異なってはいるのですが、全体の構造は似ているかと思います。
Officeスクリプトに挑戦してみたい方は、基礎コンテンツを用意しているため、ご確認ください。

>Officeスクリプトの基礎


コピーして活用できるようにコードを載せておきます。

Sub 対象行の削除()
    
    Dim sh As Worksheet
    Set sh = ActiveWorkbook.ActiveSheet
    
    Dim lastRow As Integer
    lastRow = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
    
    Dim rng As Variant
    rng = sh.Range(sh.Cells(1, 1), sh.Cells(lastRow, 1)).Value
    
    Dim i As Long
    
    For i = lastRow To 3 Step -1
        If rng(i, 1) <> "" Then
            sh.Range(sh.Cells(i, 1), sh.Cells(i, 3)).Delete Shift:=xlShiftUp
        End If
    Next i
    
End Sub
function main(workbook: ExcelScript.Workbook) {
    // Your code here

    const sh = workbook.getActiveWorksheet();
    var maxRow = sh.getRange('A:A').getRowCount();
    var lastRow = sh.getCell(maxRow - 1,0).getRangeEdge(ExcelScript.KeyboardDirection.up).getRowIndex() + 1;
    var rng = sh.getRangeByIndexes(0,0,lastRow,1).getValues();
    
    for (var i = lastRow - 1; i >= 2; i--){
        if (String(rng[i]) != ''){
            sh.getRangeByIndexes(i,0,1,3).delete(ExcelScript.DeleteShiftDirection.up);
        }
    }
}
2023/06/05
【ExcelVBA】ダブルクリックで塗りつぶしとリセットを繰り返す

【ExcelVBA】ダブルクリックで塗りつぶしとリセットを繰り返す

シート上の特定のセル範囲をダブルクリックするだけで、セルの背景色を黄色(黄色の際はリセット)する方法について解説しています。
こちらの内容を応用することで、塗りつぶしではなく、文字を変更したりすることも可能です。
※完成例は記事の最後にて配布しております。

では、以下の範囲(B2~B11)に適用していきます。

特定のシート上をダブルクリックするとプログラムが実行するようにするには、該当するシートモジュール上にプログラムを記述する必要があります。
[開発]タブから[Visual Basic]を選択します。

表示されたVBE(プログラムを記述するウィンドウ)のプロジェクトから、該当するシートをダブルクリックし選択します。
※プロジェクトが表示されていない場合は、[表示]タブの[プロジェクト エクスプローラー]を選択すると表示されます。

上記の操作で表示したものはシートモジュールと呼ばれるもので、シート単位で管理されているプログラムを管理する場所になります。
シートモジュール上の[General]から[Worksheet]を選択します。

ここで表示された「Private Sub Worksheet_SelectionChange]というものは、該当するシート上の選択しているセルが変更された場合に実行される特殊な「イベントプロシージャ」と呼ばれるものになります。
今回はダブルクリックした際に実行するようにしたいため、こちらは使用しません。

「Private Sub Worksheet_SelectionChange]を表示させると、右上に「SelectionChange」と表示されるかと思います。
ここから「BeforeDoubleClick」を選択します。


上記の操作で表示された「Private Sub Worksheet_BeforeDoubleClick」が、セルをダブルクリックすると実行される特殊なイベントプロシージャになります。
今回はこちらを使用します。

先ほどの「Private Sub Worksheet_SelectionChange」は使用しないため、削除して問題ございません。
また「Private Sub Worksheet_BeforeDoubleClick」内に以下のように記述します。
※Option Explicitは必要に応じて削除しても問題ございません。

Option Explicit

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    
    If Target.Row >= 2 And Target.Row <= 11 And Target.Column = 2 Then
        Cancel = True
        If Target.Interior.ColorIndex = xlNone Then
            Target.Interior.Color = RGB(255, 255, 0)
        Else
            Target.Interior.ColorIndex = xlNone
        End If
    End If
    
End Sub

簡単にプログラムの内容を解説します。
シート上をダブルクリックすると、「Private Sub Worksheet_BeforeDoubleClick」が実行されます。
また実行時に、「Target」にダブルクリックされたセル情報が入ってきます。

そのため、If文を活用し「Target.Row(ダブルクリックされたセルの行番号)」が2以上かつ11以下、「Target.Column(ダブルクリックされたセルの列番号)」が2(B列)の時に「If~End If」間の内容が実行されます。
実行時に「Cancel = True」で編集モードになるのを中断しています。

その次に、If文を活用し「Target.Interior.ColorIndex(ダブルクリックされたセルの背景色情報) = xlNone(無色:塗りつぶしなし)」でセルの背景色が無色の場合に「If~Else」間の内容が実行されます。
先ほどの条件を満たしていない場合は、「Else~End If」間の内容が実行されます。

そこで無色の場合は「Target.Interior.Color = RGB(255, 255, 0)」で背景色を黄色に、色が既に設定されている場合は「Target.Interior.ColorIndex = xlNone」で無色にしています。

シートモジュールを含む各モジュールについては下記にて解説しています。
>各モジュールの違いと使い分け

▼サンプルファイル▼

2023/05/18
【ExcelVBA】人数分の招待状を自動で印刷

【ExcelVBA】人数分の招待状を自動で印刷

以下の表の内容をもとに招待状を作成して印刷するという作業を自動化する方法について解説していきます。

まず初めに、できる限り数式を使って招待状を作成できるようにします。
今回の場合は、Noがキーになっているため、Noをもとに、他の氏名や性別が表示されるように以下のように作成します。

=OFFSET(招待者一覧!D2,C3,0) // フリガナ
=OFFSET(招待者一覧!C2,C3,0) // 氏名
=OFFSET(招待者一覧!E2,C3,0) // 性別

こちらではOFFSET関数を使っていますが、場合によってはVLOOKUP関数などでも対応できるかと思います。
今回の場合のOFFSET関数の使い方は以下になります。

=OFFSET(参照, 行数, 列数)
// 参照セルから指定の行数・列数移動した位置のセルの情報を返す
=OFFSET(招待者一覧!D2,C3,0) // フリガナ
// 招待者一覧シートのセルD2を基準にセルC3の数分下へ移動したセルの情報を返す

次に、VBAを使って、Noの値を変更しつつ、招待状シートを印刷します。

[開発]タブの中から[マクロ]を選択し、好みの名前でプログラムを作成します。

こちらでは以下のようなプログラムを作成しています。

Sub 自動印刷()
    
    Dim 開始No As Long: 開始No = 1
    Dim 終了No As Long: 終了No = 20
    
    Dim i As Long
    
    For i = 開始No To 終了No
        Worksheets("招待状").Range("C3").Value = i
        Worksheets("招待状").PrintOut
    Next i
    
End Sub

今回の場合、Noは1からの連番なので、招待状シートのセルC3の値を開始Noから終了Noまで順番に実行しています。
それぞれのNoをセルC3に設定した後に、招待状シートをPrintOutで印刷しています。

このPrintOutは設定されている印刷設定の内容をもとに実行されます。
そのため、こちらのプログラムを実行する前に、印刷設定にて、プリンターや余白などの設定を行う必要があります。

必要に応じてプログラムの一部を変更する必要がありますが、基本はこのようなアルゴリズムで自動化することができます。

▼サンプルファイル▼

2023/05/03
【ExcelVBA】データ登録フォームを開発する

【ExcelVBA】データ登録フォームを開発する

データ登録フォームをVBAを使って開発する場合は、基本的に以下のパターンになります。
※今回の内容は、記事の最後にて配布しています。

①登録フォームを用意する
→今回は簡単に解説するため、同じシート内の1~2行目に用意しています。

②[開発]タブから[マクロ]を選択し、好みの名前で作成する

③以下のコードを入力する

Sub テータ登録()
    
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, "A").End(xlUp).Row + 1
    
    Cells(lastRow, "A").Value = WorksheetFunction.Max(Columns(1)) + 1
    Range(Cells(lastRow, "B"), Cells(lastRow, "C")).Value = Range("B2:C2").Value
        
    Range("B2:C2").ClearContents
    
End Sub

簡単に解説します。

最初の「Dim」は一時的な値を格納する用の部屋を用意しています。(変数宣言)
「lastRow」は作成する部屋の名前(変数名)で、「As Long」が部屋の種類(変数の型)の指定で「Long」という部屋は整数を入れる用の部屋になります。

「lastRow = Cells(Rows.Count, “A”).End(xlUp).Row + 1」の「Cells(Rows.Count, “A”).End(xlUp).Row + 1」はA列の値が入力されている最終行の1つ下の行番号を取得しています。
その番号を「lastRow」に格納しています。

セルの指定方法はCells(行番号,列番号)とRange(アドレス)、Range(開始のセル情報, 終了のセル情報)などがあります。
「=」で結んでいる場所は、「右辺を左辺に代入する」という意味で読んでいただければと思います。
IF文などの中で使われる場合は、「等号」としての意味になります。

「WorksheetFunction.Max(Columns(1)) + 1」で1列目(A列)の数値の最大値に1を加えた値を取得し、「lastRow」行目のA列に入力しています。

「Range(Cells(lastRow, “B”), Cells(lastRow, “C”)).Value = Range(“B2:C2”).Value」で登録フォーム(B2:C2)の値を「lastRow」行目のB列からC列に入力しています。

最後、「Range(“B2:C2”).ClearContents」で登録フォーム(B2:C2)の値を削除しています。

④[開発]タブの[挿入]からボタンを作成する

※作成したボタンを編集する場合は、Ctrlキーを押しながらクリックします。

基本は、このようなパターンが多いです。
後は、登録フォームをユーザーフォームにしたりとアレンジしていきます。

VBAの基本的な構文に関しては以下にまとめています。

>Excel基礎(VBA)

▼サンプルファイル▼

2023/04/18
【ExcelVBA】VBA開発でインデントが重要な理由

【ExcelVBA】VBA開発でインデントが重要な理由

VBAを始めたばかりの方によくあることですが、以下のようにインデント(字下げ)がないコードをたまに見ます。

このような書き方は本当によくないです。
この処理を日本語で表現すると以下のようになります。

機能[Sample]は、1行目から1行ずつ繰り返してその中でA列の値がTrueの場合はB列に〇を入力するという作業を100行目まで繰り返して終了する。

この文章に関して、若干読みにくいと感じられた方は多いかと思います。
その理由は、一文が長くて句読点が少ないからです。

VBAのコードは、「Subで始まったらEnd Subで終わる」「Forで始まったら、Nextまで繰り返す」「Ifで始まったら、End Ifで終わる」というような要素の入れ子になっています。
この入れ子が、ぱっと見で分からない書き方は、保守的であるとは言えません。

このコードに対して、エラーが発生した場合や、機能を追加したい場合、どこを修正すべきなのかが分かりにくいからです。
例えば、この機能に「A列の値がTrueの場合はC列に×を入力する」という機能を追加する場合、どこに追加すべきなのかが直感的に分かりにくいです。

では、どうしたらよいのかというと、入れ子になる場合は、インデント(字下げ)を行うことです。
※インデントは、Tabキーを押すことで半角スペースが4つ入力されます。(デフォルト設定の場合)

以下のようにするだけでも、見やすさは天と地の差があります。

この処理を日本語で表現すると以下のようになります。

機能[Sample]というものがある。
この機能は、1行目から100行目まで1行単位で以下の処理を行う。
・対象行のA列の値がTrueの場合は、対象行のB列に〇を入力する

1つ1つの文章が短くなり、比較的読みやすい文章かと思います。


[補足] プログラミング言語のPythonでは、インデントがないと正しく実行できません。
そのくらいインデントを行うことは、プログラミングをする方にとって重要になります。

逆に言えば、インデントの有無を見るだけで、プログラミングの経験値が瞬時に分かります。

「毎回VBAで開発してくれているから、あの方はVBAができる人だ!」と思っていた人でも、蓋を開ければ、サイトからのコピペのみで本人は半分以上理解できていないというケースがあります。
このケースの場合、ほとんどがインデントが正しくないです。
このようなシステムを使い続けるのは、かなり危険です。(データの紛失や個人情報の漏洩など)

VBAに限らず、プログラミングを行う場合は、インデントを意識する必要があります。

2023/03/27
【ExcelVBA】マークのある行を削除する

【ExcelVBA】マークのある行を削除する

以下のようなシートを用意し、B列に”〇”が入力されている行を削除するマクロの作成方法について解説していきます。

まず初めに、B列に”〇”が簡単に入力できるようにドロップダウンリストを作成します。
対象の範囲を選択して、[データ]タブ内の[データの入力規則]にて下記のように設定します。
※入力値の種類を[リスト]にして、元の値に”〇”を入力しています。

これだけでドロップダウンリストの完成です。

では、本題のマクロを開発します。
[開発]タブの中の[マクロ]を選択し、”DeleteRow”という名前で作成します。
※名前は仮です。

プログラムを記述する画面が表示されましたら、以下の内容を記述します。

Sub DeleteRow()
    
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, "B").End(xlUp).Row 'B列の最終行番号を取得
    
    Dim i As Long
    
    For i = lastRow To 3 Step -1 '最終行から3行目まで順番に繰り返す
        If Cells(i, "B").Value <> "" Then 'i行目のB列の値が空白でない場合
            Rows(i).Delete 'i行目の削除
        End If
    Next i
    
End Sub

行を削除すると、行数がずれてしまうため、その対策として最終行から上に向かってB列が空白でないセルを探しています。


最後にボタンを作成します。
[開発]タブの中の[挿入]よりボタンを作成します。(フォームコントロール内のボタン)

作成すると[マクロの登録]が表示されるので、先ほど作成した”DeleteRow”を登録します。

※ボタンの作成後は、クリックすると実行されてしまいます。
 Ctrlキーを押しながらクリックするとボタンを編集できます。

これで完成です。

▼サンプルファイル▼

2023/03/08
【ExcelVBA】ActivateとSelectの違い

【ExcelVBA】ActivateとSelectの違い

VBAの以下の違いについて解説していきます。

Range("A1").Select
Range("A1").Activate

Worksheets("Sheet1").Select
Worksheets("Sheet1").Activate

答えから言うと、単体のセルに対して行う場合は大きな違いはありません。
ただ、複数のセルやシートを選択している場合は、この2つの違いを意識する必要があります。

複数のセルを選択すると、以下のように、白い箇所とグレーの箇所が出てくると思います。

この選択範囲内の白いセルが、アクティブセルで、グレーのセルが、ただ選択されているセルになります。

シートの場合は、選択されているシート全体が白くなります。
しかし、表示されているシートは、選択されているシートのどれか1つかと思います。

以下の場合は、Sheet1が表示されています。

この表示されているシートがアクティブシートになります。

なので、複数選択の際にActivateかSelectかの違いが重要になります。
動作の違いをセルとシートに関してそれぞれ載せておきます。

セルの場合

シートの場合

[補足] ちなみに複数のシートを選択する場合は、以下のように記述します。

Worksheets(Array("Sheet1", "Sheet2", "Sheet3")).Select
// Sheet1,Sheet2,Sheet3はシート名