2025/01/24
【Excel】ドロップダウンリストで複数選択可能にする

【Excel】ドロップダウンリストで複数選択可能にする

Excelでは現状、ドロップダウンリストから1つの項目しか選択できませんが、工夫することで複数選択が可能になります。
本記事では、その設定方法について詳しく解説していきます。


完成イメージ

作成するドロップダウンリストのイメージは以下になります。

① 何も入力されていない時は1つの項目のみ表示される

② 1つの項目を選択した後にリストを展開すると2つ目の項目が表示される

③ 以降、最大で5つまで指定することができる


手順1: 複数選択時の候補を準備する

こちらでは、以下のセルB3からセルB11に、複数選択可能なドロップダウンリストを作成していきます。

まずは、ドロップダウンリストの候補となる値をセルF2から横方向に並べます。
※必要に応じてセルの位置は変更してください。

次に、B列のドロップダウンリストの候補に表示させる値をセルF3以降に表示させていきます。

表示させる値は、B列のドロップダウンリストに入力した値によって変化させます。
例えば、セルB3が空の場合は、セルF3からJ3に「1」、「2」、「3」、「4」、「5」と表示させます。
次に、セルB3に「2」が入力された場合は、セルF3からJ3に「2,1」、「(空)」、「2,3」、「2,4」、「2,5」と表示させます。
更に、セルB3に「2,4」が入力された場合は、セルF3からJ3に「2,4,1」、「(空)」、「2,4,3」、「(空)」、「2,4,5」と表示させます。

このように、ドロップダウンリストから値が選択される度、ドロップダウンリストに表示させる値に選択していない値を追加して、複数選択を実現していきます。 その仕組みを実現する数式は、以下になります。

=IFS($B3="",F$2,IFERROR(FIND(F$2,$B3),0),"",TRUE,$B3&","&F$2)
// $B3="",F$2:セルB3が空の場合に通常の候補(F2)を返す(B列と2行目を「$」で固定)
// IFERROR(FIND(F$2,$B3),0),"":セルB3にセルF2の値が含まれている場合に空("")を返す(2行目とB列と「$」で固定)
// ※FIND関数で特定の文字が含まれているかどうかを確認、含まれている場合は、その文字が含まれている位置情報(先頭からの通し番号)を返し、含まれていない場合は、エラーを返す
//  IFERROR関数で、FIND関数がエラーの時に「0」を返す
//  条件式では「0」がFALSE(偽)、「0」以外の数値がTRUE「真」とされる
// TRUE,$B3&","&F$2:それ以外の場合にセルB3とセルF2の値をカンマで結合して返す(B列と2行目を「$」で固定)

この数式をセルF3に入力し、必要な範囲にコピーします。

このようにして、各行に対する候補を表示することができました。
試しに、B列に適当な値を入力することで、数式の結果が変化することが確認できます。

ExcelVBAレベル確認

手順2: データの入力規則を設定する

最後に、数式で作成した候補をドロップダウンリストとして設定していきます。

まずはドロップダウンリストを設定する範囲を選択し、[データ]タブの中の[データの入力規則]を選択します。

表示される以下の設定画面にて、[入力値の種類]を[リスト]にし、[元の値]に以下の数式を入力します。

=$F3:$J3
// 行番号を相対的に変化させる必要があるため、行番号の「$」を外す

以上の設定をして確定することで、複数選択を可能としたドロップダウンリストを作成することができます。

2025/01/17
【ExcelVBA】自動で書類の発行日とお支払い期限を設定

【ExcelVBA】自動で書類の発行日とお支払い期限を設定

以下の請求書の書類フォーマットに関して、セルB7の件名を入力すると同時に、セルG4の発行日とセルC12のお支払い期限を自動入力する仕組みの実現方法について解説していきます。

※こちらで開発したファイルは記事の最後にて配布しています。


1. 開発準備

シートで特定のセルが編集されたときに処理を実行するには、「シートモジュール」を使用します。これにより、指定したセルが変更されると同時に処理が行われます。
シートモジュールは、該当するシートのタブ上で右クリックし、[コードの表示]を選択することで表示することができます。

選択すると、以下のエディタ画面(VBE)が表示されます。
また、該当するシートのシートモジュールが表示された状態になります。
「Option Explicit」は、VBEの設定内容次第では表示されません。「Option Explicit」についての解説はこちらでは省略します。

次に、該当するシートのセルに値を入力すると同時に処理が実行される特殊なプロシージャ(イベントプロシージャ)を用意する必要があります。
そのためには、シートモジュールの左上のリストから「Worksheet」を選択します。

「Worksheet」を選択すると、自動で「Worksheet_SelectionChange」というプロシージャが表示されます。
このプロシージャは、該当するシート上のいずれかのセルが選択されると同時に処理が実行されるイベントプロシージャと呼ばれるものになります。

ただ、今回使用するイベントプロシージャは、セルに値を入力すると同時に処理が実行されるものになります。
そのため、右上のリストから「Change」を選択します。

表示された「Worksheet_Change」というプロシージャを活用します。
「Worksheet_SelectionChange」というプロシージャに関しては削除して問題ないです。


