Trying to simplify a step-by-step macro in VBA - vba

I have a spreadsheet in which there are ActiveX textboxes that are linked to specific cells. When the number in the cells change, the number in the textbox changes too. Pretty simple.
I wanted the numbers in these textboxes to be red when there is a number above zero and white when the number is zero. I've chosen white so that the zeros can't be seen at all on the printed page. I have a very basic macro that does this:
Sub textbox_change()
Worksheets("PAGE01").E21.LinkedCell = "PAGE01!AB23"
If Worksheets("PAGE01").E21.Value > 0 Then
Worksheets("PAGE01").E21.ForeColor = RGB(255, 0, 0)
Else
Worksheets("PAGE01").E21.ForeColor = RGB(255, 255, 255)
End If
Worksheets("PAGE01").E22.LinkedCell = "PAGE01!AB24"
If Worksheets("PAGE01").E22.Value > 0 Then
Worksheets("PAGE01").E22.ForeColor = RGB(255, 0, 0)
Else
Worksheets("PAGE01").E22.ForeColor = RGB(255, 255, 255)
End If
End Sub
As you can see, the code for each textbox is completed one at a time. How can I combine these so that the macro changes these colors at once, without having to have a block of code for each textbox?
Note: I've only used two textboxes in the example, but I would like to have up to 48 of these boxes total. That would be A LOT of redundancy when I'm positive that there's a much shorter way to take care of these pesky color changes.
Can you kind folks help out? Very much appreciated...

You can loop over the sheet's OLEObjects collection and check for textboxes:
Sub Tester()
Dim t
For Each t In Worksheets("PAGE01").OLEObjects
'is it a textbox ?
If t.progID = "Forms.TextBox.1" Then
'check the name begins with "E"
If t.Name Like "E*" Then
'Set the forecolor: using the built-in color constants,
' but you could instead use specific RGB() values
t.Object.ForeColor = IIf(t.Object.Value > 0, vbRed, vbWhite)
End If
End If
Next t
End Sub

Related

Excel & VBA - Changing tab colour if first 3 letter of tab name = "xxx"

New to VBA in excel, but hoping to get some help with a macro while I find my feet. Any help would be greatly appreciated.
I have a workbook where I would like to automatically colour tabs based on the tab names. My tab/sheet names are often codes. Some of my existing sheet names (for example) are:
CIS22ABC
CIS22CBA
NAS22XYZ
NAS22ZXY
MY DATA
ADMIN, etc.
I am trying to implement a script that runs across entire Workbook (i.e. under "ThisWorkbook") that searches first 3 letters of every tab name and makes tab colours based on these letters. There are lots of sheets being added and removed all the time - so an array of names won't work.
In short, I am hoping to do the following:
If first 3 letter of sheet name = "CIS" then Tab.Color = RGB(0, 255, 255)
If first 3 letter of sheet name = "NAS" then Tab.Color = RGB(66, 134, 244)
Otherwise do nothing!
Again, any help would be great. Thank you.
This will automatically execute every time you add a new sheet.
There are a good amount of events you can tie this to in order to have the macro fire automatically without user intervention. A few notable ones that may suit your needs better than the NewSheet event that I used below are SheetChange, SheetBeforeDelete, SheetActivate, etc.
This code will need to be placed in the coding space under ThisWorkbook rather a sheet or module in VBE.
Option Explicit
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Dim ws As Worksheet
For Each ws In Worksheets
Select Case Left(ws.Name, 3)
Case "CIS"
ws.Tab.Color = RGB(0, 255, 255)
Case "NAS"
ws.Tab.Color = RGB(66, 134, 244)
'Case "ABC"
'Add as many of these as you need inbetween _
Select Case and End Select
End Select
Next ws
End Sub
Try this:
Dim sheet As Worksheet
For Each sheet In ActiveWorkbook.Worksheets
Dim name As String
name = sheet.name
If Len(name) > 3 Then
Dim bit As String
bit = Mid(name, 1, 3)
Select Case bit
Case "CIS"
sheet.Tab.Color = 16776960
Case "NAS"
'etc etc
End Select
End If
Next
This should do the trick. First you need to count all the sheets and then run through each of them and check for the first 3 letters. If this is true you can color it:
For i = 1 To Sheets.Count
If Left(Sheets(i).Name, 3) = "CIS" Then
Sheets(i).Tab.Color = RGB(0, 255, 255)
End If
If Left(Sheets(i).Name, 3) = "NAS" Then
Sheets(i).Tab.Color = RGB(66, 134, 244)
End If
Next i

