ReportViewer sem DataSet Tipado e gerando PDF

Hoje eu vou falar um pouco sobre o ReportViewer sem DataSet Tipado dentro do seu aplicativo. O ReportViewer veio para facilitar o desenvolvedor na criação de relatório, pdf e tudo mais.

Só que, com ele veio o péssimo procedimento de usar Dataset Tipado. Não sei se você gosta de usar DataSet Tipado, eu pessoalmente não gosto por alguns motivos que não vou discutir por aqui.

O objetivo geral foi passar dinamicamente um datatable para o arquivo com extensão .rdlc e gerar automaticamente um pdf na tela do usuário, isso tudo sem gerar conexão pelo wizard. O ReportViewer não funciona em todos os servidores da internet, precisa ter instalado um pacote simples para que funcione. Antes de hospedar o seu site em qualquer servidor, pergunte se o mesmo possui suporte para esse tipo de relatório.

O path para instalação é simples e grátis na internet, basta baixar e instalar. O servidor não precisa ser reiniciado. Lembro também que, precisa ser instalado de acordo com a ferramenta de desenvolvimento, por exemplo: Para o VS.NET 2005, é necessário instalar a versão 2005. Para o Visual Studio .NET 2008, precisa instalar a versão do ReportViewer 2008.

Usado: Visual Studio .NET 2010, linguagem C#.NET, Relatório com ReportViewer

Montando a p√°gina

Dentro da ferramenta Visual Studio.NET 2010 foi gerado a tag do relatório ao arrastar o componente do ToolBox. Imagem 1.


Imagem 1

Depois de pegar o componente no toolbox, foi gerado pela ferramenta um registro no topo da p√°gina. (Code 1)

 

<%@ Register assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" namespace="Microsoft.Reporting.WebForms" tagprefix="rsweb" %>

 


Code 1

Depois do código no topo da página Default.aspx, dentro da tag coloquei código do reportviewer. (Code 2)

 

<rsweb:ReportViewer ID="ReportViewer1" runat="server" Width="940px" Font-Names="Verdana" Font-Size="8pt" Height="400px" >

 <LocalReport ReportEmbeddedResource=" Report1.rdlc" ReportPath="Report1.rdlc" >

   <DataSources>

       <rsweb:ReportDataSource DataSourceId="ObjectDataSource1" Name="dsRelatorios" />

   </DataSources>

 </LocalReport>

</rsweb:ReportViewer>

 

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"

 OldValuesParameterFormatString="original_{0}" SelectMethod="GetData">

</asp:ObjectDataSource>

 

Code 2

Note que na tag existe o nome do arquivo .rdlc e logo abaixo tive que colocar um datasources fictício, pois não é o meu objetivo gerar um objectdatasource. Depois de fechar a tag do ReportViewer, coloquei o objectDataSource que não se conecta em nada. O vínculo do report com o objeto é através do DataSourceId e o Id. Pode-se notar que tem o mesmo nome.

Editando ReportViewer

Depois de gerar o código na página, preciso gerar o arquivo de relatório chamado .rdlc. Utilizei o editor em XML para gerar e colocar campos, isto é, não utilizei o winzard da própria ferramenta porque ela pede o tal do objeto que não tenho e não quero criar.

Depois de criar um novo arquivo para reportViewer cliquei com o bot√£o direito e acessei o abrir com. Depois escolhi o editor XML. (Imagem 2).

Imagem 2

O próximo passo foi editar o arquivo XML. (Code 3)

 

<?xml version="1.0" encoding="utf-8"?>

