I'm trying to write a macro in Excel to sum by font colour. A colleague has suggested I use this article for help: ExtendOffice. However, it always gives a syntax error, and I'm not sure why.
The code is:
Public Function SumByColor(pRange1 As Range, pRange2 As Range) As Double
Application.Volatile
Dim rng As Range
Dim xTotal As Double
xTotal = 0
For Each rng In pRange1
If rng.Font.Color = pRange2.Font.Color Then
xTotal = xTotal + rng.Value
End If
Next
SumByColor = xTotal
End Function
The only reason you might get an error, is if one of the cells inside pRange1 has a String or some other non-numeric value.
You can modify your code by adding If IsNumeric(rng.Value) Then.
Modifed Code
Public Function SumByColor(pRange1 As Range, pRange2 As Range) As Double
Application.Volatile
Dim rng As Range
Dim xTotal As Double
xTotal = 0
For Each rng In pRange1
If rng.Font.Color = pRange2.Font.Color Then
If IsNumeric(rng.Value) Then ' <-- the only thing which might give you an error, if you have a String inside one of the cells
xTotal = xTotal + rng.Value
End If
End If
Next rng
SumByColor = xTotal
End Function
How it is being called from a sheet's cell:
Note: if you change the font's color of one of the cells, you will need to refresh the value in the cell by pressing {Enter} on the cell with the formula again.
This works good for me. Maybe you simply called it in the wrong manner.
For example, if I have data on the "D" column with some fonts in it, this code would work for me:
Public Function SumByColor(pRange1 As Range, pRange2 As Range) As Double
Application.Volatile
Dim rng As Range
Dim xTotal As Double
xTotal = 0
For Each rng In pRange1
If rng.Font.Color = pRange2.Font.Color Then
xTotal = xTotal + rng.Value
End If
Next
SumByColor = xTotal
MsgBox (SumByColor)
End Function
Sub count_colors()
Call SumByColor(Range("D2", "D" & ActiveSheet.UsedRange.Rows.Count), Range("D2"))
End Sub
(I ignored D1 since it's a header for me. You can change to anything you like)
I do have to agree with Rory, however, that using fonts as data separators is not a good idea
Related
I am writing a check in/out program in excel and have gotten te request that if a line contains "|0|" it should get a different font color.
I've tried with Instr and Cells().Characters but I cannot seem to figure out how to do it.
The cells can have a variety of rows of text. Which is easy enough to solve with splitting them on a return and having a for loop loop, but I cannot seem to figure out how to assign a different font color to a row of text that contains the required value.
Image for illustration of the data:
How do I best solve this?
Added information:
The goal of this is that on button press the whole line of text where the |O| is would be collored differently. Other lines of text that do not have this will remain the same color.
Like in this image as a concept
[]
try this
Public Sub ExampleMainSub()
Dim cell As Range
For Each cell In Selection
If HasMySymbols(cell.Value) Then
WorkWithCellContent cell
Else
cell.Font.ColorIndex = xlAutomatic
cell.Font.TintAndShade = 0
End If
Next cell
End Sub
Private Sub WorkWithCellContent(ByVal cell As Range)
Dim arr As Variant
arr = Split(cell.Value, Chr(10))
Dim firstPosOfRow As Long
firstPosOfRow = 1
Dim subLine As Variant
For Each subLine In arr
If HasMySymbols(subLine) Then
cell.Characters(start:=firstPosOfRow, Length:=Len(subLine)).Font.Color = vbRed
Else
cell.Characters(start:=firstPosOfRow, Length:=Len(subLine)).Font.ColorIndex = xlAutomatic
End If
firstPosOfRow = firstPosOfRow + Len(subLine) + 1 '+1 is needed
Next subLine
End Sub
Private Function HasMySymbols(ByVal somestring As String) As Boolean
HasMySymbols = InStr(1, somestring, "|0|") > 0
End Function
Try this. It works for me.
Sub ChangeRowFontColour()
Dim rng As Range
Dim TextToFind As String
Dim FirstFound As String
TextToFind = "Specific Text"
With ActiveSheet.UsedRange
Set rng = .Cells.Find(TextToFind, LookIn:=xlValues)
If Not rng Is Nothing Then
FirstFound = rng.Address
Do
rng.EntireRow.Font.ColorIndex = 3
For Each part In rng
lenOfPart = Len(part)
lenTextToFind = Len(TextToFind)
For i = 1 To lenOfPart
tempStr = Mid(part, i, lenTextToFind)
If tempStr = TextToFind Then
part.Characters(Start:=i, Length:=lenTextToFind).Font.ColorIndex = 0
End If
Next i
Next
Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And rng.Address <> FirstFound
End If
End With
End Sub
I have simple code that sums a range of number based on its font color. But it also sums the subtotals in that range. How can I skip a cell if its a subtotal or in some other way exclude to sum the subtotals?
Here is my code:
Public Function SumByColor(pRange1 As Range, pRange2 As Range) As Double
'Update by Extendoffice
Application.Volatile
Dim rng As Range
Dim xTotal As Double
xTotal = 0
For Each rng In pRange1
If rng.Font.Color = pRange2.Font.Color Then
xTotal = xTotal + rng.Value
End If
Next
SumByColor = xTotal
End Function
assuming subtotals are either use subtotal formula or sum (and nothing you want to include does) this works:
Public Function SumByColor(pRange1 As Range, pRange2 As Range) As Double
'Update by Extendoffice
Application.Volatile
Dim rng As Range
Dim xTotal As Double
xTotal = 0
For Each rng In pRange1
If InStr(1, LCase(rng.Formula), "sum") = 0 And InStr(1, LCase(rng.Formula), "subtotal") = 0 Then
If rng.Font.Color = pRange2.Font.Color Then
xTotal = xTotal + rng.Value
End If
End If
Next
SumByColor = xTotal
End Function
if there are sums you want included and the subtotals do use the subtotal formula then remove the first instr condition that I added
credit to #Foxfire And Burns And Burns who got there first though
I am trying to write a function that automatically deletes the minimum value for a given selection of cells. I know how to find the minimum value but I just don't know how to delete that value.
Here's what I've got.
Function MinDel(Stuff)
MinDel = Application.Worksheetfunction.min(stuff)
End Function
How do I delete the MinDel value?
You could modify the function from here like that
Option Explicit
Function AddressOfMax(rng As Range) As Range
Set AddressOfMax = rng.Cells(WorksheetFunction.Match(WorksheetFunction.Max(rng), rng, 0))
End Function
Function AddressOfMin(rng As Range) As Range
Set AddressOfMin = rng.Cells(WorksheetFunction.Match(WorksheetFunction.Min(rng), rng, 0))
End Function
Sub TestIt()
Dim rg As Range
Dim rgMin As Range
Set rg = ActiveSheet.Range("A1:A6")
Set rgMin = AddressOfMin(rg)
rgMin.Clear
End Sub
As mentioned in the comments, a UDF (User Defined Function) cannot change a value or range in Excel by default and a Sub should be used. This is my way to delete the minimal value in the Selection:
Public Sub DeleteMinimum()
Dim myRange As Range
Dim minValue As Double
Dim myMin As Range
If Not TypeOf Selection Is Excel.Range Then Exit Sub
Dim valueAssigned As Boolean: valueAssigned = False
minValue = 0
For Each myRange In Selection
If IsNumeric(myRange) Then
If Not valueAssigned Then
valueAssigned = True
minValue = myRange
Set myMin = myRange
Else
If myRange < minValue Then
minValue = myRange
Set myMin = myRange
End If
End If
End If
Next myRange
If Not myMin Is Nothing Then
myMin = "DELETED!"
End If
End Sub
The procedure below will delete the lowest value in a selection, provided that the selection comprises more than one cell. It ignores all but the first column of the selection.
Sub DelMin()
' 05 Jan 2019
Dim Arr As Variant, i As Integer
Dim Mm As Variant, m As Integer
With Selection
If .Cells.Count > 1 Then
Arr = .Value
For i = 1 To UBound(Arr)
If Not IsEmpty(Arr(i, 1)) Then
If IsEmpty(Mm) Or (Arr(i, 1) < Mm) Then
Mm = Arr(i, 1)
m = i
End If
End If
Next i
.Cells(m, 1).ClearContents
End If
End With End Sub
apologies if this has already been answered although I have searched and search with no luck. in a nutshell im trying to change the cell colour if that cell value does not match a value in a named range.
I have tried a number of methods although none are working for me , any help from the vba gurus would be greatly appreciated.
essentially I have a list of values on sheet1(Create) G2:G5000 that I need to know when they don't match value on sheet2(lists) S2:S64 <--this has a named range of Make.
please see a copy of my current code below
Sub testMake()
Dim MkData As Range, MkVal As Range
Dim MKArray As Variant
Set MkData = Worksheets("Create").Range("G2:G5000")
Set MkVal = Worksheets("Lists").Range("Make")
For Each MyCell In MkData
If MyCell.Value <> Range("MkVal") Then
MyCell.Interior.ColorIndex = 6
Else
MyCell.Interior.ColorIndex = xlNone
End If
Next
End Sub
Thanks you all for any help in advance, I have been looking at this for a few days now and seem to be no closer than when I started.
While I would use conditional formatting you could slightly adapt your code as below to do this programatically:
Sub testMake()
Dim MkData As Range
Dim MkVal As Range
Dim MKArray As Variant
Dim lngRow As Long
Dim rng1 As Range
Dim rng2 As Range
MKArray = Worksheets("Create").Range("G2:G5000").Value2
Set rng1 = Worksheets("Create").Range("G2")
Set MkVal = Range("Make")
For lngRow = 1 To UBound(MKArray)
If IsError(Application.Match(MKArray(lngRow, 1), MkVal, 0)) Then
If Not rng2 Is Nothing Then
Set rng2 = Union(rng2, rng1.Offset(lngRow - 1, 0))
Else
Set rng2 = rng1.Offset(lngRow - 1, 0)
End If
End If
Next
If Not rng2 Is Nothing Then rng2.Interior.ColorIndex = 6
End Sub
You could be using Worksheet function Vlookup to compare between the two ranges:
Sub testMake()
Dim MkData As Range, MkVal As Range
Dim MKArray As Variant
Dim result As Variant
Set MkData = Worksheets("Create").Range("G2:G5000")
Set MkVal = Worksheets("Lists").Range("Make")
For Each MyCell In MkData
On Error Resume Next
result = Application.WorksheetFunction.VLookup(MyCell, MkVal, 1, False)
If Err <> 0 Then
result = CVErr(xlErrNA)
End If
If Not IsError(result) Then
MyCell.Interior.ColorIndex = xlNone
Else
MyCell.Interior.ColorIndex = 6
End If
Next
End Sub
I have this table that contain more than 6K rows.
I need a function, that will run on each "A" Column's cell
and check -> if cell on "b" is bold than copy it,
if not, copy the cell above it.
I fount this function on the internet, but im not using VB and it will be easier if someone that already know how to use VB functions in excel than learn it from the beginning.
this code replaces the G column cells with numbers, as you can see.
Sub BoldCells()
Dim TheRange As Range
Dim TheCell As Range
Set TheRange = Range("G1", Range("G65536").End(xlUp))
For Each TheCell In TheRange
If TheCell.Font.Bold = True Then
TheCell = 7
Else: TheCell = 0
End If
Next TheCell
End Sub
Help will be very appreciated, thank you!
I am not sure how efficient this is, but looks like working with 10 lines or so of data.
Sub test()
Dim rng As Range, str As String
Set rng = Range("b1")
str = ""
Do
If rng.Font.Bold Then
str = rng.Value
End If
rng.Offset(0, -1).Value = str
Set rng = rng.Offset(1, 0)
Loop Until IsEmpty(rng)
End Sub