表示位置を指定セルに移動する

指定セルにShowメソッドを使用すると見える位置に移動できます

'A10000セルを見える位置に移動
Range("A10000").Show

処理を終了させた段階で指定の個所を見える様にしておきたい場合があります
そんなときに使用するのが「Show」メソッドです

このメソッドを使用すると、指定したセルがウィンドウ内に収まるように自動的にスクロールされます
また、その際に指定したセルは選択状態にはなりません

選択セルは変更したくないけど、画面を移動させたい場合に有効です

ただ、画面内のどこかまでが指定できません
しかも指定セルが画面内にあれば移動しない場合もありますので少し注意が必要です

コードの動き

メソッドの動きの確認
コード実行時の動き

実際にコードを実行してみると、動きがわかりやすいです

画像の動きを確認してください
A10000セルを表示状態にすると、真ん中に表示されるように画面がスクロールされています
そしてその際、選択セルがA1のままで選択範囲が移動していないことも確認できます

そして、このメソッドの最大の注意点が、画面更新を抑止している時には無効になる点です
画面更新を抑止した状態でA1セルを対象に実行しても変化がありません
抑止を解除してから、再度実行するとちゃんと画面が移動します

処理後に画面を移動させたい場合は多いので、あまり問題にならないとは思いますが画面更新を抑止する処理を作成した場合は解除してから実行するようにしてください

ただ、解説したように画面のどこに指定セルが表示されるか分からないので、どうしても指定セルを指定場所に表示させたい場合はApplication.Gotoメソッドを使用してください
こちらのメソッドであれば左上限定ですが、セルの表示位置を指定できます
あとはOffsetプロパティやスクロールさせれば思い通りの表示状態を作成することができます
Application.Gotoメソッドについては以下の記事で解説しています

セルが結合されているか調べる

MergeCellsプロパティではセルの結合状態を取得できます

'選択範囲が結合セルかを調べる
Debug.Print Selection.MergeCells
'シート内に結合セルがあるかを調べる(Nullなら存在有)
Debug.Print Cells.MergeCells

指定したセルが結合セルかどうかを調べるには「MergeCells」プロパティを使用します
このプロパティの返し値によって判定を行います

指定したセルが結合されていれば「True」、結合されていなければ「False」をそれぞれ返します
さらに、その両方が含まれていれば「Null」が返されます

なお、このプロパティは設定も可能です
Trueを代入すると結合セルとなり、Falseを代入すると非結合セルとなります
実際の書き方は以下の記事にありますので確認してください

コード解説

結合セルの存在を確認するプロパティの動き
プロパティ取得の動き

この画像の前提として、A2とB2が結合されたセルです

Debug.Print Selection.MergeCells

結合されたセルが選択状態になっていますので、このコードを実行するとTrueが返されます
つまり、選択している範囲は結合されて1セルとなってい状態と判定できます

このプロパティは、単体での判定でしかTrueを返しません
例え指定範囲が全て結合されたセルだとしてもNullが返されてしまいます

逆にすべてが結合されていないセルであればFalseが返されます

そしてその仕様から、シート全体などの範囲で使用することで結合セルの存在を調べられます

Debug.Print Cells.MergeCells

このコードを実行するとNullが返されます
結合セルとされていないセルが範囲内に含まれているからです

画像の最後の動きの部分を確認してください
再度取得する前に、すべての結合を解除しています
その状態でプロパティを取得させると、Falseが返されます
つまり、シート内に結合セルが存在しないことを意味します

どのセルが、という所まではこのプロパティで調べられませんが、存在するかどうかは調べられます

基本的に結合セルとは、見栄えなどの書式的な使い方が多く、VBA泣かせのセルです
あったら何とか解除してしまえないかと思ってしまいますが、この判定や解除をうまく活用して乗り越えてください

セルの結合を解除する

セルの結合を解除するにはUnMergeメソッドを使用します

'選択範囲内セルの結合を解除
Selection.UnMerge
'選択範囲内セルの結合を解除
Selection.MergeCells = False

