VBA के साथ Excel में अंतिम उपयोग किए गए सेल को खोजने में त्रुटि


179

जब मैं अंतिम उपयोग किए गए सेल मान को खोजना चाहता हूं, तो मैं उपयोग करता हूं:

Dim LastRow As Long

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

Debug.Print LastRow

जब मैं किसी एक तत्व को सेल में डालता हूं तो मुझे गलत आउटपुट मिल रहा है। लेकिन जब मैं सेल में एक से अधिक मूल्य डालता हूं, तो आउटपुट सही होता है। इसके पीछे क्या कारण है?


जवाबों:


309

नोट : मैं इसे "वन स्टॉप पोस्ट" बनाने का इरादा रखता हूं जहां आप Correctअंतिम पंक्ति को खोजने के तरीके का उपयोग कर सकते हैं । यह अंतिम पंक्ति का पता लगाने के लिए सर्वोत्तम प्रथाओं को भी कवर करेगा। और इसलिए जब भी मैं किसी नए परिदृश्य / जानकारी पर आता हूं, मैं इसे अपडेट करता रहूंगा।


अंतिम पंक्ति खोजने के अविश्वसनीय तरीके

अंतिम पंक्ति खोजने के कुछ सबसे सामान्य तरीके जो अत्यधिक अविश्वसनीय हैं और इसलिए कभी भी उपयोग नहीं किए जाने चाहिए।

  1. UsedRange
  2. xlDown
  3. COUNTA

UsedRangeजो भी अंतिम डेटा है उसे खोजने के लिए कभी भी उपयोग नहीं किया जाना चाहिए । यह बेहद अविश्वसनीय है। इस प्रयोग को आजमाएं।

सेल में कुछ टाइप करें 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अंतिम सेल खोजने के लिए।


एक कॉलम में अंतिम पंक्ति खोजें

कर्नल ई में अंतिम पंक्ति को खोजने के लिए इसका उपयोग करें

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रिटर्न । इसी प्रकार देता है और क्रमश:।655361048576Columns.Count25616384

उपरोक्त तथ्य कि Excel 2007+ में 1048576पंक्तियाँ भी इस तथ्य पर जोर देती हैं कि हमें हमेशा वैरिएबल की घोषणा करनी चाहिए जो पंक्ति मान को रखेगा Long, Integerअन्यथा आपको एक Overflowत्रुटि मिलेगी ।

ध्यान दें कि यह दृष्टिकोण किसी भी छिपी हुई पंक्तियों को छोड़ देगा। पर वापस देख रहे हैं स्तंभ एक के लिए ऊपर मेरी स्क्रीनशॉट , अगर पंक्ति 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

तालिका में अंतिम पंक्ति खोजें (सूची सूची)

एक ही सिद्धांत लागू होते हैं, उदाहरण के लिए एक तालिका के तीसरे कॉलम में अंतिम पंक्ति प्राप्त करने के लिए:

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
@ फ़न: सेल A5 में कुछ टाइप करें। अब जब आप ऊपर दी गई किसी भी विधि के साथ अंतिम पंक्ति की गणना करते हैं, तो यह आपको 5 देगा। अब सेल A10 लाल को रंग दें। यदि आप अब उपरोक्त कोड में से किसी का उपयोग करते हैं, तो आपको अभी भी 5 मिलेगा। यदि आप उपयोग Usedrange.Rows.Countकरते हैं तो आपको क्या मिलेगा? यह 5 नहीं होगा। अंतिम पंक्ति को खोजने के लिए गैर-व्यवस्थित बहुत अविश्वसनीय है।
सिद्धार्थ राउत

6
कृपया ध्यान दें कि .Find दुर्भाग्य से फाइंड डायलॉग में उपयोगकर्ता की सेटिंग्स को गड़बड़ कर देता है - अर्थात एक्सेल में केवल डायलॉग के लिए सेटिंग्स का 1 सेट होता है, और आप .ind का उपयोग करके उन्हें बदल देते हैं। एक अन्य चाल अभी भी UseRange का उपयोग करना है, लेकिन इसे एक पूर्ण (लेकिन अविश्वसनीय) के रूप में उपयोग करें जिससे आप सही अधिकतम निर्धारित करते हैं।
कार्ल कोलीजन

