Find and select multiple cells within a worksheet - excel

I am new to writing macros and have search everywhere for a solution to my problem with no luck, so I'm hoping for some help here.
I have an Excel spreadsheet containing multiple calculation which are automated. This means a big part of the spreadsheet is locked for other users who only need to do the calculations. Basically what I want is to have this spreadsheet in two different languages. So using a macro I want to change all the text content in my spreadsheet from one language to another. Since i only want one spreadsheet (because I keep updating it and adding new calculations to it) I thought a macro with a button to switch between the 2 language was the best solution.
Here is my problem. I used find and replace to replace each word which is working fine.
Sub Rename_EN()
'
ActiveSheet.Unprotect
Cells.Select
Selection.Replace What:="rød", Replacement:="red", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Replace What:="grøn", Replacement:="green", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Replace What:="blå", Replacement:="blue", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Replace What:="Flt-tag", Replacement:="FLT-roof", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
End Sub
But the text also have technical terms, fx. I want F_(LT-tag) to be replaced with F_(LT-roof), but with (LT-roof) as a sub-scripted text.
I searched for a long time and came to the conclusion that it is not possible to simple subscript the text in a code. (if it is, then please feel free to tell me how :)) I then found this code that can change specific characters to subscript and superscript:
Sub Super_Sub()
Dim NumSub
Dim NumSuper
Dim SubL
Dim SubR
Dim SuperL
Dim SuperR
Dim CheckSub
Dim CounterSub
Dim CheckSuper
Dim CounterSuper
Dim Cell
'
CheckSub = True
CounterSub = 0
CheckSuper = True
CounterSuper = 0
Cell = ActiveCell
'
NumSub = Len(Cell) - Len(Application.WorksheetFunction.Substitute(Cell, "[", ""))
NumSuper = Len(Cell) - Len(Application.WorksheetFunction.Substitute(Cell, "{", ""))
'
If Len(Cell) = 0 Then Exit Sub
If IsError(Application.Find("[", ActiveCell, 1)) = False Then
Do
Do While CounterSub <= 1000
SubL = Application.Find("[", ActiveCell, 1)
SubR = Application.Find("]", ActiveCell, 1)
ActiveCell.Characters(SubL, 1).Delete
ActiveCell.Characters(SubR - 1, 1).Delete
ActiveCell.Characters(SubL, SubR - SubL - 1).Font.Subscript = True
CounterSub = CounterSub + 1
If CounterSub = NumSub Then
CheckSub = False
Exit Do
End If
Loop
Loop Until CheckSub = False
End If
'
'
If IsError(Application.Find("{", ActiveCell, 1)) = False Then
Do
Do While CounterSuper <= 1000
SuperL = Application.Find("{", ActiveCell, 1)
SuperR = Application.Find("}", ActiveCell, 1)
ActiveCell.Characters(SuperL, 1).Delete
ActiveCell.Characters(SuperR - 1, 1).Delete
ActiveCell.Characters(SuperL, SuperR - SuperL - 1).Font.Superscript = True
CounterSuper = CounterSuper + 1
If CounterSuper = NumSuper Then
CheckSuper = False
Exit Do
End If
Loop
Loop Until CheckSuper = False
End If
'
End Sub
So I wanted to make a button that would run the macros in a specific order. The problem here is, that I need to select the cells with { and [ to run the code.
Can I rewrite this code to be used for a whole spreadsheet? I again searched for a solution and couldn't find one, so I tried to make yet another macro to run before this, that finds and selects all cells in a sheets containing { and [. Again I hit a wall since I can't get the it to select multiple cells in a whole sheet.

One way I can think of doing it is to have a second hidden sheet containing the replacement text in the relevant cells. You can then use FIND to find all cells containing a value, check it doesn't hold a formula and swap the value with that held in the second sheet.
Sub Test()
Dim firstAddress As String
Dim rCell As Range
Dim sValue As String
Dim MainSheet As Worksheet
Dim SecondSheet As Worksheet
'MainSheet contains your formula & text.
'SecondSheet only contains values in the text cells.
With ThisWorkbook
Set MainSheet = .Worksheets("Sheet1")
Set SecondSheet = .Worksheets("Sheet2")
End With
Set rCell = MainSheet.Cells.Find("*", , xlValues, xlWhole, , xlNext, True)
If Not rCell Is Nothing Then
firstAddress = rCell.Address
Do
'If the cell doesn't contain a formula swap its value with
'the value held in the second sheet.
If Not rCell.HasFormula Then
sValue = rCell.Value
rCell.Value = SecondSheet.Range(rCell.Address).Value
SecondSheet.Range(rCell.Address).Value = sValue
End If
Set rCell = MainSheet.Cells.FindNext(rCell)
Loop While rCell.Address <> firstAddress
End If
End Sub

Related

VBA Excel Find string in column and offset delete and repeat

I have a working code to find a specific string in a column of a specific sheet, offset and clear the contents of a specific cell. However it only clears the first occurrence of this search and I would like to have the code work on all occurrences. Can someone help me to wrap a Loop or a FindNext around this code because I wasn't able to. Please see here below the code I already have. Thnx
Dim SearchValue6 As String 'located B9
Dim Action6 As Range 'clear
SearchValue6 = Workbooks.Open("C:\Users\.......xlsm").Worksheets("Sheet1").Range("B9").Value
On Error Resume Next
Worksheets(2).Columns("A:A").Select
Set Action6 = Selection.Find(What:=SearchValue6, After:=ActiveCell, LookIn:=xlFormulas2, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Action6 Is Nothing Then
'MsgBox "No clearings made in " & ActiveWorkbook.Name
Else
Action6.Activate
ActiveCell.Offset(0, 1).Select
ActiveCell.ClearContents
End If
Please, try using the next updated code and send some feedback:
Sub FindMultipleTimes()
Dim SearchValue6 As String 'located B9
Dim Action6 As Range 'clear
SearchValue6 = Workbooks.Open("C:\Users\.......xlsm").Worksheets("Sheet1").Range("B9").Value
Dim ws As Worksheet: Set ws = Worksheets(2)
Dim firstAddress As String
Set Action6 = ws.Columns("A:A").Find(What:=SearchValue6, After:=ws.Range("A1"), LookIn:=xlFormulas2, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not Action6 Is Nothing Then
firstAddress = Action6.address
Do
Action6.Offset(0, 1).ClearContents
Set Action6 = ws.Columns("A:A").FindNext(Action6) 'find the next occurrence
Loop While Action6.address <> firstAddress
Else
MsgBox SearchValue6 & " could not be found in column ""A:A"" of sheet " & ws.name
End If
End Sub
I only adapted your code, but do you want letting the workbook necessary to extract SearchValue6 value, open?

Is it possible to use VBA to make a conditional copy of the formula from the active cell down the column

I want to implement a VBA Code to work with multiple different sheets, for example: it starts by looking for a certain number in the first row, once it's found, it jumps to that column and types a certain formula into the 2nd cell in that column, so far it works good, But the issue is that I wanna make it to Autofill that formula down the column if the first cell in that row contains data.
Like if A2 is not blank, continue the auto fill the cell in the active column (let's say the active column is D, then the it would fill the Cell d2 if a2 not blank) and stops once the cell in A Column is blank .. etc
So, Is it possible?
Sub Macro1()
Rows("1:1").Select
Selection.Find(What:="156", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=True, SearchFormat:=False).Activate
ActiveCell.Offset(1).Select
ActiveCell.FormulaR1C1 = _
"= "Formula will be here""
End Sub
Might be best to save a copy of your workbook before running the code below.
Maybe something like this is what you're after. If Find found something in column D, then it puts the dummy formula in the range D2:D?, where ? is whatever the last row in column A is (which I think is what you described).
Option Explicit
Sub Macro1()
Dim ws As Worksheet
Set ws = ActiveSheet ' Can you refer to the workbook and worksheet by name? Please do if possible
With ws
Dim cellFound As Range
Set cellFound = .Rows(1).Find(What:="156", LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True, SearchFormat:=False)
If cellFound Is Nothing Then
MsgBox ("The value was not found in the first row of sheet '" & ws.Name & "'. Code will stop running now")
Exit Sub
End If
Dim lastRow As Long
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range(cellFound.Offset(1), .Cells(lastRow, cellFound.Column)).FormulaR1C1 = "=""Formula will be here"""
End With
End Sub
Check this simple code, I think it will satisfy your needs:
Sub Macro1()
Rows("1:1").Select
Selection.Find(What:="156", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=True, SearchFormat:=False).Activate
col_Num = ActiveCell.Column
total_Rows = WorksheetFunction.CountA(Range("A:A"))
Cells(2, col_Num).Select
Cells(2, col_Num) = "=Put your Formula here"
begin_Cell = Cells(2, col_Num).Address(False, False)
end_Cell = Cells(total_Rows, col_Num).Address(False, False)
Selection.AutoFill Destination:=Range(begin_Cell & ":" & end_Cell)
End Sub
There are easier ways to locate a column header label although I'm unclear on why you are using the LookAt:=xlPart argument. It seems to me you should not have to 'wildcard' the search but a 'wild card' search can be accommodated.
Sub FindnFill()
dim m as variant
with worksheets("sheet1")
m = application.match("*156*", .rows(1), 0)
if not iserror(m) then
if not isempty(.cells(2, "A")) then
.range(.cells(2, m), .cells(.rows.count, "A").end(xlup).offset(0, m-1)).formula = _
"=""formula goes here"""
else
.cells(2, m).formula = _
"=""formula goes here"""
end if
end if
end with
end sub
Find & Fill
About the Find Method
It is best practice to always set the following three parameters, because they
are saved each time they are used.
LookIn - If you use xlFormulas, it will find e.g. =A2 + 156, which you don't want.
LookAt - If you use xlPart it will find e.g. 1567, which you don't want.
SearchOrder - Not important, since a row is being searched.
Additionally SearchDirection is by default xlNext and can therefore safely be omitted.
Additionally MatchCase is by default False and can therefore safely be omitted.
Additionally SearchFormat - To use it you previously have to set Application.FindFormat.NumberFormat and can therefore safely be omitted.
The Code
Sub FindFill()
Const cDblFind As Double = 156 ' Found Value
Const cLngRow As Long = 1 ' Found Row Number
Const cVntColumn As Variant = "A" ' First Column Letter/Number
Const cStrFormula As String = "=RC[-1]+5" ' Formula
Dim objFound As Range ' Found Column Cell Range
Dim lngRow As Long ' First Column Non-empty Rows
With ActiveSheet.Rows(cLngRow)
' Check if cell below cell in First Column and Found Row is empty.
If .Parent.Cells(cLngRow, cVntColumn).Offset(1, 0).Value = "" Then Exit Sub
' Calculate First Column Non-empty Rows.
lngRow = .Parent.Cells(cLngRow, cVntColumn).End(xlDown).Row - cLngRow
' Find cell in Found Row containing Found Value.
Set objFound = .Find(What:=cDblFind, After:=.Cells(.Row, .Columns.Count), _
LookIn:=xlValues, LookAt:=xlWhole, Searchorder:=xlByRows)
If Not objFound Is Nothing Then
' Write Formula to Found Column Range
objFound.Offset(1, 0).Resize(lngRow).FormulaR1C1 = cStrFormula
End If
End With
End Sub

My code works on the first cell its set to and none of the others

So the title says it all. I've written this short code to try and take website URL's and remove unwanted aspects to make them all nice and pretty for clients. However, for some reason this sort of template I've been using a lot has failed me this time around by only giving the royal treatment to B2 the only cell directly called out in the code. I debugs fine and runs fine just not accomplishing what I'd like it to. Not having an error makes this hard to discern what the problem is. If any of you can see whats going on here please do let me know.
Sub Website()
Application.ScreenUpdating = False
Range("B2").Select
Dim TitleString As Range, cel As Range
Set TitleString = ActiveCell
Do Until IsEmpty(ActiveCell)
For Each cel In TitleString
If InStr(1, cel.Value, "https://") > 0 Then '
Selection.Replace What:="https://", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End If
If InStr(1, cel.Value, "http://") > 0 Then
Selection.Replace What:="http://", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End If
If InStr(1, cel.Value, "/") > 0 Then
Selection.Replace What:="/*", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End If
If InStr(1, cel.Value, "www.") > 0 Then
Exit For
ElseIf InStr(1, cel.Value, "www.") = 0 Then
ActiveCell.Value = "www." & ActiveCell.Value
Exit For
End If
Next cel
ActiveCell.Offset(1, 0).Select
Loop
Application.ScreenUpdating = True
End Sub
Anytime one uses Select it forces vba to slow down.
This avoids select as well as loops.
Sub Website()
Dim rng As Range
Dim ws As Worksheet
Application.ScreenUpdating = False
Set ws = ActiveSheet
Set rng = ws.Range(ws.Cells(2, 2), ws.Cells(ws.Rows.Count, 2).End(xlUp))
rng.Replace "https://", ""
rng.Replace "http://", ""
rng.Replace "/*", ""
rng.Replace "www.", ""
rng.Value = Evaluate("INDEX(""www.""&" & rng.Address & ",)")
Application.ScreenUpdating = True
End Sub
Before:
After:
This looks like it's failing because you set the TitleString range outside of the do loop so there's only one cell to loop through. You can simplify this a lot by removing the do loop entirely. Instead declare the cells you want to loop through as a range initially.
Sub Website()
Application.ScreenUpdating = False
Range("B2").Select
Dim rng As Range
Dim cel As Range
Set rng = Range(Selection, Selection.End(xlDown))
For Each cel In rng
' IF STATEMENTS
Next
Application.Screenupdating = True
End Sub

Most efficient way to hide all rows in which a certain value occurs

The Excel auto filter is not properly working if there is more than one row for headings, and it is also not assignable to specific columns, only. So I want to filter by VBA macro.
I have
Sheet2.Range("A1:A40").Find(what:="Software", _
After:=Cells(4, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False _
).EntireRow.Hidden = True
But this only hides the row with the first occurance of "Software". Is there no way to use .find for that or do I have to use a loop?
If your range isn't super big, you can always loop through it, checking for a value, and hiding if found:
Sub test()
Application.ScreenUpdating = False
Dim lastRow As Integer, i As Integer
Dim rng As Range, cel As Range
lastRow = Sheet2.UsedRange.Rows.Count
For i = lastRow To 1 Step -1
If Cells(i, 1).Value = "Software" or cells(i,1).Value = "software" Then
Cells(i, 1).EntireRow.Hidden = True
End If
Next i
Application.ScreenUpdating = True
End Sub
Note: the software part is case sensitive, which is why I used Or.

Excel macro select cell that contains a string and replace a character

I have a worksheet with more than 200 cells.
Each cell contains a formula as below:
=AVERAGE('worksheetname'!range)
I want to run a macro that changes the formula to following formula:
=IFERROR(AVERAGE('worksheetname'!range),100%)
I have worked out that I can change =AVERAGE into for example &AVERAGE and than search & replace &AVERAGE with &IFERROR. It will allow me to search for cells which contains &IFERROR and add missing parenthesis at the end of formula )
I want to build a macro but have few problems:
how to search & replace it all once for each cell
macro gives me a mismatch error
below is a code for my macro:
Sub aaaa()
'
' IFERROR Macro
'
'
Dim myRange As Range
Dim myCell As Range
Dim i As Integer
Set myRange = Range("E4:BB120")
Sheets("Zones").Select
Cells.Replace What:="=AVERAGE(", Replacement:="&IFERROR(AVERAGE(", LookAt _
:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
For Each myCell In myRange
If myCell Like "*&IFERROR*" Then
myCell.Select
i = 1
Do While i < 2
Selection.Replace What:=")", Replacement:="),100%)", LookAt _
:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
i = i + 1
Loop
End If
Next myCell
Cells.Replace What:="&IFERROR(AVERAGE(", Replacement:="=IFERROR(AVERAGE(", LookAt _
:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
You might find it easier to do the replacement "manually" in code instead of using Replace :
Sub aaaa()
Dim myRange As Range
Dim c As Range
Dim f As String, i As Long
On Error Resume Next
Set myRange = Sheets("Zones").Range("E4:BB120").SpecialCells( _
xlCellTypeFormulas)
On Error GoTo haveError
If myRange Is Nothing Then Exit Sub
Application.Calculation = xlCalculationManual
For Each c In myRange.Cells
f = c.Formula
If f Like "=AVERAGE(*)" Then
c.Formula = "=IFERROR(" & Right(f, Len(f) - 1) & ",100%)"
i = i + 1
End If
Next c
MsgBox "Replaced " & i & " formulas"
haveError:
If Err.Number <> 0 Then MsgBox Err.Description
Application.Calculation = xlCalculationManual
End Sub

Resources