- ベストアンサー
Visual BasicのProgressBerの設定方法
mdbファイルにADOで接続して、テーブルのデータを他のmdbファイルのテーブルにINSERT INTO句で追加するプログラムを作成しました。ところがデータが多くて処理に数分を要することもあり、ユーザーがフリーズしたものと思って、強制終了してしまうという事態が度々あって困っています。 そこで、ProgressBerの追加を検討しているのですが、インターネットやヘルプでいろいろ調べても設定方法がわかりません。よいアドバイスを頂けないでしょうか?
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
プログレスバーの方法はだいたい以下の様でいかがでしょうか? (temtecomai さんの方法に追加した状態です) ProgressBar1.Max = rsr1.RecordCount Do Until rst1.EOF rst2.AddNew rst2.Fields("苗字").Value=rst1.Fields("苗字").Value rst2.Fields("名前").Value=rst1.Fields("名前").Value rst2.Fields("生年月日").Value=rst1.Fields("生年月日").Value rst2.Update ProgressBar1.Value = ProgressBar1.Value + 1 Loop レコード件数ですが、 データベースへのアクセスに、ADO を使う場合は、これで取得できますが、 DAO の場合、レコードセットの開きかたによって、これでは取得できません。 このあたりは、ヘルプを参考に、試行錯誤してみて下さい。 また、プログレスバーの表示についてですが、普通は何もしなくても自動的に更新されます。(と思っています...) もしかすると、Hawk-W さんがおっしゃているようになっているのかもしれません。この場合、ProgressBar1.Refresh を Value を変更した後に実行してみて下さい。これで、再描画されると思います。(バージョンによって、このメソッドが無い場合があります。その場合は、Form1.Refresh のように、して下さい) DoEvents だと、システムに制御が戻るため、例えばボタンなどを押せないようにとか、ウィンドウを閉じないようにとか、いろいろとコーディングの追加が必要かと思います。(ただ個人的には、大変ですがこちらの利用をお勧めします。) 時間が許せば、2つとも試してみて、違いをぜひ体験してみて下さい。
その他の回答 (7)
どの様なコードでやっているのか分かりませんが、もしやっていたら御免なさい。 画面に変化が現れたのを更新する場合、そのままだと、処理がコードの内部でループしているので、画面が更新されません。画面を更新するには、一回システムに制御を戻す必要があります。 その場合には DoEvents をValueの更新後に置いてみてください。 objRecordset.AddNew ... ProgressBar1.Value = ProgressBar1.Value + 1 DoEvents こんな感じ?
お礼
どうもありがとうございました。 Value値の設定は、Loopを一回実行するたびに1増えていくということでいいのですね。実はとても難しく考えていました。現在のカレントレコードの位置を取得して、Max値の何パーセント終了して・・・・みたいなのを考えていました。 みなさんのおかげで、悲願のプログレスバーを設定することができました。 本当にありがとうございました。
- clavia
- ベストアンサー率50% (5/10)
「INSERT INTO」では、データベースエンジンから、VB に進行状況は教えてもらえないので、ProgressBar は無理かと思います。 「AddNew」なら、1件1件新規追加して行くので可能です。 ところで、処理時間が5分の1でも、元々数分かかっていたのでしたら、2、30秒はかかるので、進行状況は表示した方がいいのではと思います。ユーザーさんも状況がわかった方が安心されると思います。
補足
急に長期出張に出ることになり、今まで確認できませんでした。 返事が遅くなり申し訳ありません。 そうですよね。楽しいことをしていての2~30秒は短いかもしれませんが、動かないパソコンの画面を眺めていての2~30秒はとても長いですよね。 ということで、やはりプログレスバーを配置したいと思います。 そこで、下のTemtecomaiさんの例にならっていろいろやってみたところ、データの追加についてはAddNewメソッドで追加できるようになりました。しかし、Value値の設定が悪いのかどうか、プログレスバーがうまく進行してくれません。下の例でいうとValue値をどのように設定すればよいのでしょうか? よろしくお願いします。
ADOのレコードセット(更新可能なもの)のAddNewメソッドを実行するとカレントレコードが新規レコードに移動します。 Do Until rst1.EOF rst2.AddNew rst2.Fields("苗字").Value=rst1.Fields("苗字").Value rst2.Fields("名前").Value=rst1.Fields("名前").Value rst2.Fields("生年月日").Value=rst1.Fields("生年月日").Value rst2.Update Loop ちょっと手元にAccessがないので自信ないですが、おおむねこんな感じだったと思います(^_^;; 詳しくはヘルプを見てください。 追加するレコードセットをrst1とします。(読取専用でOK) 追加される側のレコードセットをrst2とします。(追加可能なセットで開く) rst1の最終レコードまでループします。 その中で、rst2をAddNewすると、rst2のカレントレコードが新規レコードに移動します。 そしてrst2の各フィールドに対してrst1の値を入力していく。必要な全てのフィールドに対して行ないます。 rst2の新規レコードは「浮いた状態」なので、Updateメソッドを行なうとrst2に追加更新されます。
お礼
みなさんのお陰で、プログレスバーを上手く設定することができました。 ありがとうございました。
補足
急に長期出張に出ることになり、今まで確認できませんでした。 返事が遅くなり申し訳ありません。 AddNewメソッドでのデータの追加うまくいきました。 ところで、プログレスバーの設置はあきらめようかと思っていたのですが、せっかくLoopを使うのだから、また、上のclaviaさんのご回答でも指摘されたように、やはりプログレスバーを検討しています。そこでいろいろやってみたのですが、Value値の設定が悪いのかどうか、プログレスバーがうまく進行してくれません。この例でいうとValue値をどのように設定すればよいのでしょうか? よろしくお願いします。
>私的にはrs.RecordCountで行数を取得できるのではないかと考えているのですが、いかがでしょうか? そのとおりです。MaxにRecordCountを代入すればよいと思います。 >今書いているコードはSQLで一度にデータ全てをINSERTする様に記述しています。 はふ。それでは、ちょっと出来ないですね。 対策方法としては、10回くらい更新したら、それで一旦戻ってきてValueを増やすとか、もしくは、temtecomaiさんに言う方法ならば一回ずつ戻ってこられますね。 戻ってきた時にValueを変更すればよいわけです。
補足
急に長期出張に出ることになり、今まで確認できませんでした。 返事が遅くなり申し訳ありません。 INSERT INTOではプログレスバーの配置は無理なようなので、Loopでやりたいと思います。そこでTemtecomaiさんの例でLoopさせ、データの追加ができるようになりました。ところがValue値の設定が悪いのかどうか、プログレスバーがうまく進行してくれません。temtecomaiの例でいうとValue値をどのように設定すればよいのでしょうか? よろしくお願いします。
視覚的な手法は#1さん、#2さんのどちらも有効なので、私は別の書き込みを。 アクションクエリーであるINSERT INTO句とADOレコードセットのAddNewはどちらが速いのか。 参考URLによると相手がAccessデータベースならAddNewの方が5倍以上速い、と書いてあります。 ご参考まで。 # 話は戻りますが、#1さんと#2さんの方法を使用するとして、Max値とカレント値のとり方はご存知ですよね? まぁループで処理してるんでしょうから余計なお世話か(^_^;;
補足
ご回答ありがとうございます。 私はVB超初心者でして、ループ処理とかがよくわかりません。 >参考URLによると相手がAccessデータベースなら >AddNewの方が5倍以上速い、と書いてあります。 実は以前インターネットでいろいろ調べているときにこれと同じような記述を見つけ、Addnewを試したことがあるのですが、よく分からなくて結局INSERT INTO句を採用したという経緯があります。 今書いているコードは cn.Execute "INSERT INTO テーブル1 SELECT * FROM テーブル1 IN '' [ms access;database=C:\DB\sample.mdb;PWD="password"] " というもので外部データベースのテーブルからデータを追加するというものです。 この処理をもしAddnewメソッドに書き換えることで、処理時間を5分の1以下に短縮できるのであれば、とくにプログレスバーは必要ないので、Addnewを採用したいのですが、コードの記述法がよくわかりません。よいアドバイスをお願いできないでしょうか?
- imogasi
- ベストアンサー率27% (4737/17069)
100%完了(Max)の幅のラベルコントロール(a)をフォームに貼りつけ、同じ高さのもう一つのラベルコントロール(b)を左端を重ねて固定し、何かの事象に関連させて、右へ幅を増やして行き、右辺を徐々に右へ動かす。Bの背景色は、a(例えば白色)とは別色にして目立つようにする。こう言う方法を本で読んだ記憶があります。
補足
ご回答ありがとうございます。 >何かの事象に関連させて、右へ幅を増やして行き、右辺を徐々に右へ動かす 何らかの事象に関連させる方法がわかりません。 よいアドバイスをお願いします。
MSDNは持っていませんか? また、インターネットのMSDNにもありそうですが調べてみてください。 簡単な使い方というと、 ProgressBar.Minと ProgressBar.Maxを指定して、 ProgressBar.Valueで値を変更します。 例えば、質問の例では、 Insertする行数をMaxにして Minを0にします。 そして、一つのInsertをした時に、Valueを+1すれば、動いていく様に出来ると思います。
補足
ご回答ありがとうございます。 実はVBの初心者なものでして、その先がよくわかりません。 Maxの行数はどの様に取得するのですか?私的にはrs.RecordCountで行数を取得できるのではないかと考えているのですが、いかがでしょうか? また、Maxを設定したとして、Valueの値はどの様にすればよいのですか? 今書いているコードはSQLで一度にデータ全てをINSERTする様に記述しています。 よろしくお願いします。
お礼
どうもありがとうございました。 みなさんのお陰で、データ追加にかかる処理時間も短縮され(たような気がする)ましたし、プログレスバーの設定も上手くいきました。 結局次のように記述しました。 ProgressBar1.Visible = True ProgressBar1.Value = 0 ProgressBar1.Max = rst1.RecordCount rst1.MoveFirst Do Until rst1.EOF rst2.AddNew rst2.Fields("苗字").Value=rst1.Fields("苗字").Value rst2.Fields("名前").Value=rst1.Fields("名前").Value rst2.Fields("生年月日").Value=rst1.Fields("生年月日").Value rst2.Update rst1.MoveNext ProgressBar1.Value = ProgressBar1.Value + 1 Loop これで上手くいきました。 ありがとうございました。