I am trying to save an excel file via C#, but the file is not being saved in the location I have specified using a variable. Below is the code I have:
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
//MessageBox.Show("Excel is not properly installed!!");
return;
}
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
if (!System.IO.File.Exists(FileName))
{
xlWorkBook = xlApp.Workbooks.Add(misValue);
}
else
{
xlWorkBook = xlApp.Workbooks.Open(FileName, 0, false, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", true, false, 0, true, 1, 0);
}
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
//Some Code
xlApp.DisplayAlerts = false;
xlWorkBook.SaveAs(FileName, Type.Missing,Type.Missing,Type.Missing,false,Type.Missing,XlSaveAsAccessMode.xlExclusive,Type.Missing,Type.Missing,Type.Missing);
xlWorkBook.Close(true, FileName, misValue);
xlApp.Application.Quit();
xlApp.Quit();
What am I doing wrong here? I am beyond frustrated that is not saving where I want it to. Any help would be appreciated
As per #mohammedlok's comment about making sure there are no memory leaks, I always use a try-catch-finally method to ensure that the excel process will always close no matter what.
The sample code below worked for me:
Application excelApp = new Application();
Workbook excelWorkbook = null;
string excelFilePath = "C:\\Users\\Desktop\\Sample.xlsx";
try
{
//Create a workbook
excelWorkbook = excelApp.Workbooks.Add(Type.Missing);
//Make and name a worksheet
activeWorksheet = excelWorkbook.ActiveSheet;
//Write in cell B3 of the worksheet
Range r = activeWorksheet.get_Range("B3", Type.Missing);
r.Value2 = "This is a sample.";
//Save the workbook
excelWorkbook.SaveAs(excelFilePath, Type.Missing, Type.Missing, Type.Missing, false, Type.Missing, XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (excelWorkbook != null)
{
excelApp.Calculation = XlCalculation.xlCalculationAutomatic;
excelApp.DisplayAlerts = false;
excelWorkbook.RefreshAll();
excelWorkbook.Close(true, excelFilePath);
excelApp.Quit();
}
}
Related
I have to do a program which reads an excel xlsx file and stores the data in to the database. This my actual simple code, I don't even take the values from the excel file, but I'm not able to kill the process. I've googled a lot and I've tried many things, but the excel process stays alive.
public void readFile(path)
{
try
{
Microsoft.Office.Interop.Excel.Application xlApp = null;
Microsoft.Office.Interop.Excel.Workbooks workbooks = null;
Microsoft.Office.Interop.Excel.Workbook xlWorkbook = null;
Microsoft.Office.Interop.Excel.Worksheet xlWorksheet = null;
Microsoft.Office.Interop.Excel.Range xlRange = null;
xlApp = new Microsoft.Office.Interop.Excel.Application();
workbooks = xlApp.Workbooks;
xlWorkbook = workbooks.Open(path);
xlWorksheet = xlWorkbook.Sheets[1];
xlRange = xlWorksheet.UsedRange;
//------Here is where I will read the data
xlWorkbook.Close();
workbooks.Close();
xlApp.Quit();
Marshal.FinalReleaseComObject(xlRange);
Marshal.FinalReleaseComObject(xlWorksheet);
Marshal.FinalReleaseComObject(xlWorkbook);
Marshal.FinalReleaseComObject(workbooks);
Marshal.FinalReleaseComObject(xlApp);
xlRange = null;
xlWorksheet = null;
xlWorkbook = null;
workbooks = null;
xlApp = null;
}
catch (Exception e)
{
}
}
And the process stays alive. I hope you can help me.
I've tried many things... The code below seems to work.
public void readFile(path)
{
try
{
Microsoft.Office.Interop.Excel.Application xlApp = null;
Microsoft.Office.Interop.Excel.Workbooks workbooks = null;
Microsoft.Office.Interop.Excel.Workbook xlWorkbook = null;
Microsoft.Office.Interop.Excel.Sheets xlsheets = null;
Microsoft.Office.Interop.Excel.Worksheet xlWorksheet = null;
Microsoft.Office.Interop.Excel.Range xlRange = null;
xlApp = new Microsoft.Office.Interop.Excel.Application();
workbooks = xlApp.Workbooks;
xlWorkbook = workbooks.Open(path);
xlsheets = xlWorkbook.Sheets;
xlWorksheet = xlsheets[1];
xlRange = xlWorksheet.UsedRange;
//--------------------------------------------------------------------
xlWorkbook.Close();
workbooks.Close();
xlApp.Quit();
Marshal.FinalReleaseComObject(xlRangeColumns);
Marshal.FinalReleaseComObject(xlRangeRows);
Marshal.FinalReleaseComObject(xlRange);
Marshal.FinalReleaseComObject(xlWorksheet);
Marshal.FinalReleaseComObject(xlsheets);
Marshal.FinalReleaseComObject(xlWorkbook);
Marshal.FinalReleaseComObject(workbooks);
Marshal.FinalReleaseComObject(xlApp);
xlRangeColumns = null;
xlRangeRows = null;
xlRange = null;
xlWorksheet = null;
xlsheets = null;
xlWorkbook = null;
workbooks = null;
xlApp = null;
}
catch (Exception e)
{
}
}
There are very little differences. A month ago I would tell you that both codes are the same. Can someone tell me why this code works, while the first code doesn't?
Try putting this at the end of your code and it will kill your excel
foreach (var process in Process.GetProcessesByName("myExcelFilename"))
{
process.Kill();
}
You need either to put the objects into using blocks, or put the closing statements into a finally.
Whenever your application throws an exception, it will leave the interop open. What you should do instead is put your shutdown code in a finally block, which means that code will always be run. Like so:
public void readFile(string path)
{
Microsoft.Office.Interop.Excel.Application xlApp = null;
Microsoft.Office.Interop.Excel.Workbooks workbooks = null;
Microsoft.Office.Interop.Excel.Workbook xlWorkbook = null;
Microsoft.Office.Interop.Excel.Worksheet xlWorksheet = null;
Microsoft.Office.Interop.Excel.Range xlRange = null;
try
{
xlApp = new Microsoft.Office.Interop.Excel.Application();
workbooks = xlApp.Workbooks;
xlWorkbook = workbooks.Open(path);
xlWorksheet = xlWorkbook.Sheets[1];
xlRange = xlWorksheet.UsedRange;
//------Here is where I will read the data
}
catch (Exception e)
{
}
finally
{
xlWorkbook?.Close();
workbooks?.Close();
xlApp?.Quit();
Marshal.FinalReleaseComObject(xlRange);
Marshal.FinalReleaseComObject(xlWorksheet);
Marshal.FinalReleaseComObject(xlWorkbook);
Marshal.FinalReleaseComObject(workbooks);
Marshal.FinalReleaseComObject(xlApp);
xlRange = null;
xlWorksheet = null;
xlWorkbook = null;
workbooks = null;
xlApp = null;
}
}
Another option is not to screw around with interop and use another library, such as EPPlus (available on NuGet), to handle the reading of excel files, which would close when the program closes.
I have the following code for creating and saving an excel file in c# but when it finishes, no file is created to my desktop, I can't figure out what I'm doing wrong:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.Visible = false;
Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Worksheet ws = (Worksheet)wb.Worksheets[1];
Range rangeAToC = ws.get_Range("A1", "C1");
string[] headerRow = { "GIP Id", "First Name", "Last Name"};
int indexAtRow = 0;
foreach (Range cell in rangeAToC)
{
cell.Value2 = headerRow[indexAtRow];
indexAtRow++;
}
//Save report
wb.SaveAs("C:/Users/Abdul/Desktop/GipEmployeeReport.xls", Type.Missing,
Type.Missing,Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
//Close out COM objects
xlApp.Workbooks.Close();
xlApp.Quit();
first thing i noticed is that your using forward slashes (/) instead of backslashes \
I have tried various methods of merging worksheets using COM Interop.
Here's what I have ended up with (unnecessary code omitted for brevity):
public bool CombineWorkBooks(string exportFilePath, IEnumerable<string> filesToMergeFrom, bool deleteRawFiles)
{
var success = false;
Excel.Application xlApp = null;
Excel.Workbook mergeToWorkbook = null;
Excel.Workbooks mergeToWorkbooks = null;
Excel.Sheets mergeToWorksheets = null;
Excel.Worksheet defaultWorksheet = null;
try
{
if (filesToMergeFrom == null)
{
return false;
}
xlApp = new Excel.Application
{
DisplayAlerts = false,
Visible = false,
CutCopyMode = Excel.XlCutCopyMode.xlCopy
};
mergeToWorkbooks = xlApp.Workbooks;
mergeToWorkbook = mergeToWorkbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
mergeToWorksheets = mergeToWorkbook.Worksheets;
// Get the reference for the [first] empty default worksheet
if (mergeToWorksheets.Count > 0)
{
defaultWorksheet = mergeToWorksheets[1] as Excel.Worksheet;
}
if (defaultWorksheet == null)
{
return false;
}
var reportSheetIndex = 1;
var fileMergeCount = 0;
foreach (var mergeFromFilename in filesToMergeFrom)
{
fileMergeCount++;
Excel.Workbook sourceWorkbook = null;
Excel.Sheets childSheets = null;
// Make sure file is still there...
if (!File.Exists(mergeFromFilename))
{
continue;
}
try
{
// Open source file
sourceWorkbook = mergeToWorkbooks.Open(mergeFromFilename,
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 = sourceWorkbook.Worksheets;
if (childSheets != null)
{
var sheetsCopiedFromSource = 0;
// childSheets.Copy(defaultWorksheet, Type.Missing);
for (int iChildSheet = 1; iChildSheet <= childSheets.Count; iChildSheet++)
{
Excel.Worksheet sourceWorksheet = null;
try
{
sourceWorksheet = childSheets[iChildSheet] as Excel.Worksheet;
if (sourceWorksheet != null)
{
string name = string.Format(baseSheetName, reportSheetIndex.ToString("D4", new CultureInfo(CultureInfo.CurrentCulture.Name)));
// Assigning the worksheet name
sourceWorksheet.Name = Truncate(name, 31); // only 31 char max
// Copy the worksheet before the default sheet
sourceWorksheet.Copy(defaultWorksheet, Type.Missing);
reportSheetIndex++;
sheetsCopiedFromSource++;
}
}
finally
{
disposeCOMObject(sourceWorksheet);
}
}
// Close the childbook - for some reason, calling close below may cause an
// exception -> System.Runtime.InteropServices.COMException (0x80010108): The object invoked has disconnected from its clients.
try
{
sourceWorkbook.Close(false, Type.Missing, Type.Missing);
}
catch (COMException comException)
{
if (comException.ErrorCode != 0x80010108)
{
throw;
}
_messages.Add("Caught COMException, discarding it.");
}
_messages.Add(string.Format("Successfully copied {0} worksheets from report file: '{1}'", sheetsCopiedFromSource, mergeFromFilename));
}
}
catch (Exception ex)
{
_messages.Add(string.Format("An error occurred processing file '{0}'.", mergeFromFilename));
}
finally
{
disposeCOMObject(childSheets);
disposeCOMObject(sourceWorkbook);
}
}
// Delete the empty default worksheet
defaultWorksheet.Delete();
// Select the first sheet.
if (mergeToWorksheets.Count > 0)
{
Excel.Worksheet firstSheet = null;
try
{
firstSheet = mergeToWorksheets[1] as Excel.Worksheet;
if (firstSheet != null)
{
firstSheet.Select(Type.Missing);
firstSheet.Range["A1"].Select();
}
}
finally
{
disposeCOMObject(firstSheet);
}
}
// Determine the file extension
var fileExt = GetExcelExtension();
if (string.IsNullOrEmpty(Path.GetExtension(exportFilePath)))
{
exportFilePath = string.Format("{0}.{1}", exportFilePath, fileExt);
}
else if (Path.GetExtension(exportFilePath) != string.Format(".{0}", fileExt))
{
exportFilePath = Path.ChangeExtension(exportFilePath, fileExt);
}
_mergeOutputFile = exportFilePath;
// Save the merged output
mergeToWorkbook.SaveAs(exportFilePath,
Excel.XlFileFormat.xlWorkbookDefault,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Excel.XlSaveAsAccessMode.xlExclusive,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing,
Type.Missing);
// Close file
mergeToWorkbooks.Close();
xlApp.DisplayAlerts = true;
success = true;
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
disposeCOMObject(defaultWorksheet);
disposeCOMObject(mergeToWorksheets);
disposeCOMObject(mergeToWorkbook);
disposeCOMObject(mergeToWorkbooks);
// Quit Excel.
if (xlApp != null)
{
xlApp.Quit();
disposeCOMObject(xlApp);
}
// Only delete source files upon success...
if (success &&
deleteRawFiles)
{
deleteTemporaryFiles(filesToMergeFrom);
}
// Clean up remaining resources
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
Now - this works all well and good. BUT... the merge file has the cell/row interior colors all messed up (usually blacks and purples - something a 3 year old might prefer). The source worksheets have some rows with highlighted colors or background (interior) colors other than white.
If I add the following code, I can reset all the cell colors in the merged file to white, but I've not managed with any success to preserve the colors of the original source sheets.
// Reset the background colour in the cells to white. For some reason the worksheet copy
// operation screws up the cell backgrounds - pinks, purples and other business-like
// colours.
foreach (Excel.Worksheet targetWorksheet in mergeToWorkbook.Worksheets)
{
var usedRange = targetWorksheet.UsedRange;
usedRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.White);
}
I ran into the same problem, and found the following Microsoft support note:
http://support.microsoft.com/kb/2465477
They mention here a few workarounds. For me the following solution worked: just set the new workbook's color scheme to the old workbook's color scheme, like this:
mergeToWorkbook.Colors = sourceWorkbook.Colors;
I am open and close an excel book fro mC# like this
Microsoft.Office.Interop.Excel.Application oXL = null;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = null;
try
{
excelWorkbook = oXL.Workbooks.Open(MyFile,
0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
.....
....
....
excelWorkbook.Save();
excelWorkbook.Close(Microsoft.Office.Interop.Excel.XlSaveAction.xlSaveChanges, Type.Missing, Type.Missing);
oXL.Quit();
excelWorkbook = null;
oXL = null;
}
catch { }
But there is stil lan EXCEL.EXE process left running in the task list, why ?
how do I "kill" everything about excel when I am done ?
Is it not enough with ".Quit()" and put the reference to null ?
or is there some magic reference left in the C# heap somewhere that have not been
dereferenced ?
/Stefan
Try this..
oXL.quit()
// Note, oXL still points to excel
System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oXL)
oXL = Nothing
I have an Excel file with 5 worksheets and I want with c# code to open it
and when it is opened I want the sheet number 3 to be activated.
How can I do that?
Like this:
using Excel;
Excel.Application excelApp = new Excel.ApplicationClass();
// if you want to make excel visible to user, set this property to true, false by default
excelApp.Visible = true;
// open an existing workbook
string workbookPath = "c:/SomeWorkBook.xls";
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
// get all sheets in workbook
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
// get some sheet
string currentSheet = "Sheet1";
Excel.Worksheet excelWorksheet =
(Excel.Worksheet)excelSheets.get_Item(currentSheet);
// access cell within sheet
Excel.Range excelCell =
(Excel.Range)excelWorksheet.get_Range("A1", "A1");
Hope this helps
MDSN info here
What about something like this: (untested)
//using Excel = Microsoft.Office.Interop.Excel;
Excel.ApplicationClass app = new Excel.ApplicationClass();
Excel.Workbook workbook = app.Workbooks.Open("YourFile.xls",
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);
Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Sheets["Number 3"];
worksheet.Activate();
If wanting to present visual feedback to the User, these two statements will set the activated sheet and select the range accordingly:
Consider including the following statement immediately prior to initializing the Excel.Range...
// Set Active sheet in Excel
excelWorksheet.Activate()
Also consider the following statement immediately after initializing the Excel.Range...
// Set Active range in Excel
excelCell.Activate()
public static Workbook openExternalWorkBook(String fileName)
{
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = false;
return excel.Workbooks.Open(fileName, false);
}