Go through columns and copy cells - excel

I wrote code that goes to each row if there is data and copies the data to a different file in specific cells.
Now I want to go through each column instead of row till there is no data left.
My code for rows that is working is:
Sub Row_copying()
'load my workbooks
Dim Header As Workbook
Workbooks.Open FileName:="/Users/Header.xlsx"
Set Header = Workbooks("Header.xlsx")
Dim samplelist As Workbook
Workbooks.Open FileName:="/Users/samplelist.xlsx"
Set samplelist = Workbooks("samplelist.xlsx")
samplelist.Activate
' Loop through each row that has data
Dim lRow As Long
For lRow = 2 To Cells(Rows.Count, 1).End(xlUp).Row
If Range("A" & lRow).Value <> "" Then
'copy cell
Range("D" & lRow).Copy
Header.Activate
Range("K5:M5").Select
ActiveSheet.Paste
samplelist.Activate
Range("H" & lRow).Copy
Header.Activate
Range("F5:G5").Select
ActiveSheet.Paste
Dim DName As String, dataname As String, path As String
samplelist.Activate
path = "/Users/newdata/"
DName = "sample_"
dataname = path & DName & Format(Range("A") & lRow.Value, "000") & ".xlsx"
Header.Activate
ActiveWorkbook.SaveAs FileName:= dataname
End If
samplelist.Activate
Next lRow
Workbooks("samplelist.xlsx").Close
End Sub
I could check how many columns have data by changing the lRow to
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
MsgBox"last Column: "&lCol
I could not manage that it goes through each column and copy the cells.

Instead of using Range() to reference the cells you are checking, you could use Cells(x,y). Since you know the number of rows and columns you have, you can have a nested For i.e. For Each Row Loop All Columns.
Option Explicit
Public Sub sCopy()
Dim numberOfColumns As Long, numberOfRows As Long
Dim x As Long, y As Long
Dim ws As Worksheet
'set number of rows/columns
'set workbooks / worksheets
For x = 1 To numberOfRows
For y = 1 To numberOfColumns
If ws.Cells(x, y).Value <> "" Then
'Do what you have to do
End If
Next y
Next x
End Sub

Related

Loop through 50,000+ rows and copy data until value in the first column changes

I have an Excel sheet with 50,000+ rows of data from A:N. I have a Master Data Sheet that has a query in the BackupData worksheet. I currently copy that data and paste as values into the Backup worksheet. With the headers:
ID
Vendor #
Name
Customer #
Customer
Invoice #
Date
Item#
Item Description
Qty
B/C
Lbs
Amt
Amt#2
I am trying to loop through all of these rows and copy the range of cells A:N until the first value change in Column A, the first different ID #.
I then need to paste the selected range into a new workbook.
Basically, I want to do the opposite of consolidating.
Sub inserting()
Dim wsBData, wsExport, wsCoverSht, wsBackup As Worksheet
Dim wbAllRebates, wbSingle As Workbook
Set wbAllRebates = ActiveWorkbook
Set wsBData = wbAllRebates.Sheets("BackupData")
Set wsBackup = wbAllRebates.Sheets("Backup")
Dim rID, rTopRow As Range
Dim i As Long
Dim Counter As Integer
i = 3
Set rTopRow = Rows(1)
Set rID = wsBackup.Range("A1")
wsBData.Cells.Copy
wsBackup.Cells.PasteSpecial Paste:=xlPasteValues
Counter = 0
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
Do
If rID.Offset(i).Value <> rID.Offset(i - 1).Value Then
Rows(rID.Offset(i).Row).Insert shift:=xlDown
Call SubTotals(rID.Offset(i), rTopRow)
i = i + 1
Set rTopRow = Rows(rID.Offset(i).Row)
End If
Exit Do
Loop
MsgBox i
End Sub
Sub SubTotals(rID As Range, firstRow As Range)
rID.Value = "Total"
rID.Offset(, 9).Value = Application.WorksheetFunction.Sum(Range(firstRow.Cells(1, 10).Address & ":" & rID.Offset(-1, 1).Address))
End Sub
Try
Option Explicit
Sub SeparateWB()
Dim wsBData As Worksheet, wsBackup As Worksheet, wb As Workbook
Dim wbAllRebates As Workbook, rngHeader As Range
Dim i As Long, n As Long, LastRow As Long, StartRow As Long
Set wbAllRebates = ActiveWorkbook
With wbAllRebates
Set wsBData = .Sheets("BackupData")
Set wsBackup = .Sheets("Backup")
End With
wsBData.Cells.Copy
wsBackup.Cells.PasteSpecial Paste:=xlPasteValues
StartRow = 2
Application.ScreenUpdating = False
With wsBackup
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rngHeader = .Range("A1:N1")
For i = 2 To LastRow
' change ID next row
If .Cells(i, "A") <> .Cells(i + 1, "A") Then
' create new workbook
Set wb = Workbooks.Add(1)
rngHeader.Copy wb.Sheets(1).Range("A1")
.Range("A" & StartRow & ":N" & i).Copy wb.Sheets(1).Range("A2")
wb.SaveAs .Cells(i, "A") & ".xlsx"
wb.Close False
' move to next
StartRow = i + 1
n = n + 1
End If
Next
End With
Application.ScreenUpdating = True
MsgBox n & " workbooks created"
End Sub

