excel إظهار - خطأ في العثور على آخر خلية مستعملة في VBA





الأعمدة والصفوف (10)


نظرًا لأن السؤال الأصلي يتعلق بمشاكل العثور على الخلية الأخيرة ، فسوف أسرد في هذه الإجابة الطرق المختلفة التي يمكنك من خلالها الحصول على نتائج غير متوقعة ؛ راجع إجابتي "كيف يمكنني العثور على الصف الأخير الذي يحتوي على بيانات في ورقة Excel باستخدام ماكرو؟" لاتخاذ لي على حل هذا.

سأبدأ بالتوسع في الإجابة من خلال sancho.s والتعليق من GlennFromIowa ، بإضافة المزيد من التفاصيل:

[...] على المرء أن يقرر أولاً ما يُعتبر مستخدمًا. أرى ما لا يقل عن 6 معاني. الخلية لديها:

  • 1) البيانات ، أي صيغة ، ربما ينتج عنها قيمة فارغة ؛
  • 2) قيمة ، أي صيغة غير ثابتة أو ثابتة ؛
  • 3) التنسيق
  • 4) التنسيق الشرطي ؛
  • 5) شكل (بما في ذلك التعليق) تداخل الخلية ؛
  • 6) المشاركة في جدول (قائمة الكائن).

ما هي التركيبة التي ترغب في اختبارها؟ قد يكون اختبار بعض (مثل الجداول) أكثر صعوبة ، وبعضها قد يكون نادرًا (مثل شكل خارج نطاق البيانات) ، ولكن قد يختلف البعض الآخر وفقًا للحالة (على سبيل المثال ، الصيغ ذات القيم الفارغة).

أشياء أخرى قد ترغب في وضعها في الاعتبار:

  • أ) هل يمكن أن توجد صفوف مخفية (مثل autofilter) أو خلايا فارغة أو صفوف فارغة؟
  • ب) ما هو نوع الأداء المقبول؟
  • C) هل يؤثر الماكرو VBA على المصنف أو إعدادات التطبيق بأي طريقة؟

