当前位置:首页 > 技能相关 > C#与C++ > 正文内容

VS Visual Studio操作ReportViewer报表导出,多ReportViewer报表合并导出

admin6个月前 (11-26)C#与C++2410 修订时间:2024-11-26 10:09:51

前言

自VS2017版本后ReportViewer被摒弃,虽然可以通过NuGet再次安装回来(详见:VS Visual Studio添加ReportViewer控件(RDLC报表控件)),但是还是有很多API被摒弃,造成功能需求变窄,但是不得不说ReportViewer还是有其存在的必要性,下面的内容用来介绍如何导出ReportViewer为PDF,多个ReportViewer文件导出到同一个PDF文件,当然我们这里的ReportViewer报表并不是表格类型的,如下图:

image.png

解决方案

01、安装iTextSharp,用于操作PDF文件(这里主要是用来合并)

image.png

安装命令(也可使用NuGet安装包管理器搜索安装)

dotnet add package iTextSharp --version [具体版本号]

02、先定义报表文件和报表文件的数据集(这里是按对象连接的)

image.png

对象代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RdlcModel
{
    public class SplitCode
    {
        /// <summary>
        /// 批号
        /// </summary>
        public string BatchNumber { get; set; }
        /// <summary>
        /// 有效期
        /// </summary>
        public string ValidToDate { get; set; }
        /// <summary>
        /// 分装日期
        /// </summary>
        public string SysDate { get; set; }
        /// <summary>
        /// 追溯码拆零码
        /// </summary>
        public string SplitTraceCode { get; set; }
        /// <summary>
        /// 追溯码拆零码图像
        /// </summary>
        public byte[] SplitTraceCodeImg {  get; set; }
        /// <summary>
        /// 拆零比
        /// </summary>
        public string SplitRatio { get; set; }
    }
}

03、报表文件绑定

image.png

04、实例化对象并赋值ReportViewer,这里注意不能直接把对象赋值ReportViewer,会报错,代码如下:

//刷新,清空
this.reportViewer1.RefreshReport();
this.reportViewer1.LocalReport.DataSources.Clear();

//创建对象List<SplitCode>
List<SplitCode> splitCodes = new List<SplitCode>();

//创建SplitCode对象
SplitCode splitCode = new SplitCode();

//赋值
splitCode.ValidToDate = "2024-12-31";
splitCode.SysDate = DateTime.Today.ToString("yyyy-MM-dd");
splitCode.SplitRatio = "10/24";
splitCode.BatchNumber = "PH00025";
splitCode.SplitTraceCode = "0137744338578002";
splitCode.SplitTraceCodeImg = code128.GetCode128("83437270137744338578001"); //这里的code128是用来生成一维码的方法

//SplitCode对象添加到List<SplitCode>
splitCodes.Add(splitCode);

//将List<SplitCode>对象绑定到RDLC文件,这里DataSetSplitCode是RDLC中的名称
var RdlcModelSplitCode = new Microsoft.Reporting.WinForms.ReportDataSource("DataSetSplitCode", splitCodes);

//将RdlcModelSplitCode绑定到reportViewer1控件
this.reportViewer1.LocalReport.DataSources.Add(RdlcModelSplitCode);

//刷新控件
this.reportViewer1.RefreshReport();

image.png

05、创建ReportViewer导出PDF的方法

/// <summary>
/// ReportViewer导出为PF文件
/// </summary>
/// <param name="reportViewer"></param>
public void ExportReportToPdf(ReportViewer reportViewer)
{
    // 确保 ReportViewer 已加载报告
    if (reportViewer.LocalReport.ReportPath == string.Empty)
    {
        MessageBox.Show("请先加载报告。");
        return;
    }
    // 设置导出参数
    Warning[] warnings;
    string[] streamIDs;
    string mimeType;
    string encoding;
    string extension;
    // 获取临时文件路径
    string tempFilePath = Path.GetTempFileName();
    // 更改文件扩展名为 .pdf
    tempFilePath = Path.ChangeExtension(tempFilePath, ".pdf");
    // 自定义的页面设置(例如A4纸大小)IN寸转CM 2.54CM
    string deviceInfo = @"<DeviceInfo>
                                <OutputFormat>PDF</OutputFormat>
                                <PageWidth>2.2in</PageWidth>
                                <PageHeight>3.0in</PageHeight>
                                <MarginTop>0.1in</MarginTop>
                                <MarginLeft>0.1in</MarginLeft>
                                <MarginRight>0.1in</MarginRight>
                                <MarginBottom>0.1in</MarginBottom>
                          </DeviceInfo>";
    // 导出报告为byte[] 字节数组
    byte[] bytes = reportViewer.LocalReport.Render(
        "PDF", // 格式
        deviceInfo,  // 设备信息(对于 PDF,通常为 null)
        out mimeType,
        out encoding,
        out extension,
        out streamIDs,
        out warnings);

    // 将byte[]字节数组写入文件
    File.WriteAllBytes(tempFilePath, bytes);
    //记录临时文件路径
    PathStrs.Add(tempFilePath);
}