compare two columns in two different sheets

i would like to compare two columns in two different sheets like column A in sheet 1 start from row 2 till the last row and columns C start from row 2 till the last row. If row in column A is greater than the same row in column C a message box " the value is greater" appear and clear the greater value in column A. Thanks an advance for your support
This should get you started
Sub compare()
Dim sheet1 As Worksheet
Dim sheet2 As Worksheet
Set sheet1 = ThisWorkbook.Sheets("Sheet1")
Set sheet2 = ThisWorkbook.Sheets("Sheet2")
Dim lastrow As Integer
lastrow = sheet1.Range("A2").End(xlDown).Row
Dim i As Integer
For i = 2 To lastrow
If sheet1.Range("A" & i).Value > sheet2.Range("A" & i).Value Then
MsgBox ("the value is greater")
sheet1.Range("A" & i).Value = ""
End If
Next i
End Sub
Delete Greater Than
Option Explicit
Sub deleteGreaterThan()
Dim wb As Workbook
Dim src As Worksheet
Dim dst As Worksheet
Dim LastRow As Long
Dim i As Long
Set wb = ThisWorkbook
Set dst = wb.Worksheets("Sheet1")
Set src = wb.Worksheets("Sheet2")
LastRow = dst.Cells(dst.Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
If dst.Cells(i, "A").Value > src.Cells(i, "C").Value Then
MsgBox "The value in cell '" & dst.Cells(i, "A").Address(0, 0) _
& "' is greater."
dst.Cells(i, "A").Value = ""
End If
Next i
End Sub

Copy rows from one sheet into six sheets

I’ve a spreadsheet that will have a different number of rows each day.
I am trying to divide that number of rows by 6 then copy the info into six different sheets within the same workbook.
For example – say the original sheet has 3000 rows. 3000 rows divided by 6 (500), copied into six different sheets or maybe there are 2475 rows, now dividing it by 6 and trying to keep the number of record split between sheets approximately the same (keeping the sheet with the original 3000 or 2475 rows as is) within the same workbook.
I have code that is creating 6 additional sheets but the records are not being copied to these sheets.
Option Explicit
Public Sub CopyLines()
Dim firstRow As Long
Dim lastRow As Long
Dim i As Long
Dim index As Long
Dim strsheetName As String
Dim sourceSheet As Worksheet
Dim strWorkbookName As Workbook
Sheets.Add
Sheets.Add
Sheets.Add
Sheets.Add
Sheets.Add
Sheets.Add
Set sourceSheet = Workbooks(strWorkbookName).Worksheets(strsheetName)
firstRow = sourceSheet.UsedRange.Row
lastRow = sourceSheet.UsedRange.Rows.Count + firstRow - 1
index = 1
For i = firstRow To lastRow
sourceSheet.Rows(i).Copy
Select Case index Mod 6
Case 0:
strsheetName = "Sheet1"
Case 1:
strsheetName = "Sheet2"
Case 2:
strsheetName = "Sheet3"
Case 3:
strsheetName = "Sheet4"
Case 4:
strsheetName = "Sheet5"
Case 5:
strsheetName = "Sheet6"
End Select
Worksheets(strsheetName).Cells((index / 6) + 1, 1).Paste
index = index + 1
Next i
End Sub
FEW THINGS:
Do not create sheets in the begining. Create them in a loop if required. This way you will not end up with blank sheets if there are only say 3 rows of data. Create them in a loop.
Also the code below assumes that you do not have Sheet1-6 beforehand. Else you will get an error at newSht.Name = "Sheet" & i
Avoid the use of UsedRange to find the last row. You may want to see see Finding last used cell in Excel with VBA
CODE:
I have commneted the code. You should not have a problem understanding the code but if you do then simply post back. Is this what you are trying?
Option Explicit
'~~> Set max sheets required
Const NumberOfSheetsRequired As Long = 6
Public Sub CopyLines()
Dim wb As Workbook
Dim ws As Worksheet, newSht As Worksheet
Dim lastRow As Long
Dim StartRow As Long, EndRow As Long
Dim i As Long
Dim NumberOfRecordToCopy As Long
Dim strWorkbookName as String
'~~> Change the name as applicable
strWorkbookName = "TMG JULY 2020 RENTAL.xlsx"
Set wb = Workbooks(strWorkbookName)
Set ws = wb.Sheets("MainSheet")
With ws
If Not Application.WorksheetFunction.CountA(.Cells) = 0 Then
'~~> Find last row
lastRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Get the number of records to copy
NumberOfRecordToCopy = lastRow / NumberOfSheetsRequired
'~~> Set your start and end row
StartRow = 1
EndRow = StartRow + NumberOfRecordToCopy
'~~> Create relevant sheet
For i = 1 To NumberOfSheetsRequired
'~~> Add new sheet
Set newSht = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
newSht.Name = "Sheet" & i
'~~> Copy the relevant rows
ws.Range(StartRow & ":" & EndRow).Copy newSht.Rows(1)
'~~> Set new start and end row
StartRow = EndRow + 1
EndRow = StartRow + NumberOfRecordToCopy
'~~> If start row is greater than last row then exit loop.
'~~> No point creating blank sheets
If StartRow > lastRow Then Exit For
Next i
End If
End With
Application.CutCopyMode = False
End Sub
Your code creates 6 sheets before it does anything with the data, which might be wasteful.
Also, once these sheets are created, there are no guarantee that they will have the names Sheet1, Sheet2, etc. These names might have already been used. That is why you should always check if the destination sheet exists before attempting to create them.
Option Explicit
Public Sub CopyLines()
Dim firstRow As Long
Dim lastRow As Long
Dim i As Long
Dim index As Long
Dim strSheetName As String
Dim sourceSheet As Worksheet
Dim strWorkbookName As String
'assume the current workbook is the starting point
strWorkbookName = ActiveWorkbook.Name
'assume that the first sheet contains all the rows
strSheetName = ActiveWorkbook.Sheets(1).Name
Set sourceSheet = Workbooks(strWorkbookName).Worksheets(strSheetName)
firstRow = sourceSheet.UsedRange.Row
lastRow = sourceSheet.UsedRange.Rows.Count + firstRow - 1
index = 1
For i = firstRow To lastRow
sourceSheet.Rows(i).Copy
Select Case index Mod 6
Case 0:
strSheetName = "Sheet1"
Case 1:
strSheetName = "Sheet2"
Case 2:
strSheetName = "Sheet3"
Case 3:
strSheetName = "Sheet4"
Case 4:
strSheetName = "Sheet5"
Case 5:
strSheetName = "Sheet6"
End Select
'check if the destination sheet exists
If Not Evaluate("ISREF('" & strSheetName & "'!A1)") Then
'if it does not, then create it
Sheets.Add
'and rename it to the proper destination name
ActiveSheet.Name = strSheetName
End If
'now paste the copied cells using PasteSpecial
Worksheets(strSheetName).Cells(Int(index / 6) + 1, 1).PasteSpecial
'advance to the next row
index = index + 1
'prevent Excel from freezing up, by calling DoEvents to handle
'screen redraw, mouse events, keyboard, etc.
DoEvents
Next i
End Sub
Try the next code, please. It uses arrays and array slices and it should be very fast:
Sub testSplitRowsOnSixSheets()
Dim sh As Worksheet, lastRow As Long, lastCol As Long, arrRows As Variant, wb As Workbook
Dim arr As Variant, slice As Variant, SplCount As Long, shNew As Worksheet
Dim startSlice As Long, endSlice As Long, i As Long, Cols As String, k As Long
Const shtsNo As Long = 6 'sheets number to split the range
Set wb = ActiveWorkbook 'or Workbooks("My Workbook")
Set sh = wb.ActiveSheet 'or wb.Sheets("My Sheet")
lastRow = sh.Range("A" & rows.count).End(xlUp).row 'last row of the sheet to be processed
lastCol = sh.UsedRange.Columns.count 'last column of the sheet to be processed
arr = sh.Range(sh.Range("A2"), sh.cells(lastRow, lastCol)) 'put the range in an array
SplCount = WorksheetFunction.Ceiling_Math(UBound(arr) / shtsNo) 'calculate the number of rows for each sheet
Cols = "A:" & Split(cells(1, lastCol).Address, "$")(1) 'determine the letter of the last column
clearSheets wb 'delete previous sheets named as "Sheet_" & k
For i = 1 To UBound(arr) Step SplCount 'iterate through the array elements number
startSlice = i: endSlice = i + SplCount - 1 'set the rows number to be sliced
'create the slice aray:
arrRows = Application.Index(arr, Evaluate("row(" & startSlice & ":" & endSlice & ")"), _
Evaluate("COLUMN(" & Cols & ")"))
'insert a new sheet at the end of the workbook:
Set shNew = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.count))
shNew.Name = "Sheet_" & k: k = k + 1 'name the newly created sheet
If UBound(arr) - i < SplCount Then SplCount = UBound(arr) - i + 1 'set the number of rows having data
'for the last slice
shNew.Range("A2").Resize(SplCount, lastCol).value = arrRows 'drop the slice array at once
Next i
End Sub
Sub clearSheets(wb As Workbook)
Dim ws As Worksheet
For Each ws In wb.Worksheets
If left(ws.Name, 7) Like "Sheet_#" Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
Next
End Sub
Try this following code. It streams through data and adds sheets dynamically, renames them according to the row# , copies the headers from the first row and the data block needed.
Public Sub DistributeData()
Const n_sheets As Long = 6
Dim n_rows_all As Long, n_cols As Long, i As Long
Dim r_data As Range, r_src As Range, r_dst As Range
' First data cell is on row 2
Set r_data = Sheet1.Range("A2")
' Count rows and columns starting from A2
n_rows_all = Range(r_data, r_data.End(xlDown)).Rows.Count
n_cols = Range(r_data, r_data.End(xlToRight)).Columns.Count
Dim n_rows As Long, ws As Worksheet
Dim n_data As Long
n_data = n_rows_all
' Get last worksheet
Set ws = ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets().Count)
Do While n_data > 0
' Figure row count to copy
n_rows = WorksheetFunction.Min(WorksheetFunction.Ceiling_Math(n_rows_all / n_sheets), n_data)
' Add new worksheet after last one
Set ws = ActiveWorkbook.Worksheets.Add(, ws, , XlSheetType.xlWorksheet)
ws.Name = CStr(n_rows_all - n_data + 1) & "-" & CStr(n_rows_all - n_data + n_rows)
' Copy Headers
ws.Range("A1").Resize(1, n_cols).Value = _
Sheet1.Range("A1").Resize(1, n_cols).Value
' Skip rows from source sheet
Set r_src = r_data.Offset(n_rows_all - n_data, 0).Resize(n_rows, n_cols)
' Destination starts from row 2
Set r_dst = ws.Range("A2").Resize(n_rows, n_cols)
' This copies the entire block of data
' (no need for Copy/Paste which is slow and a memory hog)
r_dst.Value = r_src.Value
' Update remaining row count to be copied
n_data = n_data - n_rows
' Go to next sheet, or wrap around to first new sheet
Loop
End Sub
Do not use Copy/Paste as it is slow and buggy. It is always a good idea to directly write from cell to cell the values. You can do that for an entire table of cells (multiple rows and columns) with one statement like in the example below:
ws_dst.Range("A2").Resize(n_rows,n_cols).Value = _
ws_src.Range("G2").Resize(n_rows,n_cols).Value
Sub split()
On Error Resume Next
Application.DisplayAlerts = False
Dim aws As String
Dim ws As Worksheet
Dim wb As Workbook
Dim sname()
sname = Array("one", "two", "three", "four", "five", "six")
aws = ActiveSheet.Name
For Each ws In Worksheets
If ws.Name = "one" Then ws.Delete
If ws.Name = "two" Then ws.Delete
If ws.Name = "three" Then ws.Delete
If ws.Name = "four" Then ws.Delete
If ws.Name = "five" Then ws.Delete
If ws.Name = "six" Then ws.Delete
Next ws
lr = (Range("A" & Rows.Count).End(xlUp).Row) - 1
rec = Round((lr / 6), 0)
Set ws = ActiveSheet
f = 1
t = rec + 1
i = 1
While i <= 6
Sheets.Add.Name = sname(i - 1)
Sheets(aws).Select
If i = 6 Then
Range("A" & (f + 1), "A" & (lr + 1)).Select
Else
Range("A" & (f + 1), "A" & t).Select
End If
Selection.Copy
Sheets(sname(i - 1)).Select
Range("A2").Select
ActiveSheet.Paste
Cells(1, 1).Value = ws.Range("A1").Value
f = f + rec
t = t + rec
i = i + 1
Wend
End Sub

