2025/05/16
【ExcelVBA】入力と同時に値を上に詰める

【ExcelVBA】入力と同時に値を上に詰める

セルに値を入力すると同時に、値を自動で上に詰める仕組みの実現方法について紹介していきます。

また、今回の仕組みでは、表の途中の値を削除した際にも、値が自動で上に詰められます。

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


1. 開発準備

こちらでは、以下のような「氏名」を入力する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.CountLarge = 1 And _
        Target.Row >= 3 And _
        Target.Column = 2 Then
        
        Application.EnableEvents = False
        
        Dim lRow As Long
        lRow = Cells(Rows.Count, "B").End(xlUp).Row
        
        On Error Resume Next
        Range("B3", Cells(lRow, "B")). _
            SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp
        On Error GoTo 0
        
        Application.EnableEvents = True
        
    End If
    
End Sub

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

Private Sub Worksheet_Change(ByVal Target As Range)
    
    If Target.CountLarge = 1 And _
        Target.Row >= 3 And _
        Target.Column = 2 Then
        
        '省略
        
    End If
    
End Sub

「Worksheet_Change」というプロシージャの引数の「Target」に、編集されたセルの情報が渡されるため、そのセルの情報から、表の対象のセルが編集されたかどうかを確認しています。
こちらでは、編集されたセルが1つ(Target.CountLarge = 1)で、行番号が3以上(Target.Row >= 3)、尚且つ、列番号が2(Target.Column = 2)であることを確認しています。
この条件は「表の範囲内の単体のセルが編集された時」という条件になります。

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

        Application.EnableEvents = False
        
        '省略
        
        Application.EnableEvents = True

今回の処理の内容は、セルの値を上に詰めるという内容です。
Ifの条件範囲内のセルを処理の中で操作するため、「Worksheet_Change」の処理が再度実行されないようイベントを無効にする処理(Application.EnableEvents = False)を記述しています。
処理の最後には、イベントの無効化を解除する処理(Application.EnableEvents = True)を記述しています。

        Dim lRow As Long
        lRow = Cells(Rows.Count, "B").End(xlUp).Row
        
        On Error Resume Next
        Range("B3", Cells(lRow, "B")). _
            SpecialCells(xlCellTypeBlanks).Delete Shift:=xlUp
        On Error GoTo 0

表を上に詰める方法として、こちらでは表の中の空白セルを削除して上方向にシフトするという方法で実装しています。
まずは、表の値が入力されている末尾のセルの行番号を変数「lRow」に格納しています。
B列の最終行のセル(Cells(Rows.Count, “B”))からCtrlキーとカーソルキーの上を押して移動(End(xlUp))した先のセルの行番号(Row)を末尾の行番号として取得しています。

次に、表の先頭のセルB3から末尾のセル(Cells(lRow, “B”))の範囲内の空白セル(SpecialCells(xlCellTypeBlanks))を削除(Delete)して上方向にシフト(Shift:=xlUp)しています。

ただ、この処理の内容ですと、空白セルが存在しない時にエラーになってしまうので、エラー対策をしています。
具体的には、エラーになった場合は対象の処理をスキップする(On Error Resume Next ~ On Error GoTo 0)という内容を記述しています。


3. 完成

以上の内容で実現できます。
表の中のセルを編集すると同時に、表の中の空白セルが削除され、値が上に詰められます。

▼サンプルファイル▼

2025/05/13
【Excel】進捗別にタスクを簡単に抽出

【Excel】進捗別にタスクを簡単に抽出

タスク管理をしていると、「今、進行中のタスクは?」「確認が必要なタスクは?」といった情報をサッと確認したくなる場面があります。
今回は、進捗が「着手中」や「確認待ち」になっているタスクを、自動で抽出して表示する方法を紹介していきます。


1. 表の構成

今回は、以下の表を用いて実現していきます。

2行目以降のB列からE列に抽出元の表、G列からI列に進捗「着手中」のタスクを表示する用の表、K列からM列に進捗「確認待ち」のタスクを表示する用の表を用意しています。
抽出先の表に関しては、表の先頭(セルG1とK1)に抽出対象の進捗を入力しています。


