How HTML & CSS Code Can Be Used to Print POS on vb.net

213 Views Asked by At

I tried printing from HTML and CSS on a printer with the program language vb.net.

Please Guide Me

one more I want to add QR in footer section

This My code :

Public Class Form1
    Private Function ToHtml() As String
        Dim Pathimageheader As String = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logo.png")
        Dim Pathimagefooter As String = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Qr.png")
        Dim html =
            <html>
                <head>
                    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
                    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
                    <title>Receipt example</title>
                    <link rel="stylesheet" href="style.css"/>
                </head>
                <style>
                {
    font-size: 12px;
    font-family: 'Times New Roman';
}
td,
th,
tr,
table {
    border-top: 1px solid black;
    border-collapse: collapse;
}

td.description,
th.description {
    width: 75px;
    max-width: 75px;
}

td.quantity,
th.quantity {
    width: 40px;
    max-width: 40px;
    word-break: break-all;
}

td.price,
th.price {
    width: 40px;
    max-width: 40px;
    word-break: break-all;
}

.centered {
    text-align: center;
    align-content: center;
}

.ticket {
    width: 155px;
    max-width: 155px;
}

img {
    max-width: inherit;
    width: inherit;
}
</style>
                <body>
                    <div class="ticket">
                        <img src=<%= Pathimageheader %> alt="logo"></img>
                        <p class="centered">RECEIPT EXAMPLE
                        <br>Address line 1
                        </br><br>Address line2</br></p>
                        <table>
                            <thead>
                                <tr>
                                    <th class="quantity">Q.</th>
                                    <th class="description">Description</th>
                                    <th class="price">$$</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td class="quantity">1.00</td>
                                    <td class="description">ARDUINO UNO R3</td>
                                    <td class="price">$25.00</td>
                                </tr>
                                <tr>
                                    <td class="quantity">2.00</td>
                                    <td class="description">JAVASCRIPT BOOK</td>
                                    <td class="price">$10.00</td>
                                </tr>
                                <tr>
                                    <td class="quantity">1.00</td>
                                    <td class="description">STICKER PACK</td>
                                    <td class="price">$10.00</td>
                                </tr>
                                <tr>
                                    <td class="quantity"></td>
                                    <td class="description">TOTAL</td>
                                    <td class="price">$55.00</td>
                                </tr>
                            </tbody>
                        </table>
                        <p class="centered">Thanks for your purchase!
                             <br>parzibyte.me/blog</br></p>
                        <img src=<%= Pathimagefooter %> alt="logo"></img>
                    </div>
                </body>
            </html>

        Return html.ToString()
    End Function
 Private Sub BtnPrint_Click(sender As Object, e As EventArgs) Handles BtnPrint.Click
    
        myWebBrowser.DocumentText = ToHtml()

    End Sub
 Private Sub myWebBrowser_DocumentCompleted(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs) Handles myWebBrowser.DocumentCompleted
        myWebBrowser.Parent = Me
        myWebBrowser.Visible = False
        myWebBrowser.ShowPrintPreviewDialog()
    End Sub

Desired result (without botton)

sorry I can't post the original html and css code because of an error at the time of posting but below is the link of the html and css code

link

enter image description here

enter image description here

result after update code

result after update code

RESULT AFTER UPDATE CODE LATEST

RESULT AFTER UPDATE CODE LATEST

RESULT FROM ANSWER

Qrcode.png

print screen dialog

print screen dialog

1

There are 1 best solutions below

18
user246821 On BEST ANSWER

The WebBrowser control is quite old and may not support some of the newer styling. You may consider using the WebView2 control instead. Also, it appears that you've included style information twice - once as a link to a Style Sheet, and a second time in the HTML.

The following shows how to use JavaScript, CSS, and HTML to create a receipt in VB.NET. It's an implementation of the code referenced in the OP - Print receipt in thermal printer using JavaScript, CSS & HTML. The code below uses NuGet package WebView2 to display the receipt. See the comments throughout the code for more information.

VS 2022:

Create a new Windows Forms App (.NET Framework) project

Open Solution Explorer

  • In VS menu, click View
  • Select Solution Explorer

Download/install NuGet package: Microsoft.Web.WebView2

  • In Solution Explorer, right-click <project name> and select Manage NuGet Packages...
  • Click Browse tab
  • Search for Microsoft.Web.WebView2
  • Click Install

