Method XbpHTMLViewer2():printToFile() Foundation
Outputs the current page to a file (PDF).
:printToFile( <cFile>, <oPrintSettings> ) --> oAsyncResult
A AsyncResult() object which can be used for waiting for the operation to complete and for retrieving the operation result. This the number of Bytes written to the file.
The contents of the current page can be written to a PDF file using the :printToFile() method. This is similar to printing the page using the method :print() but creates a PDF file on disk instead.
Various aspects of the output operation can be configured via an optional CoreWebView2PrintSettings object which exposes various WebView2-specific output settings.
Only one print job can be active at a given time. The output is performed asynchronously. :printToFile() returns a AsyncResult() object which can be used to wait for the operation to complete and for retrieving the status of the operation.
Example for creating a PDF from a webpage
// This example demonstrates creating a PDF file from the HTML content
// loaded into a XbpHTMLViewer2 instance, in this case, a sample HTML
// invoice. The invoice contains the data in the HTML and uses CSS to
// adjust the invoice's styling for screen and printer/PDF output. A
// CoreWebView2PrintSettings object is used for specifying the desired
// output properties and the example outputs information on whether
// PDF creation succeeded or not.
#include "xbp.ch"
PROCEDURE Main()
LOCAL oDlg
LOCAL oViewer2
LOCAL oXbp
SET CHARSET TO ANSI
// Create a form for hosting the HTML viewer object and a button
// for creating a PDF from the invoice
oDlg := XbpDialog():new( AppDesktop() )
oDlg:taskList := .T.
oDlg:title := "XbpHTMLViewer2:printToFile() example"
oDlg:create( ,,, {750,540} )
CenterControl( oDlg )
oXbp := XbpPushButton():new( oDlg:drawingArea )
oXbp:caption := "Create PDF"
oXbp:activate := {|| CreateInvoicePDF(oViewer2, "INV-20151016000514")}
oXbp:layoutAlign := XBPLAYOUT_RIGHT + XBPLAYOUT_BOTTOM
oXbp:create( ,, {620,10}, {100,40} )
// Create the HTML viewer object in the form's content area
oViewer2 := XbpHTMLViewer2():new( oDlg:drawingArea )
oViewer2:layoutAlign := XBPLAYOUT_LEFT + XBPLAYOUT_TOP + XBPLAYOUT_RIGHT + XBPLAYOUT_BOTTOM
oViewer2:create( ,, {10,10}, {600,480} )
// Load the invoice into the HTML viewer
DisplayInvoice( oViewer2, "INV-20151016000514" )
oDlg:showModal()
oDlg:destroy()
RETURN
// Load an invoice into the HTML viewer
PROCEDURE DisplayInvoice( oViewer2, cId )
LOCAL cHTML
cHTML := LoadInvoice( cId )
oViewer2:setHTML( cHTML )
RETURN
// Create a PDF from the invoice currently loaded/displayed in the HTML viewer
PROCEDURE CreateInvoicePDF( oViewer2, cId )
LOCAL oPrintSettings
LOCAL oAsyncResult
LOCAL cMsg
// Specify desired output properties using a print settings object:
// - page header containing the invoice number
// - page footer which doesn't contain the file name (is empty)
oPrintSettings := CoreWebView2PrintSettings():new()
oPrintSettings:headerTitle := "Invoice: " + cId
oPrintSettings:footerUri := ""
oPrintSettings:shouldPrintHeaderAndFooter := .T.
// Output the invoice into a PDF in the local folder
oAsyncResult := oViewer2:printToFile( cId + ".pdf", oPrintSettings )
// Wait for the operation to complete and verify result. Output an error
// message if an error occured or the target file is empty
oAsyncResult:wait()
IF oAsyncResult:state() == "error" .OR. oAsyncResult:get() == 0
cMsg := "Unable to output invoice " + cId
ELSE
cMsg := "Invoice " + cId + " saved successfully."
ENDIF
MsgBox( cMsg, "PDF Output" )
RETURN
// Load an invoice given an invoice id
FUNCTION LoadInvoice( cId )
LOCAL cHTML
// This function just returns static HTML code for demonstrational
// purpose. In a real-word application, the invoice would be loaded
// from disk or from a database
UNUSED( cId )
TEXT INTO cHTML WRAP
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Invoice #INV-2024-001</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
color: #333;
background-color: #f5f5f5;
padding: 20px;
}
.invoice-container {
max-width: 210mm;
margin: 0 auto;
background: white;
padding: 20mm;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.header {
display: flex;
justify-content: space-between;
align-items: start;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 3px solid #2c3e50;
}
.company-details h1 {
font-size: 26px;
color: #2c3e50;
margin-bottom: 5px;
}
.company-details p {
color: #7f8c8d;
line-height: 1.4;
font-size: 13px;
}
.invoice-details {
text-align: right;
}
.invoice-details h2 {
font-size: 24px;
color: #e74c3c;
margin-bottom: 5px;
}
.invoice-details p {
line-height: 1.5;
font-size: 13px;
}
.addresses {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.address-block {
width: 48%;
}
.address-block h3 {
font-size: 12px;
text-transform: uppercase;
color: #7f8c8d;
margin-bottom: 6px;
letter-spacing: 1px;
}
.address-block p {
line-height: 1.5;
font-size: 13px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 15px;
font-size: 13px;
}
thead {
background-color: #2c3e50;
color: white;
}
thead th {
padding: 10px 8px;
text-align: left;
font-weight: 600;
text-transform: uppercase;
font-size: 11px;
letter-spacing: 0.5px;
}
thead th:last-child {
text-align: right;
}
tbody td {
padding: 8px;
border-bottom: 1px solid #ecf0f1;
font-size: 13px;
}
tbody td small {
font-size: 11px;
}
tbody td:last-child {
text-align: right;
font-weight: 600;
}
tbody tr:hover {
background-color: #f8f9fa;
}
.totals {
margin-left: auto;
width: 280px;
}
.totals-row {
display: flex;
justify-content: space-between;
padding: 6px 0;
border-bottom: 1px solid #ecf0f1;
font-size: 13px;
}
.totals-row.subtotal {
font-size: 13px;
}
.totals-row.tax {
font-size: 13px;
color: #7f8c8d;
}
.totals-row.total {
font-size: 18px;
font-weight: bold;
color: #2c3e50;
border-top: 2px solid #2c3e50;
border-bottom: 3px double #2c3e50;
margin-top: 6px;
padding-top: 10px;
}
.notes {
margin-top: 20px;
padding: 12px;
background-color: #f8f9fa;
border-left: 4px solid #3498db;
}
.notes h3 {
font-size: 12px;
margin-bottom: 6px;
color: #2c3e50;
}
.notes p {
line-height: 1.4;
color: #7f8c8d;
font-size: 11px;
}
.footer {
margin-top: 20px;
padding-top: 12px;
border-top: 2px solid #ecf0f1;
text-align: center;
color: #95a5a6;
font-size: 10px;
}
/* Responsive styles for mobile and tablet */
@media screen and (max-width: 768px) {
body {
padding: 10px;
}
.invoice-container {
padding: 15px;
}
.header {
flex-direction: column;
gap: 20px;
}
.company-details h1 {
font-size: 24px;
}
.invoice-details {
text-align: left;
}
.invoice-details h2 {
font-size: 22px;
}
.addresses {
flex-direction: column;
gap: 20px;
}
.address-block {
width: 100%;
}
table {
font-size: 14px;
}
thead th {
padding: 10px 5px;
font-size: 11px;
}
tbody td {
padding: 10px 5px;
}
tbody td small {
font-size: 11px;
}
.totals {
width: 100%;
}
.totals-row.total {
font-size: 18px;
}
.notes {
padding: 15px;
font-size: 14px;
}
}
@media screen and (max-width: 480px) {
.company-details h1 {
font-size: 20px;
}
.invoice-details h2 {
font-size: 18px;
}
table {
font-size: 12px;
}
thead th {
padding: 8px 3px;
font-size: 10px;
}
tbody td {
padding: 8px 3px;
}
.totals-row {
font-size: 14px;
}
.totals-row.total {
font-size: 16px;
}
}
/* Print styles */
@media print {
body {
background: white;
padding: 0;
}
.invoice-container {
box-shadow: none;
padding: 0;
max-width: 100%;
}
@page {
size: A4;
margin: 20mm;
}
.no-print {
display: none;
}
}
</style>
</head>
<body>
<div class="invoice-container">
<!-- Header -->
<div class="header">
<div class="company-details">
<h1>ACME Corp</h1>
<p>
123 Business Street<br>
New York, NY 10001<br>
Phone: (555) 123-4567<br>
Email: billing@acmecorp.com
</p>
</div>
<div class="invoice-details">
<h2>INVOICE</h2>
<p>
<strong>Invoice #:</strong> INV-2024-001<br>
<strong>Date:</strong> October 28, 2025<br>
<strong>Due Date:</strong> November 27, 2025
</p>
</div>
</div>
<!-- Addresses -->
<div class="addresses">
<div class="address-block">
<h3>Bill To</h3>
<p>
<strong>John Smith</strong><br>
XYZ Corporation<br>
456 Client Avenue<br>
Los Angeles, CA 90001<br>
United States
</p>
</div>
<div class="address-block">
<h3>Ship To</h3>
<p>
<strong>John Smith</strong><br>
XYZ Corporation<br>
789 Delivery Road<br>
Los Angeles, CA 90002<br>
United States
</p>
</div>
</div>
<!-- Items Table -->
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<strong>Website Design & Development</strong><br>
<small>Custom responsive website with 5 pages</small>
</td>
<td>1</td>
<td>$2,500.00</td>
<td>$2,500.00</td>
</tr>
<tr>
<td>
<strong>Logo Design</strong><br>
<small>Professional logo with 3 revision rounds</small>
</td>
<td>1</td>
<td>$750.00</td>
<td>$750.00</td>
</tr>
<tr>
<td>
<strong>SEO Optimization</strong><br>
<small>On-page SEO and meta tags setup</small>
</td>
<td>1</td>
<td>$500.00</td>
<td>$500.00</td>
</tr>
<tr>
<td>
<strong>Content Management System</strong><br>
<small>CMS integration and training</small>
</td>
<td>1</td>
<td>$1,200.00</td>
<td>$1,200.00</td>
</tr>
<tr>
<td>
<strong>Hosting & Domain (1 Year)</strong><br>
<small>Premium hosting and domain registration</small>
</td>
<td>1</td>
<td>$350.00</td>
<td>$350.00</td>
</tr>
</tbody>
</table>
<!-- Totals -->
<div class="totals">
<div class="totals-row subtotal">
<span>Subtotal:</span>
<span>$5,300.00</span>
</div>
<div class="totals-row tax">
<span>Tax (10%):</span>
<span>$530.00</span>
</div>
<div class="totals-row total">
<span>Total:</span>
<span>$5,830.00</span>
</div>
</div>
<!-- Notes -->
<div class="notes">
<h3>Payment Terms & Notes</h3>
<p>
Payment is due within 30 days of invoice date. Please make payment via bank transfer to the account details below,
or by check made payable to ACME Corp. Late payments may incur a 5% monthly interest charge.
Thank you for your business!
</p>
<p style="margin-top: 10px;">
<strong>Bank Details:</strong> Bank of America | Account: 123456789 | Routing: 987654321
</p>
</div>
<!-- Footer -->
<div class="footer">
<p>Thank you for your business!</p>
<p>ACME Corp • Tax ID: 12-3456789 • www.acmecorp.com</p>
</div>
</div>
</body>
</html>
ENDTEXT
RETURN cHTML
PROCEDURE AppSys()
// Prevent creation of the default console window
RETURN
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.