2. 数式の入力

・進捗「着手中」の抽出

まずは、進捗が「着手中」のタスクから抽出していきます。
以下の数式をセルG3に入力します。

=FILTER($B:$D,$E:$E=G1,"")
// 抽出元の表:$B:$D(Noから担当)
// 抽出する条件:$E:$E=G1(進捗の項目がセルG1の値と等しい)
// 抽出対象が見つからない場合に表示する値:""(空)

抽出元の表の範囲は常に固定になるため、「$」で固定しています。
抽出する進捗が入力されたのセルG1に関しては、隣の「確認待ち」のタスクを抽出する際にも、数式を入力したセルの2つ上のセルという感じに相対的な位置になるため、「$」では固定していません。

数式を入力して確定することで、以下のように「着手中」のタスクのみを抽出することができます。

・進捗「確認待ち」の抽出

次に、進捗が「確認待ち」のタスクを抽出していきます。
こちらに関しては、先ほど、セルG3に入力した数式をセルごとコピーして、セルK3に貼り付けるだけで、以下のように抽出することができます。

コピー元の数式をコピー先の数式を比較すると、抽出条件の進捗のセルのみが相対的に変わっていることが確認できます。

コピー元:=FILTER($B:$D,$E:$E=G1,"")
コピー先:=FILTER($B:$D,$E:$E=K1,"")

3. まとめ

FILTER関数を使えば、「進捗が◯◯のタスクだけを抽出したい」といったニーズに簡単に応えられます。
今回の数式のポイントは以下の2つ:

・抽出元の範囲は絶対参照
・抽出条件のセルは相対参照

こうすることで、数式を再利用しやすくなり、作業効率が大幅に向上します。

2025/05/09
【ExcelVBA】直接編集も自動抽出もできる仕組み

【ExcelVBA】直接編集も自動抽出もできる仕組み

以下の表は、黄色のセルにVLOOKUP関数を用いた数式が入力されており、IDをB列に入力すると同時に、該当する商品名と単価がC列とD列に抽出されるようになっています。

しかし、数式で値を抽出している場合、例外的に商品名や単価を修正する必要がある時に、修正することができません。
直接修正してしまうと数式が上書きされ、更新されなくなってしまいます。

今回は、そのような例外的な修正も可能とした「直接編集も自動抽出もできる仕組み」の実現方法について解説していきます。
※こちらで実現したファイルは記事の最後にて配布しています。


1. 開発準備

「直接編集も自動抽出もできる仕組み」を実現するためには、VBAで開発する必要があります。
今回の場合は、B列のIDのセルが編集された時に、自動でC列とD列の商品名と価格を表示させる必要があります。

このように、特定のシート内の特定のセルが編集された時に処理を実行する仕組みを実現するには、「シートモジュール」を使用します。

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

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

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

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

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

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


2. コードの記述

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

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Set ws1 = Worksheets("商品管理")
    Set ws2 = Worksheets("請求書")
    
    If Target.CountLarge = 1 And _
        Target.Row >= 5 And Target.Row <= 10 And _
        Target.Column = 2 Then
        
        ws2.Cells(Target.Row, "C").ClearContents
        ws2.Cells(Target.Row, "D").ClearContents
        
        Dim lRow As Long
        lRow = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
        Dim i As Long
        For i = 2 To lRow
            If ws1.Cells(i, "A").Value = Target.Value Then
                ws2.Cells(Target.Row, "C").Value = _
                    ws1.Cells(i, "B").Value
                ws2.Cells(Target.Row, "D").Value = _
                    ws1.Cells(i, "C").Value
                Exit For
            End If
        Next i
        
    End If
    
End Sub

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

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Set ws1 = Worksheets("商品管理")
    Set ws2 = Worksheets("請求書")
    
    If Target.CountLarge = 1 And _
        Target.Row >= 5 And Target.Row <= 10 And _
        Target.Column = 2 Then
        
        '省略
        
    End If
    
End Sub

