0

I have code which sorts and copies results from one worksheet to another. Sometimes I need to paste copied range to the next blank cell on selected worksheet, for which I need to use ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row.

        Worksheets("Wallets").AutoFilterMode = False

        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=5, Criteria1:="*TRANSFER*"
        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=7, Criteria1:=">0"
                 Worksheets("Wallets").Range("B2:I" & Worksheets("Wallets").Cells(Rows.Count, 1).End(xlUp).Row).Copy
                 Worksheets("Transfers").Cells(Worksheets("Transfers").Cells(Rows.Count, 1).End(xlUp).Row, 1).Offset(1, 0).PasteSpecial Paste:=xlPasteValue

        Worksheets("Wallets").AutoFilterMode = False

        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=5, Criteria1:="*EXCHANGE*"
        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=7, Criteria1:=">0"
                 Worksheets("Wallets").Range("B2:I" & Worksheets("Wallets").Cells(Rows.Count, 1).End(xlUp).Row).Copy
                 Worksheets("Transfers").Cells(Worksheets("Transfers").Cells(Rows.Count, 1).End(xlUp).Row, 1).Offset(1, 0)..PasteSpecial Paste:=xlPasteValues

I was thinking about changing code so i can replace this part more easily if I need to use other column for some worksheets for example. Is there any way to make variable recalculate each time it used in sub? Part of code below just saves first result and uses it, but I need to update row count number it for each worksheet which is currently used(perferably without using Worksheets.Select).

Sub Sort_Wallets()
Dim x As Long

       x = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
    

        Worksheets("Wallets").AutoFilterMode = False
        Worksheets("Wallets").Select
        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=5, Criteria1:="*TRANSFER*"
        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=7, Criteria1:=">0"
                 Worksheets("Wallets").Range("B2:I" & x).Copy
                 Worksheets("Transfers").Select
                 Worksheets("Transfers").Cells(x, 1).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
                 

        Worksheets("Wallets").AutoFilterMode = False
        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=5, Criteria1:="*EXCHANGE*"
        Worksheets("Wallets").Range("$A$1:$J10000").AutoFilter Field:=7, Criteria1:=">0"
                 Worksheets("Wallets").Range("B2:I" & x).Copy
                 Worksheets("Transfers").Cells(x, 1).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
End Sub
10
  • You forgot to actually ask a question. Commented Oct 23, 2020 at 12:47
  • x = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row - you should use the worksheet in question instead of ActiveSheet. Commented Oct 23, 2020 at 12:53
  • @BigBen which one? because it is different each time and I do not want to add this line every time it changes. Commented Oct 23, 2020 at 13:16
  • @GeertBellekens what do you mean? Commented Oct 23, 2020 at 13:17
  • I'm a bit confused what you're trying to do, but in your second code snippet you use ActiveSheet to get the last row, but then filter the hard-coded Wallets sheet. Commented Oct 23, 2020 at 13:18

2 Answers 2

1

If you are looping through worksheets you can, but not if you are only using two worksheets. You will need to specify the worksheet. You are using x as the last row in each case and I doubt that is true. Why set J10000 if you are going to find the last row? Also, it looks like you only want to copy the visible cells after you filter. You need to specify that you only want the visible cells. It is easier to follow your code if you Set the variables, ranges and worksheets so as not to repeat long lines. Here is an example of what I just said using your code. There may even be a better solution, but this is more readable than what you have.

Sub Sort_Wallets()
    Dim destlr As Long
    Dim sourcelr As Long
    Dim wk1 As Worksheet
    Dim wk2 As Worksheet
    Dim FiltRng As Range
    
    Set wk1 = ThisWorkbook.Worksheets("Wallets")
    Set wk2 = ThisWorkbook.Worksheets("Transfers")
    
    
    destlr = wk2.Cells(Rows.Count, 1).End(xlUp).Row
    sourcelr = wk1.Cells(Rows.Count, 1).End(xlUp).Row
    
    Set FiltRng = wk1.Range(wk1.Cells(1, 1), wk1.Cells(sourcelr, 10))
    
    wk1.AutoFilterMode = False
       
    FiltRng.AutoFilter Field:=5, Criteria1:="*TRANSFER*"
    FiltRng.AutoFilter Field:=7, Criteria1:=">0"
    wk1.Range("B2:I" & sourcelr).SpecialCells(xlCellTypeVisible).Copy

    wk2.Cells(destlr, 1).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
             

    wk1.AutoFilterMode = False
    FiltRng.AutoFilter Field:=5, Criteria1:="*EXCHANGE*"
    FiltRng.AutoFilter Field:=7, Criteria1:=">0"
    wk1.Range("B2:I" & sourcelr).SpecialCells(xlCellTypeVisible).Copy
    
    wk2.Cells(destlr, 1).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
    
End Sub
Sign up to request clarification or add additional context in comments.

4 Comments

Basically I have worksheet called Wallets that has different number of rows every day and everyday I need to sort and copy data to other worksheets based on particular keyword.I gave part of my code as a example for one worksheet.And yes it copies only visible data and that works great,no questions about that.Sometimes worksheet that I need to copy data to already has some information thats why i need to find first unused cell and paste data to it.And giving .Cells(Rows.Count, 1).End(xlUp).Row worksheet number where to find last row is what I am currently doing in my first code that I am using
The question was if there any way to not do this but change code that it will determine worksheet that is currently active in that particular line of code and use last row of this active sheet without names. Your example does the same as mine first just uses variables.
You were using x in both sheets. Using ActiveSheet is not advisable because you may not be starting from the sheet you want. Like I said, if you are going to loop through and say For each sh in ThisWorkbook.Worksheets using the Worksheets collection, then you can use the same variable for each sheet. Otherwise you need to specify, and it is best to be specific.
Looping wont work because I use different filter for each Worksheet, the only thing that is the same is finding the last row in each of them. Well too bad, I hoped there is any way not to repeat this Cells(Rows.Count, 1).End(xlUp).Row for each time I need to find last row but finally start using variables.
0

Assuming you're using your worksheets like data tables, use "tables". For each table of data, highlight it and "Insert Table", and then go into the table ribbon (available only when the cursor is within that table) and change the name of your table from whatever it is ("Table5") to something that makes sense to you.

In VBA, these are called ListObjects. As long as you know the names of these tables, you can get them with the following code:

'Returns the specified object from a collection
'Returns Nothing if the value in the collection doesn't exist.
'Throws no errors
Private Function GetFromCollection(col As Collection, sKey As String) As Object
    On Error Resume Next
    Set GetFromCollection = col.item(sKey)
    Err.Clear
End Function

Public Function GetListObjectFromWorkbook(sTableName As String, Optional bRecache As Boolean = False) As ListObject
    Static bInitialized As Boolean
    Static col As Collection
    Dim lo As ListObject
    Dim sht As Worksheet
    
    If bRecache Or Not bInitialized Then
        Set col = New Collection
        For Each sht In Sheets
            For Each lo In sht.ListObjects
                col.Add lo, lo.Name
            Next lo
        Next sht
        bInitialized = True
    End If
    Set GetListObjectFromWorkbook = GetFromCollection(col, sTableName)
End Function

From there, you don't need to know where the last row is! Adding a new row is:

Dim listrow As ListRow
Set listrow = GetListObjectFromWorkbook(sTableName).ListRows.Add

and you can manipulate the values of that new ListRow via listrow.Range

FYI: You can sort ListObjects, too. See the VB code in https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.tools.excel.listobject.sort?view=vsto-2017

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.