DataTable
或任何您想要的收藏类型。我猜这将使导出到Excel时更加容易。
在
Catergory
类,它有一个
Articleâs
. 每个
Article
表示集合(Excel电子表格)中的一行。每个
文章
ArticleReviews
打电话
Reviews
. 正如你所说的
我的问题之一是Reviewer Point列被动态更改,
另一个可能是4或5个审核点。
这听起来好像每个人都有很多评论员
文章
此外,并非所有的审稿人都会对所有的文章进行审稿。考虑到这一点以及将数据展平的要求,将意味着为每个审阅者创建一列。此外,我假设只列出审阅其中一篇文章的审阅者,否则,为每个审阅者创建一个列将很简单。我猜目标是只让专栏中的评论者至少审阅了一(1)篇文章。
话虽如此,我猜第一个问题是计算出我们需要多少列评论人,这些评论人的名字是什么。我们需要一些方法来确定哪个列属于哪个审阅者。我正在使用
Reviewer
方便的是
Category
类有一个
Artlicle
s如果创建了一个方法,该方法遍历每一篇文章,然后遍历每一篇文章的评论,并收集所有的审阅者并忽略重复项,那么这将为我们提供需要添加列的审阅者列表。如果该方法返回了
审核人
我们不仅可以使用它来确定需要多少列,还可以确定这些列的名称。
其中一个可能的问题是列顺序可能不可预测。根据第一篇文章,将确定列的顺序。因此,我建议对列进行一些排序,以保持一定的顺序。
我加了一个班
审核人
这将有助于对列名进行排序和比较。这是一个简单的问题
审核人
下面是一节课。注意
compareTo
排序所使用的方法。它按审阅者ID进行排序。这将保持相同的列顺序。
public class Reviewer : IComparable<Reviewer> {
public int ReviewerID { get; set; }
public string ReviewerName { get; set; }
public Reviewer() {
}
public Reviewer(int reviewerID, string reviewerName) {
ReviewerID = reviewerID;
ReviewerName = reviewerName;
}
public override string ToString() {
return "ReviewerID: " + ReviewerID.ToString();
}
public override bool Equals(object obj) {
return this.ReviewerName.Equals(((Reviewer)obj).ReviewerName);
}
public override int GetHashCode() {
return ReviewerName.GetHashCode();
}
public int CompareTo(Reviewer other) {
return this.ReviewerID.CompareTo(other.ReviewerID);
}
}
ArticleReview
审核人
对象来定义审阅者。
public class ArticleReview {
public long ArticleId { get; set; }
public Reviewer TheReviewer { get; set; }
public int ReviewPoint { get; set; }
public ArticleReview() {
}
public ArticleReview (long articleId, Reviewer reviewerId, int reviewPoint) {
ArticleId = articleId;
TheReviewer = reviewerId;
ReviewPoint = reviewPoint;
}
}
接下来是
文章
班级。它保存了那篇文章的所有评论。似乎有一列叫做“平均点”。这看起来像是从审查中计算出来的值。因此,我想这对政府来说是方便的
文章
文章
public class Article {
public long ArticleId { get; set; }
public string ArticleTitle { get; set; }
public int NumberOfComment { get; set; }
public int NumberOfView { get; set; }
public virtual ICollection<ArticleReview> Reviews { get; set; }
public Article() {
}
public Article(long articleId, string articleTitle, int numberOfComment, int numberOfView, ICollection<ArticleReview> reviews) {
ArticleId = articleId;
ArticleTitle = articleTitle;
NumberOfComment = numberOfComment;
NumberOfView = numberOfView;
Reviews = reviews;
}
public decimal GetAverage() {
if (Reviews.Count <= 0)
return 0;
decimal divisor = Reviews.Count;
int totPoints = 0;
foreach (ArticleReview review in Reviews) {
totPoints += review.ReviewPoint;
}
return totPoints / divisor;
}
}
最后
类别
班上有所有的学生
文章
s我们需要在这个类中完成前面描述的所有列内容。第一部分是获得一个
List<Reviewer>
没有副本。这将需要遍历所有文章,然后遍历每篇文章中的所有评论。在这个过程中,我们可以检查审阅者并创建一个所有用户的非重复列表。代码将创建一个新的空
然后循环阅读每一篇文章,循环阅读每一篇评论。检查审阅者是否已经在列表中,如果没有,则添加他们,否则忽略重复的审阅者。对列表进行排序以保持列顺序,然后返回。
我猜这个列表可以用很多方法来解决专栏的难题。在本例中,另一个方法被添加到
类别
班级。这个
GetDataTable
方法返回一个
数据表
根据文章中的数据。首先,将前四列添加到表中,标题为#of view、#of component和Average point。接下来,循环所有审阅者以添加审阅者列。审阅者名称用作列名。这就是我们在添加数据时识别哪个列属于哪个审阅者的方式。
最后,通过每个
文章
添加数据。每篇文章创建一个新行。行中的前三列可以设置为Title、view、comment和Average。接下来,我们循环浏览所有评论。每次审查
targetName
public class Category {
public long CategoryId { get; set; }
public string CategoryTitle { get; set; }
//...
public virtual ICollection<Article> Articles { get; set; }
public Category() {
}
public Category(long categoryId, string categoryTitle, ICollection<Article> articles) {
CategoryId = categoryId;
CategoryTitle = categoryTitle;
Articles = articles;
}
public DataTable GetDataTable() {
List<Reviewer> allReviewers = GetNumberOfReviewers();
DataTable dt = new DataTable();
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("#ofView", typeof(long));
dt.Columns.Add("#ofComment", typeof(long));
dt.Columns.Add("Average point", typeof(decimal));
foreach (Reviewer reviewer in allReviewers) {
dt.Columns.Add(reviewer.ReviewerName, typeof(long));
}
foreach (Article article in Articles) {
DataRow newRow = dt.NewRow();
newRow["Title"] = article.ArticleTitle;
newRow["#ofView"] = article.NumberOfView;
newRow["#ofComment"] = article.NumberOfComment;
newRow["Average point"] = article.GetAverage();
foreach (ArticleReview review in article.Reviews) {
string targetName = review.TheReviewer.ReviewerName;
for (int i = 4; i < dt.Columns.Count; i++) {
if (targetName == dt.Columns[i].ColumnName) {
newRow[review.TheReviewer.ReviewerName] = review.ReviewPoint;
break;
}
}
}
dt.Rows.Add(newRow);
}
return dt;
}
private List<Reviewer> GetNumberOfReviewers() {
// we need a list of all the different reviewers
List<Reviewer> reviewers = new List<Reviewer>();
foreach (Article article in Articles) {
foreach (ArticleReview review in article.Reviews) {
if (!reviewers.Contains(review.TheReviewer)) {
reviewers.Add(review.TheReviewer);
}
}
}
reviewers.Sort();
return reviewers;
}
}
把这些放在一起,下面的代码创建一些数据来演示。然后,
用作
DataSource
到
DataGridView
DataTable dt;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
Category cat = new Category();
cat.CategoryId = 1;
cat.CategoryTitle = "Category 1";
cat.Articles = GetArticles();
dt = cat.GetDataTable();
dataGridView1.DataSource = dt;
}
private List<Article> GetArticles() {
List<Article> articles = new List<Article>();
Article art = new Article(1, "Article 1 Title", 10, 1200, GetReviews(1));
articles.Add(art);
art = new Article(2, "Article 2 Title", 32, 578, GetReviews(2));
articles.Add(art);
art = new Article(3, "Article 3 Title", 15, 132, GetReviews(3));
articles.Add(art);
art = new Article(4, "Article 4 Title", 13, 133, GetReviews(4));
articles.Add(art);
art = new Article(5, "Article 5 Title", 55, 555, GetReviews(5));
articles.Add(art);
art = new Article(6, "Article 6 Title", 0, 0, GetReviews(6));
articles.Add(art);
return articles;
}
private ICollection<ArticleReview> GetReviews(int reviewId) {
ICollection<ArticleReview> reviews = new List<ArticleReview>();
ArticleReview ar;
Reviewer Reviewer1 = new Reviewer(1, "Reviewer 1");
Reviewer Reviewer2 = new Reviewer(2, "Reviewer 2");
Reviewer Reviewer3 = new Reviewer(3, "Reviewer 3");
Reviewer Reviewer4 = new Reviewer(4, "Reviewer 4");
Reviewer Reviewer5 = new Reviewer(5, "Reviewer 5");
Reviewer Reviewer6 = new Reviewer(6, "Reviewer 6");
switch (reviewId) {
case 1:
ar = new ArticleReview(1, Reviewer1, 15);
reviews.Add(ar);
ar = new ArticleReview(1, Reviewer2, 35);
reviews.Add(ar);
ar = new ArticleReview(1, Reviewer3, 80);
reviews.Add(ar);
ar = new ArticleReview(1, Reviewer5, 55);
reviews.Add(ar);
ar = new ArticleReview(1, Reviewer6, 666);
reviews.Add(ar);
break;
case 2:
ar = new ArticleReview(2, Reviewer1, 50);
reviews.Add(ar);
ar = new ArticleReview(2, Reviewer2, 60);
reviews.Add(ar);
ar = new ArticleReview(2, Reviewer3, 40);
reviews.Add(ar);
break;
case 3:
ar = new ArticleReview(3, Reviewer1, 60);
reviews.Add(ar);
ar = new ArticleReview(3, Reviewer2, 60);
reviews.Add(ar);
ar = new ArticleReview(3, Reviewer3, 80);
reviews.Add(ar);
break;
case 4:
ar = new ArticleReview(4, Reviewer1, 30);
reviews.Add(ar);
ar = new ArticleReview(4, Reviewer2, 70);
reviews.Add(ar);
ar = new ArticleReview(4, Reviewer3, 70);
reviews.Add(ar);
break;
case 5:
ar = new ArticleReview(5, Reviewer3, 44);
reviews.Add(ar);
break;
case 6:
break;
default:
break;
}
return reviews;
}
使用EPPlus,下面是使用
并导出
数据表
到Excel工作表。
private void btn_ExportToExcel_Click(object sender, EventArgs e) {
using (var p = new ExcelPackage()) {
var ws = p.Workbook.Worksheets.Add("MySheet");
ws.Cells["A1"].LoadFromDataTable(dt, true);
p.SaveAs(new FileInfo(@"D:\Test\ExcelFiles\EpplusExport.xlsx"));
}
}