Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
object misValue = System.Reflection.Missing.Value;
// creating new WorkBook within Excel application
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Open(System.IO.Directory.GetCurrentDirectory() + #"\Report.xlsx");
// Get current worksheet and clear it
Microsoft.Office.Interop.Excel._Worksheet worksheet1 = workbook.Worksheets[1];
Microsoft.Office.Interop.Excel._Worksheet worksheet2 = workbook.Worksheets[2];
app.DisplayAlerts = false;
worksheet1.Delete();
worksheet2.Delete();
app.DisplayAlerts = true;
//app.Worksheets[1].Delete();
//app.Worksheets[2].Delete();
workbook.Save();
Microsoft.Office.Interop.Excel._Worksheet worksheet = (Excel.Worksheet)app.Worksheets.Add(); ;
// storing header part in Excel
for (int i = 1; i < mydatatable.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = mydatatable.Columns[i - 1].ColumnName.ToString();
}
// storing Each row and column value to excel sheet
for (int i = 0; i < mydatatable.Rows.Count; i++)
{
for (int j = 0; j < mydatatable.Columns.Count; j++)
{
worksheet.Cells[i + 2, j + 1] = mydatatable.Rows[i][j].ToString();
}
worksheet.Columns.AutoFit();
}
Excel.Range chartRange;
Excel.ChartObjects xlCharts = (Excel.ChartObjects)worksheet.ChartObjects(Type.Missing);
Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(10, 80, 300, 250);
Excel.Chart chartPage = myChart.Chart;
chartRange = worksheet.get_Range("C1", "E20");
chartPage.SetSourceData(chartRange);
chartPage.ChartType = Excel.XlChartType.xlColumnClustered;
chartPage.Location(Excel.XlChartLocation.xlLocationAsNewSheet,"Chart");
workbook.Save();
workbook.Close(misValue);
Marshal.ReleaseComObject(worksheet);
app.Quit();
It creates the new worksheet perfectly, but doesn't delete the old one first. I even have two codes to delete it and it doesn't. I have more than one sheet in the app.
EDIT: I just noticed that the first time I run the code it deletes the given sheets, but if I run it a second time (etc) it won't delete them anymore and gives me error, because aparently EXCEL proccess is still open in the background for some reason, altough I use "app.Quit()". Please help!
One of the problems could be that you have one worksheet when you're trying to delete it. Make sure that you're not deleting last worksheet or it won't work. So, create new one, then delete old one; not the other way around.
EDIT:
Try this code:
app.DisplayAlerts = false;
worksheetdel.Delete();
app.DisplayAlerts = true;
Source: https://stackoverflow.com/a/678795/2006048
Related
I am unable to export data from multiple rows in DTG to specific columns in excel. I have tried multiple methods from forums. So far, the results are excel opened but no data are exported (empty cells) or only the last row of DTG are copied to the specific columns in excel.
I want this excel sheet to compile the DTG data. Hence, example user open form 1st time, enter DTG data, saves to excel and closes form. User then open form 2nd time and enter another DTG data, the 2nd DTG data will go into the same excel columns but on the next empty row (underneath the row of the 1st DTG data).
Most codes that I've tried comes from this link [Programmatically getting the last filled excel row using C# ]. I did not put the column part as I only want last row. Do note that the skeleton of all the codes are the same but the way lastUsedRow was initialized are different.
Codes below gives empty cells
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
try
{
oXL = new Microsoft.Office.Interop.Excel.Application();
oWB = oXL.Workbooks.Open("C:\\Users\\User\\Test.xlsx");
oSheet = oXL.Worksheets["Vehicles"];
Excel.Range last = oSheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range range = sheet.get_Range("A1", last);
int lastUsedRow = last.Row;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
for (int j = 1; j < dataGridView1.Columns.Count; j++)
{
oSheet.Cells[lastUsedRow, j+1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
}
OR
int lasUsedRow = oSheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing).Row;
Codes below shows only last row of DTG
int lastUsedRow = oSheet.Cells.Find("*",System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSearchOrder.xlByRows,Excel.XlSearchDirection.xlPrevious, false,System.Reflection.Missing.Value,System.Reflection.Missing.Value).Row;
OR
int lastUsedRow = oSheet.Range["B" + oSheet.Rows.Count].End[Excel.XlDirection.xlUp].Row+1;
Hope to get some help. Thank you so much!
As per Yoshi's comment, below is the updated code where it allows multiple datagridview rows to be added and compiled into excel.
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
try
{
//Start Excel and get Application object.
oXL = new Microsoft.Office.Interop.Excel.Application();
//Get a new workbook.
oWB = oXL.Workbooks.Open("C:\\Users\\User\\Test.xlsx");
//Specify different sheet names
oSheet = oXL.Worksheets["Vehicles"];
//Define last row
int _lastRow = oSheet.Range["B" + oSheet.Rows.Count].End[Excel.XlDirection.xlUp].Row+1;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
for (int j = 1; j < dataGridView1.Columns.Count; j++)
{
oSheet.Cells[_lastRow, j+1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
_lastRow++;
}
//Make sure Excel open and give the user control of Microsoft Excel's lifetime.
oXL.Visible = true;
oXL.UserControl = true;
//Autosave excel file
oWB.Save();
Marshal.ReleaseComObject(oXL);
}
catch (Exception theException)
{
String errorMessage;
errorMessage = "Error: ";
errorMessage = String.Concat(errorMessage, theException.Message);
errorMessage = String.Concat(errorMessage, " Line: ");
errorMessage = String.Concat(errorMessage, theException.Source);
MessageBox.Show(errorMessage, "Error");
}
}
From a console application using C# I am trying to open a new Excel workbook and add data to it. I can open a new workbook fine, but I am running into issues adding data to the workbook because my range object is null, and I can't seem to hook into the excel workbook that was just opened. I tried a variation of ActiveWorkbook, Sheets[1] and a couple of others and I can't seem to figure it out
using Microsoft.Office.Interop.Excel;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Application xl = null;
_Workbook wb = null;
// Option 1
xl = new Application();
xl.Visible = true;
wb = (_Workbook)(xl.Workbooks.Add(XlWBATemplate.xlWBATWorksheet));
Worksheet sheet = xl.ActiveWorkbook.ActiveSheet;
Range cell = sheet.Cells[1, 1];
//ERROR on cell.Value("Test");
cell.Value("Test");
}
}
}
This code may be help you.
using (SaveFileDialog sfd = new SaveFileDialog() { Filter = "Excel Workbook|*.xls" })
{
if (sfd.ShowDialog() == DialogResult.OK)
{
// creating Excel Application
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
// creating new WorkBook within Excel application
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
// creating new Excelsheet in workbook
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
// see the excel sheet behind the program
app.Visible = true;
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet = workbook.Sheets["Sheet1"];
worksheet = workbook.ActiveSheet;
// changing the name of active sheet
worksheet.Name = "Exported from gridview";
// storing header part in Excel
for (int i = 1; i < DGView.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = DGView.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < DGView.Rows.Count - 1; i++)
{
for (int j = 0; j < DGView.Columns.Count; j++)
{
worksheet.Cells[i + 2, j + 1] = DGView.Rows[i].Cells[j].Value.ToString();
}
}
// save the application
workbook.SaveAs(sfd.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);
// Exit from the application
app.Quit();
}
}
I used this code in my work for saving datagridview as excel sheet and it has been worked well.
I have a windows form application. In this application, I want to export some of my data in my form to excel. I have figured out how to create a Excel file and also stored some value to it. However one thing I am not sure is if there a way to add items to excel rows using a for loop (to figure out the rows and column according to how many data you have)? because it is pretty inefficient if you want to add a list of items let say 1000 items one by one.
For example: To add one item to specific cell one at a time, we can do something like this:
xlSomeDetail.Cells[1,1] = "Teacher Id";
xlSomeDetail.Cells[1,2] = "first name";
xlSomeDetail.Cells[1,3] = "Last Name";
xlSomeDetail.Cells[1,4] = "Email";
xlSomeDetail.Cells[1,5] = "Salary";
Now is there something like this if I want to do it without adding rows one by one?
//declare aRange variable
Excel.Range aRange;
aRange = (Excel.Range)xlSomeDetail.get_Range("A1", "M1");
//something like this? I am not sure
for (int i = 1; i< aRange.Rows; i++{
xlSomeDetail.Cell[1, i+ 1] = //somestring?
}
Are there any better method of doing this?
try to create multiple Xl objects
befour this split your data as per your requirment in to multiple datatables
[DllImport("user32")]
private static extern bool GetWindowThreadProcessId(int hWnd, out int id);
for(i=0;i<2;i++)
{
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.SheetsInNewWorkbook = 1;
oXL.Visible = false;
//Get a new workbook.
oWB = (Excel.Workbook)(oXL.Workbooks.Add(Type.Missing));
oSheet = (Excel.Worksheet)oWB.Worksheets.get_Item(1);+
oSheet.Name = "Summary Report";//Change the name as per your requirment
ExcelRowsCount = 2;
for (int RowsCount = 0; RowsCount < dt.Rows.Count; RowsCount++)
{
for (int ColumnsCount = 0; ColumnsCount < dt.Columns.Count; ColumnsCount++)
{
if (RowsCount.Equals(0) && ColumnsCount.Equals(0))
oSheet.Cells[2, 1] = dt.Rows[RowsCount][ColumnsCount].ToString();
else
oSheet.Cells[ExcelRowsCount + RowsCount, ColumnsCount + 1] = dt.Rows[RowsCount][ColumnsCount].ToString();
}
oXL.Visible = false;
oXL.UserControl = false;
oXL.DisplayAlerts = false;
oXL.ActiveWorkbook.SaveAs(FileName, Excel.XlFileFormat.xlWorkbookNormal, "", "", false, false, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
oWB.Close(false, Type.Missing, Type.Missing);
oXL.Workbooks.Close();
oXL.Quit();
int ExcelID;
GetWindowThreadProcessId(oXL.Hwnd, out ExcelID);
Process XLProcess = Process.GetProcessById(ExcelID);
Marshal.ReleaseComObject(oSheet);
Marshal.ReleaseComObject(oWB);
Marshal.ReleaseComObject(oXL);
XLProcess.Kill();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
I am trying to export 2 datagridviews to excel but it is missing the last line of data for both of the sets of data grid views, I have checked the code and I cant see what I have done wrong? Also it is creating a temporary file when exporting and then locking the file and not exiting gracefully and only a reboot allows you to delete the file? Any help would be great code is below. For example if i save as test.xlsx I get 2 files ~$test.xlsx and test.xlsx and both both files are locked.
private void exprtbtn_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
try
{
// creating new Excelsheet in workbook
Microsoft.Office.Interop.Excel._Worksheet worksheet1 = null;
Microsoft.Office.Interop.Excel._Worksheet worksheet2 = null;
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet1 = workbook.Sheets["Sheet1"];
worksheet1 = workbook.ActiveSheet;
// changing the name of active sheet
worksheet1.Name = "Switch Totals";
// storing header part in Excel
for (int i = 1; i < switchtotalgrd.Columns.Count + 1; i++)
{
worksheet1.Cells[1, i] = switchtotalgrd.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < switchtotalgrd.Rows.Count - 1; i++)
{
for (int j = 0; j < switchtotalgrd.Columns.Count; j++)
{
worksheet1.Cells[i + 2, j + 1] = switchtotalgrd.Rows[i].Cells[j].Value.ToString();
}
}
// Adding second worksheet
int count = workbook.Worksheets.Count;
Excel.Worksheet addedSheet = workbook.Worksheets.Add(Type.Missing,
workbook.Worksheets[count], Type.Missing, Type.Missing);
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet2 = workbook.Sheets["Sheet2"];
worksheet2 = workbook.ActiveSheet;
// changing the name of active sheet
worksheet2.Name = "Itemised Extn";
// storing header part in Excel
for (int i = 1; i < fullresult.Columns.Count + 1; i++)
{
worksheet2.Cells[1, i] = fullresult.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < fullresult.Rows.Count - 1; i++)
{
for (int j = 0; j < fullresult.Columns.Count; j++)
{
if (fullresult.Rows[i].Cells[j].Value == null)
{
fullresult.Rows[i].Cells[j].Value = "NA";
}
worksheet2.Cells[i + 2, j + 1] = fullresult.Rows[i].Cells[j].Value.ToString();
}
}
// save the application
string fileName = String.Empty;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel files |*.xls|All files (*.*)|*.*";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
fileName = saveFileDialog1.FileName;
workbook.SaveAs(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, Type.Missing);
}
else
return;
}
//Catch all errors.
catch (System.Exception)
{
}
finally
{
workbook = null;
app = null;
}
}
You probably might want to double-check your outer for loop again, e.g. for (int i = 0; i < fullresult.Rows.Count - 1; i++), shouldn't it be using less than and equal perhaps?
Since you are using Excel com interop, you will need to call this method to be able to release the resource after you are done with it, Marshal.ReleaseComObject.
A good practice is to use try{...}catch{...}finally{...}, and release com object in the finally block.
I have simple code for generating Excel which loops and produces excel sheet.
Excel.Application XlApp = null;
Excel.Workbook workbook = null;
Excel.Worksheet Ws = null;
XlApp = new Excel.Application();
XlApp.Visible = true;
workbook = XlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Ws = (Excel.Worksheet)workbook.Worksheets[1];
workbook.Worksheets.Add(Missing.Value,Missing.Value,
6, Missing.Value);
for (int j = 0; j < 7; j++)
{
Ws = (Excel.Worksheet)workbook.Worksheets[j];
Ws.Activate();
Ws.Name = SheetName.ToString();//Sheetname has a Name
}
Now the problem is When we run this code everything works fine. But sometimes what happens is, at the client side one of the sheet name is not generated it skips. So our solution to them is to try generating the sheet again and then it works fine,
So my question is why does the code skip the sheetName (sometimes), although there is no problem in the code. Does it have to do anything with clients other running processes?
Try this:
Excel.Application XlApp = null;
Excel.Workbook workbook = null;
Excel.Worksheet Ws = null;
XlApp = new Excel.Application();
XlApp.Visible = true;
workbook = XlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
// here you get the first ws, index 1
Ws = (Excel.Worksheet)workbook.Worksheets[1];
workbook.Worksheets.Add(Missing.Value, Missing.Value,
6, Missing.Value);
var SheetName = "sheet_";
// here you should start from 1 (not from 0) and include 7 in the loop count
for (int j = 1; j <= 7; j++)
{
// make sure that the ws name is unique
SheetName=String.Format("sheet_{0}",j);
Ws = (Excel.Worksheet)workbook.Worksheets[j];
Ws.Activate();
Ws.Name = SheetName;// this is already a string
}
XlApp.Quit();