<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition">

  <DataSources>

    <DataSource Name="dbConnectionString">

      <ConnectionProperties>

        <DataProvider />

        <ConnectString />

      </ConnectionProperties>

      <rd:DataSourceID>812609e6-e34e-4f00-a417-0cb8e2a63aa5</rd:DataSourceID>

    </DataSource>

  </DataSources>

  <DataSets>

    <DataSet Name="dsRelatorio_Dinamico">

      <Fields>

        <Field Name="GuiaId">

          <DataField>GuiaId</DataField>

          <rd:TypeName>System.String</rd:TypeName>

        </Field>

        <Field Name="Item">

          <DataField>Item</DataField>

          <rd:TypeName>System.String</rd:TypeName>

        </Field>

      </Fields>

      <Query>

        <DataSourceName>dbConnectionString</DataSourceName>

        <CommandText>spu_RemessaDigitalizada_Lista</CommandText>

        <rd:UseGenericDesigner>true</rd:UseGenericDesigner>

      </Query>

      <rd:DataSetInfo>

        <rd:DataSetName>dsRelatorios</rd:DataSetName>

        <rd:TableName>spu_RemessaDigitalizada_Lista</rd:TableName>

        <rd:TableAdapterFillMethod />

        <rd:TableAdapterGetDataMethod>GetData</rd:TableAdapterGetDataMethod>

        <rd:TableAdapterName />

      </rd:DataSetInfo>

    </DataSet>

  </DataSets>

  <Body>

    <ReportItems>

      <Tablix Name="tbRemessaDig">

        <TablixBody>

          <TablixColumns>

            <TablixColumn>

              <Width>1.6624in</Width>

            </TablixColumn>

            <TablixColumn>

              <Width>1.69688in</Width>

            </TablixColumn>

          </TablixColumns>

          <TablixRows>

            <TablixRow>

              <Height>0.21997in</Height>

              <TablixCells>

                <TablixCell>

                  <CellContents>

                    <Textbox Name="textbox2">

                      <CanGrow>true</CanGrow>

                      <KeepTogether>true</KeepTogether>

                      <Paragraphs>

                        <Paragraph>

                          <TextRuns>

                            <TextRun>

                              <Value>Remessa</Value>

                              <Style>

                                <FontFamily>Verdana</FontFamily>

                                <FontSize>9pt</FontSize>

                                <FontWeight>Bold</FontWeight>

                                <Color>White</Color>

                              </Style>

                            </TextRun>

                          </TextRuns>

                          <Style>

                            <TextAlign>Center</TextAlign>

                          </Style>

                        </Paragraph>

                      </Paragraphs>

                      <rd:DefaultName>textbox2</rd:DefaultName>

                      <ZIndex>15</ZIndex>

                      <Style>

                        <Border>

                          <Color>LightGrey</Color>

                          <Style>Solid</Style>

                        </Border>

                        <BackgroundColor>SteelBlue</BackgroundColor>

                        <VerticalAlign>Middle</VerticalAlign>

                        <PaddingLeft>2pt</PaddingLeft>

                        <PaddingRight>2pt</PaddingRight>

                        <PaddingTop>2pt</PaddingTop>

                        <PaddingBottom>2pt</PaddingBottom>

                      </Style>

                    </Textbox>

                  </CellContents>

                </TablixCell>

                <TablixCell>

                  <CellContents>

                    <Textbox Name="textbox3">

                      <CanGrow>true</CanGrow>

                      <KeepTogether>true</KeepTogether>

                      <Paragraphs>

                        <Paragraph>

                          <TextRuns>

                            <TextRun>

                              <Value>Item</Value>

                              <Style>

                                <FontFamily>Verdana</FontFamily>

                                <FontSize>9pt</FontSize>

                                <FontWeight>Bold</FontWeight>

                                <Color>White</Color>

                              </Style>

                            </TextRun>

                          </TextRuns>

                          <Style>

                            <TextAlign>Center</TextAlign>

                          </Style>

                        </Paragraph>

                      </Paragraphs>

                      <rd:DefaultName>textbox3</rd:DefaultName>

                      <ZIndex>14</ZIndex>

                      <Style>

                        <Border>

                          <Color>LightGrey</Color>

                          <Style>Solid</Style>

                        </Border>

                        <BackgroundColor>SteelBlue</BackgroundColor>

                        <VerticalAlign>Middle</VerticalAlign>

                        <PaddingLeft>2pt</PaddingLeft>

                        <PaddingRight>2pt</PaddingRight>

                        <PaddingTop>2pt</PaddingTop>

                        <PaddingBottom>2pt</PaddingBottom>

                      </Style>

                    </Textbox>

                  </CellContents>

                </TablixCell>

              </TablixCells>

            </TablixRow>

            <TablixRow>

              <Height>0.20997in</Height>

              <TablixCells>

                <TablixCell>

                  <CellContents>

                    <Textbox Name="GuiaId">

                      <CanGrow>true</CanGrow>

                      <KeepTogether>true</KeepTogether>

                      <Paragraphs>

                        <Paragraph>

                          <TextRuns>

                            <TextRun>

                              <Value>=Fields!GuiaId.Value</Value>

                              <Style>

                                <FontSize>9pt</FontSize>

                              </Style>

                            </TextRun>

                          </TextRuns>

                          <Style>

                            <TextAlign>Center</TextAlign>

                          </Style>

                        </Paragraph>

                      </Paragraphs>

                      <rd:DefaultName>RemessaDigitalizadaId</rd:DefaultName>

                      <ZIndex>7</ZIndex>

                      <Style>

                        <Border>

                          <Color>LightGrey</Color>

                          <Style>Solid</Style>

                        </Border>

                        <VerticalAlign>Middle</VerticalAlign>

                        <PaddingLeft>2pt</PaddingLeft>

                        <PaddingRight>2pt</PaddingRight>

                        <PaddingTop>2pt</PaddingTop>

                        <PaddingBottom>2pt</PaddingBottom>

                      </Style>

                    </Textbox>

                  </CellContents>

                </TablixCell>

                <TablixCell>

                  <CellContents>

                    <Textbox Name="Item">

                      <CanGrow>true</CanGrow>

                      <KeepTogether>true</KeepTogether>

                      <Paragraphs>

                        <Paragraph>

                          <TextRuns>

                            <TextRun>

                              <Value>=Fields!Item.Value</Value>

                              <Style>

                                <FontSize>9pt</FontSize>

                              </Style>

                            </TextRun>

                          </TextRuns>

                          <Style>

                            <TextAlign>Center</TextAlign>

                          </Style>

                        </Paragraph>

                      </Paragraphs>

                      <rd:DefaultName>Item</rd:DefaultName>

                      <Style>

                        <Border>

                          <Color>LightGrey</Color>

                          <Style>Solid</Style>

                        </Border>

                        <VerticalAlign>Middle</VerticalAlign>

                        <PaddingLeft>2pt</PaddingLeft>

                        <PaddingRight>2pt</PaddingRight>

                        <PaddingTop>2pt</PaddingTop>

                        <PaddingBottom>2pt</PaddingBottom>

                      </Style>

                    </Textbox>

                  </CellContents>

                </TablixCell>

              </TablixCells>

            </TablixRow>

          </TablixRows>

        </TablixBody>

        <TablixColumnHierarchy>

          <TablixMembers>

            <TablixMember />

            <TablixMember />

          </TablixMembers>

        </TablixColumnHierarchy>

        <TablixRowHierarchy>

          <TablixMembers>

            <TablixMember>

              <KeepWithGroup>After</KeepWithGroup>

              <RepeatOnNewPage>true</RepeatOnNewPage>

              <KeepTogether>true</KeepTogether>

            </TablixMember>

            <TablixMember>

              <Group Name="tbRemessaDig_Details_Group">

                <DataElementName>Detail</DataElementName>

              </Group>

              <TablixMembers>

                <TablixMember />

              </TablixMembers>

              <DataElementName>Detail_Collection</DataElementName>

              <DataElementOutput>Output</DataElementOutput>

              <KeepTogether>true</KeepTogether>

            </TablixMember>

          </TablixMembers>

        </TablixRowHierarchy>

        <DataSetName>dsRelatorio_Dinamico</DataSetName>

        <Top>2.01083cm</Top>

        <Left>6.24417cm</Left>

        <Height>1.09205cm</Height>

        <Width>8.53257cm</Width>

        <Style />

      </Tablix>

      <Textbox Name="textbox1">

        <CanGrow>true</CanGrow>

        <KeepTogether>true</KeepTogether>

        <Paragraphs>

          <Paragraph>

            <TextRuns>

              <TextRun>

                <Value>Relat√≥rio de Teste</Value>

                <Style>

                  <FontFamily>Tahoma</FontFamily>

                  <FontSize>20pt</FontSize>

                  <FontWeight>Bold</FontWeight>

                  <Color>SteelBlue</Color>

                </Style>

              </TextRun>

            </TextRuns>

            <Style>

              <TextAlign>Center</TextAlign>

            </Style>

          </Paragraph>

        </Paragraphs>

        <rd:DefaultName>textbox1</rd:DefaultName>

        <Top>0.17639cm</Top>

        <Left>4.33917cm</Left>

        <Height>1cm</Height>

        <Width>13.20229cm</Width>

        <ZIndex>1</ZIndex>

        <Style>

          <VerticalAlign>Middle</VerticalAlign>

          <PaddingLeft>2pt</PaddingLeft>

          <PaddingRight>2pt</PaddingRight>

          <PaddingTop>2pt</PaddingTop>

          <PaddingBottom>2pt</PaddingBottom>

        </Style>

      </Textbox>

    </ReportItems>

    <Height>3.95602cm</Height>

    <Style>

      <Border />

    </Style>

  </Body>

  <Width>21.50424cm</Width>

  <Page>

    <PageHeight>29.7cm</PageHeight>

    <PageWidth>21cm</PageWidth>

    <InteractiveHeight>11in</InteractiveHeight>

    <InteractiveWidth>8.5in</InteractiveWidth>

    <LeftMargin>2.5cm</LeftMargin>

    <RightMargin>2.5cm</RightMargin>

    <TopMargin>2.5cm</TopMargin>

    <BottomMargin>2.5cm</BottomMargin>

    <ColumnSpacing>1cm</ColumnSpacing>

    <Style />

  </Page>

  <Language>en-US</Language>

  <ConsumeContainerWhitespace>true</ConsumeContainerWhitespace>

  <rd:ReportID>f3e827ec-35d4-44d6-bb88-e1f8f29e5717</rd:ReportID>

  <rd:ReportUnitType>Cm</rd:ReportUnitType>

