I need help coding this VBA for a work project. I have a map with all the shapes (States) named and I have column U2:U52 with the the State abbreviations and column V2:V52 with the data. I need a macro to run through an "If Then" statement to change the colors and Loop through each State (line of data) based on the data entered.
Sub map1()
Dim Rng As Range
Dim ShapeName As String
Dim SHP As Shape
ShapeName = "AL"
Set Rng = ThisWorkbook.Worksheets("Sheet1").Range("V2")
Set SHP = Rng.Parent.Shapes(ShapeName)
If Rng.Value <= 1.6 Then
SHP.Fill.ForeColor.RGB = RGB(255, 0, 0) 'Red
End If
If Rng.Value > 1.6 And Rng.Value < 2.4 Then
SHP.Fill.ForeColor.RGB = RGB(0, 255, 0) 'Green
End If
If Rng.Value >= 2.4 Then
SHP.Fill.ForeColor.RGB = RGB(255, 255, 0) 'yellow
End If
End Sub
The way its written is for just one shape, how do I change it to run all states without coding it 52 times?
Here is a simple loop that should work.
Sub map1()
Dim Rng As Range
Dim ShapeName As String
Dim SHP As Shape
For i = 2 to 52
ShapeName = ThisWorkbook.Worksheets("Sheet1").Range("U" & i).Value
Set Rng = ThisWorkbook.Worksheets("Sheet1").Range("V" & i)
Set SHP = Rng.Parent.Shapes(ShapeName)
If Rng.Value <= 1.6 Then
SHP.Fill.ForeColor.RGB = RGB(255, 0, 0) 'Red
ElseIf Rng.Value > 1.6 And Rng.Value < 2.4 Then
SHP.Fill.ForeColor.RGB = RGB(0, 255, 0) 'Green
ElseIf Rng.Value >= 2.4 Then
SHP.Fill.ForeColor.RGB = RGB(255, 255, 0) 'yellow
End If
Next i
End Sub
Related
I have a form that the user fills out and and need to create a color coded grid based on their answer. I can get the cell identified that needs to be colored but cannot get the color to appear properly.
Dim PlantName As String
Dim DateEntered As String
Dim PlantRow As Integer
Dim DateColumn As Integer
Dim Address As Variant
PlantName = Me.ComboBox1.Value
DateEntered = Me.TextBox5.Value
PlantRow = Sheets("Expedite").Range("A3:A5").Find(PlantName).row
DateColumn = Sheets("Expedite").Range("B2:BB2").Find(DateEntered).Column
Address = Cells(PlantRow, DateColumn).Address
If Me.Expedite_yes.Value = True Then
Address.Interior.Color = RGB(0, 255, 0) And Address.Text.Color = RGB(0, 225, 0)
ElseIf Me.Expedite_yes.Value = False Then
Address.Interior.Color = RGB(255, 0, 0) And adress.Text.Color = RGB(255, 0, 0)
End If
The cell found in "address should be colored green in both interior and text if me.expedite_yes.value = true but I am getting a syntax error on the address.interior.color line.
Main issue: You need to modify the Interior.Color and .Font.Color of a Range object, not a String address. Also as noted in the comments, remove And and put the two items as separate lines.
If you were to keep your initial approach, that might look like:
Dim rng as Range
...
Set rng = Cells(PlantRow, DateColumn)
...
rng.Interior.Color = RGB(0, 255, 0)
rng.Font.Color = RGB(0, 225, 0)
Other issues:
Both PlantRow = Sheets("Expedite").Range("A3:A5").Find... and
DateColumn = Sheets("Expedite").Range("B2:BB2").Find assume that the PlantName and DateEntered are actually found, and will throw an error if they are not found.
You should qualify which Worksheet - assuming it's Sheets("Expedite") that the Cells are on. Otherwise there is an implicit reference to the ActiveSheet.
With those modifications, your code might look like this:
Dim PlantName As String
Dim DateEntered As String
PlantName = Me.ComboBox1.Value
DateEntered = Me.TextBox5.Value
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Expedite")
Dim plantRng As Range, dateRng As Range
Set plantRng = ws.Range("A3:A5").Find(PlantName)
Set dateRng = ws.Range("B2:BB2").Find(DateEntered)
If Not plantRng Is Nothing Then
If Not dateRng Is Nothing Then
Dim rng As Range
Set rng = ws.Cells(plantRng.Row, dateRng.Column)
Else
MsgBox "Not found - try again!"
Exit Sub
End If
End If
If Me.Expedite_yes.Value = True Then
rng.Interior.Color = RGB(0, 255, 0)
rng.Font.Color = RGB(0, 225, 0)
ElseIf Me.Expedite_yes.Value = False Then
rng.Interior.Color = RGB(255, 0, 0)
rng.Font.Color = RGB(255, 0, 0)
End If
The problem is that when you define your address, variable "Address" receives the string of the address like "B2". You need to create a range object from this address string like in the code below. For the Font color I get .Font.Color working like this:
Option Explicit
Sub test()
Dim addr As Variant
Dim TestBool As Boolean
addr = Cells(2, 2).Address
Debug.Print addr
TestBool = True
If TestBool = True Then
Range(addr).Interior.Color = RGB(0, 255, 0) And Range(addr).Font.Color = RGB(0, 255, 0)
End If
End Sub
I try to set a border to a existing powerpoint table. It runs through fine (and the row and column number is inserted in each cell as test data), but the border just does not appear. What am I doing wrong?
For i = 1 To myPresentation.Slides(w).Shapes(tableName).Table.Rows.Count
For j = 1 To myPresentation.Slides(w).Shapes(tableName).Table.Columns.Count
myPresentation.Slides(w).Shapes(tableName).Table.Cell(i, j).Shape.TextFrame.TextRange.Text = "R:" & i & " C:" & j
With myPresentation.Slides(w).Shapes(tableName).Table.Cell(i, j)
.Borders(ppBorderTop).DashStyle = msoLineSolid
.Borders(ppBorderBottom).DashStyle = msoLineSolid
.Borders(ppBorderLeft).DashStyle = msoLineSolid
.Borders(ppBorderRight).DashStyle = msoLineSolid
.Borders(ppBorderTop).ForeColor.RGB = RGB(255, 110, 0)
.Borders(ppBorderBottom).ForeColor.RGB = RGB(255, 110, 0)
.Borders(ppBorderLeft).ForeColor.RGB = RGB(255, 110, 0)
.Borders(ppBorderRight).ForeColor.RGB = RGB(255, 110, 0)
.Borders(ppBorderBottom).Weight = 1
.Borders(ppBorderTop).Weight = 1
.Borders(ppBorderLeft).Weight = 1
.Borders(ppBorderRight).Weight = 1
.Borders(ppBorderBottom).Visible = msoTrue
.Borders(ppBorderTop).Visible = msoTrue
.Borders(ppBorderLeft).Visible = msoTrue
.Borders(ppBorderRight).Visible = msoTrue
End With
Next j
Next i
Create a single slide presentation and add only two tables on it. Then run this code:
Public Sub TestMe()
Dim myTable As Table
Dim sh As Shape
For Each sh In ActivePresentation.Slides(1).Shapes
Set myTable = sh.Table
myTable.Cell(1, 1).Borders(ppBorderTop).ForeColor.RGB = RGB(255, 110, 0)
Next sh
End Sub
It should work.
From there try to build a bit further.
I have a range next to data area of the column-chart. I have to relate each column's color of the chart with this range. E.g. if there is "X" in the table, so the chart-column ralated to this row would be red, else green.
I have written something like this here below, but it doesn't work. On the other hand VBA doesn't discard this code :)
Data column begins in E2 and chart's columns are Point(1), ...(2) etc.
Sub Chart_Color()
Worksheets("Sheet1").ChartObjects("Chart 1").Activate 'sheet's name
ActiveChart.FullSeriesCollection(1).Select
LineNum = Worksheets("Sheet1").Rows.Count
For i = 1 To LineNum
i = i + 1
If Worksheets("Sheet1").Range("E:E").Cells(i + 1).Value = "X" Then
ActiveChart.FullSeriesCollection(1).Points(i).Select
With Selection.Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
.Solid
End With
Else
With Selection.Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 255, 0)
.Transparency = 0
.Solid
End With
End If
Next i
End Sub
On the presumption that your above code works, which I can't test (in part because I don't have Office 365), the code below should work more efficiently.
Dim ColorId As Long
Dim LastRow As Long
Dim R As Long ' row number
Dim i As Long
Application.ScreenUpdating = False
With Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "E").End(xlUp).Row
For R = 2 To LastRow ' start in row 2
ColorId = InStr(1, "XYZ", Trim(.Cells(R, "E").Value), vbTextCompare)
If ColorId Then
ColorId = Array(vbRed, vbGreen, vbBlue)(ColorId - 1)
With Worksheets("Ma").ChartObjects("Chart 1").FullSeriesCollection(R - 1)
For i = 1 To .Points.Count
.Points(i).Format.Fill.ForeColor = ColorId
Next i
End With
End If
Next R
End With
In case it doesn't work you might like to lift the loop construction from it. Your loop includes many thousands of cells which aren't required. The other thing I urge you to consider is my attempt to do without activating or selecting anything. I know it is possible, I know that doing so is better, but I might not quite have found the correct syntax to address the FullSeriesCollection. This I have borrowed and transscribed from your own code.
If vbRed, vbGreen and vbBlue doesn't work for you the following code can replace these values. Place it at the top of the above code, just under Dim R As Long, except for the last line which must replace the similar line of code in the middle of the procedure.
Dim myRed As Long, myGreen As Long, myBlue As Long
myRed = RGB(0, 0, 255)
myGreen = RGB(255, 255, 0)
myBlue = RGB(0, 255, 0)
Set ColorId = Array(myRed, myGreen, myBlue)(ColorId - 1)
Now it works :)
Sub chart_color()
Application.ScreenUpdating = False
Dim Cell As Range
Dim i As Byte
For i = 0 To 100
For Each Cell In Worksheets("Sheet1").Range("E1").Offset(i, 0)
If Cell.Value = "X" Then
Worksheets("Ma").ChartObjects("Chart 1").Activate
ActiveChart.FullSeriesCollection(1).Points(i).Format.Fill.ForeColor.RGB = RGB(255, 255, 0)
End If
If Cell.Value = "Y" Then
Worksheets("Ma").ChartObjects("Chart 1").Activate
ActiveChart.FullSeriesCollection(1).Points(i).Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
End If
If Cell.Value = "Z" Then
Worksheets("Ma").ChartObjects("Chart 1").Activate
ActiveChart.FullSeriesCollection(1).Points(i).Format.Fill.ForeColor.RGB = RGB(0, 255, 0)
End If
Next Cell
Next i
End Sub
We are now looking at this portion of my code which you find that it doesn't work (sorry, I can't test).
ColorId = vbRed ' ColorId is a Long
i = 1
Worksheets("Ma").ChartObjects("Chart 1").FullSeriesCollection(1) _
.Points(i).Format.Fill.ForeColor = ColorId
This is supposed to be the equivalent of your code of which you say that it does work.
i = 1
Worksheets("Ma").ChartObjects("Chart 1").Activate
ActiveChart.FullSeriesCollection(1).Points(i).Format.Fill.ForeColor.RGB = RGB(255, 255, 0)
Let's forget about the value of i for the moment. The value of 1 which I assign to it is arbitrary.
I tested both .Fill.ForeColor = ColorId and .Fill.ForeColor.RGB = ColorId on a shape object and they both work. Therefore it should be possible to simply replace my 1 1/2 lines of code with your two lines of code and replace `RGB(255, 255, 0)' with 'ColorId'. You may also have to activate (Select) Worksheets("Ma") before you can activate a chart in it.
I studied both the SeriesCollection and Points methods and will therefore amend my above code to improve the referencing of both which may open new sources of error. Are you sure you need to format the points? My instinct is to try and set the colour like this:-
Worksheets("Ma").ChartObjects(1).Chart.SeriesCollection(1) _
.Interior.Color = ColorId
Replace SeriesCollection with FullSeriesCollection only if you do filtering.
I have been working on a macro for the past week to automatically create charts in excel. I have gotten pretty far along with it (thanks in large part to help from this website and its users), but I am stuck on a seemingly insignificant step. For some reason my line with markers graph shows up with discolorations in it. What I mean by this is that the middle fill of the marker is the standard blue that excel defaults to. I think the issue lies with the [ .Visible = msoTrue] line but no matter how I manipulate the code, I cannot make my markers one solid color.
The code is below
Sub DM1R_Graph()
Dim ws As Worksheet
For Each ws In Sheets
ws.Activate
If ws.Name <> "WSNs" Then
Dim sht As Worksheet
Dim xVals As Range, yVals As Range
Dim co As Shape, cht As Chart, s As Series
Set sht = ActiveSheet
Set co = sht.Shapes.AddChart()
Set cht = co.Chart
'remove any existing series
Do While cht.SeriesCollection.Count > 0
cht.SeriesCollection(1).Delete
Loop
cht.ChartType = xlLineMarkers
'get the extent of the XValues...
'below is the first Y axis entry (Oil)
'(change the 2nd offset number to get what you want)
Set xVals = sht.Range(sht.Range("B2"), sht.Cells(Rows.Count, "B").End(xlUp))
Set yVals = xVals.Offset(0, 2)
Set s = cht.SeriesCollection.NewSeries
s.XValues = xVals
s.Values = yVals
With s.Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 176, 80)
.Transparency = 0
.Solid
End With
With s.Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 176, 80)
.Transparency = 0
End With
'below is the second y axis entry (Gas)
Set xVals = sht.Range(sht.Range("B2"), sht.Cells(Rows.Count, "B").End(xlUp))
Set yVals = xVals.Offset(0, 4)
Set s = cht.SeriesCollection.NewSeries
s.XValues = xVals
s.Values = yVals
With s.Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
.Solid
End With
With s.Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
'below is the third y axis entry (water)
Set xVals = sht.Range(sht.Range("B2"), sht.Cells(Rows.Count, "B").End(xlUp))
Set yVals = xVals.Offset(0, 5)
Set s = cht.SeriesCollection.NewSeries
s.XValues = xVals
s.Values = yVals
With s.Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 176, 240)
.Transparency = 0
.Solid
End With
With s.Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 176, 240)
.Transparency = 0
End With
'end Y axis entries
cht.HasLegend = True
'below applies the legend names to be whatever are in parenthesis'
cht.Legend.Select
ActiveChart.SeriesCollection(1).Name = "Oil (BO)"
ActiveChart.SeriesCollection(2).Name = "Gas (MCF)"
ActiveChart.SeriesCollection(3).Name = "Water (BW)"
'below applies the data labels
cht.SeriesCollection(1).Select
cht.SeriesCollection(1).ApplyDataLabels
cht.SeriesCollection(2).Select
cht.SeriesCollection(2).ApplyDataLabels
cht.SeriesCollection(3).Select
cht.SeriesCollection(3).ApplyDataLabels
'below orients the datalabels to either above,below,right,or left
cht.SeriesCollection(1).Select
ActiveChart.SeriesCollection(1).DataLabels.Select
Selection.Position = xlLabelPositionRight
cht.SeriesCollection(2).Select
ActiveChart.SeriesCollection(2).DataLabels.Select
Selection.Position = xlLabelPositionAbove
cht.SeriesCollection(3).Select
ActiveChart.SeriesCollection(3).DataLabels.Select
Selection.Position = xlLabelPositionLeft
'below moves the chart
Dim iChart As Long
Dim lTop As Double
lTop = ActiveSheet.Range("Q10").Top
For iChart = 1 To ActiveSheet.ChartObjects.Count
ActiveSheet.ChartObjects(iChart).Top = lTop
ActiveSheet.ChartObjects(iChart).Left = ActiveSheet.Range("Q1").Left
lTop = lTop + ActiveSheet.ChartObjects(iChart).Height + ActiveSheet.Range("5:7").Height
Next
'below deals with the chart title
cht.SetElement (msoElementChartTitleAboveChart)
With cht.ChartTitle
.Text = sht.Name & Chr(10) & "Oil,Gas, and Water Production Through Well Life "
.Characters.Font.Size = 12
End With
'below adds a filter to one column. You cannot have more than 1 filter per sheet.
Columns("L:L").Select
Selection.AutoFilter
End If
Next ws
End Sub
Below is a picture showing what I mean. You can see it obviously in the red series, but it also appears in the green and blue series as well.
I believe you need to set the MarkerBackgroundColor on the series.
s.MarkerBackgroundColor = RGB(255, 0, 0)
I am using an excel macro to build a table on a power point slide, and it is incredibly slow iterating through cell (about 1-2 second for each cell). Is there a way to make this process go faster? Here is my Code:
Private Function formatTable(shp As PowerPoint.Shape)
Dim i As Byte
Dim j As Byte
Dim k As Byte
Dim tabCol As Byte
With shp.Table
tabCol = .Columns.Count
For i = 1 To .Rows.Count
For j = 1 To tabCol
With .Cell(i, j).Shape
.TextFrame2.TextRange.Font.Bold = msoTrue
Select Case i
Case 1 ' Header Row
.Fill.ForeColor.RGB = RGB(128, 128, 128)
Case 2, 6, 10, 14, 19 'Elements
.Fill.ForeColor.RGB = RGB(192, 192, 192)
Case 23 'Satisfaction
.Fill.ForeColor.RGB = RGB(255, 255, 153)
Case 27, 29, 31 'Future Behaviors
.Fill.ForeColor.RGB = RGB(204, 255, 104)
Case Else
.Fill.ForeColor.RGB = RGB(255, 255, 255)
.TextFrame2.TextRange.Font.Bold = msoFalse
End Select
With .TextFrame2.TextRange.Font
.Name = "Arial"
.Fill.ForeColor.RGB = IIf(i = 1, vbWhite, vbBlack)
.Size = IIf(j <> 1 And i = 1, 7, 8)
End With
.TextFrame.TextRange.ParagraphFormat.Alignment = IIf(j = 1, ppAlignLeft, ppAlignCenter)
End With
With .Cell(i, j)
.Borders(ppBorderBottom).Weight = 1
.Borders(ppBorderTop).Weight = 1
.Borders(ppBorderLeft).Weight = 1
.Borders(ppBorderRight).Weight = 1
End With
Next
Next
End With
End Function
Unfortunately that is the only way that I know of coloring the cells in a table. I.e. via looping. However you can reduce the time drastically :)
Did you notice the Case Else part? That is the majority of the table. So you can actually remove that from the code and color the entire table in one go using the below code
oPPSlide.Shapes(1).Table.Background.Fill.ForeColor.RGB = RGB(255, 255, 255)
and you can remove the Case Else part. So you will have to loop less. In fact, it will drastically reduce the overall time. See this example that I created.
Sub Sample()
Dim oPPApp As New PowerPoint.Application
Dim oPPPrsn As PowerPoint.Presentation
Dim oPPSlide As PowerPoint.Slide
Dim FlName As String
'~~> Change this to the relevant file
FlName = "C:\Users\Siddharth Rout\Documents\MyFile.PPTX"
oPPApp.Visible = True
'~~> Open the relevant powerpoint file
Set oPPPrsn = oPPApp.Presentations.Open(FlName)
'~~> Change this to the relevant slide which has the shape
Set oPPSlide = oPPPrsn.Slides(1)
'~~> Change the background of the table in one go
oPPSlide.Shapes(1).Table.Background.Fill.ForeColor.RGB = RGB(255, 255, 255)
formatTable oPPSlide.Shapes(1)
'
'~~> Rest of the code
'
End Sub
Private Function formatTable(shp As PowerPoint.Shape)
Dim i As Long, j As Long, k As Long, tabCol As Long
With shp.Table
tabCol = .Columns.Count
For i = 1 To .Rows.Count
For j = 1 To tabCol
With .Cell(i, j).Shape
.TextFrame2.TextRange.Font.Bold = msoTrue
Select Case i
Case 1: .Fill.ForeColor.RGB = RGB(128, 128, 128)
Case 2, 6, 10, 14, 19: .Fill.ForeColor.RGB = RGB(192, 192, 192)
Case 23: .Fill.ForeColor.RGB = RGB(255, 255, 153)
Case 27, 29, 31: .Fill.ForeColor.RGB = RGB(204, 255, 104)
' Case Else
' .Fill.ForeColor.RGB = RGB(255, 255, 255)
' .TextFrame2.TextRange.Font.Bold = msoFalse
End Select
With .TextFrame2.TextRange.Font
.Name = "Arial"
.Fill.ForeColor.RGB = IIf(i = 1, vbWhite, vbBlack)
.Size = IIf(j <> 1 And i = 1, 7, 8)
End With
.TextFrame.TextRange.ParagraphFormat.Alignment = IIf(j = 1, 1, 2)
End With
With .Cell(i, j)
.Borders(ppBorderBottom).Weight = 1
.Borders(ppBorderTop).Weight = 1
.Borders(ppBorderLeft).Weight = 1
.Borders(ppBorderRight).Weight = 1
End With
Next
Next
End With
End Function