VBA script for copying highest row in table - excel

I have a table with data in a worksheet called 'DL data calculation'. I want to copy the highest row in the table (A21:E21) (after filtering) to (Y3:AC3). The problem I am facing right now is that when I declare the range try to filter, only the A21:E21 row of cells gets copied instead of the highest row. Can someone help me? I entered the script I used underneath.
Sub CopySelectionVisibleRowsEnd()
Dim ws As Worksheet
Dim mySel As Range
Dim lRow As Long
Dim lRowNew As Long
Dim lRowsAdd As Long
Dim myList As ListObject
Dim myListRows As Long
Dim myListCols As Long
Set ws = ActiveSheet
Set mySel = Selection.EntireRow
Set myList = ActiveCell.ListObject
myListRows = myList.Range.Rows.Count
myListCols = myList.Range.Columns.Count
lRow = ws.Cells.Find(What:="*", _
SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, _
LookIn:=xlValues).Row + 1
mySel.SpecialCells(xlCellTypeVisible).Copy
ws.Cells(lRow, 1).PasteSpecial Paste:=xlPasteAll
lRowNew = ws.Cells.Find(What:="*", _
SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, _
LookIn:=xlValues).Row + 1
lRowsAdd = lRowNew - lRow
With myList
.Resize ws.Range(.Range.Resize(myListRows + lRowsAdd, myListCols).Address)
End With
Application.CutCopyMode = False
End Sub

I made some changes to create sample data and working code:
Sub CreateSampleData()
Range("A21") = "F1"
Range("B21") = "F2"
Range("C21") = "F3"
Range("D21") = "F4"
Range("E21") = "F5"
Range("A22:E62") = "=INT(RAND()*1000)"
Range("A22:E62").Copy
Range("A22").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$21:$E$62"), , xlYes).Name = "Table1"
End Sub
Sub CopySelectionVisibleRowsEnd()
Dim ws As Worksheet
Dim mySel As Range
Dim lRow As Long
Dim lRowNew As Long
Dim lRowsAdd As Long
Dim myList As ListObject
Dim myListRows As Long
Dim myListCols As Long
Set ws = ActiveSheet 'Sheets("Tabelle1")
Why do you select this row?
You do want to select the first visible row here?
This line just selects the "EntireRow" of the active selection.
Set mySel = Selection.EntireRow
Let's continue with your code:
Set myList = ActiveCell.ListObject
myListRows = myList.Range.Rows.Count
myListCols = myList.Range.Columns.Count
lRow = ws.Cells.Find(What:="*", _
SearchOrder:=xlRows, _
SearchDirection:=xlNext, _
LookIn:=xlValues).Row + 1
'Here you copy the row of the active cell (if its visible).
'If you select a cell and make it unvisible with the filter
'you select nothing!
'mySel.SpecialCells(xlCellTypeVisible).Copy
'If you select a cell after the filter this can be copied with
'your code - first 5 cells only:
mySel.Range("A1:E1").SpecialCells(xlCellTypeVisible).Copy
' You want to paste to Cell Y3?
'ws.Cells(lRow, 1).PasteSpecial Paste:=xlPasteAll
ws.Range("Y3").PasteSpecial Paste:=xlPasteAll
'what is it that you want to achieve here?
lRowNew = ws.Cells.Find(What:="*", _
SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, _
LookIn:=xlValues).Row + 1
lRowsAdd = lRowNew - lRow
'I have no idea what you want to achieve here:
'With myList
'.Resize ws.Range(.Range.Resize(myListRows + lRowsAdd, myListCols).Address)
'End With
Application.CutCopyMode = False
End Sub
With the changes above at least the code was working.
Whatever row the cursor is manually placed in -> this row gets copied to the range "Y3:AC3"
With the below code I copy the first visible row (col A to E)
of the list existing on the active sheet and paste it to the
range (Y3:AC3).
Sub CopySelectionVisibleRowsEnd_NEW()
Dim myList As ListObject
Set myList = ActiveSheet.ListObjects(1) 'ActiveSheet.ListObjects("Table1")
Set CopyRange = myList.Range.Offset(1).SpecialCells(xlCellTypeVisible).Range("A1:E1")
CopyRange.Copy
Range("Y3").PasteSpecial Paste:=xlPasteAll
'or PasteValues:
'Range("Y3").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
End Sub

