★ Access2000VBA・Excel2000VBA独学 ~ ExcelVBAで、行1行分の指定や選択・挿入・追加などの方法、いろいろ。(テーブル機能を使わない普通の場合と、テーブル機能を使う場合)~プラス、ついでに2行ごと、3行ごと、x行ごと、なとで、「下へずれて選択する」方法も少し。テーブル機能を使わない場合は、主に、Range.ResizeとRange.Offsetプロパティで。
  

★ はじめに

セル範囲の選択や操作には本当に色んな方法がありますが、その中でも特に、
「1行選択(あるいは指定)して、途中の行に挿入したり、最終行に追加したり」
という処理は多いです。

(愚かな方法なのでやめることを推奨しますが)特に、「顧客データ」を、ユーザーフォームから入力したいなどの場合も、ユーザーフォーム上のテキストボックスのデータをシート側(一覧表)に転記するような処理でも使います。

なので、ここではその、
「1行選択(あるいは指定)して、途中の行に挿入したり、最終行に追加したり」
ということのテストをしてみたいと思います。
  

※重要な補足
「顧客データ」入力でいちいちユーザーフォームを使うのはロスが多くて愚かな方法です。
「顧客データ入力」じゃなくても、「一覧表データをつくりたい」という要望がある時に、いちいち手間のかかるユーザーフォームを使うのは、プログラム作成や修正、機能追加、等々の時間をドブに捨てるようなものです。
「絶対にやめましょう」。(どうしてもやむを得ない場合以外は)
データを横方向に入力するのが目が疲れるなら、ユーザーフォームではなくシートをフォームに見たてて代用する方が(セルやシートなどの色んな機能が使えるため)、はるかに効率的です。


(ExcelのショボいユーザーフォームよりもシートやAccessフォームの方が50倍良いです)
★★★★★★Access2000VBA・Excel2000VBA独学~配列を利用しての、新規レコードの一括セルデータ(レコード)追加のプログラム・その2。~顧客マスタ入力~ワークシートをフォームに見立てて、縦長のデータの行と列を入れ替えながら他のシートへ転記するサンプル。~

あるいは、
・オプション設定に関係なく
・Enterで右へセル移動でき、
・表の右端を自動検知して
・次行の先頭に折り返すプログラム
を作って、普通に一覧表にダイレクトに入力したほうがいいです。


★★★★★★Access2000VBA・Excel2000VBA独学~★表の、列名の終端を自動判別して、「TABで」じゃなくて「全部Enter」で右の列へ移動し「一番右端の列にきたら、Enterキーを押したときに、自動的に次行に移り、アクティブセルを先頭へ移動させるVBAプログラム(テンキー用?かも)~

  
シートを入力フォームとして代用すれば、拡大縮小して(文字を大きく小さく)もラクですし、データの入力制限は「入力規則」などを使えば、入力ミスの防止策としても結構なことができます。
作り変え、作り足し、もラクです。

ユーザーフォームのほうが「見た目的にカッコイイ気がする」かもしれませんが、大変無礼ですみませんが、そういう考え方は(上から目線で本当にすみませんがでもマジで)「愚の骨頂」といいますか・・・、「効率のことを無視しています」ので、無駄だらけとなり、コスパも最悪となります。
誰かが言っていても絶対に真似しなようにしてください。
作成やメンテの無駄なコスト(時間・金額)が2倍どころか、3倍も4倍もかかるようになってしまいます。

特に、最近の愚かな「教科書」を名乗るような、VBAの市販書籍などに そういうサンプルが多いので、間違ってもあこがれなどは持たぬよう、騙されないように気を付けてください。
仕事の時間をムダに奪われて、「本来かける必夜の無い」「無駄なプログラム作成用・改修用の人件費」を「垂れ流すだけ」です。

本当に、無責任でバカな市販書籍の著者やサイトには、騙されないようにご注意ください。
  

★ サンプルのダウンロード

ダウンロード

いちおう、ESETでウィルスチェックしてあります。
解凍すると、「行1行分の指定や選択・挿入・追加など.xlsm」が出てきます。

解凍できましたら、VBEを開いて下記のプログラムをF8キーでステップ実行してみたり、
コードの「行や列の値」を変えたりして、ご自分でも色々と試してみてください。
  

前半のプログラムでInsert(行の挿入を)するときに、
セルの書式もついでにコピーしたい場合は、
o_WS01.Rows.Item(i_Row).Insert

