3

My problem is that I have a list that contains a few strings and inside this list another list of decimals, something like this:

         public class excelInventario
            {
              public excelInventario() { cols = new List<decimal>); }
              public string codigo { get; set; }       
              public string nombre { get; set;}        .
              public List<decimal> cols { get; set; }  //Lista de columnas
              public decimal suma { get; set; }
              public decimal stock { get; set; }
              public decimal diferencia { get; set; }
              public decimal precio { get; set; }
            }

and now I need to put this in Excel. The problem is that when I use the method LoadFromCollection(MyList) the strings appear well in Excel, but the list of decimals is not put correctly, but:

System.Collections.Generic.List`1[System.Decimal].

Can I adapt this method or do I need to use a loop and put "manually" the row values one by one?

I suspect this second option it will be inefficient.

---------------EDIT TO ADD MORE CODE--------------

int tamcolumnas=excelin[0].cols.Count;
using (ExcelPackage package = new ExcelPackage(file))
{
ExcelWorksheet hoja = package.Workbook.Worksheets.Add("Comparativo unidades contadas VS stock");
hoja.Cells["A1"].Value = "CODART";
hoja.Cells["B1"].Value = "NOMBRE";
for(int i=0;i<tamcolumnas;i++)
{ hoja.Cells[1, i+3].Value = "COL"+(i+1); }
var MyList = new List<excelInventario>();
hoja.Cells.LoadFromCollection(MyList,true);
hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast<object>).ToArray()));

in this last line is where fails.

Say:

System.ArgumentOutOfRangeException

The specified argument is outside the range of valid values.

Ion
  • 549
  • 1
  • 11
  • 25

1 Answers1

3

Since those are Lists the closest you can get to automation is the LoadFromArray since those are not true objects. Its not exactly pretty since it requires casting so check for performance hits. Otherwise, it may be best to use plain old loops. Here is what I mean:

[TestMethod]
public void ListOfList_Test()
{
    //http://stackoverflow.com/questions/33825995/how-to-use-loadfromcollection-in-epplus-with-a-list-containing-another-list-insi
    //Throw in some data
    var MyList = new List<TestExtensions.excelInventario>();

    for (var i = 0; i < 10; i++)
    {
        var row = new TestExtensions.excelInventario
        {
            codigo = Path.GetRandomFileName(),
            nombre = i.ToString(),
            cols = new List<decimal> {i, (decimal) (i*1.5), (decimal) (i*2.5)}
        };
        MyList.Add(row);
    }

    //Create a test file
    var fi = new FileInfo(@"c:\temp\ListOfList.xlsx");
    if (fi.Exists)
        fi.Delete();

    int tamcolumnas = 10; // excelin[0].cols.Count;
    using (ExcelPackage package = new ExcelPackage(fi))
    {
        ExcelWorksheet hoja = package.Workbook.Worksheets.Add("Comparativo unidades contadas VS stock");
        hoja.Cells["A1"].Value = "CODART";
        hoja.Cells["B1"].Value = "NOMBRE";
        for (int i = 0; i < tamcolumnas; i++)
        {
            hoja.Cells[1, i + 3].Value = "COL" + (i + 1);
        }
        //var MyList = new List<TestExtensions.excelInventario>();
        hoja.Cells.LoadFromCollection(MyList, true); 
      //hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast<object>).ToArray()));
        hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast<object>().ToArray()));

        package.Save();
    }
}
Ernie S
  • 13,902
  • 4
  • 52
  • 79
  • Ok, looks fine, but the only thing i don´t understandis, what is datatable?? is a varible of DataTable type?? have any data? – Ion Nov 20 '15 at 13:07
  • @Ion Sorry, forgot to explain that. See my edit. It is just a list of your `excelInvertario` objects. – Ernie S Nov 20 '15 at 13:11
  • this give me an error: `System.ArgumentException Column out of range` – Ion Nov 20 '15 at 13:21
  • Humm.. populate the collection with something? See my edit for an complete unit test, hopefully that helps. – Ernie S Nov 20 '15 at 13:30
  • Well, your test unit Works perfect, so i need to see what is wrong when i try to use in my code, sound like something is wrong with the data inside? for what are you using var x? – Ion Nov 20 '15 at 13:37
  • perhaps my problema is when i try to put name of columns in the first row i use this: `int tamcolumnas=excelin[0].cols.Count; hoja.Cells["A1"].Value = "CODART"; hoja.Cells["B1"].Value = "NOMBRE"; for(int i=0;i – Ion Nov 20 '15 at 13:44
  • Ignore var x (took it out). Strange that wouldgive you an argument exception. Edit your question and put more code in there if you can. – Ernie S Nov 20 '15 at 13:48
  • @Ion Seems to work fine for me. I had to make some assumptions, see my edit above. I did have to clean up some of the `()` in your last line. – Ernie S Nov 20 '15 at 14:27
  • Sorry, i don´t see what you change – Ion Nov 20 '15 at 15:07
  • @Ion I put another edit. The only thing I really changed was the improperly closed () in the last line. The other thing to note is I populated `MyList` with content before trying to write it to excel. Other then that, what you have should work. Make sure your objects have proper content. – Ernie S Nov 20 '15 at 15:44
  • Ok, thanks, i allready changed that, but not Works for me. But if I do: `MyList=excelin` and then the line you suggest to me `hoja.Cells[2, 3].LoadFromArrays(MyList.Select((r) => r.cols.Cast().ToArray()));` Finally Works and put the data in Excel, the only problema is that in one column appears in all the rows `System.Collections.Generic.List1[System.Decimal]` So i supose it will be a problema with the data – Ion Nov 20 '15 at 15:57
  • @Ion Glad you got it working. Ok, so it was a matter of setting proper content. And, yes, that problem you are seeing from the `LoadFromCollection` line since it is calling `toString()` on `cols` which is the thrid property of you class `excelInventario`. That is why in my unit test I using 3 in `Cells[2, 3]` instead of using 4 - this will overwrite the third column in excel that contains the `System.Collection.Generic.List1....`. If you comment out the line with `LoadFromArray` and run you will set what I mean in the output. – Ernie S Nov 20 '15 at 16:12
  • well, i have a minium problem, after the cols property i have more propertys in my object(i edited my first post)and put the data of this properties in the 4 column overwriting the data is suposed to go here – Ion Nov 20 '15 at 16:29
  • I have no idea of how to do it properly so finaly i do it the LoadFrormArray() in the 8 column and i hide the 3 column – Ion Nov 20 '15 at 17:23
  • @Ion Ya, I think that is your best approach. Because the list is not at the end you will not able able to do it without some kind of column manipulation. – Ernie S Nov 20 '15 at 18:29