• ベストアンサー

エクセルVBAでデータ最終行取得方法

エクセルVBAでデータ最終行取得方法で良い方法を教えてください。 データの行数、列数は不定。 最多のデータ行の列も不定。 この条件で、データ最終行を取得するにはどうすればよいでしょうか? lastrow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row では、A列の最終行に限定されます。 lastrow = ActiveSheet.Cells(1, "A").SpecialCells(xlLastCell).Row では、列の限定はありませんが、一旦データ入力後、削除した部分まで入ってしまいます。 lastrow = ActiveSheet.UsedRange.Rows.Count では、データ入力後、削除した部分まで入ってしまい、かつ、1行目など上部が空白の場合、不正確になります。

質問者が選んだベストアンサー

  • ベストアンサー
  • popesyu
  • ベストアンサー率36% (1782/4883)
回答No.1

それぞれの利点も欠点も分かっているなら後は 足りない部分を補うようにすればよいだけではないでしょうか。 ・A列の最終行に限定されてしまう。 →列の指定を動的にして最大の行数を取得する。 例えばこんな感じ。ForでなくてもDoとかでも可です。 for x = 1 to ActiveSheet.Usedrange.Collumns.Count temprow = ActiveSheet.Cells(ActiveSheet.Rows.Count, x).End(xlUp).Row if temprow > lastrow then lastrow=temprow end if next 結局他の部分にしても 最終行として取得したセル内が空白がどうかのチェックを行い、空白だったら行削除するとか、1行目など上部が空白の場合の例外処理をいれて対応しましょう。

merlionXX
質問者

お礼

なるほど。 ありがとうございます。

その他の回答 (10)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.11

こんにちは。merlionXXさん。 With ActiveSheet.UsedRange  lastrow = .Cells(.Count).Row End With >.Cells(.Count)って、UsedRange内の最後(右下)のセルという理解でよいのですね? そうです。.Cells は、 左から右へ、上から下へと数を数えていきますから、最後のセルは、右端下になります。 #7 のbanker_Uさんのおっしゃるとおり、私も、SpecialCellsのLastCellは使いたいとは思います。でも、ワークシートに対する Refreshの方法が見当たらないのです。 最初Clearメソッドを使えばよいと思っていましたが、それだけではダメでした。オブジェクト自体を更新しないとダメなのですね。まだ、明確に、Refreshさせるための方法が見つかりません。ApplicationのWindowやダミーのブックで切り替えるなら出来そうですが、それは、あまりにも泥臭さすぎます。それと、ScreenUpDating ではダメだったわけです。 こんな方法も考えてみました。やはり、前回のような(自称)関西風です。 他にも、Find メソッドで、下から xlPrevious で、戻っていく方法もあると思います。 Sub FindLastRow2() '最終行を探す Dim r As Range Dim MaxRow As Long Dim ar As Variant Dim buf As Variant Set r = ActiveSheet.UsedRange ar = Evaluate("(" & r.Address & "<>"""")*(ROW(" & r.Address & "))") For i = r.Rows.Count To 1 Step -1    buf = WorksheetFunction.Index(ar, i, 0)    MaxRow = WorksheetFunction.Max(buf)    If MaxRow > 0 Then     Exit For    End If Next  MsgBox "最後の行は、" & MaxRow End Sub

merlionXX
質問者

お礼

何度もありがとうございました。 とても勉強になりました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.10

#4 です。本当にすみません、、、 #9 で、、 >#5 です。何度もすみません。 >#5 だと正しく最終行を返さないので、差替えます。すみません。 は #4 の間違いです。Wendy02 さん、大変申し訳ありませんでした。以後、気をつけます。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.9

