0

I need to create a DataTable from a List of objects of type DetalleHora. This post explains how to accomplish it, creating a column for each property of DetalleHora.

The problem I am facing is that one the properties of DetalleHora is a List of objects of type Hora, which will contain an undefined number of items (that's why I can't do this), and I can't get to iterate through this List so that the resulting DataTable contains a column for each one of the items.

This is the DetalleHora class definition:

class DetalleHora
{
    public int Id { get; set; }
    public string Fecha { get; set; }
    public string Solicitante { get; set; }
    public string Orden { get; set; }
    public string DMR { get; set; }
    public string Descripcion { get; set; }
    public string Operario { get; set; }
    public string Entrada { get; set; }
    public string Salida { get; set; }
    public List<Hora> Horas { get; set; }
    public double TotalHoras { get; set; }
    public string FirmaSolicitante { get; set; }
    public int NumeroSemana { get; set; }
}

This is the Hora class definition:

public class Hora
{
    public int IdTipoHora { get; set; }
    public string Tipo { get; set; }
    public double Cantidad { get; set; }
}

This is what I've doing (per one of the links below):

public DataTable ListToDataTable<T>(List<T> items)
    {
        DataTable dataTable = new DataTable(typeof(T).Name);

        //Get all the properties
        PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (PropertyInfo prop in Props)
        {
            //Setting column names as Property names
            // ******* I need a new column for each item in the List<Hora> Property
            dataTable.Columns.Add(prop.Name);
        }
        foreach (T item in items)
        {
            var values = new object[Props.Length];
            for (int i = 0; i < Props.Length; i++)
            {
                //inserting property values to datatable rows
                // *********** BUT THIS WON'T WORK WHEN PROPERTY IS A LIST<T>
                // I need a new column for each of the items in the List<Hora> Property
                values[i] = Props[i].GetValue(item, null);
            }
            dataTable.Rows.Add(values);
        }
        //put a breakpoint here and check datatable
        return dataTable;
    }

I've looking for a way to determine if a given property is a List of a specific type of object, but none of the folowing approaches seemed to work for me:

garciafigueres
  • 73
  • 1
  • 11
  • how about creating new `DataTable` for `List Horas` and add data to this datatable if the `prop` is a collection. – Mohammed Sajid Jun 08 '20 at 08:19
  • The problem is that I can't determine if `prop` is a collection :( – garciafigueres Jun 08 '20 at 10:42
  • 1
    yes, you can like : `if ((Props[i].GetValue(item, null) is IList list)) {//use list here}`, and you can also here ``ListToDataTable`` recurisvely to build *dataTable* inside another. second solution : declare *Horas* like *array* and use `Props[i].PropertyType.IsArray` – Mohammed Sajid Jun 08 '20 at 10:49

2 Answers2

1

I wanted to convert the List<DetalleHora> to a DataTable in order to use it to generate an Excel file using NPOI libraries in an elegant and efficient way.

However, since I was in a hurry, I discarded the original idea and decided to write the Excel file looping through the Lists' items.

Thanks anyway.

garciafigueres
  • 73
  • 1
  • 11
0

Try Following

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Id", typeof(int));
            dt.Columns.Add("Fecha", typeof(string));
            dt.Columns.Add("Solicitante", typeof(string));
            dt.Columns.Add("Orden", typeof(string));
            dt.Columns.Add("DMR", typeof(string));
            dt.Columns.Add("Description", typeof(string));
            dt.Columns.Add("Operario", typeof(string));
            dt.Columns.Add("Entrada", typeof(string));
            dt.Columns.Add("Salida", typeof(string));
            dt.Columns.Add("IdTipoHora", typeof(int));
            dt.Columns.Add("Tipo", typeof(string));
            dt.Columns.Add("Cantidad", typeof(string));
            dt.Columns.Add("TotalHoras", typeof(double));
            dt.Columns.Add("FirmSolicitante", typeof(string));
            dt.Columns.Add("NumeroSemana", typeof(int));

            List<DetalleHora> detailHoras = new List<DetalleHora>();

            foreach (DetalleHora detailHora in detailHoras)
            {
                foreach (Hora hora in detailHora.Horas)
                {
                    dt.Rows.Add(new object[] {
                        detailHora.Id,
                        detailHora.Fecha,
                        detailHora.Solicitante,
                        detailHora.Orden,
                        detailHora.DMR,
                        detailHora.Description,
                        detailHora.Operario,
                        detailHora.Entrada,
                        detailHora.Salida,
                        hora.IdTipoHora,
                        hora.Tipo,
                        hora.Cantidad,
                        detailHora.TotalHoras,
                        detailHora.FirmaSolicitante,
                        detailHora.NumeroSemana
                    });
                }
            }

        }
    }
    class DetalleHora
    {
        public int Id { get; set; }
        public string Fecha { get; set; }
        public string Solicitante { get; set; }
        public string Orden { get; set; }
        public string DMR { get; set; }
        public string Description { get; set; }
        public string Operario { get; set; }
        public string Entrada { get; set; }
        public string Salida { get; set; }
        public List<Hora> Horas { get; set; }
        public double TotalHoras { get; set; }
        public string FirmaSolicitante { get; set; }
        public int NumeroSemana { get; set; }
    }
    public class Hora
    {
        public int IdTipoHora { get; set; }
        public string Tipo { get; set; }
        public double Cantidad { get; set; }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • I'm afraid this won't work. I need to **add a column to the datatable for each one of the items within List Horas**. I mean, **Horas** can contain up to 120 different items, and I would need a column for every one of them. Thanks. – garciafigueres Jun 07 '20 at 17:04
  • 1
    I did that already. for data to make sense you need to repeat the DetailHora rows with each hora row. – jdweng Jun 07 '20 at 18:10