Change excel cell text based on content - excel

Im trying to make a VBA in excel that changes the content of a cell based on the text in the cells. All the cells I want to change contains a structure of "< (space) 0.005" the number however varies a lot and setting up all the different numbers would take too long.
I have a base for an older project but I can't seem to tweak it to the required needs.
Sub FillEmptyBlankCellWithValue()
Dim cell As Range
Dim InputValue As String
On Error Resume Next
InputValue = InputBox("Enter value that will fill empty cells in selection", _
"Fill Empty Cells")
For Each cell In Selection
If IsEmpty(cell) Then
cell.Value = InputValue
End If
Next
End Sub

You're on a right track. But in general I'd avoid using Selection or any other Select operations as they are prone to many errors.
Instead, I'd recommend using active (detected dynamic) range, or let the user define the range. eg.
Option Explicit
Private Sub fill_blanks
Dim ws as Worksheet: Set ws = Sheets("Sheet1") ' set yours
Dim firstcell as String, lastcell as String, fillvalue as String
Dim datarange as Range
firstcell = InputBox("Enter the starting cell of your data range")
lastcell = InputBox("Enter the last cell of your data range")
fillvalue = InputBox("Enter the value to fill blank cells with")
Set datarange = ws.Range(Trim(firstcell) & ":" & Trim(lastcell))
Dim cell as Range
For each cell in datarange
If IsEmpty(cell) Then
cell = fillvalue
End If
Next cell
End Sub
You could also let them define the range inside a pre-defined cells in
the worksheet, or detect the active range with .End(xlUp) for row
and .End(xlToLeft) for column. Up to you really..
Note: This will paste the result as a String (or "Text") as a Cell Format, you also need to change the Range.Format property.

Related

Can not SUM selected cells With SUMIF

I would like to be able to Check for criteria "owners" In column A and SUM cell from the same row column E with the cell above and repeat through the spread sheet where owner is found.
I have tried to use Function =SUMIF(A3,"*owner*",E2:E3) This returns the Value above the cell in the row with owner but does not SUM them.
I have also tried this VBA CODE and it does the same thing.
Sub vba_sumif()
Dim gRange As Range
Dim sRange As Range
Set gRange = Range("A3")
Set sRange = Range("E2:E3")
Range("G2") = _
WorksheetFunction.SumIf(gRange,"*Owner*", sRange)
End Sub
Ideally it would return the summed cells in the above cell. using VBA
Thanks again,
Aaron
Well first of all, I would suggest just using the formula unless you have a reason not to:
Formula:: Your first error with the formula is both ranges need to be the same size.
VBA:: Same thing here with range sizes, then you also need to remember to make sure Excel knows what sheet you're referring to. I like to do this with a With My_Worksheet_Namestatement, then include a . before any range from that sheet. Just make sure to change the sheet name to your sheet name
Option Explicit
Sub vba_sumif()
Dim TableSheet As Worksheet
Dim gRange As Range
Dim sRange As Range
Set TableSheet = Worksheets("TableSheet")
With TableSheet
Set gRange = .Range("A2:A13")
Set sRange = .Range("E2:E13")
.Range("G2").Value = _
WorksheetFunction.SumIf(gRange, "*Owner*", sRange)
End With
End Sub

Bold First Occurence in a Series Only Excel VBA

I have a long list of equipment like this;
I would like to be able to run a VBA script that allows excel to change the format of the first of a series so that they are more visible. Is this a possibility?
This is housed in an excel table, not sure if that has an impact.
You could iterate through the range update format if below cell<>previous cell.
Sub UpdateCatHead(ByRef rng As Range, Optional col_index As Integer = 1)
Dim rng_search As Range
'lets ,make sure to have range of one column
Set rng_search = rng.Columns(col_index)
Dim cell As Range, prev_cell As Range
Dim prev_cat As String
For Each cell In rng_search.Cells
'check if empty is empty and exit for?
If cell.Row = 1 Then
'update cell to bold here
Debug.Print (cell.Row)
Else
Set prev_cell = cell.Worksheet.Cells(cell.Row - 1, cell.Column) 'cell above
If CStr(cell.Value) <> CStr(prev_cell.Value) Then
'update cell to bold here
Debug.Print (cell.Row)
End If
End If
Next cell
End Sub
call Sub like this:
UpdateCatHead ThisWorkbook.Sheets("data").Range("A1:A100")

