I've had this working but never perfectly. On occasion for some reason I have not been able to determine, it fails (I mean the chart series gives me a 1004 error)
I have a"table" (called LI) and an embedded chart (PH) on Sheets("QC"
.
Sheets("Data"
contains a row of dates with data in each column containing a date.
I want table LI and chart PH to look at only 6 months of data at a time. All the functions below
are what make that happen. ShiftLeft and ShiftRight look back in history or into the future.
SkipMonths is a routine that allows the user to pick a month/year from a drop down box
(populated on WB_Open and any time the row of dates is changed) and lets them jump
immediately to that month (instead of, for example, having to press ShiftLeft 10 times to
look at data 10 months ago)
FYI, the lookup routines were created because it seems the workbookfunction.match
is not reliable. My data during development has not changed in months yet sometimes
match fails on data I know it has succeeded with prior.
The problem code is noted below with '*****
Any help is greatly appreciated as I am running out of time with this and I am out of ideas.
Thanks in advance,
Andrea
Option Explicit
Option Compare Text
Public PHChartObj As ChartObject
Public PHChart As Chart
'-------------------------------
Public Sub MoveSeries(NumToMove As Integer)
Dim CPIRow
Dim DateRow
Dim theDates As Range
Dim DataSheet As Worksheet
Dim OldestMonth As Range
Dim NewestMonth As Range
Dim QCWindow As Range
Dim DateWindow As Variant
Dim DataWindow As Variant
CPIRow = Range("CPIData"
.Row
DateRow = Range("Date"
.Row
Set theDates = Range("Date"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Set DataSheet = Sheets("Data"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Set QCWindow = Sheets("QC"
.Range("TheWindow"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
'Find the Oldest date in theDates
Set OldestMonth = FindOldestDate(QCWindow)
Set OldestMonth = LookupDate(OldestMonth.Value, DataSheet, DataSheet.Range("Date"
)
If OldestMonth Is Nothing Then
MsgBox "Error updating Program Health chart"
GoTo Cleanup
End If
'Find the newest date in theDates
Set NewestMonth = FindNewestDate(QCWindow, DataSheet, OldestMonth.Column)
If IsEmpty(NewestMonth.Value) Then
'at the end of the visible list.
Exit Sub
End If
Set PHChartObj = ActiveSheet.ChartObjects(1)
Set PHChart = PHChartObj.Chart
'Create Date and DataWindows that points to 6 columns of dates on the Data sheet
Set DateWindow = DataSheet.Range(OldestMonth.Address, NewestMonth.Address)
Set DataWindow = DateWindow.Offset(Sheets("Data"
.Range("CPIData"
.Row - 1)
'*************************************
'* Problems start in here. I can activate the object
'* and set the series CPI to ChartSeries.
'* I cannot, however, do either of the following:
'* ChartSeries.Values = DataWindow
'* SeriesCollection("CPI"
.Values = DataWindow
'* I get a "Unable to set the Values property of
'* the Series class" error.
'* Data is valid in the range. The range is only
'* 6 columns of data.
'*************************************
'Set range for CPI
PHChartObj.Activate
Dim ChartSeries As Series
Set ChartSeries = ActiveChart.SeriesCollection("CPI"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
ChartSeries.Values = DataWindow
'SeriesCollection("CPI"
.Values = DataWindow
'Set Range for SPI
Set DataWindow = DateWindow.Offset(Sheets("Data"
.Range("SPIData"
.Row - 1)
PHChartObj.SeriesCollection("SPI"
.Values = DataWindow
'Set Range for BAC/EAC4
Set DataWindow = DateWindow.Offset(Sheets("Data"
.Range("BACEAC4"
.Row - 1)
PHChartObj.SeriesCollection("BAC/EAC4"
.Values = DataWindow
'Set Category labels
PHChartObj.SeriesCollection("BAC/EAC4"
.XValues = DateWindow
Sheets("QC"
.Range("h10"
.Select
Cleanup:
Set DataSheet = Nothing
Set QCWindow = Nothing
Set OldestMonth = Nothing
Set NewestMonth = Nothing
End Sub
'-------------------------------
Sub SkipMonths(ByVal MonthsToSkip As Integer)
Dim ListIndex, ListCount
Application.ScreenUpdating = False
'QC sheet needs to be active to use this function
If ActiveSheet.Name <> "QC" Then
MsgBox "The QC sheet must be active to use this function"
Exit Sub
End If
'Check to see if months on Data sheet have been extended. They have if count in list box "Program Dates" on QC toolbar
'is different than number of dates in Date row on Data sheet.
If WorksheetFunction.CountA(Sheets("Data"
.Range("Date"
) - 1 <> CommandBars("QC"
.Controls("Program Dates"
.ListCount Then
Call CreateToolbar
End If
ListIndex = CommandBars("QC"
.Controls("Program Dates"
.ListIndex
ListCount = CommandBars("QC"
.Controls("Program Dates"
.ListCount
ActiveWorkbook.Sheets("QC"
.Range("TheOffset"
.Value = ListCount - ListIndex + 1 '+ MonthsToSkip
MoveSeries MonthsToSkip
Call Refresh
Application.ScreenUpdating = True
End Sub
'-------------------------------
Sub ShiftRight_Click()
If ActiveSheet.Name <> "QC" Then
MsgBox "The QC sheet must be active to use this function"
Exit Sub
End If
If WorksheetFunction.CountA(Sheets("Data"
.Range("Date"
) - 1 <> CommandBars("QC"
.Controls("Program Dates"
.ListCount Then
Call CreateToolbar
End If
'On Error Resume Next
If CommandBars("QC"
.Controls("Program Dates"
.ListIndex < CommandBars("QC"
.Controls("Program Dates"
.ListCount Then
CommandBars("QC"
.Controls("Program Dates"
.ListIndex = CommandBars("QC"
.Controls("Program Dates"
.ListIndex + 1
End If
If Sheets("QC"
.Range("TheOffset"
> 1 Then
Sheets("QC"
.Range("TheOffset"
= Sheets("QC"
.Range("TheOffset"
- 1
End If
'Adjust offsets and pointers for moving months on Leading indicator's table
Call SkipMonths(1)
Call DoTotalSum("Total1"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Call DoTotalSum("Total3"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
End Sub
'-------------------------------
Sub Shiftleft_Click()
'Looking at the LI table, the date fields are named cells.
' From Left to Right they are:
' Month6 Month5 Month4 Month3 Month2 Month1
'Month1 and Month2 are "two months future"
'Month3 is the most recent month containing actual data
'Month4, Month5, and Month6 are 3 months of past data.
'This is a sliding window and look at it this way.
'Pretend you put your finger on Month3...the most recent month containing acutal
'data. If you push Month3 one cell to the right, you are pushing the data into
' Month2 and Month2 into Month1. Likewise, you are pulling data into Month6
' and then from Month6 to Month5, and so on.
'On Error Resume Next
If ActiveSheet.Name <> "QC" Then
MsgBox "The QC sheet must be active to use this function"
Exit Sub
End If
If WorksheetFunction.CountA(Sheets("Data"
.Range("Date"
) - 1 <> CommandBars("QC"
.Controls("Program Dates"
.ListCount Then
'if the date range on the Data sheet has changed (e.g. if dates have been added to the row), regenerate
' the toolbar
Call CreateToolbar
End If
If CommandBars("QC"
.Controls("Program Dates"
.ListIndex > 1 Then
CommandBars("QC"
.Controls("Program Dates"
.ListIndex = _
CommandBars("QC"
.Controls("Program Dates"
.ListIndex - 1
End If
Dim LastDate As Range
Set LastDate = Sheets("Data"
.Range("IV1"
.End(xlToLeft)
Dim ActualDates As Range
Set ActualDates = Range("F1", LastDate.Address)
If Sheets("QC"
.Range("TheOffset"
< ActualDates.Count Then
Sheets("QC"
.Range("TheOffset"
= Sheets("QC"
.Range("TheOffset"
+ 1
End If
Call SkipMonths(-1)
Call DoTotalSum("Total1"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
Call DoTotalSum("Total3"![Wink ;) ;)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
End Sub
'-------------------------------
Private Function FindOldestDate(DateRange As Range) As Range
Dim Mon
Dim NumOldExamined
Dim OldestMonth As Range
Set OldestMonth = Nothing
NumOldExamined = 0
For Each Mon In DateRange
If Not WorksheetFunction.IsError(Mon.Value) Then
Set OldestMonth = Mon
Exit For
End If
NumOldExamined = NumOldExamined + 1
Next
Set FindOldestDate = OldestMonth
NumExamined = NumOldExamined
Set OldestMonth = Nothing
End Function
'-------------------------------
Private Function LookupDate(LookupValue As String, OnSheet As Worksheet, DateRange As Range) As Range
Dim MatchCol As Integer
If NumExamined < 6 Then
'NOT (all 6 dates were looked at and all contained errors (e.g. no data available))
'Do a match lookup on theDates on QC to find the column of the oldest month
'(Match function not reliable. Created home-made match function)
MatchCol = doMatch(LookupValue, DateRange)
'Create a range that points to this oldest month on Data sheet
Set LookupDate = OnSheet.Range(OnSheet.Cells(1, MatchCol).Address)
End If
End Function
'-------------------------------
Private Function doMatch(LookupValue As String, theRange As Range) As Integer
Dim Val
Dim FoundMatchCol As Integer
FoundMatchCol = 0
For Each Val In theRange
If LookupValue = Val Then
FoundMatchCol = Val.Column
Exit For
End If
Next
doMatch = FoundMatchCol
End Function
'-------------------------------
Private Function FindNewestDate(DateRange As Range, OnSheet As Worksheet, OldestMonthCol As Integer) As Range
Dim Mon
Dim NewestMonth As Range
Set NewestMonth = Nothing
For Each Mon In DateRange
If Not WorksheetFunction.IsError(Mon.Value) And Mon.Column >= OldestMonthCol Then
Set NewestMonth = Mon
End If
Next
'Create a range that points to the newest date on the data sheet
Set NewestMonth = OnSheet.Range(OnSheet.Cells(1, OldestMonthCol + (6 - NumExamined - 1)).Address)
Set FindNewestDate = NewestMonth
Set NewestMonth = Nothing
End Function
I have a"table" (called LI) and an embedded chart (PH) on Sheets("QC"
Sheets("Data"
I want table LI and chart PH to look at only 6 months of data at a time. All the functions below
are what make that happen. ShiftLeft and ShiftRight look back in history or into the future.
SkipMonths is a routine that allows the user to pick a month/year from a drop down box
(populated on WB_Open and any time the row of dates is changed) and lets them jump
immediately to that month (instead of, for example, having to press ShiftLeft 10 times to
look at data 10 months ago)
FYI, the lookup routines were created because it seems the workbookfunction.match
is not reliable. My data during development has not changed in months yet sometimes
match fails on data I know it has succeeded with prior.
The problem code is noted below with '*****
Any help is greatly appreciated as I am running out of time with this and I am out of ideas.
Thanks in advance,
Andrea
Option Explicit
Option Compare Text
Public PHChartObj As ChartObject
Public PHChart As Chart
'-------------------------------
Public Sub MoveSeries(NumToMove As Integer)
Dim CPIRow
Dim DateRow
Dim theDates As Range
Dim DataSheet As Worksheet
Dim OldestMonth As Range
Dim NewestMonth As Range
Dim QCWindow As Range
Dim DateWindow As Variant
Dim DataWindow As Variant
CPIRow = Range("CPIData"
DateRow = Range("Date"
Set theDates = Range("Date"
Set DataSheet = Sheets("Data"
Set QCWindow = Sheets("QC"
'Find the Oldest date in theDates
Set OldestMonth = FindOldestDate(QCWindow)
Set OldestMonth = LookupDate(OldestMonth.Value, DataSheet, DataSheet.Range("Date"
If OldestMonth Is Nothing Then
MsgBox "Error updating Program Health chart"
GoTo Cleanup
End If
'Find the newest date in theDates
Set NewestMonth = FindNewestDate(QCWindow, DataSheet, OldestMonth.Column)
If IsEmpty(NewestMonth.Value) Then
'at the end of the visible list.
Exit Sub
End If
Set PHChartObj = ActiveSheet.ChartObjects(1)
Set PHChart = PHChartObj.Chart
'Create Date and DataWindows that points to 6 columns of dates on the Data sheet
Set DateWindow = DataSheet.Range(OldestMonth.Address, NewestMonth.Address)
Set DataWindow = DateWindow.Offset(Sheets("Data"
'*************************************
'* Problems start in here. I can activate the object
'* and set the series CPI to ChartSeries.
'* I cannot, however, do either of the following:
'* ChartSeries.Values = DataWindow
'* SeriesCollection("CPI"
'* I get a "Unable to set the Values property of
'* the Series class" error.
'* Data is valid in the range. The range is only
'* 6 columns of data.
'*************************************
'Set range for CPI
PHChartObj.Activate
Dim ChartSeries As Series
Set ChartSeries = ActiveChart.SeriesCollection("CPI"
ChartSeries.Values = DataWindow
'SeriesCollection("CPI"
'Set Range for SPI
Set DataWindow = DateWindow.Offset(Sheets("Data"
PHChartObj.SeriesCollection("SPI"
'Set Range for BAC/EAC4
Set DataWindow = DateWindow.Offset(Sheets("Data"
PHChartObj.SeriesCollection("BAC/EAC4"
'Set Category labels
PHChartObj.SeriesCollection("BAC/EAC4"
Sheets("QC"
Cleanup:
Set DataSheet = Nothing
Set QCWindow = Nothing
Set OldestMonth = Nothing
Set NewestMonth = Nothing
End Sub
'-------------------------------
Sub SkipMonths(ByVal MonthsToSkip As Integer)
Dim ListIndex, ListCount
Application.ScreenUpdating = False
'QC sheet needs to be active to use this function
If ActiveSheet.Name <> "QC" Then
MsgBox "The QC sheet must be active to use this function"
Exit Sub
End If
'Check to see if months on Data sheet have been extended. They have if count in list box "Program Dates" on QC toolbar
'is different than number of dates in Date row on Data sheet.
If WorksheetFunction.CountA(Sheets("Data"
Call CreateToolbar
End If
ListIndex = CommandBars("QC"
ListCount = CommandBars("QC"
ActiveWorkbook.Sheets("QC"
MoveSeries MonthsToSkip
Call Refresh
Application.ScreenUpdating = True
End Sub
'-------------------------------
Sub ShiftRight_Click()
If ActiveSheet.Name <> "QC" Then
MsgBox "The QC sheet must be active to use this function"
Exit Sub
End If
If WorksheetFunction.CountA(Sheets("Data"
Call CreateToolbar
End If
'On Error Resume Next
If CommandBars("QC"
CommandBars("QC"
End If
If Sheets("QC"
Sheets("QC"
End If
'Adjust offsets and pointers for moving months on Leading indicator's table
Call SkipMonths(1)
Call DoTotalSum("Total1"
Call DoTotalSum("Total3"
End Sub
'-------------------------------
Sub Shiftleft_Click()
'Looking at the LI table, the date fields are named cells.
' From Left to Right they are:
' Month6 Month5 Month4 Month3 Month2 Month1
'Month1 and Month2 are "two months future"
'Month3 is the most recent month containing actual data
'Month4, Month5, and Month6 are 3 months of past data.
'This is a sliding window and look at it this way.
'Pretend you put your finger on Month3...the most recent month containing acutal
'data. If you push Month3 one cell to the right, you are pushing the data into
' Month2 and Month2 into Month1. Likewise, you are pulling data into Month6
' and then from Month6 to Month5, and so on.
'On Error Resume Next
If ActiveSheet.Name <> "QC" Then
MsgBox "The QC sheet must be active to use this function"
Exit Sub
End If
If WorksheetFunction.CountA(Sheets("Data"
'if the date range on the Data sheet has changed (e.g. if dates have been added to the row), regenerate
' the toolbar
Call CreateToolbar
End If
If CommandBars("QC"
CommandBars("QC"
CommandBars("QC"
End If
Dim LastDate As Range
Set LastDate = Sheets("Data"
Dim ActualDates As Range
Set ActualDates = Range("F1", LastDate.Address)
If Sheets("QC"
Sheets("QC"
End If
Call SkipMonths(-1)
Call DoTotalSum("Total1"
Call DoTotalSum("Total3"
End Sub
'-------------------------------
Private Function FindOldestDate(DateRange As Range) As Range
Dim Mon
Dim NumOldExamined
Dim OldestMonth As Range
Set OldestMonth = Nothing
NumOldExamined = 0
For Each Mon In DateRange
If Not WorksheetFunction.IsError(Mon.Value) Then
Set OldestMonth = Mon
Exit For
End If
NumOldExamined = NumOldExamined + 1
Next
Set FindOldestDate = OldestMonth
NumExamined = NumOldExamined
Set OldestMonth = Nothing
End Function
'-------------------------------
Private Function LookupDate(LookupValue As String, OnSheet As Worksheet, DateRange As Range) As Range
Dim MatchCol As Integer
If NumExamined < 6 Then
'NOT (all 6 dates were looked at and all contained errors (e.g. no data available))
'Do a match lookup on theDates on QC to find the column of the oldest month
'(Match function not reliable. Created home-made match function)
MatchCol = doMatch(LookupValue, DateRange)
'Create a range that points to this oldest month on Data sheet
Set LookupDate = OnSheet.Range(OnSheet.Cells(1, MatchCol).Address)
End If
End Function
'-------------------------------
Private Function doMatch(LookupValue As String, theRange As Range) As Integer
Dim Val
Dim FoundMatchCol As Integer
FoundMatchCol = 0
For Each Val In theRange
If LookupValue = Val Then
FoundMatchCol = Val.Column
Exit For
End If
Next
doMatch = FoundMatchCol
End Function
'-------------------------------
Private Function FindNewestDate(DateRange As Range, OnSheet As Worksheet, OldestMonthCol As Integer) As Range
Dim Mon
Dim NewestMonth As Range
Set NewestMonth = Nothing
For Each Mon In DateRange
If Not WorksheetFunction.IsError(Mon.Value) And Mon.Column >= OldestMonthCol Then
Set NewestMonth = Mon
End If
Next
'Create a range that points to the newest date on the data sheet
Set NewestMonth = OnSheet.Range(OnSheet.Cells(1, OldestMonthCol + (6 - NumExamined - 1)).Address)
Set FindNewestDate = NewestMonth
Set NewestMonth = Nothing
End Function