最後に使用されたセル値を検索する場合は、次を使用します。
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
単一の要素をセルに入れると、間違った出力が得られます。しかし、セルに複数の値を入力すると、出力は正しくなります。この背後にある理由は何ですか?
最後に使用されたセル値を検索する場合は、次を使用します。
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
単一の要素をセルに入れると、間違った出力が得られます。しかし、セルに複数の値を入力すると、出力は正しくなります。この背後にある理由は何ですか?
注Correct
:これを「ワンストップポスト」にして、最後の行を見つける方法を使用できるようにするつもりです。これは、最後の行を見つけるときに従うべきベストプラクティスもカバーします。したがって、新しいシナリオ/情報に出くわすたびに、それを更新し続けます。
信頼性が非常に低く、したがって決して使用されるべきではない最後の行を見つける最も一般的な方法のいくつか。
UsedRange
データを持つ最後のセルを見つけるために使用しないでください。信頼性が非常に低いです。この実験を試してください。
セルに何かを入力しA5
ます。次に、以下のいずれかの方法で最後の行を計算すると、5が得られます。セルをA10
赤に着色します。以下のコードのいずれかを使用した場合でも、5が得られます。使用した場合Usedrange.Rows.Count
、何が得られますか?5にはなりません。
これがどのように機能するかを示すシナリオUsedRange
です。
xlDown
同様に信頼性がありません。
このコードを検討してください
lastrow = Range("A1").End(xlDown).Row
データを持つセル()が1つしかない場合はどうなりA1
ますか?ワークシートの最後の行に到達することになります!これは、セルを選択してからキーをA1
押してからキーを押すようなものです。これにより、範囲内に空白のセルがある場合にも信頼性の低い結果が得られます。EndDown Arrow
CountA
また、間に空白のセルがあると誤った結果が得られるため、信頼性が低くなります。
したがって、の使用を避け、UsedRange
最後のセルを見つける必要がxlDown
あります。CountA
列Eの最後の行を見つけるには、これを使用します
With Sheets("Sheet1")
LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
End With
あなたが私たちが.
前に持っていることに気づいたらRows.Count
。私たちはしばしばそれを無視することを選びました。発生する可能性のあるエラーについては、この質問を参照してください。私はいつも.
前にRows.Count
使用することをお勧めしColumns.Count
ます。この質問は、 Excel2003以前とExcel2007以降のRows.Count
リターンが原因でコードが失敗する典型的なシナリオです。同様に、それぞれとを返します。65536
1048576
Columns.Count
256
16384
Excel 2007+に行があるという上記の事実は、エラーが発生する代わりに1048576
、行の値を保持する変数を常に宣言する必要があるという事実も強調しています。Long
Integer
Overflow
このアプローチでは、非表示の行がスキップされることに注意してください。上記の列Aのスクリーンショットを振り返ると、行8が非表示になっている場合、このアプローチは5
の代わりに戻ります8
。
Effective
シートの最後の行を見つけるには、これを使用します。の使用に注意してくださいApplication.WorksheetFunction.CountA(.Cells)
。ワークシートにデータを含むセルがない場合は、次のようになるため、これが必要.Find
です。Run Time Error 91: Object Variable or With block variable not set
With Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastrow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lastrow = 1
End If
End With
同じ原則が適用されます。たとえば、テーブルの3番目の列の最後の行を取得する場合です。
Sub FindLastRowInExcelTableColAandB()
Dim lastRow As Long
Dim ws As Worksheet, tbl as ListObject
Set ws = Sheets("Sheet1") 'Modify as needed
'Assuming the name of the table is "Table1", modify as needed
Set tbl = ws.ListObjects("Table1")
With tbl.ListColumns(3).Range
lastrow = .Find(What:="*", _
After:=.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End With
End Sub
注:この回答は、このコメントによって動機付けられました。の目的はUsedRange
、上記の回答に記載されているものとは異なります。
最後に使用されたセルを見つける正しい方法については、最初に何が使用されたと見なされるかを決定し、次に適切な方法を選択する必要があります。私は少なくとも3つの意味を考えています:
使用済み=空白以外、つまりデータがあります。
使用済み="...使用中、データまたはフォーマットを含むセクションを意味します。" 公式ドキュメントによると、これは保存時にExcelで使用される基準です。この公式ドキュメントも参照してください。これに気付いていない場合、基準は予期しない結果をもたらす可能性がありますが、たとえば、最終的にデータがない可能性がある特定の領域を強調表示または印刷するために、意図的に悪用される可能性もあります。そしてもちろん、ワークブックを保存するときに使用する範囲の基準として、作業の一部を失わないようにすることが望ましいです。
使用済み="...使用中、データまたはフォーマットを含むセクションを意味します"または条件付きフォーマット。 2.と同じですが、条件付き書式ルールのターゲットであるセルも含まれます。
最後に使用されたセルを見つける方法は、必要なもの(基準)によって異なります。
基準1については、この回答を読むことをお勧めします。UsedRange
信頼できないとして引用されていることに注意してください。データを含む最後のセルを報告することを単に意図していないので、それは誤解を招く(つまり、に「不公平」であるUsedRange
)と思います。UsedRange
したがって、その回答に示されているように、この場合は使用しないでください。このコメントも参照してください。
基準2UsedRange
の場合、この用途向けに設計された他のオプションと比較して、最も信頼性の高いオプションです。最後のセルが更新されていることを確認するためにワークブックを保存する必要さえありません。
Ctrl+End保存する前に間違ったセルに移動します(「ワークシートを保存するまで最後のセルはリセットされません」、
http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10%から) 29.aspx。これは古いリファレンスですが、この点では有効です)。
基準3については、組み込みの方法がわかりません。基準2は、条件付き書式を考慮していません。UsedRange
またはCtrl+で検出されない数式に基づいて、セルをフォーマットした可能性がありますEnd。この図では、フォーマットが明示的に適用されているため、最後のセルはB3です。セルB6:D7には、条件付き書式ルールから派生した書式があり、これは。によっても検出されませんUsedRange
。これを説明するには、VBAプログラミングが必要になります。
あなたの特定の質問に関して: これの背後にある理由は何ですか?
コードでは、範囲E4:E48の最初のセルをトランポリンとして使用し、。でジャンプダウンしEnd(xlDown)
ます。
「誤った」出力は、おそらく最初のセル以外に空白以外のセルが範囲内にない場合に取得されます。次に、暗闇の中で、つまりワークシートを下にジャンプします(空白の文字列と空の文字列の違いに注意する必要があります!)。
ご了承ください:
範囲に連続していない非空白のセルが含まれている場合も、間違った結果になります。
空白でないセルが1つだけあるが、それが最初のセルではない場合でも、コードは正しい結果を提供します。
このワンストップ関数を作成して、最後の行、列、セルを決定しました。データ、フォーマットされた(グループ化/コメント化/非表示)セル、条件付きフォーマットなどです。
Sub LastCellMsg()
Dim strResult As String
Dim lngDataRow As Long
Dim lngDataCol As Long
Dim strDataCell As String
Dim strDataFormatRow As String
Dim lngDataFormatCol As Long
Dim strDataFormatCell As String
Dim oFormatCond As FormatCondition
Dim lngTempRow As Long
Dim lngTempCol As Long
Dim lngCFRow As Long
Dim lngCFCol As Long
Dim strCFCell As String
Dim lngOverallRow As Long
Dim lngOverallCol As Long
Dim strOverallCell As String
With ActiveSheet
If .ListObjects.Count > 0 Then
MsgBox "Cannot return reliable results, as there is at least one table in the worksheet."
Exit Sub
End If
strResult = "Workbook name: " & .Parent.Name & vbCrLf
strResult = strResult & "Sheet name: " & .Name & vbCrLf
'DATA:
'last data row
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lngDataRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lngDataRow = 1
End If
'strResult = strResult & "Last data row: " & lngDataRow & vbCrLf
'last data column
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lngDataCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Else
lngDataCol = 1
End If
'strResult = strResult & "Last data column: " & lngDataCol & vbCrLf
'last data cell
strDataCell = Replace(Cells(lngDataRow, lngDataCol).Address, "$", vbNullString)
strResult = strResult & "Last data cell: " & strDataCell & vbCrLf
'FORMATS:
'last data/formatted/grouped/commented/hidden row
strDataFormatRow = StrReverse(Split(StrReverse(.UsedRange.Address), "$")(0))
'strResult = strResult & "Last data/formatted row: " & strDataFormatRow & vbCrLf
'last data/formatted/grouped/commented/hidden column
lngDataFormatCol = Range(StrReverse(Split(StrReverse(.UsedRange.Address), "$")(1)) & "1").Column
'strResult = strResult & "Last data/formatted column: " & lngDataFormatCol & vbCrLf
'last data/formatted/grouped/commented/hidden cell
strDataFormatCell = Replace(Cells(strDataFormatRow, lngDataFormatCol).Address, "$", vbNullString)
strResult = strResult & "Last data/formatted cell: " & strDataFormatCell & vbCrLf
'CONDITIONAL FORMATS:
For Each oFormatCond In .Cells.FormatConditions
'last conditionally-formatted row
lngTempRow = CLng(StrReverse(Split(StrReverse(oFormatCond.AppliesTo.Address), "$")(0)))
If lngTempRow > lngCFRow Then lngCFRow = lngTempRow
'last conditionally-formatted column
lngTempCol = Range(StrReverse(Split(StrReverse(oFormatCond.AppliesTo.Address), "$")(1)) & "1").Column
If lngTempCol > lngCFCol Then lngCFCol = lngTempCol
Next
'no results are returned for Conditional Format if there is no such
If lngCFRow <> 0 Then
'strResult = strResult & "Last cond-formatted row: " & lngCFRow & vbCrLf
'strResult = strResult & "Last cond-formatted column: " & lngCFCol & vbCrLf
'last conditionally-formatted cell
strCFCell = Replace(Cells(lngCFRow, lngCFCol).Address, "$", vbNullString)
strResult = strResult & "Last cond-formatted cell: " & strCFCell & vbCrLf
End If
'OVERALL:
lngOverallRow = Application.WorksheetFunction.Max(lngDataRow, strDataFormatRow, lngCFRow)
'strResult = strResult & "Last overall row: " & lngOverallRow & vbCrLf
lngOverallCol = Application.WorksheetFunction.Max(lngDataCol, lngDataFormatCol, lngCFCol)
'strResult = strResult & "Last overall column: " & lngOverallCol & vbCrLf
strOverallCell = Replace(.Cells(lngOverallRow, lngOverallCol).Address, "$", vbNullString)
strResult = strResult & "Last overall cell: " & strOverallCell & vbCrLf
MsgBox strResult
Debug.Print strResult
End With
End Sub
結果は次のようになります。
より詳細な結果を得るには、コードの一部の行のコメントを外すことができます。
1つの制限があります。シートにテーブルがある場合、結果の信頼性が低下する可能性があるため、この場合はコードの実行を避けることにしました。
If .ListObjects.Count > 0 Then
MsgBox "Cannot return reliable results, as there is at least one table in the worksheet."
Exit Sub
End If
ソリューションを使用する際に留意すべき重要な注意事項の1つ...
LastRow = ws.Cells.Find(What:="*", After:=ws.range("a1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
LastRow
...変数のLong
型が次のとおりであることを確認することです。
Dim LastRow as Long
そうしないと、.XLSXブックの特定の状況でオーバーフローエラーが発生することになります。
これは、さまざまなコードの使用に立ち寄るカプセル化された関数です。
Private Function FindLastRow(ws As Worksheet) As Long
' --------------------------------------------------------------------------------
' Find the last used Row on a Worksheet
' --------------------------------------------------------------------------------
If WorksheetFunction.CountA(ws.Cells) > 0 Then
' Search for any entry, by searching backwards by Rows.
FindLastRow = ws.Cells.Find(What:="*", After:=ws.range("a1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
End If
End Function
元の質問は最後のセルを見つける際の問題に関するものなので、この回答では、予期しない結果を得ることができるさまざまな方法をリストします。「マクロを使用してExcelシートのデータを含む最後の行を見つけるにはどうすればよいですか?」に対する私の回答を参照してください。これを解決するための私の見解のために。
まず、 sancho.sによる回答とGlennFromIowaによるコメントを拡張し、さらに詳細を追加します。
[...]最初に何が使用されていると見なされるかを決定する必要があります。少なくとも6つの意味があります。セルには:
- 1)データ、つまり数式。空白の値になる可能性があります。
- 2)値、つまり非空白の数式または定数。
- 3)フォーマット;
- 4)条件付きフォーマット。
- 5)セルに重なる形状(コメントを含む)。
- 6)テーブル(リストオブジェクト)への関与。
どの組み合わせをテストしますか?一部(テーブルなど)はテストがより困難な場合があり、一部はまれな場合(データ範囲外の形状など)ですが、その他は状況に応じて異なる場合があります(たとえば、値が空白の数式)。
あなたが考慮したいと思うかもしれない他の事柄:
それを念頭に置いて、「最後のセル」を取得する一般的な方法がどのように予期しない結果を生み出すかを見てみましょう。
.End(xlDown)
コードは、Siddharth Routの回答で説明されている理由により(たとえば、空でないセルが1つある場合や、間に空白のセルがある場合)、最も簡単に壊れます( 「xlDownも同様に信頼性が低い」を検索してください) 。Count
ing(CountA
またはCells*.Count
)に基づくソリューション、.CurrentRegion
または空白のセルまたは行が存在すると破損するソリューション.End(xlUp)
列の終わりから逆方向に検索するソリューションは、CTRL + UPと同様に、表示されている行でデータを検索します(空白の値を生成する数式は「データ」と見なされます)(したがって、オートフィルターを有効にして使用すると、誤った結果が生成される可能性があります⚠️ )。最後の行をハードコーディングするなど、標準的な落とし穴を回避するように注意する必要があります(詳細については、ここでSiddharth Routによる回答を参照し、 「列の最後の行を検索」Range("A65536").End(xlUp)
セクションを探してください)( )に依存する代わりにsht.Rows.Count
。
.SpecialCells(xlLastCell)
はCTRL+ENDと同等であり、「使用範囲」の一番下と右端のセルを返します。したがって、「使用範囲」に依存することに適用されるすべての警告は、このメソッドにも適用されます。さらに、「使用範囲」はワークブックの保存時とアクセス時にのみリセットされるため、保存されていない変更(一部の行が削除された後など)で古い結果⚠️が生成される可能性がありますworksheet.UsedRange
。dotNETによる近くの回答xlLastCell
を参照してください。sht.UsedRange
(ここのsancho.sによる回答で詳細に説明されています)データとフォーマットの両方を考慮し(条件付きフォーマットではありません)、ワークシートの「使用範囲」をリセットします。これは、希望する場合とそうでない場合があります。よくある間違いは⚠️を使用することです。これは、最後の行番号ではなく、使用された範囲の行数.UsedRange.Rows.Count
を返します(最初の数行が空白の場合は異なります)。詳細については、newguyの回答を参照してください。マクロを含むExcelシートのデータを含む最後の行?
.Find
任意のデータ(数式を含む)または任意の列の非空白値を含む最後の行を検索できます。数式と値のどちらに関心があるかを選択できますが、Excelの[検索]ダイアログ️️⚠️でデフォルトがリセットされるため、ユーザーが非常に混乱する可能性があります。また、慎重に使用する必要があります。ここでSiddharth Routの回答を参照してください( 「シートの最後の行を検索する」セクション) 。Cells
は、通常、Excel関数を再利用するよりも低速です(ただし、パフォーマンスは向上します)が、検索したいものを正確に指定できます。とVBA配列に基づく私のソリューションを参照UsedRange
して、指定された列にデータがある最後のセルを検索します。これは、非表示の行、フィルター、空白を処理し、デフォルトの検索を変更せず、非常にパフォーマンスが高くなります。どのソリューションを選択する場合でも、注意してください
Long
代わりに使用する( 65,000を超える行を取得しないようにするため)およびInteger
Overflow
Dim ws As Worksheet ... ws.Range(...)
、ではなくRange(...)
).Value
()を使用するときは、セルにエラー値が含まれていると失敗するため、のVariant
ような暗黙のキャストは避けてください。.Value <> ""
Siddarth Routの回答に加えて、Findに行番号ではなくRangeオブジェクトを返すようにすると、CountA呼び出しをスキップできると言い、返されたRangeオブジェクトをテストしてNothing(空白のワークシート)かどうかを確認します。 。
また、LastRowプロシージャのバージョンで、空白のワークシートに対してゼロを返すようにすると、空白であることがわかります。
誰もこれについて言及していないのではないかと思いますが、最後に使用したセルを取得する最も簡単な方法は次のとおりです。
Function GetLastCell(sh as Worksheet) As Range
GetLastCell = sh.Cells(1,1).SpecialCells(xlLastCell)
End Function
これは基本的に、 Cellを選択した後にCtrl+で取得したのと同じセルを返します。EndA1
注意点:Excelは、ワークシートでこれまでに使用された中で最も右下のセルを追跡します。したがって、たとえば、B3に何かを入力し、H8に何かを入力し、後でH8の内容を削除した場合でも、 Ctrl+を押すとH8セルに移動します。上記の関数は同じ動作をします。End
sub last_filled_cell()
msgbox range("A65536").end(xlup).row
end sub
これは、列Aの最後のセルです。このA65536コードはExcel2003でテストされました。
ただし、この質問はVBAを使用して最後の行を見つけることを目的としています。これは頻繁にアクセスされるため、ワークシート関数の配列数式を含めるとよいと思います。
{=ADDRESS(MATCH(INDEX(D:D,MAX(IF(D:D<>"",ROW(D:D)-ROW(D1)+1)),1),D:D,0),COLUMN(D:D))}
角かっこなしで数式を入力し、++を押して配列数式にする必要がShiftありCtrlますEnter。
これにより、列Dで最後に使用されたセルのアドレスがわかります。
pgsystemtesterのおかげで、これにより、最後に使用されたセルの行番号がわかります。
{=MATCH(INDEX(D:D,MAX(IF(D:D<>"",ROW(D:D)-ROW(D1)+1)),1),D:D,0)}
Excelの新しい計算エンジンと配列機能、およびフィルター機能を使用すると、このトピックの争いがはるかに少なくなり、以下のオプションが速度、信頼性、および単純さの最適な組み合わせを提供すると思います(これは過去にバランスを取るのが困難であることが証明されていますここにある多数の投稿が示しています)。
また、isBlank関数で定義されているようにlast used
空白ではないと定義しています。
まず、フィルター関数を使用すると、特定の行または列(この場合はColumn A
またはRow 1
)に対して以下の数式を使用して最後のセルを取得するのがはるかに簡単になることに注意してください。
=MAX(FILTER(ROW(A:A),NOT(ISBLANK(A:A))))
=MAX(FILTER(COLUMN(1:1),NOT(ISBLANK(1:1))))
上記の関数を使用すると、VBA関数に変換できますが、範囲を制限することでさらに高速になり、複数の列を実行することで機能を拡張できます(ChrisNeilsenの即時フィードバックtweeking/提案に感謝します)。また、各列を前の最後の行よりも高い行の範囲のみにスコープすることで、速度が大幅に向上することもわかりました。
Function FindLastRowInRange(someColumns As Range) As Long
Const zFx = "=MAX(FILTER(ROW(????),NOT(ISBLANK(????)),0))"
Dim tRng As Range, i As Long, tRow As Long, nRng As Range
With someColumns.Worksheet
Set tRng = Intersect(someColumns.EntireColumn, .UsedRange)
For i = 1 To tRng.Columns.Count
Set pRng = Intersect(tRng.Columns(i), _
Range(.Rows(FindLastRowInRange + 1), .Rows(.Rows.Count)))
If Not pRng Is Nothing Then
tRow = .Evaluate(Replace(zFx, "????", _
pRng.Address, 1, -1))
If tRow > FindLastRowInRange Then _
FindLastRowInRange = tRow
End If
Next i
End With
End Function
ワークシート全体(すべての列)を検討するには、前の式を参照しているが揮発性関数である別のVBA式を使用することをお勧めします。これにより、ワークシートに変更が加えられたときに数式が確実に更新されます。明らかに、これら2つの式を組み合わせることができますが、私は揮発性関数の使用を制限することを好みます。
Function FindLastRowInSheet(anywhereInSheet As Range) As Long
Application.Volatile
FindLastRowInSheet = FindLastRowInRange(anywhereInSheet.Worksheet.UsedRange)
End Function
xlup
Find
ユーザーの設定に干渉しません。うまくいけば、これで議論は終わりですが、誰かがこれに弱点を見つけたら、共有してください。
CTRL+ Shift+を模倣する方法を探していたEndので、ドットネットソリューションは素晴らしいです。ただし、Excel 2010ではset
、エラーを回避したい場合はを追加する必要があります。
Function GetLastCell(sh As Worksheet) As Range
Set GetLastCell = sh.Cells(1, 1).SpecialCells(xlLastCell)
End Function
自分でこれを確認する方法:
Sub test()
Dim ws As Worksheet, r As Range
Set ws = ActiveWorkbook.Sheets("Sheet1")
Set r = GetLastCell(ws)
MsgBox r.Column & "-" & r.Row
End Sub
Sub lastRow()
Dim i As Long
i = Cells(Rows.Count, 1).End(xlUp).Row
MsgBox i
End Sub
sub LastRow()
'Paste & for better understanding of the working use F8 Key to run the code .
dim WS as worksheet
dim i as long
set ws = thisworkbook("SheetName")
ws.activate
ws.range("a1").select
ws.range("a1048576").select
activecell.end(xlup).select
i= activecell.row
msgbox "My Last Row Is " & i
End sub
過去3年以上の間、これらは、定義された列(行の場合)および行(列の場合)ごとに最後の行と最後の列を検索するために使用している関数です。
Function lastCol(Optional wsName As String, Optional rowToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
lastCol = ws.Cells(rowToCheck, ws.Columns.Count).End(xlToLeft).Column
End Function
Function lastRow(Optional wsName As String, Optional columnToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
lastRow = ws.Cells(ws.Rows.Count, columnToCheck).End(xlUp).Row
End Function
OPの場合、これは列の最後の行を取得する方法ですE
。
Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
ここでは、よく知られているExcelの数式を使用できます。これにより、VBAを使用せずに、Excelでワークシートの最後の行を取得できます。=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
これをVBAに入れ、Excelで何も書き込まないようにするために、後者の関数のパラメーターを使用して、次のようなことを念頭に置くことができます。
Public Function LastRowWithHidden(Optional wsName As String, Optional columnToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
Dim letters As String
letters = ColLettersGenerator(columnToCheck)
LastRowWithHidden = ws.Evaluate("=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(" & letters & "))),ROW(" & letters & " )),0)")
End Function
Function ColLettersGenerator(col As Long) As String
Dim result As Variant
result = Split(Cells(1, col).Address(True, False), "$")
ColLettersGenerator = result(0) & ":" & result(0)
End Function
範囲タイプに関係なく、最後の行に対してこのユニバーサル関数を作成しました。セル参照を指定するだけで、最後の行が返されます。範囲の特性を知る必要はありません。特に、範囲が通常の範囲である場合や、ListObjectである場合は特にそうです。テーブルで通常の範囲メソッドを使用すると、間違った結果が返される場合があります。確かに事前に計画を立てて、毎回正しい方法を使用することはできますが、ユニバーサル機能を利用できるのであれば、なぜわざわざするのでしょうか。
Sub RunMyLastRow() Dim Result As Long Result = MyLastRow(Worksheets(1).Range("A1")) End Sub
Function MyLastRow(RefrenceRange As Range) As Long
Dim WS As Worksheet
Dim TableName As String
Dim ColNumber As Long
Dim LastRow As Long
Dim FirstColumnTable As Long
Dim ColNumberTable As Long
Set WS = RefrenceRange.Worksheet
TableName = GetTableName(RefrenceRange)
ColNumber = RefrenceRange.Column
''If the table (ListObject) does not start in column "A" we need to calculate the
''first Column table and how many Columns from its beginning the Column is located.
If TableName <> vbNullString Then
FirstColumnTable = WS.ListObjects(TableName).ListColumns(1).Range.Column
ColNumberTable = ColNumber - FirstColumnTable + 1
End If
If TableName = vbNullString Then
LastRow = WS.Cells(WS.Rows.Count, ColNumber).End(xlUp).Row
Else
LastRow = WS.ListObjects(TableName).ListColumns(ColNumberTable).Range.Find( _
What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
End If
MyLastRow = LastRow
End Function
''Get Table Name by Cell Range Function GetTableName(RefrenceRange As Range) As String If RefrenceRange.ListObject Is Nothing Then GetTableName = vbNullString Else GetTableName = RefrenceRange.ListObject.Name End If End Function