مع أخذ ذلك في الاعتبار ، لنرى كيف يمكن للطرق الشائعة للحصول على "الخلية الأخيرة" أن تؤدي إلى نتائج غير متوقعة:

  • .End(xlDown) رمز .End(xlDown) من السؤال بسهولة (على سبيل المثال مع خلية مفردة غير فارغة أو عندما تكون هناك خلايا فارغة بينهما ) للأسباب الموضحة في الإجابة عن طريق Siddharth Rout هنا (البحث عن "xlDown بالتساوي لا يمكن الاعتماد عليها. " ) 👎
  • أي حل يعتمد على Count ing ( CountA أو Cells*.Count ) أو .CurrentRegion سوف يكسر أيضًا وجود الخلايا الفارغة أو الصفوف 👎
  • الحل الذي يتضمن .End(xlUp) للبحث عن الخلف من نهاية العمود ، سيبحث عن البيانات (مثل الصيغ التي تنتج قيمة فارغة "data") في الصفوف المرئية (لذا استخدمها مع تمكين التصفية التلقائية) قد تنتج نتائج غير صحيحة ⚠️).

    عليك أن تتوخى الحذر لتفادي العثرات القياسية (لمزيد من التفاصيل سأشير مرة أخرى إلى الإجابة عن طريق Siddharth Rout هنا ، ابحث عن قسم "البحث عن صف في العمود" ) ، مثل الترميز الثابت للصف الأخير ( Range("A65536").End(xlUp) ) بدلاً من الاعتماد على sht.Rows.Count .

  • .SpecialCells(xlLastCell) يساوي CTRL + END ، .SpecialCells(xlLastCell) الخلية الأكثر إلى أقصى اليمين والأيسر من "النطاق المستخدم" ، لذلك تنطبق جميع التحذيرات التي تنطبق على الاعتماد على "النطاق المستخدم" ، على هذه الطريقة أيضًا. بالإضافة إلى ذلك ، تتم إعادة تعيين "النطاق المستخدم" فقط عند حفظ المصنف وعند الوصول إلى worksheet.UsedRange . xlLastCell ، لذلك قد ينتج عن xlLastCell النتائج التي لا معنى لها مع التعديلات غير المحفوظة (على سبيل المثال بعد حذف بعض الصفوف). انظر الإجابة القريبة من dotNET .
  • sht.UsedRange (الموضح بالتفصيل في الإجابة sancho.s هنا) كل من البيانات والتنسيق (على الرغم من عدم التنسيق الشرطي) ويعيد تعيين "النطاق المستخدم" لورقة العمل ، والذي قد يكون أو لا يكون ما تريده.

    لاحظ أن هناك خطأً شائعًا في الاستخدام .UsedRange.Rows.Count ⚠️ ، والذي يقوم بإرجاع عدد الصفوف في النطاق المستخدم ، وليس رقم الصف الأخير (سيكون مختلفًا إذا كانت الصفوف القليلة الأولى فارغة) ، للحصول على التفاصيل انظر إجابة newguy على كيف يمكنني العثور على آخر صف يحتوي على بيانات في ورقة Excel باستخدام ماكرو؟

  • يتيح لك .Find العثور على الصف الأخير مع أي بيانات (بما في ذلك الصيغ) أو قيمة غير فارغة في أي عمود . يمكنك اختيار ما إذا كنت مهتمًا بالصيغ أو القيم ، لكن المصيد هو أنه يعيد تعيين الإعدادات الافتراضية في مربع الحوار "بحث" في Excel ، مما قد يسبب إرباكًا كبيرًا للمستخدمين. يجب أيضًا استخدامه بعناية ، راجع الإجابة عن طريق Siddharth Rout هنا (قسم "البحث عن الصف الأخير في ورقة" )
  • عادةً ما تكون الحلول الأكثر وضوحًا التي تتحقق من Cells الفردية في حلقة أبطأ من إعادة استخدام وظيفة Excel (على الرغم من أنه لا يزال من الممكن أن يكون الأداء) ، ولكن تسمح لك بتحديد ما تريد العثور عليه بالضبط. انظر حل قائم على أساس صفيف UsedRange و VBA للعثور على آخر خلية تحتوي على بيانات في العمود المحدد - فهي تتعامل مع الصفوف المخفية ، والفلاتر ، والفراغات ، ولا تعدل الإعدادات الافتراضية للإيجاد ، وهي ذات أداء جيد.

أيا كان الحل الذي تختاره ، كن حذرا

  • استخدام Long بدلاً من Integer لتخزين أرقام الصف (لتجنب الحصول على Overflow بأكثر من 65k rows) و
  • لتقوم دائمًا بتحديد ورقة العمل التي تعمل بها (مثل Dim ws As Worksheet ... ws.Range(...) بدلاً من Range(...) )
  • عند استخدام .Value (وهو Variant ) تجنب التقليب الضمني مثل .Value <> "" لأنها ستفشل إذا كانت الخلية تحتوي على قيمة خطأ.

عندما أريد العثور على آخر قيمة خلية مستعملة ، يمكنني استخدام:

Dim LastRow As Long

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

Debug.Print LastRow

أتلقى الإخراج الخطأ عندما أضع عنصرًا واحدًا في خلية. ولكن عندما أضع أكثر من قيمة في الخلية ، يكون الإخراج صحيحًا. ما هو السبب وراء هذا؟




ملاحظة : أعتزم جعل هذه "نقطة توقف واحدة" حيث يمكنك استخدام الطريقة 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 ثم الضغط على مفتاح الإنهاء ثم الضغط على مفتاح السهم لأسفل . سيعطيك هذا أيضًا نتائج غير موثوقة إذا كانت هناك خلايا فارغة في نطاق.

