Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


81 / 3841 ページ ←次へ | 前へ→

【80868】Re:データ摘出
発言  マナ  - 19/6/4(火) 20:54 -

引用なし
パスワード
   ▼gan134 さん:

>関数でindexとmatch組合てでは出来るのですがそれをVBAでしたいのです。

なぜでしょうか?
・ツリー全体表示

【80867】データ摘出
質問  gan134  - 19/6/4(火) 20:42 -

引用なし
パスワード
   sheet1に管理番号、名前、住所、電話番号のデータを入れておいてsheet2のA1セルに管理番号を入力するとsheet1の管理番号と一致したデータを摘出しsheet2B5セルに名前、B6セルに住所、B7セルに電話番号を摘出するにはどうすれば宜しいでしょうか。ご教授お願いいたします。
関数でindexとmatch組合てでは出来るのですがそれをVBAでしたいのです。全くの素人なもんで良ければコードを教えてもらえませんか
・ツリー全体表示

【80866】Re:Userformの挿入、削除してませんか?
お礼  のり  - 19/6/4(火) 12:56 -

引用なし
パスワード
   ▼Jaka さん:
>なんとなくだけど、流れからしてUserformの挿入、削除を繰り返してませんか?
>15年ぐらい前の記憶なので、おぼろげだけど。
>1回目はOK、2回目でエラーとか。
>
>1度挿入削除をやって、上書き保存するとそのブックはだめだった様な・・・。
>削除しても、フォーム情報がへんな形で残ってしまって、2度目でこける。
>こんな感じじゃないですか?
>解決策は見つけられなかったような気が・・・。

Jaka様、
書込みして頂きまして、有り難うございます。
旅行に行っていたため、返事が遅くなってしまいました。
申し訳ございません。
ご指摘の通り、ズバリでした。
全てのUserformをエクスポート、解放した後、インポートしたら、
エラーがでなくなりました。
Userformは、開放してはダメなのようですね。
完全に解決致しました。

素晴らしいお知恵を授けて頂きまして、感謝申し上げます。
今後とも、どうぞよろしくお願い致します。
のり
・ツリー全体表示

【80865】Re:web クエリの高速化
お礼  よし  - 19/6/3(月) 3:16 -

引用なし
パスワード
   >γ さん
ありがとうございます!

所要時間については、投稿時は自分の感覚で時間を書いていましたが、その後作成したものに計測マクロをいれて計測したところ、10件で45秒ぐらいでしたので一件あたり、4.5秒ぐらいでした。

今回Yさんに作成して頂いたマクロを使用したところ、なんと5倍速くなりました!!

ちなみに私も先ほど気付いたのですが、介護保険のみURLの一部である「dt」が「kg」になっているみたいです。ただ、ここの部分については、結果シートやシート名を固定するなどして、IF文を用いて使用できるようにできました!
Yさんのおかげでこれで早く処理できます。

また、岡崎図書館事件の件は勉強になりました。
wikiで内容を読みましたが図書館側、委託の業者が悪いみたいでしたが、複数のアクセスでいらぬ誤解を招くおそれがあることに今後作成していくうえで注意したいと思います。

今後は作成して頂いたマクロを自分なりにも解析し、もっと勉強したいと思います。

ご親切にして頂き本当にありがとうございました!
・ツリー全体表示

【80864】Re:web クエリの高速化
発言  γ  - 19/6/2(日) 22:42 -

引用なし
パスワード
   守口図書館事件じゃなく
岡崎図書館事件だった。どうかしてる。
ht tps://ja.wikipedia.org/wiki/%E5%B2%A1%E5%B4%8E%E5%B8%82%E7%AB%8B%E4%B8%AD%E5%A4%AE%E5%9B%B3%E6%9B%B8%E9%A4%A8%E4%BA%8B%E4%BB%B6
・ツリー全体表示

【80863】Re:標準モジュールの内容変更をマクロで...
回答  シンガリ  - 19/6/2(日) 21:33 -

引用なし
パスワード
   ▼γ さん:
>一見するとウイルスの挙動に似ていますね。
>できないことはないのですが、
>上記の事情で、示すことが果たして適切かどうか、説が分かれるところです。
>
>どうしてそのような「マクロでマクロを変更する」必要があるのか、
>手作業ではなぜダメなのか、もうすこし説明してください。

