Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


351 / 500 ページ ←次へ | 前へ→

【6190】Re:Executeメソッドのヘルプより
発言  小僧  - 05/9/7(水) 10:26 -

引用なし
パスワード
   ▼たん さん:
こんにちは。

CurrntDB = Jet という事ではないんですね…。

DoEvent を入れると同期が取れるというのも今ひとつなんですが…。
・ツリー全体表示

【6189】Re:Executeメソッドのヘルプより
回答  たん  - 05/9/7(水) 10:17 -

引用なし
パスワード
   >DAO で Execute メソッドを使用した場合に非同期になるという
>ソースがどこを見てもみつからないです。
>(Docmd.RunSQL なら理解できるのですが)
>
>ご面倒だと思われますが何かそのような情報が記載されている
>サイトをご紹介頂けないでしょうか?

Executeメソッドのヘルプ(AC97)の最後に下記のような記述があります。
----
ODBCDirect ワークスペースでは、省略可能な定数 dbRunAsync を含む場合、
クエリーを非同期に実行します。
----

質問者の環境がわかっているわけではありませんが、上記が該当する可能性が
あると考え、発言しています。

答えになってますか?
・ツリー全体表示

【6188】Re:DoEventsの必要性?
発言  小僧  - 05/9/7(水) 10:00 -

引用なし
パスワード
   ▼たな さん、たんさん:
おはようございます。

ツリーの関係で一番下にレスしますね。


>各Executeメソッドが非同期で実行されている可能性があり、非同期実行によるリスクを
>避ける為に、DoEventsで制御していると思われます。

たん さんの仰っている上の発言がどうも理解できません。

DAO で Execute メソッドを使用した場合に非同期になるという
ソースがどこを見てもみつからないです。
(Docmd.RunSQL なら理解できるのですが)

また DoEvents を入れる事により同期が実現されるという記事も
まったく見つかりませんでした。

ご面倒だと思われますが何かそのような情報が記載されている
サイトをご紹介頂けないでしょうか?
・ツリー全体表示

【6187】Re:多分、必要
お礼  たな  - 05/9/7(水) 9:37 -

引用なし
パスワード
   ▼たん さん:

オーバーフローの件ありがとうございます。

いくつかある処理の中、1つが時々オーバーフローしてしまうそうなんです。

たんさんの御指摘通りまずは型指定がどうなっているかを調べるのと、
「オーバーフロー」で検索をかけて調べてみます。

お手数掛けてすみません。
・ツリー全体表示

【6186】Re:多分、必要
質問  たな  - 05/9/7(水) 9:31 -

引用なし
パスワード
   ▼たん さん:

もう一度じっくり読ませていただきました。
DoEventsというものは、ただ単に画面がフリーズしたようにならないという
ことではないんですね。

下記のソースで言いますと、

> CurrentDb.Execute "DELETE * FROM wrk1;" (1)
> DoEvents
>      
> (略)
> DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel8, _
>  "wrk1", strFileName, False, "", True (2)

(1)のあとにDoEventsがあると、(1)のDELETEが終了するまではその次に
処理が移らないということでしょうか。

逆にDoEventsを入れていないと、(1)のDELETEが終わる前に、
(2)の処理へ遷移するということになってしまうということでしょうか。

説明していただいている、非同期で実行されているかどうかにも
関わっていると思いますが、やはりDELETEが終わる前に
インポートをしてしまうのはよくないですね。

トランザクション化を考えてみます。
・ツリー全体表示

【6185】Re:多分、必要
回答  たん  - 05/9/7(水) 9:22 -

引用なし
パスワード
   >現在処理時間が遅いだけでなく、オーバーフローしてしまうらしいのです。

オーバーフローは単に、暗黙の型指定がおかしいからでは?

例えば処理対象のExcelシートが32768行以上ある場合、Accessの整数型は
32767がMAXなので、Iが暗黙の型指定で整数型なら、1行処理する事に、
I+1だけしれてば、当然オーバーフローです。

