2017-10-25

oo4oからADOへの変換 (1)

基本的に oo4o は ODP.NET へ移行することになりますが、VBA の場合は ADO に移行することになるかと思います。
oo4o をどこまで機械的に ADO に変換できるか確認するため、とりあえず ORACLE_BASE\ORACLE_HOME\oo4o\excel\samples のサンプルを ADO に書き換えてみます。

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 では、RecordsetCursorLocationadUseClient にし、OpenメソッドでCursorType:=adOpenStatic, LockType:=adLockOptimistic を使うようにしています。

この設定だと ADO の Recordset は厳密にはORADYN_DEFAULT ではなく、ORADYN_NO_BLANKSTRIP + ORADYN_ORAMODE + ORADYN_NO_REFETCHと同じ振る舞いをします。
(参考: AddNew メソッドとデフォルト列値

今回の例では読取り専用で充分ですので、oo4o の CreateDynaset は、

oo4o
  Const ORADYN_READONLY = &H4
  Const ORADYN_NOCACHE = &H8
  Set EmpDynaset = OraDatabase.CreateDynaset("select * from emp", ORADYN_READNONLY + ORADYN_NOCACHE)

ADO の Recordset.Open は、

ADO
  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 句がないことに注意。

ADO
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 いずれも以下のメッセージボックスが表示されます。

ORA-00923: FROMキーワードが指定の位置にありません。
ADO は、cnn.Errors.Count > 0OraSession.LastServerErr <> 0も捕まえられます。

続く

No comments:

Post a Comment