Copy and paste nested loop in excel - vba

I want to loop through 8 columns(A-H) in sheet 1 to make one new column in sheet 2. Then loop through 8 columns again(I-P) and make column B in sheet 2. I have do this for a lot of data and think this would be the best way to do it
here is my code
Range("E5").Select
Range(Selection, Selection.End(xlDown)).Select
Range("E5").Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWindow.SmallScroll Down:=-96
Range("E5:E110").Select
Selection.Copy
Sheets("56 J").Select
Range("A2").Select
ActiveSheet.Paste
Sheets("56 g").Select
Range("F5").Select
Range(Selection, Selection.End(xlDown)).Select
Range("F5").Select
Range(Selection, Selection.End(xlDown)).Select
ActiveWindow.SmallScroll Down:=-96
Range("F5:F110").Select
Selection.Copy
Sheets("56 J").Select
Range("A110").Select
ActiveSheet.Paste
Sheets("56 g").Select
any idea how I can put this in something that loops through the columns?
This is an example of what I am trying to do.I would also like to have the time and letter stay with the corresponding data when it loops. But my main focus right now is just getting the data into a single column.

You should be able to loop through the source and destination columns with a little maths.
Dim c As Long, n As Long, tws As Worksheet
Set tws = Worksheets("56 j")
With Worksheets("56 g")
For n = 1 To 2
For c = 1 To 8
With .Range(.Cells(5, c + (n - 1) * 8), .Cells(.Rows.Count, c + (n - 1) * 8).End(xlUp))
tws.Cells(tws.Rows.Count, n).End(xlUp).Offset(1, 0).Resize(.Rows.Count, .Columns.Count) = .Value
End With
Next c
Next n
End With

Option Explicit
Sub copydata()
Dim WS1, WS2 As Worksheet
Dim lastrow As Long
Dim ws1Row, ws2Row As Long
Dim mycol As Integer
Set WS1 = Worksheets("sheet1")
Set WS2 = Worksheets("sheet2")
lastrow = WS1.Cells(WS1.Rows.Count, "A").End(xlUp).Row
ws2Row = 2
For ws1Row = 5 To lastrow
For mycol = 1 To 8
WS2.Cells(ws2Row, 1) = WS1.Cells(ws1Row, mycol)
WS2.Cells(ws2Row, 2) = WS1.Cells(ws1Row, mycol + 8)
ws2Row = ws2Row + 1
Next mycol
Next ws1Row
End Sub

Related

How can I simplify using active cell / copy / paste to transfer data between sheet?

I am trying to transfer the data from sheet one to sheet two and combined the information on the second sheet. The code I have listed below works, but it seems very inefficient. I am trying to improve by VBA abilities and would love to here ways to shrink my code down, make it more efficient, and still achieve the same goal. Thanks for any help you can provide.
Sheet 1
Sheet 2
Sub batchorder()
Dim Pname As String
Dim Lplace As String
Dim numsld As Long
Dim rating As Integer
Dim lastrow As Long
Dim i As Long
Dim openc As Long
lastrow = Range("A" & Rows.Count).End(xlUp).Row
Range("A1").Select
For i = 1 To lastrow
If Cells(i, 1).Value <> "" Then
'Copy name to sheet 2
Cells(i, 1).Select
ActiveCell.Offset(0, 1).Select
Selection.Copy
Sheets("Sheet2").Select
Range("A1").Select
'Find the next open cell to paste to
Selection.End(xlDown).Select
Selection.End(xlDown).Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
'Copy place to sheet 2
ActiveCell.Offset(1, 0).Select
Selection.Copy
Sheets("Sheet2").Select
Range("B1").Select
'Find the next open cell to paste to
Selection.End(xlDown).Select
Selection.End(xlDown).Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
'Copy sold to sheet 2
ActiveCell.Offset(1, 0).Select
Selection.Copy
Sheets("Sheet2").Select
Range("C1").Select
'Find the next open cell to paste to
Selection.End(xlDown).Select
Selection.End(xlDown).Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
'Copy rating to sheet 2
ActiveCell.Offset(1, 0).Select
Selection.Copy
Sheets("Sheet2").Select
Range("D1").Select
'Find the next open cell to paste to
Selection.End(xlDown).Select
Selection.End(xlDown).Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
Sheets("Sheet1").Select
i = i + 3
Else
End If
Next i
End Sub
Sub batchorder()
Dim Row As Long
Dim i As Long
' These two lines speed up evrything ENORMOUSLY.
' But you need the lines at the end too
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Row = Sheet2.UsedRange.Rows.Count ' Row is nr of last row in sheet
While Application.CountA(Sheet2.Rows(Row)) = 0 And Row > 1
Row = Row - 1 ' skip empty rows at the end if present
Wend
For i = 1 To Sheet1.UsedRange.Rows.Count
If Sheet1.Cells(i, 1).Value <> "" Then
Sheet2.Cells(Row, 1).FormulaLocal = Sheet1.Cells(i, 2).FormulaLocal
Sheet2.Cells(Row, 2).FormulaLocal = Sheet1.Cells(i + 1, 2).FormulaLocal
Sheet2.Cells(Row, 3).FormulaLocal = Sheet1.Cells(i + 2, 2).FormulaLocal
Sheet2.Cells(Row, 4).FormulaLocal = Sheet1.Cells(i + 3, 2).FormulaLocal
i = i + 3
Row = Row + 1
End If
Next
' Restore Excel to human state.
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
You should basically never use the select statement, it gets everything really messy quickly. Here's a basic combiner of mine. Just added the If statement to check whether the cell and in this case row is empty.
This should work but more importantly try to understand what it does to learn. I gave it some comments.
Sub batchorder()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
' Just habits, but doing this here means that I won't have to write anything else than ws1 and ws2 in the future
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
Dim lastrowWs1 As Long
Dim j As Long
' first row after ws2 headers
j = 2
' With statement to make the code nicer also ".something" now means ws1.something
With ws1
' Bob Ulmas method -- just a personal preference to find the last row.
lastrowWs1 = .Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
For i = 1 To lastrowWs1
' Check if the cell is not empty
If Not .Cells(i, 1) = vbNullString Then
'Basically range.value = other_range.value
ws2.Range(ws2.Cells(j, 1), ws2.Cells(j, 4)).Value = WorksheetFunction.Transpose(.Range(.Cells(i, 2), .Cells(i + 3, 2)).Value)
' step 3 forward as the amount of rows per record was 4
i = i + 3
' go to next row for worksheet 2
j = j + 1
End If
Next i
End With
End Sub

