A really good new feature of Excel 2013 is that it cannot forced to show more than one Excel workbook in one application. This seems the cause of my Problem:
If I open an Excel workbook programmatically using c# and interop Excel 2013 starts with a new application window. I can working with the workbook in code without problems but I want to hide the application.
Using
Excel.Application excelApp = new Excel.Application();
......
excelApp.Workbooks.Open(...);
excelApp.Visible = false;
hides the application window after showing it. Is there a way to stop showing the application as in Excel 2010 or earlier Version?
In my Excel 2013, using excelApp = new Excel.Application doesn't show any window.
May it be some VBA code in opened workbook which displays window?
So I know the question is old but I needed an answer and none of the given ones worked for me. I ended up just setting Visible to false when initializing to avoid the window flashing open before hiding.
Excel.Application excelApp = new Excel.Application() { Visible = false };
Hide Excel application your code has launched, before opening any Workbook :
Excel.Application excel = new Excel.Application();
excel.Visible = false;
[...]
Excel.Workbook workbook;
workbook = excel.Workbooks.Open(...);
You should always put the Visible into try/catch-block
Excel.Application xlsApp = new Excel.Application();
try
{
// Must be surrounded by try catch to work.
// http://naimishpandya.wordpress.com/2010/12/31/hide-power-point-application-window-in-net-office-automation/
xlsApp.Visible = false;
xlsApp.DisplayAlerts = false;
}
catch (Exception e)
{
Console.WriteLine("-------Error hiding the application-------");
Console.WriteLine("Occured error might be: " + e.StackTrace);
}
Excel.Workbook workbook;
workbook = xlsApp.Workbooks.Open(File, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
Related
As part of an ETL process I am importing data from a variety of different Excel files into a database. Before this happens I need to be able to change the cell format of all cells in an excel worksheet to be in the "General" format.
I have made a start but I'm afraid I dont know how to progress after this:
using Excel = Microsoft.Office.Interop.Excel;
.
.
.
String FilePath = "Code to get file location from database"
String SheetName = "Code to get SheetName from database"
Excel.Application MyApp = new Excel.Application();
MyApp.Visible = false;
Excel.Workbook myWorkbook = MyApp.Workbooks.Open(FilePath,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing);
//Code here to convert all rows to data type of general and then save
MyApp.Workbooks.Close();
Any help on this would be greatly appreciated
You can use Range.NumberFormat property:
var myWorksheet = (Excel.Worksheet)myWorkbook.Worksheets[1];
myWorksheet.Cells.NumberFormat = "General";
Please note that this may cause problems if your sheet contains date values.
I'm building a new Excel workbook in c# by combining the first sheet of a series of different Excel workbooks; subsequently I export the new Workbook to PDF. I made this work, but there is always one Excel instance running by the end of the method.I had the same issue discussed here with a simpler setup and less Excel objects that I could solve with the GC.Collect command. Now, none of this is working.
public void CombineWorkBooks()
{
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.DisplayAlerts = false;
xlApp.Visible = false;
Workbooks newBooks = null;
Workbook newBook = null;
Sheets newBookWorksheets = null;
Worksheet defaultWorksheet = null;
// Create a new workbook, comes with an empty default worksheet");
newBooks = xlApp.Workbooks;
newBook = newBooks.Add(XlWBATemplate.xlWBATWorksheet);
newBookWorksheets = newBook.Worksheets;
// get the reference for the empty default worksheet
if (newBookWorksheets.Count > 0)
{
defaultWorksheet = newBookWorksheets[1] as Worksheet;
}
// loop through every line in Gridview and get the path' to each Workbook
foreach (GridViewRow row in CertificadosPresion.Rows)
{
string path = row.Cells[0].Text;
string CertName = CertificadosPresion.DataKeys[row.RowIndex].Value.ToString();
Workbook childBook = null;
Sheets childSheets = null;
// Excel of each line in Gridview
childBook = newBooks.Open(path,Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
childSheets = childBook.Worksheets;
if (childSheets != null)
{
// Build a new Worksheet
Worksheet sheetToCopy = null;
// Only first Worksheet of the Workbook belonging to that line
sheetToCopy = childSheets[1] as Worksheet;
if (sheetToCopy != null)
{
// Assign the Certificate Name to the new Worksheet
sheetToCopy.Name = CertName;
// set PageSetup for the new Worksheet to be copied
sheetToCopy.PageSetup.Zoom = false;
sheetToCopy.PageSetup.FitToPagesWide = 1;
sheetToCopy.PageSetup.FitToPagesTall = 1;
sheetToCopy.PageSetup.PaperSize = Microsoft.Office.Interop.Excel.XlPaperSize.xlPaperA4;
// Copy that new Worksheet to the defaultWorksheet
sheetToCopy.Copy(defaultWorksheet, Type.Missing);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheetToCopy);
childBook.Close(false, Type.Missing, Type.Missing);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(childSheets);
System.Runtime.InteropServices.Marshal.ReleaseComObject(childBook);
}
//Delete the empty default worksheet
if (defaultWorksheet != null) defaultWorksheet.Delete();
//Export to PDF
newBook.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF, #"C:\pdf\" + SALESID.Text + "_CertPres.pdf", 0, false, true);
newBook.Close();
newBooks.Close();
xlApp.DisplayAlerts = true;
DownloadFile(SALESID.Text);
System.Runtime.InteropServices.Marshal.ReleaseComObject(defaultWorksheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(newBookWorksheets);
System.Runtime.InteropServices.Marshal.ReleaseComObject(newBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(newBooks);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
GC.Collect();
GC.WaitForPendingFinalizers();
}
protected void DownloadFile(string Salesid)
{
string path = #"c:\\pdf\" + Salesid + "_CertPres.pdf";
byte[] bts = System.IO.File.ReadAllBytes(path);
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Type", "Application/octet-stream");
Response.AddHeader("Content-Length", bts.Length.ToString());
Response.AddHeader("Content-Disposition", "attachment; filename=" + Salesid + "_CertPres.pdf");
Response.BinaryWrite(bts);
Response.Flush();
Response.End();
}
The problem must have been related to the call of the DownloadFile Method. I eliminated that call, and the Excel process was properly closed. Some of these operations must have kept a reference to one of the COM objects open, so that they could not be closed. By calling "DownloadFile" at the very end after the GarbageCollect the problem is solved. (I'm not quite sure why)
In your method DownloadFile, you call
Response.End()
HttpResponse.End throws an exception (emphasis mine):
To mimic the behavior of the End method in ASP, this method tries to raise a ThreadAbortException exception. If this attempt is successful, the calling thread will be aborted, [...]
This exception aborts your thread. Thus, all your ReleaseComObject, Excel.Quit, GC.Collect stuff is never executed.
The solution: Don't call Response.End. You probably don't need it. If you need it, you might want to consider the alternative mentioned in the documentation instead:
This method is provided only for compatibility with ASP—that is, for compatibility with COM-based Web-programming technology that preceded ASP.NET. If you want to jump ahead to the EndRequest event and send a response to the client, it is usually preferable to call CompleteRequest instead.
[...]
The CompleteRequest method does not raise an exception, and code after the call to the CompleteRequest method might be executed
PS: Using Excel automation from a web application is not officially supported by Microsoft. For future development, you might want to consider using a third-party Excel library instead.
I found that sometimes the only thing that helps is the "sledgehammer method". Killing all running excel instances:
foreach (Process p in Process.GetProcessesByName("EXCEL"))
{
try
{
p.Kill();
p.WaitForExit();
}
catch
{
//Handle exception here
}
}
Looks to me that you have a reference not cleaned up. Probably something like the 'two dot rule' problem - which in my opinion is a silly rule because you can't code anything decent because it's to difficult to keep track of.
You could try Marshal.ReleaseComObject of your COM references but still asking for trouble...
My suggestion would be to try using VSTO to automate Excel. This will clear your references correctly on your behalf.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/a12add6b-99ea-4677-8245-cd667101683e/vsto-and-office-objects-disposing
I have a problem with Excel worksheet. I am trying to create an Excel file with c#.
This code works and runs correctly on my computer but in other computers get an error at last line:
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheetInvoice;
Excel.Worksheet xlWorkSheetInvoiceLine;
object misValue = System.Reflection.Missing.Value;
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheetInvoice = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheetInvoiceLine = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
System.Runtime.InteropServices.COMException (0x8002000B): Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
at Microsoft.Office.Interop.Excel.Sheets.get_Item(Object Index)
I executed a sample application with similar code on a machine with Excel 2013 and it fails at the same line of code you mentioned. By default Excel 2013 application opens up with a single worksheet ("Sheet1") so you would have to modify the code accordingly
DISP_E_BADINDEX seems to suggest the number of worksheets is less on the other computers. Build in a check to see if the number of worksheets is less than 2 before using get_Item().
i have created new sheet and assigned xlWorkSheetInvoice and xlWorkSheetInvoiceLine to solve it.
var xlSheets = xlWorkBook.Sheets as Excel.Sheets;
var xlNewSheet = (Excel.Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
var xlNewSheet2= (Excel.Worksheet)xlSheets.Add(xlSheets[2], Type.Missing, Type.Missing, Type.Missing);
xlWorkSheetInvoice = xlNewSheet;
xlWorkSheetInvoiceLine = xlNewSheet2;
xlWorkSheetInvoice = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheetInvoiceLine = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
I'm using Excel 2010.
I'm trying so save my excel file, with this code.
It does save a .xls file, but when I open the file I get this message:
The file you are trying to open, 'tre.xls', is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a thrusted source before opening the file. Do you want to open the file now?
If I press yesthe file opens. But what do I need to get rid of this format-popup?
My code:
using System;
using System.Windows.Forms;
using ExcelAddIn1.Classes;
using ExcelAddIn1.Classes.Config;
using Microsoft.Office.Interop.Excel;
using Application = Microsoft.Office.Interop.Excel.Application;
using System.Runtime.InteropServices;
private void Foo(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Execl files (*.xls)|*.xls";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
saveFileDialog.CreatePrompt = true;
saveFileDialog.FileName = null;
saveFileDialog.Title = "Save path of the file to be exported";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
// Save.
// The selected path can be got with saveFileDialog.FileName.ToString()
Application excelObj =
(Application)Marshal.GetActiveObject("Excel.Application");
Workbook wbook = excelObj.ActiveWorkbook;
wbook.SaveAs(saveFileDialog.FileName, XlFileFormat.xlWorkbookDefault,
Type.Missing, Type.Missing, false, false,
XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing);
wbook.Close();
}
}
When I save in excel in the normal way I get "Book1.xlsx", that have no problem to open.
============= FINAL SOLUTION ============
private void Foo(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Execl files (*.xls)|*.xls";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
saveFileDialog.CreatePrompt = true;
saveFileDialog.FileName = null;
saveFileDialog.Title = "Save path of the file to be exported";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
Application excelObj = (Application)Marshal.GetActiveObject("Excel.Application");
Activate(); // <-- added (recommend by msdn, but maybe not nessary here)
Workbook wbook = excelObj.ActiveWorkbook;
wbook.SaveAs(saveFileDialog.FileName, XlFileFormat.xlExcel8, Type.Missing,
Type.Missing, false, false, XlSaveAsAccessMode.xlNoChange, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing);
// wbook.Close(); // <-- don't want this anymore
}
}
With your code you save the workbook as Open XML because XlFileFormat.xlWorkbookDefault evaluates to XlFileFormat.xlOpenXMLWorkbook for Excel 2007+. This is the reason of the warning: you named the file as XLS but actually it is a XLSX.
You can change the file extension to xlsx in your saveFileDialog.Filter property or force the Excel object to save in the XLS format using XlFileFormat.xlExcel8.
EDIT
Use this to save your document:
wbook.SaveAs(saveFileDialog.FileName, XlFileFormat.xlExcel8,
Type.Missing, Type.Missing, false, false,
XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing);
try to set alerts to OFF
oExcel.DisplayAlerts = false;
This problem results from a feature called Extension Hardening, and you can find more information about it here.
Unfortunately, the link above also states that there are no expected changes to this code until at least Office 14.
If you don’t want to look for a solution, but just want to solve the problem, insert this key in your registry to suppress the notification:
[HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Excel\Security] “ExtensionHardening”=dword:00000000
You can accomplish the above by doing the following:
Open your Registry (Start -> Run -> regedit.exe).
Navigate to HKEY_CURRENT_USER\SOFTWARE\MICROSOFT\OFFICE\12.0\EXCEL\SECURITY.
Right click in the right window and choose New -> DWORD
Type “ExtensionHardening” as the name (without the quotes)
Verify that the data has the value “0″.
I am trying to export data from dataset to excel and save it directly to a given path without giving me the option to open,save or cancel.
Using ExcelLibrary this is a one liner ...
DataSet myDataSet;
... populate data set ...
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", myDataSet);
See also Create Excel (.XLS and .XLSX) file from C#
This C# Excel library can also be used to export the dataset. More details about how to export can be found here.
ExcelDocument xls = new ExcelDocument();
xls.easy_WriteXLSFile_FromDataSet("ExcelFile.xls", dataset,
new ExcelAutoFormat(Styles.AUTOFORMAT_EASYXLS1), "Sheet Name");
It's not the greatest solution but here is what I did, it opens a new excel document then copies what is in the dataset, all you need to do is sort out the columns and save it.
Btw totes my first post to answer a question, hope it helps
private void cmdExport_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("excel.exe");
try
{
copyAlltoClipboard();
Microsoft.Office.Interop.Excel.Application xlexcel;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlexcel = new Excel.Application();
xlexcel.Visible = true;
xlWorkBook = xlexcel.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1];
CR.Select();
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true);
}
catch (Exception ex)
{
MessageBox.Show("Error :" + ex.Message);
}
}
private void copyAlltoClipboard()
{
dataGridViewItems.SelectAll();
DataObject dataObj = dataGridViewItems.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Check this DataSetToExcel
and c# (WinForms-App) export DataSet to Excel
In the first link change the code as follows:
Remove the all code that initially starts and try the following
using (StringWriter sw = new StringWriter("Your Path to save"))
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
}
}
Here's another C# library, which lets you export from a DataSet to an Excel 2007 .xlsx file, using the OpenXML libraries.
http://www.mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
All of the source code is provided, free of charge, along with a demo application, and you can use this in your ASP.Net, WPF and WinForms applications.
Once you've added the class to your application, it just takes one function call to export your data into an Excel file.
CreateExcelFile.CreateExcelDocument(myDataSet, "C:\\Sample.xlsx");
It doesn't get much easier than that.
Good luck !
Hi i found a perfect solution Here
Just replace 'missing.value' with System.Type.Missing in the code. Also remove
oWB.Close(System.Type.Missing, System.Type.Missing, System.Type.Missing);
and
oXL.Quit();
from the code. Otherwise your excel will get closed automatically as soon as it open.