「Worksheet_Change」というプロシージャの引数の「Target」に、編集されたセルの情報が渡されるため、そのセルの情報から、表の対象のセルが編集されたのかどうかを確認しています。
まずはシート情報を格納する用の変数「ws1」と「ws2」を用意し、それぞれに「商品管理」と「請求書」のシート情報を格納しています。

次に、編集されたセルの情報である「Target」から、編集されたセルが1つであり、行番号が5以上10以下、列番号が2であることを確認しています。
これは以下の、IDの項目の範囲内のいずれかのセルが編集されたかどうかの判定になります。

IDの項目の範囲内のいずれかのセルが編集された場合に、Ifの中の処理を実行します。

        ws2.Cells(Target.Row, "C").ClearContents
        ws2.Cells(Target.Row, "D").ClearContents

先ほどの条件を満たしたときに、編集されたセルと同じ行のC列とD列、要するに同じ行の商品名と単価のセルを空にしています。

        Dim lRow As Long
        lRow = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
        Dim i As Long
        For i = 2 To lRow
            
            '省略
            
        Next i

次に、入力された値(ID)と一致する商品名と単価の情報を「商品管理」シートから抽出します。
「商品管理」シート内の表に関しては、今後データが追加される可能性があります。
そのため、まずは表の最終行の位置情報(行番号)を格納する用の変数「lRow」を用意し、その変数「lRow」に該当する行番号を格納しています。

最終行の行番号は、こちらではA列を基準に、A列の一番下のセルを選択して、Ctrlキーを押しながらカーソルキーの上を押して移動した先のセルの行番号から取得しています。

次に、表の先頭から順番に同じIDの行を探すために、繰り返す際の行番号を格納する用の変数「i」を用意しています。
そして、その変数「i」を活用して、2行目から先ほど取得した最終行(lRow)までを1行ずつFor文で繰り返しています。

            If ws1.Cells(i, "A").Value = Target.Value Then
                ws2.Cells(Target.Row, "C").Value = _
                    ws1.Cells(i, "B").Value
                ws2.Cells(Target.Row, "D").Value = _
                    ws1.Cells(i, "C").Value
                Exit For
            End If

最後に、繰り返しの中で、入力したID(Target.Value)と一致するID(i行目のA列の値)が存在するかどうかを確認しています。
そして、一致するIDが存在している場合に、「請求書」シートの対象行のC列とD列に、該当する商品名と単価を入力しています。

一致するIDが存在している場合は、その時点で他の商品を確認する必要がなくなるため、Exti ForでForの繰り返しを終えています。


3. 完成

以上の内容で実現できます。

IDの入力と同時に、該当するIDの商品が存在している場合は、その商品の商品名と単価が表示され、存在していない場合は、何も表示されません。
また、商品名や単価を例外的に編集した場合に関しても、対象のIDのセルを編集して確定するだけで、商品名と単価をリセットすることができます。

▼サンプルファイル▼

2025/05/06
【Excel】数式で画像を参照して抽出できる!?

【Excel】数式で画像を参照して抽出できる!?

セル上に配置した画像を数式で参照して抽出したいけど、上手く抽出できなくて困っている方いませんか?

実は、最新のExcelでは、簡単に抽出することができるようになりました。

以前のバージョンでも画像を数式で抽出することはできたのですが、工程で多く大変になります。
以前のバージョンでの実現方法については、以下の記事が参考になります。

>【便利】数式のみで画像を表示する

こちらでは、最新の機能を活用して、簡単に画像を数式で参照して抽出する方法について解説していきます。


画像を数式で参照して抽出する

通常、セルの上に配置された画像はセルの値とは見なされないため、以下のように数式で抽出することができません。

しかし、最新のExcelでは、「セル内に画像を配置する機能」が搭載されました。
こちらの機能を活用することで、セルの上ではなく、セル内に画像を配置することができます。

この機能を活用して、セル内に画像を配置する方法は簡単です。
まずは、対象の画像の左上を、配置したいセルの中に移動させます。

次に、対象の画像を選択し、画像の右上に表示されるアイコンを選択します。

