2

I am currently using the following code:

Sub SendEmail()

    Dim objOutlook As Object
    Dim objMail As Object
    Dim RowsCount As Integer
    Dim Index As Integer
    Dim Recipients As String
    Dim Category As String
    Dim CellReference As Integer

    Set objOutlook = CreateObject("Outlook.Application")
    Set objMail = objOutlook.CreateItem(0)

    If ActiveSheet.FilterMode = True Then
        RowsCount = ActiveSheet.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count - 1
    ElseIf ActiveSheet.FilterMode = False Then
        RowsCount = Application.CountA(Range("A2:A" & Rows.Count)) - 1
    End If

    ' In Range("I1") there is the job category the user wants to email
    Category = Range("I1")
    If Category = Range("S2") Then
        ' CellReference is the amount of columns to the right of column A, ie Column A is 0 so CellReference below is J - which is the column location of the email address according to that category
        CellReference = 10
    ElseIf Category = Range("S3") Then
        CellReference = 14
    ElseIf Category = Range("S4") Then
        CellReference = 18
    ElseIf Category = Range("S5") Then
         CellReference = 16
    End If

    Index = 0
    While Index < RowsCount
        Set EmailAdrs = ActiveSheet.AutoFilter.Range.Offset(1).SpecialCells(xlCellTypeVisible).Cells(1, CellReference).Offset(0 + Index, 0)
        Recipients = Recipients & EmailAdrs.Value & ";"
        Index = Index + 1
    Wend

     With objMail
        .To = Recipients
        .Subject = "This is the subject"
        .Display
    End With

    Set objOutlook = Nothing
    Set objMail = Nothing

End Sub

This code checks to see if a filter has been applied and counts the amounts of rows if there is one or isn't one, it then checks to see who should be emailed (the 'Category' which is in I1 is the job position of different individuals) and then gets the email addresses of those required, the issue I'm having is say I have the following data (this is just an example of what I want to do):

Column A         Column B             Column C
Smith            Male                 123@123.co.uk
Jones            Male                 abc@abc.co.uk
Smith            Female               456@123.co.uk
Jones            Female               def@abc.co.uk
Smith            Male                 789@123.co.uk
Smith            Female               101112@123.co.uk
Smith            Female               141516@123.co.uk
Jones            Female               ghi@abc.co.uk

And I filter on Jones in column A and Female in Column B to get two rows returned, rather than getting the email addresses def@abc.co.uk and ghi@abc.co.uk it will get the email addresses def@abc.co.uk and 789@123.co.uk because it finds the first row with the filter applied then goes to the next cell disregarding the filter.

Is there a way I can fix this so that it gets the filtered cells?

It is important to point out that the filter may not always be the same, so it won't always be both Column A and Column B, it might just be Column A or just Column B.

Ben Smith
  • 809
  • 5
  • 21
  • 46
  • I am not good with filters, but I think you can always just loop on column A, and if you find a cell containing Jones, add that cell(,2) to Recipients. – David G Jul 23 '15 at 16:53
  • When push comes to shove, what difference does it make whether there is an active filter or not if you are going to go through the visible rows? All that matters is that there are rows to go through. –  Jul 24 '15 at 10:26
  • @Jeeped are you referring to the lines such as: `If ActiveSheet.FilterMode = True Then`? – Ben Smith Jul 24 '15 at 10:37
  • Yes. Not only does the non-.FilterMode code look suspect, there really isn't any point to write two of anything. If there is no .FilterMode then all of the rows will be visible. If there is then only some of the rows will be visible. If you write the routine for visible rows then what difference does it make whether there is a FilterMode or not? –  Jul 24 '15 at 10:40
  • It doesn't make a difference at all, it just helps me see that it is counting the correct rows and means that when the line `While Index < RowsCount` runs I don't have to sit and use the debugger through a lot of records. But your right, it's not needed in there. – Ben Smith Jul 24 '15 at 10:44

2 Answers2

1

Replace the bottom section of your code with this:

