Open Method of Worksheet fails [duplicate] - vba

I am trying to create a new instance of Excel using VBA using:
Set XlApp = New Excel.Application
The problem is that this new instance of Excel doesn't load all the addins that load when I open Excel normally...Is there anything in the Excel Application object for loading in all the user-specified addins?
I'm not trying to load a specific add-in, but rather make the new Excel application behave as though the user opened it themself, so I'm really looking for a list of all the user-selected add-ins that usually load when opening Excel.

I looked into this problem again, and the Application.Addins collection seems to have all the addins listed in the Tools->Addins menu, with a boolean value stating whether or not an addin is installed. So what seems to work for me now is to loop through all addins and if .Installed = true then I set .Installed to False and back to True, and that seems to properly load my addins.
Function ReloadXLAddins(TheXLApp As Excel.Application) As Boolean
Dim CurrAddin As Excel.AddIn
For Each CurrAddin In TheXLApp.AddIns
If CurrAddin.Installed Then
CurrAddin.Installed = False
CurrAddin.Installed = True
End If
Next CurrAddin
End Function

Using CreateObject("Excel.Application") would have the same result as using New Excel.Application, unfortunately.
You will have to load the Addins that you need individually by file path & name using the Application.Addins.Add(string fileName) method.

I'm leaving this answer here for anyone else who ran into this problem, but using JavaScript.
A little background... In my company we have a 3rd party web app that used JavaScript to launch Excel and generate a spreadsheet on the fly. We also have an Excel add-in that overrides the behavior of the Save button. The add-in gives you the option of saving the file locally or in our online document management system.
After we upgraded to Windows 7 and Office 2010, we noticed a problem with our spreadsheet-generating web app. When JavaScript generated a spreadsheet in Excel, suddenly the Save button no longer worked. You would click save and nothing happened.
Using the other answers here I was able to construct a solution in JavaScript. Essentially we would create the Excel Application object in memory, then reload a specific add-in to get our save button behavior back. Here's a simplified version of our fix:
function GenerateSpreadsheet()
{
var ExcelApp = getExcel();
if (ExcelApp == null){ return; }
reloadAddIn(ExcelApp);
ExcelApp.WorkBooks.Add;
ExcelApp.Visible = true;
sheet = ExcelApp.ActiveSheet;
var now = new Date();
ExcelApp.Cells(1,1).value = 'This is an auto-generated spreadsheet, created using Javascript and ActiveX in Internet Explorer';
ExcelApp.ActiveSheet.Columns("A:IV").EntireColumn.AutoFit;
ExcelApp.ActiveSheet.Rows("1:65536").EntireRow.AutoFit;
ExcelApp.ActiveSheet.Range("A1").Select;
ExcelApp = null;
}
function getExcel() {
try {
return new ActiveXObject("Excel.Application");
} catch(e) {
alert("Unable to open Excel. Please check your security settings.");
return null;
}
}
function reloadAddIn(ExcelApp) {
// Fixes problem with save button not working in Excel,
// by reloading the add-in responsible for the custom save button behavior
try {
ExcelApp.AddIns2.Item("AddInName").Installed = false;
ExcelApp.AddIns2.Item("AddInName").Installed = true;
} catch (e) { }
}

Related

Can't Print Specific Word Document Using VB.Net [duplicate]

I have a C# WinForm application that opens and fills out a MS Word dotx template by placing text at bookmarks, and then attempts to print it, all using MS Word Interop 15.
Everything seems to go fine, the print dialog shows and completes OK, the print job shows up in the print queue (i.e. the "See what's printing" window from "Devices and Printers" on MS Windows 10). But then the job immediately disappears from the queue before it can be spooled! (document appears very very briefly with "Spooling" status, and does not print - the printer never gets the job)
Here is my code (exception checking removed for brevity):
using Word = Microsoft.Office.Interop.Word;
private void Print_Click(object sender, EventArgs e)
{
// Open the MS Word application via Office Interop
Word.Application wordApp = new Word.Application();
Word.Document wordDoc;
// Open the template
wordDoc = wordApp.Documents.Add(Template: ContractTemplatePath, Visible: false);
// Ensure the opened document is the currently active one
wordDoc.Activate();
// Set the text for each bookmark from the corresponding data in the GUI
SetBookmarkText(wordDoc, "Foo", fooTextBox.Text);
// ... There's a whole bunch of these ... then:
// Instantiate and configure the PrintDialog
var pd = new PrintDialog()
{
UseEXDialog = true,
AllowSomePages = false,
AllowSelection = false,
AllowCurrentPage = false,
AllowPrintToFile = false
};
// Check the response from the PrintDialog
if (pd.ShowDialog(this) == DialogResult.OK)
{
// Print the document
wordApp.ActivePrinter = pd.PrinterSettings.PrinterName;
wordDoc.PrintOut(Copies: pd.PrinterSettings.Copies);
}
// Close the document without saving the changes (once the
// document is printed we don't need it anymore). Then close
// the MS Word application.
wordDoc.Close(SaveChanges: false);
wordApp.Quit(SaveChanges: false);
}
The only thing I can think of here is that maybe because I do away with the document as soon as I've sent it to the printer, then the job hasn't been completely sent so it removes itself or something. If this is the case then how can I determine how long I need to keep the document around for and what's the best way of waiting for that?
EDIT: Ive done another small bit of research (dont have time for more on this just at this moment) that suggests I may be able to use the PrintEnd event, but I couldn't immediately see if this would be applicable when using Interop. Would it be a method of achieving what I want without polling?
One solution is to poll the BackgroundPrintingStatus property of the Word application. It holds a count of the documents still waiting in the printing queue. While this count is greater than 0 there are still documents awaiting printing.
There are many ways you could achieve this. Here's a simple loop which blocks the UI:
// Send document to printing queue here...
while (wordApp.BackgroundPrintingStatus > 0)
{
// Thread.Sleep(500);
}
// Printing finished, continue with logic
Alternatively you may want to wrap it in a task so that you can do other things while waiting:
await Task.Run(async () => { while (wordApp.BackgroundPrintingStatus > 0)
{ await Task.Delay(500); } });