これだけで、以下のようにセル内に画像を配置することができます。
画像が配置されたセルを選択して数式バーを確認すると、「画像」などのようなテキストが表示されます。

画像を配置したセルを編集した際も同様です。

編集して確定してしまうと「画像」のようなテキストに置き換わってしまうので注意してください。

同様に、他の画像に関してもセル内に配置することで、以下のように数式で参照して抽出することができるようになります。

ExcelVBAレベル確認

補足

ちなみに、セル内に配置した画像と同じ画像(セルごとをコピーした画像)であれば、画像で検索して抽出することも可能です。

しかし、画像をセル上に戻して、セル内に再度配置した場合など、画像に対し何かしら操作してしまった場合は、別の画像として認識されて検索できなくなってしまうようです。

2025/05/02
【Excel】複数シートを一括修正

【Excel】複数シートを一括修正

以下のように、同じ形式のテンプレートを複数用意したのに、「「No」ではなく「ID」に変更して、A列を空にしてほしい」などといった修正依頼があった場合、全てのシートを1枚1枚修正するのは大変になります。

今回は、そのような複数シートを一括で修正する時に使えるテクニックを紹介していきます。


複数シートを一括で修正

まず初めに、同じ形式の修正対象のシートを全て選択します。
複数選択する時は、先頭のシートを選択し、Shiftキーを押しながら末尾のシートを選択します。
離れているシートの場合は、Ctrlキーを押しながら選択します。

後は、アクティブになっているシートに対し、共通する修正を行うだけです。
例えば、項目名を「No」から「ID」に変更し、A列を空にする場合は、以下のようになります。

修正後は、シートの複数選択を解除する必要があります。
全シートを選択している場合は、アクティブになっているシート以外を、一部のシートを選択している場合は、選択しているシート以外を選択することで、複数選択を解除することができます。

選択を解除したら修正完了です。

2025/04/29
【Excel】VLOOKUPで空白が「0」と表示されてしまう問題を一瞬で解決

【Excel】VLOOKUPで空白が「0」と表示されてしまう問題を一瞬で解決

VLOOKUP関数を使って値を抽出したとき、「抽出元が空白なのに「0」と表示されてしまう…」という経験、ありませんか?

=VLOOKUP(B2,B5:C34,2,FALSE)

今回は、空白を空白として表示する方法について解説していきます。


IF関数を使う方法

一般的に知られているのが、IF関数を使う方法になります。
IF関数を用いた場合は、以下のような数式になります。

=IF(VLOOKUP(B2,B5:C34,2,FALSE)="","",VLOOKUP(B2,B5:C34,2,FALSE))

空白のセルを直接表示すると、Excelの仕様上「0」として表示されてしまいます。
そこで、IF関数を用いてVLOOKUP関数で抽出した値が空白の場合は「””」と、直接空白(空文字)を指定して表示させることで実現しています。

ただ、実現はできるものの数式が長いですよね。
実はもっと短く実現する方法があります。


IF関数を使わない方法

空白を直接表示する時に「0」と表示されてしまう理由は、数値として認識されてしまうためです。
そのため、数値ではなく意図的に文字列にすることで空白のまま表示することができるようになります。

意図的に文字列にするためには、VLOOKUP関数により抽出された値に空白(空文字)を加えるのが簡単です。
具体的には、以下のような数式になります。

=VLOOKUP(B2,B5:C34,2,FALSE)&""

このように、「&」で空白(空文字)を加えるだけで、「0」ではなく空白のまま表示することができます。

ただ、この方法の場合、数値を抽出する際にも文字列として抽出されてしまいます。
そのため、数値を抽出して、計算に使用する場合などには不都合が出ることもあるので、用途によっては注意する必要があります。

2025/04/25
【ExcelVBA】選択するだけでデータを別の表に移動

【ExcelVBA】選択するだけでデータを別の表に移動

グループなどを管理している表で、隣のグループの表に氏名を移動したいことってありませんか?