# この辺は「オーバーフロー」等の語句で調べれば、
# 何故オーバーフローエラーが出るのかという事でヘルプや掲示板でさんざん
# 出ると思います。(私から見ればFAQのレベルと思います。)
・ツリー全体表示

【6184】Re:多分、必要
発言  たな  - 05/9/7(水) 9:08 -

引用なし
パスワード
   ▼たん さん:

ソースの確認までしていただき、ありがとうございます。

自分も気になっていた点は、むやみにDoEventsを入れたのではなく、
意味があって、必要だから入れているのかどうかです。

たんさんの解説をよく読ませていただき、再度検討します。

現在処理時間が遅いだけでなく、オーバーフローしてしまうらしいのです。
DoEventsだけでなく、いろいろなものが潜んでいるかも知れないので、
もう一度、よく解析してみたいと思います。

ご指導ありがとうございます。
・ツリー全体表示

【6183】Re:DoEventsの必要性?
お礼  たな  - 05/9/7(水) 8:49 -

引用なし
パスワード
   ▼小僧 さん:

おはようございます。

回答ありがとうございます。

早速下記のソースを試させていただきました。

DoEvents、理解できたと思います。

DoEventsがある場合には、処理が見えるんですね。
そして実行中にボタンの操作も行えるという事ですね。

DoEventsをコメントアウトした時には、
最終結果だけが表示され、ボタンが押せない状態になっていました。

今回の解析中のものは、インポートやエクスポート処理実行中に、
ボタン操作を行い他のものも同時に実行させることはないと思うので、
(確認してみます。)
DoEventsをはずして処理の改善を行えそうです。

わかりやすい例で助かりました。

ありがとうございました。
・ツリー全体表示

【6182】Re:多分、必要
回答  たん  - 05/9/7(水) 8:39 -

引用なし
パスワード
   推測の部分もありますが、多分、こんな感じ?

各Executeメソッドが非同期で実行されている可能性があり、非同期実行によるリスクを
避ける為に、DoEventsで制御していると思われます。

-----
非同期:
非同期式クエリーもサポートします。クエリーを実行するときに、ほかの操作を始める前に
クエリーの実行が終了するのを待つ必要はありません。
-----

つまり、クエリー自体の処理件数、マシンスペックやネットワーク環境等に依存する可能性も
ありますが、

> CurrentDb.Execute "DELETE * FROM wrk1;" (1)
> DoEvents
>      
> (略)
> DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel8, _
>  "wrk1", strFileName, False, "", True (2)

という場合、DoEventsが無ければ、(1)が完了する前に、(2)が非同期で起動され、
最悪の場合、(2)で転送中のデータが(1)によって削除され、(2)終了時のデータに
整合が取れなくなる可能性があるということです。

> strSQL = "UPDATE wrk4 AS A INNER JOIN wrk3 AS B ON A.AName = B.AName "
> strSQL = strSQL & "SET B.ACode = A.ACode;"
>
> CurrentDb.Execute strSQL (3)
> DoEvents
>
> strSQL = "SELECT * FROM wrk1 WHERE F1 Is Null;"
> Set rs2 = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot) (4)

また、(3)でstrSQL変数に格納たものが実行されていますが、(4)の手前で
strSQLが更新されており、(3)の実行が完了していなければ、strSQL変数の
中身は整合が取れていない事になります。

# メモリの実行上は既に(3)で処理が動いているので、処理自体には問題が発生しないと
# 思われますが、私も所詮1ユーザなので、メモリ管理が内部でどう動いているかは
# 分かりません。

解決策としては、一連の処理をトランザクション化して、各SQL実行の同期を取るのが
良いと思われますが、具体的なルーチンは勘弁。
(BeginTrans等を使います。)

各SQLは前述したように、さまざまな環境に依存しますので、今回テストした時に、
DoEventsを外して早くなったので「外してOK」という判断は早計と思われます。