2. コードの記述

以下のコードを記述します。

Private Sub Worksheet_Change(ByVal Target As Range)
    
    If Target.Address = "$B$7" Then
        
        Dim d1 As Date
        Dim d2 As Date
        d1 = Date
        d2 = DateSerial(Year(d1), Month(d1) + 2, 0)
        
        Range("G4").Value = d1
        Range("C12").Value = d2
        
    End If
    
End Sub

では、コードについて解説していきます。

Private Sub Worksheet_Change(ByVal Target As Range)
    
    If Target.Address = "$B$7" Then
        '省略
    End If
    
End Sub

「Worksheet_Change」というプロシージャの引数の「Target」に、編集されたセルの情報が渡されるため、そのセルの情報から、表の対象のセルが編集されたのかどうかを確認しています。
こちらでは、件名を入力するセルB7が編集されたかどうかを判定しています。

この条件を満たした場合に関してのみ、Ifの中の処理を実行します。

        Dim d1 As Date
        Dim d2 As Date
        d1 = Date
        d2 = DateSerial(Year(d1), Month(d1) + 2, 0)
        
        Range("G4").Value = d1
        Range("C12").Value = d2

先ほどの条件を満たしたときに、発行日(セルG4)とお支払い期限(セルC12)のセルに日付を入力します。
こちらでは、発行日に本日の日付、お支払い期限に翌月末の日付を入力しています。
本日の日付はDateで取得することができ、翌月末はDateSerialを活用して、翌々月の0日、即ち、翌々月の1日の1日前で翌月末の日付を取得しています。

以上の内容で実現できます。
セルB7の件名を入力することで、発行日とお支払い期限が入力されます。

※実行日は2025/1/8になります。

▼サンプルファイル▼

2025/01/10
【ExcelVBA】データ変更と同時にピボットテーブルを自動更新

【ExcelVBA】データ変更と同時にピボットテーブルを自動更新

通常、ピボットテーブルは、元の表を更新したら、ピボットテーブル自体を更新しなければ反映されません。
そのため、元の表のデータを高頻度で変更する場合、毎回ピボットテーブルを更新するのは、少し手間になります。
そこで、こちらでは、元の表のデータの変更と同時に、ピボットテーブルを自動で更新する仕組みの実現方法について解説していきます。

※こちらで仕組みを取り入れたファイルは、記事の最後にて配布しています。


事前準備

仕組みを実現する前に、ピボットテーブルが用意されているシート名とピボットテーブルの名前を確認します。
ピボットテーブルの名前は、対象のピボットテーブルを選択した時に表示される[ピボットテーブル分析]タブから確認することができます。

こちらでは、「ピボットテーブル1」という作成時の名前をそのまま活用していきますが、必要に応じて分かりやすい名前に変更した方が良いです。

ExcelVBAレベル確認

開発準備

今回の仕組みは、「対象の表を編集すると同時に、対象のピボットテーブルを更新する」というものです。
このように、「特定のセルが編集されると同時に、何かしらの処理を実行する」という仕組みは、該当するシートモジュールイベントプロシージャを活用することで実現できます。

シートモジュールは、該当するシートのタブ上で右クリックし、[コードの表示]を選択することで表示することができます。

選択すると、以下のエディタ画面(VBE)が表示されます。
また、該当するシートのシートモジュールが表示された状態になります。
「Option Explicit」は、VBEの設定内容次第では表示されません。「Option Explicit」についての解説はこちらでは省略します。

次に、該当するシートのセルを編集すると同時に処理が実行される特殊なプロシージャ(イベントプロシージャ)を用意する必要があります。
そのためには、シートモジュールの左上のリストから「Worksheet」を選択します。

「Worksheet」を選択すると、自動で「Worksheet_SelectionChange」というプロシージャが表示されます。
このプロシージャは、該当するシート上のいずれかのセルが選択されると同時に処理が実行されるイベントプロシージャと呼ばれるものになります。

ただ、今回使用するイベントプロシージャは、セルを編集すると同時に処理が実行されるものになります。
そのため、右上のリストから「Change」を選択します。

表示された「Worksheet_Change」というプロシージャを活用します。
「Worksheet_SelectionChange」というプロシージャに関しては削除して問題ないです。


コードの記述

以下のコードを記述します。

Private Sub Worksheet_Change(ByVal Target As Range)
    
    If Target.Row >= 2 And _
        Target.Column >= 1 And _
        Target.Column <= 4 Then
        
        Worksheets("売上一覧") _
            .PivotTables("ピボットテーブル1") _
            .PivotCache.Refresh
        
    End If
    
End Sub

では、コードについて解説していきます。

Private Sub Worksheet_Change(ByVal Target As Range)
    
    If Target.Row >= 2 And _
        Target.Column >= 1 And _
        Target.Column <= 4 Then
        
        '処理
        
    End If
    
End Sub

「Worksheet_Change」というプロシージャの引数の「Target」に、編集されたセルの情報が渡されるため、そのセルの情報から、対象の表が編集されたかどうかを確認しています。
※今回のコードでは、複数のセルが同時に編集される場合を考慮していません。