今回は、そんな時に便利な右クリックするだけで氏名を移動できる仕組みを実現していきます。
左側の表から右側の表へ、右側の表から左側の表へ移動することができる仕組みになります。

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


1. 開発準備

今回は、表の中のセルを右クリックすることで、隣の表にデータを移動するという仕組みを実現してきます。
特定のシートの特定のセルを右クリックすることで何かしら処理を実行するには、該当するシートのシートモジュールを活用します。

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

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

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

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

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

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


2. コードの記述

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

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    
    If Target.CountLarge = 1 And _
        Target.Row >= 3 Then
        
        Dim lRow As Long
        If Target.Column = 2 Then
            Cancel = True
            lRow = Cells(Rows.Count, "C").End(xlUp).Row
            Cells(lRow + 1, "C").Value = Target.Value
            Target.Delete xlUp
        ElseIf Target.Column = 3 Then
            Cancel = True
            lRow = Cells(Rows.Count, "B").End(xlUp).Row
            Cells(lRow + 1, "B").Value = Target.Value
            Target.Delete xlUp
        End If
        
    End If
    
End Sub

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

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
    
    If Target.CountLarge = 1 And _
        Target.Row >= 3 Then
        
        '省略
        
    End If
    
End Sub

「Worksheet_BeforeRightClick」というプロシージャの引数の「Target」に、右クリックされたセルの情報が渡されるため、そのセルの情報から、表の対象の範囲内が右クリックされたかどうかを確認しています。
こちらでは、「右クリックされたセルが単体(複数範囲を選択した上での右クリックでない)で3行目以上のセル」と、まずは対象の表のデータ行が右クリックされたかどうかを確認しています。

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

        Dim lRow As Long
        If Target.Column = 2 Then
            '省略
        ElseIf Target.Column = 3 Then
            '省略
        End If

lRowという変数は、移動先の表の最終行の行番号を格納する用の変数になります。
こちらは後で使用します。

その次のIfで、右クリックされたセルが2列目(B列)なのか3列目(C列)なのかによって、処理を分岐しています。

            Cancel = True
            lRow = Cells(Rows.Count, "C").End(xlUp).Row
            Cells(lRow + 1, "C").Value = Target.Value
            Target.Delete xlUp

右クリックされたセルが2列目(B列)の場合は、「Cancel = True」で右クリック時のメニューが表示されないようにし、lRowに移動先の表(C列)の最終行の行番号を格納しています。
行番号は、C列の一番下のセルからCtrlキーとカーソルキーの上を押して止まった位置のセルの行番号を最終行の行番号として取得しています。
その次に、その取得した行番号の1つ下のセルに、右クリックされたセルの値を格納し、右クリックされたセルを削除して上に詰めています。

            Cancel = True
            lRow = Cells(Rows.Count, "B").End(xlUp).Row
            Cells(lRow + 1, "B").Value = Target.Value
            Target.Delete xlUp

右クリックされたセルが3列目(C列)の場合は、先ほどのB列とC列を入れ替えた処理を行っています。


3. 完成

以上の内容で実現できます。
移動したい氏名が入力されているセルの上で、右クリックすることで、その氏名を隣の表に移動することができます。

▼サンプルファイル▼

2025/04/22
【Excel】自動でグループ分け!FILTER関数×TEXTJOIN関数

【Excel】自動でグループ分け!FILTER関数×TEXTJOIN関数

以下の表は、氏名ごとに曜日を割り当てたものになります。

今回は、こちらの表から曜日ごとで氏名をカンマ区切りにして抽出する方法について紹介していきます。


FILTER関数とTEXTJOIN関数

カンマ区切りで並べて抽出するには、FILTER関数とTEXTJOIN関数を活用します。

FILTER関数では、以下のように条件を満たしたデータのみを抽出することができます。

=FILTER(D:D,E:E="月","")

TEXTJOIN関数では、以下のように指定した複数の値を指定した区切り文字で繋げて表示することができます。

=TEXTJOIN(",",TRUE,D3:D7)

そのため、この2つ関数を組み合わせて、対象のデータの抽出と抽出データの結合を1つ数式で行うことができます。


