Displaying merged cell data in a For loop - excel

I'm trying to display the contents of a merged cell in a For loop in Excel using VBA.
I have the a worksheet with very simple data in it
Here is my code:
'finding last record in my initial list
sheet_last_row = Sheets("mylist").Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To sheet_last_row
last_row = Sheets("results").Cells(Rows.Count, 1).End(xlUp).Row
If Sheets("mylist").Cells(i, 1).Value = 2 Then
'test if cell is merged
If Sheets("mylist").Cells(i, 2).MergeCells Then
RowCount = Sheets("mylist").Cells(i, 2).Value
End If
Sheets("mylist").Cells(i, 1).EntireRow.Copy Sheets("results").Cells(last_row + 1, 1)
End If
Next i
I'm getting the following result with this code;
I'm new at this. Can anyone show me how to make this work.

You could try:
Option Explicit
Sub test()
Dim LastRowA As Long, LastRowB, LastRowC As Long, LastRowE As Long, MaxRow As Long
Dim cell As Range, rng As Range
With ThisWorkbook.Worksheets("Sheet1")
'Find the lastrow for all the available columns
LastRowA = .Cells(.Rows.Count, "A").End(xlUp).Row
LastRowB = .Cells(.Rows.Count, "B").End(xlUp).Row
LastRowC = .Cells(.Rows.Count, "C").End(xlUp).Row
'Get the longer last row in order to avoid losing data if the last cell of a column is merge or empty
MaxRow = WorksheetFunction.Max(LastRowA, LastRowB, LastRowC)
'Set the area to loop
Set rng = .Range("A2:C" & MaxRow)
'Start looping
For Each cell In rng
'If the cell is merger
If cell.MergeCells Then
'Find the last row of column E
LastRowE = .Cells(.Rows.Count, "E").End(xlUp).Row
'Paste cell value in column E
.Range("E" & LastRowE + 1).Value = cell.Value
'Paste cell address in column F
.Range("F" & LastRowE + 1).Value = cell.Address
End If
Next
End With
End Sub
Results:

Related

How to loop this data in VBA?

I have a worksheet (first row headers) where the 3 last columns are as follows: Component 1(column AW), Component 2 (AX) and Number of Components (AY). Number of components value is either 1 or 2. If "Number of components" is 2 then I would like to copy the entire row and paste it twice to the last row of the same worksheet.
If "Number of components"is 1 then I would only like to copy it once.
Earlier there is also a column M that contains the article number and for each copied row I would like the value in column M to be replaced by the value from the corresponding row of column Component 1 / Component 2.
For example in this row the article number in column M is x. As "Number of components" is 2, I would like this whole row to be pasted twice to the last row of the worksheet. By the first time it is pasted, I need column M value to be replaced by 205334 (Component 1 value) and when it is pasted second time I need column M value to be replaced by 96423 (Component 2 value). Is it possible to loop this way? The worksheet has more than a 1000 rows.
I have written the following code to do the copy/paste part, however I'm having trouble to replace the value from Column M with the value from Columns Component 1 and 2.
Dim lastcol As Range
Dim lColumn As Long
Dim lRow As Long
Dim i As Long
lColumn = Cells(1, Columns.Count).End(xlToLeft).Column
Set lastcol = Cells(2, lColumn)
For i = 2 To Rows.Count
If lastcol.Value = 2 Then
Cells(i, lColumn).EntireRow.Select
Selection.Copy Sheets("Filtersets Database (2)").Range("A" & Rows.Count).End(xlUp).Offset(1)
Cells(i, lColumn).EntireRow.Select
Selection.Copy Sheets("Filtersets Database (2)").Range("A" & Rows.Count).End(xlUp).Offset(1)
Cells(i, lColumn).EntireRow.Select
ElseIf lastcol.Value = 1 Then
Cells(i, lColumn).EntireRow.Select
Selection.Copy Sheets("Filtersets Database (2)").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next i
Thank you in advance!
This should do what you want.
Option Explicit
Sub CopySomeThings()
Dim ws As Worksheet
Dim rngDst As Range
Dim lastcol As Long
Dim lastrow As Long
Dim i As Long
Set ws = ActiveSheet ' Sheets("Filtersets Database (2)")
lastrow = ws.Range("A" & Rows.Count).End(xlUp).Row
lastcol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set rngDst = ws.Range("A" & lastrow + 1)
For i = 2 To lastrow
With ws
If .Cells(i, lastcol).Value = 2 Then
.Rows(i).Copy rngDst
.Cells(rngDst.Row, "M").Value = .Cells(i, lastcol - 2)
Set rngDst = rngDst.Offset(1)
.Rows(i).Copy rngDst
.Cells(rngDst.Row, "M").Value = .Cells(i, lastcol - 1)
Set rngDst = rngDst.Offset(1)
ElseIf .Cells(i, lastcol) = 1 Then
.Rows(i).Copy rngDst
.Cells(rngDst.Row, "M").Value = .Cells(i, lastcol - 2)
Set rngDst = rngDst.Offset(1)
End If
End With
Next i
End Sub

