将列和行从IQueryable对象插入电子表格

时间:2019-04-01 18:14:40

标签: c# linq

如何从Queryable对象插入数据的列和行?下面列出了我到目前为止所拥有的。看来我可以将列名称放入电子表格中,但是我不确定如何使用我编写的方法插入值。


private IQueryable<ShippingRequest> GetRecordsFromDatabase()
{
   var CurrentUserId = (int)Session["UserId"];

   var results = db.ShippingRequests
                .Where(r => r.UserId == CurrentUserId);

   return results;
}
//Create the WorkSheet
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add("FedEx Rates");

//get columns of table
var columnNames = typeof(ShippingRequest).GetProperties()
.Select(x => x.Name)
.ToArray();

int i = 0;
//Adding column name to worksheet
foreach (var col in columnNames)
{
    i++;
    worksheet.Cells[1, i].Value = col;
}

//Adding records to worksheet
int j;
for (i = 0; i<columnNames.Length; i++)
{
    foreach (var item in db)
    {
        worksheet.Cells[i + 2, j + 1].Value = ???; //Not sure how to get this value
    }
}

1 个答案:

答案 0 :(得分:1)

因此,您获取了一些数据作为序列,并且希望将该序列的每个元素作为一行添加到表中。这些列都是ShippingRequests的所有可读公共属性。

让我们创建一个通用解决方案,该解决方案将添加任何列序列并显示某个类的任何对象序列。

通常,列的名称不必与所有属性的名称一一对应。有时您只想显示一些属性。有时您想创建不同的列名或显示不同的值。也许您不想将数据显示到excel工作表中,而是显示在另一种表中?

从表类定义列的可重用类可能类似于:

class Column<TSource>
{
    public int Index {get; set;}
    public string Name {get; set;}

    public Func<TSource, object> PropertyValueSelector {get; set;}

    public object GetValue(TSource source)
    {
        return this.PropertyValueSelector(source);
    }

    ... // possible other properties, like: IsVisible, IsSortable, DisplayFormat?
}

显然,您想为ShippingRequests创建一个列序列,其中包含ShippingRequest的每个公共属性。列的名称是属性的标识符。索引并不重要。

以下函数将创建您的列序列:

public static IEnumerable<Column<TSource>> CreateColumns<TSource>() 
       where TSource : class
{
    return typeof(TSource).GetProperties()
        .Where(property => property.CanRead) // they must be at least readable
        .Select( (propertyInfo, index) => new Column<TSource>
        {
            Index = index,
            Name = propertyInfo.Name,

            PropertyValueSelector = source => propertyInfo.GetValue(source);
        });
}

获得数据和列后,我们便可以填写您的工作表:

void Fill<TSource>(this ExcelWorkSheet workSheet,
     IEnumerable<Column<TSource>> columns,
     IEnumerable<TSource> sourceData)
{
    // TODO: clear worksheet?
    //Add column names to worksheet
    foreach (var column in columns)
    {
        worksheet.Cells[1, column.Index].Value = column.Name;
    }

    // add the source data
    int nextRowIndex = 2;
    foreach (var rowData in sourceData)
    {
        AddRow(workSheet, nextRowIndex, columns, rowData);
        ++nextRowIndex;
    }
}

void AddRow<TSource> AddRow<TSource>(this ExcelWorkSheet workSheet,
     int rowIndex,
     IEnumerable<Column<TSource>> columns,
     TSource rowData)
{
    foreach (var column in columns)
    {
        var value = column.GetValue(rowData);
        worksheet.Cells[rowIndex, column.Index].Value = value;
    }
}

现在,有了这个,您的代码就很简单了:

var workSheet = ...
var columns = ...
var data = ...
worksheet.Fill(columns, data);

在您的情况下:

var worksheet = excelPackage.Workbook.Worksheets.Add("FedEx Rates");
var columns = CreateColumns<ShippingRequest>().ToList();
var shippingRequests = GetShippingRequests();
worksheet.Fill(columns, shippingRequests);
// Bam! Done!

令人高兴的是,您可以使用该代码用任何类的数据填充工作表。

例如,我有一班学生,我想显示100名最年轻学生中的一些列。

// I only want to show the following columns of students:
var studentColumns = new Column<Student>
{ 
    new Column {Index = 1, Name = "Id", PropertyValueSelector = student => student.Id },
    new Column {Index = 3, Name = "Birthday", PropertyValueSelector = student => student.Id }
    new Column {Index = 2, Name = "Student Name", PropertyValueSelector = student =>
        String.Format("{0} {1} {2}", student.FirstName, 
                                     student.MiddleName,
                                     student.FamilyName} },
};

// I only want 100 youngest students:
var studentsToDisplay = GetStudents()
    .OrderByDescending(student => student.BirthDay)
    .Take(100)
    .ToList();

// filling the worksheet is only two lines:
var worksheet = excelPackage.Workbook.Worksheets.Add("Young Students");
worksheet.Fill(studentColumns, studentsToDisplay);