Format Excel File using C# - c#

The Bellow function is used to formate the excel file but after running the function the Application Excel is not closeing from the Try.. (not able to kill the application) Please Help me on this
private void FormateExcelFile()
{
try
{
int nI = 0;//For Loop
string nFieldName = string.Empty;
nUserName= WindowsIdentity.GetCurrent().Name; //Get Windows Login User
string reportFilenPath = Application.StartupPath + "\\OutPutFiles\\" + "NewTempFile.xls";
string connString = "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + reportFilenPath + "';Extended Properties=Excel 8.0;";
DataTable parts = new DataTable();
using (OleDbConnection conn = new OleDbConnection(connString))
{
string sqlParts = "Select * from [" + nSheetName + "]";
OleDbDataAdapter adapter = new OleDbDataAdapter(sqlParts, conn);
adapter.Fill(parts);
}
for (nI = 0; nI < parts.Columns.Count; nI++)
{
DataColumn column = parts.Columns[nI];
if (nI == 0) { nFieldName = column.ColumnName; }
else { nFieldName = nFieldName + "," + column.ColumnName; }
}
parts.Dispose(); parts = null;
oExcel = new Excel.Application();
oBook = oExcel.Workbooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oBook.Worksheets.get_Item(nSheetName.Replace("$", ""));
oExcel.DisplayAlerts = false;
oExcel.Visible = true;
//Check the Field Is Avilable in the Sheet if not then Add
if (nFieldName.Contains("Sub Device") == false)
{
nRng = oSheet.get_Range("A1", oMissing);
nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
oSheet.Cells[1, 1] = "Sub Device";
}
if (nFieldName.Contains("Brand") == false)
{
nRng = oSheet.get_Range("A1", oMissing);
nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
oSheet.Cells[1, 1] = "Brand";
}
if (nFieldName.Contains("Model") == false)
{
nRng = oSheet.get_Range("A1", oMissing);
nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
oSheet.Cells[1, 1] = "Model";
}
if (nFieldName.Contains("Product Details") == false)
{
nRng = oSheet.get_Range("A1", oMissing);
nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
oSheet.Cells[1, 1] = "Product Details";
}
if (nFieldName.Contains("Price") == false)
{
nRng = (Excel.Range)oSheet.Cells[1, 1];
//nRng = oSheet.get_Range("A1", oMissing);
nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
oSheet.Cells[1, 1] = "Price";
}
oBook.Save();
oBook.Close(false, oMissing, oMissing);
oExcel.DisplayAlerts = true;
releaseObject(oSheet);
releaseObject(oBook);
oExcel.Quit();
releaseObject(oExcel);
releaseObject(nRng);
nRng = null;
oExcel = null;
oSheet = null;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
releaseObject(oSheet);
releaseObject(oBook);
//oExcel.Quit();
releaseObject(oExcel);
}
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null;
}
catch (Exception ex)
{
obj = null;
MessageBox.Show("Exception Occured while releasing object " + ex.ToString());
}
finally
{
GC.Collect();
}
}

You need to release all the Excel objects you're referencing. For example:
if (nFieldName.Contains("Sub Device") == false)
{
nRng = oSheet.get_Range("A1", oMissing);
nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
oSheet.Cells[1, 1] = "Sub Device";
}
should be something like (leaving out try/finally for simplicity)
if (nFieldName.Contains("Sub Device") == false)
{
nRng = oSheet.get_Range("A1", oMissing);
var col = nRng.EntireColumn
col.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
var cells = oSheet.Cells;
var firstCell = cells[1,1];
firstCell.Value = "Sub Device";
Marshal.ReleaseComObject(nRng);
Marshal.ReleaseComObject(col);
Marshal.ReleaseComObject(cells);
Marshal.ReleaseComObject(firstCell);
}
Similarly:
oBook = oExcel.Workbooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oBook.Worksheets.get_Item(nSheetName.Replace("$", ""));
needs to be:
oBooks = oExcel.Workbooks
oBook = oBooks.Open(...);
oSheets = oBook.Worksheets
oSheet = oSHeets.get_Item(...);
and you need to release oBooks and oSheets.

