Hi there I have created the following two macros however it is inserting a row after the last cell with data. I believe this is a result of my loop condition being Do Until ActiveCell.Value = "". I would like to have the loop stop at the last cell with data.
I tried using variables Do Until Loop_Long = LastRow but this did not work for me.
All I would like is to have a macro insert a row between cells with unlike data. Then a macro that will find empty cells in the column,the ones we previously inserted, and then delete the row.
As outlined above the issue is it is inserting an extra row and not deleting it, if you put values all the way down column B after your data in column A you will see what I mean.
Here is my code:
Option Explicit
Sub Macro1()
'Insert Blank Row Between Names
Sheets("Sheet1").Select
Range("A1").Select
Do Until ActiveCell.Value = ""
If ActiveCell.Value <> ActiveCell.Offset(1).Value Then
ActiveCell.Offset(1).EntireRow.Insert
ActiveCell.Offset(1).Select
End If
ActiveCell.Offset(1).Select
Loop
End Sub
Sub Macro2()
Dim LastRow As Long
'Delete Inserted Rows
Sheets("Sheet1").Select
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("A" & LastRow).Select
Do Until ActiveCell.Value = Range("A1")
If ActiveCell.Value <> ActiveCell.Offset(-1).Value Then
ActiveCell.Offset(-1).EntireRow.Delete Shift:=xlUp
ActiveCell.Offset(-1).Select
End If
ActiveCell.Offset(-1).Select
Loop
End Sub
From what you've told me, the below code should work for you (and it better follows best practices)... Have you considered copying the data as is and then inserting the rows once you've pasted the data to the new location? That would cut out a step.
Option Explicit
'Declare module-level variables.
Dim sht As Worksheet
Dim Cell As Range
Dim NameRng As Range
Dim LastRow As Long
Sub test()
'Add blank rows.
Set sht = ActiveWorkbook.Sheets("Sheet1")
LastRow = sht.Range("A" & Rows.count).End(xlUp).Row
Set NameRng = sht.Range("A1:A" & LastRow)
For Each Cell In NameRng
If Cell <> Cell.Offset(1, 0) And Cell <> "" Then
Cell.Offset(1, 0).EntireRow.Insert
End If
Next Cell
End Sub
Sub test2()
'Delete blank rows.
Set sht = ActiveWorkbook.Sheets("Sheet1")
LastRow = sht.Range("A" & Rows.count).End(xlUp).Row
Set NameRng = sht.Range("A1:A" & LastRow + 1)
For Each Cell In NameRng
If Cell = "" Then
Cell.EntireRow.Delete
End If
Next Cell
End Sub
Related
I am new to VBA and coding in general and I am being tasked with some coding that is proving difficult. I am trying to copy/transpose/paste values from a two-column PivotTable and I need it to paste vertically on another sheet and break on blanks. (see image) I need to copy each group in the PivotTable then transpose paste values vertically on a new worksheet. I believe I need to count populated rows (using an array?) until I get to a blank row then paste the group. I can picture what I need to do but all my coding attempts are way off. Except for the copy/paste, I have no clue how to code this. I cannot figure out how to capture each group of populated rows to be pasted.
' Copy a vertical range (on "FQNID_Sites" sheet) and paste to a horizontal range in column B (next blank row on "BH_FH" sheet)
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Worksheets("FQNID_Sites")
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Worksheets("BH_FH")
Dim cellToPasteTo As Range
' Need to loop through each group breaking on each siteNFID in column D (or break on blanks in column E?)
Set rng = Range("$D$2:$E$" & ActiveSheet.UsedRange.Rows.Count)
For Each cell In rng
Set cellToPasteTo = destinationSheet.Cells(destinationSheet.Rows.Count, "B").End(xlUp).Offset(1, 0)
If cell.Value = "" And Not IsNull(copyStart) Then
copyEnd = cell.Offset(-1, 0).Address
ElseIf cell.Value = "" Then
copyStart = cell.Offset(0, -1).Address
End If
If Not IsNull(copyStart) And Not IsNull(copyEnd) Then
sourceSheet.Range(copyStart & ":" & copyEnd).Select
Selection.Copy
cellToPasteTo.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Transpose:=True
End If
Next cell
Application.CutCopyMode = False
I need it to break on each siteNFID/FQNID then paste values for each group vertically in column B on the BH_FH worksheet.
Example of the input and expected output format
This code will work. Tested on similar data structure. I used the code sheet name in the code `Sheet1'. Change as needed.
Option Explicit
Sub runTranspose()
With Sheet1
Dim lastRow As Long
lastRow = .Cells(.Rows.Count, 4).End(xlUp).Row
'load range starts to transpose
Dim i As Long
For i = 2 To lastRow
If Len(.Cells(i, 5)) = 0 Then
Dim startTranspose As Range
If startTranspose Is Nothing Then
Set startTranspose = .Cells(i, 5)
Else
Set startTranspose = Union(startTranspose, .Cells(i, 5))
End If
End If
Next
Dim c As Range
For Each c In startTranspose
transposeData c
Next
End With
End Sub
Sub transposeData(r As Range)
With Sheet1
Dim nextRow As Long
nextRow = .Cells(.Rows.Count, 8).End(xlUp).Row + 1
Dim fullRange As Range
Set fullRange = Range(r.Offset(1, -1), r.Offset(1).End(xlDown))
Dim arr As Variant
arr = fullRange.Value
.Cells(nextRow,7).Value = r.offset(-1).Value 'to add label
.Cells(nextRow, 8).Resize(2, UBound(arr)).Value = Application.Transpose(arr)
End With
End Sub
In Sheet1 on the excel sheet I have in Range("B6") I have a code so it might be one code this month but it can also be 3 more code added below in the next and it just could be two new in the next month so the values will keep on changing and number can range between 1 to anything it will be dynamic. Based on these values on the next Sheet2 the date needs to be filtered. So in Sheet2 I have three columns one is Sl_No. one ME_Code (This is what needs to be filtered based on Sheet 1 data) and prices
So I am new in VBA and tried the below code which is not working when there is multiple codes which I am trying to add to an Autofilter Array in VBA.
Here is my code which is not working when I am trying in the else option can someone please help me, I tried few option from StackOverflow itself but did not work
Here is my code,
Sub ToCheckArray()
Dim N As Long
Worksheets("Sheet1").Select
If IsEmpty(Range("B6").Offset(1, 0).Value) Then
Worksheets("Sheet1").Select
arr1 = Array(Range("B6"))
Worksheets("Sheet2").Select
Range("A1:C1").AutoFilter field:=2, Criteria1:=arr1, Operator:=xlFilterValues
Else
Worksheets("Sheet1").Select
'With Sheets("Sheet1")
'N = .Cells(Rows.Count, "B").End(xlDown).Row
'ReDim ary(6 To N)
'For i = 6 To N
'ary(i) = .Cells(i, 1)
'Next i
'End With
arr1 = Array(Range("B6", Range("B6").End(xlDown)))
Worksheets("Sheet2").Select
Range("A1:C1").AutoFilter field:=2, Criteria1:=ary, operator:=xlFilterValues
End If
End Sub
Use
Else
Dim ary As Variant
With Worksheets("Sheet1")
ary = Application.Transpose(.Range("B6", .Cells(Rows.Count, "B").End(xlDown)).Value)
End With
Worksheets("Sheet2").Range("A1:C1").AutoFilter field:=2, Criteria1:=ary, operator:=xlFilterValues
End If
As you see, I avoided Select statement in lieu of a fully qualified range reference up to the sheet reference
So your entire code could be rewritten as follows:
Sub ToCheckArray()
Dim ary As Variant
With Worksheets("Sheet1")
If IsEmpty(.Range("B6").Offset(1, 0).Value) Then
ary = Array(.Range("B6").Value)
Else
ary = Application.Transpose(.Range("B6", .Cells(Rows.Count, "B").End(xlDown)).Value
End If
End With
Worksheets("Sheet2").Range("A1:C1").AutoFilter field:=2, Criteria1:=ary, Operator:=xlFilterValues
End Sub
And should you be sure that Sheet1 has always a value in B6, and possible other values follow it down to the last not empty cell in column B, then it can collapse to:
Sub ToCheckArray()
Dim ary As Variant
With Worksheets("Sheet1")
ary = Application.Transpose(.Range("B6", .Cells(Rows.Count, "B").End(xlUp)).Value
End With
Worksheets("Sheet2").Range("A1:C1").AutoFilter field:=2, Criteria1:=ary, Operator:=xlFilterValues
End Sub
I have a dirty database where the names of each individual are written in different ways and I cannot group them.
I would like to create a macro to find and replace the names in the database using a two column list.
I have found the following code, but I´m having trouble understanding it, so cannot adapt it:
Dim Sht As Worksheet
Dim fndList As Integer
Dim rplcList As Integer
Dim tbl As ListObject
Dim myArray As Variant
Dim Rng As Range
'Create variable to point to your table
Set tbl = Worksheets("How to").ListObjects("Table2")
'Create an Array out of the Table's Data
Set TempArray = tbl.DataBodyRange
myArray = Application.Transpose(TempArray)
'Designate Columns for Find/Replace data
fndList = 1
rplcList = 2
'Loop through each item in Array lists
For x = LBound(myArray, 1) To UBound(myArray, 2)
'Loop through each worksheet in ActiveWorkbook (skip sheet with table in it)
For Each Rng In Worksheets("xxxxxxxxxx").Activate
If Rng.Name <> tbl.Parent.Name Then
Rng.Cells.replace What:=myArray(fndList, x), Replacement:=myArray(rplcList, x), _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
End If
Next Rng
Next x
End Sub
I have adjusted your code which you can see below; couple notes:
1- Using Option Explicit is always a good idea
2- If you put the array loop inside the sheet loop, you only have to perform the sheet name check n times (n=number of sheets in workbook), if you put the sheet loop inside the array loop you would have to perform the sheet name check n*x times (x = number of items in your array)...
3- You didn't specify, but I assumed that your Table1 was structured vertically with the lookup value in the first column and the replacement value in the 2nd- so there is no need to transpose your array; if your Table1 is in fact horizontal then you would need to adjust this code...
Public Sub demoCode()
Dim sheetName As String
Dim tableRange As Range
Dim myArray() As Variant
Dim wsCounter As Long
Dim rowCounter As Long
'Store name of sheet with lookup table
sheetName = "How to"
'Create an Array out of the Table's Data
Set tableRange = ThisWorkbook.Sheets(sheetName).ListObjects("Table1").DataBodyRange
myArray = tableRange
'Loop through each sheet
For wsCounter = 1 To ThisWorkbook.Sheets.Count
With ThisWorkbook.Sheets(wsCounter)
'Test to make sure the sheet is not the sheet with the lookup table
If .Name <> sheetName Then
'Loop through each item in lookup table
For rowCounter = LBound(myArray, 1) To UBound(myArray, 1)
'Replace any cells that contain whats in the first column of the lookup table, with whats in the 2nd column..
.Cells.Replace What:=myArray(rowCounter, 1), Replacement:=myArray(rowCounter, 2), LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Next
End If
End With
Next
End Sub
Hope this helps,
TheSilkCode
so to answer your second question, basically what you would need to do is remove the sheet loop (which you have done), and then the part you're missing is you also need to specify you want the code to perform the replace on just the cells within the target range, instead of performing it on the cells within the sheet (which would be all the cells)... see below for example:
Public Sub demoCode_v2()
Dim tableRange As Range
Dim myArray() As Variant
Dim rowCounter As Long
Dim targetRange As Range
'Create an Array out of the Table's Data
Set tableRange = ThisWorkbook.Sheets(sheetName).ListObjects("Table1").DataBodyRange
myArray = tableRange
'Select target range
Set targetRange = Application.InputBox("Select target range:", Type:=8)
'Loop through each item in lookup table
For rowCounter = LBound(myArray, 1) To UBound(myArray, 1)
'Replace any cells in target range that contain whats in the first column of the lookup table, with whats in the 2nd column..
targetRange.Cells.Replace What:=myArray(rowCounter, 1), Replacement:=myArray(rowCounter, 2), LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Next
End Sub
Hope this helps,
TheSilkCode
Using a slight adjustment of TheSilkCode code you could loop through a worksheet as follows:
Option Explicit
Public Sub pDemo()
Dim vMappingTable() As Variant
Dim rowCounter As Long
'1) Create an Array out of the Old to New Name mapping
vMappingTable = wksMappings.ListObjects("tbl_Mapping").DataBodyRange
'2) Loops through desired sheet and replaces any cells that contain the first column val, with the 2nd column val...
With wksToReplace.Range("X:X")
For rowCounter = LBound(vMappingTable, 1) To UBound(vMappingTable, 1)
.Cells.Replace What:=vMappingTable(rowCounter, 1), Replacement:=vMappingTable(rowCounter, 2), LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Next
End With
End Sub
Note: you can define names of table via the Name manager (Ctrl+F3) and you can set the name of worksheets in your project in the properties in the VBA editor which I have done here or use the default names/and or path.
I have the below code from Chandoo for excel. In the 'Data Sheet' it selects the sheet to copy to according to col. C, then copies col. A - G to that spreadsheet and moves to the next entry.
I am having trouble adjusting this code to suit my spreadsheet and would appreciate some assistance. My sheet name is in col. A (not c), and I only require col. B & C to be copied to the sheet. Additionally col. B & C need to be copied into col. B & G in the spreadsheet.
Sub copyPasteData()
Dim strSourceSheet As String
Dim strDestinationSheet As String
Dim lastRow As Long
strSourceSheet = "Data entry"
Sheets(strSourceSheet).Visible = True
Sheets(strSourceSheet).Select
Range("C2").Select
Do While ActiveCell.Value <> ""
strDestinationSheet = ActiveCell.Value
ActiveCell.Offset(0, -2).Resize(1, ActiveCell.CurrentRegion.Columns.Count).Select
Selection.Copy
Sheets(strDestinationSheet).Visible = True
Sheets(strDestinationSheet).Select
lastRow = LastRowInOneColumn("A")
Cells(lastRow + 1, 1).Select
Selection.PasteSpecial xlPasteValues
Application.CutCopyMode = False
Sheets(strSourceSheet).Select
ActiveCell.Offset(0, 2).Select
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Public Function LastRowInOneColumn(col)
'Find the last used row in a Column: column A in this example
'http://www.rondebruin.nl/last.htm
Dim lastRow As Long
With ActiveSheet
lastRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
LastRowInOneColumn = lastRow
End Function
Any assistance in resolving this would be greatly appreciated.
Thank you
This is a leason on the dangers of copying random code form the internet. Manipulating the active selection like this is slow, hard to read, and hard to maintain.
Here's the code refactored to do this task in a more controlled fasion.
The origonal code (refactored) is included, commented out. The code modified to reference your requested cells follows each original line
Sub copyPasteData()
Dim strSourceSheet As String
Dim strDestinationSheet As String
Dim lastRow As Long
Dim wsSource As Worksheet, wsDest As Worksheet
Dim rWs As Range
Dim rSrc As Range, rDst As Range, cl As Range
strSourceSheet = "Data entry"
' Get a reference to the source sheet
Set wsSource = Worksheets(strSourceSheet)
With wsSource
' Get a reference to the list of sheet names
'Set rWs = Range(.Cells(2, 3), .Cells(.Rows.Count, 3).End(xlUp)) ' for Column C
Set rWs = Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp)) ' for Column A
' Loop through the sheet names list
For Each cl In rWs.Cells
' Get a reference to the current row of data, all cells on that row
'Set rSrc = cl.EntireRow.Resize(1, .Cells(cl.Row, .Columns.Count).End(xlToLeft).Column)
Set rSrc = cl.EntireRow.Cells(1, 2).Resize(1, 2) ' Reference columns B and C only
' Get a reference to the current Destination sheet
Set wsDest = Worksheets(cl.Value)
With wsDest
lastRow = .Cells(.Rows.Count, 2).End(xlUp).Row ' Check last row in Column B
' Copy data to destination using Value array
'.Cells(lastRow + 1, 1).Resize(1, rSrc.Columns.Count).Value = rSrc.Value ' all data
.Cells(lastRow + 1, 2).Value = rSrc.Cells(1, 1) ' copy first cell to column B
.Cells(lastRow + 1, 7).Value = rSrc.Cells(1, 2) ' copy second cell to column G
End With
Next
End With
End Sub
I am using the following code to search in the A column of a row for a name. If the name is found, it is placed in a column 2 over. I am trying to search against a list of names rather than one name. The names are listed in sheet1, I am searching text stored in column A on sheet4. Each row has a paragraph of text I want to search. When a match is found, the matching name(s) is put in cell c of the same row.
Sub test()
Dim ws1, ws2 As Worksheet, rng1, rng2, cel1, cel2 As Range
Dim i, lrow As Long
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet4")
'i only assumed that your data is both in column A of sheet 1 and 2
lrow = ws1.Range("A" & Rows.Count).End(xlUp).Row
Set rng1 = ws1.Range("A1:A" & lrow) 'this contains the names
lrow = ws2.Range("A" & Rows.Count).End(xlUp).Row
Set rng2 = ws2.Range("A1:A" & lrow) 'this contains list of text you want to search
i = 0
For Each cel2 In rng2
For Each cel1 In rng1
If InStr(cel1.Value, cel2.Value) <> 0 Then cel1.Copy ws2.Range("c1").Offset(i, 0): i = i + 1
Next cel1
Next cel2
End Sub
Cheers!
If my comment is correct then this should work for you:
say I start with this set up:
I would first add my look up values to a named range as follows:
then you can add this code:
Sub Sample()
Application.ScreenUpdating = False
With Range("A2", Range("A" & Rows.Count).End(xlUp)).Offset(, 2)
.FormulaR1C1 = _
"=IFERROR(LOOKUP(1E+100,SEARCH(LookUpValues,RC[-2]),LookUpValues),"""")"
.Value = .Value
End With
Application.ScreenUpdating = True
End Sub
and this should result in the following:
this is another way to get what you want but not really using formula.
Option Explicit
Sub test()
Dim ws1, ws2 As Worksheet, rng1, rng2, cel1, cel2 As Range
Dim i, lrow As Long
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
'i only assumed that your data is both in column A of sheet 1 and 2
lrow = ws1.Range("A" & Rows.Count).End(xlUp).Row
Set rng1 = ws1.Range("A1:A" & lrow) 'this contains the names
lrow = ws2.Range("A" & Rows.Count).End(xlUp).Row
Set rng2 = ws2.Range("A1:A" & lrow) 'this contains list of text you want to search
i = 0
For Each cel2 In rng2
For Each cel1 In rng1
If InStr(cel1.Value, cel2.Value) <> 0 Then cel1.Copy ws1.Range("B1").Offset(i, 0): i = i + 1
Next cel1
Next cel2
End Sub
I proposed above approach since you are open to using VBA.
hope this is what or somewhat close to what you want.