Delete rows based on a range of conditions (plural) - excel

it's been a while since I've used VBA. I have a range of unique values that I would like to search a table for. And if those values exist in said table, delete the entire row.
I'm able to loop through and delete specific, singular values, but struggling with multiple. I have tried replacing "30ExGEPAc30Q4" (code below) with Range() and an array, but can't quite get it. Here's what I've got so far:
Sub test()
Dim x As Long
Dim lastrow As Long
lastrow = Sheets("LRP").ListObjects("Data_LRP").Range.Rows.Count
Worksheets("LRP").Activate
For x = lastrow To 1 Step -1
If Cells(x, 1).Value = "30ExGEPAc30Q4" Then
Rows(x).Delete
End If
Next x
End Sub

If I understand you correctly, this is what you're trying to achieve; I have cleaned up some of the unnecessary bits and now you just have to edit x and lastrow as is necessary.
Sub test()
Dim x As Long
Dim lastrow As Long
'lastrow = Sheets("LRP").ListObjects("Data_LRP").Range.Rows.Count
x = 1
lastrow = 21
'Worksheets("LRP").Activate
Do While x <= lastrow
' For x = lastrow To 1 Step -1
If Cells(x, 1).Value = "30ExGEPAc30Q4" Then
Rows(x).Delete
lastrow = lastrow - 1
Else
x = x + 1
End If
' Next x
Loop
End Sub

For those curious, it ended up looking like this. Thanks for all the help!
Sub Cull()
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim sht1row As Long
Dim sht2row As Long
Dim sht2total As Long
Dim DupID As String
Set sht1 = Worksheets("Data Form")
Set sht2 = Worksheets("LRP")
sht2.Activate
sht2total = Worksheets("LRP").ListObjects("Data_LRP").Range.Rows.Count
sht1row = 33
Do While sht1.Cells(sht1row, 2).Value <> ""
DupID = sht1.Cells(sht1row, 2).Value
For sht2row = 2 To sht2total
If DupID = Cells(sht2row, 1).Value Then
Rows(sht2row).Delete
sht2row = sht2row - 1
Exit For
End If
Next
sht1row = sht1row + 1
Loop
End Sub

Related

Replacing pos,neg values to another sheet

