I'm modifying the ribbons of an Excel file, hiding all default and context tabs but only show my own tab. However, once any add-in with its own tab(s) is installed, these tabs are still displayed, as I do not know how to address them.
I know you can remove all tabs using <ribbon startFromScratch="true">, but I need to leave them in place (I actually use a getVisible callback to hide them from the user but show them to Admin).
So, following questions:
Is there any way to apply a "default" getVisible callback for all tabs not known (I guess the answer is no)
How can I figure out tabIDs of other add-in tabs
Given that PowerPivot is more and more widespread (esp. in Excel 2013) - what is the tabID for this tab?
This is an awesome question, there is little documentation or examples about working with third party ribbons. I've done a lot of digging around and can help you with most of what you want. I'll answer you're questions slightly out of order but here goes.
3) The Tab Id for the PowerPivot addin is a qualifier Id (so must be used with idQ) and is tabGemini. You must use it in the name space: Microsoft.AnalysisServices.Modeler.FieldList.
You can check this by adding a namespace to the schema:
xmlns:x1="Microsoft.AnalysisServices.Modeler.FieldList"
and then when declaring your tab's id, use the following to insert your tab before the PowerPivot tab:
insertBeforeQ="x1:tabGemini"
2) I had a hard time finding the tab Id for PowerPivot since it's a VSTO COM addin so you can't access the XML like you can with .xlam files. The answer is simple but you need Office 2010 or later. With Excel open and the addin you are interested open too, go to the File Menu and then Options. Choose Customize Ribbon and on the right of the window at the top choose Customize the Ribbon: Main Tabs. Now uncheck the addins you are interested in and down the bottom hit Import/Export to export the XML schema. Open this file up in a text editor and you can see how they've declared their tab ids.
1) I think the trouble you've got with the getVisible call back is that no matter how you mark up your XML if someone loads up an add-in after you, it'll override whatever you've done. The following is from the Fluent Ribbon for Developers FAQ (http://msdn.microsoft.com/en-us/library/office/aa722523%28v=office.12%29.aspx#a16c7df5-93f3-4920-baa8-7b7290794c15_FAQ)
What happens when two add-ins try to repurpose the same built-in control?
The last add-in that attempts to repurpose the control becomes the active add-in.
Now I haven't gone any further than this, but if you can import/export this board schema into Office then if you can find where this get's imported into, maybe you could manually overwrite it in VBA using the filescripting object. Obviously only if it's stored as text. Bit of a long shot but worth a further look? Good luck!
The PowerPivot tab is a COM Add-In. To view the progID of it and other COM Add-Ins use:
Sub ListCOMAddins()
Dim lngRow As Long, objCOMAddin As COMAddIn
lngRow = 1
With ActiveSheet
For Each objCOMAddin In Application.COMAddIns
.Cells(lngRow, "A").Value = objCOMAddin.Description
.Cells(lngRow, "B").Value = objCOMAddin.Connect
.Cells(lngRow, "C").Value = objCOMAddin.progID
lngRow = lngRow + 1
Next objCOMAddin
End With
End Sub`
In my case the progID of the PowerPivot tab is "Microsoft.AnalysisServices.Modeler.FieldList". So to close the tab use:
Private Sub Workbook_Open()
Application.COMAddIns("Microsoft.AnalysisServices.Modeler.FieldList").Connect = False
End Sub
Related
I have search on this site and beyond for an answer to these questions, and also trawled through a collection of VB/C# books I have on VB/VSTO. So far I've drawn a blank. I've posted the same question on a VB.NET facebook group, and if I get a solution, I'll post it here so it'll help others.
I am developing an application-level Add-In for Excel using VB.Net & VSTO.
Part of the functionality involves opening .xlsm (Excel macro-enabled) files.
I have three questions I hope you can help me with.
I want to open each xlsm file with macros enabled, but not launch
any Auto_Open macro in the xlsm file, or trigger the Workbook_Open
event. Is that possible?
The xlsm file may have it's own ribbon attached to the file. Is it
possible to inhibit the xlsm's ribbon from being added?
The xlsm file may have ActiveX controls that are connected to VBA
macros. If a VBA macro produces an error, is it possible to catch
the error in the .NET Add-In? The error may include "macro not
found"
For info, at present I disable macros using the code snippet below. Whilst that helps with item #1, it doesn't help with items #2 or #3 (in fact, disabling macros is the cause of item #3).
Currently when I open the xlsm file(s) I disable macros using the following code:
' WorkbookType is a string representing a keyword within the Excel filename
' xlApp is running instance of Excel
Dim xlApp = Marshal.GetActiveObject("Excel.Application")
aWorkbook = xlApp.ActiveWorkbook
aSheet = xlApp.ActiveSheet
' Save current macro security setting
Dim oldSecurity = xlApp.AutomationSecurity
' Disable macros
xlApp.AutomationSecurity =
Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityForceDisable
' Find & open WorkbookType workbook files in ProjectFolder
Dim info As New DirectoryInfo(CurrentProjectFolder)
For Each fileItem As IO.FileInfo In info.GetFiles
If fileItem.Name.Contains("~") Then
' Ignore temporary files
ElseIf fileItem.Name.Contains(WorkbookType) AndAlso fileItem.Name.Contains(".xls") Then
xlApp.AskToUpdateLinks = False
Dim wb = xlApp.Workbooks.Open(CurrentProjectFolder & "\" & fileItem.Name, UpdateLinks:=False)
xlApp.AskToUpdateLinks = True
End If
Next
' Restore macro security setting
xlApp.AutomationSecurity = oldSecurity
The xlsm file may have ActiveX controls that are connected to VBA macros. If a VBA macro produces an error, is it possible to catch the error in the .NET Add-In? The error may include "macro not found"
COM add-ins (represented by VSTO add-ins) and VBA macros are entirely different entities. You can't handle VBA errors in COM add-ins, or the opposite. But you may react to the application events, see Object model (Excel) for the list of available events.
The xlsm file may have it's own ribbon attached to the file. Is it possible to inhibit the xlsm's ribbon from being added?
To prevent the custom ribbon UI from loading you need to edit the file by removing the ribbon XML customizations contained inside the Excel file. VBA doesn't deliver any UI customizations nowadays. You can use the Open XML SDK for editing open XML documents on the fly from VSTO add-ins without involving the host application or its object model.
I have XML mappings & a macro-button in my excel sheet (which fires this macro command) -
Sub Button2_Click()
Application.SendKeys ("%lt") '%lt (alt + L + T) - shortcut to import xml option in Developer tab
'above code opens import xml in Developer tab, enabling the user to import the XML file to map data.
End Sub
When I sent the sheet to my partners, they said the button doesn't work; Later I found out that in my computer's Excel the Developer tab (in ribbon) is visible, and in theirs it's not visible. I temporarily fixed the problem for my partners' computers (I enabled the Dev. tab & then it worked), but obviously I cannot fix for all my users, nor can I ask them to enable the developer tab on their excel. as most of them probably don't know how to enable it...
What should I do in order to invoke the Import XML action through macro (highlighted below), irrespective of whether the user has the Developer tab enabled or not? Kindly guide... Thanks!
I'm trying to modify an embedded excel table in a word document programmatically. To do this, I have modified the docx file and the embedded excel file.
The significant part of the main document is the following:
<w:object w:dxaOrig="8406" w:dyaOrig="2056">
<v:shape id="_x0000_i1028" type="#_x0000_t75"
style="width:390.75pt;height:95.25pt" o:ole=""><v:imagedata r:id="rId14"
o:title=""/>
</v:shape>
<o:OLEObject Type="Embed" ProgID="Excel.Sheet.12" ShapeID="_x0000_i1028"
DrawAspect="Content" ObjectID="_1349794876" r:id="rId15"
UpdateMode="Always"/>
</w:object>
The word document uses an OLEObject to link to the embedded excel document. For displaying purposes,
a .wmf file is used (using the v:shape element). I have modified the excel document, which outdated this preview.
This results in some strange behaviour in the document:
The preview of the embedded (excel) table shows the wrong data
Double clicking on the embedded table opens the table in an embedded excel and shows the correct data
Closing the embedded editor triggers the generation of a new preview, showing the correct data
Of course, I want the table to show the correct table when the document is opened. How can I trigger Word to discard the image and redraw the preview?
An ideal solution for me would be to trigger the regeneration of the preview just by modifying the contents of the docx, but solutions using a small script would also help.
There is no perfect solution to this, but one that works most of the time is to force an open/close of the OLEFormat.Object. It doesn't matter if you are rehydrating the embedded Excel worksheet from outside of Word (i.e. manipulating the Open XML format) or doing it through the object model. What it involves is opening the embedded Excel spreadsheet from within Word and then closing that object for the image to be changed to the current values in the embedded spreadsheet and the new image to be created.
It depends just a bit if you are doing this on many Word documents or just one. In the former case, a global template (such as normal.dot or a custom one you create and put in the STARTUP folder) or in the later case, just run code behind of one document. Both have a different way to getting things to run, but essentially you will be hooking the Document_Open event and from there checking if the current document has OLE Embedded objects and if so, opening and closing them.
Without going into the hook, like I said, the code isn't pretty. Basically because it uses SendKeys. Most of the time, this will work. Some of the time, it won't. That is the nature of SendKeys and other programs receiving the focus without consent (such as an instant messenger program).
If Word has the focus (which means you can't open the VBE and press F5), this code should do the trick:
Sub UpdateEmbeddedXLSX()
Dim workbook As InlineShape
For Each workbook In ActiveDocument.InlineShapes
With workbook
If .Type = wdInlineShapeEmbeddedOLEObject Then
''# Excel.Sheet.12 for Excel 2007
If .OLEFormat.ClassType = "Excel.Sheet.12" Then
''# Open Object as spreadsheet
.OLEFormat.DoVerb wdOLEVerbPrimary
''# If you want, you can also do any updates here like
.OLEFormat.Object.ActiveSheet.Cells(2, 2).Value = ".1"
''# Nasty - but it works - SendKeys
SendKeys "{ESC}", True
End If
End If
End With
Next
End Sub
At the very least, you could put this code in your normal.dot and assign it to the QAT to be run as a macro.
Note that the code doesn't get around Excel opening, the values changing and then closing - that is part and parcel of using embedded objects. Using linking instead of embedding would be a much smoother way to do all of this, but I realize it's not always an option.
Just to add to an old post in the event someone stumbles upon this like I did:
The above code works great, but I modified it to use bookmarks instead of using SendKeys. The SendKeys statement really messes with the NumLock on my keyboard. Just one of the quirks of that command.
What I did was create bookmarks in my Word Doc Template. Then in my code, I created a pointer to the bookmark:
Dim bMark as bookmark
Set bMark as ActiveDocument.Bookmarks("NameOfBookmark")
Then in place of the SendKeys statement, I did the following:
bMark.Range.Select
Selection.EndKey
This basically pulled the focus out of the embedded worksheet, and onto the bookmark of the page. Then the .EndKey statement simply removed the selection. You don't really even need it.
Hope this helps!
If anyone's coming here looking for how to update an Excel Object embedded in a Visio document via VBA macros without double-clicking, you just need to call Save on the embedded workbook.
Dim wb As Excel.Workbook
Set wb = ThisDocument.Pages("MyPageName").Shapes("NameOfWorksheetShape").Object
'Calling me updates the visible worksheets.
wb.Save
I need a way to programatically launch the macro-recorder in Excel, and supply the name for the new macro that will get created.
This can be from VSTO or VBA, or using the Office interop assemblies.
Any ideas how this can be accomplished?
In VBA:
Dim ctrlStart As CommandBarControl, ctrlStop As CommandBarControl
Set ctrlStart = Application.CommandBars.FindControl(ID:=184)
Set ctrlStop = Application.CommandBars.FindControl(ID:=2186)
ctrlStart.Execute
'name part would go here, but first you have to deal with a modal dialog
ctrlStop.Execute
It looks like the Execute method on the RecordMacro control opens a modal dialog. There is no way to feed a parameter to this, or to do anything like SendKeys. The only way I see to do it is to write a sub that will rename the macro after the fact. It will be a little complicated to determine what the name of the new macro is, and you will still have a dialog box to deal with.
Actually, I'm not a beginner. I know nothing about them, though I do have some programming background.
This is the thing: I have a couple of Word documents and an Excel spreadsheets. The documents need to grab some data from the spreadsheet and then print. There needs to be one document per spreadsheet row, and they need to be printed all together.
I'm not asking for code or anything; I just want to know what's the right tool for the job, and if someone could point me to a tutorial or reference or something.
This is for Office 2003 (or XP, I'm not sure).
EDIT: It seems like there are many ways to do this, so it'd be great if someone listed the pros and cons of each solution. Keep in mind that it's something that will be done many times, and once programmed/recorded/whatever it should be easy to use for someone who is not a programmer.
Javier,
Couldn't find a good tutorial, but something like this should help you get going:
You can enable the developer toolbar, if it's not available from Word options. Then, click on the Visual Basic button and add a procedure or function that can be called from your document or a command button in the Word UI.
Sample showing some super basic Excel integration:
Public Function GetValue()
Dim myExcel As Excel.Application
Dim myWorkbook As Excel.Workbook
Dim myWorkSheet As Excel.Worksheet
Set myExcel = CreateObject("Excel.Application")
Set myWorkbook = myExcel.Workbooks.Open("c:\temp\myworkbook.xlsx")
Set myWorkSheet = myWorkbook.Worksheets(1)
Dim cellValue As String
cellValue = myWorkSheet.Cells(1, 1).Value
GetValue = cellValue
End Function
This will require you add a reference to Excel object library (type library) from the Excel developer IDE.
You can load your Excel spreadsheets via VBA in an ADODB and read the ADODB row by row.
How To Use ADO with Excel Data from Visual Basic or VBA
You can accomplish this with the built-in mail merge facility in Word. There's a walkthrough of how to use it in Word 2003 here
edit: further to the question in the comments, once you have set up the mail merge document, you can save it complete with its link to the data source. This means that when the document is opened again the user just needs to say "Yes" to the choice of data being merged.
The user can (independently) also choose to have the mail merge toolbar displayed. Clicking on the "Merge to new document" button on the Mail Merge toolbar would cause the merged letters to be generated. If the toolbar isn't displayed then they need to go Tools > Letters and Mailings > Mail Merge and use the wizard to complete the job