こちらでは、「2行目以上、尚且つ、1列目から4列目の間のセル」と対象の表のデータ範囲が編集されたかどうかを確認しています。

この条件を満たした場合に関してのみ、Ifの中の処理を実行します。

        Worksheets("売上一覧") _
            .PivotTables("ピボットテーブル1") _
            .PivotCache.Refresh

こちらで、「売上一覧」シートにある「ピボットテーブル1」という名前のピボットテーブルを更新しています。

以上の内容で実現できます。
元の表のデータの変更と同時に、ピボットテーブルが自動で更新されることが確認できます。

▼サンプルファイル▼

2025/01/03
【Excel】完全一致のデータを自動で色付け

【Excel】完全一致のデータを自動で色付け

以下のような表で、全ての項目が一致するデータが入力された時のみに、行全体を色付けする方法について解説していきます。


1つの項目に同じデータが入力された時に対象のセルを色付け

まず初めに、1つの項目のみで判定する方法について解説していきます。
特定の条件を満たしたセルのみを色付けする場合は、『条件付き書式』を活用します。
条件付き書式には、予め「重複した値を色付けする」という設定が用意されていますが、こちらの設定は複数列の場合に対応できないため、あえて条件式を作成して実現していきます。

条件式を作成する場合、色付けしたい行のみに「TRUE」が表示される数式を作成する必要があります。

例えば、商品名の項目のみで判定する場合、以下の数式を作成することで、先頭行(セルC3)に対して、同じ商品名の行のみに「TRUE」と表示することができます。

=C3:C20=C3
// 表の範囲を3~20行とした場合

この数式の結果のTRUEの数を集計することが出来れば、その行(セルC3の行)が重複しているのかどうかを判定することができます。
実は、TRUEという値は「1」、FALSEという値は「0」として管理されています。
そのため、「*」や「+」などの演算子を用いることで、数値として表示することができます。

=(C3:C20=C3)*1

後は、数値をSUM関数で以下のように合計するだけで、TRUEの数を求めることができます。

=SUM((C3:C20=C3)*1)

この数式の表の範囲のみを「$」で固定して、他の行にコピーし、重複している商品名の行のみに2以上の数値が表示されることを確認します。

=SUM(($C$3:$C$20=C3)*1)
// コピーする際に表の範囲が移動しないように「$」で固定する

ただ、このままですと、空白の行に関しても、2以上の数値が表示されてしまいます。
そのため、空白の行に関してはカウントしないように、「$C$3:$C$20=C3」という条件に「商品名が空白でない」という条件を加えます。
「尚且つ」という条件を加える場合は、「*」で条件式を掛けるだけで実現できます。

=SUM(($C$3:$C$20=C3)*($C$3:$C$20<>""))
// 「*1」は不要になる

このような数式を作成することができましたら、先頭に入力した以下の数式のみをコピーし、条件付き書式にて設定していきます。

=SUM(($C$3:$C$20=C3)*($C$3:$C$20<>""))

上記の数式は、セルC3に対する数式のため、セルC3を基準に対象の範囲を選択します。

次に、[ホーム]タブの[条件付き書式]から[新しいルール]を選択します。

次に、以下の画面で[ルールの種類]を[数式を使用して書式設定するセルを決定]にし、表示されたテキストボックス内に、先ほどコピーした数式を貼り付け、「1より大きい場合」という条件を加えます。
※条件付き書式に設定した数式は、選択範囲の基準のセルから他の選択範囲に相対参照で反映されます。(「$」が付いている参照は絶対参照になります。)

=SUM(($C$3:$C$20=C3)*($C$3:$C$20<>""))>1

後は、好みの書式を[書式]から設定します。

以上の設定で確定することによって、以下のように、商品名で同じ値が入力されているセルのみに色付けすることができました。


全ての項目が一致するデータが入力された時に行全体を色付け

先ほどの手順と同様に、次は、全ての項目が一致するデータの数を求める数式を作成します。

その際は、以下のように、他の項目に対しての条件も「*」で加えます。

=SUM(($B$3:$B$20=B3)*($C$3:$C$20=C3)*($D$3:$D$20=D3)*($C$3:$C$20<>""))
// 色の反映に関しては商品名が入力されている前提とする:$C$3:$C$20<>""

こちらの数式を、先ほどと同じ手順で条件付き書式に設定していくのですが、今後は単体の列ではなく、表全体の列を色付けしたいです。
そのような際は、以下のように、数式の列の参照を固定する必要があります。

=SUM(($B$3:$B$20=$B3)*($C$3:$C$20=$C3)*($D$3:$D$20=$D3)*($C$3:$C$20<>""))

では、数式を条件付き書式に設定していきます。
上記の数式は、表の先頭行(3行目)を基準とした数式になります。
そのため、表の先頭行(3行目)を基準として表全体を選択します。

次に、[ホーム]タブの[条件付き書式]から[新しいルール]を選択し、[ルールの種類]を[数式を使用して書式設定するセルを決定]にして、表示されたテキストボックス内に、先ほどの数式を貼り付け、「1より大きい場合」という条件を加えます。
書式に関しても設定します。