</Report>

 

Code 3

O mais importante de todo esse código são as primeiras linhas. Resolvi colocar todo o código para que possa copiar sem qualquer problema. Veja os códigos importantes desse XML que na verdade é o relatório. (Code 4)

 

<DataSources>

    <DataSource Name="dbConnectionString">

      <ConnectionProperties>

        <DataProvider />

        <ConnectString />

      </ConnectionProperties>

      <rd:DataSourceID>812609e6-e34e-4f00-a417-0cb8e2a63aa5</rd:DataSourceID>

    </DataSource>

  </DataSources>

  <DataSets>

    <DataSet Name="dsRelatorio_Dinamico">

      <Fields>

        <Field Name="GuiaId">

          <DataField>GuiaId</DataField>

          <rd:TypeName>System.String</rd:TypeName>

        </Field>

        <Field Name="Item">

          <DataField>Item</DataField>

          <rd:TypeName>System.String</rd:TypeName>

        </Field>

      </Fields>

….

Code 4

Existe a parte da conex√£o que dei o nome de dbConnectionString, depois coloquei um DataSet chamado dsRelatorio_Dinamico e dentro dele dois campos chamados GuiaId e Item. Essas vari√°veis s√£o necess√°rias para n√£o dar problema. Talvez ficaria mais f√°cil usar datasettipado, mas como n√£o gosto prefiro ter um pouco de m√£o de obra para n√£o me arrepender depois.