o_WS01.Rows.Item(i_Row).Insert xlDown, xlFormatFromLeftOrAbove '書式もコピー
に書き換えます。
  

後半のプログラムでは、
「With o_List01.ListRows.Add(Position:=2)」
の部分は、
例えば
「Dim o_RtnNewRow01 As ListRow
 Set o_RtnNewRow01 = o_List01.ListRows.Add(Position:=2) 」
みたいにやっておいてから、
「With o_RtnNewRow01
  ~ ~
  ~ ~
 End With 」
などとやってほうがラクで見やすい?かも?

  
あと、ついでにですが、
組み込みのメソッドを全部「Call」で呼び出して、
変数やプロパティへの値の代入には全部「Let」を付けてみました。

一般的にはそんなことしませんが、

『 組込のメソッドはCallで呼び出せる=なら組込のメソッドの「実体・実態・正体」は、「SubかFunctionプロシージャ」では無いか?と推測できる。なぜならCallはSubとFunctionだけしか呼び出せない命令だから。 』

ということと

『 プロパティ項目への値の代入であっても、その命令文は ” 代入ステートメント ” には違いはないので、Let を使うことができるのでは?という実験を検証した。& そんなこと考えたことすらない = ” ステートメント ” の意味をまるでわかってない講師が多い?ことへの警鐘 & そんな4流以下の講師にテキトーなレッスンされて、だまされないように気を付けて。 』

という理由から、
「なぜ?」
「4流以下の講師を疑う。」
「日本のVBA教育を疑う。」
という意識をもってほしいと思ったので、そうしてみました。

  

参考URL
【最終行】
ワークシートの最終行、最終列を取得する
ワークシートの最終行、最終列を取得する(まとめ)
【行の挿入】
https://excel-ubara.com/excelvba2/EXCELVBA016.html
https://www.tipsfound.com/vba/08004
https://akira55.com/insertdelete/
Google検索「vba 行 挿入 書式」

  

  

★ Range.Offsetで、1行ずつを、下へ、選択・移動の場合
※Range.Resizeでの「下への移動」の場合も、Offsetよりもラクかも??
ただ、カウンタ変数(繰り返しの値)は、「最初の複数行」を選択したい場合などは、「0スタート」になってしまう。

'1行分を i 行飛ばしで。
ActiveSheet.Range("A1:D1").Offset(i * 3, 0).Address

'1行ずつ基準セル範囲側で移動
? ActiveSheet.Range("A" & 2 & ":D" & 2).Offset(1 , 0).Address
? ActiveSheet.Range("A" & 3 & ":D" & 3).Offset(1 , 0).Address
? ActiveSheet.Range("A" & 4 & ":D" & 4).Offset(1 , 0).Address
? ActiveSheet.Range("A" & 5 & ":D" & 5).Offset(1 , 0).Address

? ActiveSheet.Range("A" & i & ":D" & i).Offset(1 , 0).Address
--

結局

? ActiveSheet.Range("A" & i & ":D" & i).Address

? ActiveSheet.Range(Cells(i,1),Cells(i,4)).Address

とやるか、以降のようにするかのどちらか?

'1行ずつを、基準セル範囲側の設定ではなく、Range.Offsetの側で設定して移動
表の列名のセルを指定して「i」を最新行の数字にする。
(表の周囲に空白の行や列があっても)

? ActiveSheet.Range("A1:D1").Offset(0 , 0).Address
? ActiveSheet.Range("A1:D1").Offset(1 , 0).Address
? ActiveSheet.Range("A1:D1").Offset(2 , 0).Address
? ActiveSheet.Range("A1:D1").Offset(3 , 0).Address

? ActiveSheet.Range("A1:D1").Offset(i , 0).Address
? ActiveSheet.Range(Cells(1,1),Cells(1,4)).Offset(i,0).Address
? ActiveSheet.Range(Cells(1),Cells(4)).Offset(i,0).Address

  

Range.Resizeで、1行ずつ下へ移動する場合

ActiveSheet.Cells(i,1).Resize(1,4).select

↑「起点のセル=起点のRangeオブジェクト」を表現するのに、Rangeプロパティを使わずに、Cellsプロパティを使います。
Offsetと違って「起点のセル範囲」の設定をするのに、「単一セルで済ませられる」=「1行分の全部のセルじゃなくてもよい」からです。
Offsetの起点セル範囲の場合は、セル範囲を「行の全部のセル」を指定しないといけません。
カウンタ変数の i は、1スタートで行けるので、これもラク。
※ただし、Offsetじゃないとダメなケースももちろんあると思いますのでResizeを妄信しいないようにご注意を。

  
===
  