Filter & Delete Rows for the particular Column having specific value in Row 1 (Header)

I have a below code which find the particular value in cell, if that cell is having the value it will delete that row.
Sub FindDeleteBis()
Dim sh As Worksheet, lastRow As Long, rngDel As Range, i As Long
Set sh = ActiveSheet 'use here your sheet
lastRow = sh.Range("A" & Rows.count).End(xlUp).Row
For i = 1 To lastRow
Select Case sh.Range("A" & i).value
Case "ca-cns", "ca-dtc", "ca-ext", "ca-ns", "ca-ssbo" 'add here whatever string you need
If rngDel Is Nothing Then
Set rngDel = sh.Range("A" & i)
Else
Set rngDel = Union(rngDel, sh.Range("A" & i))
End If
End Select
Next
If Not rngDel Is Nothing Then rngDel.EntireRow.Delete
End Sub
But the above code works well when there are limited rows (10K), but when I want to delete 40K rows from 140K it's taking time.
How can we reduce the time?
Note: The above code works only if the particular values are in column A, I would like to have a solution where the column is selected on the basis of Value in Header (Row 1). The heading for the particular column will be "Stream"
Try this code, please. It will find a header name "Stream" for the column containing the strings to be used and do the job only if such a string header exists. The code is commented and I hope it will do what (I understood) it should:
Sub FindDeleteBisMarkedColumn()
Dim sh As Worksheet, arr As Variant, rng As Range, rngDel As Range
Dim lastRow As Long, lastCol As Long, colSort As Range, colS As Long
Set sh = ActiveSheet 'use here your sheet to be processed
lastCol = sh.Cells(1, Columns.count).End(xlToLeft).Column 'last column based on the first row
'Finding the column to be sorted (the one containing the header "Stream":_____________________________________
Set colSort = sh.Range(sh.Range("A1"), sh.Cells(1, lastCol)).Find("Stream") 'the cell keeping the "Stream" header
If colSort Is Nothing Then MsgBox "A column header named ""Stream"" must exist in the first row..." & vbCrLf & _
"It is used to determine the column where the search data exists.": Exit Sub
'_____________________________________________________________________________________________________________
colS = colSort.Column 'column number of the column to be sorted
lastRow = sh.Cells(Rows.count, colS).End(xlUp).Row 'last row calculated for column to be sorted
'Create a new column to reorder the range after sorting________________________________________________________
sh.Cells(1, lastCol + 1).value = "SortOrder"
sh.Cells(2, lastCol + 1).value = 1: sh.Cells(3, lastCol + 1).value = 2 'set the list elements to be filled down
sh.Range(sh.Cells(2, lastCol + 1), sh.Cells(3, lastCol + 1)).AutoFill _
Destination:=sh.Range(sh.Cells(2, lastCol + 1), sh.Cells(lastRow, lastCol + 1))
'_______________________________________________________________________________________________________________
Set rng = sh.Range(sh.Range("A1"), sh.Cells(lastRow, lastCol + 1)) 'define the whole range to be processed
arr = Array("ca-cns", "ca-dtc", "ca-ext", "ca-ns", "ca-ssbo") 'the array keeping the string to be used
rng.Sort Key1:=colSort, Order1:=xlAscending, Header:=xlYes 'sorting based on the 'colSort' range
Dim El As Variant, i As Long, j As Long, firstAddr As String
Dim lastAddr As String, boolFound As Boolean, iNew As Long
For Each El In arr 'iterate between each conditions array elements
For i = 2 To lastRow 'iterate between the cells of the 'colSort' range
If sh.Cells(i, colS).value = El Then 'when first matching cell has been found
firstAddr = sh.Cells(i, colS).Address: iNew = i 'matching cell 'firstAddr' is defined
For j = i To lastRow 'iterate on the same 'colSort' range, until the last identic cell
If sh.Cells(j, colS).value <> sh.Cells(j + 1, colS).value Then 'for the last matching cell
lastAddr = sh.Cells(j, colS).Address: boolFound = True: Exit For ''lastAddr' defined
End If
Next j
End If
If firstAddr <> "" Then 'if the array element has been found
sh.Range(firstAddr & ":" & lastAddr).EntireRow.Delete 'the range to be deleted is built and deleted
firstAddr = "": lastAddr = "" 'firstAddr and lastAddr are re initializated
i = iNew - 1: boolFound = False 'i (the iteration variable) is reinitialized at row after the deletion
End If
Next i
Next
lastRow = sh.Cells(Rows.count, colS).End(xlUp).Row 'last row is redefined, according to # of rows reamained
Set rng = sh.Range(sh.Range("A1"), sh.Cells(lastRow, lastCol + 1)) 'redefin the sorted area based on 'lastRow'
rng.Sort Key1:=sh.Cells(1, lastCol + 1), Order1:=xlAscending, Header:=xlYes 'sort the range on the 'SortOrder' col
sh.Range(sh.Cells(1, lastCol + 1), sh.Cells(lastRow, lastCol + 1)).Clear 'clear of 'SortOrder' column
End Sub