=SUM(($B$3:$B$20=$B3)*($C$3:$C$20=$C3)*($D$3:$D$20=$D3)*($C$3:$C$20<>""))>1

上記の設定で確定することによって、全ての項目が一致するデータの行のみを自動で色付けすることができます。

2024/12/27
【便利】必要なデータの必要な項目のみを瞬時にコピー

【便利】必要なデータの必要な項目のみを瞬時にコピー

#For #If #Selection #Application #Union #Copy

※サイト内の限定動画です。

表の中の必要なデータ(行)の必要な項目(列)のみを瞬時に選択し、コピーする機能の開発方法について解説しています。

こちらではVBAにより開発していますが、VBAを使いたくない場合は、以下のコンテンツが参考になります。
>不要な列(行)を除いて一括コピー

00:00 挨拶
00:58 完成イメージ
01:44 準備
02:09 作成(パターン1)
12:04 作成(パターン2)
13:24 作成(実行ボタン)
14:22 完成
14:58 プログラムの全体
18:03 まとめ

▼準備ファイル▼

2024/12/27
【ExcelVBA】複数シートの表を1つにまとめる

【ExcelVBA】複数シートの表を1つにまとめる

以下のように、複数シートの表(従業員別の1日の予定表)を、ボタンを押すだけで1つの表にまとめる機能の開発方法について解説していきます。

※こちらで開発したファイルは、記事の最後にて配布しています。


開発準備

まず初めに、[開発]タブを選択し、[マクロ]を選択します。

表示された以下の画面にて、開発する機能の名前を入力し、[作成]を選択します。
こちらでは、「getSchedule」と入力しています。

次に表示される以下の画面の「Sub ○○」から「End Sub」の間にコードを記述します。

ExcelVBAレベル確認

コードの記述

以下のコードを記述します。

Sub getSchedule()
    
    Dim mWs As Worksheet
    Set mWs = Worksheets("全員")
    
    Dim ws As Worksheet
    Dim i As Long
    
    mWs.Range("B4:B33").ClearContents
    
    For i = 4 To 33
        For Each ws In Worksheets
            If ws.Name <> mWs.Name Then
                If ws.Cells(i, "B").Value <> "" Then
                    mWs.Cells(i, "B").Value = _
                        mWs.Cells(i, "B").Value & _
                        ws.Name & ":" & ws.Cells(i, "B").Value & vbLf
                End If
            End If
        Next ws
    Next i
    
End Sub

では、コードについて解説していきます。

    Dim mWs As Worksheet
    Set mWs = Worksheets("全員")

集約するシート情報を変数「mWs」に割り当てています。

    Dim ws As Worksheet
    Dim i As Long

繰り返し処理で扱う変数を定義しています。
変数「ws」は各シートを繰り返す際に活用し、変数「i」は各行を繰り返す際に活用します。

    For i = 4 To 33
        '処理
    Next i

Forでの予定表の先頭行から最終行までを繰り返しています。

        For Each ws In Worksheets
            If ws.Name <> mWs.Name Then
                '処理
            End If
        Next ws

繰り返し処理の内側のFor Eachでは、ブックに存在するシート1つ1つの情報を順番に変数「ws」に割り当てて、「全員」シート以外の場合に内側の処理を実行するように記述しています。

                If ws.Cells(i, "B").Value <> "" Then
                    mWs.Cells(i, "B").Value = _
                        mWs.Cells(i, "B").Value & _
                        ws.Name & ":" & ws.Cells(i, "B").Value & vbLf
                End If

最深部では、「全員」シート以外の各シートに対し、対象行(i)の予定の有無を確認しています。
先頭のIfで予定が存在しているかどうかを確認し、予定が存在している場合に、「全員」シートに追加するように記述しています。
「全員」シートに、元々の予定に加え、対象シート(ws)の対象行(i)の予定と改行(vbLf)を加えるように記述しています。


ボタンの作成

コードが完成しましたら、「全員」シートに実行用のボタンを用意します。
ボタンは、[開発]タブの中の[挿入]から作成することができます。


完成

以上の手順で、機能が完成します。
実行することで、以下のように、複数シートの予定の内容を「全員」シートにまとめて表示することができます。

▼サンプルファイル▼

2024/12/26
【便利】集計できる形に結合を解除する機能

【便利】集計できる形に結合を解除する機能

#セル結合 #アドイン #TypeName #Selection #MergeCells #MergeArea #UnMerge #Item

※サイト内の限定動画です。

セル結合されている範囲の結合を解除すると、先頭のセル以外の値が空白になります。
こちらの機能を開発することによって、結合解除時に空白のセルにも同じ値を設定することができます。
また、開発した機能を、アドインとしてExcelの標準機能に加える方法についても解説しています。

00:00 挨拶
00:58 完成イメージ
02:35 準備
03:02 作成(結合解除機能)
13:44 アドインの保存
14:56 アドインの設定
17:20 完成
19:15 プログラムの全体
21:31 まとめ

▼準備ファイル▼

2024/12/20
【ExcelVBA】簡単なマウス操作のみで販売数を入力

