EPPlus - Named Range is not populated - c#

I'm using EPPLus to open Excel Spreadsheets and trying to read from a named range. The Named Range is Empty.
Am I using this wrong, or is it a problem with EPPlus
Code
var package = new ExcelPackage();
using (var stream = File.OpenRead(tmpExcel))
{
package.Load(stream);
}
var worksheet = package.Workbook.Worksheets["Common-Lookup"];
using (ExcelNamedRange namedRange = worksheet.Names["LupVerticalSettings"])
{
for (var row = namedRange.Start.Row; row <= namedRange.End.Row; row++)
{
for (var col = namedRange.Start.Column; col <= namedRange.End.Column; col++)
{
_.Nv(worksheet.Cells[row, col].Address, worksheet.Cells[row, col].Text);
//worksheet.Cells[rowIndex, columnIndex].Value = "no more hair pulling";
}
}
}
The Excel looks like this
Empty Named Range

I solved my problem, I'll put answer here for anyone that may need it in the future
var package = new ExcelPackage();
using (var stream = File.OpenRead(tmpExcel))
{
package.Load(stream);
}
var worksheet = package.Workbook.Worksheets["Common-Lookup"];
// Access Named Ranges from the ExcelWorkbook instead of ExcelWorksheet
//using (ExcelNamedRange namedRange = worksheet.Names["LupVerticalSettings"])
// use package.Workbook.Names instead of worksheet.Names
using (ExcelNamedRange namedRange = package.Workbook.Names["LupVerticalSettings"])
{
for (var row = namedRange.Start.Row; row <= namedRange.End.Row; row++)
{
for (var col = namedRange.Start.Column; col <= namedRange.End.Column; col++)
{
_.Nv(worksheet.Cells[row, col].Address, worksheet.Cells[row, col].Text);
//worksheet.Cells[rowIndex, columnIndex].Value = "no more hair pulling";
}
}
}

Related

How to set background color of DataRow in DataTable c#

I am exporting my DataTable to Excel.
So before exporting, I added a new row, I want to set some background color to this row.
Here is my code...
DataRow newRow = datatable3.NewRow();
for (int i = 0; i < datatable3.Columns.Count; i++)
{
newRow[i] = "Hello";
}
//newRow.BackGroundColor = "Red" - Something like this.
Here I am exporting my DataTable to Excel.
using (XLWorkbook wb = new XLWorkbook())
{
foreach (DataTable dt in ds.Tables)
{
//Add DataTable as Worksheet.
wb.Worksheets.Add(dt, dt.TableName.ToString());
}
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
return File(MyMemoryStream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ext);
}
}
It is showing like this .
How to change row background color?
it looks like you are using ClosedXMS dll. check their documentation on using colors
#Gopal
Just being a little specific to #Conor's answer!. You can try this-
//For a specific Datatable in a list of multiple
var ws = wb.Worksheets.Add(dt, dt.TableName.ToString());
for (int j = 1; j <= ds.Tables[3].Columns.Count; j++) //This is for fourth datatable/sheet
{
ws.Cell(2, j).Style.Fill.BackgroundColor = XLColor.FromArgb(255, 255, 0); //All columns of second row
}
XlColor.FromArgb(//RGB Color Code); This static method gives you the liberty of specifying the RGB color code which you can easily get through the excel template you are using.
You can use the Interior property found on an Excel.Range.
// The following just shows how the variables are created (based on creating a new Excel Spreadsheet)
var xlApp = new Excel.Application();
var xlWorkbook = xlApp.Workbooks.Add(Missing.Value);
var xlWorksheet = xlWorkbook.Worksheets[1];
// Now the actual code needed
var xlRange = xlWorksheet.UsedRange;
// This select the entire top row, but you can select your own range based on your data
var titleRange = xlRange.Range["A1", string.Concat(((char)(xlRange.Columns.Count + 64)), 1)];
// The following line sets the fill colour
titleRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Blue);

Using assertions to compare two excel files

