designation table:
deg_no deg_name
1 XYZ
2 ABC
3 pqs
4 qwe
5 tyu
6 pqr
7 lkj
8 you
9 zzz
10 xxx
ds = cls.ReturnDataSet("RetriveData_Alias1",
new SqlParameter("#Field", "deg_no"),
new SqlParameter("#TblNm", "designation"));
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
DataSet ds1 = new DataSet();
ds1 = cls.ReturnDataSet("RetriveData_Alias1",
new SqlParameter("#Field", "user_id,user_name"),
new SqlParameter("#TblNm", "User_details"),
new SqlParameter("#WhereClause", "where deg_no ='" + ds.Tables[0].Rows[i]["deg_no"].ToString() + "' "));
}
this for loop will run until the deg_no=10 and gives the all the user details and it is gives the perfect output as i want
the output.
but i want to write these data into excel file : user_details.xls
for suppose when i=1, then it will give you
user_id user_name deg_no
1 xyz 1
and for i=2
user_id user_name deg_no
2 pqr 3
and so on...
but without create new file each time .
suppose on first loop it will insert record of user_id =1
then in second loop the details of user_id=2 is append in the same file without creating a new file.
how can i do that?
If you want to generate an Excel file from database data, a reporting solution is the most flexible approach. If on the other hand you want to add the data to an already existing file, you can manipulate Excel files using the Open XML SDK or a higher-level library like EPPlus. EPPlus is available as a NuGet package so you can easily add it to your project.
The project site of EPPlus contains various samples. Creating an Excel sheet can be as simple as :
FileInfo newFile = new FileInfo(outputDir.FullName + #"\sample6.xlsx");
ExcelPackage pck = new ExcelPackage(newFile);
//Add the Content sheet
var ws = pck.Workbook.Worksheets.Add("Content");
ws.Cells["B1"].Value = "Name";
ws.Cells["C1"].Value = "Size";
ws.Cells["D1"].Value = "Created";
ws.Cells["E1"].Value = "Last modified";
EPPlus also allows you to query Excel Sheets using LINQ and even directly convert IEnumerable collections to Excel Tables :
ws.Cells["A1"].LoadFromCollection(myList, true);
This will fill a table with the property values of the objects in myList.
EPPlus also has methods to read from DataTables and DataReaders. This allows you to read your DataSet as you already do, then add each Datatable to the sheet in the appropriate places, eg:
ws.Cells["A1"].LoadFromDataTable(ds1.Tables[0], true);
...
ws.Cells["A30"].LoadFromDataTable(ds1.Tables[0], true);
This way you can use EPPlus to generate quick&dirty Excel reports when you don't want to use a full reporting solution.
You Need to read about ASP.Net Report Viewer control
May this helping you
ASP.Net Report Viewer control Tutorial with example
or you can use
Export to EXCEL from Datatable in C#.Net
or You need Office Interop as a reference then lets do the coding
using Microsoft.Office.Interop.Excel;
public void DataSetsToExcel(List<DataSet> dataSets, string fileName)
{
Microsoft.Office.Interop.Excel.Application xlApp =
new Microsoft.Office.Interop.Excel.Application();
Workbook xlWorkbook = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Sheets xlSheets = null;
Worksheet xlWorksheet = null;
foreach (DataSet dataSet in dataSets)
{
System.Data.DataTable dataTable = dataSet.Tables[0];
int rowNo = dataTable.Rows.Count;
int columnNo = dataTable.Columns.Count;
int colIndex = 0;
//Create Excel Sheets
xlSheets = xlWorkbook.Sheets;
xlWorksheet = (Worksheet)xlSheets.Add(xlSheets[1],
Type.Missing, Type.Missing, Type.Missing);
xlWorksheet.Name = dataSet.DataSetName;
//Generate Field Names
foreach (DataColumn dataColumn in dataTable.Columns)
{
colIndex++;
xlApp.Cells[1, colIndex] = dataColumn.ColumnName;
}
object[,] objData = new object[rowNo, columnNo];
//Convert DataSet to Cell Data
for (int row = 0; row < rowNo; row++)
{
for (int col = 0; col < columnNo; col++)
{
objData[row, col] = dataTable.Rows[row][col];
}
}
//Add the Data
Range range = xlWorksheet.Range[xlApp.Cells[2, 1], xlApp.Cells[rowNo + 1, columnNo]];
range.Value2 = objData;
//Format Data Type of Columns
colIndex = 0;
foreach (DataColumn dataColumn in dataTable.Columns)
{
colIndex++;
string format = "#";
switch (dataColumn.DataType.Name)
{
case "Boolean":
break;
case "Byte":
break;
case "Char":
break;
case "DateTime":
format = "dd/mm/yyyy";
break;
case "Decimal":
format = "$* #,##0.00;[Red]-$* #,##0.00";
break;
case "Double":
break;
case "Int16":
format = "0";
break;
case "Int32":
format = "0";
break;
case "Int64":
format = "0";
break;
case "SByte":
break;
case "Single":
break;
case "TimeSpan":
break;
case "UInt16":
break;
case "UInt32":
break;
case "UInt64":
break;
default: //String
break;
}
//Format the Column accodring to Data Type
xlWorksheet.Range[xlApp.Cells[2, colIndex],
xlApp.Cells[rowNo + 1, colIndex]].NumberFormat = format;
}
}
//Remove the Default Worksheet
((Worksheet)xlApp.ActiveWorkbook.Sheets[xlApp.ActiveWorkbook.Sheets.Count]).Delete();
//Save
xlWorkbook.SaveAs(fileName,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
XlSaveAsAccessMode.xlNoChange,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value);
xlWorkbook.Close();
xlApp.Quit();
GC.Collect();
}
Take note you have to name your DataSet and that will be the name of the worksheet in Excel.
DataSet dataSet1 = new DataSet("My Data Set 1");
dataAdapter1.Fill(dataSet1);
DataSet dataSet2 = new DataSet("My Data Set 2");
dataAdapter1.Fill(dataSet2);
DataSet dataSet3 = new DataSet("My Data Set 3");
dataAdapter1.Fill(dataSet3);
List<DataSet> dataSets = new List<DataSet>();
dataSets.Add(dataSet1);
dataSets.Add(dataSet2);
dataSets.Add(dataSet3);
DataSetsToExcel(dataSets, "{Your File Name}")
to add Office Interop as a reference
following these steps:
On the Project menu, click Add Reference.
On the COM tab, locate Microsoft Excel Object Library, and then click Select. In Visual Studio 2010, locate Microsoft Excel --.- Object Library on the COM tab.
Click OK in the Add References dialog box to accept your selections. If you are prompted to generate wrappers for the libraries that you selected, click “Yes”.
Related
I have an SSRS reports form where in Export my results in Excel file. As Excel behavior is to Enable Protected View for files originating from the internet. it asks for Enable Editing button clicked or setting off for Excel.
i am using script task C# to read excel in SSIS. but to execute it, i need to click on enable editing on in Excel. is there any way to not to set the settings or open the file to make it writable. my script task works in development but fails in deploy mode. below is the code. please help me to figure out.
//pass that to workbook object
Microsoft.Office.Interop.Excel.Workbook workBook = oExcel.Workbooks.Open(workbookPath);
foreach (Worksheet worksheet in workBook.Worksheets)
{
if (worksheet.Name.Equals(sheetName, StringComparison.OrdinalIgnoreCase))
{
Microsoft.Office.Interop.Excel.Range xlRange = worksheet.UsedRange;
object[,] data = new object[xlRange.Rows.Count - 1, xlRange.Columns.Count];
System.Data.DataTable dt = new System.Data.DataTable();
for (int i = 1; i <= xlRange.Rows.Count - 1; i++)
{
for (int j = 1; j <= xlRange.Columns.Count; j++)
{
data[i - 1, j - 1] = (xlRange.Cells[i, j] as Microsoft.Office.Interop.Excel.Range).Value;
}
}
workBook.Close(true);
oExcel.Application.Quit();
oExcel.Quit();
Marshal.ReleaseComObject(workBook);
Marshal.ReleaseComObject(oExcel);
dt = ArraytoDatatable(data);
dt.TableName = tableName;
//BulkLoadDataTable(dt, connectionString);
}
else
{
FireError("Wrong Sheet name found. Please Rename the sheet name as:" + sheetName);
}
}
Dts.TaskResult = (int)ScriptResults.Success;
I have a few different dictionaries with different categories of information and I need to output them all into an xls or csv file with multiple spreadsheets. Currently, I have to download each excel file for a specific date range individually and then copy and paste them together so they're on different sheets of the same file. Is there any way to download all of them together in one document? Currently, I use the following code to output their files:
writeCsvToStream(
organize.ToDictionary(k => k.Key, v => v.Value as IacTransmittal), writer
);
ms.Seek(0, SeekOrigin.Begin);
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
Response.AddHeader("Content-Length", ms.Length.ToString());
Response.ContentType = "application/octet-stream";
ms.CopyTo(Response.OutputStream);
Response.End();
where writeCsvToStream just creates the text for the individual file.
There are some different options you could use.
ADO.NET Excel driver - with this API you can populate data into Excel documents using SQL style syntax. Each worksheet in the workbook is a table, each column header in a worksheet is a column in that table etc.
Here is a code project article on the exporting to Excel using ADO.NET:
http://www.codeproject.com/Articles/567155/Work-with-MS-Excel-and-ADO-NET
The ADO.NET approach is safe to use in a multi-user, web app environment.
Use OpenXML to export the data
OpenXML is a schema definition for different types of documents and the later versions of Excel (the ones that use .xlsx, .xlsm etc. instead of just .xls) use this format for the documents. The OpenXML schema is huge and somewhat cumbersome, however you can do pretty much anything with it.
Here is a code project article on exporting data to Excel using OpenXML:
http://www.codeproject.com/Articles/692121/Csharp-Export-data-to-Excel-using-OpenXML-librarie
The OpenXML approach is safe to use in a multi-user, web app environment.
A third approach is to use COM automation which is the same as programmatically running an instance of the Excel desktop application and using COM to control the actions of that instance.
Here is an article on that topic:
http://support.microsoft.com/kb/302084
Note that this third approach (office automation) is not safe in a multi-user, web app environment. I.e. it should not be used on a server, only from standalone desktop applications.
If you're open to learning a new library, I highly recommend EPPlus.
I'm making a few assumptions here since you didn't post much code to translate, but an example of usage may look like this:
using OfficeOpenXml;
using OfficeOpenXml.Style;
public static void WriteXlsOutput(Dictionary<string, IacTransmittal> collection) //accepting one dictionary as a parameter
{
using (FileStream outFile = new FileStream("Example.xlsx", FileMode.Create))
{
using (ExcelPackage ePackage = new ExcelPackage(outFile))
{
//group the collection by date property on your class
foreach (IGrouping<DateTime, IacTransmittal> collectionByDate in collection
.OrderBy(i => i.Value.Date.Date)
.GroupBy(i => i.Value.Date.Date)) //assuming the property is named Date, using Date property of DateTIme so we only create new worksheets for individual days
{
ExcelWorksheet eWorksheet = ePackage.Workbook.Worksheets.Add(collectionByDate.Key.Date.ToString("yyyyMMdd")); //add a new worksheet for each unique day
Type iacType = typeof(IacTransmittal);
PropertyInfo[] iacProperties = iacType.GetProperties();
int colCount = iacProperties.Count(); //number of properties determines how many columns we need
//set column headers based on properties on your class
for (int col = 1; col <= colCount; col++)
{
eWorksheet.Cells[1, col].Value = iacProperties[col - 1].Name ; //assign the value of the cell to the name of the property
}
int rowCounter = 2;
foreach (IacTransmittal iacInfo in collectionByDate) //iterate over each instance of this class in this igrouping
{
int interiorColCount = 1;
foreach (PropertyInfo iacProp in iacProperties) //iterate over properties on the class
{
eWorksheet.Cells[rowCounter, interiorColCount].Value = iacProp.GetValue(iacInfo, null); //assign cell values by getting the value of each property in the class
interiorColCount++;
}
rowCounter++;
}
}
ePackage.Save();
}
}
}
Thanks for the ideas! I was eventually able to figure out the following
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook ExcelWorkBook = null;
Excel.Worksheet ExcelWorkSheet = null;
ExcelApp.Visible = true;
ExcelWorkBook = ExcelApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
List<string> SheetNames = new List<string>()
{ "Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5", "Sheet6", "Sheet7"};
string [] headers = new string []
{ "Field 1", "Field 2", "Field 3", "Field 4", "Field 5" };
for (int i = 0; i < SheetNames.Count; i++)
ExcelWorkBook.Worksheets.Add(); //Adding New sheet in Excel Workbook
for (int k = 0; k < SheetNames.Count; k++ )
{
int r = 1; // Initialize Excel Row Start Position = 1
ExcelWorkSheet = ExcelWorkBook.Worksheets[k + 1];
//Writing Columns Name in Excel Sheet
for (int col = 1; col < headers.Length + 1; col++)
ExcelWorkSheet.Cells[r, col] = headers[col - 1];
r++;
switch (k)
{
case 0:
foreach (var kvp in Sheet1)
{
ExcelWorkSheet.Cells[r, 1] = kvp.Value.Field1;
ExcelWorkSheet.Cells[r, 2] = kvp.Value.Field2;
ExcelWorkSheet.Cells[r, 3] = kvp.Value.Field3;
ExcelWorkSheet.Cells[r, 4] = kvp.Value.Field4;
ExcelWorkSheet.Cells[r, 5] = kvp.Value.Field5;
r++;
}
break;
}
ExcelWorkSheet.Name = SheetNames[k];//Renaming the ExcelSheets
}
//Activate the first worksheet by default.
((Excel.Worksheet)ExcelApp.ActiveWorkbook.Sheets[1]).Activate();
//Save As the excel file.
ExcelApp.ActiveWorkbook.SaveCopyAs(#"out_My_Book1.xls");
In my excel workbook
The first sheet tab contains
Number Name Code Subject
100 Mark ABC Mathematics
101 John XYZ Physics
The second sheet tab contains
Number Name Code Subject
103 Mark DEF Chemistry
104 John GHI Biology
I want to pass the code(which is going to be unique) as a parameter and search the entire excel workbook
and fetch name and subject..
ie..select name,subject from myexcelworkbook where code='ABC'
I am able to get sheet names, column count etc. but not able to search thro' an entire excel workbook and get the required values
const string fileName="C:\\FileName.xls";
OleDbConnectionStringBuilder connectionStringBuilder = new OleDbConnectionStringBuilder();
connectionStringBuilder.Provider = "Microsoft.ACE.OLEDB.12.0";
connectionStringBuilder.DataSource = fileName;
connectionStringBuilder.Add("Mode", "Read");
const string extendedProperties = "Excel 12.0;IMEX=1;HDR=YES";
connectionStringBuilder.Add("Extended Properties", extendedProperties);
using (OleDbConnection objConn = new OleDbConnection(connectionStringBuilder.ConnectionString))
{
objConn.Open();
Microsoft.Office.Interop.Excel.Application xlsApp = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = xlsApp.Workbooks.Open(fileName, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true);
Sheets sheets = wb.Worksheets;
for (int i =1 ; i <= wb.Worksheets.Count; i++)
{
MessageBox.Show(wb.Sheets[i].Name.ToString()); - gives sheet names inside the workbook
}
Worksheet ws = (Worksheet)sheets.get_Item(1); - gives the elements of specified sheet tab
}
//To get elements inside a specific sheet of an excel workbook/get column names
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [" + "Sheet1" + "$]", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
DataSet objDataset1 = new DataSet();
objAdapter1.Fill(objDataset1);
string columnNames = string.Empty;
// For each DataTable, print the ColumnName. use dataset.Rows to iterate row data...
foreach (System.Data.DataTable table in objDataset1.Tables)
{
foreach (DataColumn column in table.Columns)
{
if (columnNames.Length > 0)
{
columnNames = columnNames + Environment.NewLine + column.ColumnName;
}
else
{
columnNames = column.ColumnName;
}
}
}
Can someone share some ideas, so that i can find out the unique data inside the excel workbook and fetch out the needed values based on that? thanks in advance.
If the workbooks are as structured as you indicate and you will be querying multiple students then, as #Andy G suggests, you might find it easiest to just get the data into some form of record set then you run your queries on it through Linq or SQL or whatever you prefer. As you aren't wishing to modify the Excel workbook at all this is probably a better approach.
Alternatively, you can use the Excel API, like you were also trying to use. You can enumerate through the worksheets, running a Find on each. A la:
internal void GetYourData()
{
//... code to get the relevant Workbook and relevant/new Excel Application
Tuple<string, string> pupil;
string searchTerm = "ABC";
//Get the cell of the match
Range match = FindFirstOccurrenceInWorkbook(workbook, searchTerm);
if (match != null)
{
//Do whatever - per your data structure, it is probably easiest to just use .Offset(row, column) property
pupil = new Tuple<string, string>((string)match.Offset(0, -1).Value, (string)match.Offset(0, 1).Value);
}
//... code to do whatever with your results
}
internal static Range FindFirstOccurrenceInWorkbook(Workbook workbook, string searchTerm)
{
if (workbook == null) throw new ArgumentNullException("workbook");
if (searchTerm == null) throw new ArgumentNullException("searchTerm");
Sheets wss = workbook.Worksheets;
Range match = null;
foreach (Worksheet ws in wss)
{
Range cells = ws.Cells;
//Add more args as needed - this is just an example
match = cells.Find(
what: searchTerm,
after: Type.Missing,
lookIn: XlFindLookIn.xlFormulas,
lookAt: XlLookAt.xlPart);
System.Runtime.InteropServices.Marshal.ReleaseComObject(cells);
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
if (match != null)
{
break;
}
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(wss);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
return match;
}
Also, you can't use COM objects like you use without generating orphaned references -> this will prevent the Excel application from closing. You need to explicitly assign all object properties you want to use like Workbook.Worksheets to a variable then call System.Runtime.InteropServices.Marshal.ReleaseCOMObject(object) when the variable is about to go out of scope.
I currently have the following code opening and reading in an excel spreadsheet:
var connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=Excel 12.0;", fileNameTextBox.Text);
var queryString = String.Format("SELECT * FROM [{0}]",DETAILS_SHEET_NAME);
var adapter = new OleDbDataAdapter(queryString, connectionString);
var ds = new DataSet();
adapter.Fill(ds, DETAILS_SHEET_NAME);
DataTable data = ds.Tables[DETAILS_SHEET_NAME];
dataGridView1.DataSource = data;
dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
This is all good and well except I'm not interested in the first row (Possibly first two rows as row 2 is headers) of the worksheet. How can I modify the select Query to select a range like I would in excel?
I'm interested in reading in say columns A-N in rows all rows from 2 onwards that contain data.
I also need to access a couple of specific cells on a different worksheet, I assume I have to build another adaptor with a different query string for each of those cells?
Modify Select statement including just the columns you need instead of wildcard "*" like in the following example:
("SELECT Column1, Column2 FROM DETAILS_SHEET_NAME");
You can apply additional logic in order to remove unnecessary rows, for example, a "paging solution" (i.e. selecting rows from N to M) like the following one:
Assuming the Database Table "TBL_ITEM" contains two columns (fields) of interest: “Item” column, representing the unique ID and “Rank”, which is used for sorting in ascending order, the general paging problem is stated as following: Select N-rows from the table ordered by Rank offsetting (i.e. skipping) (M-N) rows:
SELECT TOP N Item,
Rank FROM (SELECT TOP M Rank, Item FROM TBL_ITEM ORDER BY Rank)
AS [SUB_TAB] ORDER BY Rank DESC
This solution and its extensions/samples are thoroughly discussed in my article Pure SQL solution to Database Table Paging (link: http://www.codeproject.com/Tips/441079/Pure-SQL-solution-to-Database-Table-Paging)
Finally, you can use a code snippet shown below in Listing 2 to export a content of DataTable object in Excel file with plenty of customization features that could be added to a code;
Listing 2. Export DataTable to Excel File (2007/2010):
internal static bool Export2Excel(DataTable dataTable, bool Interactive)
{
object misValue = System.Reflection.Missing.Value;
// Note: don't include Microsoft.Office.Interop.Excel in reference (using),
// it will cause ambiguity w/System.Data: both have DataTable obj
Microsoft.Office.Interop.Excel.Application _appExcel = null;
Microsoft.Office.Interop.Excel.Workbook _excelWorkbook = null;
Microsoft.Office.Interop.Excel.Worksheet _excelWorksheet = null;
try
{
// excel app object
_appExcel = new Microsoft.Office.Interop.Excel.Application();
// make it visible to User if Interactive flag is set
_appExcel.Visible = Interactive;
// excel workbook object added to app
_excelWorkbook = _appExcel.Workbooks.Add(misValue);
_excelWorksheet = _appExcel.ActiveWorkbook.ActiveSheet
as Microsoft.Office.Interop.Excel.Worksheet;
// column names row (range obj)
Microsoft.Office.Interop.Excel.Range _columnsNameRange;
_columnsNameRange = _excelWorksheet.get_Range("A1", misValue);
_columnsNameRange = _columnsNameRange.get_Resize(1, dataTable.Columns.Count);
// data range obj
Microsoft.Office.Interop.Excel.Range _dataRange;
_dataRange = _excelWorksheet.get_Range("A2", misValue);
_dataRange = _dataRange.get_Resize(dataTable.Rows.Count, dataTable.Columns.Count);
// column names array to be assigned to columnNameRange
string[] _arrColumnNames = new string[dataTable.Columns.Count];
// 2d-array of data to be assigned to _dataRange
string[,] _arrData = new string[dataTable.Rows.Count, dataTable.Columns.Count];
// populate both arrays: _arrColumnNames and _arrData
// note: 2d-array structured as row[idx=0], col[idx=1]
for (int i = 0; i < dataTable.Columns.Count; i++)
{
for (int j = 0; j < dataTable.Rows.Count; j++)
{
_arrColumnNames[i] = dataTable.Columns[i].ColumnName;
_arrData[j, i] = dataTable.Rows[j][i].ToString();
}
}
//assign column names array to _columnsNameRange obj
_columnsNameRange.set_Value(misValue, _arrColumnNames);
//assign data array to _dataRange obj
_dataRange.set_Value(misValue, _arrData);
// save and close if Interactive flag not set
if (!Interactive)
{
// Excel 2010 - "14.0"
// Excel 2007 - "12.0"
string _ver = _appExcel.Version;
string _fileName ="TableExport_" +
DateTime.Today.ToString("yyyy_MM_dd") + "-" +
DateTime.Now.ToString("hh_mm_ss");
// check version and select file extension
if (_ver == "14.0" || _ver == "12.0") { _fileName += ".xlsx";}
else { _fileName += ".xls"; }
// save and close Excel workbook
_excelWorkbook.Close(true, "{DRIVE LETTER}:\\" + _fileName, misValue);
}
return true;
}
catch (Exception ex) { throw; }
finally
{
// quit excel app process
if (_appExcel != null)
{
_appExcel.UserControl = false;
_appExcel.Quit();
_appExcel = null;
misValue = null;
}
}
}
You can simply ask for no headers. Modify your connection string, add HDR=No.
For your second issue, I found this post, Maybe you'll find it helpful.
Let us consider that I have two Excel files (Workbooks) in local. Each Excel workbook is having 3 worksheets.
Lets say WorkBook1 is having Sheet1, Sheet2, Sheet3
Workbook2 is having Sheet1, Sheet2, Sheet3.
So here I need to merge these two excel workbook into one and the new excel workbook that is let's say Workbook3 which will have total 6 worksheets (combination of workbook1 and workbook2).
I need the code that how to perform this operation in c# without using any third party tool. If the third party tool is free version then its fine.
An easier solution is to copy the worksheets themselves, and not their cells.
This method takes any number of excel file paths and copy them into a new file:
private static void MergeWorkbooks(string destinationFilePath, params string[] sourceFilePaths)
{
var app = new Application();
app.DisplayAlerts = false; // No prompt when overriding
// Create a new workbook (index=1) and open source workbooks (index=2,3,...)
Workbook destinationWb = app.Workbooks.Add();
foreach (var sourceFilePath in sourceFilePaths)
{
app.Workbooks.Add(sourceFilePath);
}
// Copy all worksheets
Worksheet after = destinationWb.Worksheets[1];
for (int wbIndex = app.Workbooks.Count; wbIndex >= 2; wbIndex--)
{
Workbook wb = app.Workbooks[wbIndex];
for (int wsIndex = wb.Worksheets.Count; wsIndex >= 1; wsIndex--)
{
Worksheet ws = wb.Worksheets[wsIndex];
ws.Copy(After: after);
}
}
// Close source documents before saving destination. Otherwise, save will fail
for (int wbIndex = 2; wbIndex <= app.Workbooks.Count; wbIndex++)
{
Workbook wb = app.Workbooks[wbIndex];
wb.Close();
}
// Delete default worksheet
after.Delete();
// Save new workbook
destinationWb.SaveAs(destinationFilePath);
destinationWb.Close();
app.Quit();
}
Edit: notice that you might want to Move method instead of Copy in case you have dependencies between the sheets, e.g. pivot table, charts, formulas, etc. Otherwise the data source will disconnect and any changes in one sheet won't effect the other.
Here's a working sample that joins two books into a new one, hope it will give you an idea:
using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
namespace MergeWorkBooks
{
class Program
{
static void Main(string[] args)
{
Excel.Application app = new Excel.Application();
app.Visible = true;
app.Workbooks.Add("");
app.Workbooks.Add(#"c:\MyWork\WorkBook1.xls");
app.Workbooks.Add(#"c:\MyWork\WorkBook2.xls");
for (int i = 2; i <= app.Workbooks.Count; i++)
{
int count = app.Workbooks[i].Worksheets.Count;
app.Workbooks[i].Activate();
for (int j=1; j <= count; j++)
{
Excel._Worksheet ws = (Excel._Worksheet)app.Workbooks[i].Worksheets[j];
ws.Select(Type.Missing);
ws.Cells.Select();
Excel.Range sel = (Excel.Range)app.Selection;
sel.Copy(Type.Missing);
Excel._Worksheet sheet = (Excel._Worksheet)app.Workbooks[1].Worksheets.Add(
Type.Missing, Type.Missing, Type.Missing, Type.Missing
);
sheet.Paste(Type.Missing, Type.Missing);
}
}
}
}
}
You're looking for Office Autmation libraries in C#.
Here is a sample code to help you get started.
System.Data.Odbc.OdbcDataAdapter Odbcda;
//CSV File
strConnString = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" + SourceLocation + ";Extensions=asc,csv,tab,txt;Persist Security Info=False";
sqlSelect = "select * from [" + filename + "]";
System.Data.Odbc.OdbcConnection conn = new System.Data.Odbc.OdbcConnection(strConnString.Trim());
conn.Open();
Odbcda = new System.Data.Odbc.OdbcDataAdapter(sqlSelect, conn);
Odbcda.Fill(ds, DataTable);
conn.Close();
This would read the contents of an excel file into a dataset.
Create multiple datasets like this and then do a merge.
Code taken directly from here.