使用方法

 ExportReportToPdf(this.reportViewer1);

上述方法中PathStrs.Add(tempFilePath)是用来记录导出的pdf目录地址,是一个List<string> 对象:

List<string> PathStrs = new List<string>();

注意:this.reportViewer1的值,赋值给List<ReportViewer>对象,是把控件的(内存地址?)赋值给List<ReportViewer>的元素,故无论怎么操作List<ReportViewer>的值均为最后一个值。

06、使用foreach去循环导出不同对象的PDF文件,并记录在PathStrs对象中

List<SplitCode> splitCodes = new List<SplitCode>();
Code128 code128 = new Code128();

//创建reportViewer1对象的List<SplitCode>
SplitCode splitCode = new SplitCode();
splitCode.ValidToDate = "2024-12-31";
splitCode.SysDate = DateTime.Today.ToString("yyyy-MM-dd");
splitCode.SplitRatio = "10/24";
splitCode.BatchNumber = "PH00025";
splitCode.SplitTraceCode = "0137744338578001";
splitCode.SplitTraceCodeImg = code128.GetCode128("83437270137744338578001");
splitCodes.Add(splitCode);


SplitCode splitCode1 = new SplitCode();
splitCode1.ValidToDate = "2025-12-31";
splitCode1.SysDate = DateTime.Today.ToString("yyyy-MM-dd");
splitCode1.SplitRatio = "5/24";
splitCode1.BatchNumber = "PH00005";
splitCode1.SplitTraceCode = "0137744338578002";
splitCode1.SplitTraceCodeImg = code128.GetCode128("83437270137744338578002");
splitCodes.Add(splitCode1);

//循环遍历List<SplitCode>对象splitCodes
foreach (var item in splitCodes)
{
    List<SplitCode> splitCodeslog = new List<SplitCode> { item };
    this.reportViewer1.RefreshReport();
    this.reportViewer1.LocalReport.DataSources.Clear();
    this.reportViewer1.LocalReport.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource("DataSetSplitCode", splitCodeslog));
    this.reportViewer1.RefreshReport();
    ExportReportToPdf(this.reportViewer1);
}

07、合并PDF的方法

/// <summary>
/// 合并多个PDF文单独PDF文件
/// </summary>
/// <param name="reportViewers"></param>
/// <param name="outputPath"></param>
private void MergeReportsToPdf(string outputPath)
{
    using (FileStream stream = new FileStream(outputPath, FileMode.Create))
    {
        Document document = new Document();
        PdfCopy pdfCopy = new PdfCopy(document, stream);
        PdfReader reader = null;
        try
        {
            document.Open();
            foreach (var PathStr in PathStrs)
            {
                // 打开临时PDF文件
                reader = new PdfReader(PathStr);
                // 获取PDF文件页数
                int numberOfPages = reader.NumberOfPages;
                // 主文件循环添加PDF页面
                for (int page = 0; page < numberOfPages;)
                {
                    pdfCopy.AddPage(pdfCopy.GetImportedPage(reader, ++page));
                }
                // 关闭当前文件,这里删除会报错,所以删除临时文件放在最后
                reader.Close();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("出现错误: " + ex.Message);
        }
        finally
        {
            if (reader != null)
            {
                reader.Close();
            }
            if (document.IsOpen())
            {
                document.Close();
                //循环删除临时文件
                foreach (var PathStr in PathStrs)
                {
                      File.Delete(PathStr);
                }
                //打开汇总文件
                System.Diagnostics.Process.Start(outputPath);
            }
        }
    }
}

使用方法

string outputPath = "ReportViews.pdf";
MergeReportsToPdf(outputPath);
MessageBox.Show("报告已成功合并到" + outputPath);
 您阅读本篇文章共花了: 

免责声明
本站内容均为博客主本人日常使用记录的存档,如侵犯你的权益请联系:lifei@zaiheze.com 546262132@qq.com 沟通删除事宜。本站仅带访问端口形式使用,已杜绝搜索引擎爬取。

扫描二维码推送至手机访问。

版权声明:本文由LIFEI - blog发布,如需转载请注明出处。

本文链接:http://www.lifeiai.com/?id=449

分享给朋友:

相关文章

Web API的创建3年前 (2022-11-07)
C# 第二篇 基础语法3年前 (2022-11-14)
C# 第三篇 流程控制3年前 (2022-11-15)
C# 第四篇 数组定义3年前 (2022-11-15)
C# 第五篇 字符串3年前 (2022-11-15)

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。