Im using Visual Studio to create an automated test that creates two excel sheets. As a final check, I need to compare the content of these two excel sheets and ensure that they are equal. Is there any way to do this with assertions?
Something like Assert.AreEqual(file1, file2);?
Any help or guidance would be appreciated!
Thanks to Mangist for guidance on this. Ive written the following to compare two excel files:
public bool compareFiles(string filePath1, string filePath2)
{
bool result = false;
Excel.Application excel = new Excel.Application();
//Open files to compare
Excel.Workbook workbook1 = excel.Workbooks.Open(filePath1);
Excel.Workbook workbook2 = excel.Workbooks.Open(filePath2);
//Open sheets to grab values from
Excel.Worksheet worksheet1 = (Excel.Worksheet)workbook1.Sheets[1];
Excel.Worksheet worksheet2 = (Excel.Worksheet)workbook2.Sheets[1];
//Get the used range of cells
Excel.Range range = worksheet2.UsedRange;
int maxColumns = range.Columns.Count;
int maxRows = range.Rows.Count;
//Check that each cell matches
for (int i = 1; i <= maxColumns; i++)
{
for (int j = 1; j <= maxRows; j++)
{
if (worksheet1.Cells[j, i].Value == worksheet2.Cells[j, i].Value)
{
result = true;
}
else
result = false;
}
}
//Close the workbooks
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.ReleaseComObject(range);
Marshal.ReleaseComObject(worksheet1);
Marshal.ReleaseComObject(worksheet2);
workbook1.Close();
workbook2.Close();
excel.Quit();
Marshal.ReleaseComObject(excel);
//Tell us if it is true or false
return result;
}
And using an assertion to check result:
Assert.IsTrue(compareFiles(testFile, compareFile), "Output files do not match.");
Can you convert the expected/actual Excel sheets to a text format, such as CSV?
If so, you could use Approval Tests instead. This allows you to have a text file as your "expected" test result. When tests fail it can show you the actual result of the test, diff'd against the expected result.
Screenshot taken from this review of Approval Tests.
One Option will be using Open source library called as EPPlus. You can download and refer it in you automated test application. EPPlus gives you multiple ways to read an excel file and compare. One such option is C# Datatable. Here is a sample code..
public static DataTable GetDataTableFromExcel(string path, bool hasHeader = true)
{
using (var pck = new OfficeOpenXml.ExcelPackage())
{
using (var stream = File.OpenRead(path))
{
pck.Load(stream);
}
var ws = pck.Workbook.Worksheets.First();
DataTable tbl = new DataTable();
foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
{
tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
}
var startRow = hasHeader ? 2 : 1;
for (int rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
DataRow row = tbl.Rows.Add();
foreach (var cell in wsRow)
{
row[cell.Start.Column - 1] = cell.Text;
}
}
return tbl;
}
}
For both the Excel files , same process can be adopted, and it will give you the desired results.

Getting Excel data to SQL table with EPPlus and SqlBulkCopy

I already have added the EPPlus library to my solution. I just can't seem to figure out how to get my excel data it into a datatable that will allow my bulkcopy to work. The below code doesn't work. Can anyone help me massage this into place? Thank you in advance for your assistance. I have edited this after comments from 'mason' below.
try
{
//// open file
var excel = Request.Files[0];
var file = Path.Combine(Server.MapPath("~/Uploads/"), excel.FileName);
var sqlConnectionString = ConfigurationManager.ConnectionStrings["MyDB"].ToString();
// Get the datatable from procedure on Utility.cs page
var datapush = Utility.ImportToDataTable(file, "Sheet1");
// open connection to sql and use bulk copy to write excelData to my table
using (var destinationConnection = new SqlConnection(sqlConnectionString))
{
destinationConnection.Open();
using (var bulkCopy = new SqlBulkCopy(destinationConnection))
{
bulkCopy.DestinationTableName = "MYTABLE";
bulkCopy.ColumnMappings.Add("CODE", "code");
bulkCopy.ColumnMappings.Add("TITLE", "title");
bulkCopy.ColumnMappings.Add("LAST_NAME", "last_name");
bulkCopy.ColumnMappings.Add("FIRST_NAME", "first_name");
bulkCopy.WriteToServer(datapush);
}
}
}
and here is the code on the Utility.cs page based on Mason's suggested link:
public class Utility
{
public static DataTable ImportToDataTable(string FilePath, string SheetName)
{
DataTable dt = new DataTable();
FileInfo fi = new FileInfo(FilePath);
// Check if the file exists
if (!fi.Exists)
throw new Exception("File " + FilePath + " Does Not Exists");
using (ExcelPackage xlPackage = new ExcelPackage(fi))
{
// get the first worksheet in the workbook
ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets[SheetName];
// Fetch the WorkSheet size
ExcelCellAddress startCell = worksheet.Dimension.Start;
ExcelCellAddress endCell = worksheet.Dimension.End;
// create all the needed DataColumn
for (int col = startCell.Column; col <= endCell.Column; col++)
dt.Columns.Add(col.ToString());
// place all the data into DataTable
for (int row = startCell.Row; row <= endCell.Row; row++)
{
DataRow dr = dt.NewRow();
int x = 0;
for (int col = startCell.Column; col <= endCell.Column; col++)
{
dr[x++] = worksheet.Cells[row, col].Value;
}
dt.Rows.Add(dr);
}
}
return dt;
}
}
Currently when I run the code and F11 the bug is on the Utility.cs page. right after "// get the first worksheet in the workbook"
ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets[SheetName];
returns null and the next line of code
ExcelCellAddress startCell = worksheet.Dimension.Start;
stops everything and kicks the following error "{"Object reference not set to an instance of an object."}"

Find Cell HeaderName in openXML