VBA copy mutlipe rows that meet criteria to another sheet

I really don't understand much VBA, so be patient with me.
I have a list of people assigned to a specific flight (LEGID) and I want to copy those people (Worksheet pax) to a specific cell in another worksheet (temp - cell b15), but it doesn't work.
This data table is a query report from salesforce.
Sub pax()
Dim LastRow As Long
Dim i As Long, j As Long
Dim legid As String
Application.ScreenUpdating = False
legid = ThisWorkbook.Worksheets("setup").Range("SelReq").Value
Debug.Print legid
'Find the last used row in a Column: column A in this example
With Worksheets("pax")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
' MsgBox (LastRow)
'first row number where you need to paste values in temp'
With Worksheets("temp")
j = .Cells(.Rows.Count, "a").End(xlUp).Row + 1
End With
For i = 1 To LastRow
With Worksheets("pax")
If .Cells(i, 1).Value = legid Then
.Rows(i).Copy Destination:=Worksheets("temp").Range("a" & j)
j = j + 1
End If
End With
Next i
Application.ScreenUpdating = True
End Sub
If you are looking to just get the names copied over. You can use this; however you will need to update your sheet names and ranges if they are named ranges. This code looks at a specific cell for a value on Sheet3 then if that value matches a value from a range on Sheet1 it will place the values from Column B on Sheet1 into Sheet2
Sub Test()
Dim cell As Range
Dim LastRow As Long, i As Long, j As Long
Dim legid As String
With Sheet1
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With Sheet2
j = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
legid = Sheet3.Range("A1")
For i = 2 To LastRow
For Each cell In Sheet1.Range("A" & i)
If cell.Value = legid Then
Sheet2.Range("A" & j) = cell.Offset(0, 1).Value
j = j + 1
End If
Next cell
Next i
End Sub

Copy specific cells from sheet to sheet based on condition