曜日ごとで氏名をカンマ区切りにして抽出

こちらでは、以下のB列の表に曜日ごとで抽出していきます。

まずは、「月」から抽出していきます。
「月」を抽出する数式は、以下になります。

=TEXTJOIN(",",TRUE,FILTER(D:D,E:E=B2,""))
// FILTER関数で「月」と一致する氏名を抽出し、TEXTJOIN関数でカンマ区切りにして結合

このように、1つの数式で抽出することができます。
他の曜日に関しては、数式を入力したセルをコピーして貼り付けるだけで抽出することができます。

それぞれのセルに貼り付けられる数式は、以下のように相対参照で反映されます。

火:=TEXTJOIN(",",TRUE,FILTER(D:D,E:E=B4,""))
水:=TEXTJOIN(",",TRUE,FILTER(D:D,E:E=B6,""))
木:=TEXTJOIN(",",TRUE,FILTER(D:D,E:E=B8,""))
金:=TEXTJOIN(",",TRUE,FILTER(D:D,E:E=B10,""))

まとめ

FILTER関数とTEXTJOIN関数の組み合わせは、単に曜日ごとの担当者を抽出するだけでなく、様々な条件に基づいたデータの抽出と結合を自動化できる、非常に汎用性の高いテクニックです。

これらの関数を使いこなすことで、
・データ分析の効率化
・レポート作成の自動化
・日々のルーチンワークの削減

などといった、Excelを使った業務の効率を向上させることができます。

2025/04/18
【ExcelVBA】省略した項目を自動で入力

【ExcelVBA】省略した項目を自動で入力

以下のように、所属(学年とクラス)と氏名を入力する表で、同じ所属の名前を複数件登録することがあるかと思います。

その際に、毎回同じ所属(学年とクラス)を入力するのは面倒ですし、コピーするのも地味に面倒です。
そのため今回は、所属(学年とクラス)を省略した場合は、1つ前の所属を自動で入力する仕組みの開発方法について紹介していきます。
色んな表で活用できる便利な機能になります。

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


1. 開発準備

今回は、以下の表の「氏名」の項目に値が入力された時に、「学年」の項目が空欄だった場合は1つ前の「学年」を入力、「クラス」の項目が空欄だった場合は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)
    
    Dim r As Long: r = Target.Row
    Dim c As Long: c = Target.Column
    
    If r >= 3 And c = 4 Then
        If Cells(r, "B").Value = "" Then
            Cells(r, "B").Value = _
                Cells(r - 1, "B").Value
        End If
        If Cells(r, "C").Value = "" Then
            Cells(r, "C").Value = _
                Cells(r - 1, "C").Value
        End If
    End If

End Sub

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

Private Sub Worksheet_Change(ByVal Target As Range)
    
    Dim r As Long: r = Target.Row
    Dim c As Long: c = Target.Column
    
    If r >= 3 And c = 4 Then
        
        '省略
        
    End If

End Sub

「Worksheet_Change」というプロシージャの引数の「Target」に、編集されたセルの情報が渡されるため、そのセルの情報から、表の対象のセルが編集されたかどうかを確認しています。
こちらでは、Targetの行番号と列番号を変数「r」と「c」に格納し、「r」が3以上、尚且つ、「c」が4の時、要するに「氏名」の項目が編集されたかどうかを確認しています。

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

        If Cells(r, "B").Value = "" Then
            Cells(r, "B").Value = _
                Cells(r - 1, "B").Value
        End If
        If Cells(r, "C").Value = "" Then
            Cells(r, "C").Value = _
                Cells(r - 1, "C").Value
        End If

こちらでは、学年の項目(r行目のB列)が空欄なのか、クラスの項目(r行目のC列)が空欄なのかを確認しています。
学年の項目(r行目のB列)が空欄の場合は、その項目の1つ前の値(r-1行目のB列)を入力しています。
クラスの項目(r行目のC列)に関しても同様に、空欄の場合は、その項目の1つ前の値(r-1行目のC列)を入力しています。


3. 完成