Clear only cells containing formulas

I need a VBA code that clears only cells containing formulas and skip cells containing values in a given Excel Worksheet.
I have the following Code:
Dim rng As Range, cl As Range
Set rng = ThisWorkbook.Sheets("MATRIX").Range("C2:AU10000")
For Each cl In rng
If cl.Hyperlinks = .Hyperlinks Then
cl.ClearContents
End If
Next cl
Try this approach, please:
If cl.HasFormula Then
cl.ClearContents
End If
This should be the quickest way
rng.SpecialCells(xlCellTypeFormulas).ClearContents
HasFormula vs SpecialCells(xlTypeCellTypeFormulas)
Option Explicit
Sub RemoveHasFormula()
Dim rng As Range, cl As Range
Set rng = ThisWorkbook.Sheets("MATRIX").Range("C2:AU10000")
For Each cl In rng
If cl.HasFormula Then cl.ClearContents
Next cl
End Sub
Sub RemoveSpecialCells()
Dim rng As Range
Set rng = ThisWorkbook.Sheets("MATRIX").Range("C2:AU10000")
rng.SpecialCells(xlCellTypeFormulas).ClearContents
End Sub
Delete formulae via a range's XML structure
For the sake of the art and in order to complete the above solutions I demonstrate a rather unknown approach using a range's xml spreadsheet value (so called ".Value(11)"):
Option Explicit
Sub ExampleCall()
Dim rng As Range: Set rng = Sheet1.Range("a11:b14")
'a) Get range data as xml spreadsheet value
Dim s As String: s = rng.value(xlRangeValueXMLSpreadsheet) ' //or: s = rng.Value(11)
'b) delete formulae and write data back to range
ClearFormulae s ' call sub changing s (By Reference)
rng.value(xlRangeValueXMLSpreadsheet) = s
End Sub
Sub ClearFormulae(s)
'Purpose: delete formulae in xlRangeValueXMLSpreadsheet contents of a given range
'Author : https://stackoverflow.com/users/6460297/t-m
'Date : 2020-07-18
'[1]Set xml document to memory
Dim xDoc As Object: Set xDoc = CreateObject("MSXML2.DOMDocument.6.0")
'[2]Add namespaces.
xDoc.SetProperty "SelectionNamespaces", _
"xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet' " & _
"xmlns:ht='http://www.w3.org/TR/REC-html40'"
'[3]Load cells with formulae into xml document.
If xDoc.LoadXML(s) Then ' load wellformed string content
Dim cell As Object, cells As Object
Set cells = xDoc.SelectNodes("//ss:Cell[#ss:Formula]") ' XPath using namespace prefixes
For Each cell In cells
cell.RemoveAttribute ("ss:Formula")
cell.SelectSingleNode("ss:Data/#ss:Type").Text = "String"
cell.SelectSingleNode("ss:Data").Text = ""
Next cell
'[4] return xml as string content
s = xDoc.XML
End If
End Sub
Further hint to Example call
Instead of replacing the same range, you can also copy the whole data set (including formats) to another sheet via:
Sheet2.Range("D2").Resize(rng.Rows.Count, rng.Columns.Count).value(11) = s
Caveat
As #ChrisNeilson pointed out,
"this can also gives unexpected results in some circumstances
where the range being processed by ClearFormulae includes some cells
that contain formula referring to cells outside the range being processed".
Testing Value(11) against other solutions
Testing with a 20% formula rate (in a double column range) shows that the SpecialCells approach (posted by #Storax and #VBasic2008) starts extremely fast, but looses against my Value(11) approach as soon as the data range exceeds ~ 115,100 rows.
The HasFormula solution (#FaneDuru) seems to be restricted to smaller ranges getting soon time consuming at ranges over 10000 rows.

Find text in one column, if true then match the text in the column next to it with a column on a separate sheet and insert a formula

Here's what I have:
Response Flow
I have one sheet called Response Flow that has Response, Y/N and a Total. If the Response has a Y next to it I want to match the Response Name with the Response Name on Sheet 2 ("Campaigns") and insert a formula in the column next to the response name on Sheet 2 using VBA code. Below is what I have so far.
Sub Volume_Calc()
Dim LastRowR As Long
Dim LastRowC As Long
Dim LastRowI As Long
Dim LastRowA As Long
Dim rngFoundCell As Range
Dim cell As Range
Dim text As String
Dim FindRow As Range
LastRowR = Range("C65536").End(xlUp).Row
LastRowC = Range("K65536").End(xlUp).Row
LastRowI = Range("I65536").End(xlUp).Row
LastRowA = Range("A65536").End(xlUp).Row
Set FindRow = Worksheets("ResponseFlow").Range("C:C").Find(What:="Y",
LookIn:=xlValues)
Do While FindRow = True
If Application.Match(Worksheets("Campaigns").Range("K6"),
Worksheets("ResponseFlow").Range("A4:A" & LastRowA), 0) Then
Worksheets("Campaigns").Range("I6:I" & LastRowI).Formula = "=INDEX(ResponseFlow!$B$3:$B$145,MATCH(Campaigns!$K6,ResponseFlow!$A$3:$A$145,0))"
End If
Loop
End Sub
What you're intending to do seems like it'd be easier to do in Excel without VBA, but if you insist on having some macro insert formulas, this might be an easy approach. First put the dynamic formula you want to be pasting in to the right of the columns with a Y/N, SOMEWHERE in your sheet. In my example below I used Cell("Z1"). Make sure it's dynamic so that if you were to copy/paste formula into another cell, it would adjust correctly.
Again make sure whatever dynamic match formula you want to the right of your values is somewhere and configured to be dynamic. In my example it's on Response ws in cell Z1.
Sub Volume_Calc()
Dim Resp_WS As Worksheet: Set Resp_WS = Worksheets("ResponseFlow")
Dim CAMP_WS As Worksheet: Set CAMP_WS = Worksheets("Campaigns")
Dim rCell As Range
Dim cCell As Range
'Loops through Response Sheeet column "C" looking for values of "Y"
For Each rCell In Intersect(Resp_WS.Range("C:C"), WResp_WS.UsedRange).Cells
If UCase(rCell.Value) = "Y" Then
'When finds a cell with Y, it then loops through Campaigns Sheet column "I"
'looking for a value that matches one column to the left where the "Y" was found
For Each cCell In Intersect(CAMP_WS.UsedRange, CAMP_WS.Range("I:I")).Cells
'When match is found, the macro will insert the formula to the right
'of the cell in Campaigns, with the dynamically updated formula in cell Z1
If cCell.Value = rCell.offset(0,-1).Value Then
cCell.Offset(0, 1).FormulaR1C1 = Resp_WS.Range("Z1").FormulaR1C1
End If
Next cCell
End If
Next rCell
End Sub

Using Match and Address functions within Macro or VBA

I have two worksheets, I want to use a value in sheet to_approve to lookup against column A in sheet submitted, then identify the cell reference so I can paste a value in the cell adjacent (column B).
I have used the following to identify the cell reference, but I don't know how to use it in VBA code.
=ADDRESS(MATCH(To_Approve!D19,Submitted!A:A,0),1,4,1,"submitted")
While many functions can be used in VBA using Application.WorksheetFunction.FunctionName ADDRESS is not one of these (MATCH is)
But even it it was available I would still use a Find method as below as it:
gives you the ability to match whole or part strings, case sensitive or not
returns a range object to work with if the value is found
readily handles a no match
you can control the point in the range being search as to where the search starts
multiple matches can be returned with FindNext
something like
Sub GetCell()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets("submitted")
Set rng1 = ws.Columns("A").Find(Sheets("To_Approve").[d19], , xlValues, xlWhole)
If Not rng1 Is Nothing Then
MsgBox rng1.Address & " in sheet " & ws.Name
Else
MsgBox "not found", vbCritical
End If
End Sub
This example should give you an idea of how to find a corresponding value on another sheet and place a second value in the the column to the left. When using VBA, it is not necessary to select cells and then paste; you can directly enter a value into a range (cell) object.
Sub TransferValue()
Dim rngSearch As Range
Dim rngFind As Range
Dim dValue As Double
' initialization
Set rngSearch = Worksheets("to_approve").Range("D19")
dValue = Date
' find the match & insert value
Set rngFind = Worksheets("submitted").Columns(1).Find(What:=rngSearch.Value)
If Not rngFind Is Nothing Then
rngFind.Offset(ColumnOffset:=1).Value = dValue
End If
End Sub
(Note: dValue is a placeholder for whatever value you want to enter.)

Resources