How to check the background color of an excel cell

In my program, I set the background color of an excel cell using:
sheet.cells(row, column).interior.color = System.Drawing.Color.Red
In another part of my program, I want to see if the color is red, but this code:
If(sheet.cells(row, column).interior.color = System.Drawing.Color.Red) Then
'Do something
End If
It returns an 'Type cast invalid' exception.
If the color is checked by:
If(sheet.cells(row, column).style.interior.color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red))
'Do something
End If
The colors are said to be not equal (even though the cell is red), because the interior color is 16777215 and the color translator returns 255.
How can I compare the color the right way?
I'm not that sure, but System.Drawing.Color.xxx is not existing in vba. You could try this:
ActiveSheet.Cells(row, column).Interior.Color = RGB(255, 0, 0)
If (ActiveSheet.Cells(row, column).Interior.Color = RGB(255, 0, 0)) Then
'Do something
End If
You could also have a look to .Interior.ColorIndex
I think you should change the tag of question to vba instead vb.net.
Best regards.

Microsoft Word VBA macro to convert tracked changes to cross-references into text

I need to convert tracked changes in Microsoft Word into actual text with the underline/strikethrough. I have had difficulties in dealing with tracked changes with cross-references.
For instance, if a cross reference is updated, from paragraph 5 to 6, it would appear as "65" [the 6 is underlined, but stackoverflow doesn't have that formatting option] I want to retain the 5 as raw text only, but keep the 6 as a cross-reference field.
I've gotten as far as the following macro which will do what I want if the cross reference has been /replaced/ with a new cross reference. However, it still does not work properly if the cross reference was only updated. Any help would be greatly appreciated:
Sub TypeAndStrike()
Dim chgAdd As Word.Revision
Dim Colour
Colour = RGB(255, 0, 0) ' Set the color to change the changes to.
'PD Colors: Black (0, 0, 0), Red (255, 0, 0), Green (0, 255, 0), Blue (0, 0, 255), Brown (165, 42, 42)
Dim SkipNext As Integer
' disable tracked revisions.
If ActiveDocument.Revisions.Count = 0 Then
MsgBox "There are no revisions in this document", vbOKOnly
Else
ActiveDocument.TrackRevisions = False
For Each chgAdd In ActiveDocument.Revisions
If chgAdd.Type = wdRevisionDelete Then ' It's a deletion, so make it strike through and then reject the change (so the text isn't lost).
SkipNext = 0
chgAdd.Range.Select ' move insertion point
chgAdd.Range.Font.StrikeThrough = True
chgAdd.Range.Font.Color = Colour
For Each testRange In Selection.Range.Fields ' Replace cross-refs with >text
testRange.Select
If Selection.Range = chgAdd.Range Then
SkipNext = 1
End If
Selection.TypeText Text:=Selection.Text
Next
If SkipNext = 0 Then
chgAdd.Range.Select
chgAdd.Reject
End If
ElseIf chgAdd.Type = wdRevisionInsert Then ' It's an addition, so underline it.
chgAdd.Range.Font.Underline = wdUnderlineSingle
chgAdd.Range.Font.Color = Colour
chgAdd.Accept
Else
chgAdd.Range.Select ' move insertion point
End If
Next chgAdd
End If
End Sub
I haven't worked a lot with Revisions, so my suggestion may have drawbacks, however, it occurs to me that you might be able to do something with Field.Result.
A cross-reference is a REF field, under the covers - press Alt+F9 and you can toggle on the field code view to see it.
When code queries ActiveDocument.Fields([index]).Result a RANGE object is returned (a Range is returned for any Field.Result). Result.Text returns the visible result as plain text - in your example 65.
In and of itself, that's not useful. But if you combine it with, perhaps, Result.Revisions.Count you can find out how many revisions (if any) are stored in the field. Using your example, Count returns two and you know the first (left) is the change and the second (right) is the original. That should let you figure out what the value should be. You could then remove the field (Field.Unlink) and write the desired result to the document?

Greater than Conditional Formatting using VBA

Hello I get some data from website using custom function with an XMLHTTP request now I need to apply some formatting condition to copied data and I would appreciate some advice using VBA :
The active cell "B" column
Less than 10 red
Between 10 and 15 yellow
More than 15 green
all the cell not returning any number should be blank
THX
There are two ways to do this:
The easy way:
Use Excel built-in conditional formatting (Select your range and click Home tab > Conditional Formatting > Add a rule or choose from the default rules -I think it has extensive options enough for your needs.)
The philosophical way:
Add a new module from your VBA IDE.
Copy and paste this code:
Sub ColorRange()
Dim d as Double
Dim r As Range
Set r = ActiveSheet.Range("B1:B500")
For Cell in r
If Cell.Text <> "" And IsNumeric(Cell.Value) = True Then
If Cell.Text < 10 Then
Cell.Interior.Color = RGB(255, 0, 0)
ElseIf Cell.Text >= 10 And Cell.Text <= 15 Then
Cell.Interior.Color = RGB(255, 255, 0)
Else
Cell.Interior.Color = RGB(0, 255, 0)
End If
End If
Next
End Sub
and run the macro.
Here's an output sample:
Which one I recommend?
I would recommend you use conditional formatting, no need for the VBA magic if the good old built-in Excel features can handle it, unless your need prove otherwise.

Excel - Adding animation

I am quite new to Excel and so far it has been fun learning it. I have started using Excel for modelling and i have gained enough expertise at it
I now wanted to go a step ahead and do a bit of designing on Excel
I have a specific requirement. I have 10 sheets in my workbook. I want to add some sort of animation on my first sheet. I currently have a button on my sheet 1.
On click of button it unhides all the 9 sheets and allows me to see modelling stuff in them. On clicking one more time it hides all the 9 sheets again.
Now i want to add one more thing to this.
On clicking the button i want a light bulb on the sheet to turn on and display a message (along with unhiding the sheets)
On clicking one more time i want the light bulb to turn off and hide the sheets again,
Can someone help me with this animation.
Thanks,
Sachi
Like I said it is very simple. This is how your Button and Bulb looks like.
Shapes used to create the bulb
Straight Connector
Oval
Cloud
Code
Private Sub CommandButton1_Click()
If CommandButton1.Caption = "Hide" Then
'
'~~> Your code here to Hide the Sheets
'
ActiveSheet.Shapes("Oval 2").Fill.ForeColor.RGB = RGB(255, 255, 255)
CommandButton1.Caption = "Unhide"
ElseIf CommandButton1.Caption = "Unhide" Then
'
'~~> Your code here to Unhide the Sheets
'
ActiveSheet.Shapes("Oval 2").Fill.ForeColor.RGB = RGB(255, 255, 0)
CommandButton1.Caption = "Hide"
End If
End Sub
To simply make the button change a shapes fill to yellow try this:
ActiveSheet.Shapes("SHAPE NAME").Fill.ForeColor.RGB = RGB(255, 255, 0)
The same idea can be applied to change the fill back. I've been playing with actual animation myself a lot lately too, so if you want to get something a bit more fun than the above than try something like the following. (Create a shape called Oval 1 to demo it with, or change the name to your shapes name)
Sub bulb()
steps = 300
timelimit = 0.005
increments = 255 / steps
counter = 0
r = 0
g = 0
Do
DoEvents
counter = counter + 1
r = r + increments
g = g + increments
ActiveSheet.Shapes("Oval 1").Fill.ForeColor.RGB = RGB(r, g, 0)
timeout (timelimit)
Loop Until counter = steps
End Sub
Sub timeout(duration_ms As Double)
Start_Time = Timer
Do
DoEvents
Loop Until (Timer - Start_Time) >= duration_ms
End Sub
Will need tweaking to your needs of course but the possibilities playing with this are endless.