Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Excel 2019)
大量のbookから値を取得する
投稿日時: 24/04/05 16:55:06
投稿者: shamo

いつもお世話になります。
 
VBAについて質問です。
 
デスクトップにあるフォルダ内に300個程のエクセルファイルがあります。
 
エクセルファイルの中身ですが、表がありフォーマットは全て同じで中身の数字が異なるだけです。
 
下記コードで1つづつファイルを開き値を取得するやり方で処理をしていますがとても処理時間がかかります。
 
大量のファイルから値を取得したい場合、もっと処理が早くなる方法はありますか?
コードを教えて欲しいのではなく、アドバイスをお聞きしたいです。
 
Sub A()
Dim ExcelApp As New Application
Dim targetSheet As Worksheet
Dim folderPath As String
Dim rowIndex As Long
Dim fileName As String
Dim wb As Workbook
Dim ws As Worksheet
Dim cellValue As Variant
 
Set targetSheet = ThisWorkbook.Sheets(3)
folderPath = Environ("USERPROFILE") & "\Desktop\フォルダ\"
 
With targetSheet
    .Range("D2:D" & .Cells(.Rows.Count, "A").End(xlUp).Row).ClearContents
End With
 
rowIndex = 2
 
ExcelApp.Visible = False
ExcelApp.DisplayAlerts = False
 
While Not IsEmpty(targetSheet.Cells(rowIndex, 1))
     fileName = targetSheet.Cells(rowIndex, 1).Value
     If dir(folderPath & fileName) <> "" Then
          Set wb = ExcelApp.Workbooks.Open(folderPath & fileName, , True)
          Set ws = wb.Sheets(1)
          cellValue = ws.Range("F84").Value
          If IsNumeric(cellValue) Then
              With targetSheet.Cells(rowIndex, 4)
                  .NumberFormat = "#,###"
                  .Value = cellValue
              End With
          End If
          wb.Close SaveChanges:=False
      End If
      rowIndex = rowIndex + 1
Wend
 
ExcelApp.DisplayAlerts = True
ExcelApp.Quit
Set ExcelApp = Nothing
 
End Sub

回答
投稿日時: 24/04/05 19:24:47
投稿者: 半平太

いちいちエクセルブックとして開くから遅くなるんでしょうね。
  
必要なデータを数式で取得したら、(多分)あっと言う間でしょう。
セルに入力された数式の力ってあなどれないです。
 
つまり、VBAで他ブックへの参照数式を埋め込むことになります。
ただ、シート名まで分からないと書けないので、
(既にSheet1とかで統一されていればいいですが、そうじゃない場合は)
 シート名を統一する作業か
 ブック毎の参照シート名をどこかに書き出して置く作業
のどちらかが1度必要になります。

回答
投稿日時: 24/04/05 21:08:02
投稿者: Suzu

多分、1ブックづつ開かざるを得ないのは変えられないと思います。
 
それ以外の部分の速度を上げるとなると
1セルづつ の アクセス&書き込み を減らす事でしょうか。
 
1. A列の 対象のワークブック名 を配列に入れる
2. 同じ数の配列を作成
3. 1で作成した配列から、ブック名を取得し開く
4. 開いたブックから値を読み込み、2で作成した配列に書き込み
5. 全てのブックの値を取得したら、2の配列を D列に書き込む
 
の様な流れでしょうか。
 
 
別案としては
セキュリティ上のリスクはありますが
Microsoft Excel 4.0 マクロ関数 を使い、
ブックを開かずに参照する方法があります。
 
ExecuteExcel4Macro
https://www.moug.net/tech/exvba/0060037.html
 
Excel のバージョンに拠っては、セキュリティを緩める設定が必要かもしれません。
その場合には、ご自身でWEB検索を行い設定方法を見つけると共に、リスクも確認ください。

回答
投稿日時: 24/04/05 21:24:26
投稿者: abec

このごろ同じようなことをしました。
 
値を取得する対象のセルが一つだけみたいですが、それなら ExecuteExcel4Macro でも十分な速度で持ってこれるかと思います。ただし対象セル数が多くなると遅くなります。
参照形式の数式を作成して値を取得するのはかなり早く取得できます。ただ、指定したシート名が存在しないとリンク切れのダイアログが表示され止まります(displayalert=falseで消せない)
上記2つの具体的な方法は下記など参照。
http://officetanaka.net/excel/vba/tips/tips28.htm
 
最終的にまずADODBで接続してそのファイルに存在するシート名をチェック(これもググると結構出てきます)、対象のシート名が存在するなら数式を作成して値を取得、取得後に値だけコピーという処理で取得するものを作成しました。
1ファイル0.5〜1秒ぐらいで値を持ってこれるようになりました。

回答
投稿日時: 24/04/06 07:08:40
投稿者: abec

先ほど書いたADODBによるシート名チェックと参照形式の数式で読み取る方式、もう少し見直していたら読み取るセルが30個ぐらいあっても1ファイル0.3秒以下で処理されるようになりましtた。

投稿日時: 24/04/06 08:42:38
投稿者: shamo

おはようございます。
 
・bookを開かず、直接値を参照する
・データベース
 
この2通りで試してみます。
 
皆様の貴重なご意見、本当にありがとうございました。