4
@CarlColijn: मैं इसे गड़बड़ नहीं कहूंगा। :) एक्सेल बस remembersआखिरी सेटिंग। यहां तक ​​कि जब आप मैन्युअल रूप से एक करते हैं Find, तो यह आखिरी सेटिंग को याद करता है जो वास्तव में एक वरदान है अगर कोई इस "तथ्य" को जानता है
सिद्धार्थ राउत

3
@ कीथपार्क: कृपया आगे बढ़ें :) ज्ञान का केवल एक अर्थ है यदि यह फैला हुआ है :)
सिद्धार्थ राउत

9
मुझे लगता है कि आपका विवरण UsedRange( यह अंतिम सेल जो डेटा है को खोजने के लिए बहुत अविश्वसनीय है ) भ्रामक है। UsedRangeबस उस उद्देश्य के लिए इरादा नहीं है, भले ही कुछ मामलों में यह सही परिणाम दे सकता है। मुझे लगता है कि प्रस्तावित प्रयोग भ्रम में जोड़ता है। UsedRange($ A $ 1: $ A $ 8) के साथ प्राप्त परिणाम पहले डेटा को हटाने के लिए दर्ज करने पर निर्भर नहीं करता है। डेटा को डिलीट किए बिना भी दाईं ओर का आंकड़ा समान रहेगा। कृपया मेरा उत्तर देखें।
sancho.s ReinstateMonicaCellio 13

34

नोट: यह उत्तर इस टिप्पणी से प्रेरित था । UsedRangeऊपर दिए गए उत्तर में उल्लिखित के उद्देश्य से भिन्न है।

अंतिम प्रयुक्त सेल को खोजने के सही तरीके के रूप में, किसी को पहले यह तय करना होगा कि क्या उपयोग किया जाता है , और फिर एक उपयुक्त विधि का चयन करें । मैं कम से कम तीन अर्थ लगाता हूं:

  1. प्रयुक्त = गैर-रिक्त, अर्थात, डेटा होने पर ।

  2. प्रयुक्त = "... उपयोग में, उस अनुभाग का अर्थ है जिसमें डेटा या स्वरूपण शामिल है ।" आधिकारिक दस्तावेज के अनुसार , यह एक्सेल द्वारा बचत के समय उपयोग की जाने वाली कसौटी है। इस आधिकारिक दस्तावेज को भी देखें । यदि किसी को इसके बारे में पता नहीं है, तो मानदंड अप्रत्याशित परिणाम उत्पन्न कर सकता है, लेकिन यह विशिष्ट क्षेत्रों को उजागर करने या प्रिंट करने के लिए जानबूझकर (कम अक्सर, निश्चित रूप से), उदाहरण के लिए, जिसका अंततः कोई डेटा नहीं हो सकता है। और, ज़ाहिर है, किसी कार्यपुस्तिका को सहेजते समय, किसी के काम का एक हिस्सा खोने पर उपयोग करने के लिए यह एक सीमा के मानदंड के रूप में वांछनीय है।

  3. प्रयुक्त = "... उपयोग में, उस अनुभाग का अर्थ है जिसमें डेटा या स्वरूपण शामिल है " या सशर्त स्वरूपण। 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या नहीं लगाया जाता है । चित्र में, अंतिम सेल B3 है, क्योंकि स्वरूपण स्पष्ट रूप से इसे लागू किया गया था। कक्ष B6: D7 में सशर्त स्वरूपण नियम से प्राप्त एक प्रारूप है, और इसके द्वारा भी इसका पता नहीं लगाया गया हैCtrlEndUsedRange । इसके लिए लेखांकन के लिए कुछ VBA प्रोग्रामिंग की आवश्यकता होगी।

यहां छवि विवरण दर्ज करें


अपने विशिष्ट प्रश्न के रूप में : इसके पीछे क्या कारण है?

आपका कोड आपकी श्रेणी E4 में पहले सेल का उपयोग करता है: E48 एक trampoline के लिए, के लिए नीचे कूदने केEnd(xlDown)

"त्रुटिपूर्ण" आउटपुट प्राप्त होगा यदि आपकी श्रेणी में कोई गैर-रिक्त कक्ष नहीं हैं जो शायद पहले की तुलना में हैं। फिर, आप अंधेरे में छलांग लगा रहे हैं , यानी, वर्कशीट नीचे (आपको खाली और खाली स्ट्रिंग के बीच अंतर को नोट करना चाहिए )।

