- 締切済み
EXCEL マクロ・VBA 自動で連番を振る
EXCELのマクロ・VBAについて質問です。 例えば、B列にデータを入力すると、入力した行まで自動的にA列に連番が入力されるようにしたいのですが、どういった方法があるでしょうか。 マクロやVBAについてはこれから勉強をしようと思っている素人ですので、コードとその解説をいただけると助かります。
- みんなの回答 (9)
- 専門家の回答
みんなの回答
- kagakusuki
- ベストアンサー率51% (2610/5101)
回答No.8の続きです。 例えば、 Sub Macro() Dim i As Long i = 5 Do Range("A" & i).Value = "ABC" i = i + 1 Loop While i < 5 End Sub というVBAですと、 While i < 5 という判定式が付いているのはLoopの所であって、Doの所ではないため、例えiの初期値が5となっていてもDoの所では何の判定も行われませんので、 Range("A" & i).Value = "ABC" という処理は1回だけは行われる事になり、その後のLoopの所で i < 5 という条件を満たしているのかどうかという判定が行われ、「iの値が5未満である」という条件が満たされていなければ Loop While i < 5 の所で繰り返し処理が打ち切られてLoopの次に記述されている処理へと進みますので、A5セルにだけ「ABC」という文字列データが入力されます。 又例えば、 Sub Macro() Dim i As Long i = 6 Do Range("A" & i).Value = "ABC" i = i + 1 Loop Until i > 5 End Sub というVBAですと、 Until i > 5 という判定式が付いているのはLoopの所であって、Doの所ではないため、例えiの初期値が6となっていてもDoの所では何の判定も行われませんので、 Range("A" & i).Value = "ABC" という処理は1回だけは行われる事になり、その後のLoopの所で i > 5 という条件を満たしているのかどうかという判定が行われ、「iの値が5よりも大きい」という条件が満たされていれば Loop Until i > 5 の所で繰り返し処理が打ち切られてLoopの次に記述されている処理へと進みますので、A6セルにだけ「ABC」という文字列データが入力されます。 回答No.1の【Do ~ Loop を使う方法・その】では Do n = n + 1 Range("A" & StartRow).Offset(n - 1, 0).Value = n Loop While StartRow + n - 1 < LastRow となっていますから、「StartRowの値である2から1を差し引いた値に、入力した連番の数値を加えた数が、LastRowの値(B列に値が入力されている最終行の行番号)未満」という条件が満たされている間は繰り返し処理が行われる訳です。 一方、回答No.1の【Do ~ Loop を使う方法・その2】では Do n = n + 1 Range("A" & StartRow).Offset(n - 1, 0).Value = n Loop Until StartRow + n - 1 >= LastRow となっていますから、「StartRowの値である2から1を差し引いた値に、入力した連番の数値を加えた数が、LastRowの値(B列に値が入力されている最終行の行番号)以上」という条件が満たされていない間は繰り返し処理が行われる訳です。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > 7.繰り返し処理(For~Next、Do~Loop) > Do~Loop http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_for_next.html#do_loop Office TANAKA - Excel VBA高速化テクニック[個別に呼ばない] http://officetanaka.net/excel/vba/speed/s5.htm 回答No.1のVBAで使用しているテクニックに関する説明は以上ですが、 >マクロやVBAについてはこれから勉強をしようと思っている という事でしたら、上記以外にも「配列変数」、「Select Case」、「And及びOr」、「Withを使って構文を短く纏める」、「Goto」、「On Error」、「モニター表示の更新を停止する事で処理速度を向上させる」、「一時的に手動計算モードに切り替える事で処理速度を向上させる」等も頻繁に使われるものですので、最低限覚えておくべき事柄だと思います。 【参考URL】 OfficePro > Excel VBA入門 > 配列 > 配列とは http://www.officepro.jp/excelvba/array/index1.html Office TANAKA - VBAの変数[配列とは何か] http://officetanaka.net/excel/vba/variable/07.htm Office TANAKA - VBAの変数[動的配列] http://officetanaka.net/excel/vba/variable/08.htm プログラム入門(EXCEL VBA)(2)変数と型宣言・株式会社アイティ.オフィス http://www.itoffice.jp/ITOFFPRG2.htm よねさんのWordとExcelの小部屋 > Excel VBA入門 > 8.条件分岐処理(If~Then,Select Case) > Select Case~End Select http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_if_select.html#select_case OfficePro > Excel VBA入門 > 基本文法 > 演算子 http://www.officepro.jp/excelvba/basic/index6.html Office TANAKA - 今さら聞けないVBA「Withって何ですか?」 http://officetanaka.net/excel/vba/beginner/16.htm VBAのIE制御入門ExcelのVBA入門 > エクセルVBAのステートメント一覧 > VBAのGoToステートメント http://www.vba-ie.net/statement/goto.html Office TANAKA - Excel VBAステートメント[On Errorステートメント] http://officetanaka.net/excel/vba/statement/OnError.htm Office TANAKA - Excel VBA Tips[エラーに負けない] http://officetanaka.net/excel/vba/tips/tips104.htm Office TANAKA - Excel VBA高速化テクニック[目次] http://officetanaka.net/excel/vba/speed/index.htm Office TANAKA - Excel VBA高速化テクニック[無駄な表示を止める] http://officetanaka.net/excel/vba/speed/s1.htm PCよろずごと「よろずや工房」 > Blog Archive > EXCEL VBA の高速化 第3弾・・・非表示 http://yorozuya.miraiserver.com/archives/5597
- kagakusuki
- ベストアンサー率51% (2610/5101)
次に、For Each~in~Nextに関して説明します。 For Each~in~Nextも繰り返し処理を行うという点ではFor~To~Nextと共通していますが、For~To~NextがForの次の所で指定されている変数の値を一定の刻み幅で増減して行き、Toの次の所で指定している値を最大値とする事で繰り返しの回数を定めているのに対し、For Each~in~Nextの場合は変数の値によるのではなく、inの次の所で指定している「オブジェクトのコレクション」や「配列」の中に含まれている全ての要素に対して順番に同様の処理を繰り返すというものです。(For Eachの次の所で変数こそ使用されてはいるものの、その使用されている変数が、値を格納するための変数ではなく、オブジェクトを格納するための変数である事に注意) 尤も、こんな説明の仕方ではおそらく解らないのではないかと思います。 色々なパターンがあるので説明がし難いのですが、「オブジェクトのコレクション」とは「一纏めのグループにした、同種のオブジェクト (要素)の集まり」といったところでしょうか。 【参考URL】 VBAシステム開発 > 1. VBAの世界 > 第2章 > 2.2 コレクション https://sites.google.com/site/compositiosystemae/home/vbaworld/primitive/collection インストラクターのネタ帳 > エクセルマクロ・Excel VBAの使い方 > VBAのコレクションとは http://www.relief.jp/itnote/archives/excel-vba-what-is-collection.php ますます解らなくなったのではないかと思いますので具体例を挙げますと、ワークシートはその1枚1枚がワークシートオブジェクトという同種のオブジェクトなのですから、1つのWorkbook内に存在している全てのワークシートを1つにまとめたものは「ワークシートオブジェクトという要素からなる1つのコレクション(集まり)」と見做す事が出来ます。 例えば、Book1というワークブックにSheet1、Sheet2、Sheet3という3枚のシートがあり、そのBook1内に次の様なVBAのマクロを設定しますと、「シート名をそのシートのA1セルに書き込む」という同じ処理をSheet1、Sheet2、Sheet3の各シートに対して順番に行うというマクロになります。 Sub Macro() Dim mySheet As Worksheet For Each mySheet in Worksheets mySheet.Range("A1").Value = mySheet.Name Next mySheet End Sub 又、オートシェイプ図形はその1つ1つがShapesオブジェクトという同種のオブジェクトなのですから、1枚のワークシート上に存在している全てのオートシェイプ図形を1つにまとめたものは「Shapesオブジェクトという要素からなる1つのコレクション(集まり)」と見做す事が出来ます。 例えば、Sheet1というワークシート上に複数のオートシェイプ図形がある場合、次の様なVBAのマクロを設定しますと、「Sheet1上に存在する全てのオートシェイプ図形」に対して、図形を1つずつ順番に削除して行き、Sheet1上に図形が無くなるまで同じ処理を繰り返すというマクロになります。 Sub Macro() Dim myShape As Shape For Each myShapes In Sheets("Sheet1").Shapes myShapes.Delete Next myShapes End Sub 又、ある任意のセル範囲の中に含まれているセルの1つ1つは、1個のセルそのものがRangeオブジェクトという同種のオブジェクトと見做す事が出来ますから、1つのセル範囲は「Rangeオブジェクトであるセルという要素からなる1つのコレクション(集まり)」と見做す事が出来ます。 例えば次の様なVBAのマクロを設定しますと、「B2:B8というセル範囲に含まれている全てのセルに『ABC』という文字列データ入力する」というマクロになります。 Sub Macro() Dim c As Range For Each c In Range("B2:B8") c.Value = "ABC" Next c End Sub この場合、変数cは「その繰り返し処理の中でその時処理を行う対象としているセル」を現します。 つまり、繰り返し処理の中で初回の繰り返しの時には、B2:B8の中で1番最初のセルであるB2セルが変数cの中に格納されますので、初回の繰り返しの時にはB2に「ABC」と入力されます。 同様に2回目の繰り返しの時には、B2:B8の中で2番目のセルであるB3セルが変数cの中に格納されるためB3セルに「ABC」と入力され、3回目の繰り返しの時にはB4セルに「ABC」と入力され・・・という具合に繰り返し処理がB8セルまで繰り返されます。 それと同様に、回答No.1の【For Each ~Next を使う方法】における For Each c In Range("A" & StartRow & ":A" & LastRow) n = n + 1 c.Value = n Next c という箇所では、 Range("A" & StartRow & ":A" & LastRow) というセル範囲に含まれている全てのセルに対して繰り返し処理が行われる訳です。 繰り返しが1回行われるごとに、 n = n + 1 の所で、変数nの値が1ずつ増えて行く事になり、そのnの値が c.Value = n の所で、「その繰り返し処理の中でその時処理を行う対象としているセル」である「変数cに格納されているセル」に入力される訳です。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > 7.繰り返し処理(For~Next、Do~Loop) > For~Next http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_for_next.html#each 次に、Do~Loopに関して説明します。 For~To~NextやFor Each~in~Nextの場合は繰り返す回数が最初から決まっているのに対し、Do~Loopの場合は「同じ処理を更に繰り返すのか、それともこの回で最後にするのか」という事を判定する際に、「何回繰り返したのか」という事で決めるのではなく、「設定した条件が満たされているのか否か」という事で決めているという違いがあります。 Do~Loop文はWhileかUntilのどちらか一方と組み合わせて使用され、Whileを付けた場合にはWhileの後の所に記述した判定式が真(True)となっている間は繰り返しが行われ、判定式が偽(False)となったところで繰り返し処理が終了します。 例えば、 Sub Macro() Dim i As Long i = 2 Do While i < 5 Range("A" & i).Value = "ABC" i = i + 1 Loop End Sub というVBAですと、Doの所に While i < 5 が付いているため、Doの所で i < 5 という条件を満たしているのかどうかという判定が行われ、「iの値が5未満である」という条件が満たされている間(iの値が2~4の場合)は繰り返し処理が行われ、iの値が5となった際に Do While i < 5 の所で繰り返し処理が打ち切られてLoopの次に記述されている処理へと進みますので、A2~A4のセル範囲に「ABC」という文字列データが入力されます。 一方、Untilを付けた場合にはUntilの後の所に記述した判定式が偽(False)となっている間は繰り返しが行われ、判定式が真(True)となったところで繰り返し処理が終了します。 例えば、 Sub Macro3() Dim i As Long i = 2 Do Until i > 5 Range("A" & i).Value = "ABC" i = i + 1 Loop End Sub というVBAですと、Doの所に Until i > 5 が付いているため、Doの所で i > 5 という条件を満たしているのかどうかという判定が行われ、「iの値が5よりも大きい」という条件が満たされて"いない間"(iの値が2~5の場合)は繰り返し処理が行われ、iの値が5を超えた値である6となった際に Do Until i > 5 の所で繰り返し処理が打ち切られてLoopの次に記述されている処理へと進みますので、A2~A5のセル範囲に「ABC」という文字列データが入力されます。 尚、WhileやUntilはDoの後以外にもLoopの後にもつける事が出来ます。(付ける事が出来るのは「Doの後」か「Loopの後」のどちらか片方だけであり、「Doの後」と「Loopの後」の2ヶ所に同時に付ける事は出来ません) ※ まだ途中なのですが、このままでは文字数制限内に収まりそうも御座いませんので、残りは又後で投稿致します。
- kagakusuki
- ベストアンサー率51% (2610/5101)
回答No.6の続きです。 Range("A" & i) の後に付いている.Valueとは、セルに入力されている値を表しており、セルに入力されている値が i - StartRow + 1 とイコールで結ばれているという事は、ここで Range("A" & i) に該当するセルの値を、 i - StartRow + 1 の計算結果と一致させるという事であり、それは即ち、 i - StartRow + 1 の計算結果を Range("A" & i) に該当するセルに入力するという事です。 この様に、 Range(セル番号).Value = 値 と記述する事でセルの値を高速で入力する事が出来ます。 iの値が初期値である2の時には、 i - StartRow + 1 の計算結果は1ですから、A2セルには1が入力され、その次にはiの値は3ですのでA3セルには2が入力され、又その次にはA4セルに3が入力されるという具合に繰り返し処理が行われる訳です。 因みに、 Range("A2:B5").Value = "ABC" と記述しますと、A2:B5のセル範囲に含まれている全てのセルに「ABC」という文字列を入力する事が出来ます。 又、 Range("A2").Formula = "=SUM($B$1:B2)" と記述しますと、A2セルに =SUM($B$1:B2) というワークシート関数を入力する事も出来ます。 只、ワークシート関数を入力する場合には Range("A2:A3").FormulaR1C1 = "=SUM(R1C2:RC[1])" 等の様に記述にした方が、A2セルに =SUM($B$1:B2) A3セルに =SUM($B$1:B3) という具合に、セル参照を相対参照にしている箇所のある関数をコピー&ペーストで増やした場合と同じ関数を、複数のセルに対して一度に入力出来ますので便利です。 後それから、値を入力する方法としては、.Valueを省略して Range(セル番号) = 値 とする事でも値の入力は可能ですが、私個人は省略せずに.Valueを付けて記述する事を好んでおります。 ※ 【For Each ~Next を使う方法】や【Do ~ Loop を使う方法】の説明が未だですが、そろそろ眠くなってまいりましたので、残りは又後日投稿する事に致します。
- kagakusuki
- ベストアンサー率51% (2610/5101)
尚、もし回答No.4及び5の説明で分からない事が御座いましたら、下記の参考URLのページを参考にして下さい。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > 4.セル範囲の指定方法 http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_cell.html 次に、 If LastRow < StartRow Then から End If にかけてですが、If~Thenはワークシート関数のIF関数と同じ様なもので、 If 判定式 Then 判定結果が真の場合の処理 或いは If 判定式 Then 判定結果が真の場合の処理 Else 判定結果が偽の場合の処理 End If という形式で記述されるステートメントです。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > 8.条件分岐処理(If~Then,Select Case) http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_if_select.html 前回説明した様にLastRowの値は LastRow = Range("B" & Rows.Count).End(xlUp).Row で決まっています。 何も入力されていない適当な列の中の適当なセルを選択してから[Ctrl]キーを押しながら[↑]キーを押してみますと判りますが、選択したセルの上にデータが入力されているセルが1つも無い場合には、その列の1行目のセルが選択されます。 ですから、B列にデータが無い場合にはLastRowの値は「B列において項目名が入力されている行」の行番号と同じになるか、(B項列に項目名すら無い場合には)数値の1になりますので、そのLastRowの値が、連番を入れ始める最初の行の行番号として設定されているStartRowの値よりも小さかった場合には、B列にはデータが無いと判断出来る訳です。 そしてB列にデータが無ければ連番を振るべき行も無い訳ですから、そこでマクロを終了するような構文が必要になります。 回答No.1のVBAでは判定結果が真の場合の処理として MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" Exit Sub と記述しました。 この内、Exit Subとはマクロを途中で終了するための構文です。 【参考URL】 Office TANAKA > Excel > VBAのステートメント > Exitステートメント http://officetanaka.net/excel/vba/statement/Exit.htm その前のMsgBoxは何かといいますと、ダイアログボックスを表示させるためのものです。 MsgBoxにはMsgBox関数とMsgBoxメソッドの2種類があり、回答No.1で使用しているのはMsgBoxメソッドの方です。 MsgBoxメソッドは MsgBox 表示する文字列,表示するアイコンの種類,タイトル という形式で記述され、「表示する文字列」の所に記述されている文字列を本文とした[OK]ボタン付きのダイアログボックスを表示します。 そしてそのダイアログボックスのボタンが押されるまでの間、次の処理には進みません。 MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" という記述となっていますから、表示されるダイアログボックスは「データ無し」というタイトルで、表示内容が データがありません。 マクロを終了します。 となります。 尚、vbCrLfは改行記号です。 表示する事の出来るアイコンの種類は、「警告」、「問い合わせ」、「注意」、「情報」、及びアイコン無しの5種類で、vbExclamationを指定した場合は「注意」アイコン(黄色い三角形の中に「!」マークのアイコン)が表示されます。 因みに、MsgBox関数は複数のボタンを表示させて、どのボタンが押されたのかという情報を関数の結果として返す関数で、MsgBoxメソッドとは違って( )付きで記述され、結果を返すという性質上、必ず変数と組み合わせて 変数 = MsgBox(表示する文字列,表示するアイコンやボタンの種類,タイトル) という形式で記述されます。 MsgBoxメソッドではボタンが[OK]ボタンしかないため、人間が表示内容を読んでボタンを押すまでの間待つ事にしか使えないのに対し、MsgBox関数ての場合は複数のボタンを扱う事が出来るため、どのボタンを押したのかという結果によって、その後の処理の内容を変えるという、条件分岐の際のどの分岐にするのかという事を操作している人間に選択させる事のために使う事が出来ます。 MsgBoxメソッドとMsgBox関数は双方ともに、「表示するアイコンやボタンの種類の設定」や「タイトルの設定」を省略して記述する事も可能です。 「表示するアイコンやボタンの種類の設定」を省略した際にはボタンは[OK]のみでアイコンは表示されません。 又、タイトルを省略した場合、ダイアログボックスのタイトルは自動的に「Microsoft Excel」になります。 【参考URL】 Office TANAKA > Excel > 今さら聞けないVBA > 括弧はどんなときに使うの? http://officetanaka.net/excel/vba/beginner/07.htm よねさんのWordとExcelの小部屋 > Excel VBA入門 > 19.対話型処理1(MsgBox関数) http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_msgbox.html 因みに、マクロの途中で操作している人間に判断を仰ぐための方法としては、MsgBox関数の様なボタンを選択して押すだけというもの以外にも、値を直接入力する際に使用出来るInputbox関数というものもあります。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > 20.対話型処理2(InputBox関数,InputBoxメソッド) http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_inputbox.html 次に、 For i = StartRow To LastRow Range("A" & i).Value = i - StartRow + 1 Next i の部分ですが、For~To~Nextは繰り返し処理を行うためのもので、 For 適当な整数値型の変数 = 変数の初期値 To 繰り返し処理における変数の最後の値 Step 1回の処理ごとに変数の値を幾つ変えるのかという設定値 繰り返す処理の内容 Next (Forの所で設定した)変数(の名称) という形式で記述され、Forとそれに対応するNextの間に記述されている処理を、 「(『繰り返し処理における変数の最後の値』-『変数の初期値』+1)÷『1回の処理ごとに変数の値を幾つ変えるのかという設定値』」 と同じ回数だけ繰り返します。 尚、Stepには負の数を設定する事も可能ですし、省略する事も可能で、省略した場合にはStepの値として自動的に1が設定されます。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > 7.繰り返し処理(For~Next、Do~Loop) > For~Next http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_for_next.html#for_next For i = StartRow To LastRow という事は、変数iの値をStartRowの値(=2)から始めて、(Stepの指定が省略されているので)1回の処理を行うごとにiの値を1つずつ増やして行き、iの値がLastRowと同じになるまで処理を繰り返すという事です。 処理を行う対象となるセルとして Range("A" & i) が設定されていますから、最初iの値が2の時には Range("A" & 2) 即ち、A2セルに対して処理を行い、その次の繰り返しの時にはiの値が1つ増えて3になっていますから、A3セルに対して処理を行い、その次はA4セルに・・・という具合に処理を繰り返して行って、A列のLastRow行目(=B列においてデータが入力されている最終行)のセルの所まで処理を行うという事です。 ※ まだ途中なのですが、このサイトの回答欄に入力可能な文字数は4000文字までであり、この調子で続けますと文字数制限内には収まりそうも御座いませんので、ここで一旦回答を中断し、残りは又時間のおいてから投稿させて頂きます。
- kagakusuki
- ベストアンサー率51% (2610/5101)
次にStartRowは連番を入れ始める最初の行を指定するために今回のVBAで設けた変数です。 「連番を入れ始める最初の行」の行番号は毎回同じ行なのですから固定値という事になり、固定値であれば Range("B2") の様に最初のセルを直接指定する記述の仕方でも良い訳ですが、今回は >B列にデータを入力すると、入力した行まで自動的にA列に連番が入力されるようにしたい というだけで、何行目から連番を振ればよいのかはっきりしなかったため、 If LastRow < 2 Then や For i = 2 To LastRow や Range("A" & i).Value = i - 2 + 1 等の様にVBAの構文の各所で最初の行の行番号が2であると指定してしまいますと、後から最初の行番号を実際の表に合わせて修正する際に複数箇所を修正せねばならなくなるため間違いが起きやすくなります。 そのため、 StartRow = 2 とする事で、最初の所で最初の行番号を変数に格納し、後で最初行番号の値が必要になる箇所では、変数StartRowを使って値を指定する様にしますと、もし最初の行番号の設定を修正する必要が生じたとしても、最初の StartRow = 2 の所だけを修正さえすれば、残りの箇所は一々修正する必要が無くなる訳です。 尚、今回は使っていない方法ですが、同じ要領で >B列にデータを入力すると のB列や >自動的にA列に連番が入力される のA列に関しても、例えば Dim 入力列 As String Dim 連番列 As String 入力列 = "B" 連番列 = "A" などの様にしておいた上で、例えばA列の最初の行ののセルを指定する際に Range(連番列 & StartRow) 等の様にしておきますと、もし後になってからデータを入力する列や連番を入力する列が変更になった際にも、簡単に設定を変更する事が出来る様になります。 この「必要となる設定値を最初に纏めて変数の中に格納してしまう」という方法は何も行番号や列番号だけではなく、使用するシート名や、各種の設定値等にも応用出来ます。 次にLastRowは連番を入れ無ければならない行の中で一番下の行の行番号を格納するために今回のVBAで設けた変数です。 最終行の値が必要になる度に一々、最終行を求めるための計算処理を行っていたのでは、一度求めた値を何度も計算しなおすという無駄な事を繰り返す事になり、計算処理が重くなっ てしまいますので、最初に LastRow = Range("B" & Rows.Count).End(xlUp).Row という処理を1回だけ行って、変数LastRowの中に求めた最終行の行番号の値を格納しておき、繰り返し使用する訳です。 尚、Rows.Countとはワークシート関数のROWS関数と同じ働きをする関数です。 例えば、 Range("B2:Z8").Rows.Count とした場合には、ワークシート関数における ROWS(B2:Z8) と同じく7が返されます。そして Rows.Count の様にセル範囲を指定せずにRows.Countを使った場合には、ActiveSheetの中にある全てのセルを含んだセル範囲(Excel2007以降の場合はA1:XFD1048576の範囲)に対してRows.Countを使用 したものとして扱われますので、ActiveSheetに含まれている全ての行の行数が返される事になります。 そのExcelbookの中のどのシートにおいても1番下端にある行の行番号は、ActiveSheetに含まれている全ての行の行数と同じ値になりますから、 Range("B" & Rows.Count) とする事で、ActiveSheetのB列にあるセル(未使用のセルも含む)の中で最も下にあるセル(Excel2007以降の場合はB1048576セル)を指定した事になる訳です。 次に、 .End(xlUp).Row ですが、これは[Ctrl]キーを押しながら[↑]キーを押すという操作と同じ処理を行うための構文です。 実際に、B列においてデータ入力されていないセル範囲を選択してから[Ctrl]キーを押しながら[↑]キーを押してみて下さい。その列においてデータが入力されているセルの中で最も下 にあるセルが選択される筈です。 つまり、 Range("B" & Rows.Count).End(xlUp) という構文を使う事で、B列においてデータが入力されているセルの中で最も下にあるセルを指定する事が出来る訳です。 この Range(列番号 & Rows.Count).End(xlUp) はデータが入力されている最終行を求める際に良く使われる手法ですので、今後もVBAを組む事がおありでしたら覚えておくようにされた方が良いと思います。 次に、 .Row に関してですが、これはワークシート関数のROW関数と同じ働きをするものです。 つまり、 Range("B" & Rows.Count).End(xlUp).Row という構文を使う事で、B列においてデータが入力されている最終行の行番号を求める事が出来る訳です。 従って、 LastRow = Range("B" & Rows.Count).End(xlUp).Row という箇所は、LastRowという変数の中に、B列においてデータが入力されている最終行の行番号を格納している訳です。 ※ まだ途中なのですが、区切りが良いのでここで一旦投稿し、残りは又後で投稿する事に致します。
- kagakusuki
- ベストアンサー率51% (2610/5101)
>残りは又時間のおいてから投稿させて頂きます。 と書いておきながら、大変遅くなってしまい申し訳御座いません。 それで続きですが、ワークシート関数でどのセルを参照するのかという事が重要になるのと同様に、VBAでもどのセルやどのオートシェイプ図形を取り扱うのかという事が重要になります。(セルや図形等を全く扱わないVBAというものもある事はありますが、セルを使わないのであれば何故その様なVBAを態々Excel上で動かすのかという話になります) ワークシート関数の場合では例えばE8セルを参照する際には INDEX(A:Z,8,5) INDIRECT("E8") INDIRECT("R8C5",FALSE) などの様な方法でもE8セルを参照出来ますが、一般的には E8 と入力するのがオーソドックスな方法です。 それと同様にVBAでも特定のセルやセル範囲を指定する方法はいくつもありますが、最もオーソドックスな方法はCellsプロパティやRangeプロパティを使う方法です。 例えばExcelのVBAでE8セルを指定する際には Cells(8,5) と記述するのが最も基本的なやり方で、 Cells(行番号,列番号) という形式で記述します。 又、 Cells(8,"E") の様に列番号をアルファベットで記述する事も可能です。 一方、Rangeプロパティを使ってE8セルを指定する際には Range("E8") の様に記述します。 尚、Cellsプロパティ単体では1個のセルしか指定する事は出来ませんので、例えばE8:G9の範囲を指定したい場合などにはセル範囲を変更するResizeプロパティと組み合わせて Cells(8,5).Resize(2,3) 等の様にします。 Resizeプロパティを使う際には .Resize(セル範囲に含まれる行数,セル範囲に含まれる列数) という形式で記述し、.Resizeの直前の所で指定されているセル範囲の縦横がそれぞれ何マスであるかには関係なく、Resizeプロパティの括弧内で指定した行数と列数のセル範囲に変換されます。(Cellsプロパティに対してだけではなくRangeプロパティに対しても使用可能です) 一方、Rangeプロパティでは Range("E8").Resize(2,3) という指定の仕方をする事も勿論出来ますが、 Range("E8:G9") という指定の仕方をする事も出来ますし、 Range(Cells(8,5),Cells(9,7)) や Range(Range("E8"),Range("G9")) という指定の仕方をする事も出来ます。 因みに、 Range("E:E") とすればE列全体を、 Range("E:H") とすればE列~H列の列範囲の全体を、 Range("8:8") とすれば8行目全体を、 Range("8:10") とすれば8行目~10行目の行範囲の全体を指定する事も出来ますが、列全体を指定する際にはColumnsプロパティを使って Columns(5) Columns("E") Columns("E:E") Columns("E:H") とするのが一般的ですし、行全体を指定する際にはRowsプロパティを使って Rows(8) Rows("8:10") などとするのが一般的です。 又、例えばA1セルに6と入力しておいて、別のセルにワークシート関数で ="E"&A1+2 と入力しますと別のセルには"E8"という文字列が返されますが、それと同様にVBAにおいても「&」を使って文字列を結合させる事が出来ます。 この事を利用して、例えばiという変数の中に数値の6が格納されている時に、 Range("E" & i + 2) と記述すれば、E8セルを指定する事になります。 それと注意しておかなければならないのは、CellsプロパティやRangeプロパティでセルやセル範囲を指定した場合、セルやセル範囲だけではなく同時にシートも指定する事になるという点です。 VBAでは例えばSheet1!E8セルを指定する際には Sheets("Sheet1").Range("E8") の様に、普通はどのワークシートのセルやセル範囲を指定するのかという事も、セル番号と共に指定して処理を行う様にすべきなのですが、 Range("E8") の様に、シートを指定せずにセル番号だけを指定した場合でもVBAは動く事は動きます。 では、ワークシート関数とは違ってシート上に数式を入力する訳ではないVBAにおいて、E8セルを指定する際にシート名を指定せずに記述した場合、一体どのシートのE8セルを指定した事になるのでしょうか? それは、その部分の処理を行った時にアクティブとなっているシートの中にあるE8セルを指定した事になります。 つまり、 Range("E8") という記述をした場合、 Activesheet.Range("E8") と記述したのと同じ事になります。 このActivesheetとは作業中のブックにおいてその時一番手前に表示されているシートの事で、マクロを起動させる前の段階では、その時開いていたシートがActivesheetになりますが、VBAの構文の中には、途中で別のシートをアクティブにする事が可能なものもありますし、新しいシートを作るVBAの構文の様に、処理の内容によっては勝手に別のシートがアクティブになってしまう場合もありますので、下手にシートを指定せずに処理を行った場合、意図していたシートとは別のシートのセルやセル範囲に対して処理が行われる恐れがありますので注意して下さい。 尚、どのシートを使うのかという事は特に決めずに、最初に開いていたシートのセルやセル範囲をずっと指定する必要があり、尚且つ、途中でアクティブなシートが切り替わる様な処理が行われる様な場合には次の様にします。 例えば、最初、Sheet1を開いている状態でマクロを起動させて、VBAの途中でSheet2がアクティブなシートになる様な処理が行われたとして、その後になってからでも最初に開いていたシート(この場合はSheet1)のE8セルを指定するという様な場合には、 Dim mySheet As Worksheet Set mySheet = Activesheet Sheets("Sheet2").Activate mySheet.Range("E8") となります。 つまり、 Set mySheet = Activesheet という処理を行った所で、最初にアクティブだったSheet1をmySheetという変数(この変数名も適当に変えてしまっても構いません)の中に格納してしまっていますので、その後の Sheets("Sheet2").Activate の所でSheet2がアクティブなシートとなっても、mySheetに格納されているシートはSheet1のまま変わりありませんから、 mySheet.Range("E8") という具合に変数を使ってシートを指定する事で、Sheet1!E8セルを指定する事が出来る訳です。 尚、シート自体や、セルやセル範囲自体、オートシェイプなどの図形などは値ではなくオブジェクトであり、その様なオブジェクトの類(値ではないもの)を変数に格納する際には mySheet = Activesheet とするだけでは格納する事が出来ません。 オブジェクトの類(値ではないもの)を変数に格納する際には必ず構文の頭にSetを付けて Set mySheet = Activesheet 等の様にして下さい。 次に、回答No.1で提示させて頂いたVBAの中身に関して説明致します。 まず、【For To ~Next を使う方法】においては Dim i As Long Dim StartRow As Long Dim LastRow As Long の所で 「i、StartRow、LastRowという3つのLong型(-2,147,483,648~2,147,483,647の範囲の整数を格納)の変数を使用します」 という宣言をしています。 この内、iは繰り返し処理を行う際に、同じ処理を何回行ったのかという事をカウントする際などに、慣習的に良く使われる変数の名称ですが、慣習的に良く使われる事が多いというだけの事で、iにしなければならないという決まりがある訳では御座いません。 尤も、iを使っておけば何の処理に使うための変数であるのかという事を一々説明しなくても、他の人にとってもなんとなく用途を察しやすくなるというメリットはあるかと思います。 尚、繰り返し処理を入れ子にして行う場合(繰り返し処理の途中で更に別の繰り返しを行う場合)などの様に同様の変数が複数必要になる場合には、jやk等のiに続くアルファベットが使われる場合が多い様です。 ※ まだ途中なのですが、この調子で続けますと文字数制限の関係で区切りの悪い所で中断しなければならなくなりますので、ここで一旦回答を中断し、残りは又時間のおいてから投稿させて頂きます。
- kagakusuki
- ベストアンサー率51% (2610/5101)
>マクロやVBAについてはこれから勉強をしようと思っている素人です という点を失念して、肝心な事を書き忘れておりました。 それは回答No.1で御伝えしたVBAの構文をどうすればマクロとして使う事が出来る様になるかという事に関してです。 まず、Excelを起動し、Excelのウィンドウの上の方に並んでいる[ホーム]、[挿入]、[ページレイアウト]、・・・等といったタブの中に[開発]というタブがあるかどうかを確認して下さい。 もしも無い場合には下記の参考URLのページに掲載されている方法に従って、[開発]タブが表示される様に設定して下さい。 【参考URL】 All About > デジタル > IT・インターネット > Excel VBAの使い方 > マクロ・VBA > Excelマクロ機能の基本操作(2007/2010/2013版) http://allabout.co.jp/gm/gc/425829/ その[開発]タブをクリックしますと、幾つかのグループが表示されますので、それらのグループの中で左端の所にある「コード」グループの中にある[Visual Basic]ボタンをクリックして下さい。 すると「Visual Basic Editor」のウィンドウが開きます。 【参考URL】 Tipsfound > Excel VBA > VBA の使い方 http://www.tipsfound.com/VBA/01002.vbhtml その「Visual Basic Editor」ウィンドウの左側に「プロジェクト - VBAProject」という欄があり、そこに表示されているツリーの中に、「 VBAProject(Book名)」の形式で表示されている項目がありますので、マクロを設定したいWorkbookのツリーを選択し、そのツリーの下の方にある「標準モジュール」内の「Module」(番号付きで複数の「Module」が表示されている事もありますが、どの「Module」を使っても構いません)をダブルクリックする事で選択して下さい。 尚、初めてマクロを設定する際には、「Module」自体が未設定であるため表示されませんので、マクロを設定したいWorkbookのツリーを選択してから、下記の参考URLのページに掲載されている方法に従って、「Module」を挿入して下さい。 【参考URL】 Office TANAKA - 今さら聞けないVBA「マクロってどこに書けばいいの?」 http://officetanaka.net/excel/vba/beginner/10.htm そうして、「Module」をダブルクリックで選択しますと、「Visual Basic Editor」のウィンドウの左側に、VBAの構文を書き込むための白色の欄が現れますので、そこへ回答No.1で提示させて頂いたVBAマクロの構文の中から好きなものを選び、「Sub [マクロの名称]()」という形式となっている行から、「End Sub」と記述されている行の所までの構文をコピーして貼り付けるか、或いは同じ構文をキーボード入力で書き込んで下さい。 但しその際には【 】で囲まれた部分はVBAの構文では御座いませんので、もしこの部分まで書き込んでしまいますとエラーとなってしまいますから、【 】で囲まれた部分は書きこまない様にして下さい。 尚、1つの「Module」内に複数のVBAマクロを書き込む事も出来、その場合はマクロを起動させる際に、どのマクロを使用するのかという事を選択します。(選択方法は後述します) それと、マクロによっては書きこむ場所を「Module」と表示されている「標準モジュール」内にするのではなく、ツリーの中で、「Sheet1」や「Sheet2」などと表示されている「シートモジュール」や、「ThisWorkbook」と表示されている「ブックモジュール」に書き込む場合もありますが、今回の様な「Sub」で始まっているマクロの場合は「標準モジュール」内に書き込みます。(「ブックモジュール」や「シートモジュール」に書き込むマクロは「Private Sub」で始まります) 【参考URL】 Office TANAKA - VBAの変数[変数の適用範囲] http://officetanaka.net/excel/vba/variable/05.htm こうしてVBAマクロの設定を済ませた後、設定済みのマクロを起動させる場合には次の様にします。 まず、[Visual Basic]ボタン(先述)の右隣にある[マクロ]ボタンをクリックして下さい。 すると「マクロ」ダイアログボックスが現れますので、その中に表示されているマクロの中から、実行したいマクロを選択してから、[実行]ボタンをクリックして下さい。 或いは、「マクロ」ダイアログボックスに表示されているマクロの中から、実行したいマクロを選択してダブルクリックして下さい。 するとクロが起動して、マクロによる処理が行われます。 【参考URL】 よねさんのWordとExcelの小部屋 > Excel VBA入門 > ◦マクロの自動記録と実行(Excel2007編) > マクロの実行 http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_01_2007.html#jikkou よねさんのWordとExcelの小部屋 > Excel VBA入門 > ◦マクロの自動記録と実行 > マクロの実行 http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_01.html#jikkou 尚、「マクロ」ダイアログボックスを開く方法としては、[マクロ]ボタンをクリックするという方法以外にも、[Alt]キーを押しながら[F8]キーを押すと言った方法もあります。 又、マクロを実行させる方法としては、「マクロ」ダイアログボックスを使う方法以外にも、そのマクロを登録しておいた「フォームコントロールボタン」をクリックすると言った方法もあります。 【参考URL】 インストラクターのネタ帳 > エクセルマクロ・Excel VBAの使い方 > Excel 2013・2010・2007でマクロボタンを作成する-フォームコントロール http://www.relief.jp/itnote/archives/excel-make-macro-button-form.php よねさんのWordとExcelの小部屋 > Excel VBA入門 > マクロの自動記録と実行(Excel2007編) > フォームのボタンに登録する http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_01_2007.html#form_button よねさんのWordとExcelの小部屋 > Excel VBA入門 > マクロの自動記録と実行 > フォームのボタンに登録する http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_01.html#form_button ※ まだ途中なのですが、このサイトの回答欄に入力可能な文字数は4000文字までであり、この調子で続けますと文字数制限内には収まりそうも御座いませんので、ここで一旦回答を中断し、残りは又時間のおいてから投稿させて頂きます。
- kagakusuki
- ベストアンサー率51% (2610/5101)
まず、VBAでは変数というものを使います。(使わずに済ませる事が出来る場合もありますが、使った方が楽に処理が出来る場合が大半です) 【参考URL】 Office TANAKA - VBAの変数[変数の使い方] http://officetanaka.net/excel/vba/variable/index.htm 変数とは情報を入れておくための場所の様なもので、例えばExcelにおいてA1セルに2と入力し、B1セルに3と入力し、C1セルに =A1+B1 と入力しておけば、C1セルには2+3の計算結果である5という数値データが入る事になりますね。 このワークシート関数上でセル番号を記述した処が、2や3といった数値を表しているのと同様に、予め決めておいた変数名を記述する事でデータを指定したのと同じ役割を果たす事が出来るものが変数だと考えて下さい。 例えば、xという変数を使うと決めておいてから、 x = 5 という構文をVBA上に記述しておきますと、セルに =5 と入力したのと同様に、変数xには5という数値データが格納されます。 セルと変数が異なるのは、例えばC1セルに =A1+B1 と入力しておけば、A1セルやB1セルの値を変えるだけでC1セルの値も自動的に変わりますが、それに対して変数の場合は、例えばx,y,zという3つの変数があり、 x = 5 y = 2 z = x + y と記述しておけば、変数zには5+2の結果である数値の7が格納されますが、 z = x + y x = 5 y = 2 の様に記述しても、 z = x + y という計算を行った時には、未だxの値は5ではありませんでしたし、yの値も2ではありませんでしたので、5+2の計算を行った事にはならないという点です。 つまり、 z = x + y という記述は、変数zに = x + y という関数を入力するという意味ではなく、その時点でのxとyの値を足し合わせた値をzに格納するという意味でしかありません。 ですから例えばワークシート関数でA1セルに =A1+1 などと入力しますと循環参照となってしまうためエラーとなるだけであるのに対し、変数の場合は、 x = 5 y = 2 z = x + y z = z+1 等の様に記述しますと、 z = x + y の所でzには数値の7が格納されていますから、 z = z+1 の所では、zに格納されていた値である7に1を足した値が、変数zに格納されます。 これは関数を入力した訳ではありませんので、計算が行われるのはその場限りの1回だけであり、循環は起きません。 尚、変数に格納出来るのは値だけではなく、セルやセル範囲、行全体、列全体などといったセル範囲を取り扱う際に、指定したセル範囲を格納する事で、一々Range(○○)などの様に記述しなくとも、変数を記述するだけでセル範囲を指定したのと同じ事が出来る様にする事も出来ますし、 同様にシートやWorkbook、オートシェイプ図形、等々を格納する事も出来ます。 VBAではRangeやForなどの様に、どの様な処理を行うのかという事を記述するための文字列が決まっていますが、そういった事に用いられていない文字列であれば変数の名前として使う事が出来ますので、変数名はVBAの構文を作った人間が自由に決める事が出来ます。 但し、変数名に使う事が出来るのは英数字と平仮名、カタカナ、漢字 だけであり、記号を使う事は出来ませんし、その他にも空白、「、」、「。」、「・」、「¥」、「/」等々、使えない文字も幾つかあります。(大抵の場合は、使えない文字を使おうとしますと、パソコンの方で「不正な文字です」と警告してくれますので、どんな文字が使えるのかという事を全部覚えておく必要はありません) 【参考URL】 Office TANAKA - VBAの変数[変数の名前について] http://officetanaka.net/excel/vba/variable/06.htm それからVBAでは、どんな変数を使うのかという事を先に宣言しておく事が一般的であり、宣言せずに変数を使うと、VBAを作る際に人間が間違いを犯してしまう事を誘発する原因となりかねませんので、必ず宣言してから使うようにした方が良いとされています。 【参考URL】 Office TANAKA - VBAの変数[変数の使い方] http://officetanaka.net/excel/vba/variable/01.htm Office TANAKA - 今さら聞けないVBA「変数って宣言しなくちゃいけないの?」 http://officetanaka.net/excel/vba/beginner/06.htm そして、変数を宣言する際には、どの様な種類の情報を格納するのかという事も一緒に宣言せねばなりません。 変数を宣言する際にはDimステートメントを使用し、 Dim [変数名] As [変数の型] という形式で記述した構文をVBAの構文内に入れておく事で行います。 変数を使う前であれば構文の途中で宣言しても構わないのですが、同一の変数の宣言を複数回行う事は出来ませんので、同じ処理が2回繰り返される可能性がある所で宣言しますと、「コンパイルエラー:同じ適用範囲内で宣言が重複しています。」となる恐れが生じてしまうため、変数の宣言は構文の冒頭部分でまとめて行うのが普通です。 「変数の型」とは先述の「どの様な種類の情報を格納するのか」という変数の種類を表すもので、 例えば0~255の範囲の整数値を格納する事にしか使わない変数であれば変数の型をByteにすれば良いのに対し、 -2,147,483,648~2,147,483,647の範囲の整数を格納する事に使う変数であれば型をLongにしますし、 -3.402823E38~-1.401298E-45や1.401298E-45~3.402823E38の範囲の小数部(小数点以下の桁が第6位まで)を含む数値か数値の0を格納する事に使う変数であれば型をSingleにしますし、 -2,147,483,648~2,147,483,647の範囲の整数を格納する事に使う変数であれば型をLongにしますし、 -1.79769313486232E308~-4.94065645841247E-324や4.94065645841247E-324~1.79769313486232E308の範囲の小数部(小数点以下の桁が第14位まで)を含む数値か数値の0を格納する事に使う変数であれば型をDoubleにしますし、 文字列を格納する事にしか使わない変数であれば型をStringにする といった具合です。 【参考URL】 Excelでお仕事 > VBA基本 > 変数のデータ型 http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_050_06.html Office TANAKA - VBAの変数[型は覚えなくていい] http://officetanaka.net/excel/vba/variable/03.htm Excel VBA 入門講座 変数のデータ型 データ型と変数の型の指定 - 基本文法 - Excel VBA入門 Excel VBA(エクセル マクロ) 関数集 変数定義 http://www.d3.dion.ne.jp/~jkondou/excelvba/dim.htm 変数の話だけで3000文字を超えてしまいましたが、このサイトの回答欄に入力可能な文字数は4000文字までであり、この調子で続けますと文字数制限内には収まりそうも御座いませんので、ここで一旦回答を中断し、残りは又時間のおいてから投稿させて頂きます。
- kagakusuki
- ベストアンサー率51% (2610/5101)
色々なやり方があります。 【For To ~Next を使う方法】 Sub 自動で連番を振る_その1() Dim i As Long Dim StartRow As Long Dim LastRow As Long StartRow = 2 LastRow = Range("B" & Rows.Count).End(xlUp).Row If LastRow < StartRow Then MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" Exit Sub End If For i = StartRow To LastRow Range("A" & i).Value = i - StartRow + 1 Next i End Sub 【For Each ~Next を使う方法】 Sub 自動で連番を振る_その2() Dim c As Range Dim StartRow As Long Dim LastRow As Long Dim n As Long StartRow = 2 LastRow = Range("B" & Rows.Count).End(xlUp).Row If LastRow < StartRow Then MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" Exit Sub End If For Each c In Range("A" & StartRow & ":A" & LastRow) n = n + 1 c.Value = n Next c End Sub 【Do ~ Loop を使う方法・その】 Sub 自動で連番を振る_その3() Dim StartRow As Long Dim LastRow As Long Dim n As Long StartRow = 2 LastRow = Range("B" & Rows.Count).End(xlUp).Row If LastRow < StartRow Then MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" Exit Sub End If Do n = n + 1 Range("A" & StartRow).Offset(n - 1, 0).Value = n Loop While StartRow + n - 1 < LastRow End Sub 【Do ~ Loop を使う方法・その2】 Sub 自動で連番を振る_その4() Dim StartRow As Long Dim LastRow As Long Dim n As Long StartRow = 2 LastRow = Range("B" & Rows.Count).End(xlUp).Row If LastRow < StartRow Then MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" Exit Sub End If Do n = n + 1 Range("A" & StartRow).Offset(n - 1, 0).Value = n Loop Until StartRow + n - 1 >= LastRow End Sub 【Do ~ Loop を使う方法・その3】 Sub 自動で連番を振る_その5() Dim StartRow As Long Dim LastRow As Long Dim n As Long StartRow = 2 LastRow = Range("B" & Rows.Count).End(xlUp).Row If LastRow < StartRow Then MsgBox "データがありません。" & vbCrLf & "マクロを終了します。", vbExclamation, "データ無し" Exit Sub End If Do While StartRow + n - 1 < LastRow n = n + 1 Range("A" & StartRow).Offset(n - 1, 0).Value = n Loop End Sub
お礼
お礼するつもりが補足になってしまいました(;・∀・) 改めて、ありがとうごさいます。
補足
たくさんのコードを教えていただきありがとうございます^^これから勉強して早速色々使ってみたいと思います!
お礼
こんなに丁寧に教えて頂けるなんて、、感激しています。図々しいですが次はどんな解説があるのかワクワクしております(笑)