Try to end your excel task with these commands:
Marshal.FinalReleaseComObject(sheet);
app.DisplayAlerts = false; //Very important!
range = null;
sheet = null;
// Garbage collecting
GC.Collect();
GC.WaitForPendingFinalizers();
book.Close(false, Missing.Value, Missing.Value);
Marshal.FinalReleaseComObject(book);
book = null;
app.Quit();
Marshal.FinalReleaseComObject(app);
app = null;
I had the same problem accessing my excel files, but with the shown code it closes all the time.
Of course not if the program crashes before it reaches the code, check your code with the debugger.
In your case: book --> oBook, app --> oExcel, sheet --> oSheet.

Take away these lines:
nRng = null;
oExcel = null;
oSheet = null;
I think you are releasing your Excel object, and then by making it equal to null afterwards you are doing something with Excel which starts a new instance on your machine.
After releasing the object, you don't need to set variables to null, or run GC.Collect();, the garbage collector will take care of this for you, and I think in this instance trying to clean up the managed objects yourself (after correctly cleaning up the unmanaged Excel object) is actually causing your problems.

I had the same kind of issue working with Excel interop. The problem should be originated by this kind of lines (at least it was in my case):
oBook = oExcel.Workbooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
In the end you reales oBook, but this is what's really happening here: in order to get oBook pointing to your opened workbook, you accessed a Workbooks object (using oExcel.Workbooks). This is never released, and keeps Excel from quitting.
I solved the problem by rewriting that line as:
Microsoft.Interop.Excel.Workbooks oBooks = oExcel.Workbooks;
oBook = oBooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
releaseObject(oBooks);
Of course this has to be done for every line of this kind (for instance oBook.Worksheets.get_Item(...), nRng.EntireColumn.Insert(...), and so on).

Related

Converting cell content to string data type in Excel using C#

