VBA Excel - Select rows with Left value = to variable - vba

Having trouble with this code. No errors but also doesn't seem to do anything.
In my sheet, column "M" has some values that start with the letter "T" I want to select the entire row for these. Thanks in advance.
Sub trace1()
Dim trace As String
trace = "T"
Dim LR As Long, i As Long
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If Left(Range("M" & i).Value, 1) = trace Then Rows("i:i").Select
Next i
End Sub

One possible way to answer the question as written:
Sub trace1()
Dim trace As String
trace = "T"
Dim LR As Long, i As Long
Dim SelectedRows As Range
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If Not SelectedRows Is Nothing Then
If Left(Range("M" & i).Value, 1) = trace Then Set SelectedRows = Union(SelectedRows, Rows(i))
Else
If Left(Range("M" & i).Value, 1) = trace Then Set SelectedRows = Rows(i)
End If
Next i
SelectedRows.Select 'Replace with .Copy if that's what you really wanted.
End Sub

If you are trying to select the row assigned to variable "i", you would use:
Sub trace1()
Dim trace As String
trace = "T"
Dim LR As Long, i As Long
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If Left(Range("M" & i).Value, 1) = trace Then Rows(i).Select
Next i
End Sub

"Rows("i:i")" won't work. Try collecting all the addresses of all ranges in one string and then selecting the string. Note the comma which separates each range.
Sub trace1()
Dim sRange As String
Dim trace As String
trace = "T"
Dim LR As Long, i As Long
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If Left(Range("M" & i).Value, 1) = trace Then sRange = sRange & "," & i & ":" & i
Next i
Range(Mid(sRange, 2)).Select
End Sub

using AutoFilter to give you the range as is, or the actual address
avoids slow loops
Sub trace2()
Dim strTrace As String
Dim strAddress
Dim rng1 As Range
strTrace = "T"
Set rng1 = Range([m1], Cells(Rows.Count, "M").End(xlUp))
With rng1
.AutoFilter 1, strTrace & "*"
Set rng1 = rng1.Cells(1).Offset(1, 0).Resize(rng1.Rows.Count - 1, 1)
strAddress = rng1.SpecialCells(xlVisible).EntireRow.Address
End With
MsgBox "rows that start with " & strTrace & vbNewLine & strAddress
ActiveSheet.AutoFilterMode = False
End Sub

The expression
Rows("i:i").Select
throws an error -- Rows() won't recognize the text value "i:i" as an argument.
Rows(i).Select
will work. But it won't DO anything you can see, other than the last row should be selected when the code is finished running. You may want to do whatever needs to be done to the "T" rows at the next step in your code before your get to the Next i step.
EDIT:
OK, you want multiple rows selected when the code is finished. That can be done:
Dim RowsDescript As String
Dim trace As String
trace = "T"
Dim LR As Long, i As Long
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If Left(Range("M" & i).Value, 1) = trace Then RowsDescript = RowsDescript & i & ":" & i & ","
Next i
If Len(RowsDescript) > 0 Then
RowsDescript = Left(RowsDescript, Len(RowsDescript) - 1) ' removes the last comma
Range(RowsDescript).Select
End If
What you want to end up with is an expression that looks like this:
Range("9:9,12:12,16:16").Select
How you get there is, when a row is identified as having the "T" that you want in it, add the row number and a colon and the row number again and a comma to the string RowDescript. So at the end of the loop, you end up with the string having
9:9,12:12,16:16,
in it. But we need to strip off that last comma, so there's the check for a non-zero length string, remove the last character, and then select those rows.

1."T" is not equal to "t", to remove "case sensitivity" it is required to use LCase or UCase (low case or upper case)
2.Rows("i:i") replaced by Row(i)
Sub trace1()
Dim trace As String
trace = "T"
Dim LR As Long, i As Long
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If UCase(Left(Range("M" & i).Value, 1)) = UCase(trace) Then Rows(i).Select
Next i
End Sub
And also one comment, at the final will be selected only last row in range, for example row 1,5 and 10 will start from "T", so at the end will be selected only 10th row
updated against question in the comments
this will allow you to select rows which starting from "t" or "T", but this method allow to select not more than 45 rows.
Sub Macro1()
Dim trace$, LR&, i&, Rng$
trace = "T": Rng = ""
LR = Range("M" & Rows.Count).End(xlUp).Row
For i = 1 To LR
If UCase(Left(Range("M" & i).Value, 1)) = UCase(trace) Then Rng = Rng & i & ":" & i & ","
Next i
Rng = Left(Rng, Len(Rng) - 1)
Range(Rng).Select
End Sub
Use copy/paste one by one row if you need copy rows from one sheet to another, or sort range and select range from first row to the last row where cell value start from "T"