Para abrir o relatório no modo designer, fechei o arquivo de edição XML e cliquei duas vezes em cima do Report1.rdlc. O toolbox apareceu com os dados atribuídos. (Imagem 3).


Imagem 3

Os campos apareceram. (Imagem 4)


Imagem 4

Dentro do relatório, pode ser acrescentado qualquer campo agora sem precisar mudar o XML, usando o designer torna-se possível e sem qualquer problema.

Preenchendo os campos e chamando o relatório em tempo de execução

O passo seguinte √© pegar o datatable vindo do banco de dados ou de teste (como o nosso exemplo), passar os dados para o relat√≥rio e exibir o pdf na tela. Dentro do Load da p√°gina escrevi algumas linhas de c√≥digo. Gerei um m√©todo que gera datatable din√Ęmico fora do Load. (Code 5)

 

private DataTable BuscaDadosTable()

        {

 

            DataTable table = new DataTable("tabela");

            table.Columns.Add("GuiaId", typeof(int));

            table.Columns.Add("Item", typeof(string));

 

            DataRow row;

            for (int i = 0; i < 10; i++)

            {

                row = table.NewRow();

                row["GuiaId"] = i;

                row["Item"] = "Item" + i;

                table.Rows.Add(row);

            }

            return table;

        }

 

Code 5

O datatable ser√° retornado com os mesmos campos do arquivo Report1.rdlc (GuiaId e Item). Geralmente, estes campos s√£o retornados de um banco de dados, WebService ou outro tipo de dado, fiz assim para n√£o ter problema.

O método Load da página Default.aspx possui o Code 6.

 

