
Public Function HtmlR(URL As String) As HTMLDocument
Dim buf As Object, objHTML As Object
Dim http As XMLHTTP60
Set http = CreateObject("MSXML2.XMLHTTP")
Set buf = New HTMLDocument
http.Open "GET", URL, False
http.send
Do While http.readyState <> 4
DoEvents
Loop
buf.write http.responseText
If InStr(Split(Split(http.responseText, "charset=")(1), ">")(0), "8") = 0 Then
Set buf = Nothing
With CreateObject("ADODB.Stream")
.Charset = "_autodetect"
.Type = 1
.Open
.write http.responseBody
.Position = 0
.Type = 2
buf.write .ReadText
.Close
End With
End If
Set objHTML = buf
Set HtmlR = objHTML
Set buf = Nothing
Set http = Nothing
Set objHTML = Nothing
End Function
Sub 計算用データ入手()
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim sy As String
Dim sm As String
Dim sd As String
Dim ey As String
Dim em As String
Dim ed As String
Dim code As String
Dim page As Long
Dim URL As String
Dim Pc As Integer
Dim Tobj As HTMLTable
Dim URLL As String
Dim Htdoc1 As New HTMLDocument
Dim text As TextStream
Dim fso As New FileSystemObject
sy = 2000
sm = 1
sd = 1
ey = 2016
em = 12
ed = 29
Workbooks.Add
Set text = fso.OpenTextFile("C:\Users\SK\Desktop\計算用データ入手東証二部.txt")
Do Until text.AtEndOfLine
code = text.ReadLine
Workbooks.Add
URLL = "http://stocks.finance.yahoo.co.jp/stocks/chart/? … & code & ".T&ct=z&t=1y&q=c&l=off&z=m&p=m65,m130,s&a=v"
Set Htdoc1 = HtmlR(URLL)
range("A1") = Split(Htdoc1.Title, ":")(0)
range("A2").Select
For page = 1 To 1000
URL = "http://info.finance.yahoo.co.jp/history/?code=" & code & ".T&sy=" & sy & "&sm=" & sm & "&sd=" & sd & "&ey=" & ey & "&em=" & em & "&ed=" & ed & "&tm=d&p=" & page
Dim Htdoc As New HTMLDocument
Set Htdoc = HtmlR(URL)
If Htdoc.getElementsByTagName("table")(1).Rows.Length = 1 Then Exit For
With New MSForms.DataObject
.SetText Htdoc.getElementsByTagName("table")(1).outerHTML
.PutInClipboard
End With
ActiveSheet.PasteSpecial Format:="Unicode テキスト", link:=False, DisplayAsIcon:=False, NoHTMLFormatting:=True
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
Next page
Dim fn As String
fn = range("A1")
ActiveSheet.Name = fn
range("A1").Select
ActiveWorkbook.SaveAs filename:="C:\Users\SK\Documents\マクロ用データ入れ\東証二部(20000101-20161229)\" & fn & ".xlsx" _
, FileFormat:=xlOpenXMLWorkbook, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
ActiveWorkbook.Close
Loop
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
上記のプログラムを作成しました。
計算用データ入手.txtには証券コード(4桁の数字)が並んでおり、その数字ごとに結果が保存されるようにしています。
一応上記のプログラムで動くのですが、200個ほど並んでいるコードのうち、5個ほどが終わった時点で、進まなくなってしまいます。
excel上でエラー表示がされることはなく、動いていなさそうだなと思って、エスケープを押してキャンセルしようとすると、フリーズしてしまいます。
5個の計算が終わった時点でフリーズして、また一から計算を動かすという面倒なことになっているので、改善案をご教示いただければと思います。
Application 移動用計算用データはデータのセルを移動しているだけなので、無視していただいて構いません。
また、PC本体の動作・ネットワーク環境には問題ないと思われます。
よろしくお願いいたします。
No.3ベストアンサー
- 回答日時:
エラーそのものよりも、#1のコードは、フルコードではありません。
お分かりにはなっているとは思いますが、リストはインポートするのではなく、すでにシートに書かれています。Set RngData = ThisWorkbook.Worksheets("Sheet4").Range("A1:A20") '20ファイルで試しました
Sheet4
A列
9399
6944
8886
2163
3842
.
.
になっています。
Win32APIは、特に重要ではありませんから、それは無視しても構わないと思います。比較的負荷の多いコードですから、どこかに余裕を置くために、Sleep を入れたほうが無難だというだけの話です。VBAの内部の関数よりも、外部関数などを使ったほうが負担が少ないからです。
こちらは、Excel 2013, Windows10 で作っています。Excel 2007 以降なら大丈夫だとは思いますが、それ以外のものは、今のところ想定外です。
また参照設定は、
Private objHTTP As WinHttp.WinHttpRequest 'Microsoft WinHTTP Service, version 5.1
Private oHtml As HTMLDocument ''Microsoft HTML Object Library
(実際は、これに正規表現のVBScript をCreateObjectで呼び出ししています)
--------
結果
Microsoft HTML Object Library
Microsoft WinHTTP Services, version 5.1
>NextFile:
>の部分でエラーが出てしまうのですが、どのように対処すればよいのでしょうか。
以下のように直してみてください。ただ、どのようなエラーが出ているかにもよります。
ループ上でエラーが発生すると、イミディエイトウィンドウの中にファイル名が残ります。
'//
NextFile:
End If
Next code
MsgBox "終了しましたが、一度ファイルを確認してみてください。", vbInformation
Exit Sub
ErrHandler:
Debug.Print Application.StatusBar
Application.StatusBar = False
Resume NextFile
End Sub
もちろん、エラー処理の仕方を変える方法もありますが、致命的な欠陥が発生しない限りは、当面は考えておりません。ただ、元の会社の番号からのエラーが出ない限りは、そのような場所ではエラーはでないはずです。
いずれにしても、私自身が、ご質問者さんのコードを読みきれないというか、どうしても、クリアできない所があると同じように、いくら、こちらのコードをベタで試したところで、細かな設定が食い違う場合があろうかと思います。
そこで、サンプルファイルを用意しましたので、それを使ってみてください。リストはご自分用に書き換えてください。公開期間は、3日(1/14 23:00+3days)の猶予しかありませんので、もし、ダウンロードしそこねましたら、また掲示板に書いてください。今回は、自己解凍ファイルですが、プロパティでブロック解除は必要になりますから、ご注意ください。
パスワードは、このログの9から始まる7桁の数字です。
もし、自己解凍がお嫌いでしたら、圧縮解凍ユーティリティで開けるはずです。
ファイルはZIP圧縮です。
http://bit.ly/2jPXSNF
作っていただいたプログラムの使い方が分からず断念しました。
でも、VBSとVBAを組み合わせたら少し時間がかかりますが、問題なく動きそうです。
VBSで番号を指定したら、その番号のデータをexcelに取り込んで、excelの動作を一回きって、
もう一度VBSで番号を指定して
みたいな感じです。
yahoo financeに連続アクセスすることがアクセス制限につながるらしくて、一回excelの動作を完全に切ることで、アクセス制限を避けることができたのかな?という感じです。力技ですが(笑)
アドバイス大変勉強になりました。
またご教示お願いいたします。
No.5
- 回答日時:
試しに実行してみましたが、データベースやらXMLやらを参照設定しなければならず、
時間がないので断念しました。
株価を検索させて、結果をエクセルに出すとは高度な事をされていますね。
ここはメイン(最初の起動)サブルーチン『計算用データ入手』ですか。
ここを表示させてファンクションキー8番を押してステップ実行させてみてはいかがでしょう。
http.Open "GET", URL で5回目にフリーズと言う事は、
たとえ Nothingをセットしていても、オープンのしすぎでメモリ不足になっているのかもしれません。
メモリ容量の減り方を見つつ、OpenしたものはCloseを考えてメモリを開放するとか、
どのステップに問題があるか、調べるとよいかもしれませんね。
色々と原因を探す価値はあると思います。
健闘を祈ります。
No.4
- 回答日時:
#3の内容の変更をお知らせします。
圧縮自動解凍ファイルの'exe' ファイルは、セキュリティの警告が出過ぎましたので、こちらに変更しました。(1/15 20:45 + 72 hour)
http://bit.ly/2iWdsDu
パスワードは前回と同じです。
ダウンロード後は、プロパティからブロック解除をしてください。
No.2
- 回答日時:
結局、他人のコードを直すよりも、私自身で新たなコードを書いたほうが早いです。
トライしたのは、20ファイルのみですが、100や200は、特に問題なさそうに思います。フリーズの原因は、どうやら、UserFormのDataObject です。これは、使えないようです。その場合は、Tableではなく、他の方法を取るのですが、今回は、Tableのままにしました。切り分けには、Basp21というツールの正規表現を使うと便利なのですが、それはやめました。TableをClipBoardから、シートに貼り付けるのは、便利なのですが、ClipBoard は、やはり、Win32APIで行ったほうがうまくいくのではないかと思います。ただし、開け閉めが面倒です。今回のデータの切り分けは、臨時の処置です。
ご質問者さんのコードは、全体的にみて、そのまま、ネットにアクセスするには、それぞれのコードの負荷が強すぎるように思うのです。理屈では可能でも、ExcelのVBAの実行メモリというのは、想像以上に小さいので無理があるようです。また、タイトルだけ取って、もう一度アクセスするというのも、無駄があるように思いました。
もう一つの問題点は、
>Set text = fso.OpenTextFile("C:\Users\SK\Desktop\計算用データ入手東証二部.txt")
>Do Until text.AtEndOfLine
>code = text.ReadLine
こういう所ですね。これを、Excelのブックのシートに置くことを考えました。
本来は、シートに一覧で出してしまい、その後を呼び出しをするとか、したほうが負荷が少ないと思います。
なお、私のコードでは、画面の左下のステータスバー部分に処理中のファイル名が出るようになっています。
最後に、今回のコードは出来る限り、参照設定をして負荷を減らそうと考えました。私の思惑の中だけで進めたコードからですから、まだ、修正が必要かもしれません。
No.1
- 回答日時:
解説は、次の書き込みでします。
'//
Private objHTTP As WinHttp.WinHttpRequest 'Microsoft WinHTTP Service, version 5.1
Private oHtml As HTMLDocument ''Microsoft HTML Object Library
Private sh1 As Worksheet
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
Sub Main()
Dim URL As String
Dim code As Variant
Dim RngData As Range
Dim c As Variant
Dim sy, sm, sd, ey, em, ed, page
On Error GoTo ErrHandler
Set sh1 = ThisWorkbook.Worksheets("Sheet1")
'コードデータ** (テキストインポートをやめて、データをシートに置いた)
Set RngData = ThisWorkbook.Worksheets("Sheet4").Range("A1:A20") '20ファイルで試しました
For Each c In RngData
If Application.CountIf(RngData, c) > 1 Then
MsgBox c.Value & " :のコードが重複しています", vbExclamation
Exit Sub
End If
Next
sy = 2000: sm = 1: sd = 1: ey = 2016: em = 12: ed = 29: page = ""
For Each code In RngData.Cells
Application.ScreenUpdating = False
sh1.Range("A1").CurrentRegion.ClearContents
If IsNumeric(code) Then
URL = "http://info.finance.yahoo.co.jp/history/?code=" _
& code & ".T&sy=" & sy & "&sm=" & sm & "&sd=" & sd & "&ey=" & ey & "&em=" & em & "&ed=" & ed & "&tm=d&p=" & page
Call AccessDOM(URL)
DoEvents
Sleep 500
Application.ScreenUpdating = True
NextFile:
End If
Next code
MsgBox "終了しましたが、一度ファイルを確認してみてください。", vbInformation
Exit Sub
ErrHandler:
Debug.Print Application.StatusBar
Application.StatusBar = False
GoTo NextFile
End Sub
Sub AccessDOM(strURL As String)
Dim httpLog As String
Dim ar As Variant
Dim n As Variant
Set objHTTP = New WinHttp.WinHttpRequest '("WinHttp.WinHttpRequest.5.1")
objHTTP.Open "GET", strURL, False
objHTTP.send
If objHTTP.Status = 200 Then
httpLog = objHTTP.responseText
Call RelateLog(httpLog)
Else
MsgBox "アクセスに失敗しました。"
End If
End Sub
Sub RelateLog(httpLog As Variant)
Dim buftxt As String
Dim tb1 As Object
Dim wb As Workbook
Dim fn As String
Dim rng As Range
Dim objData As DataObject
Set oHtml = New HTMLDocument
oHtml.body.innerHTML = httpLog
With oHtml
Dim oSymb
Set oSymb = .getElementsByClassName("symbol")
If oSymb.Length > 0 Then
sh1.Range("A1").Value = oSymb(0).innerText
Application.StatusBar = oSymb(0).innerText
End If
Set tb1 = .getElementsByTagName("table")
If tb1.Length > 0 Then
buftxt = tb1(1).outerHTML
Call SplitData(buftxt)
Else
GoTo EndLine
End If
' ここで、DataObjectを使う予定でした。
fn = sh1.Range("A1").Value
Set rng = sh1.Range("A1").CurrentRegion
End With
Workbooks.Add
rng.Copy ActiveSheet.Range("A1")
ActiveSheet.Range("A1").CurrentRegion.Columns.AutoFit
Call SaveFiles(fn)
End With
EndLine:
Application.StatusBar = False
End Sub
Sub SaveFiles(fn As String)
Dim n As Variant
Const myPATH As String = "C:\Users\SK\Documents\マクロ用データ入れ\東証二部(20000101-20161229)\"
ActiveSheet.Name = fn
fn = Replace(fn, "(株)", "", 1, 1, vbTextCompare)
Range("A1").Select
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs Filename:=myPATH & fn, FileFormat:=xlOpenXMLWorkbook
Application.DisplayAlerts = True
ActiveWorkbook.Close False
End Sub
Sub SplitData(arg1 As String)
'テーブルの切り分け
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
With re
.Global = True: .IgnoreCase = False: .MultiLine = True
End With
Dim Ar0
Dim Ar1
Dim Ar2
Dim k As Long, i As Long, j As Long
Dim a, Ms As Object, m As Object
Ar0 = Split(arg1, "TR")
Ar1 = Split(Ar0(1), "TH")
k = 3: j = 1
re.Pattern = "\>([^\<].+)<"
For Each a In Ar1
Set Ms = re.Execute(a)
If Ms.Count > 0 Then
Cells(2, j).Value = Ms(0).SubMatches(0)
j = j + 1
End If
If InStr(1, a, "*", vbBinaryCompare) > 0 Then Exit For
Next
re.Pattern = "\>([^\<].+)\</."
j = 0
For i = 3 To UBound(Ar0) Step 2
a = Ar0(i)
Set Ms = re.Execute(a)
If Ms.Count > 0 Then
j = 1
For Each m In Ms
Cells(k, j).Value = m.SubMatches(0)
j = j + 1
Next m
k = k + 1
End If
Next i
End Sub
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) 2つのVBAを一緒にしたら機能しなくなりました(エクセル) 7 2022/06/02 12:41
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/07/15 15:12
- Visual Basic(VBA) VBA 請求書自動作成 3 2022/04/24 01:58
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたい 6 2023/01/23 12:00
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
- Visual Basic(VBA) エクセルのマクロについて教えてください。 3 2023/02/22 08:53
- Visual Basic(VBA) このVBAでExcelアプリケーションを作成は必要ですか? 3 2023/07/19 21:13
- Excel(エクセル) VBA フォルダ見える化のコードについて 2 2023/06/19 15:04
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【関数】同じ関数なのに、エラ...
-
access テキストボックスの値取得
-
gccを行ってもexeファイルが生...
-
エクセルマクロでエラーの原因...
-
VBでファイルが開かれているか...
-
DisplayAlertsブロパティで ”実...
-
Returnに対するGoSubがありません
-
「パス名が無効です」の発生原因
-
AutoExecで自動終了させるには?
-
batファイルでレジストリキーの...
-
ホームページビルダー14でHP...
-
アクセスのクエリでコンパイル...
-
MCASのFOM出版のテキストについて
-
Excel 終了時のエラー
-
InetのResponseCodeについて
-
DBへのコネクションタイムアウト
-
EXCEL マクロについて教えてく...
-
TEXTファイルをリンクしたMDBに...
-
アクティブシート名で新しいブ...
-
Excelファイルの操作についての...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
access テキストボックスの値取得
-
Returnに対するGoSubがありません
-
「パス名が無効です」の発生原因
-
PowerShellを使って関連付けら...
-
NAS上のファイルの使用中が解除...
-
アクセスのクエリでコンパイル...
-
VBでファイルが開かれているか...
-
ExcelVBAで既に開いてるwordを...
-
エクセルマクロでエラーの原因...
-
batファイルでレジストリキーの...
-
【COBOL】read文でエラー
-
VB6 Dir関数で52エラー発生
-
「アクティブ ユーザーが多すぎ...
-
データベースソフトのアクセス2...
-
VBから参照できないCのDLLを使...
-
DisplayAlertsブロパティで ”実...
-
Access2013にてドラッグ&ドロ...
-
ACCESS VBAでのインポート
-
すでにファイルが開かれている...
-
Vba ファイル書き込み時に書き...
おすすめ情報
Win32APIであったり、知識不足で理解できない部分があるのですが、
とりあえず動かすことができず、困っています。
NextFile:
の部分でエラーが出てしまうのですが、どのように対処すればよいのでしょうか。
ご教示お願いします。