Create Templates folder

  • In Solution Explorer, right-click <project name>
  • Select Add
  • Select New Folder...
  • Rename folder: Templates

Open Properties Window

  • In VS menu, click View
  • Select Properties Window

Add logo image to Templates folder: (name: logo.png)

  • In Solution Explorer, right-click Templates
  • Select Add
  • Select Existing Item...
  • In the drop-down (lower-right) change the filter to Image Files(...) and select your logo image (ex: logo.png)
  • In Solution Explorer, under the Templates folder, select the logo image (ex: logo.png)
  • In the Properties Window, set Build Action: Content and Copy to Output Directory: Copy Always

Add QR code image to Templates folder: (name: qrCode.jpg)

  • In Solution Explorer, right-click Templates
  • Select Add
  • Select Existing Item...
  • In the drop-down (lower-right) change the filter to Image Files(...) and select your logo image (ex: qrCode.jpg)
  • In Solution Explorer, under the Templates folder, select the QR code image (ex: qrCode.jpg)
  • In the Properties Window, set Build Action: Content and Copy to Output Directory: Copy Always

Note: If you'd like to generate a QR code programmatically, see this post.

Add Style Sheet to Templates folder: (name: style.css)

  • In Solution Explorer, right-click Templates
  • Select Add
  • Select New Item...
  • On left side expand Common Items. Then click Web.
  • Select Style Sheet (name: style.css)
  • In the Properties Window, set Build Action: Content and Copy to Output Directory: Copy Always

style.css:

* {
    font-size: 12px;
    font-family: 'Times New Roman';
}

td,
th,
tr,
table {
    border-top: 1px solid black;
    border-collapse: collapse;
}

    td.description,
    th.description {
        width: 75px;
        max-width: 75px;
    }

    td.quantity,
    th.quantity {
        width: 40px;
        max-width: 40px;
        word-break: break-all;
    }

    td.price,
    th.price {
        width: 40px;
        max-width: 40px;
        word-break: break-all;
    }

.centered {
    text-align: center;
    align-content: center;
}

.ticket {
    width: 155px;
    max-width: 155px;
}

img {
    max-width: inherit;
    width: inherit;
}

@media print {
    .hidden-print,
    .hidden-print * {
        display: none !important;
    }
}

Add JavaScript file to Templates folder: (name: printReceipt.js)

  • In Solution Explorer, right-click Templates
  • Select Add
  • Select New Item...
  • On left side expand Common Items. Then click Web.
  • Select JavaScript File (name: printReceipt.js)
  • In the Properties Window, set Build Action: Content and Copy to Output Directory: Copy Always

printReceipt.js:

const $btnPrint = document.querySelector("#btnPrint");
$btnPrint.addEventListener("click", () => {
    window.print();
});

Add receipt.html to Templates folder:

  • In Solution Explorer, right-click Templates
  • Select Add
  • Select New Item...
  • On left side expand Common Items. Then click Web.
  • Select HTML Page (name: receipt.html)
  • In the Properties Window, set Build Action: Content and Copy to Output Directory: Copy Always

Note: In the HTML, I've removed the table data, and replaced it with a placeholder ("rowsPlaceHolder"). In VB.NET, we'll generate the HTML that goes here, and replace "rowsPlaceHolder" with the HTML. The paths for the style sheet and JavaScript file are relative to this HTML file, so either change the paths as necessary, or ensure that the HTML file is in the same folder as the style sheet (.css) and JavaScript file (.js).

receipt.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
    <title>Receipt example</title>
</head>
<body>
    <div class="ticket">
        <img src="./logo.png" alt="Logo">
        <p class="centered">
            RECEIPT EXAMPLE
            <br>Address line 1
            <br>Address line 2
        </p>
        <table>
            <thead>
                <tr>
                    <th class="quantity">Q.</th>
                    <th class="description">Description</th>
                    <th class="price">$$</th>
                </tr>
            </thead>
            <tbody>
                rowsPlaceHolder
            </tbody>
        </table>
        <p class="centered">
            Thanks for your purchase!
            <br />
            <img src="qrCode.jpg" alt="QRCode" />
        </p>
    </div>
    <button id="btnPrint" class="hidden-print">Print</button>
    <script src="printReceipt.js"></script>
