Ignoring empty cells in a chart VBA - vba

I created a macro that results in a set of two columns and 0 to x rows.(x=number of rows in raw data). I'm plotting a chart with the next line of code.
Set MyChart = Sheet3.Shapes.AddChart(xlColumnClustered).Chart
MyChart.SetSourceData Source:=Sheet2.Range("$A$1:$A$10,$b$1:$b$10")
This will plot just the Top 10 data .The problem is that there are cases where I have less than 10 rows. So, is there a way to make VBA to ignore empty pair of cells under the last data cell?
Update1:
I need to use a colum chart and I'm deleting any past chart in the sheet and adding a new one
Thanks.

This isn't a VBA programming question per-se. You'll need to use an XY-scatter kind of a chart, where you have X-axis and Y-axis specified on the spreadsheet.
Then you can set the chart settings to 'Ignore Hidden and Blank Cells'
Then your same code can be used to update the chart to any range even with extra cells.
If your formulas give out useful values only for the first 10 numbers and 'blank' afterwards, make sure you replace the 'blank' with an #NA using the function
=IFERROR(YourCell x 1, NA())
While NA() looks ugly on the spreadsheet, it's excellent for charts as the charts simply ignore this and then you can set the chart to plot
Blanks or
Interpolated values
in its place (depending on your settings)
For any other kind of chart, it's not possible to do this unless you track the changes on the spreadsheet with a WorkSheet Change event.
And the code to re-size your chart category and value data should be called from this event handler in the Worksheet (not a module)
Private Sub Worksheet_Change(ByVal Target As Range)
' Code to handle the change, stuffing the chart category and value data goes here
End Sub
In the worst case that you can't change the range size, you can declare the range as dynamic in the spreadsheet and refer it by its name.
In this MSFT knowledgebase articule, you'll get information on dynamic defined ranges.
http://support.microsoft.com/kb/830287

Sub test()
Dim MyChart As Chart
Dim Ws As Worksheet
Set Ws = Sheet3
With Ws
If .ChartObjects.Count > 0 Then
.ChartObjects.Delete
End If
Set MyChart = .Shapes.AddChart(xlColumnClustered).Chart
MyChart.SetSourceData Source:=Sheet2.Range("a1").CurrentRegion
End With
End Sub

This is an old question, but the accepted answer didn't really answer the question; the chart type was wrong and the discussion of #N/A is not relevant to the required chart type. The other answer was better but didn't limit the chart source data to 10 rows or 2 columns.
This code will insert the chart with the appropriate data range:
Sub CreateChart()
Dim MyRange As Range
Set MyRange = Sheet2.Range("A1").CurrentRegion.Resize(, 2)
If MyRange.Rows.Count > 10 Then
Set MyRange = MyRange.Resize(10)
End If
Dim MyChart As Chart
Set MyChart = Sheet3.Shapes.AddChart2(, xlColumnClustered).Chart
MyChart.SetSourceData Source:=MyRange
End Sub

Related

Copying the color of an Excel sheet tab to a cell

I have a few hundred worksheets in an excel file with one worksheet referencing all of the others (a tracker sheet). The other sheets have color-coded tabs based on completion, and I want to reference that in the tracker sheet. Is there any way to find the color of a worksheet tab, and add it to it's respective tracker line in the tracker sheet?
I created a sample worksheet to try and replicate your problem. There is a 'TrackerSheet', and several other blank WorkSheets with colored tabs. I don't know what your naming convention is for the sheets so I just used "Sheets"; I also used a button to execute the following code but you can use it in the event you're using:
Sub Button2_Click()
Dim tabColorIndex As Variant, index As Integer
'For all of your sheets being tracked
For index = 1 To 3
'Retrieve the tab's colorIndex at index
tabColorIndex = Sheets("Sheet" & index).Tab.colorIndex
'Set the cells' colors in the respective row from columns A to F
Sheets("TrackerSheet").Range("A" & index & ":F" & index).Interior.colorIndex = tabColorIndex
Next index
End Sub
This colors the rows as shown in the link above.
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("Sheet1")
MsgBox ws.Tab.Color
This will return the value of the colour as Hex/RGB Depending on whether it's primary or not
This was to display in a msgbox for testing
Pretty simple thing to do actually,
ActiveWorkbook.Sheets("SheetABC").Tab.Color '<= parse the color of the tab
You can then manipulate this color to your needs using a variablE.
Yes, you can use:
dim ws as worksheet
ws.tab.color=' numerical value of the tab color you are looking for
Set that in an if statement and use a counter to keep track of the tabs of the set color. You can loop through all the worksheets in the workbook as well:
for each sht in application.worksheet
next sht

