0

I want to stop my loop if the current selection is empty. I have tried the following:

If (IsEmpty(Sheets("Sheet3").ActiveCell)) Then Exit Do

If Sheets("Sheet3").Selection.Value = "" Then Exit Do ;tried to replace "" with Empty and Nothing but didn't work either

If Sheets("Sheet3").Activecell.Value is Empty Then Exit Do

If Sheets("Sheet3").Selection is blank Then Exit Do

The issue is if I don't stop the loop somehow it will carry on forever.

I was hoping somebody can help me here.

EDIT :

This is my code:

Public Sub CopyFilteredData()

  Do
    Sheets("Sheet4").Select
    ActiveSheet.Range("$A$1:$R$25239") _
      .AutoFilter _
        Field:=5, _
        Criteria1:=Sheets("Sheet3").Application.Selection.Value
    Range("A1").Select
    ActiveCell.CurrentRegion.Select
    Selection.Copy
    Sheets("Sheet5").Select
    Range("A1").Select
    ActiveCell.End(xlDown).Select
    Selection.Offset(1, 0).Select
    ActiveSheet.Paste
    Range("A1").Select
    ActiveCell.End(xlDown).Select
    Selection.Offset(1, 0).Select
    ActiveCell.FormulaR1C1 = "+"
    Sheets("Sheet3").Select
    Selection.Offset(1, 0).Select
    ' This is where the code to stop the loop needs to go
  Loop

End Sub
robinCTS
  • 5,746
  • 14
  • 30
  • 37
K. Robert
  • 101
  • 2
  • 12
  • I guess the problem is not exiting the loop, but the selection in your code never changed. – newacc2240 Nov 23 '17 at 11:06
  • The selection is always moving down and that is the criteria of my filter. The problem is that it won't stop with these option even if the cell is empty. – K. Robert Nov 23 '17 at 11:08
  • `ActiveCell` is an independent object, not belongs to any worksheet. Try `If IsEmpty(ActiveCell) Then Exit Do`. However I suggest do not use `Selection` nor `ActiveCell` in your code, use their address and access them by `.Value` directly would be better. – newacc2240 Nov 23 '17 at 11:16
  • I have just tried it, didn't work. The macro won't stop if it hits the empty cell. – K. Robert Nov 23 '17 at 11:20
  • Are you always selecting more than one cell or sometimes cell selection is just one cell? Will selection always be single column or it could be multicolumn? – shrivallabha.redij Nov 23 '17 at 11:23
  • Are you sure your `ActiveCell` is moving on? I've tried, it works perfectly. – newacc2240 Nov 23 '17 at 11:24
  • Sheets("Sheet4").Select ActiveSheet.Range("$A$1:$R$25239").AutoFilter Field:=5, Criteria1:= _ Sheets("Sheet3").Application.Selection.Value Range("A1").Select ActiveCell.CurrentRegion.Select Selection.Copy Sheets("Sheet5").Select Range("A1").Select ActiveCell.End(xlDown).Select Selection.Offset(1, 0).Select ActiveSheet.Paste Range("A1").Select ActiveCell.End(xlDown).Select Selection.Offset(1, 0).Select ActiveCell.FormulaR1C1 = "+" Sheets("Sheet3").Select Selection.Offset(1, 0).Select If IsEmpty(ActiveCell) Then Exit Do And this between DO and LOOP – K. Robert Nov 23 '17 at 11:47
  • Shrivallabha Redij - My selection will always be a single cell moving down in column A one by one until it hits an empty cell. – K. Robert Nov 23 '17 at 11:56
  • Set a breakpoint at `If IsEmpty` line and check the code ever executed or not. BTW, after my testing, the `Criteria1` part may cause the problem. Even you called `Sheets("Sheet3")`, the `Selection` is still in your `Sheets("Sheet4")` – newacc2240 Nov 23 '17 at 12:17
  • If you are posting extra code for your question, please edit it into the body of the question. Don't add it in a comment. I have done the edit for you this time :) – robinCTS Nov 24 '17 at 07:33

5 Answers5

3

This question is a classic case of the XY Problem.

Y Solution

