I am running my C# application which opens many excel files using loops but then in the end of each loop I call the below function to end the excel process but still the process in task manager is not ended and I am not sure why. Can anyone advise?
private void xlCleanup(Excel.Application xlApp, Excel.Workbook xlWorkbook, Excel.Worksheet xlWorksheet, Excel.Range xlRange)
{
//cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
//rule of thumb for releasing com objects:
// never use two dots, all COM objects must be referenced and released individually
// ex: [somthing].[something].[something] is bad
//release com objects to fully kill excel process from running in the background
if (xlRange != null || xlWorksheet != null)
{
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
}
//close and release
xlWorkbook.Close(0);
Marshal.ReleaseComObject(xlWorkbook);
//quit and release
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);
}
Try adding this to the end of the method. It has resolved this problem for me:
xlRange = null;
xlWorksheet = null;
xlWorkbook = null;
xlApp = null;
GC.Collect();
(edited to set xl vars to null)
(edit #2)
Also read the answer here:
How do I properly clean up Excel interop objects?
All,
Apologies if this is a very basic question and has been asked before, I predominately write in VBA / JAVA. However a project I am working on requires a C# script. Which carries out 3 simple steps:
Target a excel workbook which is already open. File path:
\Csdatg04\psproject\Robot\Peoplesoft To LV\Master Files - Do not use\Transactions into LV Template.xlsm
Populate cells A1,A2 & A3 with three variables already retrieved earlier in the automation.
Run a macro stored within the filepath mentioned above Macro name "ControlMacroACT"
The code I have developed is below, however in each stage identified above I am encountering errors (Probably basic errors).
Error 1: This line of code is to open a workbook I would like this to target an already active workbook.
Error 2: Worksheet not found
public void RunActualsMacro(string Filepath, string Period, String FiscalYear)
{
//~~> Define your Excel Objects
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkBook;
//~~> Start Excel and open the workbook.
//Error 1
xlWorkBook = xlApp.Workbooks.Open("\\Csdatg04\\psproject\\Robot\\Peoplesoft To LV\\Master Files - Do not use\\Transactions into LV Template.xlsm");
// Populat Cells A1,A2,A3 with string variables
// Error 2 Worksheet not found
worksheet.Rows.Cells[1, 1] = Filepath;
worksheet.Rows.Cells[2, 1] = Period;
worksheet.Rows.Cells[3, 1] = FiscalYear;
//~~> Run the macro ControlMacroAct
xlApp.Run("ControlMacroACT");
//~~> Clean-up: Close the workbook
xlWorkBook.Close(false);
//~~> Quit the Excel Application
xlApp.Quit();
}
Any help would be much appreciated.
You need to use Marshal.GetActiveObject, and this code is roughly right, but cannot test right now.
public void RunActualsMacro(string Filepath, string Period, String FiscalYear)
{
//~~> Define your Excel Objects
Excel.Application xlApp = null;
Excel.Workbook xlWorkBook;
//~~> Start Excel and open the workbook.
//handle errors below
try {
xlApp = (Excel.Application) System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
} catch {
//perhaps exit - or throw??
}
xlWorkBook = xlApp.Workbooks["Transactions into LV Template.xlsm"];
// Populat Cells A1,A2,A3 with string variables
Excel.Worksheet ws = xlWorkBook.Worksheets["Sheet1"] //what the tab name of sheet
ws.Cells[1, 1] = Filepath;
ws.Cells[2, 1] = Period;
ws.Cells[3, 1] = FiscalYear;
//~~> Run the macro ControlMacroAct
xlApp.Run("ControlMacroACT");
//~~> Clean-up: Close the workbook
xlWorkBook.Close(false);
//~~> Quit the Excel Application
xlApp.Quit();
}
I'm using Excel = Microsoft.Office.Interop.Excel to write various data to Excel sheets.
Excel.Workbook wb = null;
Excel.Worksheet ws = null;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
try {
// Create new workbook
wb = (Excel.Workbook)(excelApp.Workbooks.Add(Type.Missing));
ws = wb.ActiveSheet as Excel.Worksheet;
// write data ...
// Save & Close
excelApp.DisplayAlerts = false; // Don't show file dialog for overwrite
wb.Close(true, targetFilename, Type.Missing);
} finally {
// Close the Excel process
if (null != ws)
Marshal.ReleaseComObject(ws);
if (null != wb)
Marshal.ReleaseComObject(wb);
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);
GC.Collect();
}
This code is exectued by multiple threads at a time, and it's been working almost always. Even the Excel processes disappear in task manager.
However, sometimes a System.Runtime.InteropServices.COMException is thrown at wb.Close(true, targetFilename, Type.Missing). It claims that access on the target filename was denied. Though I've been making sure that the target filenames are unique.
May the exception be due to any bad handling of Excel or maybe that I'm using threads?
Apparently, targetFilename wasn't really unique. There was one single difference in upper/lower case spelling, and it seems like two threads tried to write to the same file at once. The issue was easily solvable by using targetFilename.ToLower().
Anyway, if you discover any further potential issues, please leave a comment.
How can I open my Excel worksheet in the current open instance of Microsoft Excel? When I use my code, a new instance of Excel is opened.
private Excel.Application xlApp;
private Excel.Workbook xlWorkBook;
private Excel.Worksheet xlWorkSheet;
xlApp = new Excel.Application();
xlApp.Visible = true;
xlWorkBook = xlApp.Workbooks.Open(textBox1.Text);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.ActiveSheet;
You can do something like the following to get a reference to a running Excel instance (if there is one):
public Excel.Application TryGetExistingExcelApplication()
{
try
{
object o = Marshal.GetActiveObject("Excel.Application");
return (Excel.Application)o;
}
catch (COMException)
{
// Probably there is no existing Excel instance running, return null
return null;
}
}
Once you have a reference to a running instance, you can access it's Workbooks collection.
One caveat: if you try to automate an existing Excel instance, you may get "server busy" exceptions. To avoid this, you can implement IOleMessageFilter error handlers. This article describes how to do it for automating Visual Studio; the technique is identical for automating Excel.
I am trying to convert some VBA code to C#. I am new to C#. Currently I am trying to open an Excel file from a folder and if it does not exist then create it. I am trying something like the following. How can I make it work?
Excel.Application objexcel;
Excel.Workbook wbexcel;
bool wbexists;
Excel.Worksheet objsht;
Excel.Range objrange;
objexcel = new Excel.Application();
if (Directory("C:\\csharp\\error report1.xls") = "")
{
wbexcel.NewSheet();
}
else
{
wbexcel.Open("C:\\csharp\\error report1.xls");
objsht = ("sheet1");
}
objsht.Activate();
You need to have installed Microsoft Visual Studio Tools for Office (VSTO).
VSTO can be selected in the Visual Studio installer under Workloads > Web & Cloud > Office/SharePoint Development.
After that create a generic .NET project and add a reference to Microsoft.Office.Interop.Excel via 'Add Reference... > Assemblies' dialog.
Application excel = new Application();
Workbook wb = excel.Workbooks.Open(path);
Missing.Value is a special reflection struct for unnecessary parameters replacement
In newer versions, the assembly reference required is called Microsoft Excel 16.0 Object Library. If you do not have the latest version installed you might have Microsoft Excel 15.0 Object Library, or an older version, but it is the same process to include.
FileInfo fi = new FileInfo("C:\\test\\report.xlsx");
if(fi.Exists)
{
System.Diagnostics.Process.Start(#"C:\test\report.xlsx");
}
else
{
//file doesn't exist
}
private void btnChoose2_Click(object sender, EventArgs e)
{
OpenFileDialog openfileDialog1 = new OpenFileDialog();
if (openfileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.btnChoose2.Text = openfileDialog1.FileName;
String filename = DialogResult.ToString();
var excelApp = new Excel.Application();
excelApp.Visible = true;
excelApp.Workbooks.Open(btnChoose2.Text);
}
}
Imports
using Excel= Microsoft.Office.Interop.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
Here is the code to open an excel sheet using C#.
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook wbv = excel.Workbooks.Open("C:\\YourExcelSheet.xlsx");
Microsoft.Office.Interop.Excel.Worksheet wx = excel.ActiveSheet as Microsoft.Office.Interop.Excel.Worksheet;
wbv.Close(true, Type.Missing, Type.Missing);
excel.Quit();
Here is a video mate on how to open an excel worksheet using C# https://www.youtube.com/watch?v=O5Dnv0tfGv4
For opening a file, try this:
objexcel.Workbooks.Open(#"C:\YourPath\YourExcelFile.xls",
missing, missing, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing,missing, missing);
You must supply those stupid looking 'missing' arguments. If you were writing the same code in VB.Net you wouldn't have needed them, but you can't avoid them in C#.
you should open like this
Excel.Application xlApp ;
Excel.Workbook xlWorkBook ;
Excel.Worksheet xlWorkSheet ;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open("csharp.net-informations.xls", 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
source : http://csharp.net-informations.com/excel/csharp-open-excel.htm
ruden
It's easier to help you if you say what's wrong as well, or what fails when you run it.
But from a quick glance you've confused a few things.
The following doesn't work because of a couple of issues.
if (Directory("C:\\csharp\\error report1.xls") = "")
What you are trying to do is creating a new Directory object that should point to a file and then check if there was any errors.
What you are actually doing is trying to call a function named Directory() and then assign a string to the result. This won't work since 1/ you don't have a function named Directory(string str) and you cannot assign to the result from a function (you can only assign a value to a variable).
What you should do (for this line at least) is the following
FileInfo fi = new FileInfo("C:\\csharp\\error report1.xls");
if(!fi.Exists)
{
// Create the xl file here
}
else
{
// Open file here
}
As to why the Excel code doesn't work, you have to check the documentation for the Excel library which google should be able to provide for you.
Microsoft.Office.Interop.Excel.Application excapp;
excapp = new Microsoft.Office.Interop.Excel.Application();
object misval=System.Reflection.Missing.Value;
Workbook wrkbuk = new Workbook();
Worksheet wrksht = new Worksheet();
wrkbuk = excapp.Workbooks._Open(#"C:\Users\...\..._template_v1.0.xlsx", misval, misval,
misval, misval, misval, misval, misval, misval, misval, misval, misval, misval);
wrksht = (Microsoft.Office.Interop.Excel.Worksheet)wrkbuk.Worksheets.get_Item(2);
Is this a commercial application or some hobbyist / open source software?
I'm asking this because in my experience, all free .NET Excel handling alternatives have serious problems, for different reasons. For hobbyist things, I usually end up porting jExcelApi from Java to C# and using it.
But if this is a commercial application, you would be better off by purchasing a third party library, like Aspose.Cells. Believe me, it totally worths it as it saves a lot of time and time ain't free.
Code :
private void button1_Click(object sender, EventArgs e)
{
textBox1.Enabled=false;
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Excell File |*.xlsx;*,xlsx";
if (ofd.ShowDialog() == DialogResult.OK)
{
string extn = Path.GetExtension(ofd.FileName);
if (extn.Equals(".xls") || extn.Equals(".xlsx"))
{
filename = ofd.FileName;
if (filename != "")
{
try
{
string excelfilename = Path.GetFileName(filename);
}
catch (Exception ew)
{
MessageBox.Show("Errror:" + ew.ToString());
}
}
}
}
For editing Excel files from within a C# application, I recently started using NPOI.
I'm very satisfied with it.