ध्यान दें कि:

  1. यदि आपकी सीमा में गैर-सन्निहित गैर-रिक्त कोशिकाएं हैं, तो यह गलत परिणाम भी देगा।

  2. यदि केवल एक गैर-रिक्त कक्ष है, लेकिन यह पहला नहीं है, तो आपका कोड अभी भी आपको सही परिणाम देगा।


3
मैं इस बात से सहमत हूं कि पहले यह तय करना होगा कि क्या उपयोग किया जाता है । मुझे कम से कम 6 अर्थ दिखाई देते हैं। सेल में: 1) डेटा, यानी, एक सूत्र, संभवतः रिक्त मान के परिणामस्वरूप; 2) एक मूल्य, यानी, एक गैर-रिक्त सूत्र या निरंतर; 3) स्वरूपण; 4) सशर्त स्वरूपण; 5) सेल को ओवरलैप करते हुए एक आकृति (टिप्पणी सहित); 6) एक तालिका (सूची वस्तु) में भागीदारी। आप किस संयोजन के लिए परीक्षण करना चाहते हैं? कुछ (जैसे टेबल्स) के लिए परीक्षण करना अधिक कठिन हो सकता है, और कुछ दुर्लभ हो सकता है (जैसे कि डेटा रेंज के बाहर एक आकृति), लेकिन अन्य स्थिति के आधार पर भिन्न हो सकते हैं (उदाहरण के लिए, रिक्त मान वाले सूत्र)।
GlennFromIowa

20

मैंने अंतिम पंक्ति, कॉलम और सेल का निर्धारण करने के लिए यह एक-स्टॉप फ़ंक्शन बनाया , यह डेटा के लिए हो, स्वरूपित (समूहीकृत / टिप्पणी / छिपी) कोशिकाओं या सशर्त स्वरूपण के लिए

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 वर्कबुक्स में कुछ स्थितियों में ओवरफ्लो त्रुटियों को प्राप्त करेंगे

यह मेरा एनकैप्सुलेटेड फंक्शन है जिसे मैं विभिन्न कोड उपयोगों में छोड़ता हूं।

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

मैं सिद्दार्थ राउत द्वारा दिए गए जवाब में यह कहना चाहूंगा कि काउंटा कॉल को एक पंक्ति संख्या के बजाय फाइंड रेंज रेंज लौटाकर फाइंड किया जा सकता है, और फिर लौटी हुई रेंज ऑब्जेक्ट को यह देखने के लिए देखें कि क्या यह कुछ भी नहीं है (रिक्त वर्कशीट) ।

इसके अलावा, मैं किसी भी LastRow प्रक्रिया के अपने संस्करण को खाली वर्कशीट के लिए एक शून्य लौटाऊंगा, तब मैं जान सकता हूं कि यह रिक्त है।


8

मुझे आश्चर्य है कि किसी ने भी इसका उल्लेख नहीं किया है, लेकिन अंतिम उपयोग किए जाने वाले सेल को प्राप्त करने का सबसे आसान तरीका है:

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

यह अनिवार्य रूप से उसी सेल को लौटाता है जो सेल चुनने के बाद आपको Ctrl+ मिलता है ।EndA1

सावधानी का एक शब्द: एक्सेल सबसे निचले-दाएं सेल का ट्रैक रखता है जो कभी एक वर्कशीट में इस्तेमाल किया गया था। तो अगर उदाहरण के लिए आप में कुछ दर्ज बी 3 और में कुछ और H8 और फिर बाद में की सामग्री हटा दें H8 दबाने, Ctrl+ Endअभी भी के लिए ले जाएगा H8 सेल। उपरोक्त फ़ंक्शन का व्यवहार समान होगा।


2
Last Cellएक्सेल में कभी-कभी एक खाली सेल (से Used Range) को संदर्भित करता है जो इससे अलग है Last Used Cell;)।
shA.t

1
ओपी को केवल अंतिम पंक्ति की आवश्यकता है लेकिन आप सही हैं, अंतिम सेल एच 5 होना चाहिए ; लेकिन आप A5 में मान को हटाने के बाद अपने फ़ंक्शन का परीक्षण कर सकते हैं आप देखेंगे कि अंतिम सेल वह खाली सेल है, और मुझे लगता है कि आपके कोड को कुछ संपादन चाहिए जैसे कि Cells(1,1).Select()यह अमान्य है ActiveSheet.Cells(1,1).Select; VBA में भी इसका उपयोग करने की अनुशंसा नहीं की गई है Select;)।
shA.t