【ExcelVBA】簡単なマウス操作のみで販売数を入力

野外イベントなどで販売数を管理しながら受付業務を行う際、商品が購入される度、販売数の数値を直接入力するのは大変です。
そのため、こちらでは、特定の商品の販売数のセルをダブルクリックするだけで、その販売数に1を加えることができる機能を開発していきます。
また、何かしらの原因でデータが紛失しないように、販売数を加算する度、自動で保存される機能も加えていきます。

こちらでは、以下の商品ごとの販売数を管理した表を活用して開発していきます。

※こちらで開発したファイルは記事の最後にて配布しています。


開発準備

「特定のセルをダブルクリックすると同時に、何かしら処理を実行する」という仕組みは、該当するシートモジュールイベントプロシージャを活用することで実現できます。

シートモジュールは、該当するシートのタブ上で右クリックし、[コードの表示]を選択することで表示することができます。

選択すると、以下のエディタ画面(VBE)が表示されます。
また、該当するシートのシートモジュールが表示された状態になります。
「Option Explicit」は、VBEの設定内容次第では表示されません。「Option Explicit」についての解説はこちらでは省略します。

次に、該当するシートのセルをダブルクリックすると同時に処理が実行される特殊なプロシージャ(イベントプロシージャ)を用意する必要があります。
そのためには、シートモジュールの左上のリストから「Worksheet」を選択します。

「Worksheet」を選択すると、自動で「Worksheet_SelectionChange」というプロシージャが表示されます。
このプロシージャは、該当するシート上のいずれかのセルが選択されると同時に処理が実行されるイベントプロシージャと呼ばれるものになります。

ただ、今回使用するイベントプロシージャは、セルがダブルクリックされると同時に処理が実行されるものになります。
そのため、右上のリストから「BeforeDoubleClick」を選択します。

表示された「Worksheet_BeforeDoubleClick」というプロシージャを活用します。
「Worksheet_SelectionChange」というプロシージャに関しては削除して問題ないです。


コードの記述

以下のコードを記述します。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    
    If Target.Column = 3 And _
        Target.Row >= 3 And _
        Target.Row <= 20 Then
        
        Cancel = True
        Target.Value = Target.Value + 1
        ThisWorkbook.Save
        
    End If
    
End Sub

では、コードについて解説していきます。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    
    If Target.Column = 3 And _
        Target.Row >= 3 And _
        Target.Row <= 20 Then

        '省略

    End If
    
End Sub

「Worksheet_BeforeDoubleClick」というプロシージャの引数の「Target」に、ダブルクリックされたセルの情報が渡されるため、そのセルの情報から、表の対象の範囲内がダブルクリックされたのかどうかを確認しています。
こちらでは、「3列目、尚且つ、3~20行目の間のセル」と販売数のセルの範囲内がダブルクリックされたかどうかを確認しています。

この条件を満たした場合に関してのみ、Ifの中の処理を実行します。

        Cancel = True
        Target.Value = Target.Value + 1
        ThisWorkbook.Save

セルをダブルクリックすると、通常、セルが編集モードになるのですが、引数の「Cancel」をTrueにすることで、編集モードにならなくなります。
その後、ダブルクリックされたセルの値に1を加えて、ブックを保存しています。

以上の内容で実現できます。
販売数のセルをダブルクリックすることで、ダブルクリックされたセルの値に1を加えて、ブックが保存されます。

▼サンプルファイル▼

2024/12/13
【ExcelVBA】データを入力する度に自動で並べ替え

【ExcelVBA】データを入力する度に自動で並べ替え

以下の表では、氏名を入力した後にクラスを入力するだけで、自動で該当するクラスの位置に移動するようになっています。

このような、特定の項目に値を入力すると同時に、その項目を基準に自動で並べ替えするという機能の開発方法について解説していきます。
※こちらで開発したファイルは記事の最後にて配布しています。


開発準備

「特定のセルに値を入力すると同時に、何かしら処理を実行する」という仕組みは、該当するシートモジュールイベントプロシージャを活用することで実現できます。

シートモジュールは、該当するシートのタブ上で右クリックし、[コードの表示]を選択することで表示することができます。

選択すると、以下のエディタ画面(VBE)が表示されます。
また、該当するシートのシートモジュールが表示された状態になります。
「Option Explicit」は、VBEの設定内容次第では表示されません。「Option Explicit」についての解説はこちらでは省略します。

次に、セルに値を入力すると同時に処理が実行される特殊なプロシージャ(イベントプロシージャ)を用意する必要があります。
そのためには、シートモジュールの左上のリストから「Worksheet」を選択する必要があります。

次に、隣のリストから「Change」を選択します。

「Change」を選択すると表示される「Worksheet_Change」というプロシージャ内にコードを記述します。
他のプロシージャに関して、使用していない場合は削除して問題ないです。


コードの記述

以下のコードを記述します。

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Dim rng As Range
    For Each rng In Target
        If rng.Column = 2 Then
            Range("B2").Sort _
                Key1:=Range("B2"), _
                Order1:=xlAscending, _
                Header:=xlYes
        End If
    Next rng
    