以上の内容で実現できます。
「氏名」の項目に値が入力された時に、「学年」の項目が空欄だった場合は1つ前の「学年」が入力され、「クラス」の項目が空欄だった場合は1つ前の「クラス」が入力されます。

▼サンプルファイル▼

2025/04/15
【Excel】同じ日付が一定間隔で続く予定表を効率的に作成

【Excel】同じ日付が一定間隔で続く予定表を効率的に作成

以下のように、同じ日程が一定間隔で続く予定表を作成したことはありませんか。

このような表を手作業で入力していくのは大変ですし、ミスも起こりやすくなります。
ということで今回は、同じ日付が一定間隔で続く予定表を効率的に作成する方法について紹介します。


同じ日付が一定間隔で続く連続した日付を入力

直接的に「一定間隔で同じ日付を繰り返す」という機能は存在しませんが、オートフィルの使い方を少し工夫することで、実現することができます。

(例)3行間隔で連続した日付を入力する場合

1. 開始日を必要な回数入力する

2. 次の行に、先頭行の日付に1を加えた日付を表示する数式を入力する

3. 入力した数式を必要な行数分コピーする(オートフィル)

これだけです。
数式の参照先が相対的に変化するため、日付を一定間隔で繰り返して入力することができます。


同じ組み合わせの値を繰り返して入力

担当の項目に「A→B→C」などと繰り返した値を入力する場合にも、オートフィルが活用できます。

(例)「A→B→C」を繰り返して入力する場合

1. 繰り返す1周分の値を入力する

2. 入力したセルを選択し、必要な行数分コピーする(オートフィル)

これだけです。


まとめ

オートフィルの機能を少し工夫して活用することで、一定間隔で続く予定表を作成することができました。
表に法則性のあるデータを入力する際は、オートフィルの機能を使って効率的に入力できないかどうかを検討してみると良いです。

2025/04/11
【Excel】年月を変更するだけで万年使えるカレンダー

【Excel】年月を変更するだけで万年使えるカレンダー

以下のように、年月の項目を指定するだけで、自動でその月のカレンダーに切り替わるシートの作成方法について解説していきます。

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


1. 指定した年月の1日の日付を表示する

まず、DATE関数を活用して、指定した年月の1日の日付を表示します。

=DATE(B2,B3,1)

これで、B2とB3に入力した年月の1日の日付が表示されます。


2. 2日以降の日付を表示する

2日以降の日付は、前の日付に1日を加えることで表示できます。

=A6+1

1つ数式を入力したら、下へ28日が表示されるまでコピーします。


3. 29日以降の日付を表示する

月によっては29日以降が不要になるため、29日以降に関しては、対象年月の月末日を超えていないかどうかを確認する必要があります。

そのためには、対象年月の月末日を取得する必要があります。
年月から月末日を取得するには、DATE関数で「翌月1日の1日前」と指定します。

=DATE(B2,B3+1,0)
// 1日の1日前なので、日を「0」と指定する

取得した月末日と前の日付(1つ上のセル)と比較し、月末日の方が大きい場合に、前の日付に1日を加えた日付を表示させます。
条件を確認し表示の有無を切り替える場合は、IF関数を活用します。

=IF(DATE(B2,B3+1,0)>A33,A33+1,"")

こちらの場合は、2025年2月の日付を表示しているため、28日の次の日付が表示されないことが確認できます。

こちらの数式を残り2行分(31日分)入力する必要があります。
そのため、数式の年月を参照しているセルに「$」を加えて固定してからコピーします。

=IF(DATE($B$2,$B$3+1,0)>A33,A33+1,"")

上記の画像のセルA35とA36が空になる理由は、IF関数の条件式(論理式)で空と比較しているためです。

文字列(数式により表示された空の文字列「””」)と数値を比較した場合、文字列の方が大きいと判断されるため、IF関数の条件を満たさず空の文字列「””」が表示されます。
※何も入力されていないセルの場合は「0」として扱われるため、挙動が異なります。


4. 曜日を表示する

