Insert row after specific text is found - excel

I am fairly new to excel and I am trying to setup a macro that adds a row after a specific point of the worksheet. Example: Row 2 contains text "Original", so it should insert a new row afterwards, and so on.
I know that it might be easier to insert before something, so I could change the setup (so for example the word "original" would be in row 2 and the new row is added above it) if that is an easier solution.
Is this possible? How?
Thanks for all the possible help.

Slightly simpler than the previous answer:
Sub NewRowInsert()
Dim SearchText As String
Dim GCell As Range
SearchText = "Original"
Set GCell = Cells.Find(SearchText).Offset(1)
GCell.EntireRow.Insert
End Sub
This will work with the current active sheet. If you want to use some other sheet, say Sheet2, you could use:
Set GCell = Worksheets("Sheet2").Cells.Find(SearchText).Offset(1)
and if you wanted to operate on a different workbook e.g. TestBook.xlsx, you could use:
Set GCell = Workbooks("TestBook.xlsx").Worksheets("Sheet2").Cells.Find(SearchText).Offset(1)
Note that I've avoided the use of select. This may not be an issue for you, but if you're searching through thousands of rows and making many replacements it could speed up your code considerably.

Try the code below = you can change the textvalue variable value to what ever you want to search for.
Sub newRow()
Dim textvalue As String
textvalue = "Original"
Cells.Find(What:=textvalue, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.offset(rowOffset:=1, columnOffset:=0).Activate
ActiveCell.EntireRow.Insert
End Sub

Related

Run-time error '91' VBA when trying to find a match in Worksheet [duplicate]

What I want:
I've got a lot of sheets whith different devices. Let's call one of these sheets "WS1".
And I've got a seperate sheet with all existing devices and the appropriate OS next to it. This one we call "list".
Now I want the other sheets (e.g. the "WS1") to check the "list", find the right device, and copy the right OS into the WS1-sheet.
the manual way would be:
select cell "C3" of WS1 and copy it.
open the "list"-Sheet and find the copied entry
select the cell left to the found entry and copy it
open the WS1 again, select the left cell right next to the active cell and paste the new clipboard (which contains the OS)
select the next cell which is under and on the right side of the active cell.
loop until every device in WS1 is filled with an OS
What I've got so far:
Dim DataObj As New MSForms.DataObject
Dim strCliBoa As String
'strCliBoa = DataObj.GetText
DataObj.GetFromClipboard
Range("C3").Select
Selection.Copy
strCliBoa = DataObj.GetText
Sheets("list").Select
Range("A1").Select
Cells.Find(What:=strCliBoa, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=True, SearchFormat:=False).Activate
ActiveCell.Offset(0, -1).Select
Selection.Copy
strCliBoa = DataObj.GetText
Sheets("WS1").Select
ActiveCell.Offset(0, -1).Select
ActiveSheet.Paste
ActiveCell.Offset(1, 1).Select
My issue:
"Runtime Error 91: Object variable or with block variable not set"
and it marks the cells.find-method.
Can someone tell me what I'm doing wrong?^^
Thanks in advance!
(oh, almost forgot: I'm using ms excel 2010 on Win7)
If the string you're looking for isn't found you'll get that error. The find function returns "Nothing" if nothing is found
Dim r As Range
Set r = Cells.find(What:=strCliBoa, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=True, SearchFormat:=False)
If r Is Nothing Then
'handle error
Else
'fill in your code
End If
I'll provide you an answer using the VLOOKUP() function. So Sheet1 contains several devices and I need to find the correct OS. Sheet2 contains the matching between device and OS.
On Sheet1 enter this formula in the cell next to device and pull it down (of course edit to your specific needs).
=VLOOKUP(A2;Sheet2!$A$1:$B$20;2;0)
EDIT: the VLOOKUP function will only work if the OS is in second column. Either switch around the columns or use a helper column at the end to contain the OS.
In the sheet where you have the Device name (WS1) put formula:
=INDEX(List!$A$2:$B$10;MATCH('WS1'!C3;List!$B$2:$B$10;0);1)
Where :
List!$A$2:$B$10 is a range where you have the Devices + OS in the list
'WS1'!C3 is the Device you want to search for in the list ("WS1" in your case)
List!$B$2:$B$10 is the column on Sheet List, where the devices are listed.
Edit 1 - VBA code
If you want to use VBA then use this :
Sub FindDevicePasteOS()
'Find corresponding OS for the device
Dim intRow As Integer
Dim wsht As Worksheet
For Each wsht In Worksheets
If wsht.Name <> "List" Then 'add more sheets you want to exclude using OR (e.g. ... Or wsht.Name <> "Cover Sheet" Then)
For intRow = 3 To wsht.Cells(Rows.Count, 3).End(xlUp).Row 'presuming there is nothing else in the column C below the devices
If Not Worksheets("List").Cells.Find(what:=wsht.Cells(intRow, 3)) Is Nothing Then
wsht.Cells(intRow, 2) = Worksheets("List").Cells.Find(what:=wsht.Cells(intRow, 3)).Offset(0, -1)
End If
Next intRow
End If
Next wsht
End Sub
So I used a psuedo solution where I added the If x is nothing block to the code to skip over the err'd pieces. I was able to process about 80% of the data which is good for me. I still can't understand why Find would return nothing.
Another interesting and maybe related problem occurred in a different computer running the same macro - after I ran into this problem a few times, my computer gave me a blue screen with a 'thread stuck in driver' message. Could they be related? Excel processing to much to fast and get's mixed in the thread processing?
Food for though, I dunno why the find won't just work every-time.
In Sobigen post I had to switch the part LookAt:=xlPart to LookAt:=xlWhole to get it to work because If r Is Nothing Then was throwing an error when it found partial matches. Other than that the code worked great thanks!

Search/Replace in One Column Impacting Entire Worksheet

In Column L (only) I want to replace any instance of data with "True" regardless of what was originally in any of the Column L cells. The code I tried was:
With ActiveSheet
intLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Let strSelectRange = "L2" & ":" & "L" & intLastRow
Range(strSelectRange).Select
Cells.Replace What:="*", Replacement:="True", LookAt:=xlPart _
, SearchOrder:=xlByColumns, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End With
First, I used .Rows.Count, "A" because in that column every row has data so I know how many rows to go down in Column L. In Column L many cells will be blank.
When I run this, every cell in the entire worksheet that has anything in it, is changed to True, not just the data in Column L.
Another method I tried was:
Range("L2:L1200").Select
Selection.Replace What:="*", Replacement:="True", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Range("A1").Select
What I don't like about this is that I picked L1200 as the number of rows just to be sure I'd search farther than the actual last row that can contain data. I'm worried that this method might cause some kind of problem at some point.
What I'd really like to know is what I'm doing wrong in the first code example.
Thanks for any help you can offer!!!
Search & Replace in Column
Use Option Explicit always, to quicker learn about the occurring
errors and to be forced to declare variables.
You should always declare your rows as Long.
When you use the With statement you use the dots on everything, even
on .Range and .Cells etc. The code might work in this case
(ActiveSheet) anyway, but it is incorrect.
Avoid the use of ActiveSheet, use the worksheet name.
Avoid the use of Select. There are many posts (articles) about this.
When ever you use Cells without anything behind it, it refers to all the
cells in the worksheet.
The first thing in the Replace function (Find function) is the range
where you're going to Replace (Find, Search). It can be a column, it
can be Cells or just a smaller range.
The Code
Sub SROneColumn()
Const cVntLRColumn As Variant = "A" ' Last Row Column Letter/Number
Const cVntCriteria As Variant = "L" ' Criteria Column Letter/Number
Const cLngFirstRow As Long = 2 ' First Row Number
Const cStrReplace As String = "True" ' Replace String
Dim lngLastRow As Long ' Last Row Number
Dim strSelectRange As String ' Select Range Address
With ActiveSheet
lngLastRow = .Cells(.Rows.Count, cVntLRColumn).End(xlUp).Row
strSelectRange = .Range(.Cells(cLngFirstRow, cVntCriteria), _
.Cells(lngLastRow, cVntCriteria)).Address
.Range(strSelectRange).Replace What:="*", Replacement:=cStrReplace, _
LookAt:=xlPart, SearchOrder:=xlByColumns, MatchCase:=False
End With
End Sub
An interesting way to use a worksheet without the use of an object variable:
Sub SRSheet()
Const cStrSheet As Variant = "Sheet1" ' Worksheet Name/Index
With ThisWorkbook.Worksheets(cStrSheet)
End With
End Sub
Range(strSelectRange).Select
selects a range (though best to avoid Select) but then your code does nothing with that selection because Cells is the entire sheet.
Maybe you want instead:
Range(strSelectRange).Replace What:="*", Replacement:="True", LookAt:=xlPart

VBA replace everything in sheet except first rows

I have a working VBA script which currently replaces all dots by commas (posted below). However I would the script avoid the first two rows and change everything else. What would be the best and easiest way to do this? I have only found solutions where you have to set a range and but I want it to work for all excel sheets regardless of the number of rows or columns.
Sheets("Sheet1").Select
Cells.Replace what:=".", Replacement:=",", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
You can still use range, but generate it dynamically: use the macro recorder and see what it gives you if you select all cells with the Select All button at the top left corner, then hold down CTRL and unselect by clicking the row headers.
After having a selected range, you can use Application.Selection instead of Cells.
set wsCSV = ... (your csv worksheet)
set rng = wsCSV.UsedRange
set ws = ... (your worksheet)
ws.UsedRange.Offset(1).ClearContents()
ws.Range("A2").Resize(rng.Rows.Count, rng.Columns.Count).Values = rng.Values

Get reference to next visible cell in autofiltered table

I have a UserForm that sits on top of my spreadsheet and simply displays information from the row containing the currently selected cell. Buttons on the form allow the user to move up/down the spreadsheet row by row. For example, when the "next record" button is clicked, the code executed is something like:
Cells(ActiveCell.Row + 1, ActiveCell.Column).Select
LoadValues
I would like it to work even if the user filters the data and then loads the form. However, using the above code, it wants to loop through all cells, not just the ones still visible after filtering. I've seen solutions for immediately looping through only visible cells, e.g.,
For Each viscell In rng.SpecialCells(xlCellTypeVisible)
...
Next viscell
So there seems like there should be a better, more direct way to do this than looping through all rows until I get to the next one with .Hidden = False but I can't seem to figure out how to get a reference to "the next visible cell" in order to select it.
Any pointers would be greatly appreciated. Thanks.
Here's a lightning-quick way to activate the first not-blank, visible cell in a filtered range. Just change 'Range("A1")' to whatever range you'd like to search after. Also consider whether you want xlByColumns or xlByRows.
ActiveSheet.Cells.SpecialCells(xlCellTypeVisible).Find(What:="*", _
After:=ActiveSheet.Range("A1"), LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
I recommend using tables whenever possible, as they have variable named ranges built-in that are easy to reference.
Here's another example, using tables. It's targeted to search a specific column, so it'll be even faster.
Just find and replace TABLE_NAME and COLUMN_NAME with your values.
ActiveSheet.Range("TABLE_NAME[[#All], COLUMN_NAME]]").SpecialCells(xlCellTypeVisible).Find _
(What:="*", After:=ActiveSheet.Range("TABLE_NAME[[#Headers],[COLUMN_NAME]]"), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
No loops required because it's built off of Excel's "Find" functionality.
And just a tip,you can also use this to grab the data of such a cell on separate worksheet without activating/selecting it at all.
Just find and replace Dbl_EXAMPLE, SHEET_NAME, TABLE_NAME and COLUMN_NAME with your references.
Dim Dbl_EXAMPLE as Double
Dbl_EXAMPLE = Sheets("SHEET_NAME").Range("TABLE_NAME[[#All], COLUMN_NAME]]").SpecialCells(xlCellTypeVisible).Find _
(What:="*", After:=Sheets("SHEET_NAME").Range("TABLE_NAME[[#Headers],[COLUMN_NAME]]"), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Value2
Just replace ".Value2" at the end with whatever property you're looking for.
Examples:
.Formula
.Row
.Column
The list goes on
I really struggled with this too and used Ryan's solution, albeit a little abbreviated, for my purposes..
This may be as brief as it gets. :)
ActiveCell.EntireColumn.SpecialCells(xlCellTypeVisible).Find(What:="*", After:=ActiveCell).Activate
Here is one method using a simple loop until the next row down is visible.
Dim rng As Range
Set rng = ActiveCell
Dim n As Long: n = 1
Do Until rng.Offset(n, 1).Rows.Hidden = False
n = n + 1
Loop
rng.Offset(n, 1).Select
LoadValues

Issue reading hidden column using VBA in Excel 2013

I am currently having issues with a Macro I am programming for Excel 2013 regarding reading hidden columns. I am trying to utilize Column A as a row of unique keys to allow me to quickly develop logic that hides and shows a row based on the key value in column A. When I hide column A manually in the sheet for visual purposes I am then unable to read from that column, aka my code returns an error. If I show the column the code executes clearly. Thanks in advance for the help!
Public Sub hideRow(findId As String, sheetName As String)
Dim lastRow As Long
Dim foundCell As Range
Dim hideThisRowNum As Integer
'Get Last Row
lastRow = Worksheets(sheetName).Range("A" & Rows.Count).End(xlUp).Row
'Find ID
With Worksheets(sheetName).Range("a1:a1000") 'This needs to be A1 to AxlDown
Set foundCell = Worksheets(sheetName).Range("A1:A" & lastRow).Find(What:=findId, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
End With
'Get Row # to Hide
hideThisRowNum = Val(foundCell.Row)
'Hide row
Worksheets(sheetName).Rows(hideThisRowNum).Hidden = True
'Set Add To Action Plan = No
Worksheets(sheetName).Range("G" & hideThisRowNum).Value = "No"
End Sub
The problem is in the .Find() call. Using LookIn:=xlValues won't find hidden cells. Change it to LookIn:=xlFormulas and it should work.

Resources