VBA를 사용하여 Excel에서 마지막으로 사용한 셀을 찾는 중 오류


179

마지막으로 사용한 셀 값을 찾으려면 다음을 사용하십시오.

Dim LastRow As Long

LastRow = Range("E4:E48").End(xlDown).Row

Debug.Print LastRow

단일 요소를 셀에 넣을 때 잘못된 출력이 발생합니다. 그러나 셀에 둘 이상의 값을 넣으면 출력이 정확합니다. 이것의 이유는 무엇입니까?


답변:


309

참고 : Correct마지막 행을 찾는 방법을 사용할 수있는 "원 스톱 포스트"로 만들고 싶습니다 . 마지막 행을 찾을 때 따라야 할 모범 사례도 다룹니다. 따라서 새로운 시나리오 / 정보를 접할 때마다 계속 업데이트하겠습니다.


마지막 행을 찾는 신뢰할 수없는 방법

매우 신뢰할 수없는 마지막 행을 찾는 가장 일반적인 방법 중 일부는 사용해서는 안됩니다.

  1. 중고 범위
  2. xlDown
  3. CountA

UsedRange해야 결코 데이터가있는 마지막 셀을 발견하는 데 사용할 수 없습니다. 매우 신뢰할 수 없습니다. 이 실험을 시도하십시오.

cell에 무언가를 입력하십시오 A5. 이제 아래 주어진 방법 중 하나를 사용하여 마지막 행을 계산하면 5가 표시됩니다. 이제 셀의 A10색을 빨간색으로 지정하십시오. 이제 아래 코드 중 하나를 사용하면 여전히 5를 얻습니다. Usedrange.Rows.Count무엇 을 사용 하면 얻을 수 있습니까? 5가되지 않습니다.

UsedRange작동 방식 을 보여주는 시나리오는 다음과 같습니다 .

여기에 이미지 설명을 입력하십시오

xlDown 똑같이 신뢰할 수 없습니다.

이 코드를 고려

lastrow = Range("A1").End(xlDown).Row

A1데이터 가있는 하나의 셀 ( ) 만있는 경우 어떻게 됩니까? 워크 시트의 마지막 행에 도달하게됩니다! 셀 A1을 선택한 다음 End키를 누른 다음 키 를 누르는 것과 같습니다 Down Arrow. 또한 범위 내에 빈 셀이있는 경우 신뢰할 수없는 결과를 제공합니다.

CountA 사이에 빈 셀이 있으면 잘못된 결과를 얻을 수 있기 때문에 신뢰할 수 없습니다.

따라서 하나의 사용을 피해야한다 UsedRange, xlDown그리고 CountA마지막 셀을 찾을 수 있습니다.


열에서 마지막 행 찾기

Col E에서 마지막 행을 찾으려면 이것을 사용하십시오.

With Sheets("Sheet1")
    LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
End With

당신이 우리에게 .이전 이 있음을 알게되면 Rows.Count. 우리는 종종 그것을 무시하기로 결정했습니다. 발생할 수있는 오류에 대해서는 질문을 참조하십시오 . 나는 항상 및 .이전 Rows.Count을 사용하는 것이 Columns.Count좋습니다. 이 질문은 Excel 2003 및 이전 버전과 Excel 2007 및 이후 버전에 대한 Rows.Count반환 65536으로 인해 코드가 실패하는 전형적인 시나리오 1048576입니다. 마찬가지로 Columns.Count반환 25616384각각.

엑셀 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

테이블에서 마지막 행 찾기 (ListObject)

예를 들어, 표의 세 번째 열에서 마지막 행을 가져 오는 것과 동일한 원칙이 적용됩니다.

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

9
@phan : A5 셀에 무언가를 입력하십시오. 이제 위의 방법 중 하나를 사용하여 마지막 행을 계산하면 5가 표시됩니다. 이제 셀 A10을 빨간색으로 채색합니다. 이제 위의 코드 중 하나를 사용하면 여전히 5를 얻습니다. Usedrange.Rows.Count무엇 을 사용 하면 얻을 수 있습니까? 5가 아닙니다. Usedrange는 마지막 행을 찾는 데 매우 신뢰할 수 없습니다.
Siddharth Rout