ご回答ありがとうございます。
確かに言われてみれば、変更しようとするマクロをすべて事前に作っておけばいいだけでした。かなり面倒ですが、一度作ってしまえばそれまでですね。
下手に難しく考えていました。
ありがとうございました。
・ツリー全体表示

【80862】Re:web クエリの高速化
発言  γ  - 19/6/2(日) 21:14 -

引用なし
パスワード
   結果を書き込むところは、
[B2].Resize(kosu, 5).Value = mat
でなくて、
ws.Range("B2").Resize(kosu, 5).Value = mat
とワークシートを指定しないといけなかったですね。修正下さい。

20件で5秒程度なのでしたので、
3000件だと、10分強で終わるのではないですか?
サーバー側がなんらかの対抗策をとってきたら別ですが。
・ツリー全体表示

【80861】Re:web クエリの高速化
回答  γ  - 19/6/2(日) 20:31 -

引用なし
パスワード
   動作するものを一応作って見ました。

<<結果シート>>のレイアウト
  A列  B列    C列     D     E   F
1 コード 保険者番号 保険者名  郵便番号  住所  電話番号
2
3

・予め設定されているA列の保険者用のコードを読み込んで使用します。
・B列以下の列に、サーバーから取得結果を書き込みます。
・同一であることを念のため確保するため、B列はA列と同じものを書き込みます。

-----------------
動作することを確認していますが、保証するものではありません。
また、スクレイピングに関しての責任は負いかねます。
データの著作権等について十分確認して下さい。

また、サーバーに連続してアクセスすると負荷が掛かり、
これを禁止するところもあります。
そこで、0.2秒の間隔を空けてアクセスするようにしていますが、
これは最低限守ってください。
(連続アクセスをした人が逮捕された"守口図書館事件"が有名です。
 検索してみてください。)

-----------------
なお、今後、「仕様の変更依頼等には一切応じる積もりはありません。」
予めご了解ください。

頻度がそう高いものではないのですから、3時間ですむなら、
今の簡潔なものでも十分と思います。

XMLHt■tpRequestと正規表現を使ったコードを以下に示します。

なお、エイチティーティーピーと言う単語が使用禁止になっていますので、
元に戻してから使用してください。("■"を""に置換すればよいでしょう)

Option Explicit

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Dim re   As Object
Dim Match  As Object
Dim Matches As Object
Dim Ht■tpRequest As Object
Dim mat()  As String

Sub main()
  Dim ws   As Worksheet
  Dim s1   As String
  Dim s2   As String
  Dim s    As String
  Dim uri   As String
  Dim myText As String
  Dim k    As Long
  Dim lastRow As Long
  Dim kosu  As Long
  
  Dim t
  t = Timer
  
  Set Ht■tpRequest = CreateObject("MSXML2.XMLHT■TP.3.0")
  Set re = CreateObject("VBScript.RegExp")
  
  Set ws = Worksheets("結果")
  
  s1 = "ht■tp://hokeninfolist.main.jp/sp/dt"
  s2 = ".html"
  
  lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
  kosu = lastRow - 1
  ReDim mat(1 To kosu, 1 To 5) '一時保持用配列
  
  For k = 1 To kosu
    Sleep 200  ' サーバー負荷を考慮して、0.2秒間隔を空ける
    s = ws.Cells(k + 1, "A").Value
    uri = s1 & s & s2
    
    ' サイトからHTMLファイルを取得
    myText = getHT■TPText(uri)
      
    If myText <> "" Then
      'HTMLを解析して該当項目を取得
      Call setEachDataToMat(myText, k)
    Else
      '何もしない
    End If
  Next
  '結果をシートに貼付
  [B2].Resize(kosu, 5).Value = mat
  
  Debug.Print Timer - t
End Sub

