選択範囲の最終セルを選択する

選択範囲の中での最終セルだけを選択状態にするコード、シートの最終セルを選択状態にするコードの解説含む

'選択中の最終セルを選択する
Selection.Cells(Selection.Cells.Count).Select

セル選択をした状態で、そのセル範囲の最後のセルのみを選択状態にするコードです

主に表を作成したりして、そのセル範囲の最後のセルを単一で指定したい場合に使用します

使用例

使用済みセル範囲の最終セルを選択状態にする
使用済み範囲の最終セルを選択
'使用済みの最終セルを選択する
ActiveSheet.UsedRange.Select
Selection.Cells(Selection.Cells.Count).Select

実際のコード使用時の動きの確認を行います
今回の作成コードはこんな感じのコードです

目的としては、保存に時間がかかるブックのため頻繁に保存を実行できないブックで、表を整えるたびに最終セルを取得していきたい場合です

SpecialCells(xlCellTypeLastCell)メソッドでも最終セルは取得できますが、上記の条件のように表の改変を行いつつ、保存を実行しない場合はうまく取得できません

ActiveSheet.UsedRange.Select

そこで、UsedRangeプロパティを使用することで保存に影響を受けずに最終セルの取得を行うことが出来ます

しかし、このプロパティでは範囲選択されてしまうため
実際どこが最終セルなのかが分かりません

Selection.Cells(Selection.Cells.Count).Select

そこで、記事コードを連続して使用することで最終セルのみを選択状態にできます

このコード自体は非常にシンプルな内容です

「Selection.Cells」という部分で、選択中のセル範囲のセル全体を表しています
そこに「()」でセルを相対的に指定することが出来ます

行列番号を指定する事以外に、セルのインデックス番号を使用することもできます
今回はこのインデックス番号で処理を行います

そして、インデックス番号は「Selection.Cells.Count」となっています
選択中のセル範囲のセル全体は上記のとおりです、そのセル全体の個数を取得しています
範囲選択のセル個数が100個あれば「100」が取得されます

このセルのインデックス番号は配列とは違い、1から始まるのでそのままの数値で最終セルを指定することが可能になります

Selection.Cells(1).Select

数値での指定を行えますので、このようにすれば選択範囲の1番目のセルを選択状態にできます

まあ、選択範囲が1つであればそこはActiveCellになるので、あえて指定することはあまりありませんが可能ではあります

シートの使用済みセルを範囲選択

UsedRangeプロパティは、シート内で使用済みのセル範囲を取得します

'使用済みのセルを範囲選択する
ActiveSheet.UsedRange.Select

シート内の使用済みセル範囲を選択するには「UsedRange」プロパティを使用します
これは、セル範囲のプロパティですがオブジェクトはシートになっていますので注意してください

コードの動きの解説

シート内の使用済みセル範囲を選択状態にする
使用済み範囲の選択
ActiveSheet.UsedRange.Select

例のコードを実行したときの動きです

コードを実行すると、B3からF8までが範囲選択されます

このプロパティは左上端と右下端の2点セルから範囲を取得します
その際、値が入力されているセルだけではなく、書式が設定されているだけでも対象となります

A列と1・2行目にデータは存在しないため、始点セルがB3になります
F8は黄色に背景色が設定されているだけですが、しっかり取得されています

イメージ的には、SpecialCells(xlCellTypeLastCell)メソッドに似ています
このメソッドはシート内の使用済みの最後のセル(右下端)を指定できるものです
このセルから始点は任意の箇所になりますが、同じように使用範囲を指定することができます

しかし、記事のプロパティでは保存の影響を受けません
保存を実行せずに最終セルを判定するには、こちらを使用することになります

ただ、範囲選択されてしまうので最終セルを保存しない状態で取得する場合は
この範囲の中から最後のセルを取得するような処理を作成する必要があります
その内容については以下の記事で解説を行っています

特定のセルを選択する

RowDifferences・ColumnDifferencesメソッドは、指定範囲の中で条件に指定したセル以外を選択するメソッドです

'アクティブセル以外のセルを選択状態にする(行方向)
Selection.RowDifferences(ActiveCell).Select
'アクティブセル以外のセルを選択状態にする(列方向)
Selection.ColumnDifferences(ActiveCell).Select

「RowDifferences」「ColumnDifferences」メソッドは、指定したセルと同一のセル以外を選択します

このメソッドは、指定範囲内に引数に指定するセルが存在していないとエラーになります

なので、基本的にはこのメソッドの引数にはActiveCellやCellsなどの相対的な指定方法で行う必要があります
また、引数に指定できるセルは単一のセルになるので、複数のセルを指定した場合もエラーになります

