どうも。つじけ(tsujikenzo)です。こちらのシリーズではノンプロ研VBA初級講座3期で学んだことをアウトプットしております。本日は5回目です。(内容が多いので分割しました)ここまで振り落とされずになんとか毎週ついてこれましたがここにきて脱落です。GAS、Pythonに続き3言語目ですが、VBAが一番難しい気もします。。。
Day5 Rangeオブジェクト
今日のアジェンダ
1.Rangeオブジェクト
2.セルの値
3.セル範囲のループ
ちょっと前回の振り返りと今日やること
Rangeオブジェクトが複数ある場合はRangesコレクションが無いのかという話については、Rangeオブジェクトは特殊でFor Eachでも回せることもあり、コレクションの特性も持っているという認識だそうです。(その要素はRangeオブジェクトです。)
おさらいですが『Rangeを操作したいなら、オブジェクト式で対象となるオブジェクトを指定しないといけません』でしたよね?ここは十分に復習しておきましょう。
○○.Range()の○○の部分はどうやって指定するのかという話でした。
本日は○○.Range()の.の右側、セルの取得方法がRange()とCells()の2種類あるよという話からスタートです。
Range() とCells()
Range(A1Notation)プロパティ・単体、もしくは範囲
Cells(行:列)プロパティ・・・・単体セル
(なぜプロパティなのに引数のように値を渡せているのかは疑問ですが、あまり深入りしないことにします。。。ゲッター/セッターだそうです。)
CurrentRegionプロパティ
そもそもCtrl + Shift + *でデータのあるセル範囲を選択できることを知らなかったが、これはセル範囲のどこかにアクティブセルを置いておかないとダメ。なので起点となるRangeオブジェクトを指定しておくことが大事。(空白セルが間に入ってると途切れてしまうので注意。起点セルからCtrl + Shift + 上下右左って感じかな)
Rangeオブジェクト.CurrentRegion
UsedRangeプロパティ
シートの使用されているセル範囲を取得する。先ほどと違い、対象がワークシート。
Worksheetオブジェクト.UsedRange
Selectionプロパティ
選択されているオブジェクトを取得する(グローバルにSelectionと書ける。)図形なんかも対象になる。
【MEMO】
イミディエイトウィンドウで下記のように記述し、現在選択されているセルアドレスを確認する場合がありますが、
? Sheet1.UsedRange.address
? Selection.address
selectionの後のピリオドを打っても入力補完の候補が出てきません。それは図形(Shape)などを選択している状態ではaddressプロパティが使えないので、Selectionはグローバルオブジェクトなのでいきなり書き始められるが、対象のオブジェクトが不明な為にメンバー候補が出ないということです。worksheets(1).などでもメンバー候補が出ないのは、シートオブジェクトにも「マクロ」や「グラフ」のようなシートもあって「ワークシート」だけではないからです。
セルの値
VBAにはValueプロパティが存在しており、取得することも書き込みすることも可能。(ここがGASとの大きな違いです)Valueプロパティは記述を省略することができるが、省略しないことを薦めます。
下記の2つはRangeオブジェクトそのものを示しているのか、値を示しているのか前後のコードを読み解かないといけないからです。
Rangeオブジェクト
Rangeオブジェクト.Value
Copyメソッド
正しく言うと「コピペメソッド」と言った方がいいです。コピーだけでなく、張り付け先のRangeオブジェクトの起点を半角スペースの後に続けて記述するという(私にとって)とてもトリッキーなメソッドです💦
こういうの(トリッキーなメソッド)はちょっと腹立たしいので、実験しましょう。下準備です。
Sheet1.Range("A1").Copy Sheet2.Range("A1")
動いているようです。
そして実験をしようと思ったけど、『パーフェクトVBA』に答えが載ってました。
CopyやCutメソッドの引数にRangeオブジェクトを指定することにより、左上隅を起点として貼り付けが行われます。取得したRangeオブジェクトと貼り付け先のRangeオブジェクトのサイズは等しくなくても構いません。なお貼り付け先を省略した場合はクリップボードに保管するのみとなります。形式を選択して貼り付けをしたい場合には、PasteSpecialメソッドを使用して貼る付けをすることができます。
後、「半角スペース」という書き方も疑問がありますが、今回はスルーします💦
【MEMO】
どうしてもスルーできないことがあったのでTwitterに投稿しました。「クリップボードに保管」って。。。
これが一行で書けるのは分かる。
Sheet1.Range("A1").Copy Sheet2.Range("A1")
そんでコピーとペーストを分けるなら、GASとPythonでメモリのこととか勉強して
きた身としては、変数(メモリ領域をね)用意して代入しておきたいじゃないですか。
Dim cp As Range
cp = Sheet1.Range("A1").Copy
そんでcpを使ってペーストしたいんですけど、どう考えてもこうなんですよ。
Sheet2.Range("A1").Paste
なので正解はこう。
Sheet1.Range("A1").Copy
Sheet2.Range("A1").Paste
これ、メモリどうなってるの?ってしばらく考えて答えが
「クリップボードに保管でした~」の私の顔。
('_')
Loop文
for next文を.Cellsプロパティと組み合わせて書くのは直感的で分かります。
With Sheet1
Dim i As Long
For i = 2 To 4
Debug.Print .Cells(i, 1).value, .Cells(i, 2).value
Next i
End With
しかし最終行が分からない場合がほとんどです。そういう時はDo While文が活躍します。
Do While 条件式
Loop
With Sheet1
Dim i As Long: i = 2
Do While .Cells(i, 1).Value <> ""
Debug.Print .Cells(i, 1).Value, .Cells(i, 2).Value
i = i + 1
Loop
End With
条件式に書かれている<> “”は
「<>」は「等しくない」という意味です。「=」の逆ですね。
また、「””」は空文字、つまり何も入力されていない状態を表しています。
とのことですね。びっくりしました💦
for Each文
他の言語でも散々考察してるので、比較的理解が早い気がします。構文の[セル範囲]には複数のオブジェクトが格納されたコレクションのようなオブジェクトが必要で、その中身をぐるぐる[変数]に代入しながらループをまわすんでしょうね。きっと。
講師がさらっと「テーブルって使ってますか?」と。リストオブジェクトとして操作できる・・・?中級でやるそうなので楽しみです。
まとめ
以上で第5回目でした。もうちょっと頑張ります。