前任者はそういう非同期による処理異常をふせぐ事を踏まえ、DoEventsを各処理の
間に入れていると思われます。
(トランザクション化を知らなかった可能性もありますが。)
・ツリー全体表示

【6181】Re:SQLでも…
お礼  くま  - 05/9/6(火) 21:49 -

引用なし
パスワード
   ▼小僧 さん:
こんばんは。
遅くまで考えていただきありがとうございます。

>  CurrentDb.Execute strSQL, dbFailOnError

なるほど。
Executeを使うんですね。勉強になります。
たんさんに教えていただいたヘルプを見てsqlは書いたのですが、docmd.runsql を使って実行するのだと思っていたのでこけまくりでした。(私にはエラーの意味が理解できず諦めてしまいました。)


>「UNIQUE」を指定しても、複数フィールドだと無理でした。
>(単独だといけます。)

本当ですね。
結局は1indexを作る度に1命令が必要と
1命令でわさっとindexは作れないという事でしょうか。。。

どっちも似たり寄ったりなら
最初に教えていただいた方法で作りこみます。
.AllowZeroLengthの定義も出来ましたし。

本当に遅い時間までありがとうございます。
・ツリー全体表示

【6180】Re:DoEventsの必要性?
回答  小僧  - 05/9/6(火) 20:08 -

引用なし
パスワード
   ▼たな さん:
こんばんは。

>DoEventsの意味をはっきりわかっていないので、
>必要性がわかりません。これはやはり絶対必要なものなのでしょうか。

DoEvents はWindowsにいったん制御を返す命令です。
といっても実感が湧かないですよね。

適当にフォームを作成して、

テキストボックス:txtTest
コマンドボタン :実行

を配置。
実行ボタンのクリック時イベントに

Private Sub 実行_Click()
Dim I As Long
  For I = 1 To 1000
    'DoEvents
    Me.txtTest.Value = I
  Next
End Sub

と記述して実行…。結果を確認されたら、
今度は DoEvents のコメントを消して実行させてみて下さい。


>今悩んでいるのは、DoEventsを消してしまって良いものか、

ご提示されたコードの内容ですと必要がない様に見えますね。
通常、描画をするような処理に DoEvents を使うことが多いですね。
・ツリー全体表示

【6179】Re:SQLでも…
発言  小僧  - 05/9/6(火) 19:54 -

引用なし
パスワード
   ▼くま さん:
こんばんは。

>sql文のようにインデックスを連続で設定もできないのですね。
>「CREATE [ UNIQUE ] INDEX index
>ON table (field [ASC|DESC][, field [ASC|DESC], ...])
>[WITH { PRIMARY | DISALLOW NULL | IGNORE NULL }]」

うーん、SQL でも同じようですね。

Sub SQLで()
'要参照設定 Microsoft DAO x.x Object Library

Dim TName As String
Dim strSQL As String

  TName = "T_Branch"

  If DCount("*", "MSysObjects", "Name = '" & TName & "'") > 0 Then _
    DoCmd.DeleteObject acTable, TName

  strSQL = "CREATE TABLE " & TName & " ( " _
      & "Company Text, " _
      & "Branch Text, " _
      & "Post Text, " _
      & "Address Text);"
  
  CurrentDb.Execute strSQL, dbFailOnError

  strSQL = "CREATE UNIQUE INDEX idx1 " _
      & "ON " & TName & " ( Company, Branch) " _
      & "WITH PRIMARY;"
  
  CurrentDb.Execute strSQL, dbFailOnError

End Sub

「UNIQUE」を指定しても、複数フィールドだと無理でした。
(単独だといけます。)

とはいえ、TableDef オブジェクトだけでなく SQL でもいけそうですね。
・ツリー全体表示

【6178】Re:CreateIndexはステートメント
お礼  くま  - 05/9/6(火) 18:25 -