結合されたセルの結合を解除するには「UnMerge」メソッドを使用します
このメソッドは指定した範囲内にある結合セル全てを一括で解除します

また、本来は結合セルの存在確認を行うMergeCellsプロパティにFalseを代入することでも実行することが出来ます

コード実行時の動き

セル結合の解除の動き
セル結合解除の動き

画像の確認をしてください
前提として、2行目はすでに結合済みのセルです
結合解除を行った際に、そちらは解除されていないことを確認してください

Selection.UnMerge

選択範囲内にあるすべての結合セルの結合を解除します
指定範囲を限定することで、シート内に複数の結合セルがあったとしても限定して解除することが可能です

Cells.UnMerge

なので、逆に指定範囲を広げてシート全てのセル範囲を指定するとシート内にあるすべての結合セルの結合を解除することが出来ます
書式統一のために使用された結合セルが多いので、あまりこういった使い方はしないかもしれませんが、結合セルがシート内に1つしか無いのであれば、そのセル範囲を検索する必要がなく楽に解除することが出来ます

MergeCellsプロパティに関しては別の記事で解説していますので、ここでは割愛します

セル範囲を結合する

セルを結合するにはMergeメソッドを使用します

'選択範囲の結合
Selection.Merge
'選択範囲の横方向への結合
Selection.Merge True

セル範囲を結合するには「Merge」メソッドを使用します
このコードを使用すると指定したセル範囲が結合セルとなります

またメソッドの引数に「True」を指定することで、横方向のみの結合を行うことが出来ます

Selection.MergeCells = True

本来は結合セルの存在確認に使用するMergeCellsプロパティを使用することでも、例コードの1つ目と同じ動きの結合を行うことが出来ます

コードの動きの解説

セル結合時のコードの動き
セル結合時の動き

各結合の後にある「Cells.UnMerge」は結合セルを解除するコードです
結合の動きを確認するために書いています

Selection.Merge

これを実行すると、選択範囲が1つのセルに結合されます
行列ともに1つのセルとして結合されます

Selection.Merge True

このメソッドの引数にTrueを指定することで横方向のみの結合を行うことが出来ます
画像の動きを確認してください
選択範囲が複数行である場合に、横にのみ結合が実行され、縦方向には結合が実行されていないことが確認できます

これは、通常操作の「横方向に結合」と同じ動きをします
複数行で縦には結合しない場合に一括で指定することが出来る方法です

1つ目では省略されていましたが、この引数を省略するとFalseが指定されていることになります

Selection.MergeCells = True

このコードは、通常は選択範囲に結合セルが存在するかを調べて、存在すればTrueを返すプロパティですが、Trueを代入することで例コードの1つ目と同じ動きを実行できます

ただ、このコードでは横方向の指定が出来ません
ですが、解除する場合も使用でき、Falseを代入するだけで可能です

結合するにはTrueを、解除するにはFalseを代入するというのがイメージしやすいので使い勝手はいいと思います
蛇足ではありますが便利なので紹介します

コード実行時の注意点として、指定範囲に複数のデータが存在する場合はExcelの警告が発生します

結合時のデータ欠損の警告メッセージ
データ欠損の警告

結合セルを使用したことがある人なら見たことあると思いますが、複数のデータがある場合にデータの欠損が発生するため警告が表示されます
ここでキャンセルを選択すると、実行時エラーが発生します

動的にセル結合を行う場合にはこの点のみ注意が必要です

セル範囲サイズを変更する

セル範囲を指定の行数・列数の範囲に変更するにはResizeプロパティを使用します

'A1から1行3列の範囲を選択
Range("A1").Resize(1, 3).Select

セル範囲サイズを減らしたり増やしたりする場合には「Resize」プロパティを使用します

このプロパティを使用すると、指定セル範囲の左上のセルから指定した行・列数のセル範囲に変更できます

例コードではA1セルを起点にセル範囲を変更しています
プロパティの引数1つ目が行数、2つめが列数になりますので、ここでは1行3列を指定することになります

つまり、「A1,B1,C1」の3つのセルが選択状態になります

使用時の動き

セル範囲サイズの変更の動き
コード実行時の動き

