Reading data from excel 2010 using Microsoft.Office.Interop.Excel - c#

I am not able to read data in Excel. Here is the code I am using:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"Book1.xlsx", 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
Excel._Worksheet xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
MessageBox.Show(xlWorksheet.Cells[i,j].ToString());
}
}
I get a message box that says something about System.__ComObject instead of a value.
How can I fix this?

I found the solution for above, here is the code:
string temp = (string)(xlRange.Cells[i, j] as Excel.Range).Value2;
MessageBox.Show(temp);

Haven´t tested it, but I think it should read
MessageBox.Show(xlRange.Cells[i,j].ToString());
or alternatively
MessageBox.Show(xlRange.Cells[i,j].Value.ToString());

Try this:
MessageBox.Show(xlRange.Cells[i][j].Value);

use the following function to get data as DATATABLE object for N'th sheet :
public DataTable GetWorkSheet(int workSheetID)
{
string pathOfExcelFile = fileFullName;
DataTable dt = new DataTable();
try
{
excel.Application excelApp = new excel.Application();
excelApp.DisplayAlerts = false; //Don't want Excel to display error messageboxes
excel.Workbook workbook = excelApp.Workbooks.Open(pathOfExcelFile, 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); //This opens the file
excel.Worksheet sheet = (excel.Worksheet)workbook.Sheets.get_Item(workSheetID); //Get the first sheet in the file
int lastRow = sheet.Cells.SpecialCells(excel.XlCellType.xlCellTypeLastCell, Type.Missing).Row;
int lastColumn = sheet.Cells.SpecialCells(excel.XlCellType.xlCellTypeLastCell, Type.Missing).Column;
excel.Range oRange = sheet.get_Range(sheet.Cells[1, 1], sheet.Cells[lastRow, lastColumn]);//("A1",lastColumnIndex + lastRow.ToString());
oRange.EntireColumn.AutoFit();
for (int i = 0; i < oRange.Columns.Count; i++)
{
dt.Columns.Add("a" + i.ToString());
}
object[,] cellValues = (object[,])oRange.Value2;
object[] values = new object[lastColumn];
for (int i = 1; i <= lastRow; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
values[j] = cellValues[i, j + 1];
}
dt.Rows.Add(values);
}
workbook.Close(false, Type.Missing, Type.Missing);
excelApp.Quit();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
return dt;
}

Try this code:
MessageBox.Show(((Excel.Range)xlRange.Cells[i,j]).Value2.ToString());
This code works sucessfully for me.

Related

C# Datatable linq condiction check

I have created the function shown below. Everything is working fine, the challenge now, is that I have some scenarios where it would be ideal to have the constructor 'RadGridView grid' as a Datatable. I'm looking for a constructor that can take the input type of 'RadGridView' or type of 'Datatable' - a kind of "universal" constructor, if that is possiple?
public static void Export(RadGridView grid, string sheetName)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel file |*.xlsx";
saveFileDialog1.Title = "Save";
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
app.Visible = false;
worksheet = workbook.Sheets["Sheet1"];
worksheet = workbook.ActiveSheet;
worksheet.Name = sheetName;
Microsoft.Office.Interop.Excel.Range aRange = worksheet.UsedRange;
workbook.Worksheets[1].Cells.NumberFormat = "#";
for (int i = 1; i < grid.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = grid.Columns[i - 1].HeaderText;
}
for (int i = 0; i < grid.Rows.Count; i++)
{
for (int j = 0; j < grid.Columns.Count; j++)
{
worksheet.Cells[i + 2, j + 1] = grid.Rows[i].Cells[j].Value.ToString();
}
}
aRange.Value = aRange.Value;
aRange.Cells.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
worksheet.Columns.AutoFit();
workbook.SaveAs(saveFileDialog1.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
app.Quit();
}
}
Thanks in advance!
I solved this by using the 'dynamic' keyword.

C# Excel only allow edit for specific row