6
찾기는 불행히도 찾기 대화 상자에서 사용자의 설정을 엉망으로 만듭니다. 즉, Excel에는 대화 상자에 대한 1 세트의 설정 만 있으며 .Find를 사용하면 해당 설정이 바뀝니다. 또 다른 방법은 UsedRange를 계속 사용하지만 올바른 최대 값을 결정하는 절대적이지만 신뢰할 수없는 최대 값으로 사용하는 것입니다.
Carl Colijn

4
@CarlColijn : 나는 그것을 엉망으로 부르지 않을 것입니다. :) Excel remembers은 마지막 설정입니다. 수동으로 작업을 수행하더라도 Find실제로 "이 사실"을 알고 있으면 마지막 설정 인 기억이 남습니다.
Siddharth Rout

3
@ KeithPark : 계속하십시오 :) 지식은 그것이 확산되는 경우에만 의미가 있습니다 :)
Siddharth Rout

9
귀하의 설명 UsedRange( 데이터가있는 마지막 셀을 찾는 것이 매우 신뢰할 수 없음 )이 오도 된 것으로 생각합니다. UsedRange경우에 따라 올바른 결과를 얻을 수 있지만 해당 목적을위한 것이 아닙니다. 나는 제안 된 실험이 혼란을 더한다고 생각한다. UsedRange($ A $ 1 : $ A $ 8)로 얻은 결과 는 처음 데이터를 삭제하고 삭제하는 데 의존하지 않습니다. 오른쪽 그림은 삭제 된 데이터를 입력하지 않아도 여전히 동일합니다. 내 대답을 참조하십시오.
sancho.s ReinstateMonicaCellio

34

참고 :이 답변은 이 의견에 의해 동기 부여되었습니다 . 목적은 UsedRange위의 답변에서 언급 한 것과 다릅니다.

마지막으로 사용한 셀을 찾는 올바른 방법에 대해서는 먼저 사용 된 것으로 판단한 다음 적절한 방법을 선택해야합니다 . 나는 적어도 세 가지 의미를 생각합니다.

  1. 사용 = 공백이 아닌, 즉 갖는 데이터를 .

  2. Used = "... 사용 중 . 데이터 또는 서식 이 포함 된 섹션을 의미합니다 ." 공식 문서에 따르면, 이것은 저장시 Excel에서 사용되는 기준입니다. 이 공식 문서를 참조하십시오 . 이를 알지 못하는 경우이 기준은 예상치 못한 결과를 낳을 수 있지만, 예를 들어 데이터가 없을 수있는 특정 영역을 강조 표시하거나 인쇄하기 위해 의도적으로 악용 될 수도 있습니다. 물론 통합 문서를 저장할 때 작업의 일부를 잃지 않도록 사용할 범위의 기준으로 사용하는 것이 바람직합니다.

  3. Used = "... 사용 중, 데이터 또는 서식 이 포함 된 섹션 또는 조건부 서식 " 을 의미합니다 . 2와 동일하지만 조건부 서식 규칙의 대상인 셀도 포함합니다.

마지막으로 사용한 셀에 따라 달라집니다 찾는 방법 당신이 (당신의 기준을)합니다 .

기준 1의 경우이 답변을 읽는 것이 좋습니다 . 참고 UsedRange신뢰할 수없는 인용된다. 데이터를 포함하는 마지막 셀을 단순히보고하는 것이 UsedRange아니라 오해의 소지가 있다고 생각합니다 (예 : "불공정" ) UsedRange. 따라서이 답변에 표시된 대로이 경우에는 사용해서는 안됩니다. 이 주석 도 참조하십시오 .

기준 2의UsedRange 경우이 용도로 설계된 다른 옵션과 비교할 때 가장 신뢰할 수있는 옵션 입니다. 마지막 셀이 업데이트되도록 통합 문서를 저장할 필요조차 없습니다. 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 프로그래밍이 필요합니다.

여기에 이미지 설명을 입력하십시오


귀하의 특정 질문에 관해서 : 이것의 이유는 무엇입니까?