End Sub

では、コードについて解説していきます。

Private Sub Worksheet_Change(ByVal Target As Range)

「Worksheet_Change」というプロシージャは、該当するシートのセルが編集されると同時に実行されます。
その際、編集されたセルの情報が引数の「Target」に渡されます。
引数の「Target」を活用して、今回の場合は、クラスの項目(列)が編集されたかどうかを判断し、編集された場合に、その項目(列)を基準に昇順に並べ替えを行います。

    Dim rng As Range
    For Each rng In Target
        If rng.Column = 2 Then
            '省略
        End If
    Next rng

今回の場合、同時に編集されたセルは1つであることが多いかと思いますが、複数セルが同時に編集することもあります。(コピー&ペーストやCtrlキーを押しながらの同時入力など)
複数セルを同時に編集した場合は、引数の「Target」に複数セルの情報が渡されます。
そのため、複数セルの同時入力を考慮し、「Target」のセルの情報をFor Eachで1つずつを変数「rng」に渡して確認しています。

次に、変数「rng」の列番号が2、即ち、B列のクラスの項目の位置であることを確認しています。B列の場合のみに次の処理を実行します。
※必要に応じて「行番号が3以上の場合」などといった条件を加えても良いです。

            Range("B2").Sort _
                Key1:=Range("B2"), _
                Order1:=xlAscending, _
                Header:=xlYes

こちらで、セルB2が含まれる表に対し、「Sort」で並べ替えを行っています。
「Key1:= Range(“B2”)」でセルB2の属する列を並べ替えの基準の列として指定し、「Order1:=xlAscending」で昇順を指定、「Header:=xlYes」で項目名を含む範囲ということを指定しています。

以上の内容で実現できます。
クラスの項目に値を入力すると同時に、自動で並べ替えられます。

▼サンプルファイル▼

2024/12/06
【ExcelVBA】複数シートの表に一括反映

【ExcelVBA】複数シートの表に一括反映

以下のように、同じ形式の予定表が複数シートに用意されている場合で、それぞれの予定表の特定の時間に同じ予定を一括で登録する機能の開発方法について解説していきます。

※こちらで開発したファイルは、記事の最後にて配布しています。

ExcelVBAレベル確認

開発準備

まず初めに、[開発]タブを選択し、[マクロ]を選択します。

表示された以下の画面にて、開発する機能の名前を入力し、[作成]を選択します。
こちらでは、「setSchedule」と入力しています。

次に表示される以下の画面の「Sub ○○」から「End Sub」の間にコードを記述します。


コードの記述

以下のコードを記述します。

Sub setSchedule()
    
    Dim mWs As Worksheet
    Set mWs = Worksheets("反映")
    
    Dim ws As Worksheet
    Dim i As Long
    
    For i = 4 To 33
        If mWs.Cells(i, "B").Value <> "" Then
            For Each ws In Worksheets
                If ws.Name <> mWs.Name Then
                    If InStr(ws.Cells(i, "B").Value, _
                        mWs.Cells(i, "B").Value) = 0 Then
                        
                        ws.Cells(i, "B").Value = _
                            mWs.Cells(i, "B").Value & vbLf & _
                            ws.Cells(i, "B").Value
                        
                    End If
                End If
            Next ws
        End If
    Next i
    
End Sub

では、コードについて解説していきます。

    Dim mWs As Worksheet
    Set mWs = Worksheets("反映")

反映元となるシート情報を変数「mWs」に割り当てています。

    Dim ws As Worksheet
    Dim i As Long

繰り返し処理で扱う変数を定義しています。
変数「ws」は各シートを繰り返す際に活用し、変数「i」は各行を繰り返す際に活用します。

    For i = 4 To 33
        If mWs.Cells(i, "B").Value <> "" Then
            For Each ws In Worksheets
                If ws.Name <> mWs.Name Then
                    '処理
                End If
            Next ws
        End If
    Next i

Forで反映シートの予定表の先頭行から最終行までを繰り返し、内側のIfで予定が空でない場合に関してのみ、更に内側のFor Eachを実行するように記述しています。

For Eachでは、存在するシート1つ1つのシート情報を順番に変数「ws」に割り当て、更に内側のIfでシート名が「反映」でない場合に関してのみ、最深部の処理を実行するように記述しています。

                    If InStr(ws.Cells(i, "B").Value, _
                        mWs.Cells(i, "B").Value) = 0 Then
                        
                        ws.Cells(i, "B").Value = _
                            mWs.Cells(i, "B").Value & vbLf & _
                            ws.Cells(i, "B").Value
                        
                    End If

最深部では、Ifで反映元のシートの対象行「i」の予定と同じ予定が登録されていないことを確認しています。
InStrを活用して、反映先のシート「ws」の対象行「i」のセルに、反映元のシート「mWs」の対象行「i」のセルの値が含まれているかどうかを判定しています。
InStrで含まれていないと判断された場合は、「0」を返します。
そのため、その結果が「0」の場合という条件式になっています。

