It is possible to get a IHTMLTxtRange from the selection and find table containing that range.
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private WebBrowser webBrowser1;
public Form1()
{
Button btn = new Button();
btn.Text = "Test";
btn.Click += button1_Click;
this.Controls.Add(btn);
var panel = new Panel();
panel.Top = btn.Height + 2;
panel.Height = this.ClientSize.Height - btn.Height + 2;
panel.Width = this.ClientSize.Width;
panel.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
webBrowser1 = new WebBrowser();
webBrowser1.Dock = DockStyle.Fill;
webBrowser1.Url = new Uri("https://www.sec.gov/Archives/edgar/data/1108134/000110813423000018/bhlb-20230630.htm");
panel.Controls.Add(webBrowser1);
this.Controls.Add(panel);
}
private void button1_Click(object sender, EventArgs e)
{
TestSelection();
TestAllTable();
}
private void TestSelection()
{
var domdoc = this.webBrowser1.Document.DomDocument as mshtml.IHTMLDocument2;
var sel = domdoc.selection;
var range = sel.createRange();
var trange = range as mshtml.IHTMLTxtRange;
var table = GetParentTable(trange.parentElement());
if (table == null)
{
var startPointRange = trange.duplicate();
startPointRange.setEndPoint("EndToStart", trange);
var startPointTable = GetParentTable(startPointRange.parentElement());
var endPointRange = trange.duplicate();
startPointRange.setEndPoint("StartToEnd", trange);
var endPointTable = GetParentTable(endPointRange.parentElement());
if (startPointTable != null)
{
table = startPointTable;
}
else if (endPointTable != null)
{
table = endPointTable;
}
else
{
MessageBox.Show("Selection is not in Table");
return;
}
}
var tableData = TableData.GetTableData(table);
System.Diagnostics.Debug.WriteLine(tableData.ToString());
}
private mshtml.IHTMLTable GetParentTable(mshtml.IHTMLElement element)
{
var parent = element;
while (parent != null)
{
if (parent is mshtml.IHTMLTable table)
{
return table;
}
parent = parent.parentElement;
}
return null;
}
private void TestAllTable()
{
var domdoc = this.webBrowser1.Document.DomDocument as mshtml.HTMLDocument;
foreach (var table in domdoc.getElementsByTagName("table").OfType<mshtml.IHTMLTable>())
{
var tableData = TableData.GetTableData(table);
System.Diagnostics.Debug.WriteLine(tableData.ToString());
System.Diagnostics.Debug.WriteLine(new string('=', 20));
}
}
}
class TableData
{
public static TableData GetTableData(mshtml.IHTMLTable table)
{
TableData tableData = new TableData();
foreach (var tableRow in table.rows.OfType<mshtml.IHTMLTableRow>())
{
RowData rowdata = new RowData();
foreach (var tablecell in tableRow.cells.OfType<mshtml.HTMLTableCell>())
{
CellData cell = new CellData();
cell.Text = tablecell.innerText;
cell.RowSpan = tablecell.rowSpan;
cell.ColSpan = tablecell.colSpan;
rowdata.Add(cell);
}
tableData.Rows.Add(rowdata);
}
return tableData;
}
public List<RowData> Rows { get; } = new List<RowData>();
public override string ToString()
{
System.Text.StringBuilder sb = new StringBuilder();
foreach (var row in this.Rows)
{
sb.AppendLine(row.ToString());
}
return sb.ToString();
}
}
class RowData : List<CellData>
{
public override string ToString()
{
return string.Join("\t", this.Select(cell => cell.Text + new string('\t', cell.ColSpan)));
}
}
class CellData
{
public string Text { get; set; }
public int ColSpan { get; set; }
public int RowSpan { get; set; }
public override string ToString() => Text;
}
}
edit: Modify to find table at start point or end point table even if outside the table range is selected.