'Sub CopyRowToSheet23()
Worksheets("Sheet2").Range("A2:E1000").Clear
Dim LastRowSheet1, LastRowSheet2 As Long
Dim i As Long
Application.ScreenUpdating = False
LastRowSheet2 = Worksheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row
Sheets("Sheet2").Range("A2:E" & LastRowSheet2).ClearContents
LastRowSheet1 = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
With Worksheets("Sheet1")
For i = 2 To LastRowSheet1 Step 1
If Cells(i, "E").Value = "YES" Then
LastRowSheet2 = Worksheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row
Rows(i).Copy Worksheets("Sheet2").Range("A" & LastRowSheet2 + 1)
End If
Next i
End With
Application.ScreenUpdating = True
Sheet3.Select
End Sub'
I´ve managed to create the code above to get all rows that have "yes" in column E. However, I´m having issues when trying to run the macro in other sheets different than Sheet1. I would like to run it in sheet3 but I haven´t found why it does not help.
Try:
Option Explicit
Sub test()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim wsRE As Long, i As Long, LastrowC As Long, LastrowE As Long, LastrowF As Long
'Set ws1
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
'Set ws2
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
wsRE = ws2.Cells(ws2.Rows.Count, "E").End(xlUp).Row
'Starting from Row 2 - let us assume that their is a header
For i = 2 To wsRE
'Check if the value in column E is yes
If ws2.Range("E" & i).Value = "Yes" Then
'Find the Last row in Sheet1 Column C
LastrowC = ws1.Cells(ws1.Rows.Count, "C").End(xlUp).Row
'Copy row i, Column A from Sheet 1 and paste it in Sheet 2 after the lastrow in column C
ws2.Range("A" & i).Copy ws1.Cells(LastrowC + 1, 3)
'Find the Last row in Sheet1 Column E
LastrowE = ws1.Cells(ws1.Rows.Count, "E").End(xlUp).Row
'Copy row i, Column B from Sheet 1 and paste it in Sheet 2 after the lastrow in column E
ws2.Range("B" & i).Copy ws1.Cells(LastrowE + 1, 5)
'Find the Last row in Sheet1 Column F
LastrowF = ws1.Cells(ws1.Rows.Count, "F").End(xlUp).Row
'Copy row i ,Column C from Sheet 1 and paste it in Sheet 2 after the lastrow in column F
ws2.Range("C" & i).Copy ws1.Cells(LastrowF + 1, 6)
End If
Next i
End Sub

Extract rows from multiple sheets into one and exclude any row with #N/A

I have one sheet of data where I need to extract the values from multiple columns and assign them a value. Column A is a string where column B is the assigned value. Columns C and D are vlookups based on column A and they will need the assigned value from column B as well. Please see the screenshots. I would need to compile a list on a separate sheet. Ideally column A would have the data from columns A, C and D from the other sheet and column B would have the assigned values. Only caveat is I need to exclude any row that has #N/A
Any macro that may work would be very helpful!
Code I was using
Sub Life_Saver_Button()
Dim lastrow As Long, erow As Long
Set S1 = Worksheets("Sheet1")
Set S2 = Worksheets("Sheet2")
lastrow = ThisWorkbook.Sheets("S1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastrow
S1.Cells(i, 1).Copy
erow = ThisWorkbook.Sheets("S2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ThisWorkbook.Sheets("S1").Paste Destination:=ThisWorkbook.Sheets("S2").Cells(erow, 1)
ThisWorkbook.Sheets("S1").Cells(i, 2).Copy
ThisWorkbook.Sheets("S1").Paste Destination:=ThisWorkbook.Sheets("S2").Cells(erow, 2)
ThisWorkbook.Sheets("S1").Cells(i, 3).Copy
ThisWorkbook.Sheets("S1").Paste Destination:=ThisWorkbook.Sheets("S2").Cells(erow, 1)
ThisWorkbook.Sheets("S1").Cells(i, 4).Copy
ThisWorkbook.Sheets("S1").Paste Destination:=ThisWorkbook.Sheets("S2").Cells(erow, 2)
ThisWorkbook.Sheets("S1").Cells(i, 5).Copy
ThisWorkbook.Sheets("S1").Paste Destination:=ThisWorkbook.Sheets("S2").Cells(erow, 1)
ThisWorkbook.Sheets("S1").Cells(i, 5).Copy
ThisWorkbook.Sheets("S1").Paste Destination:=ThisWorkbook.Sheets("S2").Cells(erow, 2)
Next i
Application.CutCopyMode = False
ThisWorkbook.Sheets("S2").Columns().AutoFit
Range("A1").Select
End Sub
Try:
Option Explicit
Sub test1()
Dim LastrowA As Long, Lastrow As Long, cell As Range, Code As Long
Dim Desc As String
With ThisWorkbook.Worksheets("Sheet1")
LastrowA = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each cell In .Range("A1:D" & LastrowA)
If Not IsError(cell.Value) = True And Not IsNumeric(cell.Value) = True Then
Desc = cell.Value
Code = .Range("B" & cell.Row).Value
Lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
If LastrowA = Lastrow Then
.Range("A" & Lastrow + 2).Value = Desc
.Range("B" & Lastrow + 2).Value = Code
Else
.Range("A" & Lastrow + 1).Value = Desc
.Range("B" & Lastrow + 1).Value = Code
End If
End If
Next
End With
End Sub
Results:

Resources