実際にコードを実行したときの動きの画像です
この動きを元に解説を行います

最初にA1セルを選択状態にしています

次に記事コードを実行します
例コードと同じものを実行してますので、解説した通りA1~C1セルが選択状態になります

言うなればこのコードは「Range(“A1:C1”).Select」と同じ動きをすることになります

そして上記でも解説したように、このプロパティで指定される起点となるのはセル範囲の左上のセルです
そのため、アクティブセルをC1に移動させてから実行したとしても範囲が移動することはありません

また、その際にセル範囲選択が再設定されるためアクティブセルは左上に移動してしまいます
この点については、アクティブセルを参照する様な処理作成を行っている場合には注意が必要です

このプロパティの大きな使い道は、特定の列だけに選択をさせたり、データ表範囲の見出しだけを除いて選択状態にする様な場合に有効なプロパティです

またこのプロパティを有効に使用すれば、配列データを出力する際の範囲選択も簡単に行うことが出来ます

セルのデータ取得時の情報について

Value・Text・Formula・Value2の各プロパティを使用するセルの情報取得時の種類の解説

Debug.Print Range("A1")

セルに入力されたデータを取得する際には通常上記のコードで対応します
このコードを実行すると、アクティブシートのA1セルの内容がイミディエイトに出力されます

A1セルに「100」と入力されていれば、出力されるのも「100」です
これは当然の話ですが、このコードには実際にはセルの入力値を指定するプロパティが省略されています

Debug.Print Range("A1").Value

省略しない形の場合は、このコードの様になります
省略した場合の既定のプロパティは「Value」プロパティです

これは入力されている値を取得するプロパティです
通常値の取得には、なんの問題もありませんので処理中ではほぼ省略する形で作成することが多いプロパティです

ただ、セルにあるデータをイメージしてください
セルには数値や文字列以外にも入力されるものがあります、日付やエラー値、関数などです
このあたりを取得したい場合にはValueプロパティでは対応できなくなります
その場合にはそれぞれ別々のプロパティがあります

取得情報によって切り替えるプロパティ

取得を行うセルの入力状態
取得を行うセル

このプロパティを説明するうえで一番分かり易い例が、関数で求められた日付データです
この画像のA2セルを対象に取得を行ってみます

同じセルを違うプロパティで取得した状態
別々のプロパティで取得した状態

先にこの画像を確認してください
これらの他にも取得プロパティは有りますが、とりあえずこれだけあればおおよそ問題ありません

Debug.Print Range("A2")
Debug.Print Range("A2").Value
→→→ #2020/05/19#

これはすでに解説したようにValueプロパティが省略されているので値が取得されます
なので、この2行のコードは同じものを意味しています
日付データを取得しているので、日付の両側に#が付与されています

Debug.Print Range("A2").Text
→→→ "2020年5月19日"

セルに表示されている状態のデータを取得するには、「Text」プロパティを使用します
これは基本的には、表示形式が適用された後のデータを取得します
Textなので、例え数値であっても文字列として取得されます

そして、このプロパティは「表示されている状態」の、と言ったように画面に見えている状態を取得します

例えば、入力値がセルの列幅より大きく表示できない場合Excelでは「#」の連続文字列で表現されることがありますが、それもしっかりその文字列を取得します

表示されているものを取得している状態
「#」が取得されている

この画像の様に「#」がイミディエイトに出力されます
実際は上記の内容と全く同じデータで「2020年5月19日」が入力されていますが、列幅を狭めた結果、表示できない表現として画像の様になります

Textプロパティはこの表現さえも素直に取得を行います
画面に表示されている状態というのは、こういうことになります

Textプロパティは表示形式が適用されたデータではない、という点に注意が必要です

ちなみに、この内容を反対に応用すれば入力したデータが列幅に収まっているかどうかを判定することも出来ますね

Debug.Print Range("A2").Formula
→→→ =A1+B1

数式を取得する場合は「Formula」プロパティを使用します
このプロパティであれば、関数の結果の値ではなく数式自体を取得することが可能です

