Renderizar el contenido del control ReportViewer directamente a PDF

Enviar directamente al usuario un informe de Reporting Services en formato PDF.


Con este ejemplo, conseguiremos crear una página en ASP.NET con la que nos devolverá un informe de Reporting Services ya convertido en formato PDF. Dependiendo de como el usuario que accede a la página tenga configurado el Explorador de Internet, éste le abrirá el documento PDF o le pedirá guardarlo.

Vamos a ello.
Creamos una nueva página e introducimos en ella un control ReportViewer y le configuramos lo siguiente:

Abrimos el archivo que contiene el código y en el evento Page_Load introducimos lo siguiente:

Dim warnings As Warning() = Nothing
Dim streamids As String() = Nothing
Dim mimeType As String = Nothing
Dim encoding As String = Nothing
Dim extension As String = Nothing
Dim bytes As Byte()
bytes = ReportViewer1.ServerReport.Render("PDF", Nothing, mimeType, encoding, extension, streamids, warnings)
Dim ms As New System.IO.MemoryStream(bytes)
Response.ContentType = "Application/pdf"
Response.BinaryWrite(ms.ToArray())
Response.End()

El servidor donde lo probé es un Windows Server 2003 con SQL Server 2005 Standard Edition. Utilizo Visual Studio 2008.

Un saludo.

Autor: toniogago

Auxiliar Técnico en Informática de Gestión.