I'm generating an excel file in C# and excel file is format is as follows.
And Columns From C1 will be dynamic since there can be several dates.
And what I need to do is only allow editing for rows with Ctype
YYY
Is there any way to identify rows with Ctype = YYY
The code I use to generate excel is as follows
public string ExcelGenerator()
{
DataTable dt = GetDataTable();
var fileName = "ExcelFile";
var excelApp = new Application();
var workbooks = excelApp.Workbooks;
var excelWorkBook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);
var sheets = excelWorkBook.Sheets;
var excelWorkSheet = sheets[1];
excelWorkSheet.Name = "ExcelFile";
int iCol = 1;
// Add column headings...
foreach (DataColumn c in dt.Columns)
{
excelWorkSheet.Cells[1, iCol] = c.ColumnName; ;
((Range)excelWorkSheet.Cells[1, iCol]).Interior.Color = ColorTranslator.ToOle(Color.DarkGray);
iCol++;
}
// for each row of data...
for (int j = 0; j < dt.Rows.Count; j++)
{
for (int k = 0; k < dt.Columns.Count; k++)
{
excelWorkSheet.Cells[j + 2, k + 1] = dt.Rows[j].ItemArray[k].ToString();
}
}
string fullpath = Path.Combine(excelPath, fileName);
if (File.Exists(fullpath))
{
try
{
File.Delete(fullpath);
}
catch (IOException e)
{
Console.Write(e.Message);
}
}
excelApp.DisplayAlerts = false;
excelWorkBook.SaveAs(fullpath, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, true, false, XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlLocalSessionChanges, Type.Missing, Type.Missing);
excelWorkBook.Close(false, Type.Missing, Type.Missing);
excelApp.Quit();
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelWorkSheet);
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(excelWorkBook);
Marshal.ReleaseComObject(excelApp);
excelWorkSheet = null;
excelWorkBook = null;
excelApp = null;
workbooks = null;
GC.WaitForPendingFinalizers();
GC.Collect();
return fileName;
}
Excel.Office.Interop don't allow range unprotection by programmatically.
For more information, you may visit this website.
https://msdn.microsoft.com/en-us/library/dkcs53f3.aspx
But if you use EPPlus library, you can do like Excel users.
if you allow selective editable column, excel requires sheet protection = true and some unprotected range.
(using EPPlus)
excelWorkSheet.Protection.IsProtected = true;
excelWorkSheet.ProtectedRanges.Add("editable", new ExcelAddress("B"));

Modify Interop Excel for Opening Existing File

I'm using Excel Interop for C# to export a datagridview to Excel and print it. I'm using this code:
try
{
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
excel.Application.Workbooks.Add(true);
int ColumnIndex = 0;
int rowIndex = -1;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
rowIndex++;
ColumnIndex = 0;
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
ColumnIndex++;
excel.Cells[rowIndex + 1, ColumnIndex] = row.Cells[col.Name].Value;
}
}
excel.Visible = true;
excel.DisplayAlerts = false;
Worksheet worksheet = (Worksheet)excel.ActiveSheet;
worksheet.Activate();
worksheet.Cells.Style.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[1, 7]].Merge();
worksheet.Range[worksheet.Cells[2, 1], worksheet.Cells[2, 7]].Merge();
worksheet.Range[worksheet.Cells[3, 1], worksheet.Cells[3, 7]].Merge();
worksheet.Range[worksheet.Cells[4, 1], worksheet.Cells[4, 4]].Merge();
worksheet.Cells[1, 1].Font.Bold = true;
worksheet.Range["A1"].Cells.Font.Size = 15;
worksheet.Range["A4"].Cells.Font.Size = 15;
worksheet.Range["B7"].Cells.Font.Size = 15;
worksheet.Range["B8"].Cells.Font.Size = 15;
worksheet.Range["B9"].Cells.Font.Size = 15;
worksheet.Range["A11"].Cells.Font.Size = 15;
worksheet.Range["B13"].Cells.Font.Size = 15;
worksheet.PrintOut(Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
GC.Collect();
GC.WaitForPendingFinalizers();
excel.Quit();
}
catch (Exception ex)
{
MessageBox.Show("Error de exportación.");
}
It works fine, but I need to open an existing file to do this same thing to avoid reconfiguration of the printing margins. I checked other similar questions and tried to apply the "workBook = oXL.Workbooks.Open("path", ...);" but it can make it work. Any thoughts?
To open a file use the open method.
Microsoft.Office.Interop.Excel.Workbooks wkbks = null;
Microsoft.Office.Interop.Excel.Workbook wkbk = null;
wkbks = excel.Workbooks;
wkbk = wkbks.Open(xlsFileName);
At the end of your method you should do a cleanup on all your interop variables:
if (wkbk != null)
{
try
{
wkbk.Close(false);
}
catch
{
}
Marshal.FinalReleaseComObject(wkbk);
wkbk = null;
}

Error while exporting datatable to Excel

