RDLC local report trying to render before loading datasource - vb.net

I have created a local report that contains a few sub reports. I am trying to load the report straight to pdf based off the click of a button.
I have tried showing the report with report viewer and it shows up fine, but when I try to render directly to pdf I get an error about data source. When I debug the code I notice that my subprocessing function does run until after the button call function finishes and throws the error.
Dim reportParam As New ReportParameter("appId", appid)
Dim reportParam2 As New ReportParameter("appDate", appDate)
Dim reportParam3 As New ReportParameter("auditDate", Now)
Dim reportArray As New ReportParameterCollection
reportArray.Add(reportParam)
reportArray.Add(reportParam2)
reportArray.Add(reportParam3)
AddHandler ReportViewer1.LocalReport.SubreportProcessing, AddressOf SetSubDataSource
ReportViewer1.LocalReport.SetParameters(reportArray)
ObjectDataSource1.SelectParameters("appID").DefaultValue = appid
ObjectDataSource1.SelectParameters("appDate").DefaultValue = appDate
ObjectDataSource1.DataBind()
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
Try
ReportViewer1.DataBind()
ReportViewer1.LocalReport.Refresh()
Dim byteViewer As Byte()
byteViewer = ReportViewer1.LocalReport.Render("PDF", Nothing, mimeType, encoding, extension, streamids, warnings)
Response.Buffer = True
'Response.Clear()
Response.ContentType = mimeType
Response.AddHeader("content-disposition", "attachment; filename=test.pdf")
Response.BinaryWrite(byteViewer)
Response.OutputStream.Write(byteViewer, 0, byteViewer.Length)
Response.Flush()
Response.Close()
Thanks for your advice in advance, I just trying to figure out how to get the report to load data sources before it renders and not after this function is complete.

Related

PDF fill in not merging correctly

We are using an asp.net website with iTextSharp.dll version 5.5.13
We can merge multiple PDF files into one using a stream and it works perfectly. However, when we use a PDF that was created in a "fill-in" function the new PDF file does not correctly merge into the other documents. It merges without the filled in values. However, if I open the filled in PDF that it creates the filled in data displays and prints fine.
I have tried merging the new "filled in" PDF at a later time but it still displays the template file as though the filled in data was missing.
Below code fills in the data
Dim strFileName As String = Path.GetFileNameWithoutExtension(strSourceFile)
Dim strOutPath As String = HttpContext.Current.Server.MapPath("~/Apps/Lifetime/OfficeDocs/Export/")
newFile = strOutPath & strFileName & " " & strRONumber & ".pdf"
If Not File.Exists(newFile) Then
Dim pdfReader As PdfReader = New PdfReader(strSourceFile)
Using pdfStamper As PdfStamper = New PdfStamper(pdfReader, New FileStream(newFile, FileMode.Create))
Dim pdfFormFields As AcroFields = pdfStamper.AcroFields
pdfFormFields.SetField("CUSTOMER NAME", strCustomer)
pdfFormFields.SetField("YR MK MODEL", strVehicle)
pdfFormFields.SetField("RO#", strRONumber)
pdfStamper.FormFlattening = False
pdfStamper.Dispose()
End Using
End If
Then code below here merges multiple PDF files/paths sent to it
Public Shared Sub MergePDFs(ByVal files As List(Of String), ByVal filename As String)
'Gets a list of full path files and merges into one memory stream
'and outputs it to a browser response.
Dim MemStream As New System.IO.MemoryStream
Dim doc As New iTextSharp.text.Document
Dim reader As iTextSharp.text.pdf.PdfReader
Dim numberOfPages As Integer
Dim currentPageNumber As Integer
Dim writer As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, MemStream)
doc.Open()
Dim cb As iTextSharp.text.pdf.PdfContentByte = writer.DirectContent
Dim page As iTextSharp.text.pdf.PdfImportedPage
Dim strError As String = ""
For Each strfile As String In files
reader = New iTextSharp.text.pdf.PdfReader(strfile)
numberOfPages = reader.NumberOfPages
currentPageNumber = 0
Do While (currentPageNumber < numberOfPages)
currentPageNumber += 1
doc.SetPageSize(reader.GetPageSizeWithRotation(currentPageNumber))
doc.NewPage()
page = writer.GetImportedPage(reader, currentPageNumber)
cb.AddTemplate(page, 0, 0)
Loop
Next
doc.Close()
doc.Dispose()
If MemStream Is Nothing Then
HttpContext.Current.Response.Write("No Data is available for output")
Else
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.ContentType = "application/pdf"
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; filename=" + filename)
HttpContext.Current.Response.BinaryWrite(MemStream.ToArray)
HttpContext.Current.Response.OutputStream.Flush()
HttpContext.Current.Response.OutputStream.Close()
HttpContext.Current.Response.OutputStream.Dispose()
MemStream.Close()
MemStream.Dispose()
End If
End Sub
I expect the "filled in" PDF in the list of files to retain the filled in data but it does not. Even if I try to merge the filled in file later it still comes up missing the filled in data. If I print the filled in file it looks perfect.
PdfWriter.GetImportedPage only returns you a copy of the page contents. This does not include any annotations, in particular not the widget annotations of form fields on the page at hand.
To also copy the annotations of the source pages, use the iText PdfCopy class instead. This class is designed to copy pages including all annotations. Furthermore, it includes methods to copy all pages of a source document in one step.
You have to tell the PdfCopy object to merge fields, otherwise the document-wide form structure won't be built.
As an aside, your code creates many PdfReader objects but does not close them. That may increase your memory requirements substantially.
Thus:
Public Shared Sub MergePDFsImproved(ByVal files As List(Of String), ByVal filename As String)
Using mem As New MemoryStream()
Dim readers As New List(Of PdfReader)
Using doc As New Document
Dim copy As New PdfCopy(doc, mem)
copy.SetMergeFields()
doc.Open()
For Each strfile As String In files
Dim reader As New PdfReader(strfile)
copy.AddDocument(reader)
readers.Add(reader)
Next
End Using
For Each reader As PdfReader In readers
reader.Close()
Next
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.ContentType = "application/pdf"
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; filename=" + filename)
HttpContext.Current.Response.BinaryWrite(mem.ToArray)
HttpContext.Current.Response.OutputStream.Flush()
HttpContext.Current.Response.OutputStream.Close()
HttpContext.Current.Response.OutputStream.Dispose()
End Using
End Sub
Actually I'm not sure whether it is a good idea to Close and Dispose the response output stream here, that shouldn't be the responsibility of a PDF merging method.
This is a related answer for the Java version of iText; you may want to read it for additional information. Unfortunately many links in that answer meanwhile are dead.

