<HOME  <お願い事項  <Access2000 TOP   <Access97 TOP   <サイト内検索
  Ac2002--VBAの沼 > ひとつのフィールドの値を複数のフィールドに分ける
  



ひとつのフィールドの値を複数のフィールドに分ける

さて・・・。
最初にお話したとおりで、基本的にこういうことは、「アクションクエリ」という種類のクエリを駆使してやるべきです(技術の高い低いにかかわらず、MS-Accessという製品を使うのであれば)。むやみにコードを書いて処理を進めようとすることは、生産性を下げ、しいては単なる自己満足ゾーンに位置付けられてしまいます(それでもいいという人もあるかもわからんですが)。しかし、時と場合によっては、こうした処理をフル活用しなくてはならないことも、あります。。。。というお話は、最初に申し上げたとおりです。
今までお話した内容を元に、いくつか例題をご紹介しますので、ぜひともトライしてみてください。



たとえば・・・こんなテーブルがあったとします。

どういう事情があったのかわかりませんが、1つのフィールドに128桁の文字数字がずらずらと入っているという、異様なテーブルです。
これを、32桁ずつ4つのフィールドに分けたいなぁと思っています。



ちょっと余談ですけれども・・・。
こういうテーブル作るとき、コレの元データがもし「テキストファイル」などの外部のファイルだとした場合、「固定長」っていうタイプのテキストファイルなわけなんですね。
例えば、こんな感じで、普通のエディタとかで開くことができるファイルです。

こういうテキストファイルをインポートしようとするとウィザードが動きますから、画面の指示に従って操作すれば、取り込むことができるわけなんです。このウィザード画面の中で、どこで区切るかマウスでちょこちょことクリックしていけば、簡単に区切ることができるんです。

    (テキストファイルをインポートする際に表示されるウィザード画面の一部)

なので、「128桁を4つに区切ってインポート」することは簡単にできるわけです。
後からコード書いてどうこうという必要はないはずです。
でもーーー例えば、取り込んじゃった後で気づいたとか、そもそもテキストファイルじゃない場合とか、いろいろあると思いますので・・・。
今回は、どこをどう間違ったのか、ベタベタなテーブルになってしまった場合の、フィールドのバラしかたを研究してみましょう。
こういうの、何かしら役に立つんじゃないかと思うんで。


バラしてもとのテーブルにもどすことはちょっと難しいので(難しいことはないですが処理中にPCがハングアップしちゃったりしたらテーブルがおかしくなっちゃいそうなので、こういう場合はいちおう、「元」と「先」という形で考えたほうが無難だと思います)、書き出し先のテーブルを別に作成します。さっきの例と同じですね。
こちらは、フィールドを4つにしました。フィールドサイズなどは適時変更してください。
今回はデフォルトの「50」のままでいけるので、そのままお話を続けますね。

それぞれのフィールドに、ばらしたフィールドを代入しつつ、AddNewしていきます。
128文字のフィールドを、32文字ずつ4つに分けるにはどうしたらいいでしょう。
これはですね。
いろんなやり方が考えられますが、ここはひとつLeft、Mid、Right関数を駆使して、「桁数を指定して文字列の取り出し」っていうのをやってみましょう。
Left、Mid、Right関数、まずはヘルプにて簡単に用法などをつかんでおいてください。

たとえば、 ABCDEFG という文字列があったとします。
   Left(“ABCDEFG”,2)   答えは AB です。左端から、指定した文字数だけ取り出します。
   Mid(“ABCDE”,3,4)   答えは CDEF です。指定した桁位置から、指定した文字数だけ取り出します。
   Right(“ABCDEFG”,3) 答えは EFG です。右端から、指定した文字数だけ取り出します。

基本的に、「テキスト型」のフィールドか、String型の変数に入っている値に対して使う関数です。

今回は、
    一つ目のフィールド    Left(元のフィールド名,32)   
    ふたつ目のフィールド   Mid(元のフィールド名,33,32)
    三つ目のフィールド    Mid(元のフィールド名,65,32)
    四つ目のフィールド    Mid(元のフィールド名,97,32)
で、いけそうじゃないです?
これを、もとのテーブルのレコード件数分、繰り返せばオッケーのはず。



ここまでは、いいですよね。
読み取り側(元のテーブル)と、書き出し側のテーブルをふたつ開いておきます。
で、忘れないうちにCloseするところを書いておいて、間にAddNewをするための処理を書きましょう。

これがループの外枠・・・。読み取り側のテーブルの最後まで、ループを繰り返すように書きます。

ループの中身はこれでいかがでしょう。

書き終わったらコンパイルしてつづり間違いなどをチェックしましょう。
実行は、とりあえずイミディエイトウィンドウからやりましょうか。手っ取り早く実行テストできますからね。
関数の書き方等問題がなければ、すんなり通ると思います。

実行が完了したかなーという予感がしたら、[データテーブル2]を開いてみてください。
各フィールドに値が入ってますか???



今回、わたしは、もとになる[データテーブル]側になぜか20000件用意してテストしてみました。
128文字のフィールドが、20000件です。正確にはちょっと作り方失敗しちゃって20003件です。ハハハ。まあ大は小を兼ねるということで。
イミディエイトウィンドウにプロシージャ名を入れて、Enterキーを押すと、しばらくカーソルが止まったままになります。しばらくすると、また明滅し始めます。明滅し始めたら、実行が終了したことになります。

私のPCで、このプロシージャで、20003件のレコードを処理するのに16秒かかりました。
1件ずつ処理しますからねぇ。。。どうしても、件数が多いと時間がかかるようになります。
これは、メモリがどれくらいついているかとか、CPUが何かとか、ディスクがどれくらいきれいな状態で空いているかとか、他に起動しているアプリケーションソフトがあるかどうかとか、常駐させているソフトがあるかとか、そういうこともからんできますので、かかる時間ははっきりいってやってみないと予想がつかないです。



これとまったく同じ処理をするのが、以下の「追加クエリ」です。
4つとも「式」なので、「レコードの追加」欄をひとつひとつ指定して作りました。

これ、実行してみますと、私のPCで、この追加クエリで、20003件のレコードを処理するのに2秒かかりました。
(空のテーブルを別に用意して、そっちに追加するようにしましたので、プロシージャを実行したときと条件的には同じです)

こういう、単純な「追加」なら、大体の場合、追加クエリのほうが処理が速いです。
これは、レコード件数が多くなればなるほど、差が顕著に現れます。
なんでかって?なんでなんですかねぇ(遠い目)
まあ、ただ、これは一概には言えないですから、鵜呑みにしないでください。このコーナーはVBAの入門以前講座ですんで、このプロシージャは「処理スピードを速めるための配慮」は何にもしてないですから・・・このまま追加クエリと比較したら、立派なSEさんたちからお叱りのメールが来てしまいます。
でも、いちおう心には留めておいてください。こういうプロシージャの場合、1レコードずつループさせて処理するわけですから、レコード件数が多くなればなるほど時間がかかることになります。もちろん追加クエリだって、追加するレコード数が20件のときと150万件のときとじゃ処理速度はぜんぜん違いますけど、1件ずつループさせてる処理とはちょっと処理方法が異なります。大量のレコードを一度にガツっと扱うときは、追加クエリを使って仕組みを考えるようにしたほうがよいと、わたしは思います。