Related

Copy and paste value

I have a code on the internet that collects data from sheet 3 to the very end one, then combines data to sheet "STOCK DETAILS".
The problem is I just want to paste all the data as value.
I'm new to excel VBA so please help me! Many thanks!
So this is the code:
Sub Combine2()
Dim J As Long, lstrw As Long, lstco As Long, lstrw2 As Long
Dim sTableName As String
'Define Variables
sTableName = "Table1"
Application.ScreenUpdating = False
On Error Resume Next
Sheets("STOCK DETAILS").ListObjects(sTableName).Delete
Sheets(3).Rows(1).Copy Destination:=Sheets("STOCK DETAILS").Range("A4")
For J = 3 To Sheets.Count ' from sheet 2 to last sheet
If WorksheetFunction.CountA(Sheets(J).Cells) > 0 Then
With Sheets(J)
lstrw = .Cells.Find(what:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row
lstco = .Cells.Find(what:="*", SearchOrder:=xlColumns, SearchDirection:=xlPrevious, LookIn:=xlValues).Column
lstrw2 = Sheets("STOCK DETAILS").Cells.Find(what:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row
.Range(.Cells(2, "A"), .Cells(lstrw, lstco)).Copy Sheets("STOCK DETAILS").Range("A" & lstrw2)(2)
End With
End If
Next
With Sheets("STOCK DETAILS").ListObjects.Add(xlSrcRange, Sheets("STOCK DETAILS").Range("A$4:$L$9999"), , xlYes)
.Name = "Table1"
.TableStyle = "TableStyleLight21"
End With
End Sub
To paste just the values you use
.Range(...).PasteSpecial xlPasteValues

Copy data based on loop and then paste data on multiple sheets created based on array

I am creating new data which is dependent upon variable x using loop, then trying to copy the data with each iteration in X and then pasting the data on multiple sheets (variable "FundSheetNames"). Here I dont know how to exit from loop FundSheetNames without next i and then again go on to X to copy new data.
Sub peer2()
ThisWorkbook.Sheets("Peer Code").Activate
Dim X As Range, Y As Range
Set X = Sheets("Peer Code").Range("J2:J11")
Dim Sht As Worksheet
Dim sheet_names As Variant
For Each sheet_Name In Sheets("Peer Code").Range("K2:K3")
For Each Y In X
Set WS = Worksheets(sheet_Name.Text)
ThisWorkbook.Sheets("Peer Fund").Activate
Range("F7:F166").Select
Selection.ClearContents
ThisWorkbook.Sheets("Peer Code").Activate
Y.Select
Selection.Copy
Range("L2").Select
Selection.PasteSpecial Paste:=xlPasteValues
Range("N2:N161").Select
Selection.Copy
ThisWorkbook.Sheets("Peer Fund").Activate
Range("F7").EntireColumn.Hidden = False
Range("$F7").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone,
SkipBlanks:= _
False, Transpose:=False
With Sheets("Peer Fund")
Set FOUNDRANGE = .Columns("F:F").Find("*", After:=.Range("F167"), searchdirection:=xlPrevious, LookIn:=xlValues)
If Not FOUNDRANGE Is Nothing Then LR1 = FOUNDRANGE.Row
End With
Range("F166:F" & LR1 + 1).EntireRow.Select
Application.Selection.EntireRow.Hidden = False
Range("A6:W" & LR1).Select
ActiveWorkbook.Worksheets("Peer Fund").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Peer Fund").Sort.SortFields.Add2 Key _
:=Range("A2:A" & LR1), SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Peer Fund").Sort
.SetRange Range("A6:W" & LR1)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("F7").EntireColumn.Hidden = False
Range("A5:W172").Select
Selection.SpecialCells(xlCellTypeVisible).Copy
WS.Activate
Range("A5").Select
Selection.PasteSpecial Paste:=xlPasteValues
Selection.PasteSpecial Paste:=xlPasteFormats
With WS
Set FOUNDRANGE = .Columns("F:F").Find("*",
After:=.Range("F167"),
searchdirection:=xlPrevious, LookIn:=xlValues)
If Not FOUNDRANGE Is Nothing Then LR2 = FOUNDRANGE.Row
End With
Range("F166:F" & LR1 + 1).EntireRow.Select
Application.Selection.EntireRow.Hidden = True
Range("F7").EntireColumn.Hidden = True
Next Y
Next sheet_Name
End Sub
Exit For
Open a new worksheet and put the code into a module. Then put in some values into column A. Put a few 5-s among the values.
The following is an example that looks for the value 5 in column A. When 5 is found it returns a message containing the address of the cell where it was found, in the Immediate window (CTRL+G).
Option Explicit
Sub FirstOccurrence()
Const Col As Variant = "A"
Const FirstRow As Long = 2
Const Criteria As Long = 5
Dim rng As Range
' Define the last non-empty cell.
Set rng = Columns(Col).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.Row < FirstRow Then Exit Sub
' Define the column range from FirstRow to row of last non-empty cell.
Set rng = Range(Cells(FirstRow, Col), rng)
Dim cel As Range
For Each cel In rng
If cel.Value = Criteria Then
Debug.Print "Cell '" & cel.Address & "' contains the value '" _
& Criteria & "'."
Exit For
End If
Next cel
End Sub
You have just seen how the code finds just the first occurrence of 5.
Now remove the line Exit For and see the results in the Immediate window (CTRL+G).

Copy Pasting table to variable range based on condition and fixed offset

The macro is suppose to copy a fixed table 1 ("E19:Q34") and paste it to a range which is 15 column offset of cell E19 i.e. "T19" and would be called 'Table 2'. the next time the macro runs it should be able to detect the table and further move ahead 15 columns to "AI19" and so on..
Sub Macro()
Application.ScreenUpdating = False
Dim Rng, rng1, rng2 As Range, ws As Worksheet,
Set ws = ActiveWorkbook.ActiveSheet
Set Rng = ActiveSheet.Range("E19")
Set rng1 = Rng.Offset(0, 15)
Set rng2 = ActiveSheet.Range("E19:Q34") 'fixed base range
'Copy the range with text and paste it after finding the right location
rng2.copy
rng1.Select
For Each rng1 In rng1.Cells
If rng1.Value = "" Then
Selection.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
ws.Paste
Application.CutCopyMode = False
Exit For
Else
Range(rng1).Address = ActiveCell.Offset(0, 15) 'attempting to change the reference of rng1
' MsgBox rng1
End If
Next rng1
End sub
Try this:
Sub Macro()
Const COL_OFFSET As Long = 15
Dim rng, ws As Worksheet, cols As Long
Set ws = ActiveSheet
Set rng = ws.Range("E19:Q34")
Application.ScreenUpdating = False
rng.Copy
cols = COL_OFFSET
'find the next empty slot
Do While Application.CountA(rng.Offset(0, cols)) > 0
cols = cols + COL_OFFSET
Loop
With rng.Offset(0, cols)
.PasteSpecial Paste:=xlValues
.PasteSpecial Paste:=xlPasteColumnWidths
.PasteSpecial Paste:=xlPasteFormats
End With
End Sub

VBA Find #N/A value and copy adjacent cells to another sheet and loop

Good day to everyone,
I have been trying to find an answer here that would fit my problem but I have been unsuccessful. I am using FIND to search column F for cell with #N/A value and copy adjacent cells to another "Sheet2" at the end of the column A. I have made the following code that works but my problem is I want to make it to loop to find the next cell with #N/A value till find all.
Sub Find()
Dim SerchRange As Range
Dim FindCell As Range
Set SerchRange = Range("F:F")
Set FindCell = SerchRange.FIND(What:="#N/A", _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If FindCell Is Nothing Then
MsgBox "Nothing was found all clear"
Else
FindCell.Select
ActiveCell.Offset(0, -3).Resize(, 3).Select
Selection.Copy
Sheets("Sheet2").Select
Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Select
ActiveSheet.Paste
End If
End Sub
Try this and let me know if it works:
Option Explicit
Sub Find()
Application.ScreenUpdating = False
Dim SearchRange As Range
Dim FindCell As Range
Dim Check As Boolean
Dim LastRow As Long
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim FindCounter As Long
Set ws = ThisWorkbook.Worksheets("Sheet1") ' <--- Insert the name of your worksheet here
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
LastRow = ws.Cells(Rows.Count, "F").End(xlUp).Row ' <--- Finds the last used row
Set SearchRange = Range("F1:F" & LastRow)
FindCounter = 0
For Each FindCell In SearchRange
If FindCell.Value = "#N/A" Then
FindCounter = FindCounter + 1
FindCell.Offset(0, -3).Resize(, 3).Copy
ws2.Range("A" & ws2.Cells(Rows.Count, "A").End(xlUp).Row + 1).PasteSpecial xlPasteValues
End If
Next
MsgBox "Succes!" & vbNewLine & vbNewLine & "This many cells were found: " & FindCounter
Application.ScreenUpdating = True
End Sub

How to accelerate an Excel VB Macro

I am trying to accelerate my Excel VB Macro.
I have tried the 5 alternatives below.
But I wonder if I could shorten the execution further.
I found 2 alternatives in User Blogs which I could not get to work.
One alternative is also found in a User Blog but do not understand.
Sub AccelerateMacro()
'
' v1 052817 by eb+mb
' Macro to copy as fast as possible sheet from one workbook into another workbooks
' Declarations for variables are not shown to make code example more legible
' Macro is stored in and run from "DestinationWorkBook.xlsm"
StartTime = Timer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Alternative = "First"
If Alternative = "First" Then
Workbooks.Open Filename:="SourceWorkBook.xls"
Cells.Select
Selection.Copy
Windows("DestinationWorkBook.xlsm").Activate
Sheets("DestinationSheet").Select
Range("A1").Select
ActiveSheet.Paste
Windows("SourceWorkBook.xls").Activate
ActiveWorkbook.Close
End If
If Alternative = "Second" Then
Workbooks.Open Filename:="SourceWorkBook.xls", ReadOnly:=True
Cells.Select
Selection.Copy
Windows("DestinationWorkBook.xlsm").Activate
Sheets("DestinationSheet").Select
Range("A1").Select
ActiveSheet.Paste
Workbooks("SourceWorkBook.xls").Close SaveChanges:=False
End If
If Alternative = "Third" Then
' I could not get this alternative to work
Workbooks.Open("SourceWorkBook.xls").Worksheets("SourceSheet").Copy
Workbooks.Open("DestinationWorkBook.xlsm").Worksheets("DestinationSheet").Range("A1").PasteSpecial
End If
If Alternative = "Fourth" Then
' I could not get this alternative to work
Workbooks.Open("DestinationWorkBook.xlsm").Worksheets("DestinationSheet").Range("A1") = Workbooks.Open("SourceWorkBook.xls").Worksheets("SourceSheet")
End If
If Alternative = "Fifth" Then
' I don't understand the code in this alternative
Dim wbIn As Workbook
Dim wbOut As Workbook
Dim rSource As Range
Dim rDest As Range
Set wbOut = Application.Workbooks.Open("DestinationWorkBook.xlsm")
Set wbIn = Application.Workbooks.Open("SourceWorkBook.xls")
With wbIn.Sheets("SourceSheet").UsedRange
wbOut.Sheets("DestinationSheet").Range("A1").Resize(.Rows.Count, .Columns.Count) = .Value
End With
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
End Sub
Instead of using UsedRange, find the actual Last Row and Last Column and use that range. UsedRange may not be the range that you think it is :). You may want to see THIS for an explanation.
See this example (UNTESTED)
Sub Sample()
Dim wbIn As Workbook, wbOut As Workbook
Dim rSource As Range
Dim lRow As Long, LCol As Long
Dim LastCol As String
Set wbOut = Workbooks.Open("DestinationWorkBook.xlsm")
Set wbIn = Workbooks.Open("SourceWorkBook.xls")
With wbIn.Sheets("SourceSheet")
'~~> Find Last Row
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find Last Column
LCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'~~> Column Number to Column Name
LastCol = Split(Cells(, LCol).Address, "$")(1)
'~~> This is the range you want
Set rSource = .Range("A1:" & LastCol & lRow)
'~~> Get the values across
wbOut.Sheets("DestinationSheet").Range("A1:" & LastCol & lRow).Value = _
rSource.Value
End With
End Sub

Resources