5
यह एक्सेल VBA के लिए दो कार्डिनल नियमों को तोड़ता है: Select का उपयोग न करें! और यह मत मानो कि आप जो चादर चाहते हैं वह सक्रिय है।
राहेल हेटिंगर ने

1
यह एक पुराना उत्तर है, लेकिन यह याद आ रहा है Set
बिगबेन

8

चूंकि मूल प्रश्न अंतिम सेल को खोजने में समस्याओं के बारे में है , इस उत्तर में मैं उन विभिन्न तरीकों को सूचीबद्ध करूंगा जिनसे आप अप्रत्याशित परिणाम प्राप्त कर सकते हैं ; देख मेरा उत्तर करने के लिए "मैं अंतिम पंक्ति है कि एक मैक्रो के साथ एक्सेल शीट में डेटा शामिल मिल सकती है?"इसे हल करने के लिए मेरे ले के लिए।

मैं sancho.s द्वारा उत्तर पर विस्तार करके शुरू करूँगा और GlennFromIowa द्वारा टिप्पणी शुरू करूँगा , और भी अधिक विवरण जोड़कर:

[...] किसी को सबसे पहले यह तय करना होगा कि क्या उपयोग किया जाता है। मुझे कम से कम 6 अर्थ दिखाई देते हैं। सेल में है:

  • 1) डेटा, यानी, एक सूत्र, संभवतः रिक्त मान के परिणामस्वरूप;
  • 2) एक मूल्य, यानी, एक गैर-रिक्त सूत्र या निरंतर;
  • 3) स्वरूपण;
  • 4) सशर्त स्वरूपण;
  • 5) सेल को ओवरलैप करते हुए एक आकृति (टिप्पणी सहित);
  • 6) एक तालिका (सूची वस्तु) में भागीदारी।

आप किस संयोजन के लिए परीक्षण करना चाहते हैं? कुछ (जैसे टेबल्स) के लिए परीक्षण करना अधिक कठिन हो सकता है, और कुछ दुर्लभ हो सकता है (जैसे कि डेटा रेंज के बाहर एक आकृति), लेकिन अन्य स्थिति के आधार पर भिन्न हो सकते हैं (उदाहरण के लिए, रिक्त मान वाले सूत्र)।

अन्य बातें जिन पर आप विचार करना चाहते हैं:

  • ए) क्या छिपी हुई पंक्तियाँ (जैसे ऑटोफ़िल्टर), रिक्त कोशिकाएँ हो सकती हैं या रिक्त पंक्तियाँ हो सकती हैं?
  • बी) किस तरह का प्रदर्शन स्वीकार्य है?
  • C) क्या VBA मैक्रो किसी भी तरह से वर्कबुक या एप्लिकेशन सेटिंग को प्रभावित कर सकता है?