protected void Page_Load(object sender, EventArgs e)

        {

            if (!IsPostBack)

            {

                try

                {

                    ReportDataSource RDS = new ReportDataSource("dsRelatorio_Dinamico", BuscaDadosTable());

 

                    ReportViewer1.Visible = true;

                    ReportViewer1.LocalReport.DataSources.Clear();

                    ReportViewer1.Reset();

                    ReportViewer1.LocalReport.ReportPath = "Report1.rdlc";

                    ReportViewer1.LocalReport.DataSources.Add(RDS);

                    ReportViewer1.LocalReport.Refresh();

 

                    Warning[] warnings;

                    string[] streamids;

                    string mimeType;

                    string encoding;

                    string extension;

 

                    string deviceInfo =

                      "<DeviceInfo>" +

                      "  <OutputFormat>PDF</OutputFormat>" +

                      "  <PageWidth>21cm</PageWidth>" +

                      "  <PageHeight>29cm</PageHeight>" +

                      "  <MarginTop>0.1in</MarginTop>" +

                      "  <MarginLeft>0in</MarginLeft>" +

                      "  <MarginRight>0in</MarginRight>" +

                      "  <MarginBottom>0.1in</MarginBottom>" +

                      "</DeviceInfo>";

 

                    byte[] bytes = ReportViewer1.LocalReport.Render("PDF", deviceInfo, out mimeType, out encoding, out extension, out streamids, out warnings);

 

                    HttpContext.Current.Response.Buffer = true;

                    HttpContext.Current.Response.Clear();

                    HttpContext.Current.Response.ContentType = mimeType;

                    HttpContext.Current.Response.AddHeader("content-disposition", ("inline; filename=ExportedReport." + "PDF"));

                    HttpContext.Current.Response.BinaryWrite(bytes);

                    HttpContext.Current.Response.Flush();

                    HttpContext.Current.Response.End();

                }

                catch (Exception ex)

                {

                    throw ex;

                }

            }

        }

 

Code 6

Depois de verificar se a página não é isPostBack, usei o ReportDataSource passando o datatable e o nome do colocado dentro do XML (dsRelatorio_Dinamico). Depois da primeira linha, uso as propriedades. (Code 7)

 

ReportViewer1.Visible = true;

ReportViewer1.LocalReport.DataSources.Clear();

ReportViewer1.Reset();

ReportViewer1.LocalReport.ReportPath = "Report1.rdlc";

ReportViewer1.LocalReport.DataSources.Add(RDS);

ReportViewer1.LocalReport.Refresh();

 

Code 7

No Code 7, coloquei o endereço do arquivo .rdlc. Se o mesmo estiver dentro de uma pasta, não esqueça de colocar o nome da pasta antes obedecendo a estrutura de diretórios. A próxima parte funciona apenas para gerar o pdf e mostrar na tela. Por isso que uso o Flush(). (Code 8)

 

                    Warning[] warnings;

                    string[] streamids;

                    string mimeType;

                    string encoding;

                    string extension;

 

                    string deviceInfo =

                      "<DeviceInfo>" +

                      "  <OutputFormat>PDF</OutputFormat>" +

                      "  <PageWidth>21cm</PageWidth>" +

                      "  <PageHeight>29cm</PageHeight>" +

                      "  <MarginTop>0.1in</MarginTop>" +

                      "  <MarginLeft>0in</MarginLeft>" +

                      "  <MarginRight>0in</MarginRight>" +

                      "  <MarginBottom>0.1in</MarginBottom>" +

                      "</DeviceInfo>";

 

                    byte[] bytes = ReportViewer1.LocalReport.Render("PDF", deviceInfo, out mimeType, out encoding, out extension, out streamids, out warnings);

 

                    HttpContext.Current.Response.Buffer = true;

                    HttpContext.Current.Response.Clear();

                    HttpContext.Current.Response.ContentType = mimeType;

                    HttpContext.Current.Response.AddHeader("content-disposition", ("inline; filename=ExportedReport." + "PDF"));

                    HttpContext.Current.Response.BinaryWrite(bytes);

                    HttpContext.Current.Response.Flush();

                    HttpContext.Current.Response.End();

 

Code 8

Todos os par√Ęmetros criados in√≠cio do Code 8 precisam ser passados para gerar corretamente o PDF na tela. Veja o resultado final do que foi escrito. Imagem 5.


Imagem 5

Espero que tenha gostado, qualquer d√ļvida pode entrar em contato.