Excel VBA: AutoFill Column Down Without Preset Range

How do i get Auto-fill to automatically detect the next new ID# to duplicate in the following line without having to tell/ set the excel range where the next ID# would start?
Below is the formula.
Sub NewTestRow()
Application.ScreenUpdating = False
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Dim LRow As Long
Set copySheet = Worksheets("Sheet1")
Set pasteSheet = Worksheets("Sheet2")
copySheet.Range("E3:K500").Copy
pasteSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
LRow = ActiveSheet.Cells(Sheets("Sheet2").Rows.Count, "A").End(xlUp).Row
Cells(2, 1).Select
Selection.Copy
ActiveSheet.Range(Cells(3, 1), Cells(LRow, 1)).Select
ActiveSheet.Paste
copySheet.Range("M3:S500").Copy
pasteSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
[EXAMPLE FORMAT IMAGE]
This code cycles through cells in the first column, and checks that it is the same as the proceeding cell in the first column. Also, I'd change "LRow =" to a better way of finding the last row, just in case there are any gaps in your data.
LRow = ActiveSheet.Cells(Sheets("Sheet2").Rows.Count, "A").End(xlUp).Row
i = 2
' --- low
While i < LRow
If ActiveSheet.Cells(i, 1) = ActiveSheet.Cells(i + 1, 1) Then
' --- new ID not found, increment to next row
i = i + 1
ElseIf
' --- Put whatever code you want to fire when a new ID is found
NewIDFound = i + 1
End If
Wend

How to add a loop with a counter in vba

