Crystal Reports 不会显示相关的表格数据

Posted

技术标签:

【中文标题】Crystal Reports 不会显示相关的表格数据【英文标题】:Crystal Reports won't display related table data 【发布时间】:2020-09-04 21:17:25 【问题描述】:

我是 Crystal Reports 的新手,并试图维护其他人的代码 - 请耐心等待。我有一个水晶报表,它与具有 2 个相关 DataTables 的 DataSet 相关联。

我按JurorProfile.JurorPK 分组。在我的组标题中,我显示了来自 JurorProfile 数据表的信息。

在报告详细信息中,我有 RowNumber、JurorQuestionAnswers.QuestionJurorQuestionAnswers.Answer

在我的 c# 代码中,我正在像这样填充数据:


public void SetDataSource(AdoProvider provider, int sessionPK, int jurorPK)

   string commandText;
   AdoQuery query;

   commandText = $@"select j.* from Juror j
   where j.JurorPK in (select JurorFK from SessionJurorLink where SessionFK = @sessionId)
   (jurorPK > 0 ? " and jurorPK = @jurorId" ? "")
   ";
   query = provider.CreateQuery(commandText, null
      , provider.CreateParameter("sessionId", DbType.Int32)
      , provider.CreateParameter("jurorId", DbType.Int32)
   );
   AdoReader jReader = query.ExecuteReader(sessionPK, jurorPK);
   report.Database.Tables["JurorProfile"]
     .SetDataSource((IDataReader)jReader.DataReader);

   commandText = $@"select ... from JurorAnswers ...
   where sessionFK = @sessionId
   (jurorPK > 0 ? " and jurorFK = @jurorId " : "")
   order by JurorFK, Rank, ParentFK, QuestionPK
   ";
   query = provider.CreateQuery(commandText, null
      , provider.CreateParameter("sessionId", DbType.Int32)
      , provider.CreateParameter("jurorId", DbType.Int32)
   );
   AdoReader qaReader = query.ExecuteReader(sessionPK, jurorPK);
   report.Database.Tables["JurorQuestionAnswers"]
     .SetDataSource((IDataReader)qaReader.DataReader);

但是,当我的报告运行时,会显示组标题,并且我会为每个问题打印一个记录号,但不会显示问题和答案。

看起来,Crystal Reports 没有将我的第二个查询的数据结果映射到 DataTable。

更奇怪的是JurorQuestionAnswers DataTable 目前有一个多余的姓和名字段。如果我在详细信息区域中包含这些字段(JurorQuestionAnswers.LastnameJurorQuestionAnswers.Firstname),它们实际上会显示出来——数据已正确映射。

我做错了什么?

更新 - 链接标签的图片

【问题讨论】:

如果你查看report.Database的内容,你能看到数据真的存在吗?我注意到您使用了两个不同的名称:JurorAnswers 和 JurorQuestionAnswers,但我认为没关系 - 但您想检查这些名称是否必须相同......第三也是最后,检查您是否在水晶中链接表格,在第二张图片中显示的选项卡“链接”(这不是问题,但以后可能是一个问题)。 如果我添加代码来循环读取阅读器的值——是的,数据就在阅读器中。我尝试检查 report.Database 的内容。它肯定显示了两个表以及它们之间的链接,但我无法找到任何一种保存数据的属性——对于任何一个表。 尝试使用以下命令检查数据集:dataset.WriteXml(...) 只是为了期待一些想法:我正在考虑这些可能性:(1)数据不存在; (2) 数据集中的列名和表名或类型与为rpt定义的不同(你使用XSD文件吗?); (3) 某些东西正在抑制“不可见”字段(您是否使用了抑制公式?)。 我还记得一件事:您可以显示您的“数据库专家”的“​​链接”选项卡吗?当您使用“预览”功能时会发生什么? 【参考方案1】:

我终于让它工作了。基本上,它涉及用新的 DataSet 替换报表上存在的 DataSet。

我必须按如下方式更改我的代码:

