The code for this program is long so I won't include it all here, but the ideas are straightforward enough.
The program builds a string holding the HTML text needed to represent the table.
It starts by determining whether the ListView has groups. It does that by looping through the ListView's items checking each one to see if its Group property is null. (For information about using ListView groups, see Use groups in a ListView control in Visual Basic .NET.)
If the control includes non-grouped items, then the code builds HTML code to display the ListView's column headers, and then loops through the items again displaying those that are not in groups. This mimics the way the ListView displays its non-grouped items.
Next the program loops through the groups in the ListView's Groups collection. For each group, the code makes a header row that displays the group's name spanning all of the columns. It then loops through the group's Items property displaying each of the items.
The code uses two functions to make pieces of this process easier: ListViewColumnHeaderHtml and ListViewItemHtml.
The ListViewColumnHeaderHtml function returns HTML code to display column headers. It loops through the ListView control's Columns collection to generate the column headers.
The ListViewItemHtml function loops through an item's SubItems collection to display the item's values. Conveniently the SubItems collection includes the item itself in its 0th entry so the program doesn't need to consider the main item separately.
When it displays any item, the code checks the column's alignment so the item is properly aligned in the HTML table.
Finally, when the HTML table is complete, the program uses the following code to display it in a WebBrowser control.
wbrTable.DocumentText = ListViewToHtmlTable(lvwResults, 1, 1, 2)
See the code for details.