#5 です。何度もすみません。 #5 だと正しく最終行を返さないので、差替えます。すみません。 それから、SpecialCells(xlCellTypeLastCell) は期待通り動作しない 場合があります。それは、ご質問文にあるとおり、 >一旦データ入力後、削除した部分まで入ってしまいます。 だからです。使う場合は、特に注意が必要ですね。 'Find Last Row Number Function GET_LASTROWNUM(ByRef SH As Worksheet) As Long      Dim rngLASTROWS As Range, R As Range   Dim lngLAST_ROWNUM As Long      On Error Resume Next   Set rngLASTROWS = SH.UsedRange _     .Rows(SH.UsedRange.Rows.Count).Columns.Offset(1)   If Err.Number > 0 Then     GET_LASTROWNUM = SH.Rows.Count     GoTo Terminate   End If   On Error GoTo 0        For Each R In rngLASTROWS     lngLAST_ROWNUM = R.End(xlUp).Row     If lngLAST_ROWNUM > GET_LASTROWNUM Then       GET_LASTROWNUM = lngLAST_ROWNUM     End If   Next R Terminate:   Set rngLASTROWS = Nothing End Function 'Find Last Column Number Function GET_LASTCOLNUM(ByRef SH As Worksheet) As Long      Dim rngLASTCOLS As Range, R As Range   Dim lngLAST_COLNUM As Long      On Error Resume Next   Set rngLASTCOLS = SH.UsedRange _     .Columns(SH.UsedRange.Columns.Count).Rows.Offset(0, 1)   If Err.Number > 0 Then     GET_LASTCOLNUM = SH.Columns.Count     GoTo Terminate   End If   On Error GoTo 0      For Each R In rngLASTCOLS     lngLAST_COLNUM = R.End(xlToLeft).Column     If lngLAST_COLNUM > GET_LASTCOLNUM Then       GET_LASTCOLNUM = lngLAST_COLNUM     End If   Next R    Terminate:   Set rngLASTCOLS = Nothing End Function

merlionXX
質問者

お礼

何度もありがとうございます。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.8

#3です。質問の意味が判りました。 Sub test01() r = Range("A1").SpecialCells(xlCellTypeLastCell).Row c = Range("A1").SpecialCells(xlCellTypeLastCell).Column MsgBox r MsgBox c mc = 1 mr = 1 '----- For i = 1 To r ct = Cells(i, "IV").End(xlToLeft).Column If mc < ct Then mc = ct Next i MsgBox "最右列は" & mc '----- MsgBox "最下列は" & r End Sub で良いでしょう。 LastCellは、質問の意味での最下行を拾うと思う。セルを上から下、左から右に連番を振った最後(のセルのIndex値)だから。 それまでの全行について、データの最右列を探せばよい。

merlionXX
質問者

お礼

ありがとうございます。

  • banker_U
  • ベストアンサー率21% (17/78)
回答No.7

私の案はこんな感じ。 何と言ってもLastCellを使わない手は無いと思う。 その1:  一旦上書き保存してからLastCellを取得する。 その2:  Lastcell.Rowからデータの入っている列を探して上へ見ていく方法。 Function LastRow() As Integer tempLastRow = ActiveCell.SpecialCells(xlCellTypeLastCell).Row tempLastcolumn = ActiveCell.SpecialCells(xlCellTypeLastCell).Column EndRowA = Range("A65536").End(xlUp).Row LastRow = tempLastRow Do While Cells(LastRow, tempLastcolumn).End(xlToLeft).Column = 1 _ And LastRow > EndRowA LastRow = LastRow - 1 Loop End Function

merlionXX
質問者

お礼

ありがとうございました。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.6

> UsedRange で得られる範囲がA1セルからではない場合に備え、 > どのような対応を組み込めばいいでしょうか? #4 の関数はその点について、対応済みです。   Set UR = SH.UsedRange   For Each R In UR.Rows(UR.Rows.Count).Columns の UR.Rows(UR.Rows.Count).Columns の部分で、UsedRange 内の 最下行を表す Columns コレクション(例えばB1:B20) が返されます。 この Columns コレクション 内を For Each ループさせて End(xlUp) プロパティーで取得しています。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

