Unable to set SlideSize property while using powerpoint interop - c#

We are trying to convert PPT file to PDF using Powerpoint Office Interop. We are using ExportAsFixedFormat() to do the conversion as shown in the below code snippet:
public static void ConvertPowerPointToPdf(string inputFile)
{
string outputFileName = #"C:\All format files\PPT2PDF.pdf";
Microsoft.Office.Interop.PowerPoint.Application powerPointApp =
new Microsoft.Office.Interop.PowerPoint.Application();
Presentation presentation = null;
Presentations presentations = null;
try
{
presentations = powerPointApp.Presentations;
presentation = presentations.Open(inputFile, MsoTriState.msoFalse, MsoTriState.msoFalse,
MsoTriState.msoFalse);
presentation.PageSetup.SlideSize = PpSlideSizeType.ppSlideSizeA4Paper; //It throws the exception here
presentation.ExportAsFixedFormat(outputFileName, PpFixedFormatType.ppFixedFormatTypePDF,
PpFixedFormatIntent.ppFixedFormatIntentPrint);
}
catch (Exception)
{
throw;
}
}
The above code works fine if we don't set the SlideSize property. The moment we try to set SlideSize property, the exception is thrown as "PageSetup (unknown member) : Failed." Screenshot of the error message is shown below:
The version of Microsoft.Office.Interop.PowerPoint is 15.0.0.0 and Microsoft Office 15.0 Object Library is used as the Office core library. My PC in Windows 8.1 and I am using Microsoft Office 2013. Since we need custom output format, we need to setup SlideSize property which is currently throwing exception.

The code you have is correct. I was able to recreate your error exactly with with the presentation being marked as 'Final'. Try adding:
presentation.Final = false;
Add it before you resize. Hope it helps. Good Luck.

Related

Create a PPT using C# without having to kill a running powerpnt process

I've been trying to create a PPT with C# using something like the code below.
Microsoft.Office.Interop.PowerPoint.Application pptApp = new Microsoft.Office.Interop.PowerPoint.Application();
The problem is, if there's another powerpnt process running, the line of code above doesn't do anything (even when debugging it). The application just hangs infinitely.
Is there a way to be able to generate PPTs without having to kill an existing powerpnt process?
With Aspose.Slides for .NET, you don't need to install PowerPoint to generate presentations with a single line of code:
using (Presentation presentation = new Presentation())
{
// Add content to the presentation here
// ...
presentation.Save("output.pptx", SaveFormat.Pptx); // You can choose many other formats
}
Also, you can see your results by using Online Viewer here.
I work at Aspose.
In NET Framework you can hook into the "Running Object Table" (ROT) and get a running Powerpoint instance using InteropServices.Marshal.
Then you can work with the running instance. If it is not running you can start it.
using System.Runtime.InteropServices;
using PowerPointApp = Microsoft.Office.Interop.PowerPoint.Application;
PowerPointApp ppApp = null;
try
{
var ppType = System.Type.GetTypeFromProgID("PowerPoint.Application");
var ppRaw = Marshal.GetActiveObject("PowerPoint.Application");
ppApp = ppRaw as PowerPointApp;
}
catch
{
}
if (ppApp == null)
{
ppApp = new PowerPointApp();
}
Marshal.GetActiveObject is not available in .NET Core and current .NET 5/6

explorer preview causes System.Runtime.InteropServices.COMException: Automation rights are not granted. on ActivePresentation.name

public static PowerPoint.Presentation GetActivePPT(this PowerPoint.Application application)
{
try
{
if (App.Presentations.Count > 0)
{
return application.ActivePresentation;
}
else
{
return null;
}
}
catch (Exception ex)
{
return null;
}
}
I call this function like so:
PowerPoint.Presentation ppPresentation = PowerPointApplication.GetActivePPT();
if(ppPresentation != null)
{
Console.WriteLine(ppPresentation.Name);
}
And I get a :
COMException: Message:Presentation (unknown member) : Invalid request. Automation rights are not granted. StackTrace: at Microsoft.Office.Interop.PowerPoint._Presentation.get_Name()
Here is what I know Presentations.Count is one and application.ActivePresentation is not null
It looks like I am not the only one to encounter this issue with Explorer preview:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/327cfc7b-07a3-49ad-9e0b-f7100852e3bf/applicationpresentationsopen-generating-exception-error-code-2147467259-automation-rights-are?forum=vsto
https://social.msdn.microsoft.com/Forums/en-US/e7437e44-1aea-4ab5-bbf2-6794037c872a/vsto-powerpoint-explorer-previewpane?forum=vsto
http://youpresent.co.uk/presentations-count-returns-wrong-number/
https://github.com/jon-hedgerows/msofficesvn/issues/25
https://groups.google.com/forum/#!topic/microsoft.public.powerpoint/KR1VuXtDccQ
It sounds like this is a permissions issue? hoping its as simple as setting something to COMVisible(true) but no good ideas at this point.
this blog post seems to claim a write lock is in play but Word and Excel do not exhibit the same behavior.
When you select a presentation in Windows Explorer with preview pane enabled, Windows Explorer appears to open the presentation in a hidden window. If you attempt to access any of the hidden presentation's object members (e.g., ppPresentation.Name) from a COM add-in you get the "Automation rights are not granted." exception.
Unfortunately, there does not appear to be a good way to determine if the hidden presentation was opened by Windows Explorer (e.g, ppPresentation.Windows.Count = 0), since accessing any of the presentation's object members via code seems to throw this exception. Therefore, the only workaround appears to be error handling, like Try/Catch.
Note that Presentations.Count returns the number of all open presentations, including those opened by the preview pane, so you will need to account for this if your add-in relies on an accurate count of presentations it can actually work with.
Also, note that this problem does not appear to affect Excel in this same way.