Screenshot#1
So i have to replace positive & negative numbers in column "A", from sheet "1" to sheet second[positive] and third sheet[negative].
Here is what i tried:
Sub Verify()
Dim row As Long
For row = 1 To 20
If ActiveSheet.Cells(row,1) <> "" Then
If ActiveSheet.Cells(row,1) > 0 Then
ActiveSheet.Cells(row,2) = ActiveSheet.Cells(row,1)
End If
End If
Next
End Sub
Here is what that program do:
Screenshot#2
So as we see i am getting positive values in column "B" sheet 1.
Your code is not currently working because you are only using ActiveSheet, rather than placing data on other worksheets as required. Below is some VBA code that loops column A in your original sheet, and outputs the data to column A in two different sheets as required:
Sub sSplitPositiveNegative()
Dim wsOriginal As Worksheet
Dim wsPositive As Worksheet
Dim wsNegative As Worksheet
Dim lngLastRow As Long
Dim lngPositiveRow As Long
Dim lngNegativeRow As Long
Dim lngLoop1 As Long
Set wsOriginal = ThisWorkbook.Worksheets("Original")
Set wsPositive = ThisWorkbook.Worksheets("Positive")
Set wsNegative = ThisWorkbook.Worksheets("Negative")
lngLastRow = wsOriginal.Cells(wsOriginal.Rows.Count, "A").End(xlUp).Row
lngNegativeRow = 2
lngPositiveRow = 2
For lngLoop1 = 1 To lngLastRow
If wsOriginal.Cells(lngLoop1, 1).Value > 0 Then
wsPositive.Cells(lngPositiveRow, 1) = wsOriginal.Cells(lngLoop1, 1)
lngPositiveRow = lngPositiveRow + 1
Else
wsNegative.Cells(lngNegativeRow, 1) = wsOriginal.Cells(lngLoop1, 1)
lngNegativeRow = lngNegativeRow + 1
End If
Next lngLoop1
Set wsPositive = Nothing
Set wsNegative = Nothing
Set wsOriginal = Nothing
End Sub
You will need to change the names of the worksheets referenced in the code to match those in your workbook.
Regards
Made the code a little reusable for you. Feel free to change sheet names or the last_row variable. The last_pos_val and last_neg_val are used so you won't have empty rows on the second and third sheet. You didn't specify what to do with zero, so it's currently added to the negative sheet.
Sub Verify()
Dim row As Long, last_row As Long, last_pos_val As Long, last_neg_val As Long
Dim ws_source As Worksheet, ws_pos As Worksheet, ws_neg As Worksheet
Dim wb As Workbook
Set wb = ThisWorkbook
Set ws_source = wb.Sheets("Sheet1")
Set ws_pos = wb.Sheets("Sheet2")
Set ws_neg = wb.Sheets("Sheet3")
last_pos_val = 1
last_neg_val = 1
last_row = 20
For row = 1 To last_row
If ws_source.Cells(row,1) <> "" Then
If ws_source.Cells(row,1) > 0 Then
ws_pos.Cells(last_pos_val,1) = ws_source.Cells(row,1)
last_pos_val = last_pos_val + 1
Else
ws_neg.Cells(last_neg_val,1) = ws_source.Cells(row,1)
last_neg_val = last_neg_val + 1
End If
End If
Next
End Sub
Split Positive & Negative
Adjust the values in the constants section.
Both subs are needed. The first sub calls the second one.
The Code
Option Explicit
Sub SplitPN()
Const Source As String = "Sheet1"
Const Positive As String = "Sheet2"
Const Negative As String = "Sheet3"
Const FirstRow As Long = 1
Const SourceColumn As Long = 1
Const PositiveFirstCell As String = "A1"
Const NegativeFirstCell As String = "A1"
Dim rngSource As Range
Dim rngPositive As Range
Dim rngNegative As Range
With ThisWorkbook
With .Worksheets(Source)
Set rngSource = .Columns(SourceColumn).Find(What:="*", _
LookIn:=xlFormulas, SearchDirection:=xlPrevious)
If rngSource Is Nothing Then Exit Sub
If rngSource.Row < FirstRow Then Exit Sub
Set rngSource = .Range(.Cells(FirstRow, SourceColumn), rngSource)
End With
Set rngPositive = .Worksheets(Positive).Range(PositiveFirstCell)
Set rngNegative = .Worksheets(Negative).Range(NegativeFirstCell)
End With
SplitPosNeg rngSource, rngPositive, rngNegative
End Sub
Sub SplitPosNeg(SourceRange As Range, PositiveFirstCell As Range, _
NegativeFirstCell As Range)
Dim Source, Positive, Negative
Dim UB As Long, i As Long
Source = SourceRange
UB = UBound(Source)
ReDim Positive(1 To UB, 1 To 1)
ReDim Negative(1 To UB, 1 To 1)
For i = 1 To UBound(Source)
Select Case Source(i, 1)
Case Is > 0: Positive(i, 1) = Source(i, 1)
Case Is < 0: Negative(i, 1) = Source(i, 1)
End Select
Next
PositiveFirstCell.Resize(UB) = Positive
NegativeFirstCell.Resize(UB) = Negative
End Sub

Adding and Setting Ranges in Excel VBA