こんにちは。Wendy02です。 >データの行数、列数は不定。 >最多のデータ行の列も不定。 実際、このようなことに出会ったことがないです。列がどこまで使うという、イメージがないと、実際にどこに行くか分らないことになってしまいます。そして、End プロパティで探していくことになりますね。 >一旦データ入力後、削除した部分まで入ってしまいます。 ClearContents を使っているようです。そうする、書式データが残っています。Clearを使えば、Format は、削除されますが、画面(Window)を切り替えない限りは、残っています。 なお、これでは、正確にはとれませんが、 lastrow = ActiveSheet.UsedRange.Rows.Count   ↓ With ActiveSheet.UsedRange  lastrow = .Cells(.Count).Row End With ということです。 まあ、KenKen_SPさんのと比較して、試してみてください。 これは、最終行のみです。(私は、こういうやり方を、関西風と呼んでいます。(^^;) '------------------------------ Sub FindLastDataRow() Dim r As Range Dim myRow As Long Dim myCol As Integer Dim i As Long  Set r = ActiveSheet.UsedRange  myRow = r.Rows.Count  For i = myRow To 1 Step -1  If WorksheetFunction.CountA(r.Rows(i).Cells) > 0 Then    Exit For  End If  Next MsgBox "最終行は、" & i End Sub

merlionXX
質問者

お礼

ありがとうございました。 With ActiveSheet.UsedRange  lastrow = .Cells(.Count).Row End With 勉強になりました! .Cells(.Count)って、UsedRange内の最後(右下)のセルという理解でよいのですね?

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.4

こんにちは。KenKen_SP です。 関数化してみました。折角なので、最終列番号を取得する関数も作って みました。汎用的に使えると思います。 ロジックは、UsedRange 内の各最終行・列でループさせて最大の行・列 番号をそれぞれ End プロパティーで取得する、、というものです。 基本的には #1 popesyu さんと同一の考え方ですが、UsedRange で得ら れる範囲は必ずしも A列からではないことに注意が必要です。 UsedRange を使う理由は、調べる範囲(ループ回数)を最小限にして、 高速化するためです。 各関数の引数には Worksheet オブジェクトを渡します。使い方は、 コードの最後の方にサンプルコードを書いておきました。 'Find Last Row Number Function GET_LASTROWNUM(ByRef SH As Worksheet) As Long      Dim UR As Range, R As Range   Dim lngLAST_ROWNUM As Long   Set UR = SH.UsedRange   For Each R In UR.Rows(UR.Rows.Count).Columns     lngLAST_ROWNUM = R.End(xlUp).Row     If lngLAST_ROWNUM > GET_LASTROWNUM Then       GET_LASTROWNUM = lngLAST_ROWNUM     End If   Next R   Set UR = Nothing End Function 'Find Last Column Number Function GET_LASTCOLNUM(ByRef SH As Worksheet) As Long      Dim UR As Range, R As Range   Dim lngLAST_COLNUM As Long   Set UR = SH.UsedRange   For Each R In UR.Columns(UR.Columns.Count).Rows     lngLAST_COLNUM = R.End(xlToLeft).Column     If lngLAST_COLNUM > GET_LASTCOLNUM Then       GET_LASTCOLNUM = lngLAST_COLNUM     End If   Next R   Set UR = Nothing End Function Sub SampleMacro()   MsgBox "最終行:= " & GET_LASTROWNUM(ActiveSheet)   MsgBox "最終列:= " & GET_LASTCOLNUM(ActiveSheet) End Sub

merlionXX
質問者

お礼

わざわざ関数をつくってくださいましてありがとうございます。 UsedRange で得られる範囲がA1セルからではない場合に備え、どのような対応を組み込めばいいでしょうか?

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

Sub test02() d = Range("A65536").End(xlUp).Row r = Range("IV1").End(xlToLeft).Column MsgBox d MsgBox r End Sub でやれば途中空白行があっても最下行(行番号)、最右列を取れますが。 UsedRange、CurrentRegionもそれぞれ特徴は ありますが。 何が困っているのかよくわからないですがとりあえず。

merlionXX
質問者

お礼

ありがとうございます。 ご教示のコードではたとえば、B2:C3のみにデータがある場合、拾うことができません。

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.2

> lastrow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row > では、A列の最終行に限定されます。 列は最大で256なのでループさせ、その中の最大を採用する。 ただし lastrow = ActiveSheet.Cells(1, "A").SpecialCells(xlLastCell).Row で最も使用しているであろう列でBreak。 ではいかが?

merlionXX
質問者

お礼

そうですね。 ありがとうございます。

関連するQ&A

  • VBA データのある最終行の取得

    エクセルVBAで最終行を取得する良い方法を教えて下さい。 VBA初心者でいきづまっていまして、、、 内容はボタンを押した時にF列に対して最終行を取得して、 その最終行の下のセルにボタンの内容が繁栄させるようにしたくて Private Sub CommandButton202_Click() Dim lastRow As Long lastRow = Cells(Rows.Count, 6).End(xlUp).Row + 1 Cells(lastRow, 6).Value = CommandButton202.Caption End Sub と作ってみたのですが、F17より下に文字がはいっているため、 検索範囲を「F列」ではなく、「F2:F16」のように範囲を指定したいのですがどうしたらよいでしょうか、、、。 結構色々調べてはみたのですができなくて、、、

  • エクセルVBAで最終行取得方法

    エクセルVBAで最終行を取得する良い方法を教えて下さい。 VBA初心者でいきづまっていまして、、、 内容はボタンを押した時にF列に対して最終行を取得して、 その最終行の下のセルにボタンの内容が繁栄させるようにしたくて Private Sub CommandButton202_Click() Dim lastRow As Long lastRow = Cells(Rows.Count, 6).End(xlUp).Row + 1 Cells(lastRow, 6).Value = CommandButton202.Caption End Sub と作ってみたのですが、F17より下に文字がはいっているため、 検索範囲を「F列」ではなく、「F2:F16」のように範囲を指定したいのですがどうしたらよいでしょうか、、、。 結構色々調べてはみたのですができなくて、、、

  • VBA 最終行を選んだシートにコピーする。

    VBAど初心者です。どうしても最終行のデータを選んだシートにコピーできません。 LastRow.Selectのところで、止まってしまいます。どのように行を設定していいのかさっぱりわかりません。どなたか、ご指導のほどよろしくお願いします。 Sub copy_last_line() Dim LastRow As Long Sheets("Sheet1").Select LastRow = Cells(Rows.Count, 1).End(xlUp).Row LastRow.Select Selection.Copy Sheets("Sheet2").Select Range("A1").Select ActiveSheet.Paste Sheets("Sheet1").Select Range("A1").Select End Sub

  • Excel vbaのClearについて

    よろしくお願いします。 Excel2003使用です。 最終行を指定して、それを使って動作をしたいのですが、、うまく動作しません。 A列~D列まで入力があり、A列の52行目からD列の最終行までをClearしたいのです。 Set ps = ThisWorkbook.Worksheets("●●") LastRow = ps.Cells(ps.Rows.Count,1).End(xlUP).Row ps.Range(Cells(52,1),Cells(LastRow,4)).Clear →Error1004がでます うまく動く方法をご存じな方、よろしくお願いします。

  • VBAで最終行を取得する方法

    最終行を取得する方法について教えていただきたいです。 例えば以下のようなデータがあった場合 (A列~D列、3行までデータがある状態) -------------------------------- 田中 24歳 生命保険 営業 山口 47歳 銀行   営業 大野 36歳 IT    SE -------------------------------- ここで最終行を取得する際に、 Range("A1").End(xlDown).Rowをすれば取得できました。 しかしデータが以下のような場合 (A列が空白) -------------------------------- 田中 24歳 生命保険 営業    47歳 銀行   営業    36歳 IT    SE -------------------------------- この場合に上記と同じ取得方法をすると、オーバーフローになります。 そこで他の取得方法を調べたのですが、 ActiveSheet.UsedRange.Rowを試したところ、最終行として取得できたのは「1」でした。 A列が空白の状態でも、今回の場合だと「3」という最終行を取得するにはどうすれば良いでしょうか。

  • エクセルVBAで最終行取得ができない

    エクセルVBAでたとえばC列にどこまでデータが入力されているかを調べるとき、通常は r = Cells(Rows.Count, "C").End(xlUp).Row などでできます。 しかし添付画像のような入力フォームが出来上がっており、かつC列に最初から何らか(画像では〒マーク)の入力がされているので、そこに回答者が途中まで入力された場合、これでは最終行は取得できません。 逆に上からEnd(xlDown)でやろうとしても、途中に空白セルがあってお手上げです。 余分な〒マークを元データから削除してしまいたいのですがそれでは入力されているところのマークまで消えてしまいます。 このようなファイルが何百もあり、それを1枚のシートにまとめようとしているのですが、この最終行取得でつまずいてしまいました。 どのような方法があるでしょうか? 画像はエクセル2013ですが、実際にマクロを動かすのは2010です。

  • Excelでフィルターのかかっているときの最終行の取り方。

    Dim mySh As Worksheet Set mySh = Sheet("Sheet1") Debug.Print mySh.Cells(mySh.Rows.Count,1).End(xlup).Row でデータのあるA列の最終行を取得していますが、この場合、フィルターがかかっていると実際のデータのある最終行でなくて見えている部分の最終行が返ってきます。 Excel2003 SP3 WindowsXP SP3 フィルターがかかっていても実際のデータのある最終行を取得する方法あるのでしょうか?

  • 最終行/処理対象のデータまでを表すVBA

    こんばんは、データの最終行/処理する対象のセルまで処理する場合のVBAの記述について質問させてください!VBAの最終行/処理する対象のセルまで選択するために使用する記述方法が何種類かありますが、そのうち、書籍やネットで検索しても出てこない記述方法について今一つ理解ができていません(T_T) 本屋で売っている書籍やネットで検索すると出てくる記述方法 Range~.End(xlUp).Row Range~.CurrentRegion Range~.SpecialCells(xlLastCell) Range~.Cells(Rows.Count, 1).End(xlUp).Row 上記のようなVBAは書籍やネットで検索すると説明や違いについても出てくるので、説明を読めば理解ができるのですが、 Sheets("テスト").Range("A1:C" & Sheets("テスト").Cells _(1).CurrentRegion.Rows.Count) Range("A1").CurrentRegion.Cells(Range _("A1").CurrentRegion.Cells.Count).Row 上記のようなVBAについては検索しても説明など出てこないうえに、 なぜ上記のような記述になるのかあまり理解できていません(>_<) 書籍やネットで検索すると出てくる「Range~.CurrentRegion」などの記述方法から何となく、CurrentRegionやCells.Countを使わないといけないというのは理解できますが、なぜ「~CurrentRegion.Rows.Count)」はRowsがカッコの中に入っていて、「~CurrentRegion.Cells.Count).Row」はカッコの外に出ているのか??といった細かいことが分からずにいます。。。 半ば丸暗記のようにして使ってしまっているのですが、もし上記のようなVBAについてわかるかたがいらっしゃれば、ご教授いただけるととても嬉しいです! また、上記以外にもまだ検索しても出てこないようなVBAがあるのでしょうか?? 頭が混乱しそうです!(゜Д゜;)

  • vba エクセル

    2行目から、最終行までEmptyにしたいのにならないです。 1行目はフィールド行なのに、そのままにしたいのですが 2行目から最終行は空白にしたいです。 なので Sub TEST() With Sheets("log") lastRow = .Cells(.Rows.Count, "b").End(xlUp).Row LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column .Range(.Cells(2, LastCol), .Cells(lastRow, LastCol)) = Empty End With End Sub としたのですが、何も起こりません。 lastRowは100、LastColは5なのですが、 このマクロを実行しても何も起こらないです。 なぜでしょうか?

  • エクセルマクロ 最終行ではなく途中行を検索したい

    よろしくお願いします。 今現在、どこからかの流用で、下記のように3(C)列の3行目から最終行まで 入力する形にしていますが、最終行ではなく(1)途中の空白、若しくは(2)指定の 行がある場合、又は(3)罫線が引かれている所まで はどのように書き換えれば よいでしょうか? ※(1)、(2)、(3)のそれぞれの場合で回等頂ければと思います。 Dim LastRow As Integer LastRow = Cells(Rows.Count, 3).End(xlUp).Row For p = 3 To LastRow Cells(p, 2).Select ActiveCell.FormulaR1C1 = p - 2 '開始位置の2行ズレ分、-2を入力 Next p

専門家に質問してみよう