Disabling a checkbox by getting its name from a server

It is quite a bit hard to explain what I have in mind but I will try my best...
I have an installer with a ton of checkboxes. Each checkbox is mod (modification for a game). At times mods interfere with a game and cause the game to crash. So I have to update the installer with either updated mod(s) or I have to temporarily disable the mod or mods that are causing the crashing.
What it will do is connect to a server that checks if a file contains "true or false" if it contains "true" it will execute code that does this:
Connects to a different server, gets the name of a checkbox, and does something like this:
NameOfCheckBox.Enabled = False
The thing is... I know how to do this, except the very last part.
How do I tell my program that the text it gets from the server is a name of checkbox that is located on the form?
This is my code:
Try
Dim request As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create("https://docs.google.com/document/d/1G3R0CoRG-LCXy-8jm-LcCJZJ9B0whsOJ64efjL0btc8/edit?usp=sharing")
Dim response As System.Net.HttpWebResponse = request.GetResponse()
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(response.GetResponseStream())
Dim status As String = sr.ReadToEnd()
Dim request2 As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create("https://docs.google.com/document/d/1cYkhGTDEpxqltOvCSSD0Kw9J_1DG1dyJSV2qQ1Xekto/edit?usp=sharing")
Dim response2 As System.Net.HttpWebResponse = request2.GetResponse()
Dim sr2 As System.IO.StreamReader = New System.IO.StreamReader(response2.GetResponseStream())
Dim checkboxtodisable As String = sr2.ReadToEnd()
If status.Contains("True") Then
Dim chk As CheckBox
chk.Name = checkboxtodisable
chk.Enabled = False
Else
End If
Catch ex As Exception
MessageBox.Show("Unable to connect to server!")
MessageBox.Show(ex.Message)
End Try
The error I get is:
Object reference not set to an instance of an object
The error is located on this line of code:
chk.Name = checkboxtodisable
You can retrieve a control by name like this:
Dim MyCheckBox As Checkbox = Me.Controls("checkbox1")
So your code would look like this:
If status.Contains("True") Then
Dim chk as checkbox = Me.Controls(checkboxtodisable)
chk.Enabled = False
End If

Set a report datasource instance at run time