इसे ध्यान में रखते हुए, आइए देखें कि "अंतिम सेल" प्राप्त करने के सामान्य तरीके अप्रत्याशित परिणाम कैसे दे सकते हैं:

  • .End(xlDown)प्रश्न का कोड सबसे आसानी से टूट जाएगा (उदाहरण के लिए एकल गैर-रिक्त कक्ष के साथ या जब बीच में रिक्त कोशिकाएँ होती हैं ) तो सिद्धार्थ राउत द्वारा उत्तर में बताए गए कारणों के लिए ( "xlDown के लिए खोज समान रूप से अविश्वसनीय है।" )
  • Countआईएनजी ( CountAया Cells*.Count) या के आधार पर कोई समाधान.CurrentRegion रिक्त कोशिकाओं या पंक्तियों की उपस्थिति में भी टूट जाएगा
  • एक .End(xlUp)कॉलम के अंत से पीछे की ओर खोज करने से संबंधित एक समाधान , जैसे CTRL + UP, डेटा की तलाश करता है (रिक्त मान पैदा करने वाले सूत्र "डेटा" माना जाता है) दृश्य माने जाते हैं (इसलिए इसे ऑटोफ़िल्टर के साथ उपयोग करने से सक्षम हो सकता है गलत परिणाम उत्पन्न हो सकते हैं) )।

    आपको मानक नुकसान से बचने के लिए ध्यान रखना होगा (विवरण के लिए मैं फिर से यहां सिद्धार्थ राउत के उत्तर का उल्लेख करूंगा , "अंतिम कॉलम में एक पंक्ति में खोजें" ), जैसे कि अंतिम पंक्ति को हार्ड-कोडिंग करना ( Range("A65536").End(xlUp)) पर भरोसा करने के बजाय sht.Rows.Count

  • .SpecialCells(xlLastCell)CTRL + END के बराबर है, "उपयोग की गई रेंज" के निचले-सबसे और दाएं-सबसे अधिक सेल को लौटाता है, इसलिए सभी कैविटीज़ जो "उपयोग की गई रेंज" पर निर्भर होते हैं, इस पद्धति पर भी लागू होते हैं। इसके अलावा, "उपयोग की गई सीमा" केवल कार्यपुस्तिका को सहेजते समय और एक्सेस करते समय रीसेट की जाती है worksheet.UsedRange, इसलिए xlLastCellबिना किसी संशोधन के बासी परिणाम प्रस्तुत कर सकते हैं (जैसे कुछ पंक्तियों को हटाए जाने के बाद)। डॉटनेट द्वारा पास का उत्तर देखें ।
  • sht.UsedRange( जवाब में विस्तार से वर्णन sancho.s द्वारा यहां दिया गया है) दोनों डेटा और स्वरूपण (हालांकि सशर्त स्वरूपण नहीं ) पर विचार करता है करता है वर्कशीट की "उपयोग की गई सीमा" को रीसेट करता है , जो आप चाहते हैं या नहीं हो सकता है।

    ध्यान दें कि whichis का उपयोग करने के लिए एक सामान्य गलती .UsedRange.Rows.Count, जो प्रयुक्त रेंज में पंक्तियों की संख्या लौटाती है , न कि अंतिम पंक्ति संख्या (वे अलग होंगी यदि पहली कुछ पंक्तियां रिक्त हैं), विवरण के लिए newguy का उत्तर देखें कि मैं कैसे पा सकता हूं अंतिम पंक्ति जिसमें मैक्रो के साथ एक्सेल शीट में डेटा है?

  • .Findआपको किसी भी कॉलम में किसी भी डेटा (फॉर्मूलों सहित) या गैर-रिक्त मान के साथ अंतिम पंक्ति खोजने की अनुमति देता है । आप यह चुन सकते हैं कि आप फ़ार्मुलों या मूल्यों में रुचि रखते हैं, लेकिन पकड़ यह है कि यह एक्सेल के फाइंड डायलॉग be में चूक को रीसेट करता है , जो आपके उपयोगकर्ताओं के लिए अत्यधिक भ्रमित हो सकता है। इसे भी सावधानी से उपयोग करने की आवश्यकता है, यहां सिद्धार्थ राउत द्वारा उत्तर देखें (अनुभाग "शीट में अंतिम पंक्ति खोजें" )
  • अधिक स्पष्ट समाधान जो व्यक्ति Cellsको एक लूप में जांचते हैं, वे आमतौर पर एक एक्सेल फ़ंक्शन (हालांकि अभी भी प्रदर्शन कर सकते हैं) का उपयोग करने की तुलना में धीमे होते हैं, लेकिन आपको वही निर्दिष्ट करते हैं जो आप खोजना चाहते हैं। दिए गए कॉलम में डेटा के साथ अंतिम सेल को खोजने के लिए और VBA सरणियों के आधार पर मेरा समाधान देखें UsedRange- यह छिपी हुई पंक्तियों, फिल्टर, ब्लैंक को हैंडल करता है, फाइंड डिफॉल्ट को संशोधित नहीं करता है और यह काफी अच्छा है।

आप जो भी समाधान निकालें, सावधान रहें

  • पंक्ति संख्याओं को संग्रहीत करने के लिए उपयोग 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

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

यहाँ, A65536कॉलम A में आखिरी सेल है इस कोड का परीक्षण एक्सेल 2003 पर किया गया था।


क्या आप बता सकते हैं कि आपका कोड इस पुराने प्रश्न का उत्तर कैसे देता है?
फावड़ा

1
हालांकि यह उत्तर संभवतः सही और उपयोगी है, यह पसंद किया जाता है यदि आप इसे समझाने के साथ कुछ स्पष्टीकरण भी शामिल करते हैं कि यह समस्या को हल करने में कैसे मदद करता है। यह भविष्य में विशेष रूप से उपयोगी हो जाता है, अगर कोई परिवर्तन (संभवतः असंबंधित) होता है जो इसे काम करना बंद कर देता है और उपयोगकर्ताओं को यह समझने की आवश्यकता है कि एक बार कैसे काम किया।
केविन ब्राउन

