具有重复的行标题和行换行的RDLC

时间:2019-02-15 14:09:45

标签: c# .net reporting-services rdlc

我正在Visual Studio的报表生成器中构建RDLC子报表。它需要水平显示数据,重复行标题,并在空间用完时包装(每行10个项目)。可以有n个项目(编号)。另请注意,Length必须显示在项目之间。另请注意,每行重复行标题。这是一个示例:

enter image description here

因此,对于一个子报表,它可能是30个“项目”(如上图所示),而另一个可以有52、20、14等。

数据像这样存储在SQL Server上:

  • Count:示例中的30
  • Weight120000,19000,20000,20000,19000,...-CSV
  • Length196,54,54,174,60,...-英寸的CSV

(我不是设计表的;应该是一对多的,而不是将数据以CSV的形式存储在列中。)

我发现了以下示例:Show data Horizontally in rdlc report,但没有显示行标题,重复行标题或包装项目。

如何创建一个RDLC来显示上述示例中的数据?谢谢。

1 个答案:

答案 0 :(得分:2)

以下是许多解决方案之一;这只是一种方法。但是它最终修复了该报告。包装物品变得行不通了。据我所知,这是不可能的。因此,我决定子报表中每行最多只能包含10个项目。

我首先处理数据,如上所述,它是从数据库以CSV值输入的。不理想,但可行。

// Split the CSV data into lists.
var weightList = dataModel.Weight.Split(',')
    // Add thousands separator to weight
    .Select(x => int.Parse(x).ToString("##,###"))   
    .ToList();
var lengthList = dataModel.Length.Split(',').ToList();
reportData.RowModelList = new List<RowModel>();

// Loop for 10 at a time
for (var i = 0; i < weightList.Count; i=i+10)
{
    var weightListTen = new List<string>();
    // Get an array of 10 weight items
    var weightArrayItems = weightList.Skip(i).Take(10).ToArray();

    // Important: we need to add 10 elements per row,
    // even if the item is blank string. This makes life
    // easier in RDLC as we won't have to tangle with 
    // out-of-bound array errors. The below issue can
    // be encountered on the last row.
    for (var k = 0; k < 10; k++)
    {
        weightListTen.Add(weightArrayItems.Length - 1 < k ? "" : weightArrayItems[k]);
    }

    var lengthListTen = new List<string>();
    // Get an array of 9 length items
    var lengthArrayItems = lengthList.Skip(i).Take(9).ToArray();
    // Same as weight: loop and add fully 10 items
    // per row (i variable), so to avoid array out-of-bound
    // errors in VBA.
    for (var l = 0; l < 10; l++)
    {
        lengthListTen.Add(lengthArrayItems.Length - 1 < l ? "" : FeetAndInches(int.Parse(lengthArrayItems[l])));
    }

    // Similar issue as above being addressed here, but
    // with a slightly different approach. We need the 
    // Id property array for this row and we want to
    // ensure we have 10 records, even if the item 
    // only has a blank string. 
    var idList = new List<string>();
    var diff = (i + 10) - weightList.Count;
    for (var j = i+1; j <= weightList.Count + diff ; j++) 
    {
        idList.Add(j <= weightList.Count ? j.ToString() : "");
    }

    // Instantiate a new row.
    var rowModel = new RowModel
    {
        Weight = weightListTen.ToArray(), 
        Length = lengthListTen.ToArray(),
        Id = idList.Select(x => x.ToString()).ToArray()
    };
    reportData.RowModelList.Add(rowModel);
}

// Helper for getting feet/inches
private static string FeetAndInches(int inches)
{
    return inches / 12 + "' " + inches%12 + "\"";
}

这里是处理RDLC渲染的Renderer类:

public class Renderer
{
    private readonly int _id;
    private ReportDataSource _dataSourceMain;
    private ReportDataSource _dataSourceRows;

    public Renderer(int id)
    {
        _id = id;
    }

    public async Task<byte[]> RenderPdfAsync()
    {
        var report = await DataService.GetReportDataAsync(_id);

        Warning[] warnings;
        string[] streamIds;
        var mimeType = string.Empty;
        var encoding = string.Empty;
        var extension = string.Empty;

        using (var report = new LocalReport())
        {
            report.ShowDetailedSubreportMessages = true;
            report.EnableExternalImages = true;

            report.ReportEmbeddedResource = "Renderer.Templates.Pdf.rdlc";
            var dsMain = new List<DataModel> { report };
            _dataSourceMain = new ReportDataSource("dsMain", dsMain);
            _dataSourceRows = new ReportDataSource("dsRows", permit.RowModelList);
            report.DataSources.Add(_dataSourceMain);
            report.DataSources.Add(_dataSourceRows);
            report.SubreportProcessing += SetSubDataSource;
            report.Refresh();
            var result = report.Render("PDF", null, out mimeType, out encoding, out extension, out streamIds, out warnings);

            if (warnings.Any())
            {
                Logger.Log(LogLevel.Error, null, "Report Processing Messages: " + string.Join(", *", warnings.Select(x => new
                                                         {x.Message, x.Code, x.ObjectName, x.ObjectType, x.Severity})));
            }

            return result;
        }
    }

    private void SetSubDataSource(object sender, SubreportProcessingEventArgs e)
    {
        e.DataSources.Clear();
        e.DataSources.Add(_dataSourceMain);
        e.DataSources.Add(_dataSourceRows);
    }
}

子报表RDLC使用绑定到dsRows的Tablix,然后在IDWeightLength行中引用数组元素。 Tablix的标题行已删除,左侧有一列,其中3个行标题的静态值输入到文本框控件中。

然后,该标题信息列的右侧有10列;这些显示该行的数组元素。在每个单元格中,表达式获取各自的数组值:第一列=Fields!Weight.Value(0)中的Weight和最后一行中的=Fields!Weight.Value(9)

有很多更好的方法可以更早地在for循环中组合数据(例如,将多个循环合并为一个);但是它正在工作,我们会在时间允许的情况下对其进行重构和提高效率。

希望这对其他人有帮助。