Related

Vba search and paste solution

i would like to come up with vba sub that searching value from one specified cell (job) across all sheets and then pastes rows but only with selected columns. If value not found any error message instead paste value.
I know it's bigger project but I'm fresh so try to my best.
As far i have solution for whole rows:
Sub TEST()
Dim tws As String
Dim l_row As String
Dim l_rowR As String
Dim job As String
Dim i As Integer
Set tws = ThisWorkbook.Sheets("Data")
tws.Range("A20") = "STATS:"
job = tws.Range("B5")
lastRow = Worksheets("Sheet1").Range("E" & Rows.Count).End(xlUp).Row
lastRowRpt = tws.Range("A" & Rows.Count).End(xlUp).Row
For i = 3 To lastRow
If Worksheets("Sheet1").Range("E" & i).Value = job And _
Worksheets("Sheet1").Range("D" & i).Value = "x2" Then
Worksheets("Sheet1").Rows(i).Copy
lastRowRpt = tws.Range("A" & Rows.Count).End(xlUp).Row
tws.Range("A" & lastRowRpt + 1).Select
tws.Paste
End If
Next i
End Sub

Different sheet pasting

I have written a code which gives me the errors (if any cell is non numeric) in a separate sheet called "Error_sheet".
But the output is a bit clumsy as it gives me non numeric cell address in a confusing fashion. Like the errors will not be pasted one after another. There will be some blanks in between if there are more than one non Numeric cells.
Sub Test()
Dim LastRow As Long, i As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
If IsNumeric(Range("A" & i).Value) Then
Else
Sheets("Error").Range("A" & Row).Value = "Error in" & i & " row of ColumnNAme"
Row = Row + 1
End If
Next i
End Sub
It gives me output like shown below but can I get the output like Error in 7,14 rows of column name in a desired cell of "Error_sheet".
[![Output][1]][1]
[1]: https://i.stack.imgur.com/JqXwq.png
My understanding of what you've written is that you want something like this.
Option Explicit
Sub Test()
' Unqualified book/sheet below, means code will always run the isnumeric check on the cells of the active sheet. Is that what you want? '
Dim LastRow As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Dim Index as long
Dim i As Long
Dim NonNumericRows() as string
Redim NonNumericRows(1 to lastrow)
For i = 2 To LastRow
If not(IsNumeric(Range("A" & i).Value)) Then
Index = index + 1
NonNumericRows(Index) = cstr(i)
End if
Next i
Redim preserve NonNumericRows(1 to index)
Sheets("Error").Range("A1").Value = "Error in row(s): " & strings.join(nonnumericrows,", ") & " of ColumnNAme"
End Sub
Hope it works or helps.
Like QHarr suggested, using Option Explicit is normally a good idea, and try not to use VBA operators as variables.
Also when working with more than 1 sheet, its best to define each in the code. I dont know what your first sheet is called, so please change the line: Set shSource = Sheets("Sheet1") to suit:
Option Explicit
Sub SubErrorSheet()
Dim lr As Long, i As Long
Dim shSource As Worksheet, shError As Worksheet
Set shSource = Sheets("Sheet1")
Set shError = Sheets("Error")
lr = shSource.Range("A" & Rows.count).End(xlUp).Row
For i = 2 To lr
If Not IsNumeric(shSource.Range("A" & i).Value) Then
shError.Range("A" & Rows.count).End(xlUp).Offset(1, 0).Value = "Error in row " & i & " of ColumnNAme"
End If
Next i
End Sub

VBA SUMIFS - Not Working, All Inputs Return Correct Values