를 들어, 트램 폴린 등 E48 : 코드는 사용자의 범위 E4의 첫 번째 셀을 사용하는 점프 아래로 End(xlDown).

"오차"출력은 아마도 첫 번째 이외의 범위에 비어 있지 않은 셀 이없는 경우 얻을 수 있습니다 . 그런 다음 어두운 곳 으로 뛰어 들어 갑니다. 즉, 워크 시트를 아래로 내립니다 ( 공백빈 문자열 의 차이점에 주목해야 합니다 !).

참고 :

  1. 범위에 연속되지 않은 비 공백 셀이 포함 된 경우 잘못된 결과도 제공됩니다.

  2. 비어 있지 않은 셀이 하나만 있지만 첫 번째 셀이 아닌 경우 코드에서 여전히 올바른 결과를 제공합니다.


3
나는 무엇이 사용되는 것으로 먼저 결정해야하는지에 동의합니다 . 나는 적어도 6 개의 의미를 봅니다. 셀은 1) 데이터, 즉 공식으로서 빈 값을 초래할 수있다. 2) 값, 즉 비 공백 공식 또는 상수; 3) 서식; 4) 조건부 서식; 5) 셀과 겹치는 모양 (주석 포함); 6) 테이블에 참여 (목록 객체). 어떤 조합을 테스트 하시겠습니까? 일부 (예 : 표)는 테스트하기가 더 어려울 수 있으며, 일부 (예 : 데이터 범위를 벗어난 모양)는 드물지만 상황에 따라 다를 수 있습니다 (예 : 빈 값이있는 수식).
GlennFromIowa

20

마지막 행, 열 및 셀결정하기 위해이 원 스톱 함수를 만들었습니다. 데이터, 형식화 (commented / commented / hidden) 셀 또는 조건부 서식 입니다.

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

결과는 다음과 같습니다.
마지막 셀을 결정

보다 자세한 결과를 얻으려면 코드의 일부 줄을 주석 처리 해제 할 수 있습니다.
마지막 열, 행

한 가지 제한 사항이 있습니다-시트에 테이블이 있으면 결과를 신뢰할 수 없게 될 수 있으므로이 경우 코드를 실행하지 않기로 결정했습니다.

If .ListObjects.Count > 0 Then
    MsgBox "Cannot return reliable results, as there is at least one table in the worksheet."
    Exit Sub
End If

2
@franklin-검토자가 거부 한받은 편지함 메시지가 방금 수정되었습니다. 나는 그 실수를 고쳤다. 나는 필요할 때 이미이 기능을 한 번 사용했고 다시 사용할 것이다. 정말 고마워 친구 야!
ZygD

11

솔루션을 사용할 때 명심해야 할 중요한 사항 ...