引用なし
パスワード
   ▼小僧 さん:
度々ありがとうございます。

>今のままですと鍵マークは付きますが、インデックス(重複あり)の設定が
>「なし」になってしまいませんでしょうか?

あっ!!本当だ。テストで見逃しました。

>面倒ですが3回に渡ってインデックスを付け直す必要があるようです。
鍵マークセットで1つ。1項目で更に1つ。とコーディングする必要があるのですね。。。

sql文のようにインデックスを連続で設定もできないのですね。
「CREATE [ UNIQUE ] INDEX index
ON table (field [ASC|DESC][, field [ASC|DESC], ...])
[WITH { PRIMARY | DISALLOW NULL | IGNORE NULL }]」

>>はぁ〜先は長い
>
>先が見えないよりは安心ですよ!
>(フォローになってない気も…)

そうですね。ありがとうございます。
修正して続きを頑張ります。
・ツリー全体表示

【6177】Re:CreateIndexはステートメント
発言  小僧  - 05/9/6(火) 18:04 -

引用なし
パスワード
   ▼くま さん:
こんにちは。


>Sub インデックスの作成(TName As String)

>なんとかこれでちゃんとindexが付いた確認まではとれたので
>あとはこれを少しづつ変形させて使わせていただきます。

[#6169]

で少し修正を加えたコードを提示しております。

今のままですと鍵マークは付きますが、インデックス(重複あり)の設定が
「なし」になってしまいませんでしょうか?

面倒ですが3回に渡ってインデックスを付け直す必要があるようです。


>はぁ〜先は長い

先が見えないよりは安心ですよ!
(フォローになってない気も…)
・ツリー全体表示

【6176】DoEventsの必要性?
質問  たな  - 05/9/6(火) 17:56 -

引用なし
パスワード
   はじめまして。AccessVBA初心者です。

現在、処理速度の改善を行う為、
他者が作成したコードを解析しています。
(Excelへのインポート・エクスポートなどを行っている処理。)

その中で気になったのが、DoEventsです。

DoEventsの意味をはっきりわかっていないので、
必要性がわかりません。これはやはり絶対必要なものなのでしょうか。

以下に、解析中のソースの一部を記載します。

********************************************* 
  With rs
    Do Until .EOF
      strFileName = txtFolder & !FileName
      
      CurrentDb.Execute "DELETE * FROM wrk1;"
      DoEvents
      
      CurrentDb.Execute "DELETE * FROM wrk2;"
      DoEvents
      
      DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel8, "wrk1", strFileName, False, "", True
      DoEvents
      
      FUC_DropTable "Sheet1$_インポート エラー"
      DoEvents
      
      CurrentDb.Execute "DELETE * FROM wrk1 WHERE F1 = '2';"
      DoEvents
      
      strSQL = "SELECT F1 FROM wrk1 WHERE (F2 Is Null AND F5 Is Null);"
      Set rs2 = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
      
      Do Until rs2.EOF
        CurrentDb.Execute "INSERT INTO wrk3 ( AName ) VALUES ( '" & rs2!F1 & "' );"
        DoEvents
        
        strAName = rs2!F1
        rs2.MoveNext
        If rs2.EOF Then Exit Do
        DoEvents
      Loop
      
      rs2.Close
      
      strSQL = "UPDATE wrk4 AS A INNER JOIN wrk3 AS B ON A.AName = B.AName "
      strSQL = strSQL & "SET B.ACode = A.ACode;"
      
      CurrentDb.Execute strSQL
      DoEvents
      
      strSQL = "SELECT * FROM wrk1 WHERE F1 Is Null;"
      Set rs2 = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
      
      Do Until rs2.EOF
        For i = 0 To intMAX - 1
          If Not IsNull(rs2.Fields(i + 1)) And Len(Trim(rs2.Fields(i + 1))) <> 0 Then
            strSQL = "INSERT INTO wrk2 ( ID, ProductCode ) "
            strSQL = strSQL & "VALUES ( " & i + 1 & ", '" & rs2.Fields(i + 1) & "' );"
            
            CurrentDb.Execute strSQL
            DoEvents
          End If
          
          If i >= 4 And (IsNull(rs2.Fields(i + 1)) Or Len(Trim(rs2.Fields(i + 1))) = 0) Then Exit For
        Next i
        
        rs2.MoveNext
        If rs2.EOF Then Exit Do
        DoEvents
      Loop
*********************************************

上記は本当に一部を抜粋したものなのですが、
異様にDoEventsが多いようです。

DoEventsありのまま実行すると、処理時間が約17分。
DoEventsを全てコメントアウトすると、処理時間が約3分になりました。

今悩んでいるのは、DoEventsを消してしまって良いものか、
消しても問題がないものかの説明があまりつかないことです。

上記処理にて、DoEventsを取ってしまっても(必要な箇所があれば残す)
問題ないでしょうか。

逆にここには必要だという箇所があれば、アドバイス頂ければ幸いです。

すみませんが、回答お願い致します。
・ツリー全体表示

【6175】Re:CreateIndexはステートメント
お礼  くま  - 05/9/6(火) 17:46 -

引用なし
パスワード
   ▼小僧 さん:
返信をありがとうございます。

せっかくいただいたモジュールがまとまっているのでそのまま使えるように
こちらで使わせていただこうと思います。
>・Call テーブルの作成2 のようにCall ステートメントで呼び出す

>提示させて頂いたコードについても、他のコード(恐らくCSVファイルの取込がありそうですね)

そうなのです。
それにテーブルの.Sizeや.AllowZeroLengthも必要なのでまだまだ頑張ります。
.CreateField(項目名, dbDate)
この書き方だと設定できないのですよねー。
またヘルプと格闘です。

>との連携についてでも、当方で回答できる限りお付き合いさせて頂きますよ。
いつもいつもありがとうございます。
たんさんにもご指摘いただいたのでまず自分で努力してみますね。
私の頭ではどうにもならなくなったら申し訳ありませんがまた宜しくお願い致します。

他にも5テーブルを作成しなくてはいけないけど、indexは3テーブルのみ必要なのでいただいたサンプルを分割して使おうと悪戦苦闘しています。
そのあとデータをcsvから入れて・・・(はぁ〜先は長い)

Sub テーブルの作成2()
'要参照設定 Microsoft DAO x.x Object Library
Dim MakeTBL As DAO.TableDef
Dim TName As String

  TName = "T_Branch"

  If DCount("*", "MSysObjects", "Name = '" & TName & "'") > 0 Then _
    DoCmd.DeleteObject acTable, TName

  Set MakeTBL = CurrentDb.CreateTableDef(TName)
  With MakeTBL
    .Fields.Append .CreateField("Company", dbText)
    .Fields.Append .CreateField("Branch", dbText)
    .Fields.Append .CreateField("Post", dbText)
    .Fields.Append .CreateField("Address", dbText)
  End With
  CurrentDb.TableDefs.Append MakeTBL
  Set MakeTBL = Nothing
  
  Select Case Left(UCase(TName), 1)
      Case "T", "M" 'トランとマスタ
        Call インデックスの作成(TName)
      Case "W"   'ワーク
      Case Else
        MsgBox "そんなテーブル聞いてない!!"
  End Select
End Sub

Sub インデックスの作成(TName As String)
Dim MyDb  As Database
Dim MakeTBL As DAO.TableDef
Dim Idx As DAO.Index

  Set MyDb = CurrentDb
  Set MakeTBL = MyDb.TableDefs(TName)
  Set Idx = MakeTBL.CreateIndex("Ind1")
  With Idx
    .Fields.Append .CreateField("Company")
    .Fields.Append .CreateField("Branch")
    .Primary = True
  End With
  MakeTBL.Indexes.Append Idx
  MakeTBL.Indexes.Refresh

  CurrentDb.TableDefs.Refresh

  Set MakeTBL = Nothing
  Set Idx = Nothing

End Sub


なんとかこれでちゃんとindexが付いた確認まではとれたので
あとはこれを少しづつ変形させて使わせていただきます。

ありがとうございました。
・ツリー全体表示

【6174】Re:CreateIndexはステートメント
回答  小僧  - 05/9/6(火) 17:07 -

引用なし
パスワード
   ▼くま さん:
こんにちは。

>モジュールのどのタイミングで入れないと駄目なのか不明で、


提示させて頂いたコードを新規モジュールにでも貼り付けて頂いて、

・ツールバーの「実行」から実行させる
・Call テーブルの作成2 のようにCall ステートメントで呼び出す

のどちらかで可能ですね。


後はくま さん次第です。
提示させて頂いたコードについても、他のコード(恐らくCSVファイルの取込がありそうですね)
との連携についてでも、当方で回答できる限りお付き合いさせて頂きますよ。
・ツリー全体表示

【6173】Re:CreateIndexの例
お礼  くま  - 05/9/6(火) 16:48 -

引用なし
パスワード
   ▼小僧 さん:
>訂正版です。
>ちょっとコード的には汚いですが…。

とんでもありません。
小僧 さん いつも返信をいただきましてありがとうございます。

>これで2つのフィールドを主キーに、
>重複ありのインデックスが設定されると思います。

たんさんのアドバイスで私がヘルプと格闘している間に
気が付けばアドバイスが追加されていて。皆様に感謝しています。

早速使わせていただきましたところ、
私がイメージしていた形で出来上がっています。完璧です。
本当にいろいろとありがとうございました。
(なんせこれで3日も悩んでいたもので、やっと先に進めます)
・ツリー全体表示

【6172】Re:CreateIndexはステートメント
お礼  くま  - 05/9/6(火) 16:40 -

引用なし
パスワード
   ▼たん さん:
>ちなみにこの2件。
>
>http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=5943;id=access
>
>http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=1657;id=

たんさん ご丁寧にアドレスまでありがとうございました。

>ただ、私は貴方がどこまで調べているのかは文面からは分かりませんし、
>この文章は貴方だけが読むものではありません。

確かにそうですね。質問が言葉足らずでした。
こちらのページも以前他の探し物の時に拝見しました。
熱い内容だなと思って読んでいたのに自分もやってしまいました。済みません。

>ちなみに、私のAC2000のヘルプでは、質問より「CREATE」で検索し、
>「CREATE INDEX ステートメントの使用例」というのがきちんとあります。
>上記のようにきちんと調べれば(例も含め)見つかるものに対して、
>見つからないと言われるのは非常に残念です。

こちらも仰る通りに探してみました。
「CREATE INDEX」で私が検索したのはVBAモジュール側のヘルプでやはり出ませんでしたが、Accessデータベース側のヘルプを使ってみたら出ました。
私の検索方法が下手なだけでした。
「CREATE INDEX ステートメントの使用例」迄記載していただきありがとうございました。

ですが、例を見ても私にはうまく理解して使う事ができませんでした。
文法はわかりましたが、モジュールのどのタイミングで入れないと駄目なのか不明で、docmd.runsql で実行してみたり、色々試しましたが私の頭はついていけてないようです。
せっかくアドバイスいただいたのに済みませんでした。

返信をいただいてから試行錯誤していたので、お礼が遅れまして申し訳ありませんでした。これからも宜しくお願いします。
・ツリー全体表示

【6171】Re:CreateIndexはステートメント
発言  たん  - 05/9/6(火) 14:35 -

引用なし
パスワード
   ちなみにこの2件。

http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=5943;id=access

http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=1657;id=
・ツリー全体表示

351 / 500 ページ ←次へ | 前へ→
ページ:  ┃  記事番号:
1084717
(SS)C-BOARD v3.8 is Free