I m using OfficeOpenXML to import Excel data into Database. here is the code sample that I am using for my task.But I want to have HeaderName while looping through each cell in row As I have to make some modifications to columns.
Any help suggestion appreciated. Thanks!
var ws = pck.Workbook.Worksheets.First();
var pck = new OfficeOpenXml.ExcelPackage();
for (var rowNum = 3; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var wsRow = ws.Cells[rowNum, 1, rowNum, DtCommon.Tables[0].Columns.Count-1];
var row = tblResult.NewRow();
foreach (var cell in wsRow)
{
row[cell.Start.Column - 1] = cell.Text; //Find HeaderName here based on cell index
}
tblResult.Rows.Add(row);
}
I've posted this suggestion in the comments, but as it helped, I'm posting it as an answer.
By looking at Your code, I suppose You're using ExcelPackage library.
If so, I suppose You may be able to get the first cell in each column by writing:
foreach (var cell in wsRow)
{
// code to get the header cell
var header = ws.Cell(1, cell.Column);
// rest of your code here
// ...
}

Export DataTable to Excel with Open Xml SDK in c#

My program have ability to export some data and DataTable to Excel file (template)
In the template I insert the data to some placeholders. It's works very good, but I need to insert a DataTable too...
My sample code:
using (Stream OutStream = new MemoryStream())
{
// read teamplate
using (var fileStream = File.OpenRead(templatePath))
fileStream.CopyTo(OutStream);
// exporting
Exporting(OutStream);
// to start
OutStream.Seek(0L, SeekOrigin.Begin);
// out
using (var resultFile = File.Create(resultPath))
OutStream.CopyTo(resultFile);
Next method to exporting
private void Exporting(Stream template)
{
using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true }))
{
// Replace shared strings
SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
IEnumerable<Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<Text>();
DoReplace(sharedStringTextElements);
// Replace inline strings
IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
foreach (var worksheet in worksheetParts)
{
DoReplace(worksheet.Worksheet.Descendants<Text>());
}
int z = 40;
foreach (System.Data.DataRow row in ExcelWorkXLSX.ToOut.Rows)
{
for (int i = 0; i < row.ItemArray.Count(); i++)
{
ExcelWorkXLSX.InsertText(workbook, row.ItemArray.ElementAt(i).ToString(), getColumnName(i), Convert.ToUInt32(z)); }
z++;
}
}
}
}
But this fragment to output DataTable slooooooooooooooooooooooowwwwwww...
How can I export DataTable to Excel fast and truly?
I wrote this quick example. It works for me. I only tested it with one dataset with one table inside, but I guess that may be enough for you.
Take into consideration that I treated all cells as String (not even SharedStrings). If you want to use SharedStrings you might need to tweak my sample a bit.
Edit: To make this work it is necessary to add WindowsBase and DocumentFormat.OpenXml references to project.
Enjoy,
private void ExportDataSet(DataSet ds, string destination)
{
using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
foreach (System.Data.DataTable table in ds.Tables) {
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
{
sheetId =
sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
sheets.Append(sheet);
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
foreach (System.Data.DataColumn column in table.Columns) {
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (System.Data.DataRow dsrow in table.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
eburgos, I've modified your code slightly because when you have multiple datatables in your dataset it was just overwriting them in the spreadsheet so you were only left with one sheet in the workbook. I basically just moved the part where the workbook is created out of the loop. Here is the updated code.
private void ExportDSToExcel(DataSet ds, string destination)
{
using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
uint sheetId = 1;
foreach (DataTable table in ds.Tables)
{
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
{
sheetId =
sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
sheets.Append(sheet);
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
foreach (DataColumn column in table.Columns)
{
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in table.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
I also wrote a C#/VB.Net "Export to Excel" library, which uses OpenXML and (more importantly) also uses OpenXmlWriter, so you won't run out of memory when writing large files.
Full source code, and a demo, can be downloaded here:
Export to Excel
It's dead easy to use.
Just pass it the filename you want to write to, and a DataTable, DataSet or List<>.
CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx");
And if you're calling it from an ASP.Net application, pass it the HttpResponse to write the file out to.
CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx", Response);
I wrote my own export to Excel writer because nothing else quite met my needs. It is fast and allows for substantial formatting of the cells. You can review it at
https://openxmlexporttoexcel.codeplex.com/
I hope it helps.
You could try taking a look at this libary. I've used it for one of my projects and found it very easy to work with, reliable and fast (I only used it for exporting data).
http://epplus.codeplex.com/
You can have a look at my library here. Under the documentation section, you will find how to import a data table.
You just have to write
using (var doc = new SpreadsheetDocument(#"C:\OpenXmlPackaging.xlsx")) {
Worksheet sheet1 = doc.Worksheets.Add("My Sheet");
sheet1.ImportDataTable(ds.Tables[0], "A1", true);
}
Hope it helps!
I tried accepted answer and got message saying generated excel file is corrupted when trying to open. I was able to fix it by doing few modifications like adding below line end of the code.
workbookPart.Workbook.Save();
I have posted full code # Export DataTable to Excel with Open XML in c#
I wanted to add this answer because I used the primary answer from this question as my basis for exporting from a datatable to Excel using OpenXML but then transitioned to OpenXMLWriter when I found it to be much faster than the above method.
You can find the full details in my answer in the link below. My code is in VB.NET though, so you'll have to convert it.
How to export DataTable to Excel

Categories

Resources