柔軟に働き方を選ぶ時代に必要なこと >>

VB6 + SQL サーバー 2000 でDB接続を行っていますが
リストのように SELECT 文の後にInsert 文を実行しようとし
Re.Closeを実行すると
-------------------------------------------------------------
実行時エラー '3704':
オブジェクトが閉じている場合は、操作は許可されません
-------------------------------------------------------------
 とエラーになり、連続するSQL文を実行する場合のopen ,Close は
どのように書けばよろしいのでしょうか。

 ネット上で見つけた資料によるとメソッド RE.CancelUpdate を使うと
ありましたがこれもエラーとなります。

どなたか 教えていただけないでしょうか。

--- sample ----------------------------------------
Dim Cn As New ADODB.Connection
Dim Re As New ADODB.Recordset

Connect = ""
Connect = "Provider = SQLOLEDB;" _
& "Data Source = サーバー;" _
& "User ID = sa;" _
& "Password = パスワード;" _
& "initial Catalog = database;"
'
Cn.Open Connect
'
strSQL = "SELECT * from DBTBL WHERE CODE = '000001'"
Re.Open strSQL, Cn, adOpenKeyset 'SQL文を実行
Re.Close
'
strSQL = "Insert Into MAS1PF (CODE,NAME,TEL,FAX) Values('11111','名前','TEL,'FAX)"
Re.Open strSQL, Cn, adOpenKeyset 'SQL文を実行
'
Re.Close
Cn.Close

A 回答 (2件)

1:strSQL = "SELECT * from DBTBL WHERE CODE = '000001'"


2:Re.Open strSQL, Cn, adOpenKeyset 'SQL文を実行
3:Re.Close
4:strSQL = "Insert Into MAS1PF (CODE,NAME,TEL,FAX) Values('11111','名前','TEL,'FAX)"
5:Re.Open strSQL, Cn, adOpenKeyset 'SQL文を実行

の 3: で Re.Close したまま、5: で Re.Open しているからだと思います。
5: の前に
Set Re = New ADODB.Recordset
を入れると正常に動作するようになると思います。
ちなみに、なぜ 2: ではエラーが発生しないかというと、
Dim Re As ADODB.Recordset
ではなく、
Dim Re As New ADODB.Recordset
として宣言しているからです。

この回答への補足

tukasa-12r さんありがとうございます。早速 試してみたのですが同じエラーが発生します。

Dim Cn1 As New ADODB.Connection
Dim Re As ADODB.Recordset

vProv = "Provider = SQLOLEDB;" _
& "Data Source = サーバー;" _
& "User ID = sa;" _
& "Password = パスワード;" _
& "initial Catalog = database;"

Cn1.Open vProv 'Db OPEN

strSQL = "SELECT * from DBTBL WHERE CODE = '000001'"
Re.Open strSQL, Cn, adOpenKeyset 'SQL文を実行
Re.Close

strSQL = "Insert Into MAS1PF (CODE,NAME,TEL,FAX) Values('11111','名前','TEL,'FAX)"
Set Re = New ADODB.Recordset
Re.Open strSQL, Cn, adOpenKeyset 'SQL文を実行

Re.Close ← ここでエラー 3704 がでます

もう少し教えていただけないでしょうか。

補足日時:2007/07/26 09:34
    • good
    • 0
この回答へのお礼

insert,update,delete の場合は Execute を使いなさいと文書を
見つけました。
Executeだと re.close は不要との記述もありました。
試したところイメージ通りの処理ができていますので、これでやってみようと
思います。

本当にありがとうございました。

お礼日時:2007/07/26 15:43

Private Sub Command1_Click()


  Dim strSQL(1) As String
  
  strSQL(0) = "INSERT INTO Table1 (ID, 顧客名) VALUES (3, 'AAA')"
  strSQL(1) = "INSERT INTO Table1 (ID, 顧客名) VALUES (4, 'BBB')"
  CnnExecute strSQL(0)
  CnnExecute strSQL(1)
End Sub

No1さんの回答で不具合自体は解消されています。
が、幾つか改善すべき点もあるようです。

CnnExecute関数は、conCNNSTRING を SQL Server 2000 のそれに変更しての動作確認も済んでいます。

改善点1、ADODB のエラー管理を行う。
改善点2、トランザクションのロールバックも行う。

なお、Set cnn = New ADODB.Connection を複数回実行するのであれば関数にすればよい。
そうすれば、 Command1_Click() のように非手続き的に安直の書くことも可能。

