基本的に oo4o は ODP.NET へ移行することになりますが、VBA の場合は ADO に移行することになるかと思います。
oo4o をどこまで機械的に ADO に変換できるか確認するため、とりあえず ORACLE_BASE\ORACLE_HOME\oo4o\excel\samples のサンプルを ADO に書き換えてみます。
Sub Get_Data()
' Create and initialize the necessary objects
' Dim OraSession As Object
' Dim OraDatabase As Object
Dim cnn As Object
' Dim EmpDynaset As Object
Dim rst As Object
Dim ColNames As Object
' Set OraSession = CreateObject("OracleInProcServer.XOraSession")
' Set OraDatabase = OraSession.OpenDatabase("ExampleDb", "scott/tiger", 0&)
Set cnn = CreateObject("ADODB.Connection")
cnn.Open "Provider=OraOLEDB.Oracle;Data Source=ExampleDb;User ID=scott;Password=tiger"
' Set EmpDynaset = OraDatabase.DbCreateDynaset("select * from emp", 0&)
Set rst = CreateObject("ADODB.Recordset")
Const adUseClient = 3
rst.CursorLocation = adUseClient
Const adOpenStatic= 3
Const adLockOptimistic = 2
Const adCommandText = 1
rst.Open "select * from emp", cnn, adOpenStatic, adLockOptimistic, adCommandText
' Using field array, ie. ColNames("ename").value, is significantly faster than using
' field lookup, ie. EmpDynaset.fields("ename").value
' Set ColNames = EmpDynaset.Fields
Set ColNames = rst.Fields
' Place column headings on sheet
For icols = 1 To ColNames.Count
Worksheets("DataSheet").Cells(1, icols).Value = ColNames(icols - 1).Name
Next
' Place data on sheet using CopyToClipboard
' EmpDynaset.CopyToClipboard -1
Sheets("DataSheet").Select
Range("A2").Select
' ActiveSheet.Paste
ActiveCell.CopyFromRecordset rst
End Sub
- oo4oのサンプルに合わせて、遅延バインディングにしています。
CreateDynaset のオプション
上の例では、 oo4o の CreateDynaset
のオプション 0&
(ORADYN_DEFAULT
) に合わせて、ADO では、Recordset
の CursorLocation
を adUseClient
にし、Open
メソッドでCursorType:=adOpenStatic, LockType:=adLockOptimistic
を使うようにしています。
この設定だと ADO の Recordset
は厳密にはORADYN_DEFAULT
ではなく、ORADYN_NO_BLANKSTRIP + ORADYN_ORAMODE + ORADYN_NO_REFETCH
と同じ振る舞いをします。
(参考: AddNew メソッドとデフォルト列値)
今回の例では読取り専用で充分ですので、oo4o の CreateDynaset
は、
Const ORADYN_READONLY = &H4
Const ORADYN_NOCACHE = &H8
Set EmpDynaset = OraDatabase.CreateDynaset("select * from emp", ORADYN_READNONLY + ORADYN_NOCACHE)
ADO の Recordset.Open
は、
Const adOpenForwardOnly= 0
Const adLockReadOnly = 1
rst.Open "select * from emp", cnn, adOpenForwardOnly, adLockReadOnly
'規定値なので、rst.Open "select * from emp", cnn で可
または、
' Executeメソッドは読み取り専用で、前方スクロールタイプのカーソルを返す。
Set rst= cnn.Execute("select * from emp")
で良いと思います。
参考
とくに ADOプログラマのためのヒント は必見。
oo4oはDAOに近いモデルのため参考になります。
エラー処理
エラー処理を追加してみます。
サンプルは Oracle® Objects for OLE開発者ガイド の LastServerErr
プロパティの例を ADO に書き換えたものです。SQL文にfrom
句がないことに注意。
Sub Form_Load()
'Declare variables as OLE Objects.
' Dim OraSession As OraSession
Dim cnn As ADODB.Connection
' Dim OraDatabase As OraDatabase
' Dim OraDynaset As OraDynaset
Dim rst As ADODB.Recordset
'Create the OraSession Object.
' Set OraSession = CreateObject("OracleInProcServer.XOraSession")
Set cnn = CreateObject("ADODB.Connection")
'Set up an error handler.
On Error GoTo errhandler
'Create the OraDatabase Object by opening a connection to Oracle.
' Set OraDatabase = OraSession.OpenDatabase("ExampleDb", "scott/tiger", 0&)
cnn.Open "Provider=OraOLEDB.Oracle;Data Source=ExampleDb;User ID=scott;Password=tiger"
'Attempt to Create the OraDynaset Object.
'Notice that the FROM keyword is missing from the SQL statement.
' Set OraDynaset = OraDatabase.CreateDynaset("select * emp", 0&)
Set rst = CreateObject("ADODB.Recordset")
Const adUseClient = 3
rst.CursorLocation = adUseClient
Const adOpenStatic = 3
Const adLockOptimistic = 2
Const adCommandText = 1
rst.Open "select * emp", cnn, adOpenStatic, adLockOptimistic, adCommandText
Exit Sub
errhandler:
'Check to see if an Oracle error has occurred.
' If OraDatabase.LastServerErr <> 0 Then
If cnn.Errors.Count > 0 Then
' 厳密には
'If cnn.Errors(cn.Errors.Count - 1).NativeError <> 0 Then
' MsgBox OraDatabase.LastServerErrText
MsgBox cnn.Errors(cnn.Errors.Count - 1).Description
Else 'Must be some non-Oracle error
MsgBox "VB:" & Err & " " & Error(Err)
End If
Exit Sub
End Sub
oo4o、ADO いずれも以下のメッセージボックスが表示されます。
ADO は、cnn.Errors.Count > 0
でOraSession.LastServerErr <> 0
も捕まえられます。
No comments:
Post a Comment