快速搜索并找不到我一直在寻找的答案。 所以我有一个vb.net windows应用程序,它使用RDLC生成发票,交货单,价目表和其他文件。为尽可能减少服务器负载,信息只会从服务器中提取一次,并且包含订单商品,价格和其他必要数据。
一旦数据被拉出(以xml为单位),它将被填充到一个数据集中,该数据集将用于生成各种报告。请注意,在多个RDLC报告中使用相同的数据集来显示不同的信息。
所以我的问题是我无法从SQL级别执行SELECT DISTINCT,因为同样的数据集也将用于生成发票,但我还需要显示来自同一数据集的价格表包括不同的订单商品。
所以我有选择:
让RDLC显示不同的行,但我不知道如何实现它。
如果不这样做,我可能需要使用现有数据集在我的xsd文件中创建另一个数据表,将数据集分成2.再次,我对执行的细节一无所知。
非常感谢任何输入。谢谢!
答案 0 :(得分:1)
此示例将包含三 DataSets
。由于我们有三个数据集,因此我将在一个 Report.rdlc 中使用三个 DataSources
。该方案将是一个简单的生产线。我们将有起动机器,正在组装的机器以及正在运送的机器。
我假设您知道如何创建DataSet(.XSD)文件。我将把代码分成几部分,并在这篇文章中向您展示最终结果。
对于您的问题,重要的是我如何将三个DataSource分配给一个报告。
我有三个自定义类clsAssemblyState
,clsExpeditionState
,clsStartState
,其中包含从数据库收集的信息。这些只是我用作对象的自定义类。您使用XML绑定数据,我将按照下面的“以编程方式填充DataTables ”部分中的方式对其进行编程。
Dim ds1 As New dsAssemblies 'Link to my DataSet called dsAssemblies'
Dim ds2 As New dsExpeditions 'Link to my DataSet called dsExpeditions'
Dim ds3 As New dsStarts 'Link to my DataSet called dsStarts'
Dim sReportDataSource1 As ReportDataSource 'First datasource'
Dim sReportDataSource2 As ReportDataSource 'Second datasource'
Dim sReportDataSource3 As ReportDataSource 'Third datasource'
Dim AssemblyStates As List(Of clsAssemblyState) = clsAssemblyState.GetAll() 'List that contains all my machines being assembled'
Dim ExpeditionStates As List(Of clsExpeditionState) = clsExpeditionState.GetAll() 'List that contains all my machines in shipping'
Dim StartStates As List(Of clsStartState) = clsStartState.GetAll() 'List of all my machines being started (paper work)'
最好在分配新数据源之前清除报告数据源。
'Reset the viewer'
rv.Reset()
rv.LocalReport.ReportEmbeddedResource = "YourProjectName.YourReportName.rdlc"
rv.LocalReport.DataSources.Clear()
sReportDataSource1 = New ReportDataSource()
sReportDataSource2 = New ReportDataSource()
sReportDataSource3 = New ReportDataSource()
这将填充我的dsAssemblies的DataTable,对其他两个DataTable也是如此,但是在这里写这个是多余的。
'Fill datatables'
If AssemblyStates.Count > 0 Then
For Each asmState As clsAssemblyState In AssemblyStates
Dim asm As New clsAssembly(asmState.FK_Assembly)
Dim Machine As New clsMachine(asm.FK_Machine)
Dim Client As New clsClient(Machine.FK_Client)
Dim State As New clsState(asmState.FK_State)
ds1.dtAssembly.Rows.Add(Machine.MachineNo, Machine.Description, Client.Nom, State.State, asm.DateTransfer.ToString("yyyy-MM-dd"))
Next
Else
'No information was retrieved from my GetAll(), therefor no rows ... I add a row with values of "N/A" notifying the user that there is nothing in that particular DataTable'
ds1.dtAssembly.Rows.Add("N/A", "N/A", "N/A", "N/A", "N/A")
End If
sReportDataSource[i].Name
是我分配给它各自DataSet的每个DataTable的名称。我将在代码下面显示DataSet的图片。
sReportDataSource1.Name = "Assembly_DataSet"
sReportDataSource2.Name = "Expedition_DataSet"
sReportDataSource3.Name = "Start_DataSet"
sReportDataSource1.Value = ds1.dtAssembly
sReportDataSource2.Value = ds2.dtExpedition
sReportDataSource3.Value = ds3.dtStart
rv.LocalReport.DataSources.Add(sReportDataSource1)
rv.LocalReport.DataSources.Add(sReportDataSource2)
rv.LocalReport.DataSources.Add(sReportDataSource3)
rv.RefreshReport()
Me.Show()
在这里您可以看到三个DataSet及其DataTables
此方法将使用三个数据源生成报告。当然,您必须将这些数据集分配到.rdlc
中的某些内容,例如三个不同的Tablix。
Private Sub GenerateStatusProduction()
Dim ds1 As New dsAssemblies
Dim ds2 As New dsExpeditions
Dim ds3 As New dsStarts
Dim sReportDataSource1 As ReportDataSource
Dim sReportDataSource2 As ReportDataSource
Dim sReportDataSource3 As ReportDataSource
Dim AssemblyStates As List(Of clsAssemblyState) = clsAssemblyState.GetAll()
Dim ExpeditionStates As List(Of clsExpeditionState) = clsExpeditionState.GetAll()
Dim StartStates As List(Of clsStartState) = clsStartState.GetAll()
'Reset the viewer'
rv.Reset()
rv.LocalReport.ReportEmbeddedResource = "YourProjectName.YourReportName.rdlc"
rv.LocalReport.DataSources.Clear()
sReportDataSource1 = New ReportDataSource()
sReportDataSource2 = New ReportDataSource()
sReportDataSource3 = New ReportDataSource()
'Fill datatables'
If AssemblyStates.Count > 0 Then
For Each asmState As clsAssemblyState In AssemblyStates
Dim asm As New clsAssembly(asmState.FK_Assembly)
Dim Machine As New clsMachine(asm.FK_Machine)
Dim Client As New clsClient(Machine.FK_Client)
Dim State As New clsState(asmState.FK_State)
ds1.dtAssembly.Rows.Add(Machine.MachineNo, Machine.Description, Client.Nom, State.State, asm.DateTransfer.ToString("yyyy-MM-dd"))
Next
Else
ds1.dtAssembly.Rows.Add("N/A", "N/A", "N/A", "N/A", "N/A")
End If
If ExpeditionStates.Count > 0 Then
For Each expdState As clsExpeditionState In ExpeditionStates
Dim Expd As New clsExpedition(expdState.FK_Expedition)
Dim Machine As New clsMachine(Expd.FK_Machine)
Dim Client As New clsClient(Machine.FK_Client)
Dim State As New clsState(expdState.FK_State)
ds2.dtExpedition.Rows.Add(Machine.MachineNo, Machine.Description, Client.Nom, State.State, Expd.DateTransfer.ToString("yyyy-MM-dd"))
Next
Else
ds2.dtExpedition.Rows.Add("N/A", "N/A", "N/A", "N/A", "N/A")
End If
If StartStates.Count > 0 Then
For Each strtState As clsStartState In StartStates
Dim Strt As New clsStart(strtState.FK_Start)
Dim Machine As New clsMachine(Strt.FK_Machine)
Dim Client As New clsClient(Machine.FK_Client)
Dim State As New clsState(strtState.FK_State)
ds3.dtStart.Rows.Add(Machine.MachineNo, Machine.Description, Client.Nom, State.State, Strt.DateTransfer.ToString("yyyy-MM-dd"))
Next
Else
ds3.dtStart.Rows.Add("N/A", "N/A", "N/A", "N/A", "N/A")
End If
sReportDataSource1.Name = "Assembly_DataSet"
sReportDataSource2.Name = "Expedition_DataSet"
sReportDataSource3.Name = "Start_DataSet"
sReportDataSource1.Value = ds1.dtAssembly
sReportDataSource2.Value = ds2.dtExpedition
sReportDataSource3.Value = ds3.dtStart
rv.LocalReport.DataSources.Add(sReportDataSource1)
rv.LocalReport.DataSources.Add(sReportDataSource2)
rv.LocalReport.DataSources.Add(sReportDataSource3)
rv.RefreshReport()
Me.Show()
End Sub
注意:rv
是我的报告查看器控件名称,而不是ReportViewer1
答案 1 :(得分:1)
经过几次实验后,我设法找到了一个更好(更简单)的问题解决方案。到目前为止,它可能是最优雅的解决方案。所以我认为我在这里发布了其他遇到同样问题的人。
这是报告在设计师中的样子 绿色标记显示相应的行组和Tablix行。相同的item_id可能存在于多个行/行中,我需要将它们显示为不同的。这可以通过使用行组属性下的分组功能来完成。 在组表达式下,添加新条目并选择需要显示为不同的字段。它也支持非常有用的表达式。