Accessing custom task pane in active window - Visual Basic, VSTO

I'm creating a COM add-in in VSTO for Ppt 2013 and am having a problem referencing the custom task pane in the active window.
My code is supposed to make the custom task pane visible for the active window only, however it currently runs for all document windows.
My code is:
For Each CTP As Microsoft.Office.Tools.CustomTaskPane In Globals.ThisAddIn.CustomTaskPanes
If CTP.Window Is Globals.ThisAddIn.Application.ActiveWindow Then
CTP.Visible = True
End If
Next
The taskpane is added to each new presentation created/ opened using the below code
AddIn_control1 = New AddIn_control
AddIn_taskpane = Me.CustomTaskPanes.add(AddIn_control1, "Add-in taskpane", Me.Application.ActiveWindow)
I conducted a little experiment and turns out CustomTaskPane.Window is always ActiveWindow. So to workaround it you can keep tracking of tackpanes in some dictionary:
Dictionary<CustomTaskPane, PowerPoint.Presentation> ctpDict = new Dictionary<CustomTaskPane, PowerPoint.Presentation>();
void Application_AfterNewPresentation(PowerPoint.Presentation Pres) {
AddIn_control AddIn_control1 = new AddIn_control();
CustomTaskPane AddIn_taskpane = this.CustomTaskPanes.Add(AddIn_control1, "Add-In Taskpane", this.Application.ActiveWindow);
ctpDict.Add(AddIn_taskpane, Pres);
}
and later you can use it:
if (cptDict[CTP] == Globals.ThisAddIn.Application.ActivePresentation) {
CTP.Visible = true;
}

VB.NET VSTO referencing custom task panes from ribbon in multiple windows PowerPoint 2013 [duplicate]

I'm creating a COM add-in in VSTO for Ppt 2013 and am having a problem referencing the custom task pane in the active window.
My code is supposed to make the custom task pane visible for the active window only, however it currently runs for all document windows.
My code is:
For Each CTP As Microsoft.Office.Tools.CustomTaskPane In Globals.ThisAddIn.CustomTaskPanes
If CTP.Window Is Globals.ThisAddIn.Application.ActiveWindow Then
CTP.Visible = True
End If
Next
The taskpane is added to each new presentation created/ opened using the below code
AddIn_control1 = New AddIn_control
AddIn_taskpane = Me.CustomTaskPanes.add(AddIn_control1, "Add-in taskpane", Me.Application.ActiveWindow)
I conducted a little experiment and turns out CustomTaskPane.Window is always ActiveWindow. So to workaround it you can keep tracking of tackpanes in some dictionary:
Dictionary<CustomTaskPane, PowerPoint.Presentation> ctpDict = new Dictionary<CustomTaskPane, PowerPoint.Presentation>();
void Application_AfterNewPresentation(PowerPoint.Presentation Pres) {
AddIn_control AddIn_control1 = new AddIn_control();
CustomTaskPane AddIn_taskpane = this.CustomTaskPanes.Add(AddIn_control1, "Add-In Taskpane", this.Application.ActiveWindow);
ctpDict.Add(AddIn_taskpane, Pres);
}
and later you can use it:
if (cptDict[CTP] == Globals.ThisAddIn.Application.ActivePresentation) {
CTP.Visible = true;
}

vsto - determine a word document if created from blank document or open from an existing document

any expert here got any idea how I can determine a word document if created from blank document or open from an existing document.
I am using Globals.ThisAddIn.Application.ActiveDocument.Saved but it seems not enough.
This should do
if (string.IsNullOrEmpty(WordInstance.ActiveDocument.Path))
{
throw new ApplicationException("Document must be saved first");
}
for vsto developers, please go here
if (Globals.ThisAddIn.Application.ActiveDocument.Path == String.Empty)
{
Word.Dialog dlg;
Object timeout = 3000;
dlg = Globals.ThisAddIn.Application.Dialogs[
Word.WdWordDialog.wdDialogFileSaveAs];
int result = dlg.Display(ref timeout);
}
else
{
Globals.ThisAddIn.Application.ActiveDocument.Save();
}
The result will store which button is pressed (0- cancel, 1- ok, 2- close)

C# Excel add-in exception when formula bar is selected and accessing Range.Value

I am just starting with Excel 2010 Add-in with VSTO and is quickly stumped by an exception generated by this code:
public void DoIt()
{
Excel.Range selectedRange = Application.Selection as Excel.Range;
if (selectedRange == null)
{
System.Windows.Forms.MessageBox.Show("Nothing selected");
}
else if(selectedRange.Cells.Count > 0)
{
selectedRange[1, 1].Value = "=2+3"; // exception on this line.
selectedRange[selectedRange.Rows.Count, selectedRange.Columns.Count].Value = "Birthday";
}
}
The exception can be reproduced by first clicking on a single cell in the worksheet, then click the formula bar and then run the above function (I call it via a Ribbon button).
Could anyone advise what is happening and how to handle this exception? Thanks you.
The exception is because you can't run code while in formula-editing mode. You also can't do quite a few other things. For example, click into the formula bar and click Ctrl-N, which normally opens a new workbook. Nothing happens.
I think you need to just Catch the exception and exit the Sub, which will mimic normal Excel operation.
Ideally you'd want to disable the button, just like most Excel ribbon buttons are when in formula-editing mode. I don't know if that's possible though.