Const conCNNSTRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\temp\db1.mdb"

Public Function CnnExecute(ByVal strSQL As String) As Boolean
On Error GoTo Err_CnnExecute
   Dim isOK As Boolean
   Dim cnn As ADODB.Connection
  
   isOK = True
   Set cnn = New ADODB.Connection
   With cnn
     .Errors.Clear
     .ConnectionString = conCNNSTRING
     .Open
     .BeginTrans
     .Execute strSQL
     .CommitTrans
   End With
Exit_CnnExecute:
On Error Resume Next
   CnnExecute = isOK
   Exit Function
Err_CnnExecute:
   isOK = False
   If cnn.Errors.Count > 0 Then
     ErrMessage cnn.Errors(0), strSQL
     cnn.RollbackTrans
   Else
     MsgBox "プログラムエラーが発生しました。システム管理者に報告して下さい。(CnnExecute)", _
        vbExclamation, " 関数エラーメッセージ"
   End If
   Resume Exit_CnnExecute
End Function

Public Sub ErrMessage(ByVal CnnErrors As ADODB.Error, ByVal strSQL As String)
   MsgBox "ADOエラーが発生しましたので処理をキャンセルします。" & Chr$(13) & Chr$(13) & _
      "・Err.Description=" & CnnErrors.Description & Chr$(13) & _
      "・Err.Number=" & CnnErrors.Number & Chr$(13) & _
      "・SQL State=" & CnnErrors.SQLState & Chr$(13) & _
      "・SQL Text=" & strSQL, _
      vbExclamation, " ADO関数エラーメッセージ"
End Sub
    • good
    • 0
この回答へのお礼

良きアドバイス ありがとうございます。
たいへん 勉強になります。
早速ためしてみます。

お礼日時:2007/07/26 15:46

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qレコードセットの値 SelectとINSERT,UPDATE,Deleteで異なる?

VB6でSQL Server2005をADOでアクセスしていますが、基本的なことですが、SELECT文の場合はrs.closeしてもエラーになりませんが、INSERT,UPDATE,DELETEの場合は、rs.closeとすると、
実行時エラー3704
オブジェクトが閉じている場合は、操作は許可されません。
というエラーメッセージが表示されます。

SQLは以下のように実行しています。
Call rs.Open(cobSQL.Text, cn, adLockOptimistic)

VB6でSQL SERVER2005(もしくは2000)でデータベースアプリを作成するのに参考になる良書などご存知でしたら教えてください。

また、VB6でADOは、ネイティブにSQL Server2005にアクセスできるのでしょうか?まだADOやデータベースの概念が良くわかっていないため、質問自体がおかしいかもしれませんが、VB6で高速にSQL SERVER 2005で処理させたいのが私の現時点での目標です。

Aベストアンサー

更新系(UPDATE、INSERT、DELETE等)のSQLでは、
レコードセットは使用してはいけません。

レコードセットを使用するのは、参照のみです。
更新系は、コネクションオブジェクトのExcuteメソッドを使用します。
つまり、レコードセットは、開く必要はなく、閉じる必要もありません。
(例)
Cn.Execute "insert into テーブル名 (XX1,XX2,XX3)values(ZZ2,ZZ2,ZZ3)

ちなみに、VB6とSQLサーバーの動作イメージとしては、
以下1、2を参考程度に。

1参照の場合(往復)
(1)VB6 → SQL文投げる  → SQLサーバー
(2)VB6 ← レコード取得  ← SQLサーバー

2更新系の場合(片道)
(1)VB6 → SQL文投げる → SQLサーバー(更新)

参考URL:http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_s12.htm

QAccessのRefresh・Requery・Repaintの違い

Requeryはもう一度ソースレコード(テーブル)を読み込むようです。このとき、テーブルの先頭レコードに移動してしまいます。
Refreshは最新のレコード(テーブル)を再表示するような気がします。レコードの移動は起こらない気がします。
Repaintは、VBAでキャプションなどを変更したとき使っています。
でも、よくわかっていません。
どんなときにどんなメソッドを使えばいいのでしょうか?
詳しい方、よろしくお願いいたします。

Aベストアンサー

たびたびすみません。
調べてたらこんなのがでてきました。
http://www.nurs.or.jp/~ppoy/access/access/acF007.html

参考URL:http://www.nurs.or.jp/~ppoy/access/access/acF007.html

Q「Nullの使い方が不正です」のエラー