LastRow = ws.Cells.Find(What:="*", After:=ws.range("a1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

... LastRow변수가 다음 Long유형 인지 확인하는 것 입니다 .

Dim LastRow as Long

그렇지 않으면 .XLSX 통합 문서의 특정 상황에서 OVERFLOW 오류가 발생합니다.

이것은 다양한 코드 사용에 빠지는 캡슐화 된 함수입니다.

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

8

Siddarth Rout이 제공 한 답변에 행 번호 대신 Range 개체 반환 반환을 사용하여 CountA 호출을 건너 뛸 수 있다고 말한 다음 반환 된 Range 개체를 테스트하여 아무것도 없는지 확인하십시오 (빈 워크 시트) .

또한 LastRow 프로 시저의 버전에서 빈 워크 시트에 대해 0을 반환하면 비어 있음을 알 수 있습니다.


8

아무도 이것을 언급하지 않았지만, 마지막으로 사용한 셀을 얻는 가장 쉬운 방법은 다음과 같습니다.

Function GetLastCell(sh as Worksheet) As Range
    GetLastCell = sh.Cells(1,1).SpecialCells(xlLastCell)
End Function

이것은 본질적으로 Cell을 선택한 후 Ctrl+ 와 동일한 셀을 반환합니다 .EndA1

주의 사항 : Excel은 워크 시트에 사용 된 가장 오른쪽 아래 셀을 추적합니다. 예를 들어 B3에 무언가를 입력하고 H8에 무언가 를 입력 한 다음 나중에 H8 의 내용을 삭제하면 Ctrl+ End를 누르면 여전히 H8 셀로 이동합니다. 위의 기능은 동일한 동작을합니다.


2
Last CellExcel에서 때로는 ( Used Range)과 다른 빈 셀을 참조합니다 Last Used Cell.
shA.t

1
OP는 마지막 행만 필요했지만 맞습니다. 마지막 셀은 H5 여야합니다 . 그러나 A5 에서 값을 삭제 한 후 함수를 테스트 할 수 있습니다 . 마지막 셀이 빈 셀임을 알 수 있습니다. 코드 Cells(1,1).Select()에 잘못된 편집이 필요하다고 생각합니다 ActiveSheet.Cells(1,1).Select. 또한 VBA에서는 Select;) 을 사용하지 않는 것이 좋습니다 .
shA.t

5
이로 인해 Excel VBA에 대한 두 가지 기본 규칙이 적용됩니다. 선택하지 마십시오! 그리고 원하는 시트가 활성 시트라고 가정하지 마십시오.
Rachel Hettinger 2016 년

1
이것은 오래된 답변이지만 누락되었습니다 Set.
BigBen

8

원래 질문은 마지막 셀을 찾는 문제 에 관한 것이기 때문에이 답변에는 예기치 않은 결과를 얻을 수있는 다양한 방법이 나열되어 있습니다 . "매크로를 사용하여 Excel 시트의 데이터가 포함 된 마지막 행을 어떻게 찾을 수 있습니까?"에 대한 내 답변을 참조하십시오. 이 문제를 해결하기 위해 노력했습니다.

나는에 확대하여 시작합니다 sancho.s로 대답 하고 GlennFromIowa에 의해 코멘트 도 자세한 내용을 추가 :

[...] 먼저 어떤 것이 사용되는지를 결정해야합니다. 나는 적어도 6 개의 의미를 봅니다. 세포는 :

  • 1) 데이터, 즉 공식은 가능한 빈 값을 초래한다.
  • 2) 값, 즉 비 공백 공식 또는 상수;
  • 3) 서식;
  • 4) 조건부 서식;
  • 5) 셀과 겹치는 모양 (주석 포함);
  • 6) 테이블에 참여 (목록 객체).

어떤 조합을 테스트 하시겠습니까? 일부 (예 : 표)는 테스트하기가 더 어려울 수 있으며 일부는 데이터 범위를 벗어난 모양과 같이 드물지만 상황에 따라 달라질 수 있습니다 (예 : 빈 값이있는 수식).

고려해야 할 다른 것들 :

  • A) 숨겨진 행 (예 : 자동 필터), 빈 셀 또는 빈 행이있을 수 있습니까?
  • B) 어떤 종류의 성능이 허용됩니까?
  • C) VBA 매크로가 통합 문서 또는 응용 프로그램 설정에 어떤 방식으로 영향을 줄 수 있습니까?

