I'm a bit dumbfounded here. Most of the tutorials I've seen around create a report using the wizard or a built-in (or ready-made) dataset. I build my dataset using queries in runtime so I'm not too sure how to adopt the ones I've seen so far.
Usually, when I create a report, it's a one record report and fields in the RDLC file can easily be populated using parameters. The one I'm trying to do below however works similarly to making a SELECT query. So here's what I'm trying to do, I'm trying to make a report that shows up like so:
Status: Approved
PID | Name | Address
1 | Name 1 | Address 1
2 | Name 2 | Address 2
===========================
Status: Denied
PID | Name | Address
3 | Name 3 | Address 3
4 | Name 4 | Address 4
I have several questions with this:
My RDLC reports are stored in a "\Reports" folder inside the folder with the .vb/.resx files. When I refer to it's using Application.StartupPath & "\Reports\myReport.rdlc", it can't find it there (obviously). Is there a way for me to embed the report files to the program (ie: use a relative folder name, where should I place the RDLC folder/file)? I don't think I should transfer the RDLC files to the Debug folder just to make this work (hence the full directory listing).
What's a good approach to take in trying to create a report using the code above? I was thinking that if I were to loop along my dataset and pass the values from there to the RDLC file as parameters, it would populate the report (as with my one-record report before) but that doesn't seem to be the case.
Refreshing the report viewer also gives me
A data source instance has not been supplied for the data source 'Dataset1'.
I created a dummy dataset in the RDLC file just to be able to use a Tablix as was suggested in several threads I read around. I'd really prefer if I could just use the dataset I made from scratch rather than use the wizard for that.
Private Sub btnGenerateReport_Click(sender As Object, e As EventArgs) Handles btnGenerateReport.Click
Dim query As String
query = BuildQuery()
SQLControl = New SQLControl
Try
If Not query = String.Empty Then
SQLControl.QueryParams(query)
If SQLControl.SQLDS.Tables(0).Rows.Count > 0 Then
FetchData()
End If
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Report Maker")
End Try
End Sub
Private Sub FetchData()
Dim dataSource As ReportDataSource
Dim PID As Integer
Dim Name As String
Dim ApplicationStatus As String
Dim Address As String
rvPreview.Reset()
rvPreview.LocalReport.ReportPath = "C:\Users\xxx\Documents\Visual Studio 2015\Projects\My Project 1\My Project 1\Reports\myReport.rdlc"
rvPreview.LocalReport.DataSources.Clear()
dataSource = New ReportDataSource()
_rparams = New List(Of ReportParameter)
With SQLControl.SQLDS.Tables(0)
For x As Integer = 0 To .Rows.Count - 1
PID = .Rows(x).Item("PID")
Name = .Rows(x).Item("LName") & ", " & .Rows(x).Item("FName")
ApplicationStatus = .Rows(x).Item("ApplicationStatus")
Address = .Rows(x).Item("StreetAddress") & ", " & .Rows(x).Item("City")
_rparams.Add(New ReportParameter("PID", PID))
_rparams.Add(New ReportParameter("Name", Name))
_rparams.Add(New ReportParameter("ApplicationStatus", ApplicationStatus))
_rparams.Add(New ReportParameter("Address", Address))
For Each param As ReportParameter In _rparams
rvPreview.LocalReport.SetParameters(_rparams)
Next
Next x
rvPreview.RefreshReport()
End With
End Sub
At the begining I have to mention that I use RDLC reports with C#, but the solution should be very similar in vb.net.
I usualy prepare every report as separate project (so I have separate DLL for every report) and use a separate class in this project to handle everything I need to do with report. I add Every RDLC file just under the project (main report file and subreports files). In my case I can read every RDLC file like a stream just using project namespace and RDLC filename as in this sample code below
Assembly assembly = Assembly.GetExecutingAssembly();
Stream stream = assembly.GetManifestResourceStream("[Some project namespace].[Some report filename].rdlc");
Then I use a code like this to connect that stream with report viewer (the stream in this code is the same object as above but this code is in another class which has access to report viewer object)
ReportViewerControl.LocalReport.LoadReportDefinition(new StreamReader(stream));
You can provide a DataSet for your report in very simple way. You can use object of the System.Data.DataTable class for table (I call this object as yourTableObject in code below) and System.Data.DataRow class for rows in that table. When you put all your data in the table then you can provide it to the report using code like this
//I use DataSet1 as dataset name because you use this name in your report definition
ReportDataSource rds = new ReportDataSource("DataSet1", yourTableObject);
ReportViewerControl.LocalReport.DataSources.Add(rds);
Ofcourse provided table should have the same fields like the dataset in your report definition.
You have to provide a valid DataSet to the report. Solution is above in point 2.
Related
I'm relatively new to form programming in Visual Basic and need some help.
I've successful got what I want from my database into a datagrid but need this in a report viewer.
dgvReport.DataSource = dsReport
Dim ds As DataTable = New DataTable("GenerateReport")
Dim ReportDataSource = New ReportDataSource("GenerateReport", ds)
rvReport.LocalReport.DataSources.Clear()
rvReport.LocalReport.DataSources.Add(ReportDataSource)
rvReport.LocalReport.ReportEmbeddedResource = "Test.Report1.rdlc"
rvReport.RefreshReport()
Where 'dsReport' is the name of the dataset I'm using.
'Generate Report' is the table name within the dataset.
"Test.report1.rdlc" is the path of the report file.
I've searched and found this code, but the error I get says that the the program cannot find the file. I was unaware that there's a file saved which you then copy the data from into the report viewer.
I don't know if this is right, what I'm doing. Any help is much appreciated.
I have a program which takes attendee’s names and contact details and writes them to a text file. In all, there are 20 rows and 5 columns which are used in my form so that when the user clicks on the ‘Save’ button, these details are written to a text file.
The code I am using works fine, and is shown below. Please note that this code is truncated to the first attendee only.
Dim AttendeeData = New DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Attendee Information\" & TextBox1.Text))
Dim FileNameTXT As String = Path.Combine(AttendeeData.FullName, "Attendee Data" + ".TXT")
Dim FileTXT As New System.IO.StreamWriter(FileNameTXT)
‘Write the Attendee details to the text file
‘Attendee Number 1
FileTXT.Write(Form1.TextBox2.Text) ‘Attendee’s Name
FileTXT.WriteLine("")
FileTXT.Write(Form1.TextBox3.Text) ‘Attendee's Nationality
FileTXT.WriteLine("")
FileTXT.Write(Form1.TextBox4.Text) ‘Attendee's Position
FileTXT.WriteLine("")
FileTXT.Write(Form1.TextBox5.Text) ‘Attendee's Email
FileTXT.WriteLine("")
FileTXT.Write(Form1.TextBox6.Text) ‘Attendee's telephone No.
FileTXT.WriteLine("")
‘Attendee Number 2 ... to Attendee Number 20
'The below line of code closes the writer
FileTXT.Close()
I decided to use this method because at some point, the text file has to be read from the text file, back into the textboxes on my form.
My problem is that when it comes to reporting, printing out these details in the above format would be cumbersome, using up sheets of paper to make the report unnecessarily plentiful. So I reckoned that displaying these data in a tabular format would be much more tidy and professional.
Please how can I achieve this? I am using Visual Basic 2010 Express. Thank you in advance.
The code I am currently using in printing is shown below:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim AttendeeData = New DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Attendee Information\" & TextBox1.Text))
For Each AttendeeDetailsTXT As FileInfo In AttendeeData.GetFiles("*.TXT", SearchOption.TopDirectoryOnly)
For Each line As String In File.ReadAllLines(AttendeeDetailsTXT.FullName)
If Not String.IsNullOrEmpty(line) Then RichTextBox1.AppendText(line & vbCrLf & vbCrLf)
Next
Next
' Send data to printing script
End Sub
How about recording the attendee's information in a structured format such as XML?
Writing the data to XML in code is quite simple - here is a good article on the subject: http://vb.net-informations.com/xml/create-xml-vb.net.htm
Reading the data back into your application will also be much simpler as you no longer have to rely on the lines in your unstructured input file being in a particular order which could cause issues with data being out of sync if, for example, a line is missing.
Displaying the data is slightly more tricky as you would have to use something like an XSLT to display your data in a tabular form but there are plenty of resources online which could get you started with this such as the W3Schools: http://www.w3schools.com/xsl/xsl_transformation.asp
I have an application developed in VB6 which I am migrating to .Net Framework 4.0. There is a report that works correctly in the original application but the migrated application does not work on the original application. As a special feature, this report changed at runtime attribute "location" in two tables (actually they are seen) used to generate the SQL with which the report is fed, but when "shooting" the reporete the changes in tables with the attribute "location" are not reflected, that I can display using the "SQL Server Profiler" tool:
objReportDocument.Database.Tables(0).Location = "NameReferenceTable""
My point is this: When the report was build, they used 5 database tables of the data base: Table1, Table2, Table3, Table4 and Table5. Later, in de data base, the tables Table1 and Table2 were deleted. The idea is that en run time a store procedure constructed Table1 and Table2 like temporary tables with the original name more any id string; this new data base tables must be used when the report are rise.
When you walk over the Tables array of the report (ReportDocument.DataBase.Tables(n)), for each table you can see two key properties: Name and Location. I understand than Location propertie indicates to Crystal Reports with which tables should work to build the reorts, this is true?
I have not much experience with Crystal Reports, I investigated two weeks why this error is generated without an answer ... I hope you can help me a bit, I really appreciate it.
regards,
Fabian.
I will provide a method that I use for our Crystal Reports objects in my application. This is just used to set the login information for the report (our reports use built-in security), but if I am understanding your problem correctly, then you should be able to add/modify this method to set the Location as well.
The properties used in the method below are:
Me.ConnectionInfo is type CrystalDecisions.Shared.ConnectionInfo
Me.LogOnInfo is type CrystalDecisions.Shared.TableLogOnInfo
Me.Report is type CrystalDecisions.CrystalReports.Engine.ReportDocument
Also, g_strDb, g_strServer, and g_strMirror are some Strings whose value is irrelevant.
One thing I have found working with Crystal Reports in .NET, is that you need to set properties at the Table level, as you can see in the method below. Hopefully this helps you with your issue.
''' <summary>
''' Apply the database connection info to all tables recursively.
''' </summary>
''' <param name="crxRpt">The report document (or subreport) to apply connection info.</param>
Private Sub SetConnectionInfo(ByVal crxRpt As ReportDocument)
Dim reportObject As ReportObject
Dim subReportObject As SubreportObject
Dim section As Section
Dim t As Table
For Each t In crxRpt.Database.Tables
' if the DatabaseName in the report is <special db name>,
' we need to make sure to set the DatabaseName to the environment
' that the user is currently connected to in order to be able to
' pull the correct information for the report
If t.LogOnInfo.ConnectionInfo.DatabaseName = "<special db name>" Then
Me.ConnectionInfo.DatabaseName = g_strDb
Else
Me.ConnectionInfo.DatabaseName = t.LogOnInfo.ConnectionInfo.DatabaseName
End If
' only ApplyLogOnInfo for tables that are being pulled from the SQL
' server, this avoids problems that arise with reports that are
' created using field definition files
If t.LogOnInfo.ConnectionInfo.ServerName = g_strServer OrElse t.LogOnInfo.ConnectionInfo.ServerName = g_strMirror Then
t.ApplyLogOnInfo(Me.LogOnInfo)
End If
Next t
For Each section In crxRpt.ReportDefinition.Sections
For Each reportObject In section.ReportObjects
If reportObject.Kind = ReportObjectKind.SubreportObject Then
subReportObject = CType(reportObject, CrystalDecisions.CrystalReports.Engine.SubreportObject)
SetConnectionInfo(subReportObject.OpenSubreport(subReportObject.SubreportName))
End If
Next reportObject
Next section
End Sub
The above method is called from a setup method:
''' <summary>
''' Initialize the database connection info.
''' </summary>
Public Sub SetUpReport()
Me.LogOnInfo = New TableLogOnInfo
Me.ConnectionInfo.UserID = conUID
Me.ConnectionInfo.Password = conPWD
Me.ConnectionInfo.ServerName = g_strServer
Me.ConnectionInfo.DatabaseName = g_strDb
Me.SetConnectionInfo(Me.Report)
End Sub
And SetUpReport() is called any time we need to display/print the report.
Well, finally find the solution...
In my conection to BD use ODBC, the associate user to this conection no had a schema associate in the BD, then when the store procedure created the temporaly tables there are creates below the shchema bdo, but when crystal reports rise the report (used my ODBC with the associate user) no found the temporaly tables. So I associated a scheemma to the user used in my ODBC.
My original reports are old, then I had to open each one in VS2012, overwrite the report to update the format and test in Main Report Preview.
I am new to reportviewer and struggling with the concepts.
I realise that I am probably being very stupid here. I have tried reading up on the reportviewer but not found any tutorials except those that drag and drop datasets. which is not what I want to do.
I want to create a report from a single datatable at first just as a learning exercise.
I have created a dataset added the table to it and have tried this code but I get an error: 'The report definition for report "C:\Users\Mike\BM\Reports\" has not been specified. Object reference not set to an instance of an object'
I don't really understand what the 'The report definition' bit means?
I would appreciate some guidance please.
Dim MyTestDS As New DataSet
Dim myTestTable As New DataTable
myTestTable = Data.Accounts.Table.Copy
MyTestDS.Tables.Add(myTestTable)
Dim DSReport As New ReportDataSource()
DSReport.Name = "MyTestDS"
DSReport.Value = MyTestDS.Tables(0)
Dim PathReport As String = "C:\Users\Mike\BM\Reports\"
ReportViewer1.LocalReport.ReportEmbeddedResource = PathReport
ReportViewer1.LocalReport.DataSources.Clear()
ReportViewer1.LocalReport.DataSources.Add(DSReport)
ReportViewer1.LocalReport.Refresh()
ReportViewer1.RefreshReport()
As a learning exercise, I think is better not using embedded resource so you can simply specify the complete report path of your rdlc file; for example:
ReportViewer1.LocalReport.ReportPath = "C:\Users\Mike\BM\Reports\YourReportFile.rdlc"
If you want to use an embedded report, I think you have to get it like this:
Get Embedded Resource
Copy YourReportFile.rdl to YourReportFile.rdlc
I am using visual studio 2010 to develop my desktop application and ms access database. I have already designed reports in access database and they are working perfectly. Now my concern is that is it possible to use these access reports in my Vb.Net application?
I need this because it would be much easier to distribute the software instead of using crystal report where I will need to install a run time machine for crystal reports.
It's possible to do but it's a horrible implementation. You basically have to launch Access, open the database file in Access, then navigate down and launch the report. There is no way to just "view" the report inside your app. It will only show inside Access.
I think your best option is to use ReportViewer control if you don't want to use Crystal Reports.
I found this: https://support.microsoft.com/kb/317113?wa=wsignin1.0
To preview or to print an Access report, you call the OpenReport method of the DoCmd object. When you call OpenReport, one of the arguments that you pass determines whether the report is previewed on the screen, or whether it is sent to the printer:
' Preview a report named Sales:
oAccess.DoCmd.OpenReport(ReportName:="Sales", View:=Access.AcView.acViewPreview)
' Print a report named Sales:
oAccess.DoCmd.OpenReport(ReportName:="Sales", View:=Access.AcView.acViewNormal)
But I haven't been able to find much info/help regarding OpenReport method or DoCmd object.
I am not a proffesional developer, but after long research it's worked for my project.
I would like to open directly from MS Access, my existing reports and then to open these from not default installation folder path (different for each one pc). The third requirement was to open more than one report (Not all together).
Design:
Form8.vb [Design]
vb.Net Code:
Imports System.ComponentModel
Imports Microsoft.Office.Interop.Access
Public Class Form8
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim oAccess As New Microsoft.Office.Interop.Access.Application()
Dim CurDir As String = System.AppDomain.CurrentDomain.BaseDirectory
Dim FPath As String = CurDir & "\YourDatabase.accdb"
oAccess.Visible = True
oAccess.OpenCurrentDatabase(FPath)
If ComboBox1.Text = "Your text" Then
oAccess.DoCmd.OpenReport(ReportName:="Your Report Name", View:=AcView.acViewPreview)
ElseIf ComboBox1.Text = "Your text2" Then
oAccess.DoCmd.OpenReport(ReportName:="Your Report Name", View:=AcView.acViewPreview)
ElseIf ComboBox1.Text = "Your text3" Then
oAccess.DoCmd.OpenReport(ReportName:="Your Report Name", View:=AcView.acViewPreview)
End If
End Sub
End Class
Replace YourDatabase with YourDatabaseName, Replace Your text,Your text1,Your text2,Your text3 with YourText, Replace Your Report Name with the Name of your report Name, As needed.
Finally, in order for this solution to work, you need:
1) Your (Conn.open) connection to look like this:
Dim dbsource As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = |DataDirectory|\Your DB.accdb"
2) In Solution Explorer, Your database to include in your project or to your setup project, to be installed with your project. like this:
Solution Explorer [image]
SetUp Project link
3) At server explorer, Data Connection the (Sourse) Database file name, must be with the full path name e.g like this:
C:\Users\User\Desktop\YourDatabase.accdb, and the connection String at the Properties like this:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source = "C:\Users\User\Desktop\YourDatabase.accdb".
I hope this helps!!!
The following code:
Preview a report named Sales:
oAccess.DoCmd.OpenReport(ReportName:="Sales", View:=Access.AcView.acViewPreview)
Print a report named Sales:
oAccess.DoCmd.OpenReport(ReportName:="Sales", View:=Access.AcView.acViewNormal)
But I haven't been able to find much info/help regarding OpenReport method or DoCmd object.
This will only work if you are using VB.Net to automate the Access application. This will open the Access application and allow you to view or print the reports just as if you were running Access directly. However, you need to have the Access application (not just the .mdb or .accdb file) on the computer that is running the VB.Net application.
I have not found any way to utilize the Access reports without having Access on the computers running the VB.Net application. I'm looking into using Crystal Reports for the application I'm working on now.