【问题标题】:RDLC with repeated row headings and row wrap具有重复行标题和换行的 RDLC
【发布时间】:2019-07-09 16:49:06
【问题描述】:

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

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

数据存储在 SQL Server 上,如下所示:

  • Count: 30 在例子中
  • Weight: 120000,19000,20000,20000,19000,... - CSV
  • Length: 196,54,54,174,60,... - 英寸 CSV

(我没有设计表格;会采用一对多而不是将数据作为 CSV 存储在列中。)

我找到了这个示例:Show data Horizontally in rdlc report,但它没有显示行标题、重复它们或包装项目。

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

【问题讨论】:

    标签: c# .net reporting-services rdlc


    【解决方案1】:

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

    我首先处理数据,如上所示,这些数据以 CSV 值从 db 中传入。不理想,但可行。

    // 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循环中的数据(例如,将多个循环合并为一个);但它正在工作,我们将在时间允许时访问它以重构和提高效率。

    希望这对其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-17
      • 2011-01-18
      • 1970-01-01
      • 1970-01-01
      • 2015-07-12
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      相关资源
      最近更新 更多