Julho 2009 - Posts
Num artigo anterior, mostrei como utilizar Custom Code num relatório. Isto é muito útil se for necessário personalizar alguma coisa, mas se precisarmos de fazer esta operação em diversos relatórios ? Bem, podemos usar as Custom Assemblies.
Para usar Custom Assemblies num relatório, é apenas necessário criar um projecto do tipo Class Library, que irá originar um *.dll, e usar esta biblioteca em todos os relatórios.
Depois de criado o ficheiro/biblioteca, é necessário copiar o *.dll para as pastas Release/Debug da aplicação, e para a pasta PrivateAssemblies (no Visual Studio 2008 está normalmente em C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\)
Para este exemplo criei uma pequena classe, que irá cortar algum texto caso o tamanho do texto seja igual ou superior a 30:
Public Class rptClass
Public Function CutText(ByVal txt As String) As String
If txt.Length >= 30 Then
Return txt.Substring(0, 26) & " ..."
Else
Return txt
End If
End Function
Public Shared Function SharedCutText(ByVal txt As String) As String
If txt.Length >= 30 Then
Return txt.Substring(0, 26) & " ..."
Else
Return txt
End If
End Function
End Class
Depois, é necessário adicionar uma referência no relatório para a biblioteca. Abrir o relatório, e no menu Reports, seleccionar a opção Report Properties. No separador References, seleccionar o *.dll criado.
NOTA: O nome da biblioteca (Assembly Name) irá ser usado mais tarde no código
Nesta janela existem 2 grelhas:
References: Se forem usados métodos definidos como Shared, é possível invocá-los directamente
Classes: Se não forem usados métodos Shared, é necessário criar uma nova instância da classe (tem de ser escrito directamente na grelha)
Depois, no relatório, podemos usar da seguinte forma:
Como podem ver, se for criada uma nova instância da classe, é necessário definir como =Code.<instância criada>.<nome do método>
Finalmente, e no código, é necessário definir que a classe criada (biblioteca) é Trusted Code, usando o Assembly Name usado nas referências:
Me.ReportViewer1.LocalReport.AddTrustedCodeModuleInCurrentAppDomain( _
"ClassLibrary1, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null")
PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!
As Lambda Expressions são funções anónimas que podem conter expressões e declarações, e que podem ser usadas para criar expressões ou Delegates. As Lambda Expressions são uma novidade do Visual Studio 2008, e utilizam métodos anónimos (Anonymous Methods), não sendo por isso necessário declarar o tipo de variáveis usadas. As Lambda Expressions conseguem detectar o tipo de dados usados, sendo por isso necessário definir Option Infer On (está por defeito desta forma).
Um exemplo simples de uma expressão Lambda:
Dim lambda1 As Func(Of Integer, Integer) = Function(x) x * x
Debug.WriteLine(lambda1(2).ToString())
Neste pequena expressão, e criado uma Func Delegate, que irá receber um valor do tipo Integer e devolver como resultado do tipo Integer. Irá depois multiplicar o valor recebido e, neste exemplo, o resultado será 4.
Um exemplo um pouco mais complexo, mas também bastante simples de entender:
Dim lambda2 As Func(Of Integer, String) = _
Function(x) If(x <= 10, 10, x * x).ToString()
Debug.WriteLine(lambda2(15))
Neste caso, irá ser indicado um Integer e devolvido uma String, sendo efectuada uma verificação. Caso o valor indicado seja menor ou igual a 10, irá devolver 10, caso contrário, irá devolver o dobro do valor indicado. Neste caso o resultado será 255.
Isto é semelhante a criar uma função externa, que faça esta validação, mas apenas numa linha de código.
Mas existem mais aplicações para as expressões Lambda. Por exemplo para atribuir Delegates a um objecto:
Dim btn As New Button() With {.Text = "Go ...", .Name = "New Button"}
Me.Controls.Add(btn)
AddHandler btn.Click, Function(s, ev) MessageBox.Show(DirectCast(s, Button).Name)
Este exemplo adiciona um botão ao Form e irá mostrar o nome do botão quando este for clicado. O “s” é o Sender e o “ev” o EventArgs. No entanto, apenas na versão 2010, é possível criar funções mais complexas, com mais linhas, sendo que o C# 3.0 já o permite.
Mas mais alguns exemplos de como as expressões Lambda podem ajudar em simplificar o código. Considerando esta simples classe para demonstração:
' O atributo DebuggerStepThrough() irá fazer que o compilador
' não pare enquanto se está a fazer o debug no código do programa
<Diagnostics.DebuggerStepThrough()> _
Public Class student
Private m_Name As String
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
End Set
End Property
Private m_Age As Int16
Public Property Age() As Int16
Get
Return m_Age
End Get
Set(ByVal value As Int16)
m_Age = value
End Set
End Property
End Class
A esta simples classe, apenas com duas propriedades – Name, Age – iremos criar uma lista, do tipo student, e adicionar alguns registos.
' Cria uma nova lista de estudantes (Classe student)
Dim studentList As New List(Of student)
' Adiciona vários registos com idades aleatórias entre os 6 ao 50 anos
Dim rnd As New Random
For x As Short = 0 To 999
Dim newStudent As New student() With { _
.Name = "Student "& x.ToString, _
.Age = CShort(rnd.Next(6, 50))}
studentList.Add(newStudent)
Next
Ok, com a classe criada e com uma lista do tipo student vamos filtrar informação! Vamos procurar todos os teenagers na lista (dos 13 aos 19).
Alguns exemplos de como podemos filtrar os dados:
Usando Delegates
Criamos uma função no programa, que retorna um resultado booleano:
Function GetTeenagers(ByVal s As student) As Boolean
Return s.Age >= 13 And s.Age <= 19
End Function
E depois:
Dim delResult As List(Of student) = _
studentList.FindAll(New Predicate(Of student)(AddressOf GetTeenagers))
For Each s As student In delResult
Debug.WriteLine(String.Format("Name: {0}, Age: {1}", s.Name, s.Age))
Next
Usando LINQ to Objects
Dim linqResult = From s As student In studentList _
Let st As student = DirectCast(s, student) _
Where st.Age >= 13 And st.Age <= 19 _
Select st
For Each s As student In linqResult
Debug.WriteLine(String.Format("Name: {0}, Age: {1}", s.Name, s.Age))
Next
Usando Lambda Expressions
Dim lambdaResult As List(Of student) = _
studentList.Where(Function(s) s.Age >= 13 And s.Age <= 19).ToList()
For Each s As student In lambdaResult
Debug.WriteLine(String.Format("Name: {0}, Age: {1}", s.Name, s.Age))
Next
Simples e prático!
Além disso podemos ainda, de uma forma bastante simples, fazer algumas operações, como calcular a média de idades ou somar todas as idades:
' Calcula a médias de idades
Dim average = studentList.Average(Function(s) s.Age)
Debug.WriteLine(average.ToString)
' Soma todas as idades
Dim sum = studentList.Sum(Function(s) s.Age)
Debug.WriteLine(sum.ToString)
Ou procurar um registo na studentList:
Dim found = studentList.Find(Function(s) s.Name = "Student 5")
If found IsNot Nothing Then
Debug.WriteLine(found.Age.ToString())
End If
Como podem ver, as Lambda Expressions podem simplificar algumas operações no código e versão 2010 do Visual Studio irá potenciar ainda mais a sua utilização.
Estas são algumas das aplicações, mas existem mais, que oportunamente poderei mostrar.
Em dois artigos anteriores, mostrei como se pode de uma forma simples, exportar e imprimir um relatório (*.rdlc) sem a utilização do controlo ReportViewer.
VB.NET: Microsoft Reports – Imprimir sem utilizar o ReportViewer
VB.NET: Microsoft Reports – Exportar Relatórios
No entanto, o exemplo de impressão que mostrei funcionava apenas caso o relatório estivesse definido com Portrait(retrato). Isto porque o método Render() é feito para uma definição, através do DeviceInfo, especifica para este formato. Para imprimir como Landscape(paisagem) é apenas necessário alterar essa definição.
Como surgiram algumas dúvidas, resolvi mostrar a classe alterada e que normalmente uso, com a possibilidade de definir no método Print(), o formato da impressão.
Os exemplos de utilização e comentários, estão disponíveis nos artigos anteriores.
Imports System.IO
Imports System.Data
Imports System.Text
Imports System.Drawing.Imaging
Imports System.Drawing.Printing
Imports System.Collections.Generic
Imports Microsoft.Reporting.WinForms
Public Class ReportUtils
Implements IDisposable
#Region "Export"
Enum rptFormat
Excel
PDF
Image
End Enum
'''<summary>
''' Exporta um LocalReport para um formato definido
'''</summary>
'''<param name="report">LocalReport</param>
'''<param name="output">Formato final</param>
'''<remarks></remarks>
Public Sub Export(ByVal report As LocalReport, ByVal output As rptFormat)
Try
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 = report.Render(output.ToString, Nothing, _
mimeType, encoding, extension, streamids, warnings)
Dim filePath As String = My.Computer.FileSystem.GetTempFileName()
Select Case output
Case rptFormat.Excel
filePath = Path.ChangeExtension(filePath, "xls")
Case rptFormat.Image
filePath = Path.ChangeExtension(filePath, "jpg")
Case rptFormat.PDF
filePath = Path.ChangeExtension(filePath, "pdf")
End Select
Using fs As New IO.FileStream(filePath, IO.FileMode.Create)
fs.Write(bytes, 0, bytes.Length)
fs.Close()
End Using
bytes = Nothing
Process.Start(filePath)
Catch ex As Exception : End Try
End Sub
'''<summary>
''' Exporta um LocalReport para um formato definido
'''</summary>
'''<param name="report">LocalReport</param>
'''<param name="output">Formato final</param>
'''<param name="filePath">Caminho para o ficheiro</param>
'''<remarks></remarks>
Public Sub Export(ByVal report As LocalReport, _
ByVal output As rptFormat, _
ByVal filePath As String)
Try
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 = report.Render(output.ToString, Nothing, _
mimeType, encoding, extension, streamids, warnings)
Using fs As New IO.FileStream(filePath, IO.FileMode.Create)
fs.Write(bytes, 0, bytes.Length)
fs.Close()
End Using
bytes = Nothing
Catch ex As Exception : End Try
End Sub
#End Region
#Region "Print"
Private currentPageIndex As Integer
Private tmpFileName As String = String.Empty
Private streamList As List(Of Stream)
Enum Orientation
Landscape
Portrait
End Enum
''' <summary>
''' Adiciona a stream à lista de streams
''' </summary>
Private Function CreateStream(ByVal name As String, _
ByVal fileNameExtension As String, _
ByVal encoding As Encoding, _
ByVal mimeType As String, _
ByVal willSeek As Boolean) As Stream
tmpFileName = My.Computer.FileSystem.GetTempFileName()
Dim s As New FileStream(tmpFileName, FileMode.Create)
streamList.Add(s)
Return s
End Function
''' <summary>
''' Exporta o ficheiro para uma lista de Streams
''' </summary>
Private Sub ExportToStream(ByVal report As LocalReport, _
ByVal Orientation AsOrientation)
Dim deviceInfo As New StringBuilder
With deviceInfo
.Append("<DeviceInfo>")
.Append(" <OutputFormat>EMF</OutputFormat>")
If Orientation = ReportUtils.Orientation.Portrait Then
.Append(" <PageWidth>8.5in</PageWidth>")
.Append(" <PageHeight>11.5in</PageHeight>")
Else
.Append(" <PageWidth>11.5in</PageWidth>")
.Append(" <PageHeight>8.5in</PageHeight>")
End If
.Append(" <MarginTop>0.3in</MarginTop>")
.Append(" <MarginLeft>0.3in</MarginLeft>")
.Append(" <MarginRight>0.3in</MarginRight>")
.Append(" <MarginBottom>0.3in</MarginBottom>")
.Append("</DeviceInfo>")
End With
Dim warnings() As Warning = Nothing
report.Render("Image", deviceInfo.ToString, _
AddressOf CreateStream, warnings)
For Each s As Stream In streamList
s.Position = 0
Next
deviceInfo = Nothing
End Sub
'''<summary>
''' Quando o PrintDocument está a imprimir, desenha
''' a página correspondente da lista de Stream
'''</summary>
Private Sub PrintPage(ByVal sender As Object, _
ByVal ev As PrintPageEventArgs)
Using pageImage As New Metafile(streamList(currentPageIndex))
currentPageIndex += 1
ev.Graphics.DrawImage(pageImage, ev.PageBounds)
ev.HasMorePages = (currentPageIndex < streamList.Count)
End Using
End Sub
'''<summary>
''' Imprime um relatório sem visualização
'''</summary>
'''<param name="report">Relatório a imprimir</param>
Public Sub Print(ByVal report As LocalReport, ByVal Orientation As Orientation)
streamList = New List(Of Stream)
' Exporta o ficheiro para uma lista de Streams
Call ExportToStream(report, Orientation)
If streamList IsNot Nothing AndAlso streamList.Count > 0 Then
' Inicia o processo de impressão
Using printDoc As New PrintDocument()
If Not printDoc.PrinterSettings.IsValid Then
Dim msg As String= "Impressora não disponível ou não válida!"
Throw New ArgumentException(msg)
End If
AddHandler printDoc.PrintPage, AddressOf PrintPage
If Orientation = ReportUtils.Orientation.Portrait Then
printDoc.DefaultPageSettings.Landscape = False
Else
printDoc.DefaultPageSettings.Landscape = True
End If
printDoc.Print()
End Using
End If
End Sub
'''<summary>
''' Imprime um relatório sem visualização
'''</summary>
'''<param name="report">Relatório a imprimir</param>
Public Sub Print(ByVal report As LocalReport)
Print(report, Orientation.Portrait)
End Sub
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Try
If streamList IsNot Nothing Then
For Each s As Stream In streamList
s.Close()
Next
streamList.Clear()
streamList = Nothing
End If
If tmpFileName <> String.Empty AndAlso _
IO.File.Exists(tmpFileName) Then
IO.File.Delete(tmpFileName)
End If
tmpFileName = String.Empty
Catch ex As Exception : End Try
End Sub
#End Region
End Class
Os Microsoft Reports estão normalmente associados ao controlo Microsoft ReportViewer, e normalmente quem os usa, usa normalmente este controlo. É verdade que este controlo permite uma série de funcionalidades muito importantes e simples de utilizar, como pré-visualizar, exportar e imprimir, mas nem sempre nas nossas aplicações, é necessário pré-visualizar para imprimir.
Os relatórios *.rdlc não têm uma função built-in que permita, de uma forma directa, a impressão de um relatório. Para o fazer, é necessário fazer um render de um relatório para uma Stream, e depois, usando um PrintDocument, colocar a Stream respectiva, que se encontra numa lista de Streams, na folha que está a imprimir.
Uma aplicação simples do método anteriormente descrito, é usando uma classe semelhante a esta:
Imports System.IO
Imports System.Data
Imports System.Text
Imports System.Drawing.Imaging
Imports System.Drawing.Printing
Imports System.Collections.Generic
Imports Microsoft.Reporting.WinForms
Public Class ReportUtils
Implements IDisposable
Private currentPageIndex As Integer
Private tmpFileName As String = String.Empty
Private streamList As List(Of Stream)
'''<summary>
''' Adiciona a Stream à lista de Streams
'''</summary>
Private Function CreateStream(ByVal name As String, _
ByVal fileNameExtension As String, _
ByVal encoding As Encoding, _
ByVal mimeType As String, _
ByVal willSeek As Boolean) As Stream
tmpFileName = My.Computer.FileSystem.GetTempFileName()
Dim s As New FileStream(tmpFileName, FileMode.Create)
streamList.Add(s)
Return s
End Function
'''<summary>
''' Exporta o ficheiro para uma lista de Streams
'''</summary>
Private Sub ExportToStream(ByVal report As LocalReport)
Dim deviceInfo As New StringBuilder
With deviceInfo
.Append("<DeviceInfo>")
.Append(" <OutputFormat>EMF</OutputFormat>")
.Append(" <PageWidth>8.5in</PageWidth>")
.Append(" <PageHeight>11in</PageHeight>")
.Append(" <MarginTop>0.25in</MarginTop>")
.Append(" <MarginLeft>0.25in</MarginLeft>")
.Append(" <MarginRight>0.25in</MarginRight>")
.Append(" <MarginBottom>0.25in</MarginBottom>")
.Append("</DeviceInfo>")
End With
Dim warnings() As Warning = Nothing
report.Render("Image", deviceInfo.ToString, _
AddressOf CreateStream, warnings)
For Each s As Stream In streamList
s.Position = 0
Next
deviceInfo = Nothing
End Sub
'''<summary>
''' Quando o PrintDocument está a imprimir, desenha
''' a página correspondente, da lista de Streams
'''</summary>
Private Sub PrintPage(ByVal sender As Object, _
ByVal ev As PrintPageEventArgs)
Using pageImage As New Metafile(streamList(currentPageIndex))
currentPageIndex += 1
ev.Graphics.DrawImage(pageImage, ev.PageBounds)
ev.HasMorePages = (currentPageIndex < streamList.Count)
End Using
End Sub
'''<summary>
''' Imprime um relatório sem visualização
'''</summary>
'''<param name="report">Relatório a imprimir</param>
Public Sub Print(ByVal report As LocalReport)
streamList = New List(Of Stream)
' Exporta o ficheiro para uma lista de Streams
Call ExportToStream(report)
If streamList IsNot Nothing AndAlso streamList.Count > 0 Then
' Inicia o processo de impressão
Using printDoc As New PrintDocument()
If Not printDoc.PrinterSettings.IsValid Then
Dim msg As String = "Impressora não disponível ou não válida!"
Throw New ArgumentException(msg)
End If
AddHandler printDoc.PrintPage, AddressOf PrintPage
printDoc.Print()
End Using
End If
End Sub
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Try
' Fecha as streams e apaga a lista
If streamList IsNot Nothing Then
For Each s As Stream In streamList
s.Close()
Next
streamList.Clear()
streamList = Nothing
End If
' Apaga o ficheiro temporário (caso exista)
If tmpFileName <> String.Empty AndAlso IO.File.Exists(tmpFileName) Then
IO.File.Delete(tmpFileName)
End If
tmpFileName = String.Empty
Catch ex As Exception : End Try
End Sub
End Class
Depois, para imprimir o relatório, é apenas necessário:
Imports Microsoft.Reporting.WinForms
Public Class frmMain
'''<summary>
''' Imprime o relatório
'''</summary>
Private Sub btnPrint_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnPrint.Click
Try
Dim rpt As New LocalReport
rpt.ReportPath = Application.StartupPath & "\..\..\rptProducts.rdlc"
' ---------------------------------------------------------
' Definir DataSource, Parameters, etc para o relatório
' ---------------------------------------------------------
Using cls As New ReportUtils
cls.Print(rpt)
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, My.Application.Info.Title, _
MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
End Class
Neste caso utiliza-se o bloco Using ... End Using, uma vez que a classe implementa um método IDisposable. Para mais informação sobre este bloco e a sua utilização, podem ver o seguinte artigo: VB.NET: AndAlso, OrElse e Using
PS: Como sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!
Os melhores conteúdos de {You Shape} IT MSDN estão agora disponíveis num eBook gratuito. O eBook tem 17 artigos escritos por programadores para programadores e comics. Os artigos foram escritos por MVP’s e Regional Director’s.
Índice do Livro
Working with Brownfield Code
Beyond C# and VB
Remaining Valuable to Employers
All I Wanted Was My
Efficiency
Getting Started with Continuous Integration
On Strike at the Software Factory
C# Features You Should Be Using
Accelerate Your Coding with Code Snippets
Is Silverlight 2 Ready for Business Applications?
Innovate with Silverlight 2
Real World WPF: Rich UI + HD
Hidden Talents
Creating Useful Installers with Custom Actions
Banking with XML
Sending Email
O livro está disponível para download em http://devshaped.com/book
No meu blog, também de tecnologia, disponibilizei uma Lista de Recursos de Aprendizagem, que julgo úteis e importantes, para quem quer aprender um pouco de Visual Basic. É essencialmente uma lista de iniciação.
Nessa lista, que não coloco aqui por ser algo extensa e porque vou actualizando periodicamente (sempre que se justifique), estão informações como Ciclos de Formação (Beginner Developer Learning Center), Vídeos, E-Books e alguns links da MSDN.
Espero que vos seja útil!
Exportar os relatórios para determinado formato, é uma opção muito prática, para simplesmente guardar um relatório num ficheiro ou, por exemplo, enviar como anexo num email. O controlo ReportViewer permite visualizar, mas também exportar, os ficheiros *.rdlc e *.rdl, quer seja uma aplicações WinForms ou ASP.NET.
No entanto é ainda mais prático, especialmente para automatizar processos, gerar esses ficheiros dinamicamente, sem ser necessário a utilização do ReportViewer.
Quando é utilizado em modo local (LocalReport) existem alguns tipos de formatos que se podem utilizar para exportar: Microsoft Excel, PDF ou como imagem.
Para exportar um relatório é necessário apenas fazer o Render() de um LocalReport para um array de bytes, e depois usar um FileStream para escrever o ficheiro final.
Pode-se usar uma classe como esta:
Public Class ReportUtils
Enum rptFormat
Excel
PDF
Image
End Enum
''' <summary>
''' Exporta um LocalReport para um formato definido
''' </summary>
''' <param name="report">LocalReport</param>
''' <param name="output">Formato final</param>
''' <param name="filePath">Caminho + Nome do ficheiro</param>
''' <remarks></remarks>
Public Sub Export(ByVal report As LocalReport, ByVal output As rptFormat, ByVal filePath As String)
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 = report.Render(output.ToString, Nothing, _
mimeType, encoding, extension, streamids, warnings)
Using fs As New IO.FileStream(filePath, IO.FileMode.Create)
fs.Write(bytes, 0, bytes.Length)
fs.Close()
End Using
bytes = Nothing
End Sub
End Class
Depois, para utilizar a classe, criando o ficheiro no formato desejado e executando-o:
Dim rpt As New LocalReport
rpt.ReportPath = Application.StartupPath & "\..\..\rptProducts.rdlc"
' ---------------------------------------------------------
' Definir DataSource, Parameters, etc, para o relatório
' ---------------------------------------------------------
Dim fileName As String = "d:\teste.pdf"
Dim clsReport As New ReportUtils
clsReport.Export(rpt, ReportUtils.rptFormat.PDF, fileName)
Process.Start(fileName)
Como podem ver neste pequeno exemplo, é bastante simples e fácil de utilizar.
Recentemente tenho escrito alguns artigos sobre Microsoft Reports. Na minha opinião são uma opção bastante válida de reporting e um sério adversário ao Crystal Report. Pessoalmente uso bastante e recomendo.
Brevemente irei escrever mais alguns artigos, sobre a utilização de Custom Assemblies, como imprimir sem a utilização de ReportViewer, como exportar para PDF ou Excel, etc., mas para já, fiquem com estes:
VB.NET: Microsoft Reporting Services
O objectivo deste artigo é mostrar os passos básicos para a criação de um relatório, definir a Data Source em modo runtime, trabalhar com Parameters, incluir imagens, usar o Expression Editor, e como alimentar um SubReport e um gráfico. Finalmente irá também mostrar algumas personalizações simples ao controlo ReportViewer.
Disponível também em Inglês na comunidade The Code Project
VB.NET: Microsoft Reports – Relatórios Embebidos
Mostra como utilizar relatórios embebidos na aplicação, ou seja, no próprio executável, de modo a não permitir a edição do ficheiro *.rdlc.
VB.NET: Microsoft Reports – Mostrando Imagens
Mostra como se podem colocar imagens num relatório, através de uma base de dados, quer as imagens estejam armazenadas (BLOB’s), quer através de um caminho para a imagem(do tipo string).
VB.NET: Microsoft Reports – Código Personalizado
Mostra como definir código personalizado(Custom Code), e com isso, manipular a informação do relatório.
Para breve há mais!
Olá a todos,
Sou o Jorge Paulino, sou programador de VB, principalmente em ambiente Windows Forms, mas também VBA, ASP.NET, etc. Além do universo VB, que é a minha área preferida, trabalho também em automação industrial.
Tenho um blog de programação, onde coloco essencialmente alguns artigos, resultado de experiências e pedidos que me fazem, e que podem espreitar em http://vbtuga.blogspot.com/. Participo também em algumas comunidades técnicas nacionais e internacionais.
Vou tentar colocar aqui também alguma informação, para quem gosta ou quer aprender, e não tenham medo de comentar e/ou corrigir os meus posts. Eu agradeço!
No dia 1 de Julho de 2009 foi-me atribuído, pela Microsoft, um MVP em Visual Basic, e é para mim uma honra, poder pertencer a este grupo.
Esta é a minha apresentação e o meu primeiro post nesta comunidade.
Um abraço,
Jorge Paulino
Microsoft MVP Visual Basic