If ActiveSheet.FilterMode = True Then
    With ActiveSheet.AutoFilter.Range
        For Each a In .Offset(1).Resize(.Rows.Count).SpecialCells(xlCellTypeVisible).Areas
            Recipients = Recipients & a(1, CellReference) & ";"
        Next
    End With
    MsgBox Replace(Recipients, ";;", vbNullString)
End If
Excel Hero
  • 14,253
  • 4
  • 33
  • 40
0

You can use

1) To select a range: (Of course you can use a formula instead of a fixed range)

Dim Rng As Range
If Category = Range("S2") Then
    ' CellReference is the amount of columns to the right of column A, ie Column A is 0 so CellReference below is J - which is the column location of the email address according to that category
    CellReference = 10
    'Set your range
    Set Rng = [Insert here your criteria to set the range when CellReference = 10]

ElseIf Category = Range("S3") Then
    CellReference = 14
    'Set your range
    Set Rng = [Insert here your criteria to set the range when CellReference = 14]
ElseIf Category = Range("S4") Then
    CellReference = 18
    'Set your range
    Set Rng = [Insert here your criteria to set the range when CellReference = 18]
ElseIf Category = Range("S5") Then
     CellReference = 16
    'Set your range
    Set Rng = [Insert here your criteria to set the range when CellReference = 16]
End If

(Consider using a Select Case instead of ElseIf) And then loop the range

'You need to replace YourSheetName with the real name of your sheet
For Each mCell In ThisWorkbook.Sheets("YourSheetName").Range(Rng).SpecialCells(xlCellTypeVisible)
    'Get cell address
    mAddr = mCell.Address
    'Get the address of the cell on the column you need
    NewCellAddr = mCell.Offset(0, ColumnsOffset).Address
    'Do everything you need
Next mCell

mCell is an Object variable that contains a lot of informations on the cells that it represents.

So, if mCell is the A1 Cell containing "Hello World":

mCell.Address will be "$A$1"
mCell.Value will be "Hello World"
mCell.Offset(0, 2).Address will be "$C$1"

You can also get and/or set a lot of other data:

mCell.NumberFormat
mCell.RowHeight
mCell.Formula

Have a look at local variables to see all you can get/set for mCell

genespos
  • 3,211
  • 6
  • 38
  • 70
  • please note that the range would be different each time depending on the category selected, please see the edited question. Thank you for your answer though. – Ben Smith Jul 24 '15 at 09:24
  • @BenSmith I edited my answer to suggest how to modify your code – genespos Jul 24 '15 at 10:04
  • thank you for your edit, I am not very proficient in VBA so would you mind just explaining to me what the lines `For Each mCell In ThisWorkbook.Sheets("BM & SM Contact List").Range(Rng).SpecialCells(xlCellTypeVisible)` and `NewCellAddr = mCell.Offset(0, ColumnsOffset).Address` do? Especially as I do not understand what the `mCell` is and the `ColumnsOffset` is. After your comment `Do everything you need` would I insert the `While Index < RowsCount` and the lines between that and `Wend` there? – Ben Smith Jul 24 '15 at 10:32
  • thank you for your answer and adding to it. However, I have the following problems with the code that when I run it it doesn't work: firstly the lines like `Set Rng = Range("A1:B2")` can't really work because the number of rows might change if more are inserted, also I with the line `Each mCell In ThisWorkbook.Sheets("YourSheetName").Range(Rng).SpecialCells(xlCellTypeVisible) I get the error: `Run-time error '1004': Application-defined or object-defined error`. Can you please help. – Ben Smith Jul 24 '15 at 11:37
  • @BenSmith I edited again. In any case, if you filter the data and loop only filtered data, are you sure to need different range? If you edit your question and explain the criteria to determine the range (or the data on the sheet) you need I'll try to give you a way. – genespos Jul 24 '15 at 14:47
  • I posted another question which has been answered, please find it using the following: http://stackoverflow.com/questions/31610634/vba-select-the-first-filtered-cell-then-move-onto-the-next-one-down . Thank you for your help though! – Ben Smith Jul 24 '15 at 14:50