Exporting datagrid into Excel document - c#

I need to export a datgrid to an excel document, but i'm encountering an error when doing so. Below is the code i'm using to export, it opens up the Excel document, and the headers are in place, but where the values in each cell should be i'm seeing System.Data.DataRowView in the excel cell. What i need to do is take the values from hat row and insert them into the Excel workbook.
Any help is appreciated, or tutorial links.
Peter
Microsoft.Office.Interop.Excel.Application excel = null;
Microsoft.Office.Interop.Excel.Workbook wb = null;
object missing = Type.Missing;
Microsoft.Office.Interop.Excel.Worksheet ws = null;
Microsoft.Office.Interop.Excel.Range rng = null;
try
{
excel = new Microsoft.Office.Interop.Excel.Application();
wb = excel.Workbooks.Add();
ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.ActiveSheet;
for (int Idx = 0; Idx < dataGrid1.Columns.Count; Idx++)
{
// Puts Column Header into excel work sheet
ws.Range["A1"].Offset[0, Idx].Value = dataGrid1.Columns[Idx].Header;
}
for (int Idx = 0; Idx < dataGrid1.Items.Count; Idx++)
{
ws.Range["A2"].Offset[Idx].Resize[1, dataGrid1.Columns.Count].Value =
dataGrid1.Items[Idx].ToString();
}
excel.Visible = true;
wb.
}
catch (COMException ex)
{
MessageBox.Show("Error accessing Excel: " + ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.ToString());
}

I found the solution, if anybody ever has the same problem.
To access the the values inside the row here's what you need to:
for (int columnIndex = 0; columnIndex < dataGrid1.Columns.Count; columnIndex++)
{
ws.Range["A2"].Offset[rowIndex, columnIndex].Value =
(dataGrid1.Items[rowIndex] as DataRowView).Row.ItemArray[columnIndex].ToString()
}

With the loop for (int Idx = 0; Idx < dataGrid1.Items.Count; Idx++) you are iterating over the items, i.e. the rows of the DataGrid. Each such item or row apparently is a DataRowView, and hence ToString gives you "System.Data.DataRowView".
You would also have to iterate over each item in a row, i.e. the cell:
for (int rowIndex = 0; rowIndex < dataGrid1.Items.Count; rowIndex++)
{
for (int columnIndex = 0; columnIndex < dataGrid1.Columns.Count; columnIndex++)
{
ws.Range["A2"].Offset[rowIndex, columnIndex].Value =
dataGrid1.Items[rowIndex][columnIndex].ToString();
}
}
Note that i haven't tested this and don't know anything about the Excel API, so i'm not really sure if the ws.Range["A2"].Offset[rowIndex, columnIndex] thing is correct.

Related

get value from data table specific cell and output to textbox