AccsessとVB間でデータの参照・登録・削除を行うプログラムを作成中です。
テキストボックスにデータを入力せずに更新するとAccess側はNull値が入るので、参照をした際に
「Nullの使い方が不正です」のエラーが表示されます。

Null値が表示可能ならその方法を教えてください。

Aベストアンサー

読み込んだ際にIsNull()で判断してみては?
If IsNull(Fields) Then
Text1.Text = ""
Else
Text1.Text = Fields
End If

QDoEvents関数って何?

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そこで「EXCEL VBA パーフェクトマスター」という本を見たら

for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
DoEvents
next i
unload userform1
と入力すれば解決することがわかりました。

しかし「DoEvents」についてあまり詳しく書いていなかったのでDoEvents関数をヘルプで見ると、
「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」

と書いてあるのですが正直、書いてあることがよくわかりません。

どなたかDoEvents関数について、
もう少しわかりやすく教えていただけませんか。
それから、最初に書いたコードで実行すると
ユーザーフォームの背景が真っ白になってしまう原因も
教えていただけませんか?

よろしくお願いいたします。

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そ...続きを読む

Aベストアンサー

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
    DoEvents
    Cells(i,1) = ""
  Next i
End Sub

Private Sub CommandButton2_Click()
  MsgBox "hoge"
End Sub

っていうフォームのコードがあった場合、
DoEvents を入れることによって、ループ中にユーザーがCommandButton2 を押すことによって CommandButton2 のクリック イベントも動いちゃいます。
CommandButton1 のクリック イベントではループの前に
CommandButton1.Enabled = False
CommandButton2.Enabled = False
を書いてフォーム上の CommandButton を無効にしておき、ループが終わったら
CommandButton1.Enabled = True
CommandButton2.Enabled = True
と書いて CommandButton を有効に戻してください。

これを工夫すれば、CommandButton2 で CommandButton1 のループを途中キャンセルする処理もすることができます。

Private Canceled As Boolean

Private Sub CommandButton1_Click()

  CommandButton2.Enabled = False

  Dim i As Long
  For i = 1 To 50000
    DoEvents

    If Canceled = True Then
      MsgBox "キャンセルしました"
      Exit Sub
    End If

    Cells(i, 1).Value = ""
  Next i
End Sub

Private CommandButton2_Click()
  Canceled = True
End Sub



コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。
コピペするなら行頭の全角スペースを半角スペースに直してください。

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
...続きを読む

QVBA オブジェクトが空かどうか判定する

皆様のお知恵を拝借させてください。

エクセルVBAでオブジェクトを入れる変数を定義し、その変数にオブジェクト
が入っているかどうか検査したいのですがどうしたらいいでしょうか。

例えば---
Dim a As Workbook
If a <> nothing then ←この部分が分からない。このままだとエラー。
処理
End if
---------
環境
エクセル2003
WinXPsp1

Aベストアンサー

もし、aが空だったら
If a Is Nothing Then 

もし、aが空じゃなかったら
If Not a Is Nothing Then

Qデータソース名および指定された既定のドライバが見つかりません。

データソース名および指定された既定のドライバが見つかりません。
オラクルに接続したのですが、上記のエラーが出て接続出来ません。
どなたか力を貸してください。

<環境>
WinXP
VS2005 Ver8.0.50727.42
Windowsアプリケーション
VB言語でオラクルに接続したいと思っています。

