How to add values to a spreadsheet from a dictionary? - c#

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
}

Related

Data validation for combo box range of column using EPPlus

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)

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();

Using OpenXML, how can I associate a list for data validation

I am processing an .xlsm file and need to know how to use a list on another sheet for data validation using openXML and C#.
To start, I have a .xlsm file with two empty sheets and macros in it. In my program I open the file, Create the column header on Sheet1 then create the validation list on sheet2. So, after I run my program Sheet1 "A1" contains the text "Color" and Sheet2 "A1:A4" contains "Blue","Green","Red","Yellow". I get this far just fine.
I would like to make it so there is a dropdown list in all cells of column "A" on sheet1 that contains each of the 4 colors and enforces them as the only input. In Microsoft Excel this is done by going to the "Data" tab, selecting "Data Validation" selecting "List" and highlighting the cells you want to use. I need to make this association programmatically.
The (Desired) XML that Microsoft Excel creates if I do it manually is this:
<extLst>
<ext uri="{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main">
<x14:dataValidations count="1" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
<x14:dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1">
<x14:formula1>
<xm:f>'Validation Data'!$A$1:$A$4</xm:f>
</x14:formula1>
<xm:sqref>A1:A1048576</xm:sqref>
</x14:dataValidation>
</x14:dataValidations>
</ext>
</extLst>
The following method and results is something I tried. It may give a better Idea of what I'm trying to do.
Here, I pass in "'Sheet2'!$A$1:$A$4" as the "validationListCells" parameter. This represents the cells in "Sheet2" that, in this example, would contain the color names "Red", "Green"...etc.
I pass in "A2:A1048576" as the "cellsToValidate" parameter. This represents all cells of Sheet1 column "A", on which I want to enforce validation.
I pass "Sheet1" as the worksheetName parameter.
private void InsertValidation(String worksheetName, String validationListCells, String cellsToValidate)
{
DataValidations dataValidations1 = new DataValidations() { Count = (UInt32Value)1U };
DataValidation dataValidation1 = new DataValidation()
{
Formula1 = new Formula1(validationListCells),
Type = DataValidationValues.List,
ShowInputMessage = true,
ShowErrorMessage = true,
SequenceOfReferences = new ListValue<StringValue>() { InnerText = cellsToValidate }
};
dataValidations1.Append(dataValidation1);
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(_documentPath, true))
{
WorksheetPart worksheetPart = GetWorksheetPartByName(spreadSheet, worksheetName);
worksheetPart.Worksheet.Append(dataValidations1);
worksheetPart.Worksheet.Save();
}
}
It results in this XML in Sheet1.xml. Which causes an error in Excel.
<x:dataValidations count="1">
<x:dataValidation type="list" showInputMessage="1" showErrorMessage="1" sqref="A2: A1048576">
<x:formula1>'Sheet2'!$A$1:$A$5</x:formula1>
</x:dataValidation>
</x:dataValidations>
It looks like I may be on the right track since it is beginning to resemble the xml created by Excel, but I'm completely new to openXML and I'm finding little about this topic on the net.
Thanks in advance!
For anyone else in need of this..the code below worked for me.
I put in there user3251089's variable names.
In general, when I try to programmatically create an excel "feature" I manually make a really basic excel that has in it that feature (delete extra sheets too). Then I reflect the code and try to make it prettier.
hope it serves to someone!
using Excel = DocumentFormat.OpenXml.Office.Excel;
using X14 = DocumentFormat.OpenXml.Office2010.Excel;
.....
Worksheet worksheet = worksheetPart.Worksheet;
WorksheetExtensionList worksheetExtensionList = new WorksheetExtensionList();
WorksheetExtension worksheetExtension = new WorksheetExtension() { Uri = "{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}" };
worksheetExtension.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
X14.DataValidations dataValidations = new X14.DataValidations() { Count = (UInt32Value)3U };
dataValidations.AddNamespaceDeclaration("xm", "http://schemas.microsoft.com/office/excel/2006/main");
//sites validation
dataValidations.Append(new X14.DataValidation()
{
Type = DataValidationValues.List,
AllowBlank = true,
ShowInputMessage = true,
ShowErrorMessage = true,
DataValidationForumla1 = new X14.DataValidationForumla1() { Formula = new Excel.Formula(validationListCells) },
ReferenceSequence = new Excel.ReferenceSequence(cellsToValidate)
});
worksheetExtension.Append(dataValidations);
worksheetExtensionList.Append(worksheetExtension);
worksheet.Append(worksheetExtensionList);
worksheet.Save();

Categories

Resources