trying to get a value from a data table, and output its contents to a textbox. seems im nearly there but for some reason studio doesnt like dt.rows[][];
ive seen multiple examples online in this format, but i get error CS002, cannot apply indexing with [] to an expression of type 'DataGridViewRow'.
im trying to locate the current row, and i can figure out the column either by putting an index number or by using the name of the column if that works better.
here is datatable_selectionChanged
private void dt_SelectionChanged(object sender, EventArgs e)
{
int row = dt.CurrentCell.RowIndex;
int col = dt.CurrentCell.ColumnIndex;
textBox1.Text = Convert.ToString(row);
textBox2.Text = Convert.ToString(col);
}
here is my mainform_load
private void mainForm_Load(object sender, EventArgs e)
{
string file = #"C:\Users\User\OneDrive - Motion Controls Robotics, Inc\Desktop\test inventory\TIS.xlsm"; //variable for the Excel File Location
DataTable dt = new DataTable(); //container for our excel data
DataRow row;
try
{
//Create Object for Microsoft.Office.Interop.Excel that will be use to read excel file
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(file);
Microsoft.Office.Interop.Excel._Worksheet excelWorksheet = excelWorkbook.Sheets[1];
Microsoft.Office.Interop.Excel.Range excelRange = excelWorksheet.UsedRange;
int rowCount = excelRange.Rows.Count; //get row count of excel data
int colCount = excelRange.Columns.Count;//number of columns to display
//Get the first Column of excel file which is the Column Name
for (int i = 2; i <= rowCount;)
{
for (int j = 1; j <= colCount; j++)
{
dt.Columns.Add(excelRange.Cells[i, j].Value2.ToString());
}
break;
}
//Get Row Data of Excel
int rowCounter; //This variable is used for row index number
for (int i = 3; i <= rowCount; i++) //Loop for available row of excel data
{
row = dt.NewRow(); //assign new row to DataTable
rowCounter = 0;
for (int j = 1; j <= colCount; j++) //Loop for available column of excel data
{
//check if cell is empty
if (excelRange.Cells[i, j] != null && excelRange.Cells[i, j].Value2 != null)
{
row[rowCounter] = excelRange.Cells[i, j].Value2.ToString();
}
else
{
excelRange.Cells[i, j].value2 = "Empty";
//row[i] = "";
}
rowCounter++;
}
dt.Rows.Add(row); //add row to DataTable
}
this.dt.DataSource = dt; //assign DataTable as Datasource for DataGridview
//close and clean excel process
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.ReleaseComObject(excelRange);
Marshal.ReleaseComObject(excelWorksheet);
//quit apps
excelWorkbook.Close();
Marshal.ReleaseComObject(excelWorkbook);
excelApp.Quit();
Marshal.ReleaseComObject(excelApp);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

delete Style in Execl Using C#

I created Excel file using this code:
Sheets worksheets = wb.Sheets;
Worksheet worksheet = (Worksheet)worksheets[4];
int rows = dt.Rows.Count;
int columns = dt.Columns.Count;
var data = new object[rows + 1, columns];
for (var column = 0; column < columns; column++)
{
data[0, column] = dt.Columns[column].ColumnName;
}
for (var row = 0; row < rows; row++)
{
for (var column = 0; column < columns; column++)
{
data[row + 1, column] = dt.Rows[row][column];
}
}
Range beginWrite = (Range)worksheet.Cells[1, 1];
Range endWrite = (Range)worksheet.Cells[rows + 1, columns];
Range sheetData = worksheet.Range[beginWrite, endWrite];
sheetData.Value2 = data;
worksheet.Select();
sheetData.Worksheet.ListObjects.Add(XlListObjectSourceType.xlSrcRange,
sheetData,
Type.Missing,
XlYesNoGuess.xlNo,
Type.Missing);
sheetData.Select();
Excel.ActiveWindow.DisplayGridlines = false;
Excel.Application.Range["2:2"].Select();
Excel.Application.Range["$A$3"].Select();
the problem here it set default format style to excel fileI don't know how to clear all format style in excel sheet
If all you are trying to do is delete all styles, this would work:
using Excelx = Microsoft.Office.Interop.Excel;
Excelx.Workbook wb = excel.ActiveWorkbook;
foreach (Excelx.Style st in wb.Styles)
st.Delete();
Then again, you may only want to clear out custom styles (not the ones that come standard), in which case a small modification would do it:
foreach (Excelx.Style st in wb.Styles)
{
if (!st.BuiltIn)
st.Delete();
}
Styles are stored at the workbook level, so at some point you need to declare your workbook. From there, the Styles collection of the Workbook object has everything you need.

export to excel from c# is not showing first row from database

I am trying to export a database from c# to excel but the first row from the database is not saving in excel.
private void exporttoexcel()
{
Microsoft.Office.Interop.Excel._Application excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = excel.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
try
{
worksheet = workbook.ActiveSheet;
worksheet.Name = "ExportedFromDatGrid";
int cellRowIndex = 1;
int cellColumnIndex = 1;
//Loop through each row and read value from each column.
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
// Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
if (cellRowIndex == 1)
{
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView1.Columns[j].HeaderText;
}
else
{
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
cellColumnIndex++;
}
cellColumnIndex = 1;
cellRowIndex++;
}
}
catch(Exception ex)
{
}
}
here is the code I'm using. could anyone help me ? I am new in coding.
You're not writing out the data but are only writing out column names when the cellColumnIndex is 1, skipping the first row. But after the first row has been processed, the row index will be incremented. Refactor your for-loop to look something like this:
// Add the column names
var index = 0;
foreach(var column in dataGridView1.Columns)
{
worksheet.Cells[0, index] = column.HeaderText;
index++;
}
//Loop through each row and read value from each column.
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
// Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
worksheet.Cells[cellRowIndex, cellColumnIndex] = dataGridView1.Rows[i].Cells[j].Value.ToString();
cellColumnIndex++;
}
cellColumnIndex = 1;
cellRowIndex++;
}
Please have a look at ClosedXML. It simplifies writing your code, and eliminate the need to have Excel installed on the machine where you want to run this.