こちら(http://support.microsoft.com/kb/310985/ja)を参考に
オラクルに接続しようとしています。

Dim cn As OdbcConnection
cn = New OdbcConnection("Driver = {Microsoft ODBC for Oracle};" & _
"Data Source=ORA_TEST;uid=UID_TEST;pwd=PWD_TEST")

Try
cn.Open()
MsgBox("Connected")
Catch ex As Exception
MsgBox("NG")
Debug.Print(ex.Message, "Error") ←(A)
Finally
cn.Close()
End Try

(A)で「ERROR [IM002] [Microsoft][ODBC Driver Manager] データ ソース名および指定された既定のドライバが見つかりません。」

のメッセージが出ます。
VB2005の「ツール」-「サーバの接続」では接続確認が取れているのですが、
コードで書くとエラーになってします。

何か書き忘れているのでしょうか。。。
すみませんがよろしくお願いいたします。

データソース名および指定された既定のドライバが見つかりません。
オラクルに接続したのですが、上記のエラーが出て接続出来ません。
どなたか力を貸してください。

<環境>
WinXP
VS2005 Ver8.0.50727.42
Windowsアプリケーション
VB言語でオラクルに接続したいと思っています。

こちら(http://support.microsoft.com/kb/310985/ja)を参考に
オラクルに接続しようとしています。

Dim cn As OdbcConnection
cn = New OdbcConnection("Driver = {Microsoft ODBC for Oracle};" & _
...続きを読む

Aベストアンサー

>cn = New OdbcConnection("Driver = {Microsoft ODBC for Oracle};" & _
>"Data Source=ORA_TEST;uid=UID_TEST;pwd=PWD_TEST")

自分の環境に合わせないとね?????

これの意味はインポートしているんですよね? スクリプトはVBSの事ですかね。VBA? VBですよね?

Imports System.Data
Imports Microsoft.Data.ODBC


それと見るHPがちょこと違う。
http://msdn.microsoft.com/ja-jp/library/system.data.oracleclient.oraclelob.aspx

QEXCEL VBAで計算値を四捨五入、切り上げ、切捨てする方法

ネットで探してみたのですが、計算結果を四捨五入して特定のセルを
返すにはどうしたらいいのでしょうか?

Sub hokangosa()

Dim ZPS As Double
Dim ZPOS As Double
Dim DMN As Double
MsgBox (" >>> 補間誤差自動計算 <<< ")
MsgBox (" >>> 初期値入力します <<< ")
ZPS = InputBox(">>> ステップを入力してください<<<")
ZPOS = Sheet1.Cells(22, 4).Value
DMN = ZPOS / ZPS
Sheet1.Cells(23, 6).Value = DMN
End Sub

ここでDMNの値を四捨五入したいです。

またこれとは別に切上げ、切捨ても教えていただけるとありがたいです。

Aベストアンサー

DMN = Application.WorksheetFunction.Round(ZPOS / ZPS, 0)
で、四捨五入
DMN = Application.RoundDown(ZPOS / ZPS, 0)
で切り捨て
DMN = Application.RoundUp(ZPOS / ZPS, 0)
で切り上げです。

引数で、対象桁を変更できます。

QエクセルVBA 「On Error GoTo 0」について

「On Error GoTo 」ステートメントの意味は、だいたい理解しています。
「On Error GoTo 0」 ステートメントについて、ご教授お願いします。
参考書には「エラーのトラップ処理を無効にする」と載っていましたが、よくわかりません。
具体的にどのような使い方をするのか、簡単なコードで説明していただければ幸いです。
よろしくお願いします。

Aベストアンサー

#3の回答者ですが、コードのどこが原因か特定し、実行時エラーとして、そのエラーが不可避な場合において、On Error Resume Next を付けますから、On Error Goto ErrHandler よりも、扱い方が難しいです。当然、その部分だけの範囲を囲うので、On Error Goto 0 を入れると思いますし、今では、使う場面が限定されているはずです。

後はテキストを参考にしてください。当面、このようなコードが必要になることはないと思いますが。

Q実行時エラー 3265「要求された名前、または序数

ADOで
rs.Open strSQL, cn, adOpenKeyset, adLockOptimistic
を過ぎようとすると
実行時エラー 3265「要求された名前、または序数に対応する項目がコレクションに見つかりません」
になるのですが、
strSQLの文字列をクエリのSQLビューに張り付けると、問題なくクエリが表示されます。

だから、
存在しないフィールド名を指定した訳ではないのですが
なぜこの部分でエラーになるのでしょうか?

オブジェクトが閉じてないのかと思い、
rs.Close: Set rs = Nothing
をイミディエイトでやってみたら
オブジェクトが閉じている場合は、操作は許可されません。
になります。

Aベストアンサー

参照設定で、ADOにチェックがあり、かつ、DAOより上にありますか?

Qカレントレコードが無い事を判定させる方法

SQLを使ってmdb内のレコードセットを取得し、
無かったらエラーを返す、という処理を作成
する場合、カレントレコードが無い事を
判定するにはどうすれば良いでしょうか?
イメージは下記のような感じです。

レコードセット as DAO.Recordset

'レコードセット取得
 Set レコードセット = db.OpenRecordset(作成したSQL文)

'判定
If カレントレコード無 Then
MsgBox "エラーメッセージ"
Exit Sub
End If

Aベストアンサー

カレントレコード無は"レコードセット.RecordCount = 0"
で行けませんか?


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報