VBAでセルに入力された数式を取得して作業を行うことは少ないのですが、配列への代入時などでは重宝するプロパティです

また、このプロパティはセル入力値が数値や文字列であれば、それをそのまま取得するので数式以外が取得できない、というものではありません

Debug.Print Range("A2").Value2
→→→ 43970

日付データが実際には内部数値で扱われている、という点はある程度Excelを勉強した方ならご存じかとは思います
その内部数値を取得することが出来るのが「Value2」プロパティです

このプロパティは、なんの加工も行われていない純粋なデータを取得するプロパティです
リファレンスでも書いてあることなのですが、その性質上セルのプロパティで処理速度が最高のプロパティです

処理速度は間違いなく速いです、そこでValueプロパティと比較してみました
リファレンスにもあり、結果が明らかですのでコードは記載しませんが、内容としては変数にセルの入力値を代入させるだけの処理をループ処理で実行しました

自分の環境になりますが、100万セルで0.1秒ほどの差でした
Value2プロパティの方がやはり速かったです

ですが、100万セルで0.1秒ほどなので相当量のビッグデータを扱う際に気にしてみる
程度で十分な差でしかありませんでした

ちなみに、これも明らかですがTextプロパティは圧倒的に遅かったです
これは文字列を扱っているので想定の範囲内ではあります
まあ、Textプロパティは目的があって使用する場面の方が多いのであまり気にしなくても良いかなとは思います

処理速度の優位性はありますが、内部数値が欲しい、という場面でValue2プロパティを使用すれば良いです

見出し行以外の全範囲を選択する

見出し以外の全体を取得します
データ範囲のみの取得や初期化に使用します

'2行目以降を全て選択する
Cells. _
Resize(Cells.Rows.Count - (Range("A2").Row - 1), Cells.Columns.Count). _
Offset(Range("A2").Row - 1, 0). _
Select

表範囲の中で、見出し(見出しを1行目だけとした場合)以外の行を取得します
見出し以外を全て新たなデータに置き換える時にデータ範囲を全て初期化する時に使用します
なお、解説の為に改行しています

2行目以降の全ての範囲を選択する
コードを実行した時の動き

画像のような表範囲の中で、1行目が見出しで2行目以降がデータ範囲である場合にコードを使用することで見出し以外の範囲を全て選択することができます
少し見づらいですが、左下のウォッチ式の中の値がA1から行範囲にアドレスが変化している部分を確認してください

また、少し応用すると空白を除いた純粋なデータ範囲のみを取得する事も可能です

コード解説

Cells. _

何よりまずは、セル全体を指定しますのでCellsオブジェクトに対して処理を行います
Cellsオブジェクトは引数を省略した場合はセル全体が取得されます

Resize(Cells.Rows.Count - (Range("A2").Row - 1), Cells.Columns.Count). _

次に、Resizeプロパティを使用して範囲サイズの変更を行います
このプロパティは引数に指定した数値のセル範囲を取得するプロパティです

この際に指定する数値は、1つ目の引数が行数になります

(Cells.Rows.Count – (Range(“A2”).Row – 1),
この部分が1つ目の引数の部分になります、ここで行数を指定します
ここでは、A2セルを起点にするので2行目ということになります
2行目から取得を行うということは、除外するのが1行目の1行だけということになりますので、セルの全行数から1を引くことで指定することができます

とはいえ、その数値は固定では2行目以降しか選択できなくなってしまいますので可変にしておいたほうが便利です
そこでRangeオブジェクトのRowプロパティを使用して指定セルの行数を取得します
その行数から、-1します
これは、除外する行数の指定なので指定セルは除外対象になりません
なので除外する行数から-1してあげることで、指定セルの1行上が指定できます

Cells.Columns.Count)
2つ目の引数は列数の指定になりますが、今回は全ての範囲を指定するのでCellsオブジェクトに含まれている列数を指定します
これで全ての列の指定になります

これで、取得するべきセル範囲に変更することが出来ました

Offset(Range("A2").Row - 1, 0). _

Reiszeプロパティは、指定セル範囲のサイズを変更しますが、左上からのサイズ変更になります