I have this sample table.
What I am trying to do is to get all the cell values in all colored cells and transpose them to another worksheet.
I have trouble with the code below to add and set those ranges together so that I can transpose all of them in a ROW in the other worksheet. I have started with the code below
Sub AddRanges()
Dim inRange As Range, inRangeValues() As Variant, outRangeValues() As Variant
Dim finalRow As Long
Dim inRange As Range
Set inRange = Sheet1.Range("A1:A6", "C1:C6", C10:C14) 'I think i got this wrong; Error Type Mismatch
inRangeValues() = inRange.Value 'generate 2d array
outRangeValues = Application.Transpose(inRangeValues)
With Sheet2
finalRow = .Cells(Rows.Count, 1).End(xlUp).Row 'find last row
If inRange.Columns.Count > 1 Then '2d array for output
.Cells(finalRow + 1, 1).Resize(UBound(outRangeValues, 1), UBound(outRangeValues, 2)) = outRangeValues 'Resize according to output array dimensions
Else '1D array for output
.Cells(finalRow + 1, 1).Resize(1, UBound(outRangeValues, 1)) = outRangeValues
End If
End With
End sub
In this example, what is the best approach to combine these ranges so I can transpose them as a ROW? Thanks.
Your code has major problems due to:
Double declaration of inRange
Wrong syntax for Set inRange the entire address needs to be enclosed in a single pair of quotes
Try Set inRange = Range("a1:a6, c1:c6, c10:c14")
Wrong method of reading into an array
When you have a range that consists of multiple areas, you have to convert each area separately.
Then you can create a 1-D array from this depending on the order you wish to have these elements, and write it wherever you want.
For example:
Option Explicit
Sub test()
Dim inRange As Range, inRangeValues As Variant, outRangeValues As Variant
Dim finalRow As Long
Dim I As Long, J As Long, V As Variant, L As Long
Dim lCols As Long
Set inRange = Range("a1:a6, c1:c6, c10:c14")
ReDim inRangeValues(1 To inRange.Areas.Count)
For I = 1 To inRange.Areas.Count
inRangeValues(I) = inRange.Areas(I)
Next I
'how many columns?
lCols = 0
For I = 1 To UBound(inRangeValues, 1)
lCols = lCols + UBound(inRangeValues(I), 1)
Next I
ReDim outRangeValues(1 To lCols)
L = 0
For I = 1 To UBound(inRangeValues, 1)
For J = 1 To UBound(inRangeValues(I), 1)
L = L + 1
outRangeValues(L) = inRangeValues(I)(J, 1)
Next J
Next I
Stop
' enter some code to write the results where you want
' below is just throwaway for proof of concept
Range("f20").Resize(columnsize:=UBound(outRangeValues)).Value = outRangeValues
End Sub
Given your input, the above code would create output like:
You are correct that your code is wrong where you highlight. Try a union. From there, it should be pretty basic to just loop through your range and put them wherever you want in the Sheet2 spreadsheet. See if the below does what you need.
Sub AddRanges()
Dim inRange As Range, acell As Range, aCounter As Long
Const startAddress As String = "A1"
Set inRange = Union(Sheet1.Range("A1:A6"), Sheet1.Range("C1:C6"), Sheet1.Range("C10:C14"))
For Each acell In inRange.Cells
If Not IsEmpty(acell) Then
finalRow = sheet2.Cells(Rows.Count, 1).End(xlUp).Row + 1 'find last row
sheet2.Cells(finalRow, 1).Value = acell.Value
End If
Next acell
End Sub
Check it out.
Sub RngAreaTransps()
Dim RangeArea As Range, LstRw As Long
Dim sh As Worksheet, ws As Worksheet
Dim col As Long, InRange As Range
Set sh = Sheets(1)
Set ws = Sheets(2)
LstRw = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
With sh
Set InRange = .Range("A1:A6, C1:C6, C10:C14")
For Each RangeArea In InRange.Areas
With ws
col = .Cells(LstRw, .Columns.Count).End(xlToLeft).Column
If col <> 1 Then col = col + 1
RangeArea.SpecialCells(xlCellTypeConstants).Copy
.Cells(LstRw, col).PasteSpecial Transpose:=True
End With
Next RangeArea
End With
Application.CutCopyMode = False
End Sub

Exceeding row limit - create new sheet

I have 2 columns on a sheet "list", one column that lists all business entities, the other lists all org units. The functionality of the code below works perfectly but returns an error because it exceeds the sheet row limit.
The data is pasted onto a sheet "cc_act" is there a way to at point of error create a new sheet called "cc_act1"...."cc_act2" until the script is complete?
Declare Function HypMenuVRefresh Lib "HsAddin" () As Long
Sub cc()
Application.ScreenUpdating = False
Dim list As Worksheet: Set list = ThisWorkbook.Worksheets("list")
Dim p As Worksheet: Set p = ThisWorkbook.Worksheets("p")
Dim calc As Worksheet: Set calc = ThisWorkbook.Worksheets("calc")
Dim cc As Worksheet: Set cc = ThisWorkbook.Worksheets("cc_act")
Dim cc_lr As Long
Dim calc_lr As Long: calc_lr = calc.Cells(Rows.Count, "A").End(xlUp).Row
Dim calc_lc As Long: calc_lc = calc.Cells(1,
calc.Columns.Count).End(xlToLeft).Column
Dim calc_rg As Range
Dim ctry_rg As Range
Dim i As Integer
Dim x As Integer
list.Activate
For x = 2 To Range("B" & Rows.Count).End(xlUp).Row
If list.Range("B" & x).Value <> "" Then
p.Cells(17, 3) = list.Range("B" & x).Value
End If
For i = 2 To Range("A" & Rows.Count).End(xlUp).Row
If list.Range("A" & i).Value <> "" Then
p.Cells(17, 4) = list.Range("A" & i).Value
p.Calculate
End If
p.Activate
Call HypMenuVRefresh
p.Calculate
'''changes country on calc table
calc.Cells(2, 2) = p.Cells(17, 4)
calc.Cells(2, 3) = p.Cells(17, 3)
calc.Calculate
'''copy the calc range and past under last column
With calc
Set calc_rg = calc.Range("A2:F2" & calc_lr)
End With
With cc
cc_lr = cc.Cells(Rows.Count, "A").End(xlUp).Row + 1
calc_rg.Copy
cc.Cells(cc_lr, "A").PasteSpecial xlPasteValues
End With
Next i
Next x
Application.ScreenUpdating = True
End Sub
I suppose there are a few ways to handle something like this. See the code sample below, and adapt it to your specific needs.
Sub LongColumnToAFewColumns()
Dim wsF As Worksheet, WST As Worksheet
Dim rf As Range, rT As Range
Dim R As Long, j As Integer
' initialize
Set wsF = ActiveSheet
Set WST = Sheets.Add
WST.Name = "Results"
j = 1
For R = 1 To wsF.Cells(Rows.Count, 1).End(xlUp).Row Step 65536
wsF.Cells(R, 1).Resize(65536).Copy
WST.Cells(j, 1).PasteSpecial xlPasteValues
WST.Cells(j, 1).PasteSpecial xlPasteValues
j = j + 1
Next R
End Sub
As an aside, you may want to consider using MS Access for this kind of thing. Or, better yet, Python or even R. Good luck with your project.