I have a column of IDs in an Excel worksheet called Sheet1. I have data that corresponds to the IDs in columns to the right of Column A. The amount of cells in a row varies. For example:
A, B, C, D, E, F, ...
John, 5, 10, 15, 20
Jacob, 2, 3
Jingleheimmer, 5, 10, 11
I'm trying to copy that data into a new worksheet, Sheet5, in the following format:
A, B, C, D, E, F, ...
John, 5
John, 10
John, 15
John, 20
Jacob, 2
Jacob, 3
Jingleheimmer, 5
Jingleheimmer, 10
Jingleheimmer, 11
I wrote the following code that copies over the first two IDs. I could continue to copy paste the second half of the code and just change the cells, however, I have 100s of IDs. This would take too long. I think whenever a process is repeated I should be using a loop. Can you help me turn this repetitive code into a loop?
Sub Macro5()
Dim LastRowA As Integer
Dim LastRowB As Integer
''' Process of copying over first ID '''
'grab all data cells in B2 to the right
With Sheets("Sheet1").Select
Range("B2", Range("B2").End(xlToRight)).Select
Selection.Copy
End With
'paste that data into the first empty cell of Column B in Sheet5
With Sheets("Sheet5").Select
Range("B1").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
End With
'grab the corresponding ID in cell A2
With Sheets("Sheet1").Select
Range("A2").Select
Application.CutCopyMode = False
Selection.Copy
End With
'paste the corresponding ID into the first empty cell of Column A in Sheet5
With Sheets("Sheet5").Select
LastRowB = Cells(Rows.Count, "B").End(xlUp).Row
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Selection.AutoFill Destination:=Range("A1:A" & LastRowB)
End With
''' Repeat that process for each row in Sheet1 '''
'grab all data cells in B3 to the right
With Sheets("Sheet1").Select
Range("B3", Range("B3").End(xlToRight)).Select
Selection.Copy
End With
'paste that data into the first empty cell of Column B in Sheet5
With Sheets("Sheet5").Select
LastRowB = Cells(Rows.Count, "B").End(xlUp).Row
Range("B" & LastRowB + 1).Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
End With
'grab the corresponding ID in cell A3
With Sheets("Sheet1").Select
Range("A3").Select
Application.CutCopyMode = False
Selection.Copy
End With
'paste the corresponding ID into the first empty cell of column A in Sheet5
'and autofill down to the last populated cell in column B
With Sheets("Sheet5").Select
LastRowA = Cells(Rows.Count, "A").End(xlUp).Row + 1
Range("A" & LastRowB + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
LastRowB = Cells(Rows.Count, "B").End(xlUp).Row
Selection.AutoFill Destination:=Range("A" & LastRowA & ":A" & LastRowB)
End With
End Sub
Try this:
Sub test()
Dim i As Integer
Dim j As Integer
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim nRow As Integer
Dim lRow As Integer
Dim lCol As Integer
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet5")
nRow = 1
With ws1
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 1 To lRow
lCol = .Cells(i, .Columns.Count).End(xlToLeft).Column
For j = 2 To lCol
ws2.Cells(nRow, 1).Value = .Cells(i, 1).Value
ws2.Cells(nRow, 2).Value = .Cells(i, j).Value
nRow = nRow + 1
Next j
Next i
End With
End Sub
It runs through each row in the sheet one at a time, copying over the names and associated numbers up through the last column with values in that row. Should work very quickly and doesn't require constant copy & pasting.
This should do what you're looking for.
Sub test()
Dim lastrow As Long, lastcol As Long
Dim i As Integer, j as Integer, x as Integer
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet5")
lastrow = ws1.Cells(Rows.Count, "A").End(xlUp).Row
x = 1
With ws1
For i = 1 To lastrow
lastcol = .Cells(i, .Columns.Count).End(xlToLeft).Column
For j = 2 To lastcol
ws2.Cells(x, 1).Value = .Cells(i, 1).Value
ws2.Cells(x, 2).Value = .Cells(i, j).Value
x = x + 1
Next j
Next i
End With
End Sub

loop through cells and copy data to the next 5 cells if there is data

good afternoon,
I have a worksheet where I need a macro to copy the value from D1 and paste it to the next 5 cells (paste it to E1:I1), then if the next cell has data (J1) copy it and paste it to the next five cells etc. until the next cell is blank (the problem is that every time this spreadsheet has a different number of columns). I did try to do this with macro recorder but I have to set every time the cells that I want to copy the data from and the cells that I will paste them to. There must be an easier way than this, any help would be appreciated.
Range("D1").Select
Selection.Copy
Range("E1:I1").Select
ActiveSheet.Paste
Range("J1").Select
Application.CutCopyMode = False
Selection.Copy
Range("K1").Select
ActiveWindow.SmallScroll ToRight:=10
Range("K1:O1").Select
ActiveSheet.Paste
Range("P1").Select
Application.CutCopyMode = False
Selection.Copy
Range("Q1:U1").Select
ActiveSheet.Paste
Range("V1").Select
Application.CutCopyMode = False
Selection.Copy
ActiveWindow.SmallScroll ToRight:=12
Range("W1").Select
ActiveSheet.Paste
Range("X1:AA1").Select
ActiveSheet.Paste
Range("AB1").Select
Application.CutCopyMode = False
Selection.Copy
Range("AC1:AG1").Select
ActiveSheet.Paste
ActiveWindow.SmallScroll ToRight:=8
Range("AH1").Select
Application.CutCopyMode = False
Selection.Copy
Range("AI1:AM1").Select
ActiveSheet.Paste
Range("AN1").Select
Application.CutCopyMode = False
Selection.Copy
Range("AO1:AS1").Select
ActiveSheet.Paste
Consider the following to first find the last column in spreadsheet and iterate every 5 columns using Cells(r, c) reference for numbering:
Sub CopyNextFive()
LastColumn = ActiveSheet.UsedRange.Columns(ActiveSheet.UsedRange.Columns.Count).Column
For i = 4 To LastColumn Step 6
Cells(1, i).Copy
Range(Cells(1, i + 1), Cells(1, i + 5)).PasteSpecial xlPasteAll
Next i
Application.CutCopyMode = False
End Sub
I would do this by using RC notation and looping something like this:
dim myValue
dim c as integer
dim x as integer
c=4 'Start in column D
myValue = cells(1,c).value 'Row 1 of column D
while myValue <> ""
for x = 1 to 5
cells(1,c+x).value=myValue
next x
c=c+x+1 'To give us the 10th column: J
myValue = cells(1,c).value
wend
Sub mySub()
Dim src As Range: Set src = ActiveSheet.Range("D1")
Dim dest As Range: Set dest = ActiveSheet.Range("E1:I1")
Do Until Trim(src.Text) = vbNullString
src.Copy dest
Set src = src.Offset(, 6): Set dest = dest.Offset(, 6)
Loop
End Sub
You'd need to run some form of loop. There are several kinds: For ... Next, Do Until ..., etc. Have a read about them (http://www.excelfunctions.net/VBA-Loops.html) and you'll see they give you great versatility.
In your case, one of many solutions could be as follows:
' Adjust these values to suit
Const SHEET_NAME As String = "Sheet1" 'name of sheet
Const START_COLUMN As String = "D" 'column letter where routine starts
Const ROW_NUM As Long = 1 'row number of your data
Const COPY_SIZE As Integer = 5 'number of columns to copy the data
Dim rng As Range
' The looping routine
Set rng = ThisWorkbook.Worksheets(SHEET_NAME).Cells(ROW_NUM, START_COLUMN)
Do Until IsEmpty(rng)
rng.Offset(, 1).Resize(, COPY_SIZE) = rng.Value2
Set rng = rng.Offset(, COPY_SIZE + 1)
Loop

Find some value in a different worksheet

I'm trying to read every line in one sheet (Get_Command) and looking for the value in the first column in an another sheet (Command_List); if this value is in the Command_List I want to copy the line (deleting some columns) to a third sheet (Set_Command).
Sub Macro1()
'
' Macro1 Macro
'
Dim fnFormat As Range
Dim c As Long
Dim MyCol As Long
Dim fCommand As Range
Dim Command As String
With Sheets("Get_Command")
.Select
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
For Lrow = 1 To Lastrow Step 1
Command = Cells(Lrow, 1).Value
Set fCommand = Worksheets("Command_List").Columns("A:A").Find(Command, LookIn:=xlValues)
If Not fCommand Is Nothing Then
Lastcolumn = .Cells(Lrow, .Columns.Count).End(xlToLeft).Column
Range("A" & Lrow).Select
Selection.Copy
Sheets("Set_Command").Select
Range("A" & Lrow).Select
ActiveSheet.Paste
ActiveSheet.Columns("A").Replace What:="Get:", Replacement:="Set", LookAt:=xlPart, SearchOrder:=xlByColumns
Application.CutCopyMode = False
Sheets("Get_Command").Select
Set fnFormat = Range(Cells(Lrow, 5), Cells(Lrow, Lastcolumn)).Find("nFormat", LookIn:=xlValues)
If fnFormat Is Nothing Then 'If it is not found
c = 1
For Lcolumn = 5 To Lastcolumn Step 2
Cells(Lrow, Lcolumn).Select
Selection.Copy
Sheets("Set_Command").Select
c = c + 1
Cells(Lrow, c).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Sheets("Get_Command").Select
Next Lcolumn
Else
c = 1
'It should remove "(", ")", "," and the columns that a don't need
For Lcolumn = 5 To fnFormat.Column - 3 Step 2
Cells(Lrow, Lcolumn).Select
Selection.Copy
Sheets("Set_Command").Select
c = c + 1
Cells(Lrow, c).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Sheets("Get_Command").Select
Next Lcolumn
For Lcolumn = fnFormat.Column + 3 To Lastcolumn Step 2
Cells(Lrow, Lcolumn).Select
Selection.Copy
Sheets("Set_Command").Select
c = c + 1
Cells(Lrow, c).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Sheets("Get_Command").Select
Next Lcolumn
End If
End If
Next Lrow
End With
End Sub
The problem is on:
Command = Cells(Lrow, 1).Value
Set fCommand = Worksheets("Command_List").Columns("A:A").Find(Command, LookIn:=xlValues)
The Command is saving what I want, but fCommand is returning always Nothing.
Could someone help me to find my error?
Thanks! =)
Find returns Nothing when it does not find a matchin cell. So you have problem with the data that you are using. Potential source for your problem:
there are leading or trailing spaces in your command or in the list of possible commands
you are referencing the wrong range in Find