• ベストアンサー

ループの途中でユーザーからの入力を受け付けるには?

VBのVer.5.0です。 まったくの初心者なのでどなたか教えて下さい。 CSVファイルをEOFまで1件ずつ読み込んで、ある条件に該当したレコードの場合に、フォーム上で修正するようにしたいと思っています。 ループの途中でいったん手続きを中断し、ユーザーからの入力を受け付けるようにするにはどんな命令があるでしょうか。 SetFocusだけではフォーカスが移動するだけで入力できないまま次のレコードの読み込みへと手続きが流れてしまいます。 いったん全レコードを読み込んで変数の配列に格納してから処理するしかないのでしょうか。 以前はCOBOLのプログラミングをしていましたが、項目の入力を受け付けるのは、Acceptという命令でした。 VBでこれに該当するコマンドが何なのか知りたいと思っています。 検索してもどうしても見つけられませんでしたので、よろしくお願いします。

noname#236498
noname#236498

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

こちらこそレスが遅くてすいません。 現在、24h稼動のシステムサポート業務のため、シフト勤務をしていて、何も無ければ即座に対応できるのですが。。。。 アクセスでCSVを作成しているのですね?どのようなデータの内容かわかりませんが、、、 ------------------------------- ※例1 アクセスからのエクスポート時に 形式:「区切り記号付き」 フィールド区切り文字:「カンマ」 テキスト区切り記号:「"」 ------------------------------- としている場合 「数字,"文字列","文字列",数字,数字・・・」 となると思います。 .今回扱うファイルにはレコードによって値がセットされていないフィールド 未設定値項目が存在していれば、単にカンマが連続出力されるだけです。 「数字,,"文字列",,数字・・・」 質問者さんの場合、フィールドの数だけ変数を用意し、読み取る形式で行われているようですね。 この場合、数値項目が未設定値(Nullと言います)で、読み取る変数も数値型であれば、型の不一致でエラーになります。 CSVは所詮テキストなので、型など制約なくデータが存在します。 「絶対に数値項目にNull値は無い」という自信が無ければ、全て文字列として受け取りましょう。 ------------------------------- ※例2 アクセスからのエクスポート時に 形式:「区切り記号付き」 フィールド区切り文字:「タブ」 テキスト区切り記号:「{なし}」 ------------------------------- としている場合 「数字≪Tab≫文字列≪Tab≫文字列≪Tab≫数字≪Tab≫数字・・・」 となります。 テキスト区切り記号を利用していなければ、前回書いた案の、「一気に読む」方式が利用できます。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sub Main()   Dim l_strCSVファイル  As String   Dim l_strバッファ    As String      Dim l_var改行      As Variant   Dim l_var項目      As Variant   Dim l_lng改行ループ   As Long   Dim l_lng項目ループ   As Long      l_strCSVファイル = "c:\データ.txt"      If Not ファイル_読む(l_strCSVファイル, l_strバッファ) Then     Exit Sub   End If      'レコード分割(改行での分割)   l_var改行 = Split(l_strバッファ, vbCrLf)   For l_lng改行ループ = 0 To UBound(l_var改行)          'フィールド分割(TAB区切りでの分割)     l_var項目 = Split(l_var改行(l_lng改行ループ), vbTab)          For l_lng項目ループ = 0 To UBound(l_var項目)       Debug.Print l_var項目(l_lng項目ループ),     Next l_lng項目ループ            Debug.Print        Next l_lng改行ループ End Sub Function ファイル_読む( _      ByVal p_strファイル名 As String _     , Optional ByRef p_strバッファ As String = "" _ ) As Boolean   Dim l_bln結果    As Boolean   Dim l_intFileNo   As Integer   Dim l_lngサイズ   As Long   Dim l_strバッファ  As String      l_bln結果 = False      'ファイルが無い   If (Dir(p_strファイル名) = "") Then     GoTo PGMEND   End If      'サイズを得る   l_lngサイズ = FileLen(p_strファイル名)      'ファイルが空っぽ   If (l_lngサイズ < 1) Then     GoTo PGMEND   End If      '領域確保   l_strバッファ = String$(l_lngサイズ, vbNullChar)      '読む   l_intFileNo = FreeFile   Open p_strファイル名 For Binary As #l_intFileNo     Get #l_intFileNo, , l_strバッファ   Close #l_intFileNo      l_bln結果 = True    PGMEND:   p_strバッファ = l_strバッファ      ファイル_読む = l_bln結果 End Function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ もし一度に全部読む処理 Open p_strファイル名 For Binary As #l_intFileNo   Get #l_intFileNo, , l_strバッファ Close #l_intFileNo がメモリを使用しすぎるのであれば、バイナリ形式で読むのではなく、質問者さんが行っている方式で「Line Input」を利用すると良いです。 一行ずつ読み取り、項目数で配列化させる方式です。 Dim l_var項目      As Variant Open p_strファイル名 For Input As #l_intFileNo   Do Until EOF(l_intFileNo)     Line Input #l_intFileNo, l_strバッファ     l_var項目 = Split(l_strバッファ, vbTab)     'l_var項目の利用方法は、上記サンプルから理解してください   Loop Close #l_intFileNo >Excelで開くと云々 については、データを公開してもらえないとよくわかりませんが、書式を持たないテキストデータをExcelに読み込むと、型を勝手に決めて値を書き換えることはあります。 Excelでのテキストデータ操作は、あまりしない方が好ましいでしょう。