public void SetDataSource(AdoProvider provider, int sessionPK, int jurorPK)

   string commandText;
   AdoQuery query;
   
   // ** Added Direct Reference to DataSet **//
   var ds = new QuestionAnswersData(); 

   commandText = $@"select j.* from Juror j
   where j.JurorPK in (select JurorFK from SessionJurorLink where SessionFK = @sessionId)
   (jurorPK > 0 ? " and jurorPK = @jurorId" ? "")
   ";
   query = provider.CreateQuery(commandText, null
      , provider.CreateParameter("sessionId", DbType.Int32)
      , provider.CreateParameter("jurorId", DbType.Int32)
   );
   AdoReader jReader = query.ExecuteReader(sessionPK, jurorPK);

   // ** REPLACED THIS LINE **//
   // report.Database.Tables["JurorProfile"]
   //  .SetDataSource((IDataReader)jReader.DataReader); 

   //** WITH THIS LINE **//
   ds.Tables["JurorProfile"].Load((IDataReader)jReader.DataReader, LoadOption.OverwriteChanges, null);  

   commandText = $@"select ... from JurorAnswers ...
   where sessionFK = @sessionId
   (jurorPK > 0 ? " and jurorFK = @jurorId " : "")
   order by JurorFK, Rank, ParentFK, QuestionPK
   ";
   query = provider.CreateQuery(commandText, null
      , provider.CreateParameter("sessionId", DbType.Int32)
      , provider.CreateParameter("jurorId", DbType.Int32)
   );
   AdoReader qaReader = query.ExecuteReader(sessionPK, jurorPK);

   //** REPLACED THIS LINE **//
   //report.Database.Tables["JurorQuestionAnswers"]
   // .SetDataSource((IDataReader)qaReader.DataReader); 

   //** WITH THIS LINE **//
   ds.Tables["JurorQuestionAnswers"].Load((IDataReaderjReader.DataReader, LoadOption.OverwriteChanges, null);

   //** NOW TIE THE DATASOURCE DIRECTLY TO THE REPORT **//
   base.SetDataSource(ds); 

【讨论】:

【参考方案2】:

当你说 JurorQuestionAnswersDataTable 当前有一个多余的姓和名字段”我很想知道,当你在数据集设计器中单击它们并查看 @987654323 时@property,你会看到类似Parent.Firstname 的东西(或者代码是否包含类似somedatatable.FirstnameColumn.Expression = "Parent.Firstname" 的东西)。

我已经很久没有使用 CR 了,但我的即时假设是 CR 无法导航 DataRelations,有人解决了这个问题,而是使用 built in ability for a DataColumn Expression to reference other tables 从概念上将父数据导入到子表中,因此 CR 只有一张数据表来处理。然后 CR 将在父列本身上执行一个组(并且因为它们可靠地重复相同的数据,所以它们只分组为一个值)所以你可以达到相同的效果,你只需要重复数据

如果是这种情况,请遵循模式 - 如果您希望在标题中包含父列 X,请在子表中添加一个数据列(在设计器中),称为 ParentX(我喜欢将 Parent 这个词放在通过关系派生,因此人们不会认为它们是多余的,而是经过深思熟虑的),将其 Experssion 设置为 Parent.X,然后更新/刷新您的 CR,以便它可以看到新的列和组

【讨论】:

不幸的是,ExpressionLastnameFirstname 上都是空的。此外,奇怪的是 CR 似乎确实在导航 DataRelations,因为它正在查找适当数量的子记录并遍历适当数量的详细信息行——只是无法生成实际数据。

以上是关于Crystal Reports 不会显示相关的表格数据的主要内容,如果未能解决你的问题,请参考以下文章

Crystal Reports 使用多个表格 - 不能完全正确

Crystal Reports:需要使用汇总字段作为记录选择公式的一部分

Crystal Reports (C#):信息显示不正确

10页Crystal Reports后增加参数字段

Vb.net 和 Crystal Reports 添加组和子报表

Crystal Reports并列数据比较