Reputation: 115
Hello everyone and thanks for your help in advance. I need to develop an application to generate a multipage PDF with iTextSharp. Each page needs to have a header and footer. Additionally, each page will have a variety of different objects including tables, paragraphs, and something similar to listitems (probably a cone column table). I'm trying to find a tutorial to accomplish this. At the heart of my confusion is how to determine when a break should happen and how to not overlay the footer if for example the table or paragraph is too long to fit on the page. Any help would be appreciated.
I appreciate the response from Bruno and am intrigued with styling an HTML page, then rendering with iText, but I'm really struggling with how to actually do this on a real page. Here is some sample HTML of the page I want to print:
<body>
<header class="onlyprint">
<ul>
<li>
Dr. Who
</li>
<li>
1234 Somewhere St.
</li>
<li>
Anywhere, US 12345
</li>
</ul>
</header>
<div id="divmain" style="width: 760px;">
<ul id="ulPatientDetails">
<li>
<label>Patient Name:</label>
<span>TESTCASE, TOM</span>
</li>
<li>
<label>MRNumber:</label>
<span>999999</span>
</li>
<li>
<label>Patient DOB:</label>
<span>99/99/9999</span>
</li>
</ul>
<table id="tblhistorian">
<caption>Historian</caption>
<tr>
<th>Time Entered</th>
<th>Historian</th>
<th>Historian Name</th>
<th>Other Persons</th>
<th>Language</th>
<th>Other Language</th>
<th>Translator</th>
<th>Entered By</th>
</tr>
<tr>
<td>
99/99/9999
</td>
<td>
Mother
</td>
<td></td>
<td></td>
<td>
English
</td>
<td></td>
<td></td>
<td>
Dr. Who
</td>
</tr>
</table>
<ul id="ulPatientAllergies">
<li>
<label>Allergies:</label>
<span>BLAH BLAH BLAH BLAH</span>
</li>
</ul>
<table id="tblTobaccoUse">
<caption>Tobacco Use</caption>
<tr>
<th>Patient Uses Tobacco</th>
<th>Family Uses Tobacco</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td>N/A</td>
<td>No</td>
<td>Someone</td>
<td>99/99/9999</td>
</tr>
</table>
<table id="outsidemedications">
<caption>Active Prescriptions</caption>
<tr>
<th>Date</th>
<th>Prescribed By</th>
<th>Prescription</th>
<th>SIG</th>
<th>Route</th>
<th>Dispense</th>
<th>Refills</th>
</tr>
<tr>
<td>
99/99/9999
</td>
<td>
DR. WHO
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
</td>
<td>
</td>
<td>
0
</td>
</tr>
<tr>
<td>
99/99/9999
</td>
<td>
DR. WHO
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
<table id="outsidemedications">
<caption>Other Medications</caption>
<tr>
<th>Medication</th>
<th>SIG</th>
<th>Source</th>
<th>Category</th>
<th>Comments</th>
<th>Entered By</th>
<th>Date Entered</th>
</tr>
<tr>
<td colspan="7">No current medications.</td>
</tr>
</table>
<table id="tblChiefComplaints">
<caption>Chief Complaints</caption>
<tr>
<th>Category</th>
<th>Description</th>
<th>Duration</th>
</tr>
<tr>
<td>General</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>BLAH BLAH BLAH BLAH</td>
</tr>
<tr>
<td>General</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>BLAH BLAH BLAH BLAH</td>
</tr>
</table>
<table id="tblReviewOfSystems">
<caption>Review of Systems</caption>
<tr>
<th>Category</th>
<th>Symptom</th>
<th>Result</th>
</tr>
<tr>
<td>General</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Skin</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Eyes</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Ears</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Nose</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Mouth or Teeth</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Face or Neck</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Respiratory</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Cardio</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Abdomen</td>
<td>BLAH BLAH BLAH BLAH </td>
<td>None</td>
</tr>
<tr>
<td>MSLymph</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
<tr>
<td>Neuro</td>
<td>BLAH BLAH BLAH BLAH</td>
<td>None</td>
</tr>
</table>
<table id="tblPesentIllnesses">
<caption>History of Present Illnesses</caption>
<tr>
<th>Complaint</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td>BLAH BLAH BLAH BLAH</td>
<td>Dr. Who</td>
<td>99/99/9999</td>
</tr>
<tr>
<td>BLAH BLAH BLAH BLAH</td>
<td>Dr. Who</td>
<td>99/99/9999</td>
</tr>
<tr>
<td>BLAH BLAH BLAH BLAH</td>
<td>Dr. Who</td>
<td>99/99/9999</td>
</tr>
</table>
<table id="tblFamilyIllnesses">
<caption>Family History</caption>
<tr>
<th>Relationship</th>
<th>Name</th>
<th>DOB</th>
<th>Age</th>
<th>Illness</th>
</tr>
</table>
<table id="tblWellChildHistory">
<caption>Well Child History</caption>
<tr>
<th>Dietary History</th>
<th>Physical Activity</th>
<th>Sleeping Habits</th>
<th>Bowel Habits</th>
<th>Dental Visit In Past Year</th>
<th>Exposure To Illnesses</th>
<th>Alcohol Use</th>
<th>Drug Use</th>
<th>Travel History</th>
<th>Sexual Activity</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td colspan="3">No past medical history.</td>
</tr>
</table>
<table id="tblSocialHistory">
<caption>Social History</caption>
<tr>
<th>Primary Caregiver</th>
<th>Home Status</th>
<th>Child Attends</th>
<th>School Name</th>
<th>Grade</th>
<th>School Performance</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td colspan="12">No social history entered for this visit.</td>
</tr>
</table>
<table id="tblDevelopmentalMilestones">
<caption>Developmental Milestones</caption>
<tr>
<th>Category</th>
<th>Question</th>
<th>Answer</th>
<th>Entered By</th>
<th>TimeEntered</th>
</tr>
<tr>
<td colspan="3">No developmental assessment entered.</td>
</tr>
</table>
<table id="tblDevelopmentalComments">
<caption>Developmental Comments</caption>
<tr>
<th>Comment</th>
<th>Entered By</th>
<th>TimeEntered</th>
</tr>
<tr>
<td colspan="3">No developmental comments entered.</td>
</tr>
</table>
<table id="tblHouseholdRiskFactorResponses">
<caption>Household Risk Factors</caption>
<tr>
<th>Question</th>
<th>Response</th>
<th>Comment</th>
</tr>
<tr>
<td colspan="3">No household risk factors entered for this visit.</td>
</tr>
</table>
<table id="tblFamilyBarriersResponses">
<caption>Family Barriers</caption>
<tr>
<th>Question</th>
<th>Response</th>
<th>Comment</th>
</tr>
<tr>
<td colspan="3">No household risk factors entered for this visit.</td>
</tr>
</table>
<table id="tblPHQAAssessments">
<caption>PHQ-A Assessment</caption>
<tr>
<th>Question</th>
<th>Response</th>
<th>Score</th>
</tr>
<tr>
<td colspan="3">No current assessments.</td>
</tr>
</table>
<table id="tblPatientVitals">
<caption>Vitals</caption>
<tr>
<th>Time Entered</th>
<th>Temp.</th>
<th>H.R.</th>
<th>R.R.</th>
<th>Weight</th>
<th>Height</th>
<th>BMI</th>
<th>Head Circ.</th>
<th>O2 Sat.</th>
<th>BP</th>
<th>Comments</th>
<th>Entered By</th>
</tr>
<tr>
<td>11/3/2017 2:51:00 PM</td>
<td>98.6</td>
<td>90</td>
<td>25</td>
<td>58.0000</td>
<td>0.0000</td>
<td></td>
<td>0.0000</td>
<td>0.0000</td>
<td>0/0 Sitting Sitting</td>
<td></td>
<td>Dr. Who</td>
</tr>
</table>
<ul id="ulexamdetails">
<li id="liphysicalexamheader">Physical Exam</li>
<li><span class="categorylabel">General</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span><span class="spexception"> Except: BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Skin</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Head</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Eyes</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Ears</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Nose</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Mouth</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span><span class="spexception"> Except: BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Face Or Neck</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Respiratory</span></li>
<li><span class="spnormal"></span></li>
<li><span class="categorylabel">Cardio</span></li>
<li>
<span class="spnormal">BLAH BLAH BLAH BLAH
</span>
</li>
<li><span class="categorylabel">Abdomen</span></li>
<li>
<span class="spnormal">BLAH BLAH BLAH BLAH
</span>
</li>
<li><span class="categorylabel">MS/Lymph</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
<li><span class="categorylabel">Neuro</span></li>
<li><span class="spnormal">BLAH BLAH BLAH BLAH</span></li>
</ul>
<table id="tblVisionResults">
<caption>Vision Results</caption>
<tr>
<th>Left Eye</th>
<th>Right Eye</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td colspan="4">No vision results this visit.</td>
</tr>
</table>
<table id="tblHearingTestResults">
<caption>Hearing Results</caption>
<tr>
<th>Frequency</th>
<th>Db Right</th>
<th>Db Left</th>
<!--
<th>Entered By</th>
<th>Time Entered</th>
-->
</tr>
<tr>
<td colspan="4">No hearing results this visit.</td>
</tr>
</table>
<table id="tblInhouseLabs">
<caption>In-house Labs</caption>
<tr>
<th>Lab</th>
<th>Lab Value</th>
<th>Comment</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td colspan="4">No in-house labs results this visit.</td>
</tr>
</table>
<table id="tblInhouseUrineResults">
<caption>In-house Urine Results</caption>
<tr>
<th>Leukocytes</th>
<th>Nitrite</th>
<th>Urobili</th>
<th>Protein</th>
<th>PH</th>
<th>Blood</th>
<th>SG</th>
<th>Ketone</th>
<th>Bilirubin</th>
<th>Glucose</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td colspan="12">No urine results this visit.</td>
</tr>
</table>
<table id="tblInOfficeCourse">
<caption>Assessment</caption>
<tr>
<th>In-Office Course</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td colspan="3">No in-office course.</td>
</tr>
</table>
<fieldset id="fldassessment">
<legend>Assessment</legend>
<table id="tbldiagnosiscodes" name="tbldiagnosiscodes"></table>
<table id="tblPatientAssessment">
<caption>Assessment</caption>
<tr>
<th>Assessment</th>
<th>Entered By</th>
<th>Time Entered</th>
</tr>
<tr>
<td>BLAH BLAH BLAH BLAH</td>
<td>Dr. Who</td>
<td>99/99/9999</td>
</tr>
</table>
<table id="tblComplianced">
<caption>Compliance</caption>
<tr>
<th>Compliance</th>
<th>Compliance Code</th>
<th>Entered By</th>
<th>Time Entered By</th>
</tr>
<tr>
<td colspan="4">No Compliance Entered This Visit.</td>
</tr>
</table>
</fieldset>
<fieldset id="fldplanofcare">
<legend>Plan of Care</legend>
<table id="tblvisitprescriptions" name="tblvisitprescriptions"></table>
<table id="tblDiagnosisCodes">
<caption>Diagnosis Codes</caption>
<tr>
<th>Code</th>
<th>Description</th>
</tr>
<tr>
<td colspan="2">No Diagnosis Codes Entered</td>
</tr>
</table>
<table id="tblCPTCodes">
<caption>CPT Codes</caption>
<tr>
<th>Code</th>
<th>Description</th>
</tr>
<tr>
<td>
99213
</td>
<td>
ESTAB. EXPANDED
</td>
</tr>
</table>
<table id="tblPrescriptionsThisVisit">
<caption>Prescriptions This Visit</caption>
<tr>
<th>Date</th>
<th>Prescribed By</th>
<th>Prescription</th>
<th>SIG</th>
<th>Route</th>
<th>Dispense</th>
<th>Refills</th>
</tr>
<tr>
<td>
99/99/9999
</td>
<td>
Dr. Who
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
BLAH BLAH BLAH BLAH
</td>
<td>
</td>
<td>
</td>
<td>
0
</td>
</tr>
</table>
<table id="tblLabsOrdered">
<caption>Labs Ordered This Visit</caption>
<tr>
<th>Date</th>
<th>Test Ordered</th>
<th>Ordered By</th>
<th>Order Urgency</th>
</tr>
<tr>
<td colspan="4">No Labs Ordered This Visit.</td>
</tr>
</table>
<table id="outsidemedications">
<caption>Radiology Orders This Visit</caption>
<tr>
<th>Date</th>
<th>Test Ordered</th>
<th>Ordered By</th>
<th>Order Urgency</th>
</tr>
<tr>
<td colspan="4">No Radiology Ordered This Visit.</td>
</tr>
</table>
<table id="tblcptcodes" name="tblcptcodes"></table>
<table id="tblReferrals">
<caption>Referrals This Visit</caption>
<tr>
<th>Speciality</th>
<th>Speciality Group</th>
<th>Specialist</th>
</tr>
<tr>
<td colspan="4">No Referrals This Visit.</td>
</tr>
</table>
<div id="divplanofcare">
<ul id="ulcareplanlist">
<li>BLAH BLAH BLAH BLAH</li>
</ul>
</div>
</fieldset>
</div>
<!--End of body-->
<footer class="onlyprint">
<ul>
<li>Tom Testcase</li>
<li>99/99/9999</li>
</ul>
</footer>
</body>
I'm not exactly sure how to implement the CSS to make sure the page contents don't overwrite the footer. Also, since many of the elements on the page are tables that may expand, do you have to have some advance knowledge of how much data is in these element on where to use page break? Would someone please help me get started? Thanks.
Upvotes: 0
Views: 1315
Reputation: 917
An example of setting up your document with headers, footers and page breaks with CSS:
Page set up
@page {
size: A4 portrait;
margin-left: 0.5cm;
margin-right: 0.5cm;
background: #FFF;
}
Headers
@page {
@top-left {
margin: 10pt 0 10pt 10pt;
border-top: .25pt solid #666;
font-size: 9pt;
color: #FFF;
}
@top-center {
margin: 10pt 10pt 10pt 0;
border-top: .25pt solid #666;
font-size: 9pt;
color: #FFF;
}
@top-right {
margin: 10pt 10pt 10pt 0;
border-top: .25pt solid #666;
font-size: 9pt;
color: #FFF;
}
}
Footers
@page {
@bottom-left {
margin: 10pt 0 10pt 10pt;
border-top: .25pt solid #666;
font-size: 9pt;
color: #FFF;
}
@bottom-center {
margin: 10pt 10pt 10pt 0;
border-top: .25pt solid #666;
font-size: 9pt;
color: #FFF;
}
@bottom-right {
margin: 10pt 10pt 10pt 0;
border-top: .25pt solid #666;
font-size: 9pt;
color: #FFF;
content: "Page " counter(page) " of " counter(pages); /* Add if you need page numbers */
}
}
Page breaks
Use page-break-before
, page-break-after
, and page-break-inside
on your elements to set up appropriate page breaks.
Additional reading
Update by Bruno Lowagie
The above anwer is correct, but incomplete. It explains how to define headers and footers in HTML, but doesn't explain how to create a PDF with those headers and footers. Fortunately, this requires only a single line of code.
See the HTML to PDF tutorial. In Chapter 2: defining styles and CSS, there's a section named Adding "Page X of Y" using an @page rule that shows how the @page
rule works in combination with the pdfHTML add-on for iText 7.
All you need to do, is write this line of code:
HtmlConverter.ConvertToPdf(src, dest);
where src
is the source (a HTML file) and dest
is the destination (a PDF file).
Upvotes: 1
Reputation: 77528
First of all: we no longer talk about iTextSharp. iTextSharp was renamed to iText for .NET. The current version is iText 7.
Adding headers and footers is explained in chapter 3 of the iText 7 Jump-Start Tutorial for .NET:
First, you need to create an implementation of the IEventHandler
interface, for example:
protected internal class MyEventHandler : IEventHandler {
public virtual void HandleEvent(Event @event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent)@event;
PdfDocument pdfDoc = docEvent.GetDocument();
PdfPage page = docEvent.GetPage();
int pageNumber = pdfDoc.GetPageNumber(page);
Rectangle pageSize = page.GetPageSize();
PdfCanvas pdfCanvas = new PdfCanvas(page.NewContentStreamBefore(), page.GetResources(), pdfDoc);
//Set background
Color limeColor = new DeviceCmyk(0.208f, 0, 0.584f, 0);
Color blueColor = new DeviceCmyk(0.445f, 0.0546f, 0, 0.0667f);
pdfCanvas.SaveState()
.SetFillColor(pageNumber % 2 == 1 ? limeColor : blueColor)
.Rectangle(pageSize.GetLeft(), pageSize.GetBottom(), pageSize.GetWidth(), pageSize.GetHeight())
.Fill()
.RestoreState();
//Add header and footer
pdfCanvas.BeginText()
.SetFontAndSize(C03E03_UFO.helvetica, 9)
.MoveText(pageSize.GetWidth() / 2 - 60, pageSize.GetTop() - 20)
.ShowText("THE TRUTH IS OUT THERE")
.MoveText(60, -pageSize.GetTop() + 30)
.ShowText(pageNumber.ToString())
.EndText();
//Add watermark
iText.Layout.Canvas canvas = new iText.Layout.Canvas(pdfCanvas, pdfDoc, page.GetPageSize());
canvas.SetProperty(Property.FONT_COLOR, Color.WHITE);
canvas.SetProperty(Property.FONT_SIZE, 60);
canvas.SetProperty(Property.FONT, C03E03_UFO.helveticaBold);
canvas.ShowTextAligned(new Paragraph("CONFIDENTIAL"), 298, 421, pdfDoc.GetPageNumber(page), TextAlignment.
CENTER, VerticalAlignment.MIDDLE, 45);
pdfCanvas.Release();
}
}
In the event handler above, we set a back ground, add a header and a footer, add a watermark. That's more than you need, but feel free to adapt.
Once you have this implementation, you can declare it as an event handler for a specific PdfDocument
instance:
PdfDocument pdf = new PdfDocument(new PdfWriter(dest));
pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, new MyEventHandler(this));
For the full example, see C03E03_UFO.cs.
Upvotes: 0