トップ回答者
QueryTables.Add()再質問

質問
回答
-
HTMLを解析して変換する必要があります。
webページはいろいろあるので、取り込みたいwebpageに合わせて自分で取り込みたい形になるように抽出する処理を書いてください。
'Imports System.Linq Public Class Form1 '参照の追加でCOMのMicrosoft HTML Object Libraryを追加する Sub New() ' この呼び出しはデザイナーで必要です。 InitializeComponent() Me.Controls.Clear() InitializeComponent_() Me.WebBrowser1.ScriptErrorsSuppressed = True Me.TextBox1.Text = "http://moneycentral.msn.com/investor/external/excel/quotes.asp?quote=MSFT" Me.WebBrowser1.Navigate(Me.TextBox1.Text) End Sub Private Sub WebBrowser1_Navigating(sender As Object, e As System.Windows.Forms.WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating btnFindHtmlTables.Enabled = False Me.ListBox1.Items.Clear() Me.DataGridView1.DataSource = Nothing End Sub Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted btnFindHtmlTables.Enabled = True End Sub Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged Me.btnGetDataTable.Enabled = Me.ListBox1.SelectedIndex >= 0 End Sub Private Sub btnNavigate_Click(sender As System.Object, e As System.EventArgs) Handles btnNavigate.Click Me.WebBrowser1.Navigate(Me.TextBox1.Text) End Sub Private Sub btnFindHtmlTables_Click(sender As System.Object, e As System.EventArgs) Handles btnFindHtmlTables.Click Me.ListBox1.Items.Clear() If (Me.WebBrowser1.StatusText = "") Then End If For Each table As mshtml.HTMLTable In FindWebpageTables(Me.WebBrowser1) If (table.caption IsNot Nothing) Then Me.ListBox1.Items.Add(table.caption) ElseIf Not String.IsNullOrWhiteSpace(table.id) Then Me.ListBox1.Items.Add(table.id) Else Me.ListBox1.Items.Add("Table" + (Me.ListBox1.Items.Count + 1).ToString()) End If Next Me.btnGetDataTable.Enabled = ListBox1.Items.Count > 0 End Sub Private Sub btnGetDataTable_Click(sender As System.Object, e As System.EventArgs) Handles btnGetDataTable.Click If (Me.ListBox1.SelectedIndex >= 0) Then Me.DataGridView1.DataSource = GetWebpageToTable(Me.WebBrowser1, Me.ListBox1.SelectedIndex) End If End Sub ''' <summary> ''' ウェブブラウザに表示されている内容からHTMLのテーブルを探します ''' </summary> Private Function FindWebpageTables(ByVal wb As WebBrowser) As List(Of mshtml.HTMLTable) Dim list As New List(Of mshtml.HTMLTable) Dim tables = wb.Document.GetElementsByTagName("table") For Each elem As HtmlElement In tables Dim t As mshtml.HTMLTable = TryCast(elem.DomElement, mshtml.HTMLTable) If (t IsNot Nothing) Then list.Add(t) End If Next Return list End Function ''' <summary> ''' ウェブブラウザに表示されている内容のテーブルからDataTableに変換します ''' </summary> Private Function GetWebpageToTable(ByVal wb As WebBrowser, ByVal index As Integer) As DataTable Dim tables = FindWebpageTables(wb) Dim table = tables(index) 'テーブルの列数を調べます Dim columnCount As Integer = table.cols 'colsがうまく取れない? For Each row As mshtml.HTMLTableRow In table.rows columnCount = Math.Max(columnCount, row.cells.Cast(Of mshtml.HTMLTableCell).Count()) Next '取り込むDataTableを作ります Dim dt As New DataTable For num As Integer = 1 To columnCount Dim clm As DataColumn clm = New DataColumn("Column" + num.ToString(), GetType(String), String.Empty) dt.Columns.Add(clm) Next 'HTMLのテーブルの各行をループで回してDataRowに文字を入れていきます For Each row As mshtml.HTMLTableRow In table.rows Dim dr As DataRow = dt.NewRow For Each cell As mshtml.HTMLTableCell In row.cells dr.Item(cell.cellIndex) = cell.innerText Next dt.Rows.Add(dr) Next Return dt End Function Private Sub InitializeComponent_() Me.Panel1 = New System.Windows.Forms.Panel() Me.TextBox1 = New System.Windows.Forms.TextBox() Me.btnNavigate = New System.Windows.Forms.Button() Me.btnFindHtmlTables = New System.Windows.Forms.Button() Me.btnGetDataTable = New System.Windows.Forms.Button() Me.SplitContainer1 = New System.Windows.Forms.SplitContainer() Me.SplitContainer2 = New System.Windows.Forms.SplitContainer() Me.ListBox1 = New System.Windows.Forms.ListBox() Me.DataGridView1 = New System.Windows.Forms.DataGridView() Me.WebBrowser1 = New System.Windows.Forms.WebBrowser() Me.Panel1.AutoSize = True Me.Panel1.Controls.Add(Me.TextBox1) Me.Panel1.Controls.Add(Me.btnNavigate) Me.Panel1.Controls.Add(Me.btnFindHtmlTables) Me.Panel1.Controls.Add(Me.btnGetDataTable) Me.Panel1.Dock = System.Windows.Forms.DockStyle.Top Me.Panel1.Font = New System.Drawing.Font("MS UI Gothic", 14.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(128, Byte)) Me.Panel1.Location = New System.Drawing.Point(0, 0) Me.Panel1.Name = "Panel1" Me.Panel1.Size = New System.Drawing.Size(678, 26) Me.Panel1.TabIndex = 0 Me.TextBox1.Dock = System.Windows.Forms.DockStyle.Top Me.TextBox1.Location = New System.Drawing.Point(0, 0) Me.TextBox1.Name = "TextBox1" Me.btnNavigate.AutoSize = True Me.btnNavigate.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink Me.btnNavigate.Dock = System.Windows.Forms.DockStyle.Right Me.btnNavigate.Name = "btnNavigate" Me.btnNavigate.Text = "移動" Me.btnFindHtmlTables.AutoSize = True Me.btnFindHtmlTables.Dock = System.Windows.Forms.DockStyle.Right Me.btnFindHtmlTables.Size = New System.Drawing.Size(118, 26) Me.btnFindHtmlTables.Text = "テーブル認識" Me.btnGetDataTable.AutoSize = True Me.btnGetDataTable.Dock = System.Windows.Forms.DockStyle.Right Me.btnGetDataTable.Text = "取り込み" Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill Me.SplitContainer1.Panel1.Controls.Add(Me.SplitContainer2) Me.SplitContainer1.Panel2.Controls.Add(Me.WebBrowser1) Me.SplitContainer1.SplitterDistance = 200 Me.SplitContainer2.Dock = System.Windows.Forms.DockStyle.Fill Me.SplitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal Me.SplitContainer2.Panel1.Controls.Add(Me.ListBox1) Me.SplitContainer2.Panel2.Controls.Add(Me.DataGridView1) Me.SplitContainer2.Size = New System.Drawing.Size(300, 376) Me.SplitContainer2.SplitterDistance = 98 Me.SplitContainer2.TabIndex = 1 Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Fill Me.ListBox1.FormattingEnabled = True Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize Me.DataGridView1.Dock = System.Windows.Forms.DockStyle.Fill Me.WebBrowser1.Dock = System.Windows.Forms.DockStyle.Fill Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(678, 402) Me.Controls.Add(Me.SplitContainer1) Me.Controls.Add(Me.Panel1) Me.Name = "Form1" Me.Text = "Form1" Me.btnFindHtmlTables.Enabled = False Me.btnGetDataTable.Enabled = False Me.DataGridView1.DataSource = Nothing Me.SplitContainer2.SplitterDistance = 50 Me.SplitContainer1.SplitterDistance = 200 End Sub Friend WithEvents Panel1 As System.Windows.Forms.Panel Friend WithEvents TextBox1 As System.Windows.Forms.TextBox Friend WithEvents btnNavigate As System.Windows.Forms.Button Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer Friend WithEvents WebBrowser1 As System.Windows.Forms.WebBrowser Friend WithEvents DataGridView1 As System.Windows.Forms.DataGridView Friend WithEvents btnGetDataTable As System.Windows.Forms.Button Friend WithEvents btnFindHtmlTables As System.Windows.Forms.Button Friend WithEvents SplitContainer2 As System.Windows.Forms.SplitContainer Friend WithEvents ListBox1 As System.Windows.Forms.ListBox End Class
#前の質問は間違ってC#に投稿されているので、レスがつく前に消しておいた方がいいです
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2016年12月10日 1:28
- 回答の候補に設定 栗下 望Microsoft employee, Moderator 2016年12月12日 1:18
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月20日 4:37
-
Oldman-beg さま よろしく。
私も以前に同じ事を考え、VB で書きました。
汎用的なものを書くのは至難だと思います。
特定の決まったサイトの表が更新され、それをデータとして取得するだけなら、以下に経験を纏めてアップしてあります。
VB HTML の表をデータベースに取り込む
http://shiroyuki-mot-says.blogspot.com/2015/02/vb-table-html2db.html
HTML での注意点は、デザイン目的にテーブルが利用されるケースが多々ある事です。
言い換えれば、表で無いのにテーブル定義が含まれている事があります。
それから Script の実行を停止させる必要があるかも知れません。
対象となる html をお手元にコピーして、良く眺めて見る事が大事です。
尚、
gekka さまがすっきりとしたコードをお示しになっているので、そちらを参考にして下さい。- 回答の候補に設定 栗下 望Microsoft employee, Moderator 2016年12月19日 4:14
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月20日 4:37
-
標準の機能ではないことをするには外部のライブラリを使用することになります。
今回は、コードの頭に書いてあるようにMicrosoft HTML Object Libraryというライブラリを使用しています。
#できないこともないですが、ちょっと手間が増えるのでこのライブラリを追加するにはVS2010のメニューのプロジェクト->参照の追加、もしくはソリューションエクスプローラーのプロジェクトを右クリックして参照の追加を選びます。
参照の追加というダイアログが表示されますので、COMタブを選び、一覧からMicrosoft HTML Object Libraryを選択してOKしてください。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2016年12月10日 5:40
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月20日 4:37
すべての返信
-
HTMLを解析して変換する必要があります。
webページはいろいろあるので、取り込みたいwebpageに合わせて自分で取り込みたい形になるように抽出する処理を書いてください。
'Imports System.Linq Public Class Form1 '参照の追加でCOMのMicrosoft HTML Object Libraryを追加する Sub New() ' この呼び出しはデザイナーで必要です。 InitializeComponent() Me.Controls.Clear() InitializeComponent_() Me.WebBrowser1.ScriptErrorsSuppressed = True Me.TextBox1.Text = "http://moneycentral.msn.com/investor/external/excel/quotes.asp?quote=MSFT" Me.WebBrowser1.Navigate(Me.TextBox1.Text) End Sub Private Sub WebBrowser1_Navigating(sender As Object, e As System.Windows.Forms.WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating btnFindHtmlTables.Enabled = False Me.ListBox1.Items.Clear() Me.DataGridView1.DataSource = Nothing End Sub Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted btnFindHtmlTables.Enabled = True End Sub Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged Me.btnGetDataTable.Enabled = Me.ListBox1.SelectedIndex >= 0 End Sub Private Sub btnNavigate_Click(sender As System.Object, e As System.EventArgs) Handles btnNavigate.Click Me.WebBrowser1.Navigate(Me.TextBox1.Text) End Sub Private Sub btnFindHtmlTables_Click(sender As System.Object, e As System.EventArgs) Handles btnFindHtmlTables.Click Me.ListBox1.Items.Clear() If (Me.WebBrowser1.StatusText = "") Then End If For Each table As mshtml.HTMLTable In FindWebpageTables(Me.WebBrowser1) If (table.caption IsNot Nothing) Then Me.ListBox1.Items.Add(table.caption) ElseIf Not String.IsNullOrWhiteSpace(table.id) Then Me.ListBox1.Items.Add(table.id) Else Me.ListBox1.Items.Add("Table" + (Me.ListBox1.Items.Count + 1).ToString()) End If Next Me.btnGetDataTable.Enabled = ListBox1.Items.Count > 0 End Sub Private Sub btnGetDataTable_Click(sender As System.Object, e As System.EventArgs) Handles btnGetDataTable.Click If (Me.ListBox1.SelectedIndex >= 0) Then Me.DataGridView1.DataSource = GetWebpageToTable(Me.WebBrowser1, Me.ListBox1.SelectedIndex) End If End Sub ''' <summary> ''' ウェブブラウザに表示されている内容からHTMLのテーブルを探します ''' </summary> Private Function FindWebpageTables(ByVal wb As WebBrowser) As List(Of mshtml.HTMLTable) Dim list As New List(Of mshtml.HTMLTable) Dim tables = wb.Document.GetElementsByTagName("table") For Each elem As HtmlElement In tables Dim t As mshtml.HTMLTable = TryCast(elem.DomElement, mshtml.HTMLTable) If (t IsNot Nothing) Then list.Add(t) End If Next Return list End Function ''' <summary> ''' ウェブブラウザに表示されている内容のテーブルからDataTableに変換します ''' </summary> Private Function GetWebpageToTable(ByVal wb As WebBrowser, ByVal index As Integer) As DataTable Dim tables = FindWebpageTables(wb) Dim table = tables(index) 'テーブルの列数を調べます Dim columnCount As Integer = table.cols 'colsがうまく取れない? For Each row As mshtml.HTMLTableRow In table.rows columnCount = Math.Max(columnCount, row.cells.Cast(Of mshtml.HTMLTableCell).Count()) Next '取り込むDataTableを作ります Dim dt As New DataTable For num As Integer = 1 To columnCount Dim clm As DataColumn clm = New DataColumn("Column" + num.ToString(), GetType(String), String.Empty) dt.Columns.Add(clm) Next 'HTMLのテーブルの各行をループで回してDataRowに文字を入れていきます For Each row As mshtml.HTMLTableRow In table.rows Dim dr As DataRow = dt.NewRow For Each cell As mshtml.HTMLTableCell In row.cells dr.Item(cell.cellIndex) = cell.innerText Next dt.Rows.Add(dr) Next Return dt End Function Private Sub InitializeComponent_() Me.Panel1 = New System.Windows.Forms.Panel() Me.TextBox1 = New System.Windows.Forms.TextBox() Me.btnNavigate = New System.Windows.Forms.Button() Me.btnFindHtmlTables = New System.Windows.Forms.Button() Me.btnGetDataTable = New System.Windows.Forms.Button() Me.SplitContainer1 = New System.Windows.Forms.SplitContainer() Me.SplitContainer2 = New System.Windows.Forms.SplitContainer() Me.ListBox1 = New System.Windows.Forms.ListBox() Me.DataGridView1 = New System.Windows.Forms.DataGridView() Me.WebBrowser1 = New System.Windows.Forms.WebBrowser() Me.Panel1.AutoSize = True Me.Panel1.Controls.Add(Me.TextBox1) Me.Panel1.Controls.Add(Me.btnNavigate) Me.Panel1.Controls.Add(Me.btnFindHtmlTables) Me.Panel1.Controls.Add(Me.btnGetDataTable) Me.Panel1.Dock = System.Windows.Forms.DockStyle.Top Me.Panel1.Font = New System.Drawing.Font("MS UI Gothic", 14.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(128, Byte)) Me.Panel1.Location = New System.Drawing.Point(0, 0) Me.Panel1.Name = "Panel1" Me.Panel1.Size = New System.Drawing.Size(678, 26) Me.Panel1.TabIndex = 0 Me.TextBox1.Dock = System.Windows.Forms.DockStyle.Top Me.TextBox1.Location = New System.Drawing.Point(0, 0) Me.TextBox1.Name = "TextBox1" Me.btnNavigate.AutoSize = True Me.btnNavigate.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink Me.btnNavigate.Dock = System.Windows.Forms.DockStyle.Right Me.btnNavigate.Name = "btnNavigate" Me.btnNavigate.Text = "移動" Me.btnFindHtmlTables.AutoSize = True Me.btnFindHtmlTables.Dock = System.Windows.Forms.DockStyle.Right Me.btnFindHtmlTables.Size = New System.Drawing.Size(118, 26) Me.btnFindHtmlTables.Text = "テーブル認識" Me.btnGetDataTable.AutoSize = True Me.btnGetDataTable.Dock = System.Windows.Forms.DockStyle.Right Me.btnGetDataTable.Text = "取り込み" Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill Me.SplitContainer1.Panel1.Controls.Add(Me.SplitContainer2) Me.SplitContainer1.Panel2.Controls.Add(Me.WebBrowser1) Me.SplitContainer1.SplitterDistance = 200 Me.SplitContainer2.Dock = System.Windows.Forms.DockStyle.Fill Me.SplitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal Me.SplitContainer2.Panel1.Controls.Add(Me.ListBox1) Me.SplitContainer2.Panel2.Controls.Add(Me.DataGridView1) Me.SplitContainer2.Size = New System.Drawing.Size(300, 376) Me.SplitContainer2.SplitterDistance = 98 Me.SplitContainer2.TabIndex = 1 Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Fill Me.ListBox1.FormattingEnabled = True Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize Me.DataGridView1.Dock = System.Windows.Forms.DockStyle.Fill Me.WebBrowser1.Dock = System.Windows.Forms.DockStyle.Fill Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.ClientSize = New System.Drawing.Size(678, 402) Me.Controls.Add(Me.SplitContainer1) Me.Controls.Add(Me.Panel1) Me.Name = "Form1" Me.Text = "Form1" Me.btnFindHtmlTables.Enabled = False Me.btnGetDataTable.Enabled = False Me.DataGridView1.DataSource = Nothing Me.SplitContainer2.SplitterDistance = 50 Me.SplitContainer1.SplitterDistance = 200 End Sub Friend WithEvents Panel1 As System.Windows.Forms.Panel Friend WithEvents TextBox1 As System.Windows.Forms.TextBox Friend WithEvents btnNavigate As System.Windows.Forms.Button Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer Friend WithEvents WebBrowser1 As System.Windows.Forms.WebBrowser Friend WithEvents DataGridView1 As System.Windows.Forms.DataGridView Friend WithEvents btnGetDataTable As System.Windows.Forms.Button Friend WithEvents btnFindHtmlTables As System.Windows.Forms.Button Friend WithEvents SplitContainer2 As System.Windows.Forms.SplitContainer Friend WithEvents ListBox1 As System.Windows.Forms.ListBox End Class
#前の質問は間違ってC#に投稿されているので、レスがつく前に消しておいた方がいいです
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2016年12月10日 1:28
- 回答の候補に設定 栗下 望Microsoft employee, Moderator 2016年12月12日 1:18
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月20日 4:37
-
Oldman-beg さま よろしく。
私も以前に同じ事を考え、VB で書きました。
汎用的なものを書くのは至難だと思います。
特定の決まったサイトの表が更新され、それをデータとして取得するだけなら、以下に経験を纏めてアップしてあります。
VB HTML の表をデータベースに取り込む
http://shiroyuki-mot-says.blogspot.com/2015/02/vb-table-html2db.html
HTML での注意点は、デザイン目的にテーブルが利用されるケースが多々ある事です。
言い換えれば、表で無いのにテーブル定義が含まれている事があります。
それから Script の実行を停止させる必要があるかも知れません。
対象となる html をお手元にコピーして、良く眺めて見る事が大事です。
尚、
gekka さまがすっきりとしたコードをお示しになっているので、そちらを参考にして下さい。- 回答の候補に設定 栗下 望Microsoft employee, Moderator 2016年12月19日 4:14
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月20日 4:37
-
標準の機能ではないことをするには外部のライブラリを使用することになります。
今回は、コードの頭に書いてあるようにMicrosoft HTML Object Libraryというライブラリを使用しています。
#できないこともないですが、ちょっと手間が増えるのでこのライブラリを追加するにはVS2010のメニューのプロジェクト->参照の追加、もしくはソリューションエクスプローラーのプロジェクトを右クリックして参照の追加を選びます。
参照の追加というダイアログが表示されますので、COMタブを選び、一覧からMicrosoft HTML Object Libraryを選択してOKしてください。
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 編集済み gekkaMVP 2016年12月10日 5:40
- 回答としてマーク 栗下 望Microsoft employee, Moderator 2016年12月20日 4:37