つまり、上のコードで変更した行数では範囲の下から行数が削られていきます
なので、このままでは1行目が除外されるわけでは無く、最下行が除外された状態になります

そこでOffsetプロパティを使用して範囲を移動させます
Offsetプロパティは引数に指定した数値分、セル範囲を移動させます

今回は行方向への移動を行いますので、引数の1つ目に移動数を指定します
この移動値に関しては、Resizeプロパティで使用したものと同じになります

Select

最後に、この取得したセル範囲を選択状態にします
ここのメソッドを変更すれば、他の操作も可能になります

メソッドを使用せずに変数に取得させて、これらの範囲に対して色々な操作を行うことも出来ます

DoループでRangeオブジェクトを使用する

Doループを使用して、セルを移動させて検証していく際に、Range型の変数を利用する方法

'A2の下にある空白セルを選択する
Dim セル As Range
Set セル = Range("A2")

Do Until セル = ""
Set セル = セル.Offset(1, 0)
Loop
セル.Select

セル選択を減らすためには、RangeオブジェクトをForEachループで処理を行います
ただその処理は事前にセル範囲が分かっている場合に限定されます

今回の記事にある、空白のセルになるまで処理を繰り返す
というような、セル範囲ではなくセル単体を検証していくようなループではDoループで処理を行います

そして、その際にセルを選択することを無くすためには、コードにあるRange.OffsetプロパティやCellsオブジェクトなどで整数値を増減させて移動させます

この方法でセル選択は無くすことが出来るので、処理速度の向上は図れています

ただ、この方法での面倒な場合があります
それは別のシートやブックのセルを処理したい場合です
この場合には、シート名から指定する必要があり、コードが冗長になります
Withステートメントを使用する方法もいいのですが、あまり処理行が長い場合にはコードの可読性はあまり高くありません

そこで使用したいのが記事コードです

コードの解説

Dim セル As Range
Set セル = Range("A2")

Do Until セル = ""
Set セル = セル.Offset(1, 0)
Loop
セル.Select

このコードではセルを変数に代入して、それを更新していくことでセルの移動を行うループ方法です

DoループをRange型変数で実行した時の動き
コード実行によるセル選択

画像のコードの動きを確認してください
最初にA2セルが代入されて、ループ処理により検証取得されたセルを最後に選択しています、A2から下方向に空白のセルを検索しているので、A4が選択されて終了しています

Dim セル As Range
Set セル = Range("A2")

まずはセル変数の宣言と、初期位置の取得です
A2セルを取得させることで、この変数での初期位置とします

Do Until セル = ""

・・・

Loop

取得したセルが空白になるまでループを繰り返します
ただ、当然このままでは永遠にA2セルを参照し続けるので無限ループです

Set セル = セル.Offset(1, 0)

ここでセルを更新しています
セル変数に代入するセルは、その変数自体を指定することができます

このセル変数からOffsetを使用して1つ下のセルを代入させます

セル変数自体は、すでにブックやシートを含めたセルが取得されていますのでアクティブブックやシートである必要もありません

そして、ここでの代入によって次のセルが参照対象になるわけですが、セルへの参照が切り替わるだけでセル選択に関しては行っていませんので、メモリ上で処理が実行されています

なので整数型を使用した移動処理と差は感じられることは無いと思います

セル.Select

空白のセルが見つかったら、セルの更新が行われずにループを抜けるので
ループ後にそのセル変数を操作することが出来ます

別のシートのセル範囲を操作したいことは多いので、この方法を使用すればコードが非常にすっきりするので試してみてください

処理実行前の選択範囲に戻す

Application.Gotoメソッドを使用して、処理を実行する前のセル選択範囲に戻す方法

'処理前の選択範囲の取得
Application.Goto Selection

’取得したセル範囲を選択
Application.Goto

処理を実行する時にどうしてもセル選択を行う必要があり、しかも処理実行後にはもともと選択していたセル範囲に選択を戻しておきたい

そんな場面があります、そんな時に使用するのがこのコードです

コード解説

Application.Goto Selection

Range("A100:A103").Select
Range("B100:B103").Select
Range("C100:C103").Select

