基本的に 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