Very often I need to create conditional formating rules on my excel worksheets, not always on the same range, to format the text color depending on what's written.
The most common situation is turning all the cells in the range that have the text "Effective" green and bold, and "Not effective" red and bold.
I tried to create this macro using the Record Macro function on the Developer tab, but it didn't work, the code was blank.
As I have zero knowledge on VBA, I was wondering if somebody could give me a help creating this macro.
Definitions:
There's no fixed range, it needs to capture the selected range;
Format based on text, if "Effective" green and bold, if "Not effective" red and bold.
Only for one sheet.
[Solved]
Sub EffectiveNot()
'
' EffectiveNot Macro
'
Dim rStart As Range
Set rStart = Selection
Selection.FormatConditions.Add Type:=xlTextString, String:="Effective", _
TextOperator:=xlContains
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.Bold = True
.Italic = False
.Color = -11489280
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Selection.FormatConditions.Add Type:=xlTextString, String:="Not effective", _
TextOperator:=xlContains
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.Bold = True
.Italic = False
.Color = -16776961
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
End Sub
Any chance you checked your ThisWorkbook-Module? The macro recorder adds a new empty module each day you run it, then dumps the code in there...
This is basically what the macro recorder comes up with, after I cleaned it up a bit. Feel free to swap Selection to a range-object more appropriate for your use.
Option Explicit
Sub format()
With Selection
With .FormatConditions
.Delete
With .Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=""Not Effective""")
With .Font
.Color = vbRed
.Bold = True
End With
.StopIfTrue = False
End With
With .Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="=""Effective""")
With .Font
.Color = vbGreen
.Bold = True
End With
.StopIfTrue = False
End With
End With
End With
End Sub
Related
Is it possible to copy information from mutiple cells, to one cell and keep the formatting? as an example, I have A1=Hello (Green, bold font), A2, World (red font)
Want to have B2=Hello World (with words in different color).
Looking for a solution in Google Sheets, but as an alternative, Excel would also work
For example my activecell has word "bankeris", so I made first 3 letters one color and another 3 letters with other color. This code is via "Macro recording". So copy/paste will do same.
With ActiveCell.Characters(Start:=1, Length:=3).Font
.Name = "Calibri"
.FontStyle = "Regular"
.Size = 11
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
.Underline = xlUnderlineStyleNone
.Color = -16776961
.TintAndShade = 0
.ThemeFont = xlThemeFontMinor
End With
With ActiveCell.Characters(Start:=4, Length:=3).Font
.Name = "Calibri"
.FontStyle = "Regular"
.Size = 11
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
.Underline = xlUnderlineStyleNone
.ThemeColor = xlThemeColorAccent6
.TintAndShade = -0.249977111117893
.ThemeFont = xlThemeFontMinor
End With
Thank you Bankeris.
The solution I need is a bit different - the number of characters will be variable, I purely need to copy the format from the original cell.
To give a big picture - there is a table with approx 8 columns, each column will have its color, but the numbers of characters in the cell will be different. The goal if to create a sentence which will include information from the specified row...but the format of each word in the sentence needs to be the same as in the original table.
Potentially, this solution could be used, but the number of chars for each color would need to be identified from te original cell and put as a variable in the code
Is there a way to assign a font to a range?
Let's say I have an object myFont. I can write:
with Range("A1").Font
.Bold=myFont.Bold
.Size=myFont.Size
same with other properties
end with
but there are a lot of font properties. Is there a way to do something like
Range("A1").Font=myFont?
No one-liner to do what you want. One possible shortcut below, but you're really still iterating over each property...
Dim p, myFont, rng As Range
'populate myFont, rng
For Each p In Array("Bold", "Color", "Size") 'for example
CallByName rng.Font, p, VbLet, CallByName(myFont, p, VbGet)
Next p
To change the font properties, follow the code below. Specifically, to change Range("A1") font name, use "Font.Name" as shown below.
To get this, I simply recorded a Macro of me changing the font and then stopping the Macro to view the code. Try recording Macros to find the property you need at times. Hope this helps.
Sub ChangeFontCustomRange()
' Change Font Name
'Select the Range to change font to
Range("A1").Select
'Change font properties, specifically, Font.Name
With Selection.Font
.Name = "Calibri" 'Type exact font name here
.Size = 11
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
.Underline = xlUnderlineStyleNone
.ThemeColor = xlThemeColorLight1
.TintAndShade = 0
.ThemeFont = xlThemeFontNone
End With
End Sub
So I've been searching everywhere for a way to temporarily show a text box in excel. Basically, what I'm trying to show a text for 5 seconds after the user clicks the button. I don't want anyone to "do the code for me" but instead give me pointers. The user clicks a button to switch language. When that button is pressed, I want a message to appear saying: "All values have been reset". My question is the following: Is there a function in excel-vba that show a textbox for a certain amount of time before disappearing or turning his visibility value to false?
All the rest of the code to switch the language has already been done I'm really only looking to find the function that turns off the visibility after time. (a timer or i don't know)
I doubt showing the code I have so far would help but if you wish to see it, indicate it in the comments.
Thank you SO
Here is my code so far:
Private Sub Ok_Click()
startTimer
Unload Me
End Sub
Sub startTimer()
Application.OnTime Now + TimeValue("00:00:01"), "NextTime"
End Sub
Sub NextTime()
If Sheet3.Range("B5") = 0 Then reset
If Sheet3.Range("B5") = 0 Then Exit Sub
Sheet3.Range("B5").Value = Sheet3.Range("B5").Value - TimeValue("00:00:01")
startTimer
End Sub
Sub reset()
Sheet3.Range("B5") = ("00:00:05")
End Sub
Consider:
Sub MAIN()
Call BoxMaker
DoEvents
DoEvents
newHour = Hour(Now())
newMinute = Minute(Now())
newSecond = Second(Now()) + 5
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime
ActiveSheet.Shapes("SPLASH").Delete
End Sub
Sub BoxMaker()
ActiveSheet.Shapes.AddTextbox(msoTextOrientationHorizontal, 217.5, 51#, _
482.25, 278.25).Select
Selection.Name = "SPLASH"
Selection.Characters.Text = "Please Wait for Macro"
With Selection.Characters(Start:=1, Length:=21).Font
.Name = "Arial"
.FontStyle = "Regular"
.Size = 36
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
.Underline = xlUnderlineStyleNone
.ColorIndex = xlAutomatic
End With
Selection.HorizontalAlignment = xlCenter
Selection.VerticalAlignment = xlCenter
End Sub
I am trying to set up a new table at the end of my document and format it to my specifications. But the backgroundcolor and the textcolor do not seem to work. The Font size also is not exactly what I want, since it applies to the whole table and not only one cell.
This is what I have so far:
Dim myRange As Object
Set myRange = ActiveDocument.Content
myRange.Collapse Direction:=wdCollapseEnd
ActiveDocument.Tables.Add Range:=myRange, NumRows:=3, NumColumns:=2
With .Tables(.Tables.Count)
.Cell(1, 1).Select
With Selection
.Shading.Texture = wdTextureNone
.Shading.ForegroundPatternColor = wdColorWhite
.Shading.BackgroundPatternColor = wdColorGray25
.Font.Size = 14
.Font.Bold = True
.Text = "Hello World"
End With
End With
I want the first row of the table without borders and with font 14, bold, white text on gray background.
I found the Answer.
The solution is as follows:
With .Tables(.Tables.Count)
With .Cell(1, 1)
.Shading.BackgroundPatternColor = wdColorGray50
With .Range
With .Font
.TextColor = wdColorWhite
.Size = 18
.Bold = True
End With
.Text = "Hello World"
End With
End With
End With
I removed the selection of the cell and used it directly. But the real thing was, the use of .Range when applying .Font and .Text
I have two cells A1 and A2. I want to merge them and store in A3 keeping the formatting intact. I was able to use the below code to do this. But there is a huge performance issue. Can any one suggest a better solution? Is there a simpler way to do this?
Sub Merge_Cells(rngFrom1 As Range, rngFrom2 As Range, rngTo As Range)
Dim iOS As Integer
Dim lenFrom1 As Integer
Dim lenFrom2 As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlManual
lenFrom1 = rngFrom1.Characters.Count
lenFrom2 = rngFrom2.Characters.Count
rngTo.Value = rngFrom1.Text & rngFrom2.Text
For iOS = 1 To lenFrom1
With rngTo.Characters(iOS, 1).Font
.Bold = rngFrom1.Characters(iOS, 1).Font.Bold
.Size = 9 'rngFrom1.Characters(iOS, 1).Font.Size
.Color = rngFrom1.Characters(iOS, 1).Font.Color
.Italic = rngFrom1.Characters(iOS, 1).Font.Italic
.Strikethrough = rngFrom1.Characters(iOS, 1).Font.Strikethrough
.Underline = rngFrom1.Characters(iOS, 1).Font.Underline
End With
Next iOS
For iOS = 1 To lenFrom2
With rngTo.Characters(lenFrom1 + iOS, 1).Font
.Name = rngFrom2.Characters(iOS, 1).Font.Name
.Bold = rngFrom2.Characters(iOS, 1).Font.Bold
.Size = 9 'rngFrom2.Characters(iOS, 1).Font.Size
.Color = rngFrom2.Characters(iOS, 1).Font.Color
.Italic = rngFrom2.Characters(iOS, 1).Font.Italic
.Strikethrough = rngFrom2.Characters(iOS, 1).Font.Strikethrough
.Underline = rngFrom2.Characters(iOS, 1).Font.Underline
End With
Next iOS
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Three suggestions:
1. Set a character's properties only if you need to
It's possible (I don't know for sure) that setting a character's properties is more expensive than getting a character's properties. If the cost differential is high enough then it makes sense to check the property to see if it needs to be set, before you actually set it.
So, for example, your code would become:
Sub Merge_Cells2(rngFrom1 As Range, rngFrom2 As Range, rngTo As Range)
Dim iOS As Integer
Dim lenFrom1 As Integer
Dim lenFrom2 As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlManual
lenFrom1 = rngFrom1.Characters.Count
lenFrom2 = rngFrom2.Characters.Count
rngTo.Value = rngFrom1.Text & rngFrom2.Text
For iOS = 1 To lenFrom1
With rngTo.Characters(iOS, 1).Font
If .Bold <> rngFrom1.Characters(iOS, 1).Font.Bold Then .Bold = rngFrom1.Characters(iOS, 1).Font.Bold
If .Size <> 9 Then .Size = 9
If .Color <> rngFrom1.Characters(iOS, 1).Font.Color Then .Color = rngFrom1.Characters(iOS, 1).Font.Color
If .Italic <> rngFrom1.Characters(iOS, 1).Font.Italic Then .Italic = rngFrom1.Characters(iOS, 1).Font.Italic
If .StrikeThrough <> rngFrom1.Characters(iOS, 1).Font.StrikeThrough Then .StrikeThrough = rngFrom1.Characters(iOS, 1).Font.StrikeThrough
If .Underline <> rngFrom1.Characters(iOS, 1).Font.Underline Then .Underline = rngFrom1.Characters(iOS, 1).Font.Underline
End With
Next iOS
For iOS = 1 To lenFrom2
With rngTo.Characters(lenFrom1 + iOS, 1).Font
If .Bold <> rngFrom2.Characters(iOS, 1).Font.Bold Then .Bold = rngFrom2.Characters(iOS, 1).Font.Bold
If .Size <> 9 Then .Size = 9
If .Color <> rngFrom2.Characters(iOS, 1).Font.Color Then .Color = rngFrom2.Characters(iOS, 1).Font.Color
If .Italic <> rngFrom2.Characters(iOS, 1).Font.Italic Then .Italic = rngFrom2.Characters(iOS, 1).Font.Italic
If .StrikeThrough <> rngFrom2.Characters(iOS, 1).Font.StrikeThrough Then .StrikeThrough = rngFrom2.Characters(iOS, 1).Font.StrikeThrough
If .Underline <> rngFrom2.Characters(iOS, 1).Font.Underline Then .Underline = rngFrom2.Characters(iOS, 1).Font.Underline
End With
Next iOS
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
As I mentioned, I don't really know if this is a win, and the degree of advantage might vary from property to property. Maybe someone more knowledgable than I can comment. Or you can just try it out and see if it helps.
2. Set size all at once
Since you seem to be setting size to 9 all the time, I'd suggest setting size to 9 for the entire cell all at once, a rather than character by character. Then again, maybe you commented it out because you intend to restore size copying, and if so, this suggestion won't work.
3. Exploit sparseness
If the formatting is sparse, then you can check long runs of characters (or entire cells) for a particular property before you do anything. For example, if many cells have no bolding, check each cell before doing anything else. You might not have to do anything at all about bolding. My Excel returns Null when a property isn't uniform across a run of characters. (ymmv) If you get a Null, then you know you'll have to slice that character run more finely.
4. Addendum
#DavidZemens' suggestion about font size led me to this idea, which pays off only if Set is more expensive than Get for character properties. One could by inspection formulate a guess of the most common character style (font, size, color, bold, etc.), define that by hand as a cell style and apply it to the target range by hand. That would minimize the number of If's that trigger property sets.
-hth