In the below code I am getting this kind of exception.
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in Data_Consistency.exe
Additional information: Exception from HRESULT: 0x800A03EC
for (i = 0; i < excelCell.Columns.Rows.Count; i++)
{
if (excelCell.Value2 == null)
continue;
else
excelWorksheet.Range[excelCell,Type.Missing].ToString();
}
Possible solution is
get value from cell:
var cellValue = (string)(excelWorksheet.Cells[10, 2] as Excel.Range).Value;
write to cell again (already string)
or write =TEXT(var, "0") which convert in excel
this worked for me.......
{
string l_connectionString = "";
string l_filePath = txtComparisonFile.Text;
string l_fileExt = System.IO.Path.GetExtension(l_filePath);
if (l_fileExt.CompareTo(".xls") == 0)
l_connectionString = #"provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + l_filePath + ";Extended Properties='Excel 8.0;HRD=Yes;IMEX=1';"; //for below excel 2007
else
l_connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + l_filePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1';";
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = false;
string workbookPath = l_filePath;
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
string currentSheet = l_selectedSheet;
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets.get_Item(currentSheet);
Excel.Range excelCell = (Excel.Range)excelWorksheet.get_Range(l_comparisonSheetRange);
excelWorksheet.Columns.NumberFormat = "#";
excelWorkbook.Save();
excelWorkbook.Close();
g_objExcelHelper.g_objDtCompare = g_objExcelHelper.GetDataTable(l_connectionString, l_selectedSheet, l_comparisonSheetRange, g_objExcelHelper.g_objDtCompare);

How to insert rich text to excel file from c#

I have a requirement of inserting bold and underlined text to excel file while preserving new line through c# code in windows form application. My function is as below:
private bool insertIntoExcel(string pathname , string sheetname ,int excelRow, int excelColumn,string value)
{
try
{
Microsoft.Office.Interop.Excel._Application oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = true;
oXL.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook mWorkBook = oXL.Workbooks.Open(pathname, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Get all the sheets in the workbook
Microsoft.Office.Interop.Excel.Sheets mWorkSheets = mWorkBook.Worksheets;
//Get the allready exists sheet
Microsoft.Office.Interop.Excel._Worksheet mWSheet1 = (Microsoft.Office.Interop.Excel.Worksheet)mWorkSheets.get_Item(sheetname);
Microsoft.Office.Interop.Excel.Range range = mWSheet1.UsedRange;
mWSheet1.Cells[excelRow, excelColumn] = value;
}catch
{
return false;
}
return true;
}
this code dosen't preserves new linw, bold, underline and bullets line. How to achieve this? Thanks
if your value has '\n' or Environment.NewLine maybe you can split it by these characters:
For example:
string[] newLineChars = { "\n", Environment.NewLine};
string[] splittedVals = value.Split(newLineChars, StringSplitOptions.None);
foreach (string val in splittedVals)
{
mWSheet1.Cells[excelRow, excelColumn] += val;
}

Writing Data to an Existing Excel File in C#

I want to write data to an existing Excel file, whilst preserving the original data.
The file has sheet1; I want to write on sheet2, then save.
The problem is that every time I save, it will create a new Excel file and overwrite the existing one.
Could anyone provide any help to keep the old data while saving?
I have the following function
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
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);
MessageBox.Show(xlWorkSheet.get_Range("A1","A1").Value2.ToString());
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
MessageBox.Show("Unable to release the Object " + ex.ToString());
}
finally
{
GC.Collect();
}
}
}
}
This is my way to add data to existing excel file: (Its very simple and efficient)
1 - Add Microsoft.Office.Interop.Excel component as a reference to your application
You can find it in .Net FrameWork in Extensions section
2- then add:
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
3- Now I have a simple class with 3 methods (openExcel, addDataToExcel, closeExcel)
public class ExcelFile
{
private string excelFilePath = string.Empty;
private int rowNumber = 1; // define first row number to enter data in excel
Excel.Application myExcelApplication;
Excel.Workbook myExcelWorkbook;
Excel.Worksheet myExcelWorkSheet;
public string ExcelFilePath
{
get { return excelFilePath; }
set { excelFilePath = value; }
}
public int Rownumber
{
get { return rowNumber; }
set { rowNumber = value; }
}
public void openExcel()
{
myExcelApplication = null;
myExcelApplication = new Excel.Application(); // create Excell App
myExcelApplication.DisplayAlerts = false; // turn off alerts
myExcelWorkbook = (Excel.Workbook)(myExcelApplication.Workbooks._Open(excelFilePath, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value)); // open the existing excel file
int numberOfWorkbooks = myExcelApplication.Workbooks.Count; // get number of workbooks (optional)
myExcelWorkSheet = (Excel.Worksheet)myExcelWorkbook.Worksheets[1]; // define in which worksheet, do you want to add data
myExcelWorkSheet.Name = "WorkSheet 1"; // define a name for the worksheet (optinal)
int numberOfSheets = myExcelWorkbook.Worksheets.Count; // get number of worksheets (optional)
}
public void addDataToExcel(string firstname, string lastname, string language, string email, string company)
{
myExcelWorkSheet.Cells[rowNumber, "H"] = firstname;
myExcelWorkSheet.Cells[rowNumber, "J"] = lastname;
myExcelWorkSheet.Cells[rowNumber, "Q"] = language;
myExcelWorkSheet.Cells[rowNumber, "BH"] = email;
myExcelWorkSheet.Cells[rowNumber, "CH"] = company;
rowNumber++; // if you put this method inside a loop, you should increase rownumber by one or wat ever is your logic
}
public void closeExcel()
{
try
{
myExcelWorkbook.SaveAs(excelFilePath, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value); // Save data in excel
myExcelWorkbook.Close(true, excelFilePath, System.Reflection.Missing.Value); // close the worksheet
}
finally
{
if (myExcelApplication != null)
{
myExcelApplication.Quit(); // close the excel application
}
}
}
}
According to Programmatically Insert to Existing Excel File using C# by R Manimaran:
Here is the code which will do the insertion in an already exists excel file.
private static Microsoft.Office.Interop.Excel.Workbook mWorkBook;
private static Microsoft.Office.Interop.Excel.Sheets mWorkSheets;
private static Microsoft.Office.Interop.Excel.Worksheet mWSheet1;
private static Microsoft.Office.Interop.Excel.Application oXL;
public static void ReadExistingExcel()
{
string path = #"C:\Tool\Reports1.xls";
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = true;
oXL.DisplayAlerts = false;
mWorkBook = oXL.Workbooks.Open(path, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
//Get all the sheets in the workbook
mWorkSheets = mWorkBook.Worksheets;
//Get the allready exists sheet
mWSheet1 = (Microsoft.Office.Interop.Excel.Worksheet)mWorkSheets.get_Item("Sheet1");
Microsoft.Office.Interop.Excel.Range range= mWSheet1.UsedRange;
int colCount = range.Columns.Count;
int rowCount= range.Rows.Count;
for (int index = 1; index < 15; index++)
{
mWSheet1.Cells[rowCount + index, 1] = rowCount +index;
mWSheet1.Cells[rowCount + index, 2] = "New Item"+index;
}
mWorkBook.SaveAs(path, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal,
Missing.Value, Missing.Value, Missing.Value, Missing.Value,Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive,
Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value);
mWorkBook.Close(Missing.Value, Missing.Value, Missing.Value);
mWSheet1 = null;
mWorkBook = null;
oXL.Quit();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
If you need to create a new Sheet use the following code.
oSheet = (Excel.Worksheet)oWB.Sheets.Add(Missing.Value, Missing.Value, Missing.Value, Missing.Value);
oSheet.Name = SheetName;
Use ClosedXml dll in my case its resolved my problem
var workbook = new XLWorkbook(fileName);
var ws1 = workbook.Worksheet(1);
var ws2 = workbook.Worksheet(2);
workBook.SaveAs(fileName);
Here is my code:
public void ExcelDataAssign(List<string> ColumnwiseData, int length, DateTime ReportDate, List<string> AmountList, List<string> PeriodDateList, int CellId)
{
int PeriodColIndex = 6, Desc1ColIndex = 14, Desc2ColIndex = 11, Desc3ColIndex = 9, PeriodDateColIndex = 7;
int PeriodRowIndex = 3, Desc1RowIndex = 1, Desc2RowIndex = 1, Desc3RowIndex = 1, PeriodDateRowIndex = 3;
string cellName = ColumnwiseData[length];
string CapitiveName = ColumnwiseData[2 * length];
string DomicileName = ColumnwiseData[3 * length];
string file = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + #"\Excel\OutputTemplate.xlsx";
string fileName = file.Replace("bin", "").Replace("Debug", "");
var workbook = new XLWorkbook(fileName);
var ws1 = workbook.Worksheet(1);
ws1.Cell(1, 2).Value = DomicileName;
ws1.Cell(2, 2).Value = CapitiveName;
ws1.Cell(3, 2).Value = cellName;
ws1.Cell(4, 2).Value = ReportDate;
int amntIncr = 0;
while (AmountList.Count > amntIncr)
{
ws1.Cell(PeriodColIndex, PeriodRowIndex).Value = "Period";
ws1.Cell(Desc1ColIndex, Desc1RowIndex + 2).Value = AmountList[amntIncr];
ws1.Cell(Desc2ColIndex, Desc2RowIndex + 2).Value = (AmountList[amntIncr + 1]);
ws1.Cell(Desc3ColIndex, Desc3RowIndex + 2).Value = (AmountList[amntIncr + 2]);
PeriodRowIndex++;
Desc1RowIndex++;
Desc2RowIndex++;
Desc3RowIndex++;
amntIncr = amntIncr + 3;
}
int periodDateIncr = 0;
while (PeriodDateList.Count > periodDateIncr)
{
ws1.Cell(PeriodDateColIndex, PeriodDateRowIndex).Value = PeriodDateList[periodDateIncr];
PeriodDateRowIndex++;
periodDateIncr = periodDateIncr + 3;
}
var ws2 = workbook.Worksheet(2);
ws2.Cell(1, 2).Value = DomicileName;
ws2.Cell(2, 2).Value = CapitiveName;
ws2.Cell(3, 2).Value = cellName;
ws2.Cell(4, 2).Value = ReportDate;
SqlParameter paramCellId = new SqlParameter("#CellId", CellId);
SqlParameter paramReportDate = new SqlParameter("#ReportDate", ReportDate);
DataTable dt = new DataTable();
var data = SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, "Usp_inputResult", paramCellId, paramReportDate).Tables[0];
List<string> lstClmwiseData = new List<string>();
foreach (DataRow r in data.Rows)
{
foreach (DataColumn c in data.Columns)
{
lstClmwiseData.Add(r[c].ToString());
}
}
int snoColIndex = 6, GLCodeColIndex = 6, DescriptioColIndex = 6, movementDebitColIndex = 6, movementCreditColIndex = 6, ClosingdebitcolIndex = 6, ClosingCreditColIndex = 6;
int snoRowIndex = 1, GLCodRowIndex = 2, DescriptioRowIndex = 3, movementDebitRowIndex = 4, movementCreditRowIndex = 5, ClosingdebitRowIndex = 6, ClosingCreditRowIndex = 7;
int secondSheet = 0;
int SnoIncrement = 1;
while (lstClmwiseData.Count > secondSheet)
{
ws2.Cell(snoColIndex, snoRowIndex).Value = SnoIncrement;
ws2.Cell(GLCodeColIndex, GLCodRowIndex).Value = lstClmwiseData[secondSheet];
ws2.Cell(DescriptioColIndex, DescriptioRowIndex).Value = lstClmwiseData[secondSheet + 1];
ws2.Cell(movementDebitColIndex, movementDebitRowIndex).Value = lstClmwiseData[secondSheet + 2];
ws2.Cell(movementCreditColIndex, movementCreditRowIndex).Value = lstClmwiseData[secondSheet + 3];
ws2.Cell(ClosingdebitcolIndex, ClosingdebitRowIndex).Value = lstClmwiseData[secondSheet + 4];
ws2.Cell(ClosingCreditColIndex, ClosingCreditRowIndex).Value = lstClmwiseData[secondSheet + 5];
snoColIndex++;
GLCodeColIndex++;
DescriptioColIndex++;
movementDebitColIndex++;
movementCreditColIndex++;
ClosingdebitcolIndex++;
ClosingCreditColIndex++;
SnoIncrement++;
secondSheet = secondSheet + 6;
}
string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + #"\Downloads\ReportUtitlity";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string FileName = workbook.Author + "_" + "Report_"+CellId+ "CellId" +"_" + $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss-fff}";
workbook.SaveAs(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + #"\Downloads\ReportUtitlity\" + FileName + ".xlsx");
}

"Exception from HRESULT: 0x800A01A8"

I've written this code to count the number of rows that are populated in an excel worksheet. It works until it gets yo a certain number of rows (not the total). Then comes up with the error message "Exception from HRESULT: 0x800A01A8" Any help much appreciated
namespace ConsoleApplication1
{
class ExcelClass
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Excel.Application excelApp = new Excel.Application(); // Creates a new Excel Application
excelApp.Visible = true; // Makes Excel visible to the user.
// The following code opens an existing workbook
string workbookPath = "D:\\RSG_D.xls"; // Add your own path here
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath, 0,
false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true,
false, 0, true, false, false);
// The following gets the Worksheets collection
Excel.Sheets excelSheets = excelWorkbook.Worksheets;
// The following gets Sheet1 for editing
string currentSheet = "Sheet1";
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelSheets.get_Item(currentSheet);
//declare a variable to hold the CurrentCulture
System.Globalization.CultureInfo oldCI;
//get the old CurrenCulture and set the new, en-US
//void SetNewCurrentCulture()
//{
oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
//}
int rowCounter = 1;
while ( rowCounter != null)
{
Excel.Range countRows = (Excel.Range)excelWorksheet.Cells[rowCounter, 1] as Excel.Range;
object CountRows = countRows.Value;
rowCounter++;
Console.WriteLine(CountRows);
}
excelWorkbook.Close(0);
excelApp.Quit();
//reset Current Culture back to the originale
System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
}
}
}
I had the exact same problem tonight: Here is the code I have used and it's worked properly for me:
Excel.Application oExcel = new Excel.Application();
//oExcel.Visible = true; (this caused me huge problems
Excel.Workbook oBook = oExcel.Workbooks.Open(#"C:\Yoink\Birr Castle Demesne Interactive Map\Birr Castle Demesne Interactive Map\bin\Debug\Red Tree Trail.xlsx");
Excel.Worksheet oSheet1 = oBook.Worksheets["Red Tree Trail"] as Excel.Worksheet; (use your own worksheet title there)
Excel.Range rng = oSheet1.get_Range("A1", "AJ51"); (use your own range there
int rowCount = rng.Rows.Count;
int colCount = rng.Columns.Count;
string[,] tsReqs = new string[rowCount, colCount];
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
string str = rng.Cells[i, j].Text;
tsReqs[i - 1, j - 1] = str;
}
}
I think your problem is in this line:
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(workbookPath, 0,
false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true,
false, 0, true, false, false);

