views:

183

answers:

2

Basically I've coded an Excel 2007 project in VB.NET 2010 that allows you to create charts with a fair amount of interactivity. I want the user to be able to save and reopen this workbook and still have that interactivity in any already-created charts, so they don't have to re-create them.

When I create the charts, I use Sheet1.Controls.AddChart(...), which returns a Microsoft.Office.Tools.Excel.Chart with which I can handle events and such. However, when I reopen the file and look through the Sheet1.Controls collection, there are no Chart objects. Accessing the charts through Sheet1.ChartObjects.Chart gives me Interop Charts, when I need the Tools Charts.

Is there a better way to do this? Should I just be using Interop charts from the get-go?

+1  A: 

According to the MSDN article, you can use the HasVstoObject and GetVstoObject methods to convert a native object into a host control. The docs don't specifically mention the chart object, though.

Mark
According to http://msdn.microsoft.com/en-us/library/cc442765.aspx:To re-create a Microsoft.Office.Tools.Excel.Chart host control, you must first delete the native Microsoft.Office.Interop.Excel.Chart, and then re-create the Microsoft.Office.Tools.Excel.Chart by using the AddChart(Range, String) or AddChart(Double, Double, Double, Double, String) method. There is no Add<control class> method that enables you to create a new Microsoft.Office.Tools.Excel.Chart based on an existing Microsoft.Office.Interop.Excel.Chart.So it looks like they have to be completely recreated on _Startup.
Paul
+1  A: 

Paul, I apologize in advance if I'm not addressing your issue. Up until now I didn't realize there were two types of charts and I'd be interested in understanding the issues with them. At any rate, after some fooling around I was able to create a chart, name it, have it persist and have it respond to events. It does rely on interop charts though:

Public Class ThisWorkbook
    Dim clsChart As cChart

    Private Sub ThisWorkbook_Startup() Handles Me.Startup
        Dim coChartObj As Microsoft.Office.Interop.Excel.ChartObject
        Dim chtMyChart As Microsoft.Office.Interop.Excel.Chart
        Dim i As Int32

        With Globals.Sheet1
            For i = 1 To .ChartObjects.count
                If .ChartObjects(i).Name = "MyChart" Then
                    chtMyChart = .ChartObjects(i).chart
                    Exit For
                End If
            Next i
            If chtMyChart Is Nothing Then
                chtMyChart = .Shapes.AddChart.Chart
                chtMyChart.SetSourceData(.Range("A1:B2"))
                coChartObj = chtMyChart.Parent
                coChartObj.Name = "MyChart"
            End If
            clsChart = New cChart
            clsChart.chtChart = chtMyChart
        End With
    End Sub
End Class

Public Class cChart
    Public WithEvents chtChart As Microsoft.Office.Interop.Excel.Chart

    Private Sub chtChart_Resize() Handles chtChart.Resize
        MessageBox.Show("resize")
    End Sub
End Class
Doug Glancy
Hi Doug,Were you able to handle the events of those charts in your code? From my experience, I had to use Microsoft.Office.Tools.Excel.Chart and declare it WithEvents in order to have its events properly triggered and handled by my code. Please let me know (and demonstrate) if you've been able to do this with just the Interop variety. Thanks!
Paul
Paul, I'm a VBA programmer with a bit of .Net, so this is pretty much how I'd do it in VBA:I made a class called cChart (now shown at the end of my code). It contains a WithEvents chart as you described. I included a Resize event for demonstration.Then in my ThisWorkbook code I declare clsChart as cChart at the top and assign the newly or previously created chart to that WithEvents chart in the 2 lines near the end:clsChart = New cChartclsChart.chtChart = chtMyChartThe best way to test this is to publish it, open the workbook, make changes, save, reopen etc.
Doug Glancy
Hi Doug, that sounds quite reasonable. One of the reasons I was using the Tools chart in the first place is that that's the object type returned by Sheet1.Controls.AddChart(...). I like using that function because it allows me to set the name of the chart in the parameters. I'll see if I can find a way to work in the Interop version. I feel like I had a problem getting events to fire properly with the Interop version, but it was a while ago when I was trying that, so I'll give it another shot when I get the chance. Thanks!
Paul