この条件を満たしたときに、反映先のシート「ws」の対象行「i」のセルに元々入力されている値に対し、改行「vbLf」と反映元のシートの対象行「i」のセルの値を加えています。

ExcelVBAレベル確認

ボタンの作成

コードが完成しましたら、反映シートに実行ボタンを用意します。
実行ボタンは、[開発]タブの中の[挿入]から作成することができます。


完成

以上の手順で、機能が完成します。
反映シートの10:00の予定(セルB8)に「共通の予定」と入力して、「一括反映」ボタンを押した実行結果は、以下になります。

既存の予定が存在する場合は、その予定を残したまま、先頭に「共通の予定」が追加されます。

▼サンプルファイル▼

2024/11/29
【Excel】カテゴリー単位で交互に色付け

【Excel】カテゴリー単位で交互に色付け

以下の表のように、特定の項目(カテゴリー)の値単位で交互に自動で色付けする方法について解説していきます。

※こちらで使用したファイルは記事の最後にて配布しています。

ExcelVBAレベル確認

条件式の作成

まずは、色付けする行の条件式を作成していきます。
色付けする行の条件式は、以下の手順で作成していきます。

1.カテゴリーの重複を除いた表を用意
2.対象行のカテゴリーが重複を除いた表の上から何番目なのかを求める
3.(2)で求めた数値が偶数の場合にTRUEと表示する

では順番に作成していきます。


1.カテゴリーの重複を除いた表を用意

まずは、カテゴリーの重複を除いた表の用意です。
重複を除いた表を用意する際は、UNIQUE関数を活用します。
この関数の使い方は、以下になります。

=UNIQUE(配列, [列の比較], [回数指定])
// 配列:対象のデータの範囲
// [列の比較]:データが列方向の場合(TRUE)、行方向の場合(FALSE[省略時])
// [回数指定]:重複していないデータのみを抽出する場合(TRUE)、重複を除いた全件を抽出する場合(FALSE[省略時])

実際にUNIQUE関数を活用して数式を作成すると、以下のようになります。

=UNIQUE(C3:C100)
// 表の範囲は100行目までとする

※空白のセルは「0」として抽出されます。


2.対象行のカテゴリーが重複を除いた表の上から何番目なのかを求める

次に、それぞれの行のカテゴリーが先ほど抽出した表の何番目になるのかをMATCH関数を活用して求めます。
この関数の使い方は、以下になります。

=MATCH(検査値, 検査範囲, [照合の種類])
// 検査値:検索する値
// 検査範囲:検索する範囲
// [照合の種類]:(1)以下、(0)完全一致、(-1)以上(省略時は(1)が指定される)

実際にMATCH関数を活用して数式を作成すると、以下のようになります。

=MATCH(C3,UNIQUE(C3:C100),0)
// C3:検索する値
// UNIQUE(C3:C100):検索する範囲(直接UNIQUE関数を指定)
// 0:完全一致で検索

他の行でも、正しく求めることができることを確認します。
そのため、数式の中のカテゴリーの項目の範囲を絶対参照にします。
検査値に関しては、列方向に反映した際に、参照列が移動しないように列のみを絶対参照にします。

=MATCH($C3,UNIQUE($C$3:$C$100),0)

この数式を下へコピーすることで、カテゴリーが切り替わる位置で数値をカウントアップすることができます。

カテゴリーが入力されていない行に関しては、エラーが表示されます。
理由は、UNIQUE関数で抽出した値に空が存在しないためです。
(UNIQUE関数で抽出した値では、空が「0」になってしまっているため、空ではヒットしません。)

一度、エラーはこのままにしておきます。


3.(2)で求めた数値が偶数の場合にTRUEと表示する

次は、先ほどMATCH関数で抽出した、それぞれの値が偶数の場合にTRUEと表示する数式を作成していきます。

偶数かどうかを判定する場合は、ISEVEN関数を活用します。
この関数の使い方は、以下になります。

=ISEVEN(数値)
// 数値:対象の数値

実際にISEVEN関数を活用して数式を作成すると、以下のようになります。

=ISEVEN(MATCH($C3,UNIQUE($C$3:$C$100),0))

この数式を下へコピーすることで、偶数番目のカテゴリーのみにTRUEと表示することができます。

ただ、空白の場合にエラーになってしまうので、エラーに関しては、IFERROR関数を活用してFALSEと表示するようにしていきます。
この関数の使い方は、以下になります。

=IFERROR(値, エラーの場合の値)
// 値:エラーを検証する値
// エラーの場合の値:値がエラーの時に表示する値

実際にIFERROR関数を活用して数式を作成すると、以下のようになります。

=IFERROR(ISEVEN(MATCH($C3,UNIQUE($C$3:$C$100),0)),FALSE)

この数式を下へコピーすることで、偶数番目のカテゴリーのみにTRUEと表示することができます。

このように条件式を作成することができましたら、後は条件付き書式で設定してきます。

ExcelVBAレベル確認

条件付き書式の設定

まずは、色付けする可能性のある対象の範囲を全選択します。

先ほど作成した条件式は3行目を基準とした100行目までに対応させた数式になります。
そのため、セルB3を基準にD100までを選択します。

