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.
Related
I'm trying to write a program that changes and prints an existing label "label.lbx" from a p-Touch Brother printer.
But my program stops at:
bpac.Document doc = new bpac.Document();
The error message:
**System.IO.FileNotFoundException:** "The COM class directory for the component with CLSID {B940C105-7F01-46FE-BF41-E040B9BDA83D} could not be retrieved due to the following error: 8007007e The specified module was not found. (HRESULT exception: 0x8007007E).
I have already removed and added the Interop.bpac.dll file. Project cleaned up and rebuilt. Moved the file to the Debug Order. But it didn't help.
Does anyone have an idea why the error message is coming?
My Code:
string path = #"C:\Users\source\repos\LabelTool\label.lbx";
bpac.Document doc = new bpac.Document();
doc.Open(path);
doc.SetPrinter("Printer", true);
doc.GetObject("ReplacePlace").Text = textBox1.Text;
doc.StartPrint("", bpac.PrintOptionConstants.bpoDefault);
doc.PrintOut(1, bpac.PrintOptionConstants.bpoDefault);
doc.EndPrint();
doc.Close();
I was able to solve the problem. For those who have the problem, try the following.
First of all you need the 32 bit version. Then it should work on your computer.
Next you have to pay attention that the dll file is always created with a release.
I had to change from "Any CPU" to "x86". And:
Reference --> selection of the dll file in my case (Interop.bpac)-->
below in properties: Embed interopt types = False ; Local copy= True
See picture
The code then changes:
using bpac;
...
string path = #"C:\Users\source\repos\LabelTool\label.lbx";
bpac.Document doc = new bpac.Document();
doc.Open(path);
doc.SetPrinter("Printer", true);
doc.GetObject("ReplacePlace").Text = textBox1.Text;
doc.StartPrint("", bpac.PrintOptionConstants.bpoDefault);
doc.PrintOut(1, bpac.PrintOptionConstants.bpoDefault);
doc.EndPrint();
doc.Close();
Hope this helps some of you and saves you the trouble of troubleshooting.
I'm creating a wpf application for internal deployment.
A user using the software is getting the following error when trying to create an excel interop instance.
Retrieving the COM class factory for component with CLSID (...) failed due to the following error: 80070002 The system cannot find the file specified
The section that is catching the error is the following
try
{
_excelApplication = new Microsoft.Office.Interop.Excel.Application();
GetWindowThreadProcessId(_excelApplication.Hwnd, out ExcelAppProcessId);
_excelApplication.ScreenUpdating = false;
}
catch(Exception e)
{
//TODO Move message box to parents
MessageBox.Show($"Termination Error: Could not open Excel Application: {e.Message}");
Environment.Exit(110);
}
Previously the same user had an issue while trying to open Access (can't remember what the exact error was) and I implemented the following to fix it.
try
{
//MessageBox.Show($"OS: {EnvironmentFunctions.is64BitOperatingSystem} Process: {EnvironmentFunctions.is64BitProcess}");
if (EnvironmentFunctions.is64BitOperatingSystem && !EnvironmentFunctions.is64BitProcess)
{
string PathValue = "";
string sAdd = "";
string strCommonFiles =
Environment.GetEnvironmentVariable("CommonProgramFiles(x86)");
sAdd = ";" + strCommonFiles + "\\microsoft shared\\DAO";
PathValue = Environment.GetEnvironmentVariable("Path");
PathValue += sAdd;
Environment.SetEnvironmentVariable("path", PathValue);
}
_accessApplication = new Microsoft.Office.Interop.Access.Application();
GetWindowThreadProcessId(_accessApplication.hWndAccessApp(), out AccessAppProcessId);
}
catch
{
MessageBox.Show("Termination Error: Could not open Access Application");
Environment.Exit(110);
}
Would there be a similar solution but for the Excel interop?
Notes about the user: They are one of the few left running windows 7.
Retrieving the COM class factory for component with CLSID (...) failed due to the following error: 80070002 The system cannot find the file specified
Typically this error is caused by only a few issues, which I will list below.
Recent Windows updates
Partition issue's and or problems
Bitness issue's (determined what Office is installed on the end machine and what the application is compiled against)
I asked earlier about what you were targeting because you have some code that is checking if the pc is 64bit and you have already ran into some issues. This then lead me to bitness issues with creating instances of Excel.
My recommendation and solution to your exact issue is because the end machine is 32bit, so compiling for x86/32bit should fix the issue.
On a final note, you may be able to remove that old code as it wouldn't be needed anymore.
I'm using the following code to run a VBA macro via C# Excel interop:
public void macroTest()
{
Excel.Application xlApp = new Excel.Application();
xlApp.Visible = true;
string bkPath = #"C:\somePath\someBk.xlsm";
Excel.Workbook bk = xlApp.Workbooks.Open(bkPath);
string bkName = bk.Name;
string macroName = "testThisMacro_m";
string runString = "'" + bkName + "'!"+macroName;
xlApp.Run(runString);
bk.Close(false);
xlApp.Quit();
}
testThisMacro_m is in a module testMacro, and this runs successfully. When I replace it with:
string macroName = "testThisMacro_s";
where testThisMacro_s has its code in Sheet1, the xlApp.Run() line gives the following COM Exception:
Cannot run the macro ''someBk.xlsm'!testThisMacro_s'.
The macro may not be available in this workbook or all macros may be disabled.
I checked macro security settings, and they are indeed set to "Disable with notification", but being able to run a macro from a module and not from a worksheet seems to indicate that this is a different issue than application-level macro security.
Is there something different that I have to do when making an interop call to a macro in a worksheet?
UPDATE: I was able to get the macro to execute by changing the call to:
string macroName = "Sheet1.testThisMacro_s"
but it seems that this hands control back to C# before the macro completes, so now I need to figure out how to check for macro completion (probably a different question).
A Worksheet object is an object - and objects are defined with class modules. Worksheets, workbooks, user forms; they're all objects. And you can't just call a method on an object, if you don't have an instance of that object.
Macros work off standard modules, which aren't objects, and don't need to be instantiated.
Application.Run can't call methods of an object, that's why macros need to be in standard modules.
I was able to get the macro to execute by changing the call to:
string macroName = "Sheet1.testThisMacro_s"
Wouldn't a helper sub solve both of your problems, re: Mat's Mug's reply concerning instantiation?
In some standard module:
Sub testHelperSubToBeCalledFromInterop
Call Sheet1.testThisMacro_s
End Sub
EDIT:
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.
In fact, I have a C# application that is runned.
When it's launched, it runs an excel instance and save it to a variable :
excelApp = new Excel.Application();
Then I cycle through each of the excel's addins to find my own created added :
private void getAddin()
{
const string addinName = "myAddInName";
foreach (Office.COMAddIn addin in excelApp.COMAddIns)
if (addin.Description.ToUpper().Contains(addinName.ToUpper()))
{
myAddin = addin;
return;
}
}
The problem is that, it may happens that my plugin is in the deactivated elements list. (Due to some crash)
Then I must go to (on excel's frame) :
File >Options >AddIns >Manage >Deactivated elements >Achieve >"myAddin" >Activate
to get my addin working again (after excel's restart)...
I tried using an addin's property to reactivate it but may app crashes again in that case.
myAddin.Connect = loadAddin;
Someone has an idea on how to resolve it / auto-reactivate a disabled plugin using C# ?
This should help
http://msdn.microsoft.com/en-us/library/aa662931(v=office.11).aspx
I believe you need to do
if(!myAddin.Connect)
{
myAddin.Connect =true;
}