So, after much researching and using code below in a Class the items I'm passing (a DataTable) open up in Excel. I have around 5 sheets that need to open in the same book. The code below is for the first 2. The problem is they are all opening in NEW WorkBooks -- I need them all to open in the SAME WorkBook. They are opening on the correct sheet in each new Workbook though. I thought a simple "if" statement would work, however, it is not--
Any input on how to get them consolidated into one WorkBook would be greatly appreciated and thanks in advance!
Microsoft.Office.Interop.Excel.Application oExcel = new
Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks oBooks;
Microsoft.Office.Interop.Excel.Sheets oSheets;
Microsoft.Office.Interop.Excel.Workbook oBook;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
oExcel.Visible = true;
oExcel.DisplayAlerts = false;
oExcel.Application.SheetsInNewWorkbook = 5;
oBooks = oExcel.Workbooks;
oBook = (Microsoft.Office.Interop.Excel.Workbook)(oExcel.Workbooks.Add(Type.Missing));
oSheets = oBook.Worksheets;
if (sheetName == "Combined")
{
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oSheets.get_Item(1);
oSheet.Name = sheetName;
object[,] arr = new object[dt.Rows.Count, dt.Columns.Count];
for (int r = 0; r < dt.Rows.Count; r++)
{
DataRow dr = dt.Rows[r];
for (int c = 0; c < dt.Columns.Count; c++)
{
arr[r, c] = dr[c];
}
}
Microsoft.Office.Interop.Excel.Range c1 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1, 1];
Microsoft.Office.Interop.Excel.Range c2 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1 + dt.Rows.Count - 1, dt.Columns.Count];
Microsoft.Office.Interop.Excel.Range range = oSheet.get_Range(c1, c2);
range.Value2 = arr;
}
else if (sheetName == "Auto")
{
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oSheets.get_Item(2);
oSheet.Name = sheetName;
object[,] arr = new object[dt.Rows.Count, dt.Columns.Count];
for (int r = 0; r < dt.Rows.Count; r++)
{
DataRow dr = dt.Rows[r];
for (int c = 0; c < dt.Columns.Count; c++)
{
arr[r, c] = dr[c];
}
}
Microsoft.Office.Interop.Excel.Range c1 =
(Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1, 1];
Microsoft.Office.Interop.Excel.Range c2 =
(Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1 + dt.Rows.Count - 1,
dt.Columns.Count];
Microsoft.Office.Interop.Excel.Range range = oSheet.get_Range(c1, c2);
range.Value2 = arr;
}
Well your code is a bit too long to understand without comments, but if you wanna add a new sheet inside your current workbook, there is the myWorkbook.Sheets.Add() method (where myWorkbook is a ref to your current workbook).
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.sheets.add(v=office.14).aspx
Related
I have the following code and I am trying to copy certain Range values from one Excel file to another.
I have managed to select the range from the first excel, but it does not "paste" it where I've selected the range to.
In this example, it copies it to the first cells in the second excel.
Could anyone help please?
Thank you!
Microsoft.Office.Interop.Excel.Application application = new Microsoft.Office.Interop.Excel.Application();
Workbook workbook = application.Workbooks.Open(#"Excel.xlsx", 1);
Worksheet xlWorksheet = (Worksheet)workbook.Sheets[9];
Workbook workbook1 = application.Workbooks.Open(#"Excel2.xlsx", 1);
Worksheet xlWorksheet1 = (Worksheet)workbook1.Sheets[1];
Range range1 = xlWorksheet.get_Range("C1", "C5");
object[,] valueArray = (object[,])range1.get_Value(XlRangeValueDataType.xlRangeValueDefault);
Range range2 = xlWorksheet1.get_Range("F1", "F5");
object[,] valueArray2 = (object[,])range2.get_Value(XlRangeValueDataType.xlRangeValueDefault);
for (int i = 2; i <= valueArray.GetLength(0); i++)
{
for (int j = 1; j <= valueArray.GetLength(1); j++)
{
for (int k = 1; k <= valueArray2.GetLength(0); k++)
{
for (int l = 1; l <= valueArray2.GetLength(1); l++)
{
valueArray2[i,j] = valueArray[i, j].ToString();
}
}
}
}
workbook1.Save();
workbook.Close();
workbook1.Close();
application.Quit();
Solution
Microsoft.Office.Interop.Excel.Application application = new
Microsoft.Office.Interop.Excel.Application();
Workbook workbook = application.Workbooks.Open(#"D:\Excel.xlsx", 1);
Worksheet xlWorksheet = (Worksheet)workbook.Sheets[1];
Workbook workbook1 = application.Workbooks.Open(#"D:\Excel2.xlsx", 1);
Worksheet xlWorksheet1 = (Worksheet)workbook1.Sheets[1];
Range range1 = xlWorksheet.get_Range("C1", "C5");
Range range2 = xlWorksheet1.get_Range("F1", "F5");
range1.Copy(range2);
workbook1.Save();
workbook.Save();
workbook.Close();
workbook1.Close();
application.Quit();
Thank you!
I want to read a selected cell range of Excel sheet into a DataTable without using OLEDB. And I don't want to use 3rd party tools either.
Here is what I have done so far:
public void converter()
{
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkbook = xlApp.Workbooks.Open(path);
Microsoft.Office.Interop.Excel.Sheets sheets = xlWorkbook.Worksheets;
xlWorksheet = xlWorkbook.Sheets[3];
for (int i = 1; i <= 10; i++)
{
range = xlWorksheet.get_Range("A2", "I8");
System.Array myvalues = (System.Array)range.Cells.Value;
//string[] strArray = ConvertToStringArray(myvalues);
//List<string> lst = myvalues.OfType<string>().ToList();
}
}
How can I achieve this?
After Googling, I ended up with following but I do not know how to make it work with cell range
public System.Data.DataTable READExcel(string path)
{
Microsoft.Office.Interop.Excel.Application objXL = null;
Microsoft.Office.Interop.Excel.Workbook objWB = null;
objXL = new Microsoft.Office.Interop.Excel.Application();
objWB = objXL.Workbooks.Open(path);
Microsoft.Office.Interop.Excel.Worksheet objSHT = objWB.Worksheets[5];
int rows = objSHT.UsedRange.Rows.Count;
int cols = objSHT.UsedRange.Columns.Count;
System.Data.DataTable dt = new System.Data.DataTable();
int noofrow = 1;
for (int c = 1; c <= cols; c++)
{
string colname = objSHT.Cells[1, c].Text;
dt.Columns.Add(colname);
noofrow = 2;
}
for (int r = noofrow; r <= rows; r++)
{
DataRow dr = dt.NewRow();
for (int c = 1; c <= cols; c++)
{
dr[c - 1] = objSHT.Cells[r, c].Text;
}
dt.Rows.Add(dr);
}
objWB.Close();
objXL.Quit();
return dt;
}
Kindly help me achieve this.
It's not perfect and you might need to tweek some parameters, I didn't check if it gets the correct area, thats your work.
But it gets a DataTable out of an Excel Worksheet, as you asked.
I'd prefer creating an custom object list with the columns as properties, rather than a DataTable, but thats only me.
public System.Data.DataTable READExcel(string path,int row,int col, int rowamount, int colamount, int worksheetindex)
{
Microsoft.Office.Interop.Excel.Application objXL = null;
Microsoft.Office.Interop.Excel.Workbook objWB = null;
objXL = new Microsoft.Office.Interop.Excel.Application();
objWB = objXL.Workbooks.Open(path);
Microsoft.Office.Interop.Excel.Worksheet objSHT = objWB.Worksheets[worksheetindex];
int rows = objSHT.UsedRange.Rows.Count;
int cols = objSHT.UsedRange.Columns.Count;
System.Data.DataTable dt = new System.Data.DataTable();
// Change that for other column names
for (int c = col; c <= col + colamount; c++)
{
dt.Columns.Add(objSHT.Cells[row, c].Text);
}
// read the content
for (int r = row; r <= row+rowamount; r++)
{
DataRow dr = dt.NewRow();
for (int c = col; c <= col+colamount; c++)
{
dr[c - 1] = objSHT.Cells[r, c].Text;
}
dt.Rows.Add(dr);
}
objWB.Close();
objXL.Quit();
return dt;
}
Call it like that:
// A2 -> row:2,col:1 till F6 row:2+4, col1+5
READExcel(#"path", 2, 1, 4, 5, 3);
The faster way would be using Value2, example: var range = xlWorksheet.Range["A3", "B4"].Value2; (get_Range() doesn't work with my excel)
and iterate over it, filling the DataTable. range[1,1] would be the content of A3 in this example.
i am generating an Excel from DataSet using the following code
int ColumnsCount;
if (DataTable == null || (ColumnsCount = DataTable.Columns.Count) == 0)
throw new Exception("ExportToExcel: Null or empty input table!\n");
// load excel, and create a new workbook
Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbooks.Add();
// single worksheet
Microsoft.Office.Interop.Excel._Worksheet Worksheet = Excel.ActiveSheet;
object[] Header = new object[ColumnsCount];
// column headings
for (int i = 0; i < ColumnsCount; i++)
Header[i] = DataTable.Columns[i].ColumnName;
Microsoft.Office.Interop.Excel.Range HeaderRange = Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[1, ColumnsCount]));
HeaderRange.Value = Header;
HeaderRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.BlanchedAlmond); //ConsoleColor.Yellow;//
HeaderRange.Font.Bold = true;
// DataCells
int RowsCount = DataTable.Rows.Count;
object[,] Cells = new object[RowsCount, ColumnsCount];
for (int j = 0; j < RowsCount; j++)
for (int i = 0; i < ColumnsCount; i++)
Cells[j, i] = (DataTable.Rows[j][i]);
Worksheet.get_Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[2, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[RowsCount + 1, ColumnsCount])).Value = Cells;
Worksheet.Columns.AutoFit();
Worksheet.SaveAs(ExcelFilePath);
Excel.Quit();
Console.Write("Excel file saved!");
However one of my columns is being shown as 1.004E+12 instead of 1004000003451, although it a string column being returned from sql server as varchar. How can i prevent it? Can any one help?
In the end it was simple, just used .columns method
Worksheet.Columns("A").NumberFormat ="#";
here is my code. I want to export Column6 and it rows to an Excel sheet. How can i do it?
Excel.Application excel = new Excel.Application();
excel.Visible = true;
object Missing = Type.Missing;
Workbook workbook = excel.Workbooks.Add(Missing);
Worksheet worksheet = (Worksheet)workbook.Sheets[1];
for (int i = 5; i < dataGridView6.Columns.Count; i++)
{
worksheet.Cells[1, 1] = dataGridView6.Columns[i].HeaderText;
}
for (int i = 0; i < dataGridView6.Rows.Count - 1; i++)
{
for (int j = 5; j < dataGridView6.Columns.Count - 1; j++)
{
worksheet.Cells[1, 1] = dataGridView6.Rows[i].Cells[j].Value.ToString();
}
}
}
I'm begining in WPF and i'm working with datagrid
I have multi datagrids. If i click a button ("Export" button) first time, it will create a new excel window and export data to first sheet. Then, i change to another datagrid and click a button ("Export" button) second time. so, it will create a new sheet in excel window which created before. Can you help me change my code ?
Thank you very much!!
public void Export(DataTable dt, string sheetName, string title)
{
Microsoft.Office.Interop.Excel.Application oExcel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks oBooks;
Microsoft.Office.Interop.Excel.Sheets oSheets;
Microsoft.Office.Interop.Excel.Workbook oBook;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
Excel.Range _range = null;
oExcel.DisplayAlerts = false;
oExcel.Application.SheetsInNewWorkbook = 1;
oBooks = oExcel.Workbooks;
oBook = (Microsoft.Office.Interop.Excel.Workbook)(oExcel.Workbooks.Add(Type.Missing));
oSheets = oBook.Worksheets;
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oSheets.get_Item(1);
oSheet.Name = sheetName;
Microsoft.Office.Interop.Excel.Range head = oSheet.get_Range("A1", "C1");
head.MergeCells = true;
head.Value2 = title;
head.Font.Bold = true;
head.Font.Name = "Tahoma";
head.Font.Size = "18";
head.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
List<object> objHeaders = new List<object>();
for (int n = 0; n <= dt.Rows.Count; n++)
{
objHeaders.Add(dt.Columns[n].ColumnName);
}
var headerToAdd = objHeaders.ToArray();
_range = oSheet.get_Range("A3", Type.Missing);
_range = _range.get_Resize(dt.Rows.Count, dt.Columns.Count);
_range.ColumnWidth = 30;
_range.set_Value(Type.Missing, headerToAdd);
Excel.Range rowHead = oSheet.get_Range("A3", "C"+dt.Columns.Count);
rowHead.Font.Bold = true;
rowHead.Borders.LineStyle = Microsoft.Office.Interop.Excel.Constants.xlSolid;
rowHead.Interior.ColorIndex = 15;
rowHead.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
int row = dt.Rows.Count;
int col = dt.Columns.Count;
object[,] arr = new object[row, col];
for (int r = 0; r < dt.Rows.Count; r++)
{
DataRow dr = dt.Rows[r];
for (int c = 0; c < dt.Columns.Count; c++)
{
arr[r, c] = dr[c];
}
}
int rowStart = 4;
int columnStart = 1;
int rowEnd = rowStart + dt.Rows.Count - 1;
int columnEnd = dt.Columns.Count;
Microsoft.Office.Interop.Excel.Range c1 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[rowStart, columnStart];
Microsoft.Office.Interop.Excel.Range c2 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[rowEnd, columnEnd];
Microsoft.Office.Interop.Excel.Range range = oSheet.get_Range(c1, c2);
range.Value2 = arr;
range.Borders.LineStyle = Microsoft.Office.Interop.Excel.Constants.xlSolid;
Microsoft.Office.Interop.Excel.Range c3 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[rowEnd, columnStart];
Microsoft.Office.Interop.Excel.Range c4 = oSheet.get_Range(c1, c3);
oSheet.get_Range(c3, c4).HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
oExcel.Visible = true;
}
}
You need to use field Microsoft.Office.Interop.Excel.Application oExcel in your class to store its value. First time it will be null, but on second - it will be opened excel. But you must be carefull with such a behavior, user can close excel, before 2nd export. So you need implement Closed event handler and clear your field (similar problem)