Below is my code to read existing excel file:
FileInfo newFile = new FileInfo("C:\\Excel\\SampleStockTakeExceptionReport.xlsx");
using (ExcelPackage xlPackage = new ExcelPackage(newFile))
{
var ws = xlPackage.Workbook.Worksheets.Add("Content");
ws.View.ShowGridLines = false;
ws.Column(4).OutlineLevel = 1;
ws.Column(4).Collapsed = true;
ws.Column(5).OutlineLevel = 1;
ws.Column(5).Collapsed = true;
ws.OutLineSummaryRight = true;
//Headers
ws.Cells["B1"].Value = "Name";
ws.Cells["C1"].Value = "Size";
ws.Cells["D1"].Value = "Created";
ws.Cells["E1"].Value = "Last modified";
ws.Cells["B1:E1"].Style.Font.Bold = true;
System.Diagnostics.Process.Start("C:\\Excel\\SampleStockTakeExceptionReport.xlsx");
}
While I run the code. It throws a runtime error.
Error.
System.InvalidOperationException: A worksheet with this name already exists in the workbook
at OfficeOpenXml.ExcelWorksheets.Add(String Name)
at Report.Form1.ExportToExcel1(DataTable Tbl, String ExcelFilePath) in C:\SMARTAG_PROJECT\SUREREACH\EXCEL\Report\Report\Form1.cs:line 43
It's pretty straight forward, either:
first check if the worksheet exists and only if it doesn't then execute your code
just remove the existing worksheet if it exists and add it again with your values
modify those values for the existing worksheet "Content"
Try something like this maybe:
FileInfo newFile = new FileInfo("C:\\Excel\\SampleStockTakeExceptionReport.xlsx");
using (ExcelPackage xlPackage = new ExcelPackage(newFile))
{
//Check if worksheet with name "Content" exists and retrieve that instance or null if it doesn't exist
var ws = xlPackage.Workbook.Worksheets.FirstOrDefault(x => x.Name == "Content");
//If worksheet "Content" was not found, add it
if (ws == null)
{
ws = xlPackage.Workbook.Worksheets.Add("Content");
}
//Rest of code
}
Related
All,
I have been struggling to simply reference an Excel file so that I can extract its data into a new worksheet automatically.
I know this means to create a new Excel file and its items:
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
Excel.Range oRng;
//Start Excel and get Application object.
oXL = new Excel.Application();
oXL.Visible = true;
//Get a new workbook.
oWB = (Excel._Workbook)(oXL.Workbooks.Add(Missing.Value));
oSheet = (Excel._Worksheet)oWB.ActiveSheet;
But this is where I am lost...I want the user to select another Excel file through a file dialog and then I want to copy data from said file into the new workbook above.
Ex: New file, user selects "MyExcel.csv". How would I reference this so that I can, say, copy Column A into the new worksheet? Whatever works with C#.
Maybe this helps:
Make sure your manage your Nugets and add the reference "Microsoft.Office.Interop.Excel" --> (References (Right click) --> Manage Nuget Packages --> Browse --> "Microsoft.Office.Interop.Excel" --> Install)
Note: This is is a copy paste into the same worksheet. To copy the data into another worksheet from another file just pass the "worksheet" as parameter to the method and paste it there.
public class Excel1
{
private readonly string excelSufix = ".xlsx";
private readonly string excelFilePrefix = "..."; //Where you excel file is located
private string getFilePath(string fileName)
{
return excelFilePrefix + fileName + excelSufix; //returns the file path by the given file name
}
public void CopyPaste(string fileName, int worksheet, string toCopyRange, string whereInsertRange)
{
//Range should look like = "A:C" or "D:F"
var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Visible = true;
var workBook = excelApp.Workbooks.Open(getFilePath(fileName));
var workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets[worksheet];
var toCopy = workSheet.Range[toCopyRange];
var whereInsert = workSheet.Range[whereInsertRange];
whereInsert.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, toCopy.Cut());
}
}
Edit: You could add a constructor to the class where you pass the file Path and some class variables which reference the file, the worksheet etc etc... In this case, you will have independent objects for each file
Based on your description, you want to copy one column from the csv file and paste in the new excel file.
First, I convert the csv file to datatable.
Second, I select the specific column and convert one column to datatable.
Third, I convert the datatable to the new excel file.
You can try the following code.
using System;
using System.Data;
using Excel = Microsoft.Office.Interop.Excel;
class Program
{
static void Main(string[] args)
{
string path = "D:\\t.csv";
DataTable table = ReadCsv(path);
table= new DataView(table).ToTable(false, "Tests");
ExportToExcel(table, "D:\\t.xlsx");
}
public static DataTable ReadCsv(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[1];
int rows = objSHT.UsedRange.Rows.Count;
int cols = objSHT.UsedRange.Columns.Count;
DataTable dt = new 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;
}
public static void ExportToExcel( DataTable tbl, string excelFilePath = null)
{
try
{
if (tbl == null || tbl.Columns.Count == 0)
throw new Exception("ExportToExcel: Null or empty input table!\n");
// load excel, and create a new workbook
var excelApp = new Excel.Application();
excelApp.Workbooks.Add();
// single worksheet
Excel._Worksheet workSheet = excelApp.ActiveSheet;
// column headings
for (var i = 0; i < tbl.Columns.Count; i++)
{
workSheet.Cells[1, i + 1] = tbl.Columns[i].ColumnName;
}
// rows
for (var i = 0; i < tbl.Rows.Count; i++)
{
// to do: format datetime values before printing
for (var j = 0; j < tbl.Columns.Count; j++)
{
workSheet.Cells[i + 2, j + 1] = tbl.Rows[i][j];
}
}
// check file path
if (!string.IsNullOrEmpty(excelFilePath))
{
try
{
workSheet.SaveAs(excelFilePath);
excelApp.Quit();
Console.WriteLine("Excel file saved!");
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
+ ex.Message);
}
}
else
{ // no file path is given
excelApp.Visible = true;
}
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: \n" + ex.Message);
}
}
}
Initial csv file.
The excel file:
For example, see the image
I want to swap the worksheet "Sheet1" to "Sheet3".
My Code using EPPlus:
ExcelPackage masterPackage = new ExcelPackage();
foreach (var file in files)
{
ExcelPackage pckg = new ExcelPackage(new FileInfo(file));
foreach (var sheet in pckg.Workbook.Worksheets)
{
//check name of worksheet, in case that worksheet with same name already exist exception will be thrown by EPPlus
string workSheetName = sheet.Name;
foreach (var masterSheet in masterPackage.Workbook.Worksheets)
{
if (sheet.Name == masterSheet.Name)
{
workSheetName = string.Format("{0}_{1}", workSheetName, DateTime.Now.ToString("yyyyMMddhhssmmm"));
}
}
//add new sheet
if (sheet.Name.Contains("MB_STORE_POTENTIALvsWALLET"))
{
masterPackage.Workbook.Worksheets.Add(workSheetName, sheet);
}
else
{
masterPackage.Workbook.Worksheets.Add(workSheetName, sheet);
masterPackage.Workbook.Worksheets.MoveToStart(1);
}
}
}
masterPackage.SaveAs(new FileInfo(resultFile));
How to do this? Any suggestion please..
If only you need to swap the sheets (I mean content do not required to be processed) then renaming sheet should be simple.
Rename the "Sheet1" to "adsf"
Rename the "Sheet3" to "Sheet1"
Rename the "adsf" to "Sheet3"
Sheets("Sheet1").Name = "adsf"
Sheets("Sheet3").Name = "Sheet1"
Sheets("adsf").Name = "Sheet3"
This is working fine:
ExcelPackage masterPackage = new ExcelPackage();
foreach (var file in files)
{
ExcelPackage pckg = new ExcelPackage(new FileInfo(file));
foreach (var sheet in pckg.Workbook.Worksheets)
{
//check name of worksheet, in case that worksheet with same name already exist exception will be thrown by EPPlus
string workSheetName = sheet.Name;
foreach (var masterSheet in masterPackage.Workbook.Worksheets)
{
if (sheet.Name == masterSheet.Name)
{
workSheetName = string.Format("{0}_{1}", workSheetName, DateTime.Now.ToString("yyyyMMddhhssmmm"));
}
}
//add new sheet
if (sheet.Name.Contains("MB_STORE_POTENTIALvsWALLET"))
{
masterPackage.Workbook.Worksheets.Add(workSheetName, sheet);
}
else
{
masterPackage.Workbook.Worksheets.Add(workSheetName, sheet);
masterPackage.Workbook.Worksheets.MoveBefore(2, 1);
}
}
}
masterPackage.SaveAs(new FileInfo(resultFile));
I want to merge multiple Excel files with EPPlus in C#.
I did the following:
using (MemoryStream protocolStream = new MemoryStream())
{
ExcelPackage pck = new ExcelPackage();
HashSet<string> wsNames = new HashSet<string>();
foreach (var file in files)
{
ExcelPackage copyPck = new ExcelPackage(new FileInfo(file));
foreach (var ws in copyPck.Workbook.Worksheets)
{
string name = ws.Name;
int i = 1;
while (!wsNames.Add(ws.Name))
name = ws.Name + i++;
ws.Name = name;
var copiedws = pck.Workbook.Worksheets.Add(name);
copiedws.WorksheetXml.LoadXml(ws.WorksheetXml.DocumentElement.OuterXml);
}
}
pck.SaveAs(protocolStream);
protocolStream.Position = 0;
using (FileStream fs = new FileStream(resultFile, FileMode.Create))
protocolStream.CopyTo(fs);
}
But I get the following error in pck.SaveAs(protocolStream):
System.ArgumentOutOfRangeException
in
System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument
argument, ExceptionResource resource) in
System.Collections.Generic.List1.get_Item(Int32 index) in
OfficeOpenXml.ExcelStyleCollection1.get_Item(Int32 PositionID)
I also tried it with the Worksheet.Copy method, but I lose the styling with it.
Here is an example of merging several files into one by coping all worksheets from source excel files.
var files = new string[] { #"P:\second.xlsx", #"P:\second.xlsx" };
var resultFile = #"P:\result.xlsx";
ExcelPackage masterPackage = new ExcelPackage(new FileInfo(#"P:\first.xlsx"));
foreach (var file in files)
{
ExcelPackage pckg = new ExcelPackage(new FileInfo(file));
foreach (var sheet in pckg.Workbook.Worksheets)
{
//check name of worksheet, in case that worksheet with same name already exist exception will be thrown by EPPlus
string workSheetName = sheet.Name;
foreach (var masterSheet in masterPackage.Workbook.Worksheets)
{
if (sheet.Name == masterSheet.Name)
{
workSheetName = string.Format("{0}_{1}", workSheetName, DateTime.Now.ToString("yyyyMMddhhssmmm"));
}
}
//add new sheet
masterPackage.Workbook.Worksheets.Add(workSheetName, sheet);
}
}
masterPackage.SaveAs(new FileInfo(resultFile));
My worksheet is initially named in the 5th line of my code, but I want to rename it based off the workbook name in my case statement. It is not getting renamed. How to fix??
DateTime d = DateTime.Today;
string s = d.ToString("MMddyyyy");
using (ExcelPackage pck = new ExcelPackage())
{
ExcelWorksheet objWorksheet = pck.Workbook.Worksheets.Add("Sheet 1");
objWorksheet.Cells["A1"].LoadFromDataTable(dataTable, true);
switch (pageName)
{
case "abcd":
worksheetName = "abcd";
workbookName = "abcd_" + s + ".xlsx";
objWorksheet.Cells["A1:K20"].AutoFitColumns();
break;
}
}
Looks like you are modifying some unrelated local variable. You would need to modify the Name property on the sheet object:
objWorksheet.Name = "abcd";
Given below is my code.. I have Excel template that contains 2 or three sheet. when I am performing and saving data on all excel its getting successful but if I am working on only one excel sheet it throws exception on xlPackage.Save();
HOW to save on only one sheet of Excel
String filePath = string.Format(ConfigurationManager.AppSettings["IcxFileFormatPath"]);
filePath += #"\ARK_New_FromDeviceSettings.xlsx";
String Template = string.Format(ConfigurationManager.AppSettings["IcxFileFormatTempPath"]);
FileInfo newFile = new FileInfo(filePath);
FileInfo UITemplate = new FileInfo(Template + #"\ARK_New_FromDeviceSettings.xlsx");
using (ExcelPackage xlPackage = new ExcelPackage(newFile, UITemplate))
{
ExcelWorksheet systemWorksheet = xlPackage.Workbook.Worksheets["System Details"];
if (systemWorksheet != null)
{
const int startRow = 2;
int row = startRow;
// DataTable dt
foreach (var systemDetailList in systemDetail)
{
if (row > startRow)
systemWorksheet.InsertRow(row);
systemWorksheet.Cell(row, 1).Value = Convert.ToString(systemDetailList.ModbusTCPIDofDCUDevice);
systemWorksheet.Cell(row, 2).Value = systemDetailList.DCUSerialNumber;
}
}
xlPackage.Save();
}
// HttpContext context = HttpContext.Current;
Response.Clear();
Response.Clear();
Response.ContentType = "application/ms-excel";
Response.AppendHeader("Content-Disposition", "attachment;filename=UIRateTemplate.xlsx");
Response.WriteFile(filePath);
Response.Flush();
Response.End();
Since you don't do anything other than save the ExcelPackage if there is no "System Details" worksheet, why don't you move the line "xlPackage.Save()" one line up, before that close brace? It will no longer save, but you aren't making any changes anyhow, and you'll eliminate the NullReferenceException.