Sub setEachDataToMat(myText As String, k As Long)
  Dim j As Long
  
  '保険者番号,保険者名,郵便番号,住所を取得し、配列matに書込む
  re.pattern = """dt"">(.*?)</div>"
  re.IgnoreCase = True
  re.Global = True
  Set Matches = re.Execute(myText)
  
  j = 1
  For Each Match In Matches
    mat(k, j) = Match.SubMatches(0)
    j = j + 1
    If j >= 5 Then Exit For
  Next
  
  '電話番号
  re.pattern = """dttel""><(?:.*?)>(.*?)</a>"
  Set Matches = re.Execute(myText)
  mat(k, 5) = Replace(Matches(0).SubMatches(0), "&nbsp;", "")
End Sub

Function getHT■TPText(uri As String) As String
  With Ht■tpRequest
    .Open "GET", uri, False
    .send
    'return codeが200でないとき(例:404該当無しなど)
    If Not (.Status >= 200 And _
        .Status < 300) Then
      getHT■TPText = ""
      Exit Function
    End If
    getHT■TPText = .responseText
  End With
End Function
・ツリー全体表示

【80860】Re:標準モジュールの内容変更をマクロで...
回答  γ  - 19/6/2(日) 19:26 -

引用なし
パスワード
   一見するとウイルスの挙動に似ていますね。
できないことはないのですが、
上記の事情で、示すことが果たして適切かどうか、説が分かれるところです。

どうしてそのような「マクロでマクロを変更する」必要があるのか、
手作業ではなぜダメなのか、もうすこし説明してください。
・ツリー全体表示

【80859】標準モジュールの内容変更をマクロで実行
質問  シンガリ  - 19/6/2(日) 17:30 -

引用なし
パスワード
   マクロ初級者です。
以下の内容をマクロで実行したいのですが可能なのでしょうか?
ご教授ください。よろしくお願いします。

ファイルを開いた状態で
1.既存の「マクロ1」を呼び出し標準モジュールの内容のみ削除。
   ↓
2.あらかじめSheet1に作成しておいたマクロの内容を上記標準モジュールに貼り付け「マクロ1」を実行。
・ツリー全体表示

【80858】Re:web クエリの高速化
質問  よし  - 19/6/1(土) 19:45 -

引用なし
パスワード
   >γ さん
マクロ1というのが、ウェブクエリにて新たなシートを作成し、抽出したデータ貼り付けるマクロです。
マクロ2はマクロ1で作成したシートのデータから詳細ページのURLを作成し、作成したURLを元にウェブクエリにて詳細ページのデータを抽出し、あらかじめ作成している貼付シートに上書きを行い、さらに貼付シートのデータをマクロ1で作成したシートに入力するマクロです。
うまく説明ができず申し訳ないです。

件数も多く、ウェブページにアクセスする回数も多いとこれだけ掛からず負えないのですかね。

ウェブクエリは高速化できないんですね。
自作でウェブクエリと同等のことができ、さらに高速化できるマクロは作成可能でしょうか?可能であればご教示頂けないでしょうか?厚かましいことをお願いしてごめんなさい。
・ツリー全体表示

【80857】Re:vba初心者
お礼  shizu  - 19/6/1(土) 13:04 -

引用なし
パスワード
   ▼γ さん:
>book.Worksheets("Sheet1")がエラーの元でしょうか。
>そのExcelブックにSheet1という名前のシートがないからでは?

ご指摘の通りでした。
ありがとうございました。
・ツリー全体表示

【80856】Re:vba初心者
発言  γ  - 19/6/1(土) 11:16 -

引用なし
パスワード
   book.Worksheets("Sheet1")がエラーの元でしょうか。
そのExcelブックにSheet1という名前のシートがないからでは?

開いたときに一番左のシートであれば、
book.Worksheets(1) という書き方ができます。

そのあたりを検討してください。
・ツリー全体表示

【80855】Re:vba初心者
質問  shizu  - 19/6/1(土) 10:59 -

引用なし
パスワード
   ▼γ さん:
早速 ありがとうございます。

>どの行でエラーになるのか、エラーメッセージは何か。
  エラーは 15行目(黄色で塗りつぶされています)の
    ThisWorkbook.Worksheets("Sheet1").Range("A" & CStr(i)).Value =    book.Worksheets("Sheet1").Range("B3").Value
  の部分になります。

  エラーメッセージは
  ”実行時 エラー9
  インデックスが有効範囲にありません。”
  と、表示されます。

>関係する変数はどうなっているのか。
>等々。

 すみません。
 変数がどうなっているか、勉強不足で理解できていません。