メソッドの動き

特定のセルを選択状態にする(列方向)
行方向への指定選択
Selection.RowDifferences(ActiveCell).Select

画像ではこのコードが実行されています
RowDifferencesメソッドは、行方向への操作時に使用します

画像の動きではActiveCellはA2になりますので、条件は「ステータスA」が指定される形になります

このメソッドは、指定したもの以外を選択状態にするので
元々の選択範囲から「ステータスA」を除いたセルが選択状態になります

空白も対象になるので、列全体を指定するワークシートの列全体を選択してしまいます

特定のセルを選択状態にする(行方向)
列方向への指定選択
Selection.ColumnDifferences(ActiveCell).Select

ColumnDifferencesメソッドは、列方向への操作時に使用します

画像の動きでは、ActiveCellはB2になっていますので、空白のセルが指定される形になります

なので、選択範囲の中で空白ではないセルが指定される形になっています

この画像の動きのように、行のなかで特定の列だけにデータが入力されている表でどの列にデータが入力されているかを調べるのに適しているメソッドです

ただ、指定範囲の中に条件のセルを含める必要があるのがすこし難点です
なので、この画像の例の表ではその為にあえて何も入力しない空白列(B列)が作成されています
こうすることで、常に空白を指定することが出来るようにはなります

しかし、この動きであればFindメソッドの方が柔軟に条件も指定出来て便利ではあります
ですが、Findメソッドは一度に条件にあてはまるセルを選択するような動きはできません
あくまでも1セルずつ処理を行っていきます

でもこのメソッドなら、条件さえ整えてあげれば一括で条件に当てはまるセルを一括選択できます
逆説なので、条件を整えるのがたいへんですが・・・

使いどころが難しいメソッドですが、機能としては便利な機能だと思います

フィルタ機能(全解除)

フィルタの条件を全解除するにはShowAllDataメソッドを使用します

'フィルタの条件設定をクリアする
ActiveSheet.ShowAllData
'フィルタの条件設定をクリアする
On Error Resume Next
ActiveSheet.ShowAllData
On Error GoTo 0

フィルタのどれかの列でソートがかかっている状態を一括で全解除するには「ShowAllData」メソッドを使用します

このメソッドは、フィルタがかかっていない状態で実行するとエラーが発生します
なので、処理の最初に初期化しておきたいような場合はエラーを無視して実行します

フィルターが設定されているかは調べればわかりますが、あまり意味は無いと思います

また、ここでいう解除とはフィルタ機能の解除ではありません
ソート条件の解除になりますので、注意してください

フィルタを処理中にかけなおす場合は、当然エラーにはなりませんので1つ目のエラー無視は入れずに実行するといいです

ユーザーがフィルタをかけて保存していると、当然処理がうまくいかない可能性がありますのでフィルタのあるシートを処理する場合は最初に入れておくと安心です

ちなみに、昇順降順の矢印の表示もクリアされますがその設定は解除されたりはしません

Worksheets(1).ShowAllData

またこのメソッドはシートに対して行いますので、このコードのようにワークシートを指定して、別のシートのフィルタ条件を解除することもできます

引数を渡してプロシージャを実行する

引数付きのプロシージャの作成方法と呼び出し方法について

'セルを引数に持つプロシージャ
Sub 呼出テスト(引数 As Range)

End Sub

プロシージャの呼び出しにはCallステートメントを使用します
この時に引数付きのプロシージャを実行する事ができます

その際には呼び出し先のプロシージャで引数の設定を行う必要があります

関数と同様にプロシージャ名の隣の「()」の中に指定を行います
通常引数の無い場合は、空白状態になっています

ここは引数を設定するための場所になります

引数は、変数と同じものを指定します
書き方も変数の宣言と同じものになります

実際の処理の動き

Sub 処理テスト()

 Call 呼出テスト(Range("A1"))

 Call 呼出テスト(Range("A1:A10"))

End Sub

Sub 呼出テスト(引数 As Range)

Debug.Print 引数.Address

End Sub

処理の動きの確認には以上のコードを使用します

引数付きの処理を呼び出したときの動き
引数付きの処理の呼び出し

画像の動きの確認をしてください

 Call 呼出テスト(Range("A1"))

 Call 呼出テスト(Range("A1:A10"))

Callステートメントで2回処理を呼び出しています
その際に、引数としてセルを指定しています

指定方法はプロシージャ名の後に「()」を指定して、中に引数に設定するものを記載します

Sub 呼出テスト(引数 As Range)