Delete entire row based on date -excel VBA

I am trying to delete all row where column A value(Its formatted as date) is less than today's date. I have to run these through entire non empty A column. but facing an issue with the code to run as loop through entire rows. each time its deleting only 1 row. Please let me know how to run it through entire row set.
Sub DeleteRowBasedOnDateRange()
Dim spem As Workbook
Dim ws As Worksheet
Dim N As Long, I As Long
Set spem = Excel.Workbooks("SwitchP.xlsm")
Set ws = spem.Worksheets("data")
N = ws.Cells(Rows.count, "A").End(xlUp).row
For I = 2 To N
If Cells(I, "A").Value < Date Then
Cells(I, "A").EntireRow.Delete
I = I + 1
End If
Next I
End Sub
Quick fix
Loop backwards.
Also you do not need the I=I+1 as that is done automatically.
Sub DeleteRowBasedOnDateRange()
Dim spem As Workbook
Dim ws As Worksheet
Dim N As Long, I As Long
Set spem = Excel.Workbooks("SwitchP.xlsm")
Set ws = spem.Worksheets("data")
N = ws.Cells(ws.Rows.count, "A").End(xlUp).row
For I = N to 2 Step -1
If ws.Cells(I, "A").Value < Date Then
ws.Rows(I).Delete
End If
Next I
End Sub

Delete row's with a lower number value

Having a bit of trouble with the below macro. The idea is that it will look through the records on the 'Paste' sheet and compare against the number saved in 'B1' on the 'LastRun' sheet and remove the row if the number is lower. When running the macro, it gets stuck on the 'End If' section.
Sub DeleteOld()
Worksheets("Paste").Activate
endrow = Sheets("Paste").Range("X2000").End(xlUp).Row
OldData = Sheets("LastRun").Range("B1").Value
For i = endrow To 2 Step -1
NewData = Cells(i, 24).Value
If NewData < OldData Then
Cells(i, 24).EntireRow.Delete
End If
Next i
End Sub
Any help is appreciated.
Please try this:
Option Explicit
Sub DeleteOld()
Dim endrow As Long, i As Long
Dim newdata As Double, olddata As Double
olddata = Sheets("LastRun").Range("B1").Value
With Worksheets("Paste")
endrow = .Range("X2000").End(xlUp).Row
For i = endrow To 1 Step -1
newdata = .Cells(i, 24).Value
If newdata < olddata Then
.Cells(i, 24).EntireRow.Delete
End If
Next i
End With
End Sub
Maybe this will help. However, in order to simplify, it's checking the value in the first column in the sheet where row deletion should take place.
Public Sub test()
Dim i As Long
Dim lastRow As Long
Dim rngB2 As Range
Set rngB2 = Sheets("lastRun").Cells(1, 2)
With Sheets("paste")
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = lastRow To 1 Step -1
Dim curRng As Range
Set curRng = .Cells(i, 1)
If curRng.Value < rngB2.Value Then
.Rows(curRng.Row).Delete
'curRng.Interior.Color = rgbRed
End If
Next i
End With
End Sub

Resources