The following code is throwing an 1004 runtime error when I go to run. The debugger highlights the SUMIFS function in just above part 2.
The goal of this sub is to locate duplicate rows using columns 1, 3, and 5 as "primary-keys" and then combine values by column for rows 6-7 and 10-17 based off those values for each row. Hence the SUMIFS.
I'm confused. Using the immediate window I can return the correct values for each section of the SUMIFS fuction (ws.Cells(lRow, lCol).Select will select the correct cell, etc.). My next thought was that the ranges were not interpreted correctly by the SUMIFS so I popped the same function, using specific ranges, into the immediate window and received the same error. See line below for immediate window entry - note that the goal is to combine values between rows 21:23 in this example.
debug.Print application.WorksheetFunction.SumIfs(range("F21:F23"), range("A9:A30"), range("A21").Value, range("C9:C30"), range("C21").Value, range("E9:E30"), range("E21").Value)
I'm assuming, and 100% sure, that named ranges, .codenames, and variables are working as desired. That said, I've been mistaken before.
Any help would be greatly appreciated.
Private Sub dba_combine_rows()
Const COL_TRIPS = 6
Const COL_EMP_TRIP = 7
Const COL_LN_HC = 10
Const COL_USN_PR = 17
Dim lLastRow As Long
Dim ws As Worksheet
Set ws = DBA
Dim answer As Integer
answer = MsgBox("Are you sure you want to combine rows?", vbYesNo, "Combine Rows")
If answer = vbNo Then
Exit Sub
End If
'Get the last row
Dim i As Long
For i = Range("inputRange" & ws.CodeName).Column To (Range("inputRange" & ws.CodeName).Column + Range("inputRange" & ws.CodeName).Columns.Count - 1)
If ws.Cells(ws.Rows.Count, i).End(xlUp).Row > lLastRow Then
lLastRow = ws.Cells(ws.Rows.Count, i).End(xlUp).Row
End If
Next i
''Combine, start modify
'Set aliases for columns A & B & C, used for checking duplicates
Dim rngA As Range, rngB As Range, rngC As Range
Set rngA = ws.Range("inputRange" & ws.CodeName).Columns(1)
Set rngB = ws.Range("inputRange" & ws.CodeName).Columns(3)
Set rngC = ws.Range("inputRange" & ws.CodeName).Columns(5)
Dim lRow As Long, lCol As Long, strHolderA As String, lHolderR As Long
For lRow = ws.Range("inputRange" & ws.CodeName).Row To lLastRow
'Part 1 - Check for duplicate entity-country
If Application.CountIfs(rngA, ws.Cells(lRow, rngA.Column), rngB, ws.Cells(lRow, rngB.Column), rngC, ws.Cells(lRow, rngC.Column)) > 1 Then
strHolderA = (ws.Cells(lRow, rngA.Column).Value & ws.Cells(lRow, rngB.Column).Value & ws.Cells(lRow, rngC.Column).Value)
lHolderR = lRow
For lCol = COL_TRIPS To COL_USN_PR
If lCol = COL_EMP_TRIP Then
lCol = COL_LN_HC
End If
ws.Cells(lRow, lCol).Value = Application.WorksheetFunction.SumIfs( _
ws.Range(Col_Letter(lCol) & lRow & ":" & Col_Letter(lCol) & lLastRow), rngA, ws.Cells(lRow, rngA.Column).Value, rngB, ws.Cells(lRow, rngB.Column).Value, rngC, ws.Cells(lRow, rngC.Column).Value)
Next lCol
'Part 2 - Delete similar rows, excluding 1st
Dim lRow2 As Long
For lRow2 = ws.Range("inputRange" & ws.CodeName).Row To lLastRow
If (ws.Cells(lRow2, rngA.Column).Value & ws.Cells(lRow2, rngB.Column).Value & _
ws.Cells(lRow2, rngC.Column).Value) = strHolderA And lRow2 <> lHolderR Then
Rows(lRow2 & ":" & lRow2).Select
Selection.Delete Shift:=xlUp
lRow2 = lRow2 - 1
End If
Next lRow2
End If
Next lRow
End Sub
The sum_range parameter (the first one) has to be the same size as the criteria ranges, which all. also, have to be the same size.
"F21:F23" is just 3 cells, while the others i.e. "A9:A30" count 22 cells each.

Take out characters and put in a new column in Excel