CountA غير موثوق أيضًا لأنه سيعطيك نتيجة غير صحيحة إذا كانت هناك خلايا فارغة بينهما.

وبالتالي يجب على المرء تجنب استخدام UsedRange ، xlDown و CountA للعثور على الخلية الأخيرة.

البحث عن الصف الأخير في العمود

للعثور على الصف الأخير في Col E ، استخدم هذا

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

إذا لاحظت أن لدينا . قبل Rows.Count . كثيرا ما نختار تجاهل ذلك. انظر THIS السؤال عن الخطأ المحتمل الذي قد تحصل عليه. أنا دائما تقديم المشورة باستخدام . قبل Rows.Count و Rows.Count . هذا السؤال هو سيناريو كلاسيكي حيث ستفشل التعليمة البرمجية بسبب إرجاع Rows.Count 65536 لـ Excel 2003 والإصدارات السابقة و 1048576 لبرنامج Excel 2007 والإصدارات الأحدث. وبالمثل ، Columns.Count إرجاع 256 و 16384 ، على التوالي.

الحقيقة أعلاه أن Excel 2007+ يحتوي على صفوف 1048576 كما يؤكد على حقيقة أنه يجب علينا دائماً تعريف المتغير الذي سيحمل قيمة الصف كما Long بدلاً من Integer آخر سوف تحصل على خطأ Overflow .

البحث عن الصف الأخير في ورقة

للعثور على الصف الأخير 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



لقد قمت بإنشاء هذه الدالة ذات التوقف الواحد لتحديد الصف الأخير ، والعمود والخلية ، سواء كان ذلك للبيانات ، أو التنسيق (المجمَّع / المُعلَّق / الخفي) أو التنسيق الشرطي .

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



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



أتساءل أن لا أحد قد ذكر ذلك ، ولكن أسهل طريقة للحصول على آخر خلية مستعملة هي:

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

يؤدي هذا بشكل أساسي إلى إرجاع الخلية نفسها التي تحصل عليها عن طريق Ctrl + End بعد تحديد الخلية A1 .

كلمة تحذير: يقوم برنامج Excel بتتبع الخلية الموجودة في أقصى الجانب الأيمن والتي تم استخدامها في ورقة العمل. لذلك إذا قمت مثلاً بإدخال شيء ما في B3 وشيء آخر في H8 ثم قمت لاحقًا بحذف محتويات H8 ، فسيظل ضغط Ctrl + End يأخذك إلى خلية H8 . الوظيفة المذكورة أعلاه سيكون لها نفس السلوك.




فيما يتعلق بالطريقة الصحيحة للعثور على آخر خلية مستعملة ، يتعين على المرء أولاً أن يقرر ما يعتبر مستخدمًا ، ثم يختار طريقة مناسبة . أتصور معنىين على الأقل:

  1. استخدام = غير فارغ ، أي ، وجود بيانات .

  2. تستخدم = "... قيد الاستخدام ، وهذا يعني القسم الذي يحتوي على البيانات أو التنسيق ." هذا هو المعيار المستخدم بواسطة Excel في وقت الحفظ . انظر أيضا this . عادة ما ينتج هذا المعيار نتائج غير متوقعة ، ولكن قد يتم استغلاله عن قصد (أقل شيوعًا ، بالتأكيد) ، على سبيل المثال ، لتسليط الضوء على مناطق معينة أو طباعتها ، والتي قد لا تحتوي في النهاية على بيانات. وبطبيعة الحال ، فمن المستحسن كمعيار للنطاق لاستخدامها عند حفظ مصنف.

تعتمد كيفية العثور على الخلية الأخيرة المستخدمة على ما تريد (المعيار الخاص بك) .