if then till last row

I want that if cell in column e is not blank but cell in column i is blank then write unregister in column i or else write what ever written in column i.
Please help - I have used below code:
Sub Simple_If()
Dim lastrow As Long
lastrow = Cells(Rows.Count, "F").End(xlUp).Row
If Range("e2:e" & lastrow).Value <> "" And Range("i2:i" & lastrow).Value = "" Then
Range("i2:i" & lastrow).Value = "unregister"
End If
End Sub
The reason your code was not working is because you can't get .value of a .range (Range("e2:e" & lastrow).Value <> ""). Instead, use a for loop to iterate through each cells value individually.
I have commented each line of the code below to help you understand what is happening.
To make this work, change SO.xlsm to the name of your workbook and 63649177 to the name of your worksheet.
Sub Simple_If()
Dim WB As Workbook ' workbook - full name of the file containing data.
Dim WS As Worksheet ' worksheet - worksheet within workbook containing data.
Dim lRow As Long ' last row - find last row containing data
Dim i As Long ' iteration - used for loop
Set WB = Workbooks("SO.xlsm") ' set the name of the workbook here
Set WS = WB.Worksheets("63649177") ' set the name of the worksheet here
lRow = WS.Cells(WS.Rows.count, "E").End(xlUp).Row ' find the last row of E in the WS object, not user defined.
Set Rng = WS.Range("E2:E" & lRow) ' set the initial range
For i = 2 To lRow ' from line 2 to the last row, repeat this loop
If WS.Range("E" & i).Value <> "" And WS.Range("I" & i).Value = "" Then ' if E contains data and I does not then
WS.Range("I" & i).Value = "unregister" ' fill cell with "unregister"
End If ' end if
Next ' cycle through next iteration of loop
End Sub
Output
Loop Through Rows
You were trying to check the values of two ranges "E2:E & LastRow" and "I2:I & LastRow" in one go, but you cannot do that. You have to loop through the rows of the ranges and check each cell i.e. "E2", "E3", "E4" ... "E" & LastRow and "I2", "I3", "I4" ... "I" & LastRow. For this task a For Next loop can used.
The 1st code is showing how it is done using Range.
The 2nd code is showing how it is done using column strings (letters) with Cells.
The 3rd code is showing how it is done using column numbers with Cells.
The 4th code is showing how you can define the column ranges (rng1, rng2) and use Cells with one parameter.
The 5th code is showing how you can define constants to store the so called 'magic' characters and later quickly access (change) them. It is also modified to be able to change the resulting column (tgtCol).
Range might seem easier, but you have to learn Cells, too, e.g. because you cannot loop through columns using Range, you have to use column numbers with Cells.
Study the first three codes closely, and you will learn the differences soon enough.
The Code
Option Explicit
Sub fillSimpleRangeVersion()
' Calculate the last non-blank cell in column "F".
Dim LastRow As Long
LastRow = Range("F" & Rows.Count).End(xlUp).Row
Dim i As Long
' Loop through the rows from 2 to LastRow.
For i = 2 To LastRow ' i will change: "2, 3, 4 ... LastRow"
' Check that current cell in column "E" is not blank and
' that current cell in column "I" is blank:
' If not E2 blank and I2 blank then,
' If not E3 blank and I3 blank then ...
' If not E & LastRow blank and I & LastRow blank then.
If Not IsEmpty(Range("E" & i)) And IsEmpty(Range("I" & i)) Then
' If true, write "unregister" to current cell in column "I".
Range("I" & i).Value = "unregister"
' The Else statement is not needed, because you only write when
' the condition is true.
Else
' If not true, do nothing.
End If
Next i
End Sub
Sub fillSimpleCellsStringsVersion() ' Column Strings E, F, I
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
Dim i As Long
For i = 2 To LastRow
If Not IsEmpty(Cells(i, "E")) And IsEmpty(Cells(i, "I")) Then
Cells(i, "I").Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsNumbersVersion() ' Column Numbers 5, 6, 9
Dim LastRow As Long
LastRow = Cells(Rows.Count, 6).End(xlUp).Row
Dim i As Long
For i = 2 To LastRow
If Not IsEmpty(Cells(i, 5)) And IsEmpty(Cells(i, 9)) Then
Cells(i, 9).Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsVersionWithRanges()
Dim LastRow As Long
LastRow = Cells(Rows.Count, "F").End(xlUp).Row
Dim rng1 As Range
Set rng1 = Range("E2:E" & LastRow)
Dim rng2 As Range
Set rng2 = Range("I2:I" & LastRow)
Dim i As Long
For i = 1 To rng1.Rows.Count
If rng1.Cells(i).Value <> "" And rng2.Cells(i).Value = "" Then
rng2.Cells(i).Value = "unregister"
End If
Next i
End Sub
Sub fillSimpleCellsExpanded()
Const FirstRow As Long = 2 ' First Row
Const LastRowCol As Variant = "F" ' The column to Calculate Last Row
Const Col1 As Variant = "E" ' Column 1
Const Col2 As Variant = "I" ' Column 2
Const tgtCol As Variant = "I" ' Target Column, the Column to Write to
' You want to write to the same column "CritCol2 = tgtCol", but if you
' want to write to another column, you can easily change "tgtCol".
Const Criteria As String = "unregister" ' Write Criteria
Dim LastRow As Long
LastRow = Cells(Rows.Count, LastRowCol).End(xlUp).Row
Dim i As Long
For i = FirstRow To LastRow
If Not IsEmpty(Cells(i, Col1)) And IsEmpty(Cells(i, Col2)) Then
Cells(i, tgtCol).Value = Criteria
Else
' The following line is only needed if "CritCol2" is different
' than "tgtCol".
Cells(i, tgtCol).Value = Cells(i, Col2).Value
End If
Next i
End Sub