★ Range.Offsetで、複数の行ずつを、下へ、選択・移動の場合
※Range.Resizeでの「下への移動」の場合は、
「1行ずつ」なら、Offsetよりもラクだけど、
「複数行ずつ」だと、ちょっと考え方が面倒くさい。逆に、Offsetの方がラク。
一番最後に事例があります。

列構成は変えずに、同じ列に 2行ずつの場合(i は 「2行ずつの i くくりめ」という意味です。)
? ActiveSheet.Range(Cells(1,1),Cells(2,4)).Offset(3*2,0).Address
$A$7:$D$8
$A$5:$D$6
$A$3:$D$4
$A$1:$D$2
つまり、
? ActiveSheet.Range(Cells(1,1),Cells(2,4)).Offset(i*2,0).Address
iには「0」を入れてもエラーにはならない。

===

列構成は変えずに、同じ列に 3行ずつの場合
? ActiveSheet.Range(Cells(1,1),Cells(3,4)).Offset(3*3,0).Address
$A$7:$D$8
$A$5:$D$6
$A$3:$D$4
$A$1:$D$2
つまり、
? ActiveSheet.Range(Cells(1,1),Cells(3,4)).Offset(i*3,0).Address
iには「0」を入れてもエラーにはならない。

===

列構成は変えずに、同じ列に x 行ずつの場合
? ActiveSheet.Range(Cells(1,1),Cells(3,4)).Offset(3*3,0).Address
$A$7:$D$8
$A$5:$D$6
$A$3:$D$4
$A$1:$D$2
つまり、
? ActiveSheet.Range(Cells(1,1),Cells(x,4)).Offset(i*x,0).Address
iには「0」を入れてもエラーにはならない。

※列も変数化したい場合は、
? ActiveSheet.Range(Cells(FirstCelNum,l_ClmnStrt),Cells(x,l_ClmnEnd)).Offset(i*x,0).Address
みたいな感じで?
FirstCelNum は複数行のセル範囲の左上のセルの行の位置
l_ClmnStrtは同じ左上のセルの列の位置
x はくくりたい行数(=右下のセルの行の位置)
l_ClmnEndは右下のセルの列の位置

もう少し簡単にすると、
? ActiveSheet.Range(Cells(AA,BB),Cells(x,CC)).Offset(i*x,0).Address
で、
AA は 複数行のセル範囲の左上のセルの行の位置
BB は 同じ左上のセルの列の位置
x はくくりたい行数(=右下のセルの行の位置)
CC は 右下のセルの列の位置

・・・・という感じ。

  

★ Range.Resizeで、複数の行ずつを、下へ、選択・移動の場合(列構成は固定)
※Range.Resizeでの「下への移動」の場合も、Offsetよりもラクかも??
ただ、カウンタ変数(繰り返しの値)の i は、「最初の複数行」を選択したい場合などは、「0スタート」になってしまう。

ActiveSheet.Cells(i * x + 1, 1).Resize(x, 4).Select

Cells(i*x+1,1) などの「+1」は、Range.Resize が「1スタートだから?」
「x」は複数行の行数指定。もちろん「1行」の意味で「1」で指定しもOK。
「i」は、「くくり」としての繰り返し回数の指定。ただし、服須行移動の場合は、『 i は「+1」しないといけなくなってしまう 』ため、それに引きずられて i の値は「0スタート」にしないといけない。

あと、「起点のセル=起点のRangeオブジェクト」を表現するのに、Rangeプロパティを使わずに、Cellsプロパティを使います。
Offsetと違って「起点のセル範囲」の設定をするのに、「単一セルで済ませられる」=「1行分の全部のセルじゃなくてもよい」から、OffsetじゃなくてResizaが使えます。
(Offsetの起点セル範囲の指定の場合は、セル範囲を「行の全部のセル」を指定しないといけません。)
※ただし、Offsetじゃないとダメなケースももちろんあると思いますのでResizeを妄信しいないようにご注意を。
  

なお、2列め~4列目までの「3列分」で下へ移動するなら、以下のようになります。

ActiveSheet.Cells(i * x + 1, 2).Resize(x, 3).Select