I am using below code to export excel using Microsoft.Office.Interop.Excel. [Ms office 2003].
I need to export around 150000 rows can have maximum 300 columns.
but getting error on Get_Range. [ Working fine for 50000 rows and 40 columns]
public static void ExportToExcel(DataTable dt, string outputPath)
{
try
{
// Create the Excel Application object
ApplicationClass excelApp = new ApplicationClass();
// Create a new Excel Workbook
Workbook excelWorkbook = excelApp.Workbooks.Add(Type.Missing);
int sheetIndex = 0;
// Copy each DataTable
// Copy the DataTable to an object array
object[,] rawData = new object[dt.Rows.Count + 1, dt.Columns.Count];
// Copy the column names to the first row of the object array
for (int col = 0; col < dt.Columns.Count; col++)
{
rawData[0, col] = dt.Columns[col].ColumnName;
}
// Copy the values to the object array
for (int col = 0; col < dt.Columns.Count; col++)
{
for (int row = 0; row < dt.Rows.Count; row++)
{
rawData[row + 1, col] = dt.Rows[row].ItemArray[col];
}
}
// Calculate the final column letter
string finalColLetter = string.Empty;
string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int colCharsetLen = colCharset.Length;
if (dt.Columns.Count > colCharsetLen)
{
finalColLetter = colCharset.Substring(
(dt.Columns.Count - 1) / colCharsetLen - 1, 1);
}
finalColLetter += colCharset.Substring(
(dt.Columns.Count - 1) % colCharsetLen, 1);
// Create a new Sheet
Worksheet excelSheet = (Worksheet)excelWorkbook.Sheets.Add(
excelWorkbook.Sheets.get_Item(++sheetIndex),
Type.Missing, 1, XlSheetType.xlWorksheet);
excelSheet.Name = "data";
// Fast data export to Excel
string excelRange = string.Format("A1:{0}{1}",
finalColLetter, dt.Rows.Count + 1);
//excelSheet.get_Range(
excelSheet.get_Range(excelRange, Type.Missing).Value2 = rawData;
// Mark the first row as BOLD
((Range)excelSheet.Rows[1, Type.Missing]).Font.Bold = true;
// Save and Close the Workbook
excelWorkbook.SaveAs("C:\\Dashsrv\\data.Xls", XlFileFormat.xlWorkbookNormal, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlExclusive,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
excelWorkbook.Close(true, Type.Missing, Type.Missing);
excelWorkbook = null;
// Release the Application object
excelApp.Quit();
excelApp = null;
// Collect the unreferenced objects
GC.Collect();
GC.WaitForPendingFinalizers();
MessageBox.Show("File created at");
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Getting error on below line of code
[{"Exception from HRESULT: 0x800A03EC"}]
excelSheet.get_Range(excelRange, Type.Missing).Value2 = rawData;
IS Get_Range() has some limitation for rows/Columns?
As I know for MS Office 2003 column's limit is 256, not sure about rows limt.
Thanks
Excel 2003 can have a maximum of 65536 rows in a single worksheet (specification)
Excel 2007 and newer can have 1048576 rows (specification: Excel 2007, Excel 2010 and Excel 2013)
Excel 2003 row limit is 65,536 - http://support.microsoft.com/kb/120596

CSV export with interop

I'm using this code to generate an Excel file. It should be simple to change the export to CSV file, just by modifying a parameter in the saveAs call, but it doesn't work. Any ideea why ?
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.Visible = false;
if (xlApp == null)
{
MessageBox.Show("EXCEL could not be started. Check that your office installation and project references are correct.");
return false;
}
Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
try
{
if (details != false)
{
//Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
wb.Worksheets.Add();
Worksheet detailsWs = (Worksheet)wb.Worksheets[2];
for (int i = 0; i < dt.Columns.Count; i++)
{
detailsWs.Cells[1, i + 1] = dt.Columns[i].Caption;
}
}
Worksheet ws = (Worksheet)wb.Worksheets[1];
if (ws == null)
{
MessageBox.Show("Worksheet could not be created. Check that your office installation and project references are correct.");
}
for (int i = 0; i < dt.Columns.Count; i++)
{
ws.Cells[1, i + 1] = dt.Columns[i].Caption;
}
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
ws.Cells[i + 2, j + 1] = dt.Rows[i].ItemArray[j];
}
worker.ReportProgress((i * 100) / dt.Rows.Count);
}
wb.SaveAs(filename, XlFileFormat.xlCSV, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlShared, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wb.Close(true, filename);
return true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
// Cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (wb != null)
{
wb.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(wb);
}
if (xlApp != null)
{
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
}
}
i used the old way. lines of strings, with commas
XlSaveAsAccessMode.xlShared is the reason. i don't know why but i get that error too.
I try changing XlSaveAsAccessMode.xlNoChange and XlSaveAsAccessMode.xlExclusive,
it worked!

Categories

Resources