</body>
</html>

In Solution Explorer, you should see the following:

enter image description here


Add a Form to the project (name: FrmReceipt.vb)

Note: This form will host the WebView2 browser control which will display the receipt.

  • In Solution Explorer, right-click <project name>
  • Select Add
  • Select New Item...
  • On left side click Common Items.
  • Select Form (Windows Form) (name: FrmReceipt.vb)
  • Double-click the form to add the Load event handler
  • Resize the form as desired

Open the Toolbox

  • In VS menu, select View
  • Select Toolbox

Add WebView2 to FrmReceipt (name: webView21)

  • In Solution Explorer, right-click FrmReceipt.vb and select View Designer.
  • In the Toolbox, scroll to the top and expand WebView2 Windows Forms Control
  • Drag WebView2 control onto FrmReceipt
  • On the form, click the WebView2 control to select it
  • In the Properties Window, set Dock: Fill

FrmReceipt.vb:

Note: In the code below, you'll notice that the async keyword has been added to the Load event handler.

Imports Microsoft.Web.WebView2.WinForms

Public Class FrmReceipt

    Private appTempFolder As String = String.Empty
    Private receiptFilename As String = String.Empty

    Public Sub New(receiptFilename As String)

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.receiptFilename = receiptFilename

        'set value
        appTempFolder = System.IO.Path.GetDirectoryName(receiptFilename)
        Debug.WriteLine($"FrmReceipt appTempFolder: {appTempFolder}")
    End Sub

    Private Async Sub FrmReceipt_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Debug.WriteLine($"WebView2 version: {GetWebView2Version()}")

        'set UserDataFolder
        WebView21.CreationProperties = New CoreWebView2CreationProperties() With {.UserDataFolder = appTempFolder}

        'explicitly initialize CoreWebView2
        Await WebView21.EnsureCoreWebView2Async()

        'display receipt
        WebView21.Source = New Uri($"file:///{receiptFilename}")
    End Sub

    Public Function GetWebView2Version() As String
        Dim webView2Assembly As System.Reflection.Assembly = GetType(WebView2).Assembly
        Return FileVersionInfo.GetVersionInfo(webView2Assembly.Location).ProductVersion
    End Function
End Class

One can use the following to generate the receipt:

Note: The code below will go in the main form (ex: Form1.vb). If desired one can rename Form1.vb to something such as FrmMain.vb.

Private appTempFolder As String = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location))
Private templatesFolder As String = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Templates")
Private addressLine1 As String = "123 Walnut Street"
Private addressLine2 As String = "Some City, ABC 12345"

Private Sub CreateReceipt()
    'for testing, we'll create a folder in the user's temp folder
    If Not System.IO.Directory.Exists(appTempFolder) Then
        System.IO.Directory.CreateDirectory(appTempFolder)
    End If

    'copy the following files so that they exist in the same folder as the .html file
    System.IO.File.Copy(System.IO.Path.Combine(templatesFolder, "logo.png"), System.IO.Path.Combine(appTempFolder, "logo.png"), True)
    System.IO.File.Copy(System.IO.Path.Combine(templatesFolder, "printReceipt.js"), System.IO.Path.Combine(appTempFolder, "printReceipt.js"), True)
    System.IO.File.Copy(System.IO.Path.Combine(templatesFolder, "qrCode.jpg"), System.IO.Path.Combine(appTempFolder, "qrCode.jpg"), True)
    System.IO.File.Copy(System.IO.Path.Combine(templatesFolder, "style.css"), System.IO.Path.Combine(appTempFolder, "style.css"), True)

    'get data
    'here a method is used to generate test data
    'but one could get data from a database instead
    Dim dt As DataTable = CreateTestData()

    'HTML filename
    Dim receiptFilename As String = System.IO.Path.Combine(appTempFolder, "receipt.html")

    'generate HTML and save to file
    GenerateHtml(dt, receiptFilename)

    'display receipt
    Dim receipt As FrmReceipt = New FrmReceipt(receiptFilename)
    receipt.Show()
End Sub