I have created a report that is based on a business object - this works great. I am now trying to add a button that renders the report directly to PDF (in a winforms application).
I know what I need to do - in code I am creating a ReportViewer, setting the DataSource, specifying the report (it's an embedded resource), then rendering the report into a byte array before using System.IO.File.WriteAllBytes to flush the byte array to disk. One thing I'm hung up on though, is how do I specify the instance of the object properly? I keep getting the "An error has occurred during the report processing" error. In IntelliTrace I can see that an exception is thrown "A data source instance has not been supplied for the data source 'IssRep'" (IssRep is the dataset name in the report. Here is the code:
Dim warning As Warning() = Nothing
Dim streamids As String() = Nothing
Dim mimetype As String = Nothing
Dim encoding As String = Nothing
Dim extension As String = Nothing
Dim viewer As New ReportViewer
Dim bs As New BindingSource
bs.DataSource = issuedet
Dim rds As New ReportDataSource
rds.Value = bs
viewer.LocalReport.DataSources.Add(rds)
viewer.ProcessingMode = ProcessingMode.Local
viewer.LocalReport.ReportEmbeddedResource = "FRSFE.SR.rdlc"
Dim pdfbytes As Byte()
Try
pdfbytes = viewer.LocalReport.Render("PDF", Nothing, mimetype, encoding, extension, streamids, warning)
File.WriteAllBytes("C:\Shared\FRS\SR.PDF", pdfbytes)
Catch ex As Exception
MsgBox(ex.Message)
End Try
I'm pretty sure whatever I'm stuck on is pretty simple as I'm very rusty on .NET but I just can't figure it out!
Try setting rds.Name = "IssRep" before adding it to viewer.LocalReport.DataSources.

AxAcroPdf Control - Issues reloading PDF

When using the axAcroPdfLib.AxAcroPDF control in my Windows Forms application, I'm not able to reload the same image. The image is initially loaded with the LoadFile() method.
Upon using the LoadFile() method again on the same path AFTER saving changes to the PDF, the control becomes blank (no PDF shown).
If I set the src property of the control to the path, I get a message saying the file does not begin with '%PDF-'. But it does. I opened it with Word and it clearly begins with %PDF-. It's not corrupt or locked either.
I've even tried closing, disposing, or setting it to Nothing, and then completely re-instantiating it as I did the first time it's loaded - no effect. The window closes and shows with the control blank.
Loading a different file via the above methods has the same effect - blank.
Using Windows 7 64-bit, VS 2010, VB.NET.
The code is below. For right now, I'm just trying to draw a simple line on it.
Private Sub _btnBarCode_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _btnBarCode.Click
Dim pdfReader As iTextSharp.text.pdf.PdfReader = Nothing
Try
pdfReader = New iTextSharp.text.pdf.PdfReader(File.ReadAllBytes(_path))
Using fs As New FileStream(_path, FileMode.Create, FileAccess.Write)
Using pdfStamper = New iTextSharp.text.pdf.PdfStamper(pdfReader, fs)
Dim pdfPage As iTextSharp.text.pdf.PdfContentByte = pdfStamper.GetOverContent(1)
Using barCodeForm As New FBarCode
barCodeForm.Barcode = _barCode
If (barCodeForm.ShowDialog(Me) = DialogResult.OK) Then
Dim screenBarCode As Point = barCodeForm.Location
Dim clientBarCode As Point = Point.op_Subtraction(PointToClient(screenBarCode), New Point(0, 50)) '_pdfControl.Location '_imgView.Location
clientBarCode = New Point(10, 50)
Dim barcodeImg As New Bitmap(200, 50)
Using gc As Graphics = Graphics.FromImage(barcodeImg)
gc.DrawLine(Pens.Red, New Point(10, 10), New Point(20, 20))
'barCodeForm._barCode.DrawBarCode(gc, clientBarCode)
End Using
Dim convert As ImageConverter = New ImageConverter()
Dim bmpBytes As Byte() = DirectCast(convert.ConvertTo(barcodeImg, GetType(Byte())), Byte())
Dim thisImage As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(bmpBytes)
thisImage.SetAbsolutePosition(clientBarCode.X, clientBarCode.Y)
thisImage.SetDpi(72, 72)
pdfPage.AddImage(thisImage)
rdrAdobePdf.LoadFile(_path) 'Blank pdf
'rdrAdobePdf.src = _path '"Does not begin with '%PDF-' (even though it does)
'Me.Close()
'_myParent.ResetPdfViewer()
'ReloadPdfViewer(Me.Barcode)
End If
End Using
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, "An error occurred.")
Return
Finally
If Not pdfReader Is Nothing Then pdfReader.Close()
End Try
End Sub
Any ideas what could be the problem here?
Problem was solved by getting the reloading code out of that click method. Putting it in another click method solved the problem - not sure why. The code I used just ran .LoadFile, then Form.Show() and Form.Activate().

Render Html using RDL Local Report

I need to render html from rdl reports using the LocalReport class, I dont want to use ReportViewer for the same. Is there any way i can enable generating HTML.
As far as I know LocalReport cannot be exported to HTML (only Excel,Word and PDF are available). But if you are still interested in export you can use following
Dim Report = New LocalReport
prepare report the same way as for viewing (Datasource for RDL reports with ReportViewer)
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() = Nothing
bytes = Report.Render(RenderFormat, Nothing, mimeType, encoding, extension, streamids, warnings)
Using fs As New IO.FileStream(RepPath, IO.FileMode.Create)
fs.Write(bytes, 0, bytes.Length)
fs.Close()
ReDim bytes(0)
end Using
You can get list of available extensions with Report.ListRenderingExtensions
ServerReport solution is similar, but more possible export formats is available.