質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

4285閲覧

[VBA]C#で作成したDLLの戻り値DbDataReaderの受け取り方がわかりません。

siritaidake

総合スコア8

DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2016/11/22 05:14

編集2016/11/22 05:45

###前提・実現したいこと

下記サイトを参考に、VBAでしようできるDLLをC#で作成しました。

C#でVBA向けの.NETライブラリ(COMコンポーネント)を作成するには?

DLLは、C#で別のアプリケーションから使用できることは検証済みです。
VBA(Excel 2013) でも使用できることは確認済みです。

ただ、ある関数が返してくる戻り値が受け取れなくて困っています。
ある戻り値は C#では DbDataReader なのですが、VBAではどうしたら受け取れるのでしょうか?
それらしきものを探したのですが、見つけられませんでした。

DLLの方でLIST型にして返すという手も考えてはいますが、
まずはVBAでそのまま DbDataReader を受け取れないのかどうか教えてほしいです。

###発生している問題・エラーメッセージ
if res.HasRows then の行で[オブジェクトが必要です]とエラーがでる

###該当のソースコード

Dim obj as new Test.Access call obj.Open dim res as Variant set res = obj.ExcuteReader("select * from hoge") if res.HasRows then 省略 end if call obj.Close

※Test.AccessはC#で作った自作のDLLを参照して使えるようにしました

###試したこと
0. 受け取る方を変えてみた
dim res as Object
set res = obj.ExcuteReader("select * hoge")
上記の行で[オブジェクトが必要です]とエラーがでてしまう。

  1. Select文実行するだけにしてみた

Dim obj as new Test.Access
call obj.Open
obj.ExcuteReader("select * hoge")
call obj.Close

###補足情報(言語/FW/ツール等のバージョンなど)

Test.Accessで使用できる関数は下記の通りです。

public void Open() public void Close() public DbDataReader ExcuteReader(string sql) public int ExcuteNonQuery(string sql) public DataTable Select(string sql)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lain

2016/11/22 05:44

該当のソースコードの「set res = obj.ExcuteReader("select * hoge")」行はとおって、次の「if res.HasRows then」の行でのエラーですか?
siritaidake

2016/11/22 05:47

そうです。 if文とって、res.HasRowsだけにしてもエラーがでます。(SQL間違っていたので修正しました。)
lain

2016/11/22 05:50

そのif文のところで resの内容ってnullになってませんか?
siritaidake

2016/11/22 05:58

ウォッチ式でみたのですが、宣言した際にはEmptyと値は表示されています。ExcuteReader実行後は何も表示されなくなります。でも型にはVariant/OracleDataReaderという型になるので、返ってきているのだと思います。
siritaidake

2016/11/22 06:00

OracleDataReaderは、C#でOracleのNuget Packageを使って使用できるようにしたやつです。OracleDataReaderは、SQLDataReaderと同じつくりをしていて、DbDataReaderを継承しています。
guest

回答3

0

自己解決

C#のDLL内で、DbDataReaderを保持し、そのデータにアクセスできるインターフェースを実装し、VBAからも使えるようにしました。

/* C#の方 元のDbDataReaderを使うのと同じように使えるようにしました */ void bool Read(); void string GetValue(int colindex);
'VBA Private Sub CommandButton2_Click() 'クラスのインスタンスを生成 Dim o As New TestOracle.DbAccess '接続 o.Open 'カーソルを開く(SELECT文の実行) o.ExcuteReader ("SELECT * FROM testtable where rownum <= 10") 'データがなくなるまで繰り返す Do While o.Read debug.print o.GetValue(0) debug.print o.GetValue(1) Loop 'カーソルを閉じる Call o.CloseCursor '接続を切断する Call o.Close End Sub

投稿2016/11/24 06:48

siritaidake

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

DbDataReaderクラス(SQLDataReaderも含む)にはSQLクエリを引数とするコンストラクタがありません。
SqlCommandクラスを経由して下のコード(VBAの事は考えてません)のように使用してみてください。

c#

1 2SqlConnection con = new SqlConnection("SQL接続文字列"); 3SqlCommand command = new SqlCommand("select * from hoge", con); 4con.Open(); 5SqlDataReader reader = command.ExecuteReader(); 6if(reader.HasRows) 7{ 8 処理... 9} 10con.Close(); 11con.Dispose(); 12 13 14 15

投稿2016/11/22 06:28

lain

総合スコア161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siritaidake

2016/11/22 06:48

やはり、C#で作ったDLL側の関数内で、VBAで受け取れるように別の形で返しなさいということですか?
siritaidake

2016/11/22 07:13 編集

補足します。 C#で下記のように書いています。(省略したるところや、別のクラスも登場しているので説明しずらいですが。)これをDLLにしました。そして、5つのメソッドを通して使おうとしています。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; ///////////////////////////////////////////////////// //DLLにする為 using System.Net; using System.Runtime.InteropServices; ///////////////////////////////////////////////////// //SQLServerとOracle使うため using System.Data; using System.Data.Common; using System.Data.SqlClient; using Oracle.ManagedDataAccess.Client; ///////////////////////////////////////////////////// namespace TestOracle { [Guid (DbAccess.ClassId)] public class DbAccess { public const string ClassId = "1F9B0653-A03E-453D-8D9F-E1D3B965F18E"; protected DbConnection connection = null; private ConnectionString xml = null; public void Open(string xmlFilePath) { ReadXml(xmlFilePath); if (null == connection) { connection = new OracleConnection(); } connection.ConnectionString = string.Format(@"Data Source=({0}) ;User ID={1}; Password={2}; " , xml.XmlDataSource, xml.XmlUserId, xml.XmlPassword); this.Open(); } protected void Open() { if (null != connection) { connection.Open(); } } public void Close() { if (null != connection) { connection.Close(); connection = null; } } public DbDataReader ExcuteReader(string sql) { DbCommand command = connection.CreateCommand(); command.CommandText = sql; return command.ExecuteReader(); } public int ExcuteNonQuery(string sql) { DbCommand command = connection.CreateCommand(); command.CommandText = sql; return command.ExecuteNonQuery(); } public DataTable Select(string sql) { DataTable resultData = new DataTable(); DbDataAdapter dbAdapter = null; if (1 == GetDbType()) { dbAdapter = new OracleDataAdapter(); } else { dbAdapter = new SqlDataAdapter(); } DbCommand command = connection.CreateCommand(); command.CommandText = sql; dbAdapter.SelectCommand = command; dbAdapter.Fill(resultData); return resultData; } protected int GetDbType () { int ret = 0; if (null != connection) { if (null != connection) { if (0 <= connection.GetType().ToString().ToUpper().IndexOf("ORACLE")) { ret = 1; } } } return ret; } protected void ReadXml(string strFilepath) { System.Xml.Serialization.XmlSerializer xmlSerial = new System.Xml.Serialization.XmlSerializer(typeof(ConnectionString)); System.IO.FileStream fsR = new System.IO.FileStream(strFilepath, System.IO.FileMode.Open); xml = (ConnectionString)xmlSerial.Deserialize(fsR); fsR.Close(); } }//class }
guest

0

fromがないだけだったり?

"select * from hoge"

投稿2016/11/22 05:35

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siritaidake

2016/11/22 05:43

ごめんなさい、実際にはあります。記入ミスです、修正します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問