Private Function CreateTestData() As DataTable
    'create new instance
    Dim dt As DataTable = New DataTable("Items")

    'Add column: Qty
    Dim quantity As DataColumn = New DataColumn() With {.ColumnName = "Qty", .DataType = GetType(Double)}
    dt.Columns.Add(quantity)

    'Add column: Description
    Dim description As DataColumn = New DataColumn() With {.ColumnName = "Description", .DataType = GetType(String)}
    dt.Columns.Add(description)

    'Add column: Price
    Dim price As DataColumn = New DataColumn() With {.ColumnName = "Price", .DataType = GetType(Decimal)}
    dt.Columns.Add(price)

    Dim row As DataRow = Nothing

    row = dt.NewRow() 'create new row
    row("Qty") = 1
    row("Description") = "ARDUINO UNO R3"
    row("Price") = 25
    dt.Rows.Add(row) 'add to DataTable

    row = dt.NewRow() 'create new row
    row("Qty") = 2
    row("Description") = "JAVASCRIPT BOOK"
    row("Price") = 10
    dt.Rows.Add(row) 'add to DataTable

    row = dt.NewRow() 'create new row
    row("Qty") = 2
    row("Description") = "JAVASCRIPT BOOK"
    row("Price") = 10
    dt.Rows.Add(row) 'add to DataTable

    row = dt.NewRow() 'create new row
    row("Qty") = 1
    row("Description") = "STICKER PACK"
    row("Price") = 10
    dt.Rows.Add(row) 'add to DataTable

    Return dt
End Function

Private Sub GenerateHtml(dt As DataTable, outputFilename As String)

    'get HTML from template
    Dim html As String = File.ReadAllText(System.IO.Path.Combine(templatesFolder, "receipt.html"))
    Dim itemsHtml As StringBuilder = New StringBuilder()
    Dim total As Decimal = 0

    'create HTML for each item
    For i As Integer = 0 To dt.Rows.Count - 1
        'create HTML for each row
        itemsHtml.AppendFormat($"{Space(16)}<tr>{System.Environment.NewLine}")

        'convert to double
        Dim quantity As Double = 0
        Double.TryParse(dt(i)("Qty").ToString(), quantity)

        'convert to decimal
        Dim price As Decimal = 0
        Decimal.TryParse(dt(i)("Price").ToString(), price)

        'add data to table column
        itemsHtml.AppendFormat($"{Space(20)}<td class = ""quantity"">{quantity.ToString("N2")}</td>{System.Environment.NewLine}")
        itemsHtml.AppendFormat($"{Space(20)}<td class = ""description"">{dt(i)("Description")}</td>{System.Environment.NewLine}")
        itemsHtml.AppendFormat($"{Space(20)}<td class = ""price"">{price.ToString("N2")}</td>{System.Environment.NewLine}")

        itemsHtml.AppendFormat($"{Space(16)}</tr>{System.Environment.NewLine}")

        'add
        total += price
    Next

    'add HTML for Total
    itemsHtml.AppendFormat($"{Space(16)}<tr>{System.Environment.NewLine}")

    itemsHtml.AppendFormat($"{Space(20)}<td class = ""quantity""></td>{System.Environment.NewLine}")
    itemsHtml.AppendFormat($"{Space(20)}<td class = ""description"">TOTAL</td>{System.Environment.NewLine}")
    itemsHtml.AppendFormat($"{Space(20)}<td class = ""price"">${total.ToString("N2")}</td>{System.Environment.NewLine}")

    itemsHtml.AppendFormat($"{Space(16)}</tr>{System.Environment.NewLine}")

    'replace address
    html = html.Replace("Address line 1", addressLine1)
    html = html.Replace("Address line 2", addressLine2)

    'replace place holder with HTML for items
    html = html.Replace("rowsPlaceHolder", itemsHtml.ToString())

    'save
    System.IO.File.WriteAllText(outputFilename, html)
End Sub

Private Function Space(numSpaces As Integer) As String
    Return New String(" ", numSpaces)
End Function

Usage:

CreateReceipt()

Update:

If one needs to adjust the size of an image, one can use MS Paint to resize the image prior to adding it to the Templates folder or one can use the width and height properties of the img tag in the HTML to specify the desired size. When setting these properties in the HTML, the width and height should be less than or equal to the width and height of the image.

<img src="qrCode.jpg" alt="QRCode" width="75" height="75" />