Here is the layout of my page that I am exporting:
-------------------------------
' Text text text '
' '
' Gridview '
' '
' Text text text '
--------------------------------
Here is my table after rendering to HTML
<table cellspacing="0" id="mytest_gvMain" style="width:100%;border-collapse:collapse;">
<tbody>
<tr>
<th scope="col">Item</th>
<th scope="col">Description</th>
<th scope="col">Quantity</th>
<th scope="col">Unit</th>
<th scope="col">Rate</th>
</tr>
<tr>
</tr>
</tbody>
</table>
As you see the gridview is in the middle of the page. Because the gridview can of any size expanding to different pages, I would like to set SplitLate = false, so the row stays together. Now some of the text in the last row is on page 1 and the some of it on the first row of page 2. Please have a look at this image .
Some data on last row of page 5 and some on first row of page 6. I have read some documents suggesting document.add(table) but that will add the table to the end of my document. Is there a way I set SplitLate on the gridview itself?
Based on Chris suggestion, I have updated my code to use xmlworker based on this link Cannot get CSS to work in iTextSharp (5.4.3) when making pdf.
Using input As New MemoryStream(bytes, False)
Dim ms As New MemoryStream()
Dim document As New iTextSharp.text.Document(iTextSharp.text.PageSize.LETTER, 36, 36, 36, 36)
Dim writer As PdfWriter = PdfWriter.GetInstance(document, ms)
writer.CloseStream = False
document.Open()
Dim htmlContext As HtmlPipelineContext = New HtmlPipelineContext(Nothing)
htmlContext.SetAcceptUnknown(True)
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory())
Dim cssResolver As ICSSResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(False)
cssResolver.AddCssFile(HttpContext.Current.Server.MapPath("/assets/css/pdf.css"), True)
Dim pipeline As New CssResolverPipeline(cssResolver, New HtmlPipeline(htmlContext, New PdfWriterPipeline(document, writer)))
Dim pdfworker As New XMLWorker(pipeline, True)
Dim p As New XMLParser(True, pdfworker, New System.Text.UTF8Encoding)
Try
'p.AddListener(pdfworker)
'p.Parse(input, Encoding.UTF8)
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, input, New FileStream(HttpContext.Current.Server.MapPath("~/assets/css/pdf.css"), FileMode.Open, FileAccess.Read))
Catch
Finally
pdfworker.Close()
End Try
document.Close()
ms.Position = 0
Response.Buffer = True
Response.Clear()
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "attachment; filename=preview.pdf")
Response.BinaryWrite(ms.GetBuffer())
Response.Flush()
End Using
Any help appreciated.
Related
Having an issue with my button click event. I needed to add this button from one page to another so naturally it was copied and variables changed out within the click event method to match the new page. in the HTML side I added the button there too (stating in case someone wonders if I forgot that part).
Everything is identical to the other page... The issue is... when I try to run it to test the button I get a build error with no errors being displayed. One time I managed to get an error that stated "Handles clause requires a WithEvents variable defined in the containing type or one of its base types." So I commented out the handles portion of the method and it runs yay! except... the button doesn't work. I have tried a few suggestions that stated to restart the IDE, and where someone also mentioned to comment out the handles portion. Is there something I am missing?
<tr>
<td style="width: 209px" valign="middle" align="left"></td>
<td style="width: 7px;" valign="middle"></td>
<td valign="bottom" align="left">
<br>
<asp:Button ID="btnSaveAsExcel" runat="server" Width="264px" Text="Export to Excel"></asp:Button>
</td>
<td valign="middle" align="left"></td>
</tr>
Private Sub btnSaveAsExcel_Click(sender As Object, e As EventArgs) Handles btnSaveAsExcel.Click
If dgFacilitySummary.Visible Then
Dim DummydgFacilitySummary As New DataGrid
DummydgFacilitySummary.DataSource = Session("dsFacilitySummary").tables(0)
DummydgFacilitySummary.DataBind()
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" & "Faci+lity Summary Report" & ".xls")
HttpContext.Current.Response.Charset = ""
EnableViewState = False
Dim sw As New StringWriter()
Dim hw As New HtmlTextWriter(sw)
DummydgFacilitySummary.RenderControl(hw)
HttpContext.Current.Response.Write(sw.ToString())
HttpContext.Current.Response.End()
ElseIf dgFacilities.Visible Then
Dim DummydgFacilities As New DataGrid
DummydgFacilities.DataSource = Session("dsFacilityMatches").tables(0)
DummydgFacilities.DataBind()
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" & "Facility Summary Report" & ".xls")
HttpContext.Current.Response.Charset = ""
EnableViewState = False
Dim sw As New StringWriter()
Dim hw As New HtmlTextWriter(sw)
DummydgFacilities.RenderControl(hw)
HttpContext.Current.Response.Write(sw.ToString())
HttpContext.Current.Response.End()
End If
End Sub
both of that is exactly how it is on another page and it works there.
Try deleting the btnSaveAsExcel_Click() method from your code behind file. Then select btnSaveAsExcel in the drop down list on the upper left of the IDE just above your code. That will populate the drop down list on the upper right with all the events for the btnSaveAsExel button. Select the OnClick event and that will create a btnSaveAsExcel_Click() method.
It would probably be a good idea to only copy the markup and then use the method I just described to create the event handlers in the code behind file.
I am using iTextSharp to create a pdf from a gridview. When there is a null value in the table the pdf places a   in its place. How do I remove this and show the null value? I do know the pdf is created after the gridview is already populated however is there a way to tell it that nulls should show as blanks? My code is as follows:
Protected Sub btnPDF_Click(sender As Object, e As System.EventArgs) Handles btnPDF.Click
Dim pdfTable As New PdfPTable(grdResults.HeaderRow.Cells.Count)
For Each headerCell As TableCell In grdResults.HeaderRow.Cells
Dim font As New Font()
font.Color = New BaseColor(grdResults.HeaderStyle.ForeColor)
Dim pdfCell As New PdfPCell(New Phrase(headerCell.Text, font))
pdfCell.BackgroundColor = New BaseColor(grdResults.HeaderStyle.BackColor)
pdfTable.AddCell(pdfCell)
Next
For Each gridViewRow As GridViewRow In grdResults.Rows
For Each tableCell As TableCell In gridViewRow.Cells
Dim font As New Font()
font.Color = New BaseColor(grdResults.RowStyle.ForeColor)
Dim pdfCell As New PdfPCell(New Phrase(tableCell.Text, font))
pdfCell.BackgroundColor = New BaseColor(grdResults.RowStyle.BackColor)
pdfTable.AddCell(pdfCell)
Next
Next
Dim pdfDocument As New Document(iTextSharp.text.PageSize.A4, 10.0F, 10.0F, 10.0F, 10.0F)
pdfDocument.SetPageSize(PageSize.A4.Rotate())
PdfWriter.GetInstance(pdfDocument, Response.OutputStream)
pdfDocument.Open()
pdfDocument.Add(pdfTable)
pdfDocument.Close()
Response.ContentType = "application/pdf"
Response.AppendHeader("content-disposition", "attachment, filename-results.pdf")
Response.Write(PdfDocument)
Response.Flush()
Response.End()
End Sub
The values that I was receiving the   in the pdf came from calculated fields. When there was no value for the calculation it would not put anything in the gridview cell so in turn it would put the blank space value in the pdf. I went back to the calculations and if a value was not determined than I placed a space for the value. For instance -
If dtRaw.Rows(0).Item("ParameterName").ToString() <> "NOY" Then
drCalcRow("NAAQGreater") = iNAAQS
drCalcRow("NAAQGreater80") = iNAAQS80
Else
drCalcRow("NAAQGreater") = " "
drCalcRow("NAAQGreater80") = " "
End If
It works however it adds a lot to the code. It would be nice to have something one time that would check when it loops through the rows as it writes the pdf. I have tried a couple of things but nothing worked or even made an impact.
I am making an admin section that will allow access to several small SQL tables in my project.
I have repeaters set up to show my lists with a button to bring up a Modal for adding a new entry or editing an existing one. The code behind stores a value from the selected row, and then I would like to query my SQL Class to return a value to fill my text boxes. The code works back to the SQL Class and I can display a message box and get the proper results. I can't however get it to pass the value if the query back to the VB page to fill the text boxes.
Here is the Repeater
<%--Employee Repeater--%>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table class="display" id ="employeeList">
<thead>
<tr>
<th>
Name
</th>
<th>
Email
</th>
<th>
Update
</th>
</tr>
</thead>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<%# Eval("name")%>
</td>
<td>
<%# Eval("email")%>
</td>
<td>
<asp:Button ID="cmdEditName" runat="server" Text="Edit/Delete" CommandArgument= '<%#Databinder.Eval(Container.DataItem, "id")%>' OnClick="EditName"/>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
My Code Behind
'Open Name Modal bound to repeater
Public Sub EditName(ByVal sender As Object, ByVal e As System.EventArgs)
Dim wLink As New Button
Edit = True
wLink = DirectCast(sender, Button)
txtEditId.Text = wLink.CommandArgument
SQL.RunReader("SELECT name from Admin_Contacts WHERE Admin_Contacts.id = '" & txtEditId.Text & "' ")
txtEditName.Text = results
SQL.RunReader("SELECT email from Admin_Contacts WHERE Admin_Contacts.id = '" & txtEditId.Text & "' ")
txtEditEmail.Text = results
ModalName.Show()
End Sub
And the code in my SQL Class
Public Function RunReader(ByVal Query As String) As String
Dim results As String = ""
Try
SQLCon.Open()
SQLCmd = New SqlCommand(Query, SQLCon)
Dim R As SqlDataReader = SQLCmd.ExecuteReader
While R.Read
results = (R(0))
'MsgBox is just to show that I am getting results
MsgBox(results)
End While
SQLCon.Close()
Catch ex As Exception
MsgBox(ex.Message)
If SQLCon.State = ConnectionState.Open Then
SQLCon.Close()
End If
End Try
Dim results = SQL.RunReader("SELECT name from Admin_Contacts WHERE Admin_Contacts.id = '" & txtEditId.Text & "' ")
txtEditName.Text = results
Complete the runreader function with return statement
Public Function RunReader(ByVal Query As String) As String
Dim results As String = ""
Try
SQLCon.Open()
SQLCmd = New SqlCommand(Query, SQLCon)
Dim R As SqlDataReader = SQLCmd.ExecuteReader
While R.Read
results = (R(0))
'MsgBox is just to show that I am getting results
MsgBox(results)
End While
SQLCon.Close()
Catch ex As Exception
MsgBox(ex.Message)
If SQLCon.State = ConnectionState.Open Then
SQLCon.Close()
End If
End Try
Return results
End Function
Then call this method as
Dim results = SQL.RunReader("SELECT name from Admin_Contacts WHERE Admin_Contacts.id = '" & txtEditId.Text & "' ")
I am having trouble exporting my gridview to an excel file. Everything works except when I hit the export button, the data that is supposed to be exported to an excel file displays on the web page instead. I am suspecting that this is a problem with Response.ContentType and the file name that I specified. However, I already went through multiple documentations and examples and it doesn't seem like those two are the root problems in my case. Can Anyone help?
<asp:Button ID="btnExport" runat="server" Text="Export To MS Excel File" CssClass="btnMain" OnClick="btnExport_Click" />
Protected Sub btnExport_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim filename As String = "PerformanceEval Status Report" & Date.Now.Year.ToString & "-" & _
formatNumberTo2Digits(DateTime.Now.Month) & "-" & formatNumberTo2Digits(DateTime.Now.Day) & ".xls"
With Page.Response
.Clear()
.Buffer = True
.AddHeader("content_disposition", "attachment;filename" & filename)
.Charset = ""
'--to open the Excel file without saving then comment out the line below
'.Cache.SetCacheability(HttpCacheability.NoCache)
'.ContentType = "application/vnd.xls" 'data appears on web page
'.ContentType = "application/vnd.ms-excel" 'try to download .aspx document NOT .xml
.ContentType = "application/ms-excel" 'data appears on web page
End With
Dim strWriter As New System.IO.StringWriter
Dim htmlWriter As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(strWriter)
Dim gvexport As GridView = New GridView
gvexport.AutoGenerateColumns = False
gvexport.CssClass = "gridData"
gvexport.GridLines = GridLines.Horizontal
gvexport.HeaderStyle.CssClass = "gridHeader"
gvexport.RowStyle.CssClass = "gridRow"
gvexport.AlternatingRowStyle.CssClass = "gridRow_Alt"
gvexport.FooterStyle.CssClass = "gridFooter"
Dim dv As DataView = New DataView(Me.ds.Tables(0)) 'default is sorted by last name
'Dim dv As DataView = New DataView(Me.ds.Tables(0))
dv.RowFilter = GetFilter()
'-- add columns for report
addGVcolumn("Employee Name", "EmployeeName", gvexport, -1, HorizontalAlign.Left)
addGVcolumn("Employee ID", "SID", gvexport, -1, HorizontalAlign.Left)
addGVcolumn("Email", "WorkEmail", gvexport, -1, HorizontalAlign.Left)
addGVcolumn("StatusID", "StatusID", gvexport, 50, HorizontalAlign.Center)
gvexport.DataSource = dv
gvexport.DataBind()
gvexport.RenderControl(htmlWriter)
Response.Output.Write(strWriter.ToString())
Response.Flush()
Response.End()
Again, I am able to generate the content but is not able to make my data exports into excel. Thanks a lot!
You are giving the wrong header:
.AddHeader "content-disposition", "attachment; filename="& filename &";"
I have a problem trying to apply a css file to my pdf using the iTextSharp (5.4.3) generation library. basically the css is not being applied at all.
I have the following method in my vb.net file
Protected Sub btnPreview_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnPreview.Click
Dim bytes As Byte()
bytes = System.Text.Encoding.UTF8.GetBytes(letterRadEdit.Content)
Dim tagProcessor As tool.xml.html.DefaultTagProcessorFactory()
Using input As New MemoryStream(bytes, False)
Dim ms As New MemoryStream()
Dim document As New iTextSharp.text.Document(iTextSharp.text.PageSize.LETTER, 36, 36, 36, 36)
Dim writer As PdfWriter = PdfWriter.GetInstance(document, ms)
writer.CloseStream = False
document.Open()
Dim htmlContext As HtmlPipelineContext = New HtmlPipelineContext(Nothing)
htmlContext.SetAcceptUnknown(True)
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory())
Dim cssResolver As ICSSResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(False)
cssResolver.AddCssFile(HttpContext.Current.Server.MapPath("/assets/css/pdf.css"), True)
Dim pipeline As New CssResolverPipeline(cssResolver, New HtmlPipeline(htmlContext, New PdfWriterPipeline(document, writer)))
Dim pdfworker As New XMLWorker(pipeline, True)
Dim p As New XMLParser(True, pdfworker, New System.Text.UTF8Encoding)
Try
'p.AddListener(pdfworker)
'p.Parse(input, Encoding.UTF8)
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, input, New FileStream(HttpContext.Current.Server.MapPath("~/assets/css/pdf.css"), FileMode.Open, FileAccess.Read))
Catch
Finally
pdfworker.Close()
End Try
document.Close()
ms.Position = 0
Response.Buffer = True
Response.Clear()
Response.ContentType = "application/pdf"
Response.AddHeader("content-disposition", "attachment; filename=preview.pdf")
Response.BinaryWrite(ms.GetBuffer())
Response.Flush()
End Using
End Sub
the CSS file simply contains :
p{color:#e10000;margin-bottom:1.2em;}
(This is to test whether it's rendering correctly, all text should be red)
My problem is that the following command
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, input, New FileStream(HttpContext.Current.Server.MapPath("~/assets/css/pdf.css"), FileMode.Open, FileAccess.Read))
correctly produces the pdf, but doesn't apply the CSS to it. I know it's reading the CSS because I had a permissions exception until I applied the FileAccess.Read property
the method
p.Parse(input, Encoding.UTF8)
doesn't produce any pdf, just an 'Element not allowed' exception, this is because the html (coming from a radeditor text box Q3 2013) is old html and the parse seems to have a problem with tables.
iTextSharp is very poor with designs using css, images etc. Instead wkhtmltopdf is the best.
Well it would appear that the CSS was correctly being applied as I tested a
td{
border:1px solid red;
padding:0.4em;
margin:0;
}
to the pdf, and all the cells got bordered in red, so it would appear that the pdf overrides certain styles. Not sure why.