C# Excel doesn't close itself when using OleDbConnection's Open method

I am creating and releasing references to excel com interfaces to manipulate excel's worksheets.
In this situation Excel closes itself correctly.
If I use OleDbDataAdapter connection to fetch data then excel is still in the memory.
I have read almost everything on this subject.
I have created subroutines to appropriate release references.
I am using:
GC.Collect();
GC.WaitForPendingFinalizers();
What else can I do?
This seems to be obscure problem..
Here is the code:
namespace ExcelTestCode
{
class Program
{
static void Main(string[] args)
{
Application excel = null;
Workbook workbook = null;
Worksheet workSheet = null;
object oMissing = Missing.Value;
excel = new Application { Visible = false };
workbook = excel.Workbooks.Open(#"c:\temp.xls", 0, false, 5, "", "",
true, XlPlatform.xlWindows, "\t", false, false, 0, true, true, oMissing);
workSheet = (Worksheet)workbook.Sheets[1];
try
{
string strError = "";
System.Data.DataTable dtTable = null;
//If I remove the following line, everything is allright
dtTable = ImportDataTableFromExcelIMEX(#"c:\temp.xls", out strError);
}
finally
{
if (workSheet != null)
{
Marshal.ReleaseComObject(workSheet);
workSheet = null;
}
if (workbook != null)
{
workbook.Close(false, oMissing, oMissing);
Marshal.ReleaseComObject(workbook);
workbook = null;
}
if (excel != null)
{
excel.Quit();
Marshal.ReleaseComObject(excel);
excel = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
public static System.Data.DataTable ImportDataTableFromExcelIMEX(string filename, out string error)
{
string connstring = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + #";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""";
OleDbConnection upocn = new OleDbConnection(connstring);
try
{
upocn.Open();
System.Data.DataTable dt = null;
dt = upocn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
using (OleDbDataAdapter upoda = new OleDbDataAdapter("select * from [" + dt.Rows[0]["TABLE_NAME"].ToString() + "]", upocn))
{
DataSet upods = new DataSet();
error = string.Empty;
upoda.Fill(upods);
if (!string.IsNullOrEmpty(error))
return null;
return upods.Tables[0];
}
}
catch (Exception ex)
{
error = ex.Message;
}
finally
{
upocn.Close();
upocn = null;
}
return null;
}
}
}
try using (OleDbConnection upocn = new OleDbConnection(connectionString)), or call upocn.Dispose()
From MSDN OleDbConnection.Dispose: Releases all resources used by the System.ComponentModel.Component.
OleDbConnection.close: Closes the connection to the data source
Updated I can produce this problem if i do connection.close like in above code, but when i call dispose it works fine, I dont see any instance of excel. Below is code that works for me. Ensure you clean running instance from task manager before you test
class Program
{
static void Main(string[] args)
{
Application excel = null;
Workbook workbook = null;
Worksheet workSheet = null;
object oMissing = Missing.Value;
excel = new Application { Visible = false };
workbook = excel.Workbooks.Open(#"c:\Book1.xls", 0, false, 5, "", "",
true, XlPlatform.xlWindows, "\t", false, false, 0, true, true, oMissing);
workSheet = (Worksheet)workbook.Sheets[1];
try
{
string strError = "";
System.Data.DataTable dtTable = null;
//If I remove the following line, everything is allright
dtTable = ImportDataTableFromExcelIMEX(#"c:\Book1.xls", out strError);
}
finally
{
if (workSheet != null)
{
Marshal.ReleaseComObject(workSheet);
workSheet = null;
}
if (workbook != null)
{
workbook.Close(false, oMissing, oMissing);
Marshal.ReleaseComObject(workbook);
workbook = null;
}
if (excel != null)
{
excel.Quit();
Marshal.ReleaseComObject(excel);
excel = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
public static System.Data.DataTable ImportDataTableFromExcelIMEX(string filename, out string error)
{
string connstring = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + #";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""";
try
{
using (OleDbConnection upocn = new OleDbConnection(connstring))
{
upocn.Open();
System.Data.DataTable dt = null;
dt = upocn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
using (OleDbDataAdapter upoda = new OleDbDataAdapter("select * from [" + dt.Rows[0]["TABLE_NAME"].ToString() + "]", upocn))
{
DataSet upods = new DataSet();
error = string.Empty;
upoda.Fill(upods);
if (!string.IsNullOrEmpty(error))
return null;
return upods.Tables[0];
}
}
}
catch (Exception ex)
{
error = ex.Message;
}
return null;
}
}
I had the same problem. Basically I had to put
finally
{
if (xlCmd != null)
{
xlCmd.Dispose();
xlCmd = null;
}
}
before initializing a new OleDBCommand xlCmd and
finally
{
if (xlCon != null)
xlCon.Dispose();
}
after telling OleDBConnection xlCon to close. Make sure you also initialize your excel connection with a using block such as below:
using (OleDbConnection xlCon = new OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; " +
"Data Source = " + xlFile + ";Mode=ReadWrite;" +
"Extended Properties='Excel 12.0;HDR=YES;'")) //Automatically creates a new excel file (Do not include IMEX=1)
{
These manual cleanups are required if you want to open your file while your application is running and you're done with your export.

Categories