이를 염두에두고 "마지막 셀"을 얻는 일반적인 방법이 어떻게 예기치 않은 결과를 생성 할 수 있는지 살펴 보겠습니다 .

  • .End(xlDown)질문 의 코드는 Siddharth Rout의 답변에 설명 된 이유 때문에 (예 : 하나의 비어 있지 않은 단일 셀 또는 사이에 빈 셀이있는 경우) 가장 쉽게 중단 됩니다 ( "xlDown은 똑같이 신뢰할 수 없습니다" ) .
  • Counting ( CountA또는 Cells*.Count)을 기반으로 하거나 .CurrentRegion빈 셀이나 행이있을 때 중단되는 솔루션 👎
  • .End(xlUp)CTRL + UP과 마찬가지로 열 끝에서 뒤로 검색 하는 솔루션 은 보이는 행 에서 데이터 (공백 값을 생성하는 수식은 "데이터"로 간주 됨)를 찾습니다 (자동 필터를 사용하여 사용하면 잘못된 결과가 발생할 수 있음) ).

    마지막 행 하드 코딩과 같은 표준 함정을 피하기 위해주의를 기울여야합니다 (자세한 내용 은 Siddharth Rout의 답변을 여기에서 다시 참조하십시오 . "열에서 마지막 행 찾기" 섹션 참조 Range("A65536").End(xlUp)). 에 의존하는 대신 sht.Rows.Count.

  • .SpecialCells(xlLastCell)CTRL + END와 동일하며 "사용 된 범위"의 맨 아래 및 가장 오른쪽 셀을 반환하므로 "사용 된 범위"에 의존하는 모든 경고는이 방법에도 적용됩니다. 또한 통합 문서를 저장할 때, "사용 된 범위는"단지 재설정 및 액세스 할 때 worksheet.UsedRange, 그래서 xlLastCell저장되지 않은 변경과 부실 results⚠️을 생산하고 있습니다 (예를 들어, 일부 행이 삭제 된 후). dotNET 근처의 답변을 참조하십시오 .
  • sht.UsedRange( 여기 에서 sancho.s의 답변 에 자세히 설명되어 있음 ) 는 데이터와 서식 (조건부 서식은 아니지만 )을 모두 고려 하고 워크 시트의 "사용 범위"를 재설정합니다 .

    일반적인 실수 는 마지막 행 번호가 아닌 사용 된 범위 의 행 수.UsedRange.Rows.Count 를 반환하는 ⚠️을 사용 하는 것입니다 (처음 몇 행이 비어 있으면 다를 수 있음). 자세한 내용은 어떻게 찾을 수 있는지에 대한 newguy의 답변을 참조하십시오 매크로가있는 Excel 시트의 데이터가 포함 된 마지막 행?

  • .Find데이터 (공식 포함) 또는 모든 열에서 공백이 아닌 값 으로 마지막 행을 찾을 수 있습니다 . 수식이나 값에 관심이 있는지 여부를 선택할 수 있지만 Excel의 찾기 대화 상자 ️️⚠️ 에서 기본값을 재설정 하여 사용자에게 혼란을 줄 수 있습니다. 또한 신중하게 사용해야합니다. 여기 Siddharth Rout의 답변을 참조 하십시오 ( "시트의 마지막 행 찾기" 섹션) )
  • Cells루프에서 개별 ' 를 검사하는보다 명확한 솔루션 은 일반적으로 Excel 함수를 다시 사용하는 것보다 느리지 만 (아직 성능이있을 수는 있지만) 원하는 것을 정확하게 지정할 수 있습니다. 주어진 열에 데이터가있는 마지막 셀을 찾으려면 내 솔루션 기반 UsedRange및 VBA 배열을 참조하십시오. 숨겨진 행, 필터, 공백을 처리하고 찾기 기본값을 수정하지 않으며 성능이 뛰어납니다.

어떤 솔루션을 선택하든 조심하십시오

  • 행 번호를 저장하는 Long대신 사용 Integer( Overflow65k 개 이상의 행 을 사용하지 않도록 )
  • 항상 작업중 인 워크 시트를 지정하십시오 (예 : Dim ws As Worksheet ... ws.Range(...)대신 Range(...))
  • 사용하는 경우 .Value이다 (이는 Variant) 등 암시 캐스트 방지 .Value <> ""셀 에러 값을 포함하는 경우가 실패로한다.

4

그러나이 질문은 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 열에서 마지막으로 사용한 셀의 주소가 제공됩니다.


1
나는 이것을 좋아한다. 행 번호 만 가져 오도록 약간 변경할 수 있습니다 ... '{= MATCH (INDEX (D : D, MAX (IF (D : D <> "", ROW (D : D) -ROW (D1) +1))) , 1), D : D, 0)} '
PGSystemTester 2018

3
sub last_filled_cell()
msgbox range("A65536").end(xlup).row
end sub

여기, A65536이 코드가 Excel 2003에서 테스트 된 열 A의 마지막 셀이 있습니다.


코드가이 오래된 질문에 어떻게 대답하는지 설명 할 수 있습니까?
shoover

1
이 답변은 정확하고 유용 할 수 있지만, 문제를 해결하는 데 도움이되는 방법을 설명하기 위해 설명과 함께 포함 하는 것이 좋습니다 . 이것은 작동을 멈추게하는 변경 (아마도 관련이없는)이 있고 사용자가 한 번 작동 한 방식을 이해해야하는 경우 특히 유용합니다.
Kevin Brown

