Data validation for combo box range of column using EPPlus - c#

I using EPplus for exporting excel.i have to give a combo box.Currently i have given the range manually.but i want this dropdown for entire column.Can any one tell how to do this
ExcelPackage excel = new ExcelPackage();
ExcelWorksheet P = excel.Workbook.Worksheets.Add("Pass");
var droplist = P.DataValidations.AddListValidation("C2:C50000");
droplist.Formula.Values.Add("a");
droplist.Formula.Values.Add("b");

The following line should work:
var droplist = P.DataValidations.AddListValidation("C:C");
EDIT:
Alternatively, you can set ExcelRange to MaxRows. You can then define the range then skipping the first or first n rows. Code below skips first row:
var range = ExcelRange.GetAddress(2, 3, ExcelPackage.MaxRows, 3);
var val = p.DataValidations.AddListValidation(excelRange);
Where GetAddress is:
public static string GetAddress(int FromRow, int FromColumn, int ToRow, int ToColumn)
ExcelCellBase has the extension method to get an address: GetAddress
ExcelPackage has a public const MaxRows (1048576)

Related

Get excel row sum into variable instead of cell

I'm trying to retrieve the sum of a row from an excel document.
When googling this all of the solutions involved writing a =SUM(1:1) like formula into a cell and then writing the result to a variable.
Since I don't want to edit the excel file i was wondering if it's possible to retrieve the sum of a row range directly into a variable without the pit stop?
Thanks in Advance!
This will save the sum of the values of two cells into "myVariable"
Dim myWB As Workbook
Set myWB = ActiveWorkbook
Set ws = myWB.Sheets(1)
Dim myVariable As Variant
myVariable = ws.Cells(1,1).Value + ws.Cells(2,1).Value
If you are using xlsx files you can use this cool lib :
https://closedxml.codeplex.com/documentation
It uses DocumentFormat.OpenXml you can install closedXml and dependancies with this command :
Install-Package ClosedXML
Example to do a sum on the first row :
//open the excel file
var wb = new XLWorkbook("excel File path");
//get the first worksheel
var ws = wb.Worksheet(0);
var lineNumber = 0;
var startColumn = 0;
var endColumn = 10;
var cells = ws.Range(lineNumber, startColumn, lineNumber, endColumn).Cells().ToList();
var sum = cells.Sum(xlCell => (int) xlCell.Value);

What is the analogue to Excel Interop's Worksheet.UsedRange.Rows in Spreadsheet Light?

Using Excel Interop, you can get the count of rows in use by a sheet like so:
_xlSheet.UsedRange.Rows
(where "_xlSheet" is an Excel.Worksheet).
What is the equivalent in Spreadsheet Light?
You can add a worksheet like so:
var sl = new SLDocument();
. . .
sl.AddWorksheet("SheetsToTheWind");
...but how can you then access that worksheet to interrogate it for its used row count?
After adding the worksheet it is active as well. That means that you can get the WorksheetStatistics from the method GetWorksheetStatistics. That statistics instance has a NumberOfRows property:
// NOTE: The information is only current at point of retrieval.
var stats = sl.GetWorksheetStatistics();
var rowcount = stats.NumberOfRows;
If you want to to know the rowcount of all sheets you can do:
foreach(var name in sl.GetSheetNames())
{
sl.SelectWorksheet(name);
var stats = sl.GetWorksheetStatistics();
var rowcount = stats.NumberOfRows;
Trace.WriteLine(String.Format("sheet '{0}' has {1} rows", name, rowcount));
}
Adding to rene's answer:
Since accessing the Statistics' NumberOfRows property does not automagically update (you must call GetWorksheetStatistics() each time to get the up-to-date stats), I found it handy to write this helper method:
private int GetCurrentNumberOfRows()
{
// This reference to "sl" assumes that you have declared "SLDocument sl;" and
// instantiated it ("sl = new SLDocument();"), perhaps in your class' constructor
var stats = sl.GetWorksheetStatistics();
return stats.NumberOfRows;
}
..and then call it as needed:
int lastRow = GetCurrentNumberOfRows();

How to store a column of data in excel to string[] in C#

I have a string[] member like this:
private string[] mStrings = null;
and code in the constructor like this:
Excel.Application excelApp = new Excel.Application();
Excel.Workbook excelWorkBook = excelApp.Workbooks.Open(excel_file_path);
Excel.Worksheet excelWorkSheet = (Excel.Worksheet)excelWorkBook.Sheets[2]; // I get the data from the second sheet
I want to store data in column F to mStrings, so I wrote code like this:
mStrings = excelWorkSheet.Columns["F"].Value2;
this code is wrong, so what is the right code? Thanks!
There might be a better way of solving this, but i managed to solve your problem by getting UsedRange in the column then iterating over the column with a simple 'for' loop, storing the values to a List of strings and then passing the List to an array of strings
string[] mColumn = null;
List<string> mlstColumn = new List<string>();
// get used range of column F
Range range = excelWorkSheet.UsedRange.Columns["F", Type.Missing];
// get number of used rows in column F
int rngCount = range.Rows.Count;
// iterate over column F's used row count and store values to the list
for (int i = 1; i <= rngCount; i++)
{
mlstColumn.Add(excelWorkSheet.Cells[i, "F"].Value.ToString());
}
// List<string> --> string[]
mColumn = mlstColumn.ToArray();
// remember to Quit() or the instance of Excel will keep running in the background
excelApp.Quit();