Export to Excel in datagridView is working only while debugging

I have a datagridview in c# where i am showing records.Now as per my requirement i have to export this into excel.So i have written following method for this..
public static void ExportToExcel(DataGridView dgView)
{
Microsoft.Office.Interop.Excel.Application excelApp = null;
try
{
// instantiating the excel application class
object misValue = System.Reflection.Missing.Value;
excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook currentWorkbook = excelApp.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel.Worksheet currentWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)currentWorkbook.ActiveSheet;
currentWorksheet.Columns.ColumnWidth = 18;
if (dgView.Rows.Count > 0)
{
currentWorksheet.Cells[1, 1] = DateTime.Now.ToString("s");
int i = 1;
foreach (DataGridViewColumn dgviewColumn in dgView.Columns)
{
// Excel work sheet indexing starts with 1
currentWorksheet.Cells[2, i] = dgviewColumn.Name;
++i;
}
Microsoft.Office.Interop.Excel.Range headerColumnRange = currentWorksheet.get_Range("A2", "G2");
headerColumnRange.Font.Bold = true;
headerColumnRange.Font.Color = 0xFF0000;
//headerColumnRange.EntireColumn.AutoFit();
int rowIndex = 0;
for (rowIndex = 0; rowIndex < dgView.Rows.Count; rowIndex++)
{
DataGridViewRow dgRow = dgView.Rows[rowIndex];
for (int cellIndex = 0; cellIndex < dgRow.Cells.Count; cellIndex++)
{
currentWorksheet.Cells[rowIndex + 3, cellIndex + 1] = dgRow.Cells[cellIndex].Value;
}
}
Microsoft.Office.Interop.Excel.Range fullTextRange = currentWorksheet.get_Range("A1", "G" + (rowIndex + 1).ToString());
fullTextRange.WrapText = true;
fullTextRange.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
}
else
{
string timeStamp = DateTime.Now.ToString("s");
timeStamp = timeStamp.Replace(':', '-');
timeStamp = timeStamp.Replace("T", "__");
currentWorksheet.Cells[1, 1] = timeStamp;
currentWorksheet.Cells[1, 2] = "No error occured";
}
using (SaveFileDialog exportSaveFileDialog = new SaveFileDialog())
{
exportSaveFileDialog.Title = "Select Excel File";
exportSaveFileDialog.Filter = "Microsoft Office Excel Workbook(*.xlsx)|*.xlsx";
if (DialogResult.OK == exportSaveFileDialog.ShowDialog())
{
string fullFileName = exportSaveFileDialog.FileName;
currentWorkbook.SaveAs(fullFileName, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook, System.Reflection.Missing.Value, misValue, false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Microsoft.Office.Interop.Excel.XlSaveConflictResolution.xlUserResolution, true, misValue, misValue, misValue);
currentWorkbook.Saved = true;
MessageBox.Show("Exported successfully", "Exported to Excel", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (excelApp != null)
{
excelApp.Quit();
}
}
}
Now one strange thing is happening when i am trying to get the excel report using my application i am not able to get that whereas if i am trying to get it by debugging my code i am getting but it too is taking hell lot of time.
On debugging the code This line ..
Microsoft.Office.Interop.Excel.Range fullTextRange = currentWorksheet.get_Range("A1", "G" + (rowIndex + 1).ToString());
is taking considerable lot of time ..
Please help me ..
Excel Interop is never going to be fast as you're remote controlling an instance of the Excel application. You might want to create a CSV file and then using Excel Interop to convert this to a .xls or .xlsx file.
Here's example on how to convert csv to xls
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application excel = new Excel.Application();
Excel.Workbook workBook = excel.Workbooks.Add();
var inputFile = new FileInfo("Book1.csv");
var sheet = Spreadsheet.Read(inputFile);
workBook.ActiveSheet = sheet; // unsure about this part, but basically you need to transfer data.
workBook.SaveAs(#"C:\Temp\fromCsv.xls");
workBook.Close();
I think the below section slows down your code a lot
int rowIndex = 0;
for (rowIndex = 0; rowIndex < dgView.Rows.Count; rowIndex++)
{
DataGridViewRow dgRow = dgView.Rows[rowIndex];
for (int cellIndex = 0; cellIndex < dgRow.Cells.Count; cellIndex++)
{
currentWorksheet.Cells[rowIndex + 3, cellIndex + 1] = dgRow.Cells[cellIndex].Value;
}
}
I think it would be much faster to export DataGridView to an Excel spreadsheet by not looping through calling Cells each time because each call to Cells is quite expensive when using COM.
I suggest your convert your DataGridViewColumn to a 2D array and then export the entire DataGridView in one go like this:
object[,] toExport = new object[dgView.Rows.Count, dgView.Columns.Count];
for (int row = 0; row < dgView.Rows.Count; row++)
{
DataGridViewRow dgRow = dgView.Rows[row];
for (int column= 0; column < dgRow.Cells.Count; column++)
{
toExport[row, column] = dgRow.Cells[row].Value;
}
}
// export in one go instead of looping and accessing Cells each time
// use Excel.Application.Transpose(array) if needed
ws.get_Range("A3").set_Value(Type.Missing, toExport);
Additionally you may add an xlApp.ScreenUpdating = false; at the start and then switch it back to true when you're done modifying sheet.

Reading Values from Table

I populate values from my gridview in my table using this Code:
Table table = new Table();
// get gridlines from gridview
table.GridLines = GridView1.GridLines;
if (GridView1.HeaderRow != null)
{
table.Rows.Add(GridView1.HeaderRow);
}
foreach (GridViewRow row in GridView1.Rows)
{
table.Rows.Add(row);
}
if (GridView1.FooterRow != null)
{
table.Rows.Add(GridView1.FooterRow);
}
What I need is to read every data from the table which contains the values of the gridview into an Excel worksheet cell.
How can I achieve this?
PS: This is my worksheet obj in code-behind in C#.
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Or Is there any other way to add the data from GridView to something else than, using table, which can be easily read?
public void ExportToExcel()
{
var Excel = new Microsoft.Office.Interop.Excel.Application();
XlReferenceStyle RefStyle = Excel.ReferenceStyle;
Excel.Visible = true;
Workbook wb = null;
string path = "yourpath";
try
{
wb = Excel.Workbooks.Add(path);
}
catch (System.Exception ex)
{
throw new Exception(ex.Message);
}
Worksheet ws = wb.Worksheets.get_Item(1) as Worksheet ;
for (int j = 0; j < GridView1.Columns.Count; ++j)
{
(ws.Cells[1, j + 1] as Range).Value2 = GridView1.Columns[j].HeaderText;
for (int i = 0; i < GridView1.Rows.Count; ++i)
{
object Val = GridView1.Rows[i].Cells[j].Value;
if (Val != null)
(ws.Cells[i + 2, j + 1] as Range).Value2 = Val.ToString();
}
}
Excel.ReferenceStyle = RefStyle;
Marshal.ReleaseComObject((object)Excel);
GC.GetTotalMemory(true);
}
Yes, there is a number of ways depending of what you gonna do. In your case the easiest one is CSV file (that would be work with Excel excellent). And there is no need to do somethins with DataGridView, if you have a DataSource

Categories