بالنسبة إلى المعيار 1 ، أقترح قراءة هذه الإجابة . لاحظ أنه يتم الاستشهاد بـ UsedRange أنه غير موثوق به. أعتقد أن هذا مضللة (أي "غير عادلة" إلى UsedRange ) ، كما لا يعني ببساطة UsedRange للإبلاغ عن آخر خلية تحتوي على بيانات. لذلك لا ينبغي أن تستخدم في هذه الحالة ، كما هو مبين في هذا الجواب. انظر أيضا هذا التعليق .

بالنسبة للمعيار 2 ، يعد UsedRange الخيار الأكثر موثوقية ، مقارنة بالخيارات الأخرى المصممة لهذا الاستخدام أيضًا. حتى أنه يجعل من غير الضروري حفظ مصنف للتأكد من أن يتم تحديث الخلية الأخيرة. سينتقل Ctrl + End إلى خلية غير صحيحة قبل الحفظ ("لم تتم إعادة تعيين آخر خلية حتى تحفظ ورقة العمل" ، من http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10%29.aspx إنها إشارة قديمة ، ولكن في هذا الصدد صالحة).

هناك مشكلة أخرى:
لا يضع المعيار 2 حسابًا على التنسيق الشرطي. واحد قد يكون الخلايا المنسقة ، استنادا إلى الصيغ ، والتي لم يتم الكشف عنها من قبل UsedRange أو Ctrl + End . في الشكل ، الخلية الأخيرة هي B3 ، حيث تم تطبيق التنسيق بشكل صريح عليها. الخلايا B6: D7 يكون تنسيق مشتق من قاعدة تنسيق شرطي ، ولا يتم الكشف عن هذا حتى بواسطة UsedRange .

فيما يتعلق بسؤالك المحدد : ما السبب وراء هذا؟

تستخدم التعليمات البرمجية الخاصة بك الخلية الأولى في النطاق الخاص بك E4: E48 كـ trampoline ، للقفز لأسفل مع End(xlDown) .

سيحصل الإخراج "الخاطئ" على ما إذا لم تكن هناك خلايا غير فارغة في نطاقك بخلاف أولها. ثم ، أنت قفز في الظلام ، أي أسفل ورقة العمل (يجب أن تلاحظ الفرق بين السلسلة الفارغة والفارغة !).

لاحظ أن:

  1. إذا كان نطاقك يحتوي على خلايا غير متجاورة غير متجاورة ، فسيعطي أيضًا نتيجة خاطئة.

  2. إذا لم يكن هناك سوى خلية واحدة غير فارغة ، ولكنها ليست الخلية الأولى ، فسيظل رمزك يوفر لك النتيجة الصحيحة.




ومع ذلك ، يسعى هذا السؤال للعثور على الصف الأخير باستخدام 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.




كنت أبحث عن طريقة لتقليد 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



sub last_filled_cell()
msgbox range("a65536").end(xlup).row
end sub

"هنا a65536 هي الخلية الأخيرة في العمود تم اختبار هذا الرمز على excel sti72003" 200

وإذا كنت تستخدم "a1،048،576"

كود بلدي هو فقط للمبتدئين لفهم مفاهيم ما نهاية (xlup) وغيرها من الأوامر ذات الصلة يمكن القيام به




وأعتقد أن الطريقة الأكثر أناقة مما قدمه @D_Bester هو استخدام خيار find() بدون حلقات عبر مجموعة من الخلايا:

Sub test()
    Dim cl As Range, i&
    Set cl = Range("E1:E" & Cells(Rows.Count, "E").End(xlUp).Row)
    i = cl.Find("*", , xlValues, , xlByRows, xlPrevious).Row
    Debug.Print "Last row with data: " & i
End Sub

اختبار

أيضا، أكثر نسخة أقصر من التعليمات البرمجية التي تم توفيرها أعلاه هي:

Sub test2()
    Debug.Print [E:E].Find("*", , xlValues, , xlByRows, xlPrevious).Row
End Sub




excel vba excel-vba excel-formula