空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

【VBA】Excelで、ひとつ上の可視セルの値を取得して貼り付けする

Excelでフィルタの適用状態に関わらず、任意のセルの(見た目上の)ひとつ上のセルの値を取得しようというもの。

元ネタはこちら
koroko.hatenablog.com
別の方法で、こちらでも。
infoment.hatenablog.com

両者とは別のアプローチで・・・

目次

抑えておくべき事

Range.Areasオブジェクト

MSのサイトより抜粋。

選択範囲内にある領域 (隣接しているセルのブロック) のコレクションです。

Areasコレクションの各メンバーは、 Range オブジェクトです。 Areasコレクションには、選択範囲内の各セルの不連続な連続した範囲のrangeオブジェクトが1つ含まれています。 選択範囲に領域が1つしか含まれていない場合、 Areasコレクションには、その選択範囲に対応するRangeオブジェクトが1つだけ含まれます。

https://docs.microsoft.com/ja-jp/office/vba/api/excel.areas

Rangeオブジェクトは、Range("A1:C3") といった指定をした場合のように、単一の矩形領域の場合だけでなく
Rrange("A1:C3,D2:F4")とか、Unionメソッドにより複数の矩形領域を纏めてひとつのRangeオブジェクトとして扱ったりする場合もあります。
それらの1個以上の矩形領域をCollectionとして纏められたものが、Range.Areasオブジェクトです。

Itemプロパティ

Areasオブジェクトに含まれているひとつの要素(Rangeオブジェクト)を返すプロパティです。

構文
Areas.Item(Index)

パラメーター

名前 必須/オプション データ型 説明
Index 必須 Long オブジェクトのインデックス番号を指定する。

省略記法
Areas(Index)
という記述でも同様に処理できます。

Countプロパティ

Areasコレクションに含まれるオブジェクトの数を返すプロパティです。
これにより前述のItemプロパティに指定できるインデックスの上限値がわかります。
構文
Areas.Count

実際の例

領域が分かれることで、Areas.Countが増え、それぞれの要素(Rangeオブジェクト)の情報(下の例ではAddress)を取得できています。
f:id:Z1000S:20190915101422j:plain

フィルターを使用している場合

フィルター適用前の状態が下図の要なデータで見てみる。
f:id:Z1000S:20190915104847j:plain

C列のデータを選択した状態
f:id:Z1000S:20190915104858j:plain

B列をDDで抽出した状態
f:id:Z1000S:20190915105629j:plain
SpecialCells(xlCellTypeVisible)を指定しないと、非表示のセルも含まれてしまう。
SpecialCells(xlCellTypeVisible)を指定することで、可視セルのみを対象としている。
また、非表示セルが間に入ると、Areasオブジェクト内のItemプロパティで取得する領域が別々になっている

処理

考え方

  1. 上記のフィルター適用時の結果から、基準となるセルの上の全てのセルのうち、表示されているセルと、基準のセルをUnionで纏める。
  2. 基準となるセルは、Unionで纏めたRangeの一番下なので、Areas.Item(Areas.Count) にある。
  3. Areas.Item(Areas.Count).Rows.Count が1ならば、基準セルのひとつ上のセル(見た目ではなく実際の1行上のセル)は非表示なので、Areas.Item(Areas.Count-1) の一番下のセルが求めるセル。
  4. Areas.Item(Areas.Count).Rows.Count が2以上なら、基準セルの1行上のセルは表示されているので、基準セルの1行上のセルが求めるセル。

コード

取得データ貼り付け処理

データ取得処理

コードをコピーしたい方へ

いつもの通り、コードはダブルクリックすれば選択できますので・・・

使い方

pasetFromAboveCellsValueをイミディエイトウィンドウから呼ぶなり、
適当なボタンに登録するなり、使いやすいようにして下さい。

実行サンプル

f:id:Z1000S:20190915123340g:plain

最後に

今回は、前回のやつがあったから気がつけた。
ちょっと満足。

z1000s.hatenablog.com

貼り付けだけが目的であれば、プロシージャを分けずに1つにした方が
無駄なコピーが無くせるので、スッキリするかも。



単一のセルだけでなく、複数のセルに対応したのと
データの途中の行でも実行可能なので、少しは使えるか?