Debug.Print 引数.Address

End Sub

呼び出し先の処理では、引数は「(引数 As Range)」として指定されています

ここに呼び出し時に指定するセルを代入することができます
代入されたものは通常の変数と同じ使い方になるので、Addressプロパティでセルアドレスを取得することが出来ます

Callステートメントにより同様の処理をまとめることが出来ますが、こうして対象が違っていてまとめることが出来ない場合に使用できます

なお、この引数付きのプロシージャからデバッグモードに入ることはできません
なので動作確認を行いたい場合は、呼び出し元のプロシージャから実行することでデバッグモードを行うことが可能になります

また、ここではSubプロシージャで行っていますが、Functionプロシージャでも全く同様に使用できます

エラー処理(エラー内容をクリアする)

On Error GoTo -1ステートメントは、エラー情報をクリアすることが出来ます。再度エラー処理を適応することが可能になります

'エラー情報をクリアする
On Error GoTo -1

処理を移動させずに、エラー状態の解除のみを実行するには「On Error GoTo -1」ステートメントを使用します

このステートメントを使用する場面は、エラーが発生している状態で、さらにエラーが発生した場合にどうしたいかによります
つまりエラー処理中のエラーはどうするか、という点です

エラー処理中のエラー発生について

エラールーチン中にエラーの再発生したときの動き
エラー処理中のエラー発生時の動き

画像の動きを確認してください
エラーが発生した際、On Error GoToステートメントにより「エラー発生」のラベル行に処理が移動します

このとき、エラー情報は発生したものが保持された状態です
この状態をエラールーチンが行われている状態といいます

このエラールーチン中に、再度エラーが発生した場合はステートメントの影響に関係なく実行時エラーが発生して処理が停止します

エラー処理とはいえ、処理である以上その処理にエラーが発生する可能性があります
その際にユーザーに処理停止を対処させるのは難しい話である場合が多いと思います

そこで、エラー処理中にエラーが発生したら、エラー処理を行いたい
こういった状況が出てくることがあります
そんなときに使用するのが、このステートメントになります

ステートメント使用時のエラー処理

エラールーチン中にエラーを解除する動き
エラー情報をクリアした時の動き

On Error GoTo -1ステートメントを使用している場合の動きになります

エラー発生:
On Error GoTo 0
On Error Resume Next
'Err.Raise (1)
On Error GoTo -1
Err.Raise (1)
Debug.Print "エラー終了"

この処理が画像のエラー処理部分になります

On Error GoTo 0

まず、最初にOn Error GoTo エラー発生の設定を解除するためにこのコードを実行します
これをしていないと、後で発生するエラーでまた「エラー発生:」に戻ってきてしまい無限ループに入ってしまいます

これで、エラーが発生したらメッセージが出て処理が停止する通常の状態になっています

ただ、このステートメントはエラー発生時の制御を解除しただけであり
エラー情報をクリアしたわけではないので、エラールーチンは継続中です

On Error Resume Next
'Err.Raise (1)

次に、エラー処理中にエラーが発生した場合の対応を作成します

今回はエラー処理中に発生したエラーは無視するように設定しますので、On Error Resume Nextステートメントを使用します

2行目はエラー発生させるコードをコメントアウトしています

実際、ここでもまだエラールーチン中なのでエラーが発生した場合は実行時エラーが発生し処理が停止します

On Error GoTo -1

ここでようやく記事のステートメントを使用しています

この時点で、エラー情報がクリアされます
そして、その時点でエラールーチンも終了しています

これにより、上記で設定したエラー発生時の制御が有効な状態になります

Err.Raise (1)
Debug.Print "エラー終了"

画像の動きと合わせて確認してください

ここでエラーを発生させていますが、処理は停止せずに最後のエラー終了の文字列出力まで実行されています

エラー処理中のエラー対応について

通常エラーの解除にはResumeかResume Nextのどちらかのステートメントを使用しますが、このステートメントでは処理が戻ってしまいます

通常、処理の組み方としてはそれが正統な作り方だと思います
でも前述したように、エラー処理を作成するということはそこでもエラーが発生する可能性は十分にあり得ます

例えば、以下の記事の動きを確認してもらいたいのですが
エラー処理でLong型変数に加算していき使用できる整数値で処理が正常に戻ります

ただ、このエラー処理でも使用できる数値がLong型の範囲内になかった場合
加算され続けて、いずれオーバーフローして実行時エラーが発生します

処理上、ほぼあり得ませんが
エラーが出ない処理は無い、ということは事実として存在します