The main reason none of your four attempts to detect an empty cell work, is a lack of understanding on what Selection and ActiveCell actually are. They are properties of the Application object and return the following

  • Selection - the selected object of the active sheet (the top most sheet)

  • ActiveCell - the active cell of the active sheet (the top most sheet)

You can't use Sheets("Sheet3").ActiveCell or Sheets("Sheet3").Selection as the Sheet object doesn't have these properties.

What you can use is Application.ActiveCell and Application.Selection or, more simply, ActiveCell and Selection. Of course, this will only work after activating Sheet3.

My preferred way of doing this is:

Sheets("Sheet3").Activate
If (IsEmpty(ActiveCell)) Then Exit Do

Your code also contains a similar problem with this bit:

Criteria1:=Sheets("Sheet3").Application.Selection.Value

While the code correctly gets the Selection object, it doesn't actually activate Sheet3 and is exactly the same as writing:

Criteria1:=Application.Selection.Value or Criteria1:=Selection.Value

Fixing this issue by storing the Sheet3 selection value in a variable leads to the following working code:

Option Explicit
'(v0.2)
Public Sub Y_Fixed_BUT_VERY_VERY_VERY_BAD_CODE()

  ' Added three lines and changed a fourth to fix the incorrect usage of "Selection" for the criteria
  ' Changed a fifth line to add the correct loop exit code
  Sheets("Sheet3").Activate ' Fix#1 Not necessary if the code is always run from Sheet3
  Dim varSheet3ActiveCellValue As Variant ' Fix#2
  Do
    varSheet3ActiveCellValue = ActiveCell.Value2 ' Fix#3
    Sheets("Sheet4").Select
    ActiveSheet.Range("$A$1:$R$25") _
      .AutoFilter _
        Field:=5, _
        Criteria1:=varSheet3ActiveCellValue ' Fix#4
    Range("A1").Select
    ActiveCell.CurrentRegion.Select
    Selection.Copy
    Sheets("Sheet5").Select
    Range("A1").Select
    ActiveCell.End(xlDown).Select
    Selection.Offset(1, 0).Select
    ActiveSheet.Paste
    Range("A1").Select
    ActiveCell.End(xlDown).Select
    Selection.Offset(1, 0).Select
    ActiveCell.FormulaR1C1 = "+"
    Sheets("Sheet3").Select
    Selection.Offset(1, 0).Select ' Fix#5
    If IsEmpty(ActiveCell) Then Exit Do
  Loop

End Sub

X Solution

As mentioned in response to your first posted question, you really, really need to learn how to avoid using .Select. This Stack Overflow post is a good place to start.

The following code is the equivalent to the above, without using a single .Select, .Activate, Selection, or ActiveCell. It also includes a better way to find the last value in a column. (Your method fails unless there is a least one cell containing a value after the first cell.)

A useful way to work out how the code works is to select a word in it, for example With and pressing F1. This will bring up the Excel Help related to that word, with explanations and examples.

'============================================================================================
' Module     : <in any standard module>
' Version    : 1.0
' Part       : 1 of 1
' References : N/A
' Source     : https://stackoverflow.com/a/47468132/1961728
'============================================================================================
Option Explicit

Public Sub X__GOOD_CODE()

  Dim rngFilterCriteriaList As Range
  With Sheets("Sheet3").Range("A3")
    Set rngFilterCriteriaList = Range(.Cells(1), .EntireColumn.Cells(Rows.Count).End(xlUp))
  End With
  Dim rngCell As Range
  For Each rngCell In rngFilterCriteriaList
    Sheets("Sheet4").Range("A1:R25239") _
      .AutoFilter _
        Field:=Range("E:E").Column, _
        Criteria1:=rngCell.Value2
    Sheets("Sheet4").Range("A1").CurrentRegion.Copy _
      Destination:=Sheets("Sheet5").Range("A:A").Cells(Rows.Count).End(xlUp).Offset(1)
    Sheets("Sheet5").Range("A:A").Cells(Rows.Count).End(xlUp).Offset(1).Value2 = "+"
  Next rngCell
  Sheets("Sheet4").Cells.AutoFilter