Hi I'm a bit new to vba so I will try to explain my problem as far as possible.
I have a dataset in Excel in Column A, I have a lot of file names like this:
1. AB000**1234**45.tif
2. AB000**1235**45.tif
3. AB000**1236**45.tif
4. AB000**1237**45.tif
etc..
From this I want to take out all the strong characters and put in column C so it will look like this:
1. 1234
2. 1235
3. 1236
4. 1237
etc..
At the moment I have a code that looks like this:
Sub TakeOut
Dim str1 As String
Dim LR As Long
Dim cell As Range, RNG As Range
LR = Range("A" & Rows.Count).End(xlUp).Row
Set RNG = Range("A1:A" & LR)
For Each cell In RNG
L = Len(RNG)
If L > 0 Then
RNG = ...
End If
Next cell
Range("C:C").Columns.AutoFit
End Sub
I have tried to count left(5) and right(6) but don't know how to take out the 4 character that I want.
Hope you can help me with this.
If you want to take out the strong characters from the string. Try it below. It will take all the Bold Characters in a cell and place it in C column.
Hope you are looking for this?
Sub get_bold_content()
Dim lastrow, i, j, totlength As Long
lastrow = Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To lastrow
totlength = Len(Range("A" & i).Value)
For j = 1 To totlength
If Range("A" & i).Characters(j, 1).Font.Bold = True Then
outtext = outtext & Range("A" & i).Characters(j, 1).Text
End If
Next j
Range("C" & i).Value = outtext
outtext = ""
Next i
End Sub
Take a look at the Mid() Function link.
usage in your case:
Mid(cell.Value, 6, 4) 'First parameter is the string, 6 is the start character, 4 is length
The easiest way without looping would be something like this:
Sub TakeOut()
Dim rng As Range
Set rng = Range("A1", Range("A" & Rows.Count).End(xlUp))
rng.Offset(, 1) = Evaluate("IF(" & rng.Address & "="""","""",MID(" & rng.Address & ",6,4))")
End Sub

Clear content of a range if cell contains a specific text

I want to make a macro that clears the content of the cells in the blue border (~40.000 Rows) when the cells in the red border (column AX) contain the text "NoBO" (=No Backorder) without losing the formulas in the columns AP:AX.
Sub clear_ranges()
Dim ws As Worksheet
Dim x As Integer
Dim clearRng As Range
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Input")
For x = 6 To ws.Range("B" & Rows.Count).End(xlUp).Row
If (ws.Range("AX6" & x).Value = "NoBO") Then
If clearRng Is Nothing Then
Set clearRng = ws.Range("B6" & x & ":" & "AN6" & x)
Else
Set clearRng = Application.Union(clearRng, ws.Range("B6" & x & ":" & "AN6" & x))
End If
End If
Next x
clearRng.Clear
End Sub
And for some reason:
For x = 6 To ws.Range("B" & Rows.Count).End(xlUp).Row
gives me a error "Overflow". After searching I know what this error means but I can't find a solution for this.
tl;dr - I want to delete the range B6:B##### (till last row) to AN6:AN####*(till last row) if cell AX##### containts NoBO
It is too easy to get an overflow using Integer. Replace:
Dim x As Integer
with:
Dim x As Long
Try:
Sub clear_ranges()
Dim ws As Worksheet
Dim x As Integer
Dim clearRng As Range
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Input")
For x = 6 To ws.Range("B" & Rows.Count).End(xlUp).Row
If ws.Range("AX" & x).Value = "NoBO" Then
ws.Range("B" & x & ":" & "AN" & x).Clear
End If
Next x
Application.ScreenUpdating = True
End Sub
I think the Union function can only store up to 30 ranges so it might not suit your needs.
Hi if you are Deleting Rows it's the Best to use a For Each Loop or start from the bottom of the column and work up.
'Loop through cells A6:Axxx and delete cells that contain an "x."
For Each c In Range("AX6:A" & ws.Range("B" & Rows.Count).End(xlUp).Row)
If c.Value2 = "NoBo" Then
Set clearRng = ws.Range("B" & c.Row & ":" & "AN" & c.Row)
End If
clearRng.Clear
Next
try this
Option Explicit
Sub clear_ranges()
Dim ws As Worksheet
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Sheets("Input")
With ws
With .Range("B5:AX" & .Cells(.Rows.Count, "B").End(xlUp).Row) 'take all data
.AutoFilter Field:=49, Criteria1:="NoBO" 'filter to keep only rows with "NoBO" in column "AX" (which is the 49th column from column "B"
With .Offset(1).Resize(.Rows.Count - 1) 'offset from headers
If Application.WorksheetFunction.Subtotal(103, .Columns(1)) > 0 Then Intersect(.SpecialCells(xlCellTypeVisible), ws.Columns("B:AN")).ClearContents 'clear cells in columns "B:AN" of filtered rows
End With
.AutoFilter 'remove autofilter
End With
End With
Application.ScreenUpdating = True
End Sub
You can try
Assuming that there are no blank cells in AX Column
Sub clr_cell()
For i = 6 To ActiveSheet.Range("AX6", ActiveSheet.Range("AX6").End(xlDown)).Rows.Count
'counts the no. of rows in AX and loops through all
If ActiveSheet.Cells(i, 50).Value = "NoBo" Then
ActiveSheet.Range(Cells(i, 2), Cells(i, 40)).ClearContents
'clears range B to AN
End If
Next i
End Sub
I tested this on 40k rows and it worked fine. It takes a while to execute due to the no. of rows maybe.