タイトル【WindowsオフィスでWebObjects】Direct to Web向けにデータベースを変更するカテゴリーWindows, WebObjects
作成日2001/3/7 18:0:39作成者新居雅行
Direct to Webから書き込みができるようにするには、Accessのデータベースを変更しないといけないことを、一連の連載で紹介した。Direct to WebでAccessのデータベースをWebで公開した場合、Webブラウザ側から新たなレコードを作成したり、あるいは編集するときなど、Accessのオートナンバー型のフィールドの扱いの問題で、修正や新規レコード作成ができないという事態になってしまった。よくよくしらべると、Direct to Webのメカニズムとして、自分自身で主キーの管理をしており、オートナンバー型で自動的に主キー値をシリアルに設定するデータベース側の処理とうまく処理が噛み合わないのである。Direct to Webからの書き込みを可能にするには、オートナンバー型をあきらめ、数値型の長整数型フィールドに変更するしかないということが分かったという次第だ。
しかしながら、そうなると、今度はAccessのデータベースファイルをAccessで開いた時のアプリケーション利用に支障が出る。オートナンバー型の主キーフィールドを使う理由は、主キー値の設定を自動的に行うということで、設定する以上は何もしなくても、たとえばフォームで新しいレコードを作成したときには主キー値が確実に設定されるというメリットがあるからだ。しかし、オートナンバー型から数値型に変更してしまうと、その機能が利用できない。
ここで、Direct to Webでの書き込みもでき、しかも、Accessのデータベースファイルを開いてフォームやレポートなどでの作業の両方をしたいということを考えた。結論的には、まずは主キーフィールドをオートナンバー型でないように変更する。そして、Accessのフォームに、オートナンバーの処理に相当する機能を付け加えることにした。

本来、オートナンバーに替わる連番自動入力機能を、テーブルに定義できればいいのだが、Accessではたとえばテーブルのフィールドの既定値プロパティでは、ユーザ定義関数が使えないなどの制約がある。トリッキーなことをしても仕方ないので、無難な線としては、フォームにプログラムを加えるという手法を考えた。ただし、この方法だと、テーブルのデータシートビューで新しいレコードを手入力するときには要注意ということになる。もっとも、一般的にはそう言うそういうアプリケーションは「作り込んだ」ものとは言えないとは思うので、フォームでの新規入力以外は除外しよう。
Accessのフォームでは、レコードソースとしてテーブルを指定するのが一般的だと思うので、その状態での話をしたい。SQLステートメントなどを指定する場合には、取り出すフィールドに主キーフィールドが含まれるようにすればよいだろう。まず、その主キーのフィールドを、コントロールにいったん配置しよう。これはうまく動くことを確認すれば後から削除すればいい。もちろん、そのまま配置しておいてもかまわない。
そして、フォームのイベントプロシージャを記述する。「挿入前処理」というイベントに対して別掲のようなプロシージャを記述する。もちろん、AccessなのでVisual Basicのプログラムだ。Access 2000向けなので、思い切ってADOを使ってみた。これは一例なので、実際に作成されているデータベースに合せて調整をしてもらいたい。

Private Sub Form_BeforeInsert(Cancel As Integer)

Dim rs As New ADODB.Recordset
Dim pkNum As Long
Dim tableName As String
Dim pkField As Variant

’=============================
’いちおう、ここをカスタマイズすれば、そこそこ汎用的かも
tableName = Me.RecordSource ’フォームのデータソースとなるテーブル
Set pkField = Me.id ’主キーのフィールドを参照
’=============================

rs.Source = _
"select PK from EO_PK_TABLE where NAME=’" & tableName & "’"
rs.ActiveConnection = Application.CurrentProject.Connection
rs.CursorType = adOpenDynamic
rs.LockType = adLockOptimistic

rs.Open
rs.MoveFirst
pkNum = rs.Fields("PK").Value + 1
rs.Fields("PK").Value = pkNum
rs.Update
rs.Close

pkField.Value = pkNum

End Sub

このプロシージャをきちんと動かすために、少しは変更しないといけない。まずはフォームのデータソースにあるテーブル名だ。これを変数tableNameに得る。データソースにテーブルを指定していれば、単にRecordSourceプロパティで得られるが、そうでない場合にはここをカスタマイズすればいい。下手にプログラムするよりは、どっちにしてもフォームごとにこのプロシージャを設定することになるので、文字列定数を入れるのが無難だろう。
次に、主キーフィールドに対応するコントロールを、pkField変数で参照するが、プログラムは主キーフィールドがidという名前の場合だ。違う名前からこの部分を修正すればいいだろう。そのフィールドをフォームに配置すると、コントロール名がidというテキストフィールドが配置される。だから、そのコントロールが存在すればコントロールを参照するが、コントロールを削除するとレコードソースに存在するidフィールドを参照することになる。いずれにしても、pkField変数に代入している部分は、実際のテーブルにあわせないといけないということになる。
あとは、ADOの機能を利用して、Direct to Webが作成するEO_PK_TABLEの内容から、テーブルの主キー値の値を取り出し、それを主キーフィールドにセットし、1だけ値を増加させ、EO_PK_TABLEに戻しているというわけだ。ちなみに、取り出した値に1を増やしたものを主キーフィールドに設定しているのが処理のポイントだ。あと、EO_PK_TABLEの値を変更することから、とりあえずは無難に動的カーソルにし、楽観的ロックにしてある。

このイベントプロシージャは、レコードを新規入力する必要のあるフォームすべてに設定しなければならない。汎用的に作ってもう少し短くまとめることもできなくはないとは思うが、そのあたりは実際に作っているアプリケーションに合せていただければと思う。
こうして、新規にレコードを作成する場合、どこかのフィールドに文字を1文字でも入力すれば、上記のイベントプロシージャが呼び出され、主キーフィールドにシリアル値が入力されるという具合になる。これで、なんとか、AccessのアプリケーションとDirect to Webが両立できたかというところだ。
関連リンク