Is there any way to adjust the sequence of LegendEntries (Series) in Excel chart by VBA?

I'm working on an Excel chart automation. When I try to move up a LegendEntry(Series) object, I cannot find any related API method from MS site. The manual way is like this: Select the chart > Right click > Select Data... > Choose one of the LegendEntry > Click button Move Up. How could I do this by VBA? Thank you in advance.
Here is another way
Sub Sample()
Dim ws As Worksheet
Dim objChrt As ChartObject
Dim chrt As Chart
Set ws = ActiveSheet
Set objchart = ws.ChartObjects(1)
Set chrt = objchart.Chart
chrt.FullSeriesCollection(2).PlotOrder = 1
End Sub
Screenshot
The legend entry order is the same as the series order. I'm not sure if this is even exposed in the object model. You can change the number of the last parameter of the series formula to re-order the series and the legend entries alike.
ActiveSheet.ChartObjects("Chart 1").Activate
Debug.Print ActiveChart.FullSeriesCollection(1).Formula
This will get you something like
=SERIES(Sheet1!$B$6,,Sheet1!$C$6,1)
The 1 as the last parameter means that it is the first series in the chart and hence the legend. Change that parameter to move the legend entry to a different position.

Excel VBA: Update chart button when new row of data is added to datasheet

I'm working on an Excel VBA macro that will create a timeline for a list of projects. I would like the macro to be dynamic and have an update command button that will refresh the chart when new information is added to the data sheet.
However, anytime I add a new row to the data sheet, the chart format goes haywire. Here is my code:
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
On Error Resume Next
ThisWorkbook.Charts.Delete
On Error GoTo 0
Dim ChartSheet1 As Chart
Set ChartSheet1 = Charts.Add
With ChartSheet1
.SetSourceData Source:=Sheets("Sheet1").Range("A2:A61,F2:F61,I2:I61")
.ChartType = xlBarStacked
End With
Application.ScreenUpdating = True
End Sub
The "ThisWorkbook.Charts.Delete" is to delete the existing chart and have it replaced with the new, updated chart.
Column A contains the project titles. Column F contains the date that the project starts on. Column I contains the number of days that the project will last for.
I have 59 rows of data in my data sheet. I made the range to 61 so that I could add another row or two of data to see if my code works. But it doesn't. I used the record macro function to make most of my code. I understand this isn't the best technique but I have no background in VBA and was looking for a quick solution. I've been trying to learn the basics but can't find a solution for the problem I'm having.
I'm thinking that the problem is with "61" and that I should change that to a variable like "lastRow". Or maybe I'm completely off due to my lack of experience with programming. Thanks for any insight.
You can make the data source dynamic by calculating the last row of the data in VBA like this:
Private Sub CommandButton1_Click()
' declare variables for last row and worksheet
Dim lastRow
Dim sh As Worksheet
Set sh = ActiveWorkbook.Worksheets("Sheet1")
' get last populated cell in column A
lastRow = sh.Cells(Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False
On Error Resume Next
ThisWorkbook.Charts.Delete
On Error GoTo 0
Dim ChartSheet1 As Chart
Set ChartSheet1 = Charts.Add
With ChartSheet1
.SetSourceData Source:=Sheets("Sheet1").Range("A2:A" & lastRow & ",F2:F" & lastRow & ",I2:I" & lastRow)
.ChartType = xlBarStacked
End With
Application.ScreenUpdating = True
End Sub
Your code completely deletes the chart sheet and then creates a new one. I'm not sure what "the chart format goes haywire" means in your world, but without any formatting you'll get the Excel default horizontal bar chart with that code.
Turn the data in the worksheet into a Table (Insert tab > Table). Make the chart using this table.
Now whenever a row is added to or deleted from the table, the chart automatically updates to reflect the current contents of the table.
No need for VBA, no need to delete and recreate the chart, and lose then try to restore its formatting.
Look at the numbers. The Range goes from Row 2 to Row 61, which covers 59 rows of data. If you want to add another 2 more rows of data, you need to change it to "63".

Highlighting a chart based on a range of cells and the chart titles

I have a column of cells (Range A2:A10) which contain names of students. For each student, I have a chart titled after their name which track their performances in another sheet. I would like to change the chart background to light red colour if their names appear in the column of cells.
This is a fairly straight forward combination of ideas. You need to iterate through the charts, check the title against a list, and change the background color. The code below is an example to show the idea.
When iterating through Charts on a sheet, you start with the ChartObjects method. The ChartObject contains a reference to the actual Chart where you can get the Title and change the background. Note that checking the Title of a Chart without one will throw an error, so I start with a check to Chart.HasTitle.
I am using Application.Match to check if the range contains the title. This will return an error if it is not found, so I am checking for that error.
Finally, if the match exists, you change the background of the Chart through a lengthy list of properties. If you want to change a different part of the chart, record a macro to find the right property.
Sub ColorBasedOnTitle()
Dim chtObj As ChartObject
Dim sht As Worksheet
Dim rng_students As Range
'assume active sheet, change if not
Set sht = ActiveSheet
'need to set a reference to the list of names... named range is probably prefered here
Set rng_students = sht.Range("B3:B6")
'loop through all charts on sheet
For Each chtObj In sht.ChartObjects
'if chart has title, check its value
Dim title As String
If chtObj.Chart.HasTitle Then
title = chtObj.Chart.ChartTitle.Text
'use Match to see if title is in list of names
Dim search As Variant
search = Application.Match(title, rng_students, 0)
'see if student is in list, change background if so
If Not IsError(search) Then
chtObj.Chart.ChartArea.Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
End If
End If
Next chtObj
End Sub
Here is a picture of my Excel instance so you can see the result. Note that my Chart titled "F" is outside the range of checked names which are highlighted grey for emphasis.

copying different ranges of cells in excel according to styling

Im using a pivot table to arrange my data. when I copy my data to another sheet its looks like that:
but I want the data to be one by the other like that:
how can I use the bold lines as headers and cut only the required ranges which are not fixed? I tried using macros but I could only copy fixed ranges so I'm doing it manually each time (and some om the sheets are pretty big).
please help,
thank you.
You have full control on all the cells in the PivotTable. Sample code:
Dim curpivottable As PivotTable
Set curpivottable = ActiveSheet.PivotTables(1)
Dim curRange As Range
Set curRange = curpivottable.TableRange1
For Each cell In curRange.Cells
If (cell.Font.Bold) Then
'This is a bold cell
End If
Next cell
Bear in mind that curRange includes all the contents in curpivottable, from the first row (where the title is).
-- UPDATE
My answer above was the generic way to deal with ranges in PivotTables. If all what you want is just copying/pasting a range, you can do it directly (is the same if the range is in the PivotTable or not). Example:
Dim origRange As Range
Set origRange = Sheets("Sheet1").Range("A2:A500")
Dim destRange As Range
Set destRange = Sheets("Sheet2").Range("A2")
origRange.Copy
destRange.PasteSpecial xlPasteValues
Equivalently, you can check the format of the given cells (being bold or not) independently upon being inside a PivotTable or not.