質問するログイン新規登録

回答編集履歴

2

追記

2016/05/12 10:15

投稿

kaz.Suenaga
kaz.Suenaga

スコア2042

answer CHANGED
@@ -21,7 +21,7 @@
21
21
  まずそこからいってみましょう。
22
22
 
23
23
  ---
24
- (2016/05/12 14:07 のコメントの続きです。)
24
+ ##(2016/05/12 14:07 のコメントの続きです。)
25
25
 
26
26
  1つのソースコードの中でSQLServerにもAccessにも接続したいのか、SQLServerへの接続はAccessのリンクテーブルを通じて行うのかで回答が変わりますが、仮に後者の場合、
27
27
 
@@ -49,4 +49,102 @@
49
49
  Set cn = CurrentProject.Connection
50
50
  ```
51
51
 
52
- に置き換えれば動作するでしょう。
52
+ に置き換えれば動作するでしょう。
53
+
54
+
55
+ ---
56
+ ##(2016/05/12 18:57 のコメントの続きです。)
57
+
58
+ > >変数の「参照渡し」と「値渡し」を知っていますか
59
+ > javaの資格を取る際に、勉強したので意味としてはわかります。
60
+ >
61
+ > >↓の2つのコードの違いを理解できますか。
62
+ >  Dim cn As New ADODB.Connection
63
+ >  Dim cn As ADODB.Connection
64
+ >
65
+ > 実はこれは以前から気になっていたのですが、ネットなどでサンプルコードをみると、
66
+ >  Dim cn As ADODB.Connection
67
+ >  の方は、後ほど変数にNEWを代入してインスタンス化していますが、
68
+ >  Dim cn As New ADODB.Connection
69
+ > と初めから宣言しているとその後のインスタンス化は不要なのかなぁ…と、
70
+ > ぼんやりとしかわからないので気になっていました。
71
+
72
+ あ、じゃあ説明はしやすいですね。
73
+
74
+ VBAの場合、大前提として Dim は変数の定義です。
75
+ その際、オブジェクト型の変数の場合、 New をつけることで同時にインスタンス化されます。
76
+
77
+ 細かいことを抜きにして、
78
+
79
+ ```VBA
80
+ Dim obj as New object ' 型宣言とインスタンス化を同時に行う
81
+ ```
82
+
83
+ ```VBA
84
+ Dim obj as object ' 型宣言
85
+ Set obj = New Object ' インスタンス化
86
+ ```
87
+
88
+ は同義です。
89
+
90
+
91
+ オブジェクト型以外のほとんどの変数の場合、VBAでは変数の代入は値渡しで行われるのですが、オブジェクト型の場合は参照渡しで行われます。
92
+
93
+ ```VBA
94
+ Dim obj1 As Object
95
+ Dim obj2 As Object
96
+
97
+ Set obj1 = New Object
98
+ Set obj2 = obj1
99
+ ```
100
+
101
+ この場合、変数 obj2 は obj1 への参照となります。
102
+ つまり obj2 への操作は obj1 にも影響します。
103
+
104
+ ```VBA
105
+ Dim obj1 As Object
106
+ Dim obj2 As Object
107
+
108
+ Set obj1 = New Object
109
+ Set obj2 = New Object
110
+
111
+ Set obj2 = obj1
112
+ ```
113
+ この場合、動作は結局一緒なのですが、obj2 として生成されたインスタンスは、obj1 への参照に上書きされ消えます。
114
+ (実動上は無駄なだけなはず)
115
+
116
+ で 2016/05/12 14:57 のコメントにあった下記のソースの
117
+ ```VBA
118
+ Dim cn As New ADODB.Connection 'SQLserverへの接続 
119
+ ● Dim cn2 As New ADODB.Connection 'Accessへの接続
120
+ Dim rs1 As New ADODB.Recordset
121
+ Dim rs2 As New ADODB.Recordset
122
+ Dim rs3 As New ADODB.Recordset
123
+
124
+ Dim strConnectionString As String 'SQLServer接続文字列
125
+
126
+ strConnectionString = CStr(DLookup("connectionString", "接続文字列テーブル", "ID= 2"))
127
+ ●Set cn2 = CurrentProject.Connection
128
+
129
+ cn.Open strConnectionString
130
+ ●’cn2.Open ←ここでは実行時エラー'3705'「オブジェクトが開いている場合は、操作は許可されません」とエラーが出る為一旦コメントアウト中です。
131
+         この記述は、不要もしくは違う箇所に書かなければなりませんか?ご教示いただければ幸いです。
132
+
133
+ rs1.Open "顧客マスタ", cn, adOpenForwardOnly, adLockReadOnly //エラー
134
+ ● rs2.Open "Q売上", cn2, adOpenForwardOnly, adLockReadOnly
135
+ ● rs3.Open "Q売上明細", cn2, adOpenForwardOnly, adLockReadOnly
136
+ ```
137
+
138
+ `cn2.Open` でエラーが出る理由は、`Dim cn2 As New ADODB.Connection` としてインスタンスを生成したものの、その後で `Set cn2 = CurrentProject.Connection` をすることにより、cn2 はCurrentProject.Connection への参照となっています。
139
+
140
+ つまりいま開いているAccessファイルへの接続なので、さらにOpenはできないため、エラーが出ます。
141
+
142
+ ```
143
+ Dim cn2 As ADODB.Connection
144
+ Set cn2 = CurrentProject.Connection
145
+ ```
146
+ で、cn2 は既に開いたAccessDBへの接続になっているわけです。
147
+
148
+
149
+
150
+ という事でほぼ理解上は解決するのではないでしょうか。

1

追記

2016/05/12 10:15

投稿

kaz.Suenaga
kaz.Suenaga

スコア2042

answer CHANGED
@@ -18,4 +18,35 @@
18
18
  「cn」はなんですか。
19
19
  おまじないとしてではなく、言葉でそれを考えてみると、どうすればいいか、には辿り着くと思います。
20
20
 
21
- まずそこからいってみましょう。
21
+ まずそこからいってみましょう。
22
+
23
+ ---
24
+ (2016/05/12 14:07 のコメントの続きです。)
25
+
26
+ 1つのソースコードの中でSQLServerにもAccessにも接続したいのか、SQLServerへの接続はAccessのリンクテーブルを通じて行うのかで回答が変わりますが、仮に後者の場合、
27
+
28
+ > ADOのコードに
29
+ > Set cn = CurrentProject.Connection
30
+
31
+ が正解です。
32
+ 元のソースコードの
33
+
34
+ ```VBA
35
+ Dim cn As New ADODB.Connection
36
+
37
+ Dim strConnectionString As String 'SQLServer接続文字列
38
+
39
+ strConnectionString = CStr(DLookup("connectionString", "接続文字列テーブル", "ID= 2"))
40
+
41
+ cn.Open strConnectionString
42
+ ```
43
+
44
+ が、
45
+
46
+ ```VBA
47
+ Dim cn As ADODB.Connection
48
+
49
+ Set cn = CurrentProject.Connection
50
+ ```
51
+
52
+ に置き換えれば動作するでしょう。