2

मैं नकल के लिए एक रास्ता के लिए देख रहा था CTRL+ Shift+End , इसलिए DotNet समाधान महान है, मेरी 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

1

यहाँ मेरे दो सेंट हैं।

IMHO डेटा को छुपाने के साथ एक छिपी हुई पंक्ति के जोखिम को एक स्टॉप उत्तरxlUp माना जाना महत्वपूर्ण है । मैं मानता हूं कि यह सरल है और उस समय के अधिकांश काम करेगा, लेकिन यह बिना किसी चेतावनी के अंतिम पंक्ति को समझने का जोखिम प्रस्तुत करता है। यह CATASTROPHIC का उत्पादन कर सकता है जो ढेर Overlow पर कूद गया और इस मूल्य पर कब्जा करने की "यकीन है कि जिस तरह से" करने के लिए देख रहा था किसी के लिए कुछ poinit में परिणाम है।

Findविधि निर्दोष है और मैं के रूप में एक यह की सहमति दे देगा एक बंद करो जवाब । हालांकि परिवर्तन की खामीFind सेटिंग्स कष्टप्रद हो सकता है, खासकर अगर यह यूडीएफ का हिस्सा हो।

पोस्ट किए गए अन्य उत्तर ठीक हैं, हालांकि जटिलता थोड़ी अधिक हो जाती है। इस प्रकार यहां विश्वसनीयता, न्यूनतम जटिलता और उपयोग न करने का संतुलन खोजने का मेरा प्रयास है 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सेटिंग्स को संशोधित नहीं करता है
  • डायनेमिक यदि यूडीएफ के रूप में उपयोग किया जाता है तो पूरे कॉलम को चुना जाता है।

यह बुरा क्यों है:

  • डेटा के बहुत बड़े सेटों के साथ और निर्दिष्ट कॉलमों में उपयोग की गई रेंज और अंतिम पंक्ति के बीच बड़े पैमाने पर अंतर के साथ, यह दुर्लभ मामलों में धीमी गति से प्रदर्शन करेगा।

हालांकि, मुझे लगता है कि वन-स्टॉप-सॉल्यूशन जिसमें 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

ओपी के मामले में, यह कॉलम में अंतिम पंक्ति प्राप्त करने का तरीका है E:

Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)

अंतिम पंक्ति, डेटा के साथ खाली पंक्तियों की गिनती:

यहां हम जाने-माने एक्सेल फ़ार्मुलों का उपयोग कर सकते हैं , जो हमें VBA में शामिल किए बिना एक्सेल में एक वर्कशीट की अंतिम पंक्ति देते हैं -=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)

VBA में इसे रखने के लिए और एक्सेल में कुछ भी नहीं लिखने के लिए, बाद के कार्यों के लिए मापदंडों का उपयोग करते हुए, ऐसा कुछ ध्यान में रखा जा सकता है:

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

@PGSystemTester - हां, लेकिन मेरी समझ में, जब मैं इसे प्रोग्राम करता हूं, अगर यह छिपा होता है तो यह अंतिम कॉलम / पंक्ति नहीं है जिसकी जरूरत है।
२० पर Vityata

खुशी है कि आप के लिए काम करता है। मुझे संदेह है कि आपकी स्थिति एक विशिष्ट उपयोग-मामला नहीं है। अधिक बार जब मैं उन ग्राहकों के साथ काम करता हूं जिन्हें अंतिम पंक्ति की आवश्यकता होती है, तो वे डेटा के साथ निम्नतम सेल के लिए खोज कर रहे हैं, न कि डेटा के साथ सबसे कम दिखाई देने वाली सेल। वैसे भी ... खुशी है कि यह काम करता है। 👍
PGSystemTester

@PGSystemTester - मुझे आपकी बात मिल गई, लेकिन संरचना का ख्याल रखना और अदृश्य कोशिकाओं को आकर्षण की तरह काम नहीं करने देना।
वित्रता

@PGSystemTester - हाँ, यदि कार्य संभवतः खाली पंक्तियों की अनुमति देता है, तो मैं शायद EVAL()और प्रसिद्ध एक्सेल सूत्र का उपयोग करूंगा । हालाँकि लोग सोच सकते हैं कि Eval()यह बुराई है और यह एक और दिलचस्प कहानी है, जिस पर लिखना है ...
Vityata

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.