26 opiniones en “Renderizar el contenido del control ReportViewer directamente a PDF”

  1. buenos días no se si puedas ayudarme e implementado tu código para C# queda algo asi en la pagina de load

            Warning[] warnings = null;
            string[] streamids = null;
            string mimeType = null;
            string encoding = null;
            string extension = null;
            byte[] bytes = null;
            ReportViewer1.LocalReport.ReportPath = "Report1.rdlc";
            bytes = ReportViewer1.ServerReport.Render("PDF", null,out mimeType,out encoding,out extension,out streamids,out warnings);
            System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
            Response.ContentType = "Application/pdf";
            Response.BinaryWrite(ms.ToArray());
            Response.End();
    

    pero me sale el siguiente error

    El código de usuario no controló Microsoft.Reporting.WebForms.MissingReportSourceException
    Message=No se ha especificado el origen de la definición de informe
    Source=Microsoft.ReportViewer.WebForms
    StackTrace:
    en Microsoft.Reporting.WebForms.ServerReport.EnsureExecutionSession()
    en Microsoft.Reporting.WebForms.ServerReport.Render(String format, String deviceInfo, PageCountMode pageCountMode, String& mimeType, String& encoding, String& fileNameExtension, String[]& streams, Warning[]& warnings)
    en Microsoft.Reporting.WebForms.Report.Render(String format, String deviceInfo, String& mimeType, String& encoding, String& fileNameExtension, String[]& streams, Warning[]& warnings)
    en _Default.Page_Load(Object sender, EventArgs e) en c:\Users\Administrador\Documents\Visual Studio 2010\WebSites\ReportsWebsite1\Default.aspx.cs:línea 23
    en System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
    en System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
    en System.Web.UI.Control.OnLoad(EventArgs e)
    en System.Web.UI.Control.LoadRecursive()
    en System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
    InnerException:

    además no se como llamar el •ProcessingMode dentro del defaul me podrias ayudar por favor

    1. Hola María.

      Tienes que indicar dónde está el informe: en el servidor o local.

      prueba a poner el siguiente código:

              ReportViewer1.ServerReport.ReportPath = "Report1.rdlc";
              ReportViewer1.ProcessingMode = ProcessingMode.Remote;
      

      También lo puedes cambiar en las propiedades del control.

      1. buenas tardes ya lo hice y ahora tengo el siguiente error La ruta de acceso del elemento \»Report1.rdlc\» no es válida. Debe tener menos de 260 caracteres. Se aplican también otras restricciones. Si el servidor de informes está en modo nativo, la ruta de acceso debe comenzar por una barra diagonal. (rsInvalidItemPath) que pena contigo la verdad soy nueva en el tema

  2. Estimad@s coloco todo al parecer bien..

    string strNull = null;
    string strPDF = «PDF»;
    string enCoding = Request.Headers[«Accept-Encoding»];
    string mimeType = «application/pdf»;
    string extension = «.pdf»;
    string[] streamids = null;
    Warning[] warnings = null;

    Reporte.ProcessingMode = ProcessingMode.Remote;
    Reporte.LocalReport.ReportPath = Server.MapPath(@»FichaSolicitud.rdlc»);

    byte[] bytes = Reporte.ServerReport.Render(strPDF, strNull, out mimeType, out enCoding, out extension, out streamids, out warnings);

    Pero me indica que: No se ha especificado el origen de la definición de informe

    Alguien tiene alguna idea!!!!

    Nota: Esto no me queda claro
    •Server Report: ◦Report Path: //
    ◦ReportServer: http:///reportserver

    1. Hola Darkmedel,

      El control ReportViewer tiene las siguientes propiedades para ProcessingMode.Remote:

      ServerReport.ReportPath
      ServerReport.Render

      También tiene otros 2 parámetros para ProcessingMode.Local:

      LocarReport.ReportPath
      LocalReport.Render

      Estás mezclando ServerReport y LocalReport. Tienes que hacer coincidir estas propiedades dependiendo de la localización del informe. Si es un archivo RDLC en el propio IIS utiliza LocalReport. Si el informe está publicado en un servidor der Reporting Services, utiliza ServerReport.

  3. alguien sabe por que me genera el siguiente error La ruta de acceso del elemento «Report1.rdlc» no es válida. Debe tener menos de 260 caracteres. Se aplican también otras restricciones. Si el servidor de informes está en modo nativo, la ruta de acceso debe comenzar por una barra diagonal. (rsInvalidItemPath)

    1. Hola María,

      encontré la solución para mi caso. A ver si te funciona a ti.
      Tengo un informe en el servidor llamado «servidor» y el informe se llama «Control de Stocks» y está en la carpeta «adevesa».
      Lo que hice fue lo siguiente:

      ReportViewer1.ServerReport.ReportPath = "/adevesa/Control de stocks"
      ReportViewer1.ServerReport.ReportServer = "http://servidor/reportserver"

      Fíjate que en el nombre del informe no le puse la extensión .rdlc ni caracteres especiales.

  4. hola toniago perdona la pregunta se que es muyu tonta pero bueno yo tengo mi proyecto C:\Users\Administrador\Documents\Visual Studio 2010\WebSites\ReportsWebsite6 coloco toda la direccion o solo coloco /ReportsWebsite6/Report1 gracias por tu ccolaboracion

    1. Hola María,
      veo que el informe lo tienes en local y no en remoto. Utliza LocalReport.ReportPath = Server.MapPath(«.»)+@»\Report1″
      También utiliza LocalReport.Render

      Haré pruebas para confirmártelo cuando pueda. Mientras, ve probando y nos cuentas.

      1. muchisimas gracias ya me funciono…

        gracias por tu gran paciencia y colaboracion. quisiera saber si sabescomo puedo hacer lo siguiente tengo un visor de reportes y desde alli abro varios reportes el problema esta en qu para uno quiero el de exportar solo a pdf y para los otros si que permita exportar los multiples formatos sabes como puedo delimitar que si es un reporte me muestre el visor con el exportar solo a pdf y en los otros si el general…

      2. buenos dias tengo una pequeña pregunta cuando le estoy enviando parametros al reporte de que manera puedo capturar los mismos y colocarlos en el codigo para que me los muestre

      3. Hola María,

        en una expresión puedes utilizar los parámetros con la siguiente notación:

        =Parameter!NombreParametro.Value

        Ten en cuenta que el nombre del parámetro es sensible a mayúsculas.
        Tengo hecho algún informe de ventas donde utilizo un filtro con los 3 últimos años y en el título del informe utilizo una expresión para indicar el año seleccionado:

        ="Informe de ventas del año " + Parameter!Ano.Value

  5. Hola toniogago. Te escribo porque tengo un problema a ver si me puedes ayudar a solucionarlo. Resulta que tengo una imagen que entra como parámetro y no se despliega genero el informe. Como puedo solucionar esto.

    Gracias.

    Acá el código:

    Warning[] warnings;
                string[] streamIds;
                string mimeType = string.Empty;
                string encoding = string.Empty;
                string extension = string.Empty;
    
                // Setup the report viewer object and get the array of bytes
    
                ReportViewer1.ProcessingMode = ProcessingMode.Local;
                if (Session["CulturaIdioma"].ToString() == "ES-CO")
                    ReportViewer1.LocalReport.ReportPath = @"App\Reportes\ReporteConsulta_ENCA.rdlc";
                else
                    ReportViewer1.LocalReport.ReportPath = @"App\Reportes\ReporteConsulta_ENG_ENCA.rdlc";
    
    
                byte[] bytes = ReportViewer1.LocalReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamIds, out warnings);
    
                Response.Buffer = true;
                Response.Clear();
                Response.ContentType = mimeType;
                Response.AddHeader("content-disposition", "attachment; filename=" + "REPORTE_CONSULTA" + "." + extension);
                Response.BinaryWrite(bytes); // create the file
                Response.Flush(); // send it to the client to download
    
  6. Estimado Antonio. Le escribo para consultarle 1 duda. Agradecida desde ya.
    Me encuentro desarrollando en VStudio 2017.
    1º Situacion: Tengo un reportview en un webform que funciona perfectamente en forma local. El archivo de reporte .rdlc se encuentra en la raiz del proyecto. Muestro codigo:

    if (!Page.IsPostBack)
    {
         OleDbConnection conn = new OleDbConnection(cadena);
         string sql = "select TOP 5 NombreCompañía, NombreContacto from Clientes";
         conn.Open();
         DataSet ds = new DataSet();
         OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
         da.Fill(ds,"tablaLogica");
         conn.Close();
    
         this.ReportViewer1.LocalReport.ReportPath = "Report2.rdlc";
         this.ReportViewer1.LocalReport.DataSources.Clear();
         this.ReportViewer1.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", ds.Tables["tablaLogica"]));
         this.ReportViewer1.LocalReport.Refresh();
    }    
    

    2º Situacion: cuando en el proyecto raiz agrego una carpeta de reportes y ahi colocar el archivo. rdlc el ReportPath queda de esta manera:

    this.ReportViewer1.LocalReport.ReportPath = "/reportes/Report2.rdlc";
    

    ademas debo crear en el directorio C:\ la carpera reportes y ahi colocar el archivo Report2.rdlc para que funcione.
    Hasta aqui todo claro usando en forma local.

    Mi Duda: cuando vaya a produccion y lo publique en un servidor, que estoy haciendo mal en este codigo?? pues me arroja un error al invocar a la pagina que levanta el reporte.

     ReportViewer1.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote;
     ReportViewer1.ServerReport.ReportServerUrl = new Uri("http://nombreservidor/reportes");
     ReportViewer1.ServerReport.ReportPath = "Report2.rdlc";
     ReportViewer1.ServerReport.Refresh();
    
  7. Hola Nanci,

    intenta utilizar direcciones relativas utilizando el punto para indicar el directorio actual.
    En la línea donde pones:

    this.ReportViewer1.LocalReport.ReportPath = “/reportes/Report2.rdlc”

    Cámbialo poniendo un punto delante de la primera barra del directorio:

    this.ReportViewer1.LocalReport.ReportPath = “./reportes/Report2.rdlc”

    De esta manera le estás indicando al servidor que desde el directorio actual de la página que contiene tu código, entre en el subdirectorio reportes y utilice el archivo Report2.rdlc

    El problema lo puedes tener también al utilizar el ProcessingMode Remote. Este modo utilízalo sólo si tienes un servidor de informes (Reporting Services).

    En el proyecto de Visual Studio haz lo siguiente:

    * crea la carpeta «reportes» y coloca el informe rdlc en esa carpeta
    * utiliza ReportViewer1.LocalReport con la ruta relativa utilizando el punto o el símbolo ~
    * No cambies el ProcessingMode a Remote. Déjalo en local.

    un saludo.

  8. Estimado @toniogago: muchísimas gracias por compartir tu experiencia, estoy armando una Aplicación Web en ASP con Visual Basic usando VS 2008.

    Trabajando de forma Local y con IIS (Win7-64) + SQL Server Express 2008 R2 Mi código quedo así:

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
    ReportViewer1.Visible = True
    Dim warnings As Warning() = Nothing
    Dim streamids As String() = Nothing
    Dim mimeType As String = Nothing
    Dim encoding As String = Nothing
    Dim extension As String = «.pdf»
    Dim bytes As Byte()

    bytes = ReportViewer1.LocalReport.Render(«PDF», Nothing, mimeType, encoding, extension, streamids, warnings)
    Dim ms As New System.IO.MemoryStream(bytes)
    Response.ContentType = «Application/pdf»
    Response.BinaryWrite(ms.ToArray())
    Response.End()
    ReportViewer1.Visible = False
    End Sub

    Ya veremos cuando lo pase al ambiente de desarrollo en el trabajo… otra vez a pelear… Saludos!

  9. Hola Antonio,

    Gracias por compartir tu conocimiento, en mi caso estoy usando el localreport ya que no tengo un servidor de reportes, el inconveniente que tengo es que de manera local en mi laptop funciona, pero al pasar a un servidor web no, por favor tu apoyo, muchas gracias de antemano.

    El código que estoy usando es el siguiente:

    public ActionResult Imprimir(string idComprobante)
    {
    try
    {
    string Reporttype = «PDF»;
    string fileExtencion;
    string mimeType;
    string encodig;

    using (var db = new DBEntities())
    {
    //Directorio de almacenamiento
    var path01 = Server.MapPath(«~/Reportes»);
    if (!Directory.Exists(path01))
    Directory.CreateDirectory(path01);
    //Fin

    LocalReport localReport = new LocalReport();
    localReport.ReportPath = Server.MapPath(«~/Reportes/Report1.rdlc»);

    localReport.Refresh();
    localReport.EnableExternalImages = true;

    ReportDataSource reportDataSource = new ReportDataSource();
    reportDataSource.Name = «ComprobantesDataSet»;
    reportDataSource.Value = db.sp_Reporte(Convert.ToInt32(id)).ToList();
    localReport.DataSources.Add(reportDataSource);
    localReport.Refresh();

    fileExtension = «application/pdf «pdf»;

    string[] streams;
    Warning[] warnings;
    byte[] renderByte;
    var fileName = «001-000001»;

    renderByte = localReport.Render(Reporttype, «», out mimeType, out encodig, out fileExtension, out streams, out warnings);
    Response.AddHeader(«content-disposition», «attachment;filename =» + fileName + «.» + fileExtension);

    //Guardamos el Archivo en la ruta asignada
    string rutaArchivo = Server.MapPath(«~/Reportes/» + fileName + fileExtension);
    FileStream fs = System.IO.File.Create(path01 + «/» + fileName + fileExtension);
    fs.Write(renderByte, 0, renderByte.Length);
    fs.Close();

    return File(renderByte, «pdf»);
    }
    }
    catch (Exception e)
    {
    System.IO.StreamWriter sw = new System.IO.StreamWriter(ruta, true);
    string texto;
    texto = » MESSAGE: » + e.Message.ToString() + » SOURCE: » + e.Source + » STACKTRACE: » + e.StackTrace;
    sw.WriteLine(texto);
    sw.Close();

    HttpContext.Response.StatusCode = 500;
    return Json(Util.errorJson(e));
    }
    }

    El error que obtengo es el siguiente:
    MESSAGE: An error occurred during local report processing.
    SOURCE: Microsoft.ReportViewer.WebForms STACKTRACE: at Microsoft.Reporting.WebForms.LocalReport.EnsureExecutionSession()
    at Microsoft.Reporting.WebForms.LocalReport.InternalRender(String format, Boolean allowInternalRenderers, String deviceInfo, PageCountMode pageCountMode, CreateAndRegisterStream createStreamCallback, Warning[]& warnings)
    at Microsoft.Reporting.WebForms.LocalReport.InternalRender(String format, Boolean allowInternalRenderers, String deviceInfo, PageCountMode pageCountMode, String& mimeType, String& encoding, String& fileNameExtension, String[]& streams, Warning[]& warnings)
    at Microsoft.Reporting.WebForms.LocalReport.Render(String format, String deviceInfo, PageCountMode pageCountMode, String& mimeType, String& encoding, String& fileNameExtension, String[]& streams, Warning[]& warnings)
    at Microsoft.Reporting.WebForms.Report.Render(String format)
    at Web.Controllers.VentaController.Imprimir(String idComprobante) in C:\Web\Controllers\VentaController.cs:line 292

  10. Estimados,

    Resolví el error, imprimí el error completo, en el que me indicaba que faltaba la dll: Microsoft.SqlServer.Types.dll, por alguna razón necesita esta dll.

    Microsoft.Reporting.WebForms.LocalProcessingException: An error occurred during local report processing. —> Microsoft.Reporting.DefinitionInvalidException: The definition of the report ‘h:\…..\Report1.rdlc’ is invalid. —> Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: An unexpected error occurred in Report Processing. —> System.IO.FileNotFoundException: Could not load file or assembly ‘Microsoft.SqlServer.Types, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91’ or one of its dependencies. The system cannot find the file specified.

    Espero los ayude.

    Saludos.

Deja un comentario