日付から曜日を取得するには、TEXT関数を活用します。
以下のように、TEXT関数を活用して日付に対応する曜日を表示します。

=TEXT(A6,"aaa")
// 「aaa」は曜日を表示する書式記号

1つ数式を入力したら、最終行までコピーします。

日付の項目が空の文字列「””」の行に関しては、空の文字列「””」が表示されます。
※何も入力されていないセルの場合は「0」として扱われるため、挙動が異なります。


5. 完成

これで、指定した年月に応じてカレンダーが自動的に切り替わる仕組みが完成しました。
関数を組み合わせることで、ある程度は自動化することができます。
今回は、DATE関数IF関数TEXT関数の3つの関数を活用しました。
これらの関数は、よく使われるため覚えておくと良いです。

▼サンプルファイル▼

2025/04/08
【Excel】シートを完全に非表示にする

【Excel】シートを完全に非表示にする

特定のシートを隠したい場合、通常の「非表示」設定では再表示から簡単に表示されてしまいます。

再表示させない目的で、ブックを保護するという方法もありますが、ブックを保護してしまうと、「シートが移動できない、追加できない」などと扱いづらくなってしまいます。

そこで、本記事では、再表示では表示できない「シートを完全に非表示にする」方法について解説していきます。


「通常の非表示」と「完全非表示」の違い

Excelには、以下の2種類の非表示設定があることはご存じでしょうか。

1.通常の非表示(再表示で簡単に戻せる)
2.完全非表示(再表示からは戻せない)

恐らく、2つ目の「完全非表示」の設定方法については知らない方がほとんどかと思います。
2つ目の方法を活用することで、ブックを保護しなくてもシートを隠し、誤って表示されるリスクを防ぐことができます。
途中計算用のシートなど、あまり触ってほしくないシートに活用すると良いです。

ただ注意点として、しばらく操作をしていないと、設定した本人すらシートの存在を忘れてしまう可能性があります。
後継ぎなどのことも考慮した上で、非表示にした際の手順書を残しておくと良いです。

ExcelVBAレベル確認

シートを「完全非表示」にする方法

シートを完全に非表示にするためには、「VBE(Visual Basic Editor)」を活用します。
通常、VBEはマクロを開発する際に活用する画面ですが、今回はマクロの開発は行いません。
そのため、マクロ有効ブックにする必要もないです。

① VBEを開く

「Alt」キーを押しながら「F11」キーを押すことで、VBEの画面を開くことができます。
[開発]タブが表示されている場合は、[開発]タブの中の[Visual Basic]を選択することでも開くことができます。

② 「プロジェクトエクスプローラー」と「プロパティウィンドウ」を表示する

VBEの画面に「プロジェクトエクスプローラー」と「プロパティウィンドウ」が表示されていない場合は、[表示]メニューから表示します。

③ 「完全非表示」にする対象のシートのプロパティを表示する

「完全非表示」にする対象のシートを選択するか、「プロジェクトエクスプローラー」から対象のシートの項目を選択します。
選択すると、「プロパティウィンドウ」に対象のシートのプロパティが表示されます。
対象のシートのプロパティかどうかは「Name」の項目で確認することができます。
こちらでは「休日一覧」シートを選択しています。

④ 「完全非表示」を設定する

対象のシートの「Visible」プロパティを「2 – xlSheetVeryHidden」にします。

以上です。
これで対象のシートを完全に非表示にすることができます。

この方法で非表示にした場合は、「再表示」からは表示することができません。

ただ、シート自体は存在しているため、数式などで参照することはできます。


シートを再表示する方法

「完全非表示」にしたシートを再表示する際は、VBEのプロパティウィンドウから設定します。
再表示する際は、「プロジェクトエクスプローラー」から対象のシートの項目を選択し、対象のシートの「Visible」プロパティを「-1 – xlSheetVisible」に戻します。

これだけで、非表示にしたシートを表示することができます。


まとめ

シートを完全に非表示にすると、誤って表示されるリスクを防げます。
完全に非表示にしても、VBAや数式で参照することは可能です。
ぜひ試してみてください。