How to append a new row to an Excel file using C# and ClosedXML?

I should append a new row to an existing Excel file. The task consists of two parts:
Add to non-existing file (works well).
Add to existing file (doesn't work: it doesn't make NEW record, displaying only the old record from "else" body).
Here is my code:
private static void ExportToEXCEL(DataTable dt, string paymentStoryPath)
{
if (File.Exists(paymentStoryPath))
{
XLWorkbook currentWorkbook = new XLWorkbook(paymentStoryPath);
IXLWorksheet currentWsh = currentWorkbook.Worksheet("Payment history");
//IXLCell cellForNewData = index.Cell(index.LastRowUsed().RowNumber() + 1, 1);
IXLRow rowForNewData = currentWsh.Row(currentWsh.LastRowUsed().RowNumber()+1);
rowForNewData.InsertRowsBelow(1);
rowForNewData.Value = dt;
currentWorkbook.Save();
}
else
{
//not exist
XLWorkbook wb = new XLWorkbook();
wb.Worksheets.Add(dt, "Payment history");
wb.SaveAs(paymentStoryPath);
}
}
What is wrong and what should I change in my code?
To add a DataTable use the InsertTable() method:
XLWorkbook currentWorkbook = new XLWorkbook(paymentStoryPath);
IXLWorksheet currentWsh = currentWorkbook.Worksheet("Payment history");
IXLCell cellForNewData = currentWsh.Cell(currentWsh.LastRowUsed().RowNumber() + 1, 1);
cellForNewData.InsertTable(dt);
currentWorkbook.Save();
I've got the following code from one of my projects that inserts a DataTable into Excel.
//insert rows below a range from the cell going table rows down
ws.Range(
cell.Address.RowNumber
, cell.Address.ColumnNumber
, cell.Address.RowNumber + DocDataSet.Tables[tableNo].Rows.Count
, cell.Address.ColumnNumber)
.InsertRowsBelow(DocDataSet.Tables[tableNo].Rows.Count);
//InsertData returns a range covering the inserted data
var ra = ws.Cell(cell.Address.RowNumber, cell.Address.ColumnNumber)
.InsertData(DocDataSet.Tables[tableNo].AsEnumerable());
//apply the style of the table token cell to the whole range
ra.Style = cell.Style;
Its been a while since I wrote it, but as far as I know the idea is, create a range that will cover the rows and columns that will be populated. The Cell object has a InsertData method that can take any IEnumerable source.
You might not need the ws.Range line, I was inserting into a template so I had to create the space first.
I took #raidri example and took it one step further where I have an extension method to handle this.
public static class Extensions
{
public static void ToExcelFile(this DataTable dataTable, string filename, string worksheetName = "Sheet1")
{
using(var workbook = new XLWorkbook())
{
workbook.Worksheets.Add(dataTable, worksheetName);
workbook.SaveAs(filename);
}
}
}
Use
myDataTable.ToExcelFile(#"C:\temp\myFile.xlsx");

How to add values to a spreadsheet from a dictionary?

I have a template spreadsheet document that has two columns, Server Name and IP Address.
How can I populate the spreadsheet so that each dictionary key goes in its own cell in the Server column and the corresponding value goes in the cell next to it in the IP column?
I am using the EPPlus library but couldn't find anything on the topic.
Below is what I found and tried, but its for lists
using (ExcelPackage package = new ExcelPackage(_fileInfo))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
for (int i = 0; i < listOfIPs.Count; i++)
{
worksheet.Cells[i + 2, 1].Value = listOfIPs[i];
}
package.Save();
}
I am not familiar with EPPlus, therefore I am not sure how you get the reference to the active sheet - you need to figure out this bit though once that's done pure C# with a bit of knowledge about VBA model and you can easily avoid any iterations to get contents of your dictionary to a spreadsheet:
// create a sample dictionary and fill it
Dictionary<string, string> myCol = new Dictionary<string, string>();
myCol.Add("server1", "ip1");
myCol.Add("server2", "ip2");
// grab a reference to the active Sheet
// this may vary depending on what framework you are using
Worksheet ws = Globals.ThisWorkbook.ActiveSheet as Worksheet;
// create a Range variable
Range myRange;
// Transpose the keys to column A
myRange = ws.get_Range("A1");
myRange.get_Resize(myCol.Keys.ToArray().Count(),1).Value =
ws.Parent.Parent.Transpose(myCol.Keys.AsEnumerable().ToArray());
// transpose the Values to column B
myRange = ws.get_Range("B1");
myRange.get_Resize(myCol.Values.ToArray().Count(), 1).Value =
ws.Parent.Parent.Transpose(myCol.Values.AsEnumerable().ToArray());
Debugging results as expected
With EPPlus I think you can do it like this (untested)
using (ExcelPackage package = new ExcelPackage(file))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("test");
worksheet.Cells["A1"].LoadFromCollection(myColl, true, OfficeOpenXml.Table.TableStyles.Medium);
package.Save();
}
More details on VBA Collections iterations and printing to Sheet # vba4all.com
You can just access the keys of a dictionary and iterate over them just like you are iterating over the list.
var foo = new Dictionary<string, string>(); // populate your dictionary
foreach(var key in foo.Keys)
{
var value = foo[key];
// do stuff with 'key' and 'value', like put them into the excel doc
}

Categories

Resources