Invalid Cast Exception, Unable to Cast COM object to Excel

Similar questions have been asked before, but I want to try and refine it to my situation.
I am downloading a legacy file type (Excel 2003 (.xls)) and I need to strip the data from the file. The problem is I get :
{"Unable to cast COM object of type 'Microsoft.Office.Interop.Excel.ApplicationClass'
to interface type 'Microsoft.Office.Interop.Excel._Application'. This operation failed
because the QueryInterface call on the COM component for the interface
I am currently trying to get this working on my machine before I send the app to production, which will/does have excel on the server.
I have tried reinstalling office, but that did not work. I think the problem lies more in the fact that I have office 2013 on my box and I am attempting to run a decade old file type through it.
I tried to use this:
public void Convert(String file)
{
var app = new Application();
var wb = app.Workbooks.Open(file);
wb.SaveAs(file + "x", XlFileFormat.xlOpenXMLWorkbook);
wb.Close();
app.Quit();
}
That still causes the same problem, because the file will not open.
Any suggestions?
UPDATE
Here is the full method I am using
public Worksheet GetExcelBy(string url)
{
var fileName = #"C:\temp\tempfile.xls";
var webClient = new WebClient();
webClient.DownloadFile(url, fileName);
Convert(fileName);
var excel = new Application();
var workbook = excel.Workbooks.Open(fileName);
return (Worksheet)workbook.Worksheets["Data 6"];
}
this is the URL:
http://tonto.eia.doe.gov/dnav/pet/xls/pet_pri_spt_s1_d.xls
I presume the line with var excel = new Application(); is the line where the exception is raised. From my experience in the matter, as I also tried to follow other advice found on the internet, the solution I accidentally found was to explicitly define the non use of 32 bit access mode for the interop dll.
For doing so in visual studio, I had to tick and then untick the box "Prefer 32-bit" in the build section of the project configuration, which added <Prefer32Bit>false</Prefer32Bit> in the .csproj file.

writing data from C# to Excel interrupted by opening Excel Window

While my C# program writes data continuously to an Excel spreadsheet, if the end user clicks on the upper right menu and opens the
Excel Options window, this causes following exception:
System.Runtime.InteropServices.COMException with HRESULT: 0x800AC472
This interrupts the data from being written to the spreadsheet.
Ideally, the user should be allowed to do this without causing an exception.
The only solution I found to this error code was to loop and wait until the exception went away:
Exception from HRESULT: 0x800AC472
which effectively hangs the app, data is not written to Excel and the user is left in the dark about the problem.
I thought about disabling the main menu of Excel while writing to it, but cannot find a reference on how to do this.
My app supports Excel 2000 to 2013.
Here is how to reproduce the issue:
Using Visual Studio Express 2013 for Windows Desktop, .NET 4.5.1 on Windows 7 64-bit with Excel 2007, create a new Visual C# Console Application project.
Add reference to "Microsoft ExceL 12.0 Object Library" (for Excel) and to "System.Windows.Forms" (for messagebox).
Here is the complete code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks;
using System.Threading; // for sleep
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using Microsoft.Win32;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int i = 3; // there is a split pane at row two
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
try
{
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.Application();
xlApp.Visible = false;
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlApp.Visible = true;
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
// next 2 lines for split pane in Excel:
xlWorkSheet.Application.ActiveWindow.SplitRow = 2;
xlWorkSheet.Application.ActiveWindow.FreezePanes = true;
xlWorkSheet.Cells[1, 1] = "Now open the";
xlWorkSheet.Cells[2, 1] = "Excel Options window";
}
catch (System.Runtime.InteropServices.COMException)
{
System.Windows.Forms.MessageBox.Show("Microsoft Excel does not seem to be installed on this computer any longer (although there are still registry entries for it). Please save to a .tem file. (1)");
return;
}
catch (Exception)
{
System.Windows.Forms.MessageBox.Show("Microsoft Excel does not seem to be installed on this computer any longer (although there are still registry entries for it). Please save to a .tem file. (2)");
return;
}
while(i < 65000)
{
i++;
try
{
xlWorkSheet.Cells[i, 1] = i.ToString();
Thread.Sleep(1000);
}
catch (System.Runtime.InteropServices.COMException)
{
System.Windows.Forms.MessageBox.Show("All right, what do I do here?");
}
catch (Exception)
{
System.Windows.Forms.MessageBox.Show("Something else happened.");
}
}
Console.ReadLine(); //Pause
}
}
}
Lanch the app, Excel appears and data is written to it. Open the Excel options dialog window from the menu and up pops the error:
An exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll and wasn't handled before a managed/native boundary
Additional information: Exception from HRESULT: 0x800AC472
Click on Continue and my message box "All right, what do I do here?" appears.
Please advise?
Best regards,
Bertrand
We finally went all the way to Microsoft Support with this issue. Their final response was:
I am able to reproduce the issue. I researched on this further and
found that this behaviour is expected and by design. This
exception, 0x800AC472 – VBA_E_IGNORE, is thrown because Excel is busy
and will not service any Object Model calls. Here is one of the
discussions that talks about this.
http://social.msdn.microsoft.com/Forums/vstudio/en-US/9168f9f2-e5bc-4535-8d7d-4e374ab8ff09/hresult-800ac472-from-set-operations-in-excel?forum=vsto The work around I see is to explicitly catch this exception and retry
after sometime until your intended action is completed.
Since we cannot read the minds of the user who might decide to open a window or take a note without realizing the soft has stopped logging (if you mask the error), we decided to work around using:
xlWorkSheet.EnableSelection = Microsoft.Office.Interop.Excel.XlEnableSelection.xlNoSelection;
to lock the Excel window UI. We provide an obvious "unlock" button but when the user clicks it, he is sternly warned in a messagebox along with a "Do you wish to continue?"
Make Excel Interactive is a perfect solution. The only problem is if the user is doing something on Excel at the same time, like selecting range or editing a cell. And for example your code is returning from a different thread and trying to write on Excel the results of the calculations. So to avoid the issue my suggestions is:
private void x(string str)
{
while (this.Application.Interactive == true)
{
// If Excel is currently busy, try until go thru
SetAppInactive();
}
// now writing the data is protected from any user interaption
try
{
for (int i = 1; i < 2000; i++)
{
sh.Cells[i, 1].Value2 = str;
}
}
finally
{
// don't forget to turn it on again
this.Application.Interactive = true;
}
}
private void SetAppInactive()
{
try
{
this.Application.Interactive = false;
}
catch
{
}
}
xlApp = new Excel.Application();
xlApp.Interactive = false;
What I have done successfully is to make a temp copy of the target excel file before opening it in code.
That way I can manipulate it independent of the source document being open or not.
One possible alternative to automating Excel, and wrestling with its' perculiarities, is to write the file out using the OpenXmlWriter writer (DocumentFormat.OpenXml.OpenXmlWriter).
It's a little tricky but does handle sheets with > 1 million rows without breaking a sweat.
OpenXml docs on MSDN
Since Interop does cross threading, it may lead to accessing same object by multiple threads, leading to this exception, below code worked for me.
bool failed = false;
do
{
try
{
// Call goes here
failed = false;
}
catch (System.Runtime.InteropServices.COMException e)
{
failed = true;
}
System.Threading.Thread.Sleep(10);
} while (failed);