End Sub
Community
  • 1
  • 1
robinCTS
  • 5,746
  • 14
  • 30
  • 37
  • Just came back from holiday and read through your answer, it looks brilliant, I will try it as soon as I can! – K. Robert Nov 28 '17 at 10:20
  • @K.Robert Thanks. Was wondering where you had got to. I've left out a few details as I didn't want the post to get *too* long. Let me know if you think I need to add any more explanations. – robinCTS Nov 28 '17 at 10:36
  • Just tried it, works brilliantly, thanks very much you have saved me a lot of time with this! – K. Robert Nov 28 '17 at 10:41
-1

selection can contain 1 or more cells. If you want to check if all the cells in the selection are empty you can use the worksheet function countblank which returns the number of empty cells. If the number of empty cells in the selection equals the number of cells in the selection then all the cells in the selection are empty. your test can be adapted like this

    If Application.WorksheetFunction.CountBlank(Selection) = Selection.Count Then Exit Do
h2so4
  • 1,559
  • 1
  • 10
  • 11
-1

if u cannot specify the range then have to activated sheet3 then its works refer below:

ThisWorkbook.Worksheets("Sheet3").Activate
If ActiveCell = "" Then
Exit Do
End If
Ashok
  • 284
  • 2
  • 5
  • 23
  • Is it any different to Sheets("Sheet3").Select what I already do? – K. Robert Nov 23 '17 at 16:32
  • @K.Robert The `Sheets` object is a parent object for Worksheets and Chart Sheets. If a workbook has 3 worksheets and 1 chart sheet, `sheets' function will count 4 sheets but `worksheets` will count 3 three sheets – Ashok Nov 24 '17 at 04:47
  • Ashok (& @K.Robert) In other words, no. `ThisWorkbook.Worksheets("Sheet3").Activate` and `Sheets("Sheet3").Select` behave exactly the same in this situation – robinCTS Nov 24 '17 at 07:54
  • @robinCTS - here sheets and worksheets both working same but i am elaborate what the difference between those two objects – Ashok Nov 24 '17 at 08:44
  • Who gave the devote for above ans - may know reason pls? – Ashok Nov 24 '17 at 08:48
  • @robinCTS May be but developer should understand what is the purpose of using function,object etc.. – Ashok Nov 24 '17 at 08:54
  • I realise that. However, if we are taking about supplying irrelevant info, you forgot to mention the difference between the `ThisWorkbook` object and the `Application` object. What you didn't do is *actually answer* K.Robert's question, which, I repeat, is "no". – robinCTS Nov 24 '17 at 08:55
  • As for why the downvote, my guess is that the other 3 short answers are very low quality (irrelevant/don't actually answer the question) and your answer *looks* like it might be too. Somebody saw this and decided to downvote them all. Your answer is correct but, as the wording is hard to understand it is easy to mistake it for low quality. (I realise this is not your fault, as I don't think English is your first language.) – robinCTS Nov 24 '17 at 09:07
-1

Your selection will not change if you are not changing the cell by using .select in the code and therefore will likely result in infinite loop. But using .select in the code is not considered as good practice as it slows down the process.

I'd suggest using For...each Loop like below.

Dim rng as Range
For each rng in selection
    If Len(rng.Value) = 0 then Exit Sub '\\ Exit at first blank cell
    '\\ Do process here
Next rng
shrivallabha.redij
  • 5,832
  • 1
  • 12
  • 27
  • I am definitely changing the cell with the offset.Select code. I do know it is not ideal however couldn't figure out how to make it work with the Dim and as version, I've only got into VBA :). – K. Robert Nov 23 '17 at 16:30
-2

Your solution is here. Credits to mvptomlinson from MrExcel.com

The right code is

'Your code to loop through copying sheets
    If ActiveSheet.Range("A1").Value = "" Then Exit Sub
'Your code to continue if A1 isn't empty
Arjeel
  • 148
  • 10
  • It cannot be a specific range though, it needs to be the value of my current selection which I have tried as you can see above. I have tested your code by all means with replacing .Range with .Selection but didn't work. – K. Robert Nov 23 '17 at 11:15