2

CTRL+ Shift+ 를 모방 할 수있는 방법을 찾고 End있었으므로 Excel 2010을 제외하고 dotNET 솔루션은 훌륭 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

1

여기 내 센트가 있습니다.

IMHO 데이터가 제외 된 숨겨진 행의 위험이 너무 커서 원 스톱 응답xlUp 으로 간주 할 수 없습니다 . 나는 그것이 간단하고 대부분의 시간 동안 작동 할 것이라는 데 동의하지만 경고없이 마지막 행을 과소 평가 할 위험이 있습니다. 이것은 CATASTROPHIC을 생산할 수 있습니다 스택 Overlow에 뛰어 들어이 값을 캡처하는 "확실한 방법"을 찾고 있던 사람에 대한 몇 가지 poinit에서 결과를.

Find방법은 완벽하며 원 스톱 답변 으로 승인합니다 . 그러나 Find설정 변경의 단점은 특히 UDF의 일부인 경우 성 가실 수 있습니다.

게시 된 다른 답변은 괜찮지 만 복잡성이 약간 초과됩니다. 따라서 여기에 안정성의 균형, 최소한의 복잡성 및을 사용하지 않는 균형을 찾으려고 시도했습니다 Find.

Function LastRowNumber(Optional rng As Range) As Long

If rng Is Nothing Then
    Set rng = ActiveSheet.UsedRange
Else
    Set rng = Intersect(rng.Parent.UsedRange, rng.EntireColumn)
    If rng Is Nothing Then
        LastRowNumber = 1
        Exit Function
    ElseIf isE = 0 Then
        LastRowNumber = 1
        Exit Function

    End If

End If

LastRowNumber = rng.Cells(rng.Rows.Count, 1).Row

Do While IsEmpty(Intersect(rng, _
    rng.Parent.Rows(LastRowNumber)))

    LastRowNumber = LastRowNumber - 1
Loop

End Function

이것이 좋은 이유 :

  • 많은 변수가 아닌 상당히 간단합니다.
  • 여러 열을 허용합니다.
  • Find설정을 수정하지 않습니다
  • 전체 열이 선택된 상태에서 UDF로 사용되는 경우 동적입니다.

왜 이것이 나쁜지 :

  • 매우 큰 데이터 세트와 지정된 열의 사용 된 범위와 마지막 행 사이에 큰 간격이 있으면 드물게 수행 속도가 느려집니다.

그러나 find설정 을 엉망으로 만들 거나 느리게 수행 하는 단점이있는 원 스톱 솔루션이 더 나은 전반적인 솔루션이라고 생각합니다. 그런 다음 사용자는 자신의 설정으로 문제를 해결하여 코드 진행 상황을 파악하여 개선하려고 시도 할 수 있습니다. 를 사용 xLUp하면 잠재적 인 위험에 대해 경고하지 않으며 코드를 제대로 알지 못하는 기간을 아는 사람을 위해 계속할 수 있습니다.


1

지난 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

마지막 행 / 열이 숨겨져 있으면 잘못된 결과가 반환됩니다.
PGSystemTester 2018

@PGSystemTester-예, 이해하지만 프로그래밍 할 때 숨겨져 있으면 마지막 열 / 행이 아닙니다.
Vityata '11

다행입니다. 귀하의 상황이 일반적인 사용 사례가 아닌 것 같습니다. 내가 마지막 행을 필요로 고객과 작업 할 때 더 자주, 그들은 데이터가 아닌 가장 낮은 가장 낮은 셀 seaching하는 데이터 셀. 어쨌든 .. 잘 작동합니다. 👍
PGSystemTester

@PGSystemTester-요점을 알았지 만 구조를 관리하고 보이지 않는 셀을 허용하지 않는 것은 매력처럼 작동합니다.
Vityata

@PGSystemTester-예, 작업이 빈 행을 허용 EVAL()하는 경우 유명한 Excel 수식을 사용합니다. 사람들은 그것이 Eval()악 하다고 생각할 수도 있지만 이것은
쓸만한

0
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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.