So I have a large data set where I would like to combine rows depending if the information in the first column matches to a certain degree. I was wondering if there is a macro that could do this. Below I have included images of a similar simplified data set. I would assume the macro would create the new table in a new worksheet or insert a row below the existing data but I am not sure. Any help or tips on this problem would be very helpful.
Sample dataset:
Output:
you may try the following (commented) code:
Option Explicit
Sub main()
Dim cell As Range, cell2 As Range
With Worksheets("experiment").Range("A1").CurrentRegion '<--| reference data worksheet(change "experiment" to its actual name) cell "A1" contiguous range column "A"
.Sort key1:=Range("A1"), order1:=xlAscending, Header:=xlYes '<--| sort it by "experiment" column to have "smaller" names at the top
For Each cell In .Offset(1).Resize(.Rows.Count - 1, 1) '<--| loop through its 1st column cells skipping header row
If cell.Value <> "" Then '<--| if current cell isn't blank (also as a result of subsequent operations)
.AutoFilter Field:=1, Criteria1:="*" & cell.Value & "*" '<--| filter on referenced column to get cell "containing" current cell content
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 2 Then '<--| if more than 2 rows has been foun: header row gets always filtered so to have at least 2 rows to consolidate we must filter at least 3
With .Offset(1).Resize(.Rows.Count - 1) '<--| reference filtered rows skipping header row
For Each cell2 In .Offset(, 1).Resize(, .Columns.Count - 1).SpecialCells(xlCellTypeVisible).Areas(1).Rows(1).Cells '<--| loop through 1st filtered row cells skipping 1st column ("experiment")
cell2.Value = WorksheetFunction.Subtotal(9, cell2.EntireColumn) '<--| update their content to the sum of filtered cells in corresponding column
Next cell2
With .Resize(, 1).SpecialCells(xlCellTypeVisible) '<--| reference filtered rows 1st column ("experiment") cells
.Value = .Cells(1, 1) '<--| have them share the same name
End With
.RemoveDuplicates Columns:=Array(1), Header:=xlNo '<--| remove duplicates, thus leaving the 1st filtered row with totals
End With
End If
End If
Next cell
.Parent.AutoFilterMode = False '<--| show all rows back
End With
End Sub
Add a column that extracts the first few characters of the first column. Then create a pivot table with that new column in the rows and the other columns in the values area. No VBA required.
Related
I need VBA code for the following:
If cells in a certain column contain a certain word, I need to cut and paste the entire row onto a different sheet. I found some code, but it matches the row on the destination sheet. I just need it to go on to the different sheet and be deleted from the source.
Can anyone kindly advise?
if your "Column" has a header as its first cell then you can use AutoFilter() as per following code (see comments to adjust it to your actual needs)
Sub main()
With Worksheets("mySheetName") '<--| reference the worksheet with data (change "mySheetName" to your actual worksheet with data name
With .Range("A1", .Cells(.Rows.count, "A").End(xlUp)) '<--| reference its "column" (change "A" occurrences to your actual column with data index)
.AutoFilter Field:=1, Criteria1:="d" '<--| change "word" to your actual word to be looked for
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then
With .Resize(.Rows.count - 1).Offset(1).SpecialCells(xlCellTypeVisible)
.Copy Worksheets("myOtherSheetName").Range("A1")
Application.DisplayAlerts = False
.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
End With
End If
.AutoFilterMode = False
End With
End With
End Sub
I have some code in my VBA script that is supposed to delete entire rows when the value of the respective B column of the row equals zero. Unfortunately, the lines of code I have been using are not doing exactly what I want as it deletes the entire row if ANY of the cells in the respective row equals zero.
Here is the code so far:
With Worksheets("Sheet2")
For myloop = .Range("B10000").End(xlUp).Row To 1 Step -1
If .Cells(myloop, 4).Value = 0 Then .Rows(myloop).EntireRow.Delete
Next myloop
End With
For instance I had a row in which the cell in column D was equal to zero and this code deleted the entire row even though the value of the cell in column B was not zero. How can I change the code so it actually only scans for the entries in column B?
Any help is appreciated and thanks in advance.
The user gizlmo provided the answer:
Change .Cells(myloop, 4).Value to .Cells(myloop, 2).Value
an AutoFilter() approach is the following:
With Worksheets("Sheet2") '<--| reference your shet
With .Range("B1", .Cells(Rows.Count, "B").End(xlUp)) '<--| reference its column B range from row 1 (header) down to last not empty row
If WorksheetFunction.CountBlank(.Cells) + WorksheetFunction.CountIf(.Cells, 0) = 0 Then Exit Sub '<--| exit of no empty or "zero" cells
.AutoFilter Field:=1, Criteria1:=0, Operator:=xlOr, Criteria2:="" '<--| filter column B cells with "0" content
.Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete '<--| if any filtered cell other than headers then delete their entire rows
End With
.AutoFilterMode = False
End With
Working on Microsoft Visual Basic Application Edition 7.1 in Excel 2013
Data are on columns from A to D, rows' number varies from time to time. I would like to delete all rows for which column B's value doesn't start with LCR (and also I would like not to bore with a for...next loop).
Something like:
Columns("B:B").AutoFilter Field:=1, Criteria1:="<>LCR*"
Selection.Delete
Unfortunately, this code deletes heading row (row number 1) and I don't want.
I tried to store row number 1 elsewhere in a range variable, but it doesn't work (run-time error '424')
Set r1 = Range("A1:D1")
r1.Copy
Columns("B:B").AutoFilter Field:=1, Criteria1:="<>LCR*"
Selection.Delete
With Range("A1:D1")
.Insert Shift:=xlDown
.Select
.Value = r1.Value
End With
How can I tell the filter to start from row number two (or how can I correctly store content of row number one so to paste it after deletion by filter)?
Thanks in advance for your help
Define your range for deleting as Range(Cells(2,2),Cells(ActiveSheet.UsedRange.Rows.Count,2)) (To replace the Selection call). This will delete everything except for the first cell in the column
Edit to avoid excel prompt: Range(Cells(2,2),Cells(ActiveSheet.UsedRange.Rows.Count,2)).EntireRow
in a more complete way you could go like this
Sub main()
With Worksheets("MyWantedSheet") '<--| always specify full worksheet reference (change "MyWantedSheet" with your actual sheet name)
With .Columns("B:B") '.Resize(.Cells(.Rows.Count, "B").End(xlUp).Row) '<--| refer to wanted column range down to its last non empty cell
.AutoFilter '<--| remove possible preeeding autofilter filtering
.AutoFilter Field:=1, Criteria1:="<>LCR*" '<--| apply current filtering
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if there are visible cells other than the "header" one
.Resize(.Parent.Cells(.Parent.Rows.Count, "B").End(xlUp).Row - 1).Offset(1).SpecialCells(xlCellTypeVisible).EntireRow.Delete '<--|delete visible rows other than the first ("headers") one
End If
End With
.AutoFilterMode = False '<--| remove drop-down arrows
End With
End Sub
I've been banging my head on this one for a while.
I have a big macro I made doing a number of operations on a file but got stuck on doing a series of filtering and vlookups.
Here is a portion of what I got. I added comments to make it clearer.
'FILTER ALL 3P VALUES IN ONE COLUMN AND ADD A VALUE IN ALL RESPECTIVE CELLS IN OTHER COLUMN
Application.ScreenUpdating = False
With ActiveSheet.UsedRange
.AutoFilter Field:=22, Criteria1:="*3P*"
.Offset(1).Range("AU1:AU" & Cells(Rows.Count, "A").End(xlUp).Row).SpecialCells(xlCellTypeVisible).Select
'HERE I SELECT ALL VISIBLE FILTERED CELLS BY COUNTING IN ROW A BECAUSE THESE CELLS ARENT BLANK
.Selection.Value = "3P PROGRAM"
.AutoFilter
End With
'NOW I WANT TO FILTER ROW FOR BLANKS AND THEN FILL THIS RANGE WITH A FORMULA
'HERE IS THE PROBLEM
With ActiveSheet.UsedRange
.AutoFilter Field:=47, Criteria1:="="
.Offset(1).Range("AU1:AU" & Cells(Rows.Count, "A").End(xlUp).Row).SpecialCells(xlCellTypeVisible).Select
.Selection.FormulaR1C1 = "=VLOOKUP(RC[-38],'[WeeklyData.xlsx]Sheet1'!C8:C16,9,FALSE)"
.AutoFilter
End With
Problem is at the vlookup step. I want that range of visible filtered blank cells to get the value gotten by vlookup. Every cell should take a cell 38 columns to the left as a vlookup reference.
I cant find a way to make formula work. I would like to:
-insert vlookup to that filtered range,
-remove filter (Autofilter)
-Select calculated column with offset of 1 for headers and paste as special values
- carry on to do this process 5, 6 more times for blank or invalid entries in other columns.
Is there a way to do this?
Any help is appreciated
I prefer the Range.CurrentRegion property over the Worksheet.UsedRange property. It refers to the 'data island' created at the origin point (in this case, A1).
With ActiveSheet
If .AutoFilterMode Then AutoFilterMode = False
With .Cells(1, 1).CurrentRegion
'Set the filter
.AutoFilter Field:=22, Criteria1:="*3P*"
'Shift off the header row
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
'check if there are any visible cells
If CBool(Application.Subtotal(103, .Cells)) Then
'Put 3P PROGRAM into the visible cells in column AU
Intersect(.Columns(47), .SpecialCells(xlCellTypeVisible)) = "3P PROGRAM"
End If
End With
'remove the filter
.AutoFilter Field:=22
'set the formula on column AU blank cells
Intersect(.Columns(47), .SpecialCells(xlCellTypeBlanks)).FormulaR1C1 = _
"=VLOOKUP(RC[-38], '[WeeklyData.xlsx]Sheet1'!C8:C16, 9, FALSE)"
'revert column AU within the .CurrentRegion to the values returned by the formulas
.columns(47).cells = .columns(47).cells.value
End With
End With
The second filter is replaced by using the Range.SpecialCells method with the xlCellTypeBlanks property. The Intersect method isolates the cell range reference to the blank cells within column AU. You may want to make a check for blank cells before running that operation.
[This is in Excel 2007]
In other words, the loop will cycle through all the active cells in a one-column range (rngAddressName) and, if the cell in the range AND the cell directly to the left of it contain the string "#N/A", then it will delete that row.
Unfortunately, nothing I have tried has had any actual effect. Here is my best go at it:
i = 1
For counter = 1 To rngSC2A.Rows.Count
Contents = rngSC2A.Cells(i).Value
If Contents = "#N/A" Then
If rngAddressName.Cells(i).CellOffset(0, -1).Value = "#N/A" Then
rngAddressName.Cells(i).EntireRow.Delete
Else
End If
Else
i = i + 1
End If
Next
But this doesn't seem to find any rows with the conditions satisfied (even though such rows exist in the worksheet).
I think it might have something to do with the fact that I am looking in the Cell.Value, but I am not sure.
You can autofilter your range, delete any rows that meet your criteria, then turn the autofilter off. This is a much more efficient approach than looping.
The example below works on columns A and B in Sheet1. Modify the variables to reference the range and sheet in your workbook.
Sub DeleteDoubleNA()
Dim ws As Worksheet
Dim rng As Range
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
lastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("A1:B" & lastRow)
' filter and delete all but header row
With rng
.AutoFilter field:=1, Criteria1:="#N/A"
.AutoFilter field:=2, Criteria1:="#N/A"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
' turn off the filters
ws.AutoFilterMode = False
End Sub
This is a different take on on the excellent answer posted by #Jon Crowell.
If you use an Excel table, you can use the table's ListObject to get the data range which automatically excludes the header and footer rows.
This avoids the sometimes incorrect calculation search for a last row.
You also want to clear any pre-existing filters on the data so that you don't overlook any rows.
Dim myTable As Object
Set myTable = ActiveSheet.ListObjects(1) ' Works if worksheet contains only one table
' Clear pre-existing filters on the table
myTable.AutoFilter.ShowAllData
' Filter the table
With myTable.DataBodyRange
.AutoFilter field:=1, Criteria1:="#N/A"
.AutoFilter field:=2, Criteria1:="#N/A"
End With
' Delete visible cells in the filtered table
myTable.DataBodyRange.SpecialCells(xlCellTypeVisible).EntireRow.Delete
' Clear filters on the table
myTable.AutoFilter.ShowAllData
The (1) in ListObjects(1) is the first (in my case only) table in the worksheet. DataBodyRange refers to the data range of that table excluding header and footer rows.