Method XbpHTMLViewer2():printToFile() Foundation

Outputs the current page to a file (PDF).

Syntax
:printToFile( <cFile>, <oPrintSettings> ) --> oAsyncResult
Parameters
<cFile>
Name and path of the PDF file to write the output into.
<oPrintSettings>
A CoreWebView2PrintSettings() object with the desired settings for output. This parameter is optional. The object exposes various WebView2-specific output settings via its member variables. If no object is passed, the default settings are used.
Return

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.

Description

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 

Feedback

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.