Excel Macro - Fetching the values of one column based on the values from other column

I need a macro to write the row values present in column A if there is a value present in column B .
For example :
Column A Column B
Arjun
Arun 12
For the above example, I need a macro which can write "Arun 12" in Sheet2 of the work book with the Headers "Name" and "Hours".Before this the macro should clear the data present in Sheet two completely.
This will copy the all rows of columns A and B from Sheet1 to Sheet2 if B is not a Null string. And also will add the headers "Name" and "Hours".
Option Explicit 'requires that every variable has to be defined before use, e.g. with a Dim statement.
Sub DoStuff_GoodPractice()
Dim lastRowSrc As Long, lastRowDest As Long, i As Long 'declare row counts as Long so all rows can be used
Dim shtSource As Worksheet, shtDestination As Worksheet
Set shtSource = ThisWorkbook.Worksheets("Sheet1") 'full qualified identification of the worksheets
Set shtDestination = ThisWorkbook.Sheets("Sheet2")
lastRowSrc = shtSource.Range("A" & shtSource.Rows.Count).End(xlUp).Row 'determine the last used row
'clear destination sheet and write headers:
shtDestination.Cells.Clear
shtDestination.Range("A1").Value = "Name"
shtDestination.Range("B1").Value = "Hours"
lastRowDest = 1 'start with row 1 as destination
For i = 1 To lastRowSrc 'loop through all used rows
If shtSource.Range("A" & i).Value <> vbNullString And _
shtSource.Range("B" & i).Value <> vbNullString Then 'check if cells are not a null string
shtSource.Range("A" & i & ":B" & i).Copy Destination:=shtDestination.Range("A" & lastRowDest + 1) 'copy current row
lastRowDest = lastRowDest + 1 'jump to the last used row in destination
End If
Next i
End Sub
This should accomplish what you're after.
Sub DoStuff()
Dim lastRow As integer, lastRowSheet2 As integer, i As Integer
Dim sheet1 As WorkSheet, sheet2 As Worksheet
Set sheet1 = Sheets("Sheet1")
Set sheet2 = Sheets("Sheet2")
lastRow = sheet1.Range("A" & Rows.Count).End(xlUp).Row
sheet2.Cells.Clear
For i = 1 To lastRow
If sheet1.Range("A" & i).Value <> "" And sheet1.Range("B" & i).Value <> "" then
lastRowSheet2 = sheet2.Range("A" & Rows.Count).End(xlUp).Row
sheet1.Range("A" & i & ":B" & i).Copy Destination:= sheet2.Range("A" & lastRowSheet2 + 1)
End If
Next i
End Sub

Resources