なので、このコードを実行することによってエラーの発生がクリアされるので再度エラーが発生した場合は改めてエラー処理を適応することが出来ます

ただ、エラーの情報がクリアされるので当然エラーの発生した行もどこにあるかが分からなくなります
なので、Resumeステートメントなどでエラー発生した行に戻ることはできなくなるので注意が必要です

エラー処理(エラー処理後に戻す)

Resume Next・Resumeステートメントを使用すると、エラー処理後に処理を戻すことが出来ます

'エラー発生の次行に戻す
Resume Next
'エラー発生行に戻す
Resume

エラーが発生して、On Error GoToステートメントで処理を移動させていた状態から元のエラー発生した場所に戻すには「Resume Next」「Resume」ステートメントを使用します

戻す場所によって、コードを使い分けます

エラーが発生した行の次行に戻すにはResume Nextステートメントを使用します
エラーが発生した行に戻すにはResumeステートメントを使用します

動きの確認

エラー処理後に次の行から再実行する動き
Resume Next

エラーが発生した次の行に処理を戻すコードです

次の行に処理が戻るので、もともとエラーが発生した処理は実行されません
つまり、そのエラーが発生した処理が以降の処理に影響を与えない場合にのみ使用できます

当然、以降の処理にこのエラーが発生した処理を前提としていた場合バグが発生します

例えば、フォルダの新規作成や、存在しなかったファイルの削除など
エラーが発生すること自体は処理に影響を与えない場合に利用できます

On Error Resume Nextステートメントでもエラーが無視できますが、エラー処理が行えません
ユーザーにエラーが発生していることはメッセージで伝える必要がある場合はこちらのコードでエラー処理を作成してコードは次の行から再開させます

エラー処理後エラー発生行から実行する動き
Resume

このコードはエラーの発生した行に戻します

エラーが発生した行に処理を戻すことになるので、このエラー原因を解消するようにエラー処理を組まないと、無限ループに入ってしまいます

画像の動きを確認してください
A1セルからマイナス方向への移動ができないため、エラーが発生します

エラー処理では、移動値に数値を加算してから処理を発生行に戻しています

しかし加算値が「1」なので「-2」からは2回実行する必要があるので、2回エラーが発生して、最後にまた「0」になりA1セルが指定されて処理が正常動作に戻ります

このように、エラー処理で複数回繰り返してでもエラー原因を解消するような組み方が重要になります

ファイルの名前を付ける際に、重複しない連番をここで更新していくことで取得することが出来ます

なお、どちらのステートメントもエラー処理に使用するコードとなります
エラーが発生していない状態で実行されるとエラーが発生します

エラー発生後のエラー処理の最後に入れるようにします

エラー処理(発生時に移動させる)

エラーの発生時に任意の箇所に処理を移動させるコード。On Error GoToステートメントを使用します

'エラー発生したときは移動させる
On Error GoTo エラー発生

エラー発生:

エラー処理として、エラーが発生した際に特定の処理を実行する場面があります

その場合、エラーが発生した時点で実行するステートメント行を移動させることになります
その際に使用するのが「On Error GoTo」ステートメントです

On Error GoTo エラー発生

このステートメントに指定した文字列がラベル文字列となります
行指定も出来ますが、通常は例のように文字列で指定します
ここでは「エラー発生」の部分が当てはまります

このコード以降にエラーが発生した時点で、処理は停止せず指定した行に処理が移動されます

なお、ラベル文字列の設定はGotoステートメントと同じ設定の仕方になるので混同しないようにわかりやすい名前を付けましょう
Gotoメソッドと同じようにラベル文字列行の前には処理を終了させる「Exit Sub」を配置するようにしましょう

この設定を解除するには「On Error GoTo 0」ステートメントを使用します
解除しないと、以降の全ての処理でエラー処理が実行されますので、エラーの予期している範囲で使用するようにします

コードの動き

エラー発生時に処理を移動させる動き
エラー発生時の動き
Err.Raise (1)

このコードはエラーを意図的に発生させるコードです

このコードが実行された時点で、エラーが発生しOn Error GoToステートメントにより処理が移動しています

通常、エラー処理は正常処理の後に作成します
そのままEnd Subまで走らせる形で処理を継続させます

エラーが発生せずに処理が通常終了する動き
エラーが発生しない場合の動き

エラーが発生せずに正常に処理が実行された場合の動きです
終了コードにより、End Subまで行かずに処理を終了させています

これが通常のエラー処理の組み込み方です

処理終了コードを入れていない場合の間違った動き
終了コードを入れてない場合の動き

この画像のように、終了コードを入れ忘れていた場合、正常処理後にエラー処理が実行されてしまいます

