是否可以在RDLC报告中显示来自数据集的不同记录

时间:2013-05-31 03:49:33

标签: .net sql vb.net dataset rdlc

快速搜索并找不到我一直在寻找的答案。 所以我有一个vb.net windows应用程序,它使用RDLC生成发票,交货单,价目表和其他文件。为尽可能减少服务器负载,信息只会从服务器中提取一次,并且包含订单商品,价格和其他必要数据。

一旦数据被拉出(以xml为单位),它将被填充到一个数据集中,该数据集将用于生成各种报告。请注意,在多个RDLC报告中使用相同的数据集来显示不同的信息。

所以我的问题是我无法从SQL级别执行SELECT DISTINCT,因为同样的数据集也将用于生成发票,但我还需要显示来自同一数据集的价格表包括不同的订单商品。

所以我有选择:

  1. 让RDLC显示不同的行,但我不知道如何实现它。

  2. 如果不这样做,我可能需要使用现有数据集在我的xsd文件中创建另一个数据表,将数据集分成2.再次,我对执行的细节一无所知。

  3. 非常感谢任何输入。谢谢!

2 个答案:

答案 0 :(得分:1)

此示例将包含 DataSets。由于我们有三个数据集,因此我将在一个 Report.rdlc 中使用三个 DataSources。该方案将是一个简单的生产线。我们将有起动机器,正在组装的机器以及正在运送的机器。

我假设您知道如何创建DataSet(.XSD)文件。我将把代码分成几部分,并在这篇文章中向您展示最终结果。

对于您的问题,重要的是我如何将三个DataSource分配给一个报告。


声明

我有三个自定义类clsAssemblyStateclsExpeditionStateclsStartState,其中包含从数据库收集的信息。这些只是我用作对象的自定义类。您使用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()

以编程方式填写DataTable

这将填充我的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

将DataTables分配给DataSources

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

DataSets


完整报告代码

此方法将使用三个数据源生成报告。当然,您必须将这些数据集分配到.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)

经过几次实验后,我设法找到了一个更好(更简单)的问题解决方案。到目前为止,它可能是最优雅的解决方案。所以我认为我在这里发布了其他遇到同样问题的人。

这是报告在设计师中的样子 enter image description here 绿色标记显示相应的行组和Tablix行。相同的item_id可能存在于多个行/行中,我需要将它们显示为不同的。这可以通过使用行组属性下的分组功能来完成。 enter image description here 在组表达式下,添加新条目并选择需要显示为不同的字段。它也支持非常有用的表达式。 enter image description here