名前ボックスを活用することで、簡単に選択することができます。

選択できましたら、[ホーム]タブの中の[条件付き書式]から[新しいルール]を選択します。

条件付き書式の設定画面にて、[ルールの種類]を[数式を使用して、書式設定するセルを決定]にし、表示されたテキストボックス内に、先ほどの条件式を入力します。
※アクティブセルに対する条件式を入力します。

条件式の入力ができましたら、[書式]を選択し、好みの書式を設定します。
こちらでは、書式設定の画面にて、[塗りつぶし]から灰色を設定します。

上記のように設定して確定することで、以下のように、カテゴリー単位で交互に自動で色付けすることができます。

※広範囲に設定すると、Excelファイルが重たくなります。そのため、今回のように100行目までなどと必要最低限の範囲にしておくとよいです。

▼サンプルファイル▼

2024/11/22
【ExcelVBA】カテゴリー単位でセルを自動結合

【ExcelVBA】カテゴリー単位でセルを自動結合

以下の表のカテゴリーの項目のように同じ値が複数行に続く場合、それらの同じ値のセルを瞬時に結合する機能の開発方法について解説していきます。

こちらで開発する機能は、どんな表にも適用できるようしています。
そのため、既存の表をプレゼン用や配布用として用意する際に活用すると便利です。
※こちらで開発したファイルは、記事の最後にて配布しています。

ExcelVBAレベル確認

開発準備

まず初めに、[開発]タブを選択し、[マクロ]を作成します。

表示された以下の画面にて、開発する機能の名前を入力し、[作成]を選択します。
こちらでは、「自動結合」と入力しています。

次に表示される以下の画面の「Sub ○○」から「End Sub」の間にコードを記述します。


コードの記述

以下のコードを記述します。

Sub 自動結合()

    Dim colNo As Long
    colNo = ActiveCell.Column
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, colNo).End(xlUp).Row
    
    Dim sRow As Long
    sRow = 1
    Dim i As Long
    Application.DisplayAlerts = False
    For i = 1 To lastRow
        If Cells(i, colNo).Value <> Cells(i + 1, colNo).Value Then
            Range(Cells(sRow, colNo), Cells(i, colNo)).Merge
            sRow = i + 1
        End If
    Next i
    Application.DisplayAlerts = True
    
End Sub

では、コードについて解説していきます。

    Dim colNo As Long
    colNo = ActiveCell.Column

今回の機能は、選択しているセルの列に対して、同じ値が連続するセルを結合していきます。
そのため、基準となる列番号を格納する用の「colNo」という変数を用意し、アクティブセル(ActiveCell)の情報から列番号(Column)を取得しています。

    Dim lastRow As Long
    lastRow = Cells(Rows.Count, colNo).End(xlUp).Row

先頭行から1行ずつ、同じ値が連続していないかどうかを確認していきます。
そのため、繰り返し終える位置である最終行の行番号を格納する用の「lastRow」という変数を用意し、「colNo」の列を基準に最終行の行番号を取得しています。
取得される行番号は、「colNo」の列の、シート上の一番下のセル(Cells(Rows.Count, colNo))を選択している状態で、「Ctrl+↑」(End(xlUp))で移動した先のセルの行番号(Row)になります。

    Dim sRow As Long
    sRow = 1

こちらに関しては、結合する際の開始の行番号を格納する用の「sRow」という変数を用意しています。
また、初期値として「1」を設定しています。

    Dim i As Long
    Application.DisplayAlerts = False
    For i = 1 To lastRow
        …
    Next i
    Application.DisplayAlerts = True

次に、先頭行から最終行までを繰り返す時に使用する「i」という変数を用意し、繰り返し処理(For)の前に、結合時の以下の警告を無視する設定(Application.DisplayAlerts = False)を行っています。

繰り返し処理(For)を終えた後には、警告を無視する設定を解除するコード(Application.DisplayAlerts = True)を記述しています。

    For i = 1 To lastRow
        If Cells(i, colNo).Value <> Cells(i + 1, colNo).Value Then
            Range(Cells(sRow, colNo), Cells(i, colNo)).Merge
            sRow = i + 1
        End If
    Next i

では最後、繰り返し処理(For)の内容です。
繰り返し処理(For)では、先頭行から最終行(lastRow)まで1行ずつ繰り返し、内側の条件分岐(If)で、「繰り返し処理の該当行(i)の該当列(colNo)の値と、その次の行(i + 1)の値が一致しない場合」という条件の確認を行っています。
一致しない場合に関しては、該当列(colNo)の開始の行(sRow)から繰り返し処理の該当行(i)までの範囲のセルを結合(Merge)しています。
結合後は、次の結合時の開始の行番号(sRow)を繰り返し処理の該当行(i)の次の行番号(i + 1)に変更しています。

上記のコードを実行することによって、選択しているセルの列に対して、同じ値が連続するセルを結合することができます。

以下のコードに関しては、単体のセル範囲では結合されません。

Range(Cells(sRow, colNo), Cells(i, colNo)).Merge

そのため、今回のようなコードの内容で実現することができます。

▼サンプルファイル▼