ビッグデータの抽出
ビッグデータの抽出をSQLを使用して抽出するためのプロシージャーで、接続から簡単なSQL文を作成して抽出まで行っています。
Public Sub ExcelConnect()
Const adOpenKeyset = 1
Const adOpenStatic = 3
Const adLockReadOnly = 1
Dim dbCon As Object
Dim dbRs As Object
Dim strSQL As String
Set dbCon = CreateObject("ADODB.Connection")
Set dbRs = CreateObject("ADODB.Recordset")
dbCon.Provider = "Microsoft.ACE.OLEDB.12.0"
'HDR YES:シートの1行目をヘッダ列として扱う、NO:1行目から行データとして扱う フィールド名は、F+列番号
'IMEX 0:エクスポート モード、1:インポート モード、2:リンク モード
dbCon.Properties("Extended Properties") = "Excel 12.0;HDR=NO;IMEX=1"
dbCon.Open ThisWorkbook.FullName
strSQL = ""
strSQL = strSQL & "SELECT F1, F2 "
'Sheet1のA2:B1001を対象とする
strSQL = strSQL & " FROM [Sheet1$A2:B1001] " 'Cells(1,1)からシート全体を取得したい場合 [Sheet1$]
strSQL = strSQL & " WHERE F2 > 40000 "
strSQL = strSQL & " ORDER BY F2;"
dbRs.Open strSQL, dbCon, adOpenStatic, adLockReadOnly
'HDR=YESとした場合、フィールド名をセットする
'For i = 0 To dbRs.Fields.Count - 1
' Sheet1.Cells(1, 10 +i).Value = dbRs.Fields(i).Name
'Next i
Sheet1.Cells(2, 10).CopyFromRecordset dbRs
dbRs.Close
Set dbRs = Nothing
dbCon.Close
Set dbCon = Nothing
End Sub
エクセルへの接続
列ヘッダーを結果セットに読み込み(ヘッダーがあってもHDR = NOを使用)、列データが数値である場合は、IMEX = 1を使用してクラッシュを回避します。IMEX = 1を常に使用することは、混合データ列のデータを取得するより安全な方法です。
Public Sub ExcelConnect()
Const adOpenKeyset = 1
Const adOpenStatic = 3
Const adLockReadOnly = 1
Dim dbCon As Object
Dim dbRs As Object
Dim strSQL As String
Set dbCon = CreateObject("ADODB.Connection")
Set dbRs = CreateObject("ADODB.Recordset")
dbCon.Provider = "Microsoft.ACE.OLEDB.12.0"
'HDR YES:シートの1行目をヘッダ列として扱う、NO:1行目から行データとして扱う フィールド名は、F+列番号
'IMEX 0:エクスポート モード、1:インポート モード、2:リンク モード
dbCon.Properties("Extended Properties") = "Excel 12.0;HDR=NO;IMEX=1"
dbCon.Open ThisWorkbook.FullName
strSQL = ""
strSQL = strSQL & "SELECT F1, F2 "
'Sheet1のA2:B1001を対象とする
strSQL = strSQL & " FROM [Sheet1$A2:B1001] " 'Cells(1,1)からシート全体を取得したい場合 [Sheet1$]
strSQL = strSQL & " WHERE F2 > 40000 "
strSQL = strSQL & " ORDER BY F2;"
dbRs.Open strSQL, dbCon, adOpenStatic, adLockReadOnly
'HDR=YESとした場合、フィールド名をセットする
'For i = 0 To dbRs.Fields.Count - 1
' Sheet1.Cells(1, 10 +i).Value = dbRs.Fields(i).Name
'Next i
Sheet1.Cells(2, 10).CopyFromRecordset dbRs
dbRs.Close
Set dbRs = Nothing
dbCon.Close
Set dbCon = Nothing
End Sub
エクセルへの接続
列ヘッダーを結果セットに読み込み(ヘッダーがあってもHDR = NOを使用)、列データが数値である場合は、IMEX = 1を使用してクラッシュを回避します。IMEX = 1を常に使用することは、混合データ列のデータを取得するより安全な方法です。
Excel 2007以降 Xlsx files Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\myFolder\myExcel2007file.xlsx; Extended Properties="Excel 12.0 Xml;HDR=YES"; Treating data as text Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\myFolder\myExcel2007file.xlsx; Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=1"; Xlsb files Provider=Microsoft.ACE.OLEDB.12.0; Data Source=c:\myFolder\myBinaryExcel2007file.xlsb; Extended Properties="Excel 12.0;HDR=YES"; Xlsm files Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\myFolder\myExcel2007file.xlsm; Extended Properties="Excel 12.0 Macro;HDR=YES";
VBScriptの使用例
VBScriptの使用例です。大部分が定型コードです。スクリプトの前半部分では、いくつか定数を定義し、2 つのオブジェクト (ADODB.Connection と ADODB.Recordset) を作成していることを説明するぐらいでしょう。これらのオブジェクトは、データに接続したり、データ ソースからデータを取得するのに必要です。これらの大部分は、ADO スクリプト内で手を加えないでそのまま使用する定型コードです。注意するのは、"Data Source" の部分のみです。この部分では、使用するワークシートへのパスを指定します。ワークシートへのパスに空白が含まれていたらどうなるでしょう。この場合は、まったく問題がないので、次のようにファイル パス全体を空白なども一緒に記述します。
On Error Resume Next
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H0001
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Scripts\Test.xls;" & _
"Extended Properties=""Excel 8.0;HDR=Yes;"";"
objConnection.Open ConnectionString
objRecordset.Open "Select * FROM [Sheet1$] Where Number = 2", _
objConnection, adOpenStatic, adLockOptimistic, adCmdText
Do Until objRecordset.EOF
Wscript.Echo objRecordset.Fields.Item("Name"), _
objRecordset.Fields.Item("Number")
objRecordset.MoveNext
Loop
ADO プロバイダ
「Excel ではなく、Excel へのアクセスに使用される ADO プロバイダを指します。プロバイダを Excel 8.0 のままにしておくことで、すべてがうまくいきます。(https://technet.microsoft.com/ja-jp/library/ee692882.aspx)」と言っているので、下記のようにしない方がいいかも。
objConnection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\Scripts\Test.xls;" & _
"Extended Properties=""Excel 12.0;HDR=Yes;"";"
「ShellExecuteEX」関数
'----------------------------------------------------------------------ShellExecuteEX
'SHELLEXECUTEINFO構造体の定義をします。
#If VBA7 And Win64 Then
'64ビット版
Public Type SHELLEXECUTEINFO
cbSize As Long '構造体のサイズ
fMask As Long '処理制御フラグ。2つ以上設定するときはOr演算子で結びます。
hwnd As LongPtr 'ShellExecuteEXを呼び出すウィンドウのハンドル
lpVerb As String '処理制御文字列。指定しないときは"open"になります。
lpFile As String '起動するファイルの名前
lpParameters As String '起動する実行可能ファイルへのパラメータ(lpFileメンバが実行可能ファイルのとき)。
lpDirectory As String '作業用ディレクトリ。設定しないときはカレントディレクトリになります。
nShow As Long '起動する実行ファイルのウィンドウの状態
hInstApp As LongPtr '33以上の値のときはインスタンスハンドル、32以下の値では下表に示すエラー値
lpIDList As LongPtr 'ITEMIDLIST構造体のアドレス。fMaskメンバにSEE_MASK_IDLISTが設定されていないと無視します。(オプション)
lpClass As String 'ファイルクラス名もしくはGUID。fMaskメンバにSEE_MASK_CLASSNAMEが設定されていないと無視します。(オプション)
hkeyClass As LongPtr 'ファイルクラスのレジストリキーのハンドル。fMaskメンバにSEE_MASK_CLASSKEYが設定されていないと無視します。(オプション)
dwHotKey As Long '実行ファイルに関連したホットキー。fMaskメンバにSEE_MASK_HOTKEYが設定されていないと無視します。(オプション)
hIcon As LongPtr 'ファイルクラスのアイコンハンドル。fMaskメンバにSEE_MASK_ICONが設定されていないと無視します。(オプション)
hProcess As LongPtr '実行ファイルのハンドル。fMaskメンバにSEE_MASK_NOCLOSEPROCESSが設定されていないと0になります。(オプション)
End Type
'----------------------------------------------------------------------
'ファイルのプロパティダイアログの表示やクリッカブルURLの実装などを行ないます。
'lpExecInfo :SHELLEXECUTEINFO構造体のポインター
'戻り値 :失敗すると0 成功すると0以外を返します。
Public Declare PtrSafe Function ShellExecuteEX Lib "shell32.dll" Alias "ShellExecuteEx" ( _
lpExecInfo As SHELLEXECUTEINFO) As LongPtr
#Else
'32ビット版
Public Type SHELLEXECUTEINFO
cbSize As Long
fMask As Long
hwnd As Long
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As String
nShow As Long
hInstApp As Long
lpIDList As Long
lpClass As String
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hProcess As Long
End Type
Public Declare Function ShellExecuteEX Lib "shell32.dll" Alias "ShellExecuteEx" ( _
lpExecInfo As SHELLEXECUTEINFO) As Long
#End If
'----------------------------------------------------------------------
'解説 :ファイルからプログラムを実行してファイルを開きます。
'パラメータ :hWnd フォームのハンドル
' :strPNAME 実行プログラム
' :strFNAME 開こうとするファイル
'戻り値 :成功すればtrue、失敗すればfalse
'----------------------------------------------------------------------
Public Function FileOpen(ByVal FullPath As String) As Long
Dim ShellInfo As SHELLEXECUTEINFO
Dim Res As Long
On Error GoTo ERROR_SHORI
Res = 0
'ShellExecuteEX関数を利用して、拡張子に関係付けられているプログラムから開きます。
'SHELLEXECUTEINFO構造体のメンバーに値を入れます。
With ShellInfo
.cbSize = Len(ShellInfo)
.fMask = (SEE_MASK_FLAG_NO_UI Or SEE_MASK_NOCLOSEPROCESS)
.hwnd = 0
.lpVerb = "OPEN" & vbNullChar
.lpFile = FullPath & vbNullChar
.lpParameters = vbNullChar
.lpDirectory = vbNullChar
.nShow = SW_SHOW
.hInstApp = 0
.lpIDList = 0
End With
'ShellExecuteEX関数を実行します。
RES = ShellExecuteEX(ShellInfo)
OWARI:
FileOpen = Res
Exit Function
ERROR_SHORI:
Res = 0
Resume OWARI
End Function
MsgBoxの流用
'------------------------------------------------------------------
Private Sub TextBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim FileDialog As CFileDialog
Dim strTitle As String
Dim intInd As Long
Dim strPath As String
Dim strFilter As String
strTitle = "ファイルの選択"
intInd = 1
strPath = ThisWorkBook.Path
strFilter = "Microsoft Excelブック,*.xls?," & _
"Microsoft Wordドキュ,*.doc?," & _
"すべてのファイル,*.*"
'オブジェクトを作成します。
Set FileDialog = New CFileDialog
With FileDialog
.DialogTitle = strTitle
.Filter = strFilter
.FilterIndex = intInd
.InitialDir = strPath
End With
If FileDialog.Show Then
Me.TextBox1.Value = FileDialog.FileName
Me.TextBox2.Value = FileDialog.FilePath
Me.TextBox3.Value = FileDialog.FileBook
End If
Set FileDialog = Nothing
End Sub
'------------------------------------------------------------------
'クラスの「Class_Initialize」の書き方により下のように簡略できます
'------------------------------------------------------------------
Private Sub TextBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim FileDialog As CFileDialog
'オブジェクトを作成します。
Set FileDialog = New CFileDialog
If FileDialog.Show Then
Me.TextBox1.Value = FileDialog.FileName
Me.TextBox2.Value = FileDialog.FilePath
Me.TextBox3.Value = FileDialog.FileBook
End If
Set FileDialog = Nothing
End Sub
CFileDialog
クラス モジュールです。上のコードの中では、オブジェクト名を「CFileDialog」として使っています。
Option Explicit
'------------------------------------------------------------------
#If VBA7 And Win64 Then
'64ビット版
Private Declare PtrSafe Function SetCurrentDirectory Lib "Kernel32" Alias _
"SetCurrentDirectoryA" (ByVal CurrentDir As String) As LongPtr
#Else
'32ビット版
Private Declare Function SetCurrentDirectory Lib "Kernel32" Alias _
"SetCurrentDirectoryA" (ByVal CurrentDir As String) As Long
#End If
' -----------------------------------------------メンバー(フィールド)の定義
Private pMH_strDialogTitle As String
Private pMH_strFileName As String
Private pMH_strInitialDir As String
Private pMH_strFilter As String
Private pMH_intFilterIndex As Integer
Private pMH_strFilePath As String
Private pMH_strFileBook As String
'------------------------------------------------------------------
'タイトル名のセット
Public Property Let DialogTitle(ByVal strValue As String)
pMH_strDialogTitle = strValue
End Property
'------------------------------------------------------------------
'フィルターのセット
Public Property Let Filter(ByVal strValue As String)
pMH_strFilter = strValue
End Property
'------------------------------------------------------------------
'フィルターインデックスのセット
Public Property Let FilterIndex(ByVal intValue As Integer)
pMH_intFilterIndex = intValue
End Property
'------------------------------------------------------------------
'デフォルトのオープンフォルダー
Public Property Let InitialDir(ByVal strValue As String)
pMH_strInitialDir = strValue
End Property
'------------------------------------------------------------------
'フルパスの取得
Public Property Get FileName() As String
FileName = pMH_strFileName
End Property
'------------------------------------------------------------------
'パスの取得
Public Property Get FilePath() As String
FilePath = pMH_strFilePath
End Property
'------------------------------------------------------------------
'拡張子付きのファイル名
Public Property Get FileBook() As String
FileBook = pMH_strFileBook
End Property
'------------------------------------------------------------------
Private Sub Class_Initialize()
pMH_strDialogTitle = "ファイルの選択"
pMH_intFilterIndex = 1
pMH_strInitialDir = ThisWorkbook.Path
pMH_strFilter = "Microsoft Excelブック,*.xls?," & _
"Microsoft Wordドキュ,*.doc?," & _
"すべてのファイル,*.*"
End Sub
'------------------------------------------------------------------
' 戻り値 : キャンセルが選択された場合はFalse、それ以外はTrue
'------------------------------------------------------------------
Public Function Show() As Boolean
Dim I As Integer
Dim FLG As Boolean
Dim varBUF As Variant
On Error GoTo ERROR_SHORI
'カレントを移動する(これがないとネットワークフォルダーに対応できない)
SetCurrentDirectory pMH_strInitialDir & "\"
'ダイヤログを開く
varBUF = Application.GetOpenFileName(FileFilter:=pMH_strFilter, _
FilterIndex:=pMH_intFilterIndex, _
Title:=pMH_strDialogTitle, _
MultiSelect:=False)
'選択がなかったときエラーとする
If varBUF = False Then
GoTo ERROR_SHORI
End If
'メンバーに選択されたファイルのフルパスをセットする→プロパティで取得する
pMH_strFileName = varBUF
'最後まで続けることによって、選択されたファイルのパスとファイル名を取得する
For I = 1 To Len(pMH_strFileName)
If Mid(pMH_strFileName, I, 1) = "\" Then
pMH_strFilePath = Left(pMH_strFileName, I - 1)
pMH_strFileBook = Mid(pMH_strFileName, I + 1)
End If
Next I
'成功したときの戻り値をセットする
FLG = True
OWARI:
Show = FLG
Exit Function
ERROR_SHORI:
'選択がなかった、またはエラーのときの戻り値をセットする
FLG = False
Resume OWARI
End Function