Office.Interop.Powerpoint import

I am having trouble with PowerPoint conversion to HTML.
Here is code
Microsoft.Office.Interop.PowerPoint.Application oApplication = new Microsoft.Office.Interop.PowerPoint.Application();
Microsoft.Office.Interop.PowerPoint.Presentation oPresentation = oApplication.Presentations.Open(sourceFileName);
oPresentation.SaveAs(destFileName, Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType.ppSaveAsHTML);
oPresentation.Close();
oApplication.Quit();
I get the following error
System.Runtime.InteropServices.COMException (0x80048240):
Presentations (unknown member) : Invalid request. The PowerPoint Frame
window does not exist. at
Microsoft.Office.Interop.PowerPoint.Presentations.Open(String
FileName, MsoTriState ReadOnly, MsoTriState Untitled, MsoTriState
WithWindow) at
SmartBoard_V2.Section.Admin.Areas.DersEditor.DersEdit.convertPowerPoint(String
fennKod) in c:\Users\Kamandar\Documents\Visual Studio
2012\Projects\SmartBoard_V2\SmartBoard_V2\Section\Admin\Areas\DersEditor\DersEdit.aspx.cs:line 163
Note that if you're automating PPT 2013 (or presumably later), this won't work. As of 2013, PowerPoint no longer has a SaveAsHTML method.
I suspect that you need to set the application to visible before you try and save it.
To do this simply add the following code before declaring the oPresentation object.
oApplication .Visible = Office.MsoTriState.msoTrue;
Edit: Just noticed you are using ASP.NET, Although it is not recommended, you can check here for a similar problem.

Categories