Exit Sub
エラー発生:

なので基本的には、以上のような形でコードを作成するようにしましょう

EOF関数(プロパティ)

EOF関数(プロパティ)はデータの末尾を判定するために使用します

EOF関数とは、開かれているデータの末尾を調べる関数です
データベースではプロパティとして使用されます

データが末尾に到達した時点で「True」を返します
それ以外の時点では「False」を返します

主に使用するのは、テキストデータの読み取りや、データベースデータのレコードの最終データの判定に使用します

関数の書式

引数(太字は必須引数)
(Filenumber)
戻り値の型 Integer型(Boolean型)

引数「Filenumber」はOpenステートメントで開いたときのファイル番号です

プロパティでの使用時に引数はありません

実際の使用場面

今回はよく使用するテキストデータの末尾判定処理を行います

取得を行うテキストデータ
末尾判定を行うテキストデータ

この画像のテキストデータを取得しながらEOF関数の動きを確認します

Sub 処理テスト()
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
    Do Until EOF(1) = True
        Debug.Print EOF(1)
        Line Input #1, 文字列変数
        Debug.Print 文字列変数
    Loop
    Debug.Print EOF(1)
Close #1
End Sub

このコードが今回作成した処理です
内容としては、テキストデータをメモリ上に読み込みモードで開き
そのファイル番号をEOF関数で「True」が返されるまで取得し続けるループ処理です

EOF関数のコード上の動き
コードの動き

画像の動きを確認してください
EOFがテキストデータの存在している場合には「False」が返されています
データが末尾に来た時点で「True」が返されてループが終了しています

この判定を行っていないと、データが存在しない状態で参照しようとしてエラーが発生します

また、ループ条件の1行に関して

    Do Until EOF(1) = True

この部分に関しては、If関数と同様に比較を行わない方法でも構いません

    Do Until EOF(1)

この様に、「=」以降は入力しなくても関数がTrueを返して条件が成り立つので必要はありません

ただ、それはある程度知識のある人が見てパッと分かるようなコーディングだと思いますのでIfステートメントにしても、自分は「= True」は省略しないようにしています

比較を行わないので、処理速度にも影響はあるようです
見やすさの方が重視するので、あまり気にしませんがねぇ

なお、テキストデータを一括で1つのデータで読み込む場合は
以下の方法も利用できます

テキストデータを1文字ずつ取得する

テキストデータから指定文字数を取得するにはInput関数を使用します。Input#ステートメントとは別物になります

'テキストデータから1文字取り出す
文字列変数 = Input(1, 1)
'テキストデータから1文字ずつ全て取り出す
Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
Do Until EOF(1) = True
文字列変数 = Input(1, 1)
Debug.Print 文字列変数
Loop
Close #1

テキストデータから指定の文字数を取得するには「Input」関数を使用します
同じ名前のInput#ステートメントとは使い方が全く違いますので注意してください

例えば、テキストデータの文字列の文字コードを調べていきたい場合に使用できます
文字コードの取得は1文字ずつしか行えませんので、この関数で1文字ずつ取得していくことで簡単に調べることができます

関数の書式

引数(太字は必須引数)
(Number, Filenumber)
戻り値の型 String型

引数「Number」は取得する文字数です。バイト数ではなく文字数になりますので、半角も全角もどちらでも1文字は「1」になります

引数「Filenumber」はOpenステートメントで開いたファイル番号です

コード解説

文字列変数 = Input(1, 1)

関数で戻り値があるので、基本的に変数などに代入させて使用します

このコードでは、ファイル番号1の1文字を取得します
この関数をコード中で再度実行すると、次の文字が取得されます
なので、ループ処理を使用することで最後まで取得させることができます

2つ目の例コードのループ処理を以下で解説します

Open ThisWorkbook.Path & "\新しいテキスト ドキュメント.txt" For Input As #1
~~ 中略 ~~
Close #1

Openステートメントの取得モード「Input」で指定テキストファイルを開いています
この時、対象ファイルが存在しない場合は新規作成されてしまいます

Close#ステートメントで開いたデータをメモリから閉じています

Do Until EOF(1) = True
~~ 中略 ~~
Loop

テキストデータを最後まで参照するためのループ処理です

取得するテキストデータの最終データを判定するEOF関数を使用してループを行います

文字列変数 = Input(1, 1)
Debug.Print 文字列変数

ここで1文字を取得して、イミディエイトに出力しています

このループ処理のイミディエイト出力の箇所に、処理を組めばテキストデータを1文字ずつ加工していくことができます