Posts 1 - 10 of 11
First | Prev. | 1 2 | Next | Last
|
|
Michael Thrift
Posts: 41
Joined: 2015-06-09
|
In adapting our existing Add-In to support Office 2013 and above, we are having to contend with the switch from MDI to SDI.
Part of our current process with Office 2010 is to create a TaskPaneCollectionItem & a TaskPaneInstance when a user opens up an "Application" from our Add-In ribbon.
The term "application" in this context represents a TaskPane with a UserControl and an EXCEL Workbook. The TaskPane and the embedded UserControl is directly tied to the workbook, and is not relevant for any other workbook open in EXCEL.
When an application is opened, it also results in the dynamic creation and opening of a new workbook. The workbook and the TaskPane are then tied together so that we can activate the TaskPane when the workbook is activated, and we can dispose of the TaskPane when the workbook is closed.
What is currently happening, is the TaskPane is created BEFORE the workbook, so the TaskPane gets attached to the "Book 1" window, while the Application window gets a blank copy of a task pane. It occurs before the workbook is created, because right now, I pass the TaskPane instance into my constructor of the method that builds the workbook, so the workbook can have a reference to it.
My thought is to PREVENT Add-In Express from creating a TaskPane instance automatically when a new window is created, because we only want the task pane to appear for the specific application it is tied to. I know that I can cancel the Task Pane creation in ADXBeforeTaskPaneInstanceCreate. However, I want to create my own instance of a TaskPane and ensure that it is attached to the new workbook window.
When is the best time to do this to ensure it gets attached to the correct window? |
|
Posted 28 Sep, 2016 10:59:36
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18821
Joined: 2006-05-11
|
Hello Michael,
The link between an Excel workbook and a given instance of the task pane may exist only if the task pane instance contains some information related to the workbook. I suggest that you broke this link by introducing another UserControl (#2) containing this information as well as the UserControl (#1) that you currently have. This allows you to show the UserControl #2 on any task pane suitable. For instance, if the user opens the same workbook in several windows, Add-in Express will create several (e. g. N) task pane instances and your code may show several (e.g. M) instances of the UserControl #2 on some or all of these task pane instances.
Also, this allows you to show/hide an Excel task pane when you need this. To show/hide the task you call the Show and hide methods available on the task pane class. To prevent a task pane instance from being shown, you set this.Visible=true (Me.Visible = True in VB.NET) in the ADXTaskPaneBeforeShow event of the task pane class (in your case this is ADXExcelTaskPane).
What do you think?
Andrei Smolin
Add-in Express Team Leader |
|
Posted 29 Sep, 2016 06:48:17
|
|
Top
|
|
Michael Thrift
Posts: 41
Joined: 2015-06-09
|
See code below. How does the CreateTaskPaneInstance() method know which window to associate itself with? The only place that I have found where the TaskPane gets associated with the correct window, is if I place the code in the Window.Activate() or Workbook.Activate() event. The problem is that the event first fires when the workbook is created, and I haven't yet identified that workbook as an application that needs a taskpane attached to it. I certainly don't want my logic to fire everytime a workbook gets activiated.
Right now I am employing a CancelTaskPane Boolean to suppress the creation of task pane instances unless I create them.
Public Function CreateTaskPane(pPos As AddinExpress.XL.ADXExcelTaskPanePosition) As PwrToolsTaskPane
Dim objUL As New clsUserLog
objUL.StartUserLog()
Try
'Create The Task Pane
CancelTaskPane = False
If pPos <> ADXExcelTaskPanePosition.Right And pPos <> ADXExcelTaskPanePosition.Left Then
pPos = ADXExcelTaskPanePosition.Right
End If
Dim TaskPaneCI As ADXExcelTaskPanesCollectionItem = _
PwrToolsTaskPaneManager.Items.Add(New ADXExcelTaskPanesCollectionItem With { _
.TaskPaneClassName = "FastPowerTools.PwrToolsTaskPane", _
.AlwaysShowHeader = True, _
.IsDragDropAllowed = True, _
.CloseButton = False, _
.Position = pPos, _
.AllowedDropPositions = (ADXExcelAllowedDropPositions.Right Or ADXExcelAllowedDropPositions.Left), _
.DefaultRegionState = ADXRegionState.Normal, _
.Enabled = True})
'Get Index Of TaskPaneCI In Collection
Dim x As Integer = PwrToolsTaskPaneManager.Items.Count - 1
'Create The Task Pane Instance
Dim TaskPane As PwrToolsTaskPane = PwrToolsTaskPaneManager.Items(x).CreateTaskPaneInstance()
CancelTaskPane = True
Return TaskPane
objUL.EndUserLog()
Catch ex As Exception
objUL.EndUserLog(, , clsUserLog.LOGTYPE.EROR, objUL.GetExMessage(ex))
Throw New Exception(objUL.GetExMessage(ex))
End Try
End Function
|
|
Posted 29 Sep, 2016 08:18:53
|
|
Top
|
|
Alexander Solomenko
Posts: 140
Joined: 2009-02-27
|
Hi Michael,
The CreateTaskPaneInstance() method simply creates an instance of the form. The form is associated with the Excel window at the moment when it is being shown, i.e. when the Show method is called. In this case, the form is shown in the active Excel window. I will send you (to a personal email) a sample project that displays a TaskPane on a ribbon button click in any Excel window. Also, I'd like to draw your attention to the fact that after the creation of a TaskPane instance, it will remain in the TaskpaneInstances collection until you close the Excel window. TaskpaneManager will destroy the TaskPane instance on its own. No calls of the Dispose method should be done.Regards,
Aleksandr Solomenko |
|
Posted 30 Sep, 2016 09:36:53
|
|
Top
|
|
Michael Thrift
Posts: 41
Joined: 2015-06-09
|
This is helpful information, and thank you for sending the sample project. See code below.
Your button created and displayed a taskpane on the excel window that the user was on when they clicked the button. Our Add-In opens an "App" which requires a new workbook to be created. In the code below, a new workbook is opened, but the TaskPane gets attached to the original window, NOT the window associated with xlWB. What is interesting, is the Window.Activate() and Workbook.Activate() event fires immediately after you execute ExcelApp.Workbooks.Add(), and yet the taskpaneinstance does not recognize this as the active workbook.
Is there a way to associate the TaskPane instance with xlWB all in this same method?
Private Sub AdxRibbonButton1_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton1.OnClick
'I added this code ******
Dim xlWB As Excel.Workbook = ExcelApp.Workbooks.Add()
'***********************
Dim taskPane = Me.AdxExcelTaskPanesCollectionItem1.TaskPaneInstance
If IsNothing(taskPane) Then
CancelTaskpane = False
taskPane = Me.AdxExcelTaskPanesCollectionItem1.CreateTaskPaneInstance
CancelTaskpane = True
End If
If Not taskPane.Visible Then
taskPane.Show()
End If
End Sub
|
|
Posted 30 Sep, 2016 13:35:55
|
|
Top
|
|
Michael Thrift
Posts: 41
Joined: 2015-06-09
|
The TaskPaneCollectionItem.FormsManager.HostHandle is set when the TaskPaneCollectionItem is created. Once the HostHandle is set, it doesn't retry to get the window, it just uses the window it has. If the TaskPaneCollectionItem is instantiated when the first window is active, it will not matter that a different window is active when the taskpaneinstnace is created, it will get the HostHandle from the FormsManager. And if it has already been set, it will be the original window.
I may be wrong of course, but if that is true, it would mean that the taskpanecollectionitem needs to be instantiated after the window is activated? |
|
Posted 30 Sep, 2016 14:06:18
|
|
Top
|
|
Alexander Solomenko
Posts: 140
Joined: 2009-02-27
|
Hi Michael,
Michael Thrift writes:
Once the HostHandle is set, it doesn't retry to get the window, it just uses the window it has.
Whenever you switch to another Excel window, FormsManager.HostHandle is set to reflect the change; it always contains the handle of the active Excel window.
I added one more button to the sample, which opens a new workbook and adds a TaskPane there. Please check your email box.Regards,
Aleksandr Solomenko |
|
Posted 03 Oct, 2016 08:57:35
|
|
Top
|
|
Michael Thrift
Posts: 41
Joined: 2015-06-09
|
Thank you again for working with me on this. I need to clarify one additional point. While the TaskPane is technically managed at the Add-In / Excel Application level, the functionality of any single task pane we build is truly unique to the workbook being created, and therefore has a unique UserControl added to it, along with a unique title etc.
In your example, it is simply creating an instance of an existing TaskPaneCollectionItem that was pre-compiled. My CollectionItems are generated at runtime, when the user selects the application. When a user opens an "App" we want to do the following (in whatever order will work):
1. Dynamically create a workbook from code that is named after the App, and creates the worksheets needed. (this is something I am doing)
2. Create a TaskPane that is labeled after the App Name and has a custom user control(wpf) loaded into it. This has been done in the past by creating a new TaskPaneCollectionItem. (I believe my issue is that this item doesn't get re-created, only the 1st one, which is a blank collection item.)
3. Display the Task Pane with the newly opened workbook.
See code below. Consider how you would accomplish opening a TaskPane in a new Workbook if the TaskPaneManager had no collection items in it.
Private Sub AdxRibbonButton2_OnClick(sender As Object, control As IRibbonControl, pressed As Boolean) Handles AdxRibbonButton2.OnClick
Dim books As Excel.Workbooks = ExcelApp.Workbooks
If Not IsNothing(books) Then
CancelTaskpane = False
Dim book As Excel.Workbook = books.Add()
If Not IsNothing(book) Then
Marshal.ReleaseComObject(book)
End If
Marshal.ReleaseComObject(books)
End If
End Sub
Thoughts? |
|
Posted 03 Oct, 2016 10:19:59
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18821
Joined: 2006-05-11
|
Hello Michael,
TaskPaneCollectionItem is an entity that only contains a description of properties common for all task pane instances, e.g. you can set the TaskPaneCollectionItem so that all instances of the specified task pane class are docked to the specified side of the Excel window. If no other logic is involved, the TaskPanesManager creates a new instance of the specified task pane class and show it whenever it detects a new Excel window. To prevent a given task pane instance from displaying, you set this.Visible=false (Me.Visible = false in VB.NET) in the ADXTaskPaneBeforeShow event of the task pane class (in your case this is ADXExcelTaskPane).
To show a unique UI on a pane shown in an Excel windows, you can populate instances of a *single* task pane class with different controls, e.g. with different UserControls. This doesn't require creating a new TaskPaneCollectionItem which simplifies the logic a lot. To put a UserControl on the pane, you can use the Load, ADXBeforeTaskPaneShow, and ADXAfterTaskPaneShow events of the task pane class.
Does this make sense?
Andrei Smolin
Add-in Express Team Leader |
|
Posted 04 Oct, 2016 06:22:49
|
|
Top
|
|
Michael Thrift
Posts: 41
Joined: 2015-06-09
|
Yes, I have been able to make this work now. When a user opens an "App", I store the necessary configuration information into a global object. I then modify the TaskPaneInstance after the InitalizeComponents() call in the constructor of the TaskPane.
The disconnect for me was an inability to get a hold of the TaskPaneInstance within the same method that created the workbook.
A small inconvenience is that we previously saved the panel location for each app independently. So if a user wanted one App's Task Pane on the left, while another App's TaskPane on the right, we accomplished this by having separate TaskPaneCollectionItems for each app. As of now, for Office 16, we are no longer doing this. |
|
Posted 04 Oct, 2016 13:56:19
|
|
Top
|
|
Posts 1 - 10 of 11
First | Prev. | 1 2 | Next | Last
|