Application.Goto

記事コードを上記の様に変更しました
選択範囲を変更して処理実行前の選択範囲に戻します

処理実行前の選択範囲に戻る動き
処理実行後にもともとの選択範囲に戻す
Application.Goto Selection

Application.Gotoメソッドを使用して、最初にもともとのセル範囲を再指定します

ここは正直、引数にSelectionを指定する必要はありません
このSelectionはコードでいうRange(“A100:A103”)を指定しても構いません

コードの可読性の為にしているだけですね

SelectionでもRange指定であっても、このコードが実行された時点で、もともと選択されていたセル範囲がApplication.Gotoメソッドに保持されます

Range("A100:A103").Select
Range("B100:B103").Select
Range("C100:C103").Select

そのあとで、適当に処理を実行してセル選択を別の範囲にします
この時、選択範囲の変更は何度行っても問題ありません

Application.Goto

処理を実行して、またもともとの選択範囲に戻したい場合はApplication.Gotoメソッドの引数Referenceを省略して指定することで、もともとの選択範囲が指定されます

2つ目の引数ScrollをTrueに指定すれば、もともとの選択範囲を表示内の左上に表示させます

また、このメソッドは直前に保持した分のみしか保持できませんので
処理の中でApplication.Gotoメソッドを使用したい場合は利用できません

その場合はもともとの選択範囲をRange型のObject変数に代入して保持しておく方法で行います
あまりないとは思いますが・・・

ブックやシートの選択を含めてセル選択をする

Application.Gotoメソッドを使用することで、ブックやシートの選択をセル選択と同時に行います

'「Book1」の「Sheet1」のA2セルを選択する
Application.Goto Workbooks("Book1").Worksheets("Sheet1").Range("A2")

ブックやシートの選択をセルの選択と同時に行うには、Application.Gotoメソッドを使用します
このメソッドを使用すると、セルの選択を指定すると同時にブックやシートの選択も行います

RangeオブジェクトのSelectメソッドでもセル選択を行うことができます
ですが、アクティブではないブックやシートのセルを指定するとエラーが発生します

メソッドの書式

引数(太字は必須引数)
Goto Reference, Scroll

Referenceは、移動先のセルを指定します、ブックやシートも合わせて指定することでその範囲までを同時にアクティブにすることができます
また、ここを省略した場合はこのメソッドを実行した時のセル範囲が指定されますが、これに関しては以下の記事で解説を行っています

Scrollは、移動先のセルの表示に関する設定です
この引数にTrueを指定すると、セル範囲の左上を表示範囲の左上に合わせます
省略した場合は、Falseが指定されるので画面内であれば画面がスクロールしません

コード解説

Application.Goto Workbooks("Book1").Worksheets("Sheet1").Range("A2")

このコードでは、別のブックから指定のシートのセル選択を行います
Book1のSheet1のA2のセルを選択しています

ブック間のセル選択の移動
別のブックのシートのセルへ移動する

画像の動きを確認してください
特にシートのタブの部分に注目してください

シートのタブの見出しが変わっていることが変わると思います
ここから別のブックにアクティブが切り替わっていることが分かります

その後、A2セルが選択状態になっていることが分かります

Application.Goto Worksheets("Sheet1").Range("A2")

この様に、ブックは指定せずにシートから指定すればアクティブブックのシート間の移動が可能です
さらに、シートの指定もせずにRangeのみの指定を行えば、アクティブシートのセル選択を行います

Application.Goto Range("B3"), True

引数2つ目の、ScrollにTrueを設定したコードです
シートの指定も行っていませんので、アクティブシートのセル選択になります

指定セルを左上に合わせて表示する

画像の動きを確認してください
A1セルからB3セルへ選択が移動しています

ウィンドウ上ではセルが移動していないので、パッと見て分かりにくいですが
B3セルが左上に来ています

表の作成などを行って、最終的にその表を表示画面に綺麗に表示させる場合などに使用するといいかもしれません
通常の処理上では、ウィンドウ上での動きが分かりにくいので使用することは無いかもしれません