>フォルダが自分自身が含まれているものなら、
>自分自身をもう一度開こうとしていることが想像されますが。

  同じフォルダ内にvbaがあるエクセルがありま。

  以上まだまだ説明が足りないかもしれませんが、よろしくお願いいたします。
・ツリー全体表示

【80854】Re:web クエリの高速化
発言  γ  - 19/6/1(土) 9:29 -

引用なし
パスワード
   提示されたマクロとマクロ1マクロ2の関係がよくわかりませんが、
3000個の繰り返しを2時間と言うことは、一件2.4秒ですか。

ネットの状況、サーバー側のレスポンス等の状況に依存しますが、
その程度はかかるのかもしれませんよ。

Webクエリ自体はパッケージ化されたものなので、
ユーザー側で手を加えて高速化するとか言ったことはできません。

シート間の転記も3項目だけなら、そこが足を引っ張ることも
考えにくいでしょう。
・ツリー全体表示

【80853】Re:vba初心者
発言  γ  - 19/6/1(土) 9:20 -

引用なし
パスワード
   >デバッグが表示されます。
それだけではなく、もっと状況を説明しましょう。
どの行でエラーになるのか、エラーメッセージは何か。
関係する変数はどうなっているのか。
等々。
フォルダが自分自身が含まれているものなら、
自分自身をもう一度開こうとしていることが想像されますが。
いずれにしてももう少し説明が必要ですね。
・ツリー全体表示

【80852】vba初心者
質問  shizu  - 19/6/1(土) 8:38 -

引用なし
パスワード
   vba初心者です。
 複数のエクセルファイルから、指定した複数セルを1つのエクセルファイルにまとめようとしています。
以下のようなvbaを試したのですが、
デバッグが表示されます。
何が悪いのかわかりません。

ちなみに、取り込みたい複数のエクセルファイル、1つにまとめたいエクセルファイルは同じフォルダ内にあります。


Sub tenki()
  Dim folder As String
  Dim file As String
  Dim book As Workbook
  Dim i As Integer
  i = 2
  
  With Application.FileDialog(msoFileDialogFolderPicker)
    If .Show = True Then
      folder = .SelectedItems(1)
    End If
  End With
  
  file = Dir(folder & "\*.xlsx")
  
  Do While file <> ""
  
    Set book = Workbooks.Open(folder & "\" & file)
    
    ThisWorkbook.Worksheets("Sheet1").Range("A" & CStr(i)).Value = book.Worksheets("Sheet1").Range("B3").Value
    ThisWorkbook.Worksheets("Sheet1").Range("B" & CStr(i)).Value = book.Worksheets("Sheet1").Range("C3").Value
    ThisWorkbook.Worksheets("Sheet1").Range("C" & CStr(i)).Value = book.Worksheets("Sheet1").Range("D3").Value
    ThisWorkbook.Worksheets("Sheet1").Range("D" & CStr(i)).Value = book.Worksheets("Sheet1").Range("C4").Value
    
    
    file = Dir()
    i = i + 1
    
    book.Close
  Loop
  
End Sub


ご教授 宜しくお願い致します。
・ツリー全体表示

【80851】web クエリの高速化
質問  よし  - 19/6/1(土) 2:10 -

引用なし
パスワード
   VBA初心者です。
現在、全国保険者情報一覧というウェブページから保険者種別ごとにマクロ1でクエリデータをシートに貼り付け、マクロ2でマクロ1で貼り付けたデータの保険者番号を元に詳細情報ウェブページにアクセスし、を貼付シートを作成しそこに一時的貼り付け、必要箇所をコピして保険者番号の横にペーストしたら、今度はその下の保険者番号を元に詳細情報ウェブページにアクセスし、先ほどの貼付シートに上書きし、必要箇所をコピして保険者番号番号の横にペーストするというループマクロを組んだのですが、マクロ1はそれなりにすぐにおわりますが、マクロ2は保険者種別にもよりますが、件数が多いもので3000ぐらいあり、処理が終わるのに2時間ほどかかります。

このwebクエリマクロを早くする方法をご教授いただけないでしょうか。

実際に使用しているマクロは下記のとおりです。
注釈:URLは保険者番号を変えるだけでそれぞれの詳細情報ウェブページにアクセスできることから、セルに保険者番号のぞくURL入力し、そのセルを元にURLを組み合わせてアクセスしています。


Sub 詳細情報取込み介護保険除く()

'確認ボタン
Dim rc As Integer
rc = MsgBox("この作業は数時間を要します。(途中で止めることもできません)実行しますか?", vbYesNo + vbQuestion, "確認")
If rc = vbYes Then
  MsgBox "処理を行います。「終わりました」と表示されるまで触らないで下さい"

'高速化
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False

'シート名の取得(SNはSheetNameの略)
  Dim SN As String
  SN = ActiveSheet.Name
  
'繰り返し準備(HNは保険者HokenjaNumberの略また回数の定義としても使用)
HN = 2
Do Until Cells(HN, 1) = ""
  
'URL取得(KURLはKobetsuURLの略)
  Dim KURL As String
  KURL = "URL;" & Sheets("保険者一覧").Cells(2, 3) & Sheets(SN).Cells(HN, 1) & Sheets("保険者一覧").Cells(2, 4)

'データ取り込み
  Sheets("貼付シート").Activate
  Application.CutCopyMode = False
  With ActiveSheet.QueryTables.Add(Connection:= _
    KURL, Destination:=Range( _
    "$A$1"))
    .Name = "dt01010016"
    .FieldNames = True
    .RowNumbers = False
    .FillAdjacentFormulas = False
    .PreserveFormatting = True
    .RefreshOnFileOpen = False
    .BackgroundQuery = False
    .RefreshStyle = xlOverwriteCells
    .SavePassword = False
    .SaveData = True
    .AdjustColumnWidth = True
    .RefreshPeriod = 0
    .WebSelectionType = xlEntirePage
    .WebFormatting = xlWebFormattingNone
    .WebPreFormattedTextToColumns = True
    .WebConsecutiveDelimitersAsOne = True
    .WebSingleBlockTextImport = False
    .WebDisableDateRecognition = False
    .WebDisableRedirections = False
    .Refresh BackgroundQuery:=False
    .Delete
  End With
  
  '詳細情報の転記
  Sheets(SN).Cells(HN, 4) = Sheets("貼付シート").Range("A10")
  Sheets(SN).Cells(HN, 5) = Sheets("貼付シート").Range("A12")
  Sheets(SN).Cells(HN, 6) = Sheets("貼付シート").Range("A14")
  Sheets(SN).Activate
  
   '項目作成
   Range("D1") = "郵便番号"
   Range("E1") = "住所"
   Range("F1") = "電話番号"
  
  '回数増やす
  HN = HN + 1
Loop

'確認ダイアログ表示
Application.DisplayAlerts = True

'高速化停止
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

MsgBox "終わりました。"

Else
  MsgBox "処理を中断します。"
  
End If


End Sub
・ツリー全体表示

【80850】Userformの挿入、削除してませんか?
発言  Jaka  - 19/6/1(土) 1:31 -

引用なし
パスワード
   なんとなくだけど、流れからしてUserformの挿入、削除を繰り返してませんか?
15年ぐらい前の記憶なので、おぼろげだけど。
1回目はOK、2回目でエラーとか。

1度挿入削除をやって、上書き保存するとそのブックはだめだった様な・・・。
削除しても、フォーム情報がへんな形で残ってしまって、2度目でこける。
こんな感じじゃないですか?
解決策は見つけられなかったような気が・・・。
・ツリー全体表示

【80849】Re:エクセル userformのイニシャライズ...
発言  γ  - 19/5/31(金) 9:39 -

引用なし
パスワード
   バグはありません、と断言していますが、
バグっているから、.Showでエラーになっているものと思料。

オプションのエラートラップは、3つの選択肢がありますが、
3番目のものに指定していませんか?
これを、一時的に、最初の
・エラー発生時に中断
に変更してみると、実際のエラー箇所が表示されて止まるはずです。
ただし、これはデバッグ用のものなので、バグ解決後、
元の選択肢に戻しておいたほうがよいと思います。
(後半部分は想像です。実際に確認していません。あしからず)
・ツリー全体表示

81 / 3841 ページ ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free