noname#236498
質問者

お礼

重ねてのご回答ありがとうございます。 お忙しいところを私のような初心者の為に多くのお時間を割いてご丁寧にご説明していただき、とても感激しております。 今回の場合は、Line Inputで読み込んでいるのですが、ご説明のお陰でACCESSでの保存形式によって一度に読み込む方法も選択できることが分かり、こちらも必ず試してどちらの方が処理に適しているか検証させていただくつもりです。 コーディングまでして見本を示していただきまして、本当にありがとうございます。 実はプログラミングを職場で、質問を自宅からしておりまして、今すぐに教えていただいたことを実行できないのですが、月曜日にまず、ループの途中で入力させるために別フォームを表示させるプログラムを完成させ、それから一度に読み込むプログラムを別途、同じ処理内容で作成してみます。 自宅からのため具体例を挙げずに言葉だけの質問になってしまい、とても申し訳ありません。 実際に試してみてまた質問させていただくかも知れませんが、お時間のあるときで構いませんので、またご指導いただければ幸いです。 ご親切にありがとうございます。

その他の回答 (3)

回答No.3

>Accept InputBoxが近いかも? Dim strRet strRet = InputBox("入力を促す文言", "たいとる", "規定値") MsgBox strRet 欠点はキャンセルと、空文字の違いがわからないこと。。。 なので、オリジナルで入力フォームを用意して、ループの中に入力したいタイミングでそのフォームをモーダル表示してあげれたら、Acceptに近いと思います。 ところでCSVはカンマ区切りですか? サイズは結構大きいですか? というのは、バイナリオープンで回さずに一度で読み取れる方法あります。 回さないで済むので、かなり高速ですが、CSVがあまりに大きいと、メモリの消費が激しいです。 私の場合は、 ・ファイルサイズがあまり大きい物ではない ・区切り文字が本文に必ず使用されていない という状態であれば、一度に読み取り、Split関数を利用して配列に分割します。 ファイルの排他制御を考慮しなくてよくなるので、処理が簡潔になります。

noname#236498
質問者

お礼

ご丁寧な回答ありがとうございます。 すぐに回答してくださったのに、お礼が遅れて大変申し訳ありません。 実は質問した翌日から体調不良で自宅におり、教えていただいた方法が試せていないのですが、入力用の別フォームを用意するやり方を試してみるつもりです。 まだ最近VBを始めたばかりでCOBOLとの違いに戸惑うことばかりの状態です。 別途、追加の質問もさせていただきますので、お時間がありましたら引き続きご指導いただければ幸いです。

noname#236498
質問者

補足

ご回答ありがとうございます。 CSVはカンマ区切りで、15000~20000件くらいのデータ量です。 今回の処理で使用するのは、元がTEXT形式なのをACCESSで加工してCSV形式にしたものです。 ふと思いましたが、同じCSVでもいったんEXCELで開いて保存したものだと項目の区切られ方が異なるのでしょうか? 読み込み方法についてなのですが、 (1)Input #intFF, X(1), X(2), X(3), X(4), X(5)    カンマ区切りで1件に5項目あるデータを読み込む場合・・・ (2)Line Input #intFF, strREC 1件の項目数が不定の場合はこの方法でカンマ位置を自分で探す・・・ ということらしいのですが、今回扱うファイルにはレコードによって値がセットされていないフィールド(FILLER)が含まれている場合があります。 その場合でも、カンマで区切られてさえいれば項目数が特定されているものとして(1)の方法で読み込めるのでしょうか。 そのとき、その項目にはどんな値(16進数)がセットされるのでしょうか。 というのも、あとで別のレコードと値が完全一致しているかどうか比較しているのですが、画面上では見た目が同じなのに不一致データとして認識されてしまう場合があるのです。 お時間がありましたら引き続きご指導いただければ幸いです。

  • herencia
  • ベストアンサー率56% (120/211)
回答No.2

DoEvevntsとともにSleepやTimerを使うと動作がスムーズになるかと思います。 .Netだとスレッドが使えるんですけどね。

参考URL:
http://www.yuushirai.jp/shirai/Vb4/Vb42main.html
noname#236498
質問者

お礼

ご回答ありがとうございます。 すぐに回答してくださったのに、お礼が遅れて大変申し訳ありません。 DoEvevntsは使っていたのですが、Timerは併用していませんでした。 ご指摘の通り動作があまりスムースではなかったので、教えていただいた方法も組み込んでみます。 全くの初心者ですので、大変助かりました。ありがとうございました。

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.1

処理ループの開始に先立ち「実行中」フォームを表示させる。 そのフォームに「キャンセル」ボタンを作成して、クリックイベントでは「キャンセルフラグ」をONにする。 一方処理ループのどこかに、キャンセルフラグの状態を判断させる箇所を作り、必要に応じてループを抜け出す。 ここで「DoEvevnts」を記述しないと、ループが走りっぱなしになる。 ということでキーワード「Visual Basic ループ キャンセル DoEvents -.net」でぐぐってみてください。 大半のサンプルは「帳票打ち出しのキャンセル」ですが、 いろいろ見つかります。

noname#236498
質問者

お礼

ご回答ありがとうございます。 すぐに回答してくださったのに、お礼が遅れて大変申し訳ありません。 ユーザーに判断させてボタンをクリックさせなくても強制的に入力待ちにする状態にできないものかと思っていたのですが、フラグを立ててループを抜けるか、条件に一致した場合に別フォームを表示させて入力させるかしかないようですね。 教えていただいたキーワードで検索したところ、入力に関する処理の仕方や、フォームのちらつきを防止する方法などが見つかりました。 初心者ですので大変助かりました。ありがとうございました。

関連するQ&A

  • COBOLの入力チェックについて

    COBOL初心者です。 コンソールから入力した文字列の桁数チェックをしたいのですが、どのようにコーディングすればよいですか? ACCEPT命令を使ってコンソールから入力しています。 是非よろしくお願いします。

  • CSV形式のファイルを読み込んでテーブルに格納するには?

    VB6でCSV形式のファイルを読み込んで それをデータベースに書き込みたいのですがどうやれば いいか分かりません・・・。 1レコードが1行に書かれている固定長のレコードなら 1行ずつ読み込んでそれをループさせてEOFになるまで という風に読みこんでいたのですが、 CSVの場合はどのようにすればよいのでしょうか? 基本的には同じような考えのような気がするのですが。 プログラミング初心者ですみません。 どなたか分かりやすいサンプルなど教えてもらえませんでしょうか?

  • テキストボックスの入力チェック(ACCESS VBA)

    テキストボックスに何かを入力し、フォーカスが他のものに移動したときに、LostFocusイベントで入力内容のチェックをかけています。(文字数チェック、ストアドをつかって入力内容と一致するものがDBにあるかなど) もし、入力が誤っている場合には他のものにフォーカスを移さず、そのテキストボックスにフォーカスを残したい(setfocusを使用)のですが、setfocusをしてもlostfocusされてしまうため、うまくいきません。 VBではValidateイベントというものがあるようですが、 VBAではみあたりません。 どなたかよい方法をご存知でしたら教えてください。

  • 命令を変数に応じて変化させるには?

    「テーブル1」というテーブルの「データ」というフィールドにA~Jまで10個データが格納されていたとします。 このデータを変数 DATA01~DATA10 にそれぞれ格納したいと思っています。 下記ソースでは、レコードの終端までループしても、DATA01に「テーブル1」の1レコード目の値、"A"しか格納できませんが、これをDATA02に"B",DATA03に"C"・・・と順々に格納するにはどうしたら良いのでしょうか? それぞれの変数に応じた命令を一つ一つ書くのではなく、Countの値に応じて命令そのものを変化させて行いたいと思っています。他の言語ではわかるのですが、VBではどうするのかわかりません。 ご指導程お願い致します。 Private Sub テスト_Click()   Set DB = CurrentDb   Set RS = DB.OpenRecordset("テーブル1")   Count = 1   Do Until RS.EOF    DATA01 = RS!データ    RS.MoveNext    Count = Count + 1   Loop   End Sub

  • ダブルコーテーション付き文字列をファイルから読み込むには

    お世話になります。 ホストから出力されたファイルをVBで読込みたいのですが、文字列の中に「":ダブルコーテーション」が含まれます。 VBでopenすると2番目の「":ダブルコーテーション」で切れてしまい、EOFでループすると1レコードで何回もループしてしまします。 対処法等ありましたらご教授ください。 よろしくお願いします。

  • ADO.NETのSqlDataReaderをADOのRecordSetのように使いたい

    いつもお世話になっております。 SqlDataReaderについての質問なのですが、ADOでのレコードセットであった、EOFプロパティ(それに該当するものも)が見当たらず困っています。 レコードを最後まで書き出すことは、while(DataReader.read = True)でもできますが、ループの中に判定を入れて、条件次第ではレコードを進めないということができません。 ADO.NETのときはDO UNTIL RecordSet.Eof = True と、RecordSet.nextを組みせて柔軟に書き出しができていた分、ちょっと不便に感じています。 EOFと同様のプロパティというのもあるのでしょうか?

  • ADOでループすると1レコードずつ飛ばしてしまう

    アクセスなのですが Sub test() Set cn = CurrentProject.Connection rs.Open "テーブル", cn, adOpenKeyset, adLockOptimistic rs.Filter = "(店名 = '" & str店名 & "') And (URL = '未')" For j = 1 To rs.RecordCount rs("URL") = "http" rs.Update rs.MoveNext Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub このようにして、既存のレコードにフィルタをかけて該当のレコードの値を更新しているのですが rs.MoveNext をいれると、 1レコード目、3レコード目、5レコード目・・・と言う順番になってしまい、 最終的にrs.RecordCountの数を越したレコードを指定してしまい 実行時エラー 3021 「BOFとEOFのいずれかTRUEになっていか、または現のレコードが要求された操作には、現在のレコードが必要です。」 となってしまいます。 だからって rs.MoveNextをいれないと、rs.RecordCountに達するまで、 いつまでも同じレコードをループしてしまいます。 1レコードずつ順番にデータを掴む方法を教えてください。

  • access vbでループ処理

    レコードセットでテーブルの内容をフォームのテキストボックスに表示 させたいのですが、vbの知識が無く困ってます。以下の処理をループ処理で 簡単に出来ないでしょうか。 ' PASU1 = rs!PASU ' rs.MoveNext ' PASU2 = rs!PASU ' rs.MoveNext ' PASU3 = rs!PASU ' rs.MoveNext ' PASU4 = rs!PASU ' rs.MoveNext ' PASU5 = rs!PASU ' rs.MoveNext ' PASU6 = rs!PASU レコードセットは, Do Until rs.EOF   loop を用いれば繰り返し出来ると解っているのですがフォームの, PASU[1,2,3,,,]の数字の部分を指定することが出来ずにいます。 変数など駆使すれば出来ると思うのですが良くわかりません。 どなたか教えてください。

  • テキストボックス 空白確認

    エクセル VBAで コマンドボタンをクリックすると テキストボックスに空白があった場合 空白のテキストボックスにセットフォーカスしたいのですが 下記のように少ない場合は まだいいですが 多くなってきたとき見易さの面でも簡単にしたいのですが VBだとコントロール配列のインデックス値をループ処理 すればよいと思いますがVBAだとどのようにすればいいのでしょうか? Private Sub CommandButton3_Click() If TextBox2 = "" Then TextBox2.SetFocus ElseIf TextBox3 = "" Then TextBo3.SetFocus ElseIf TextBox4 = "" Then TextBox4.SetFocus ElseIf TextBox5 = "" Then TextBox5.SetFocus End If 御願いします。

  • VB6(SP5) 無限ループ

    VB6(SP5)で、プログラミングをしております。 コマンドボタンをクリックすると、別のフォームを開く仕様にしております。 下記のプログラミングです。 ブレイクポイントで、テキストボックスにフォーカスが戻る事は、確認しております。 が、再び、同じフォームが開きます。要するに無限ループになってしまって いるのです。しかも、開発マシン(Win2000)では、再現しません。 実際のあるマシン(Win98SE)のみ再現します。(全てではありません) 助言の程、よろしくお願い致します。 Private Sub CB_Code_Click() Form1.iDoF = True Form1.Show Do While Form1.iDoF = True DoEvents Loop Set Form1 = Nothing Form_Activate DoEvents Text1.SetFocus End Sub

専門家に質問してみよう