月別アーカイブ: 2018年3月

4D v16: フォームの2ページ目にWebエリアを配置しない

4D v16: フォームの2ページ目にWebエリアを配置しない

フォームにWebエリアを配置して、WA SET PAGE CONTENTでhtmlコンテンツをレンダリングしています。

このフォームで表示したいWebエリアが4つあって、1ページのフォームでは入りきらない。そこでページを増やして2ページ目にWebエリアを配置したのでした。するとその2ページのWebエリアにhtmlコンテンツが表示されない。

不思議なことに3ページに移動させて戻ったりすると2ページのWebエリアは表示される。2ページから1ページに戻って、2ページに行くと表示される。しかしウインドウを開いた直後に2ページに移動させたときだけはどうしても表示されないのでした。メソッドが悪いわけではなさそう。

(4D サポートに電話して確認、解決しました)

これは4D、というかWebエリアの仕様でした。Webエリアは表示方法や画面制御について外部のレンダリングを使っていて、そのため4Dが制御しきれない部分があって、ウインドウを開いた直後に表示されるページ(1ページと0ページ)には、ウインドウを開いたタイミングで表示されるが、別ページのWebエリアにはオブジェクトがロードされる前にコマンドを実行しても作用しない、ということでした。どうやらFORM GOTO PAGE(2)の直後にWA SET PAGE CONTENTを実行しても、まだWebエリアはロードしきれていないため内容が表示されない。

で、回避策を考えました。
1)ページをやめて別のウインドウを開く
2)0ページに配置して、1ページを表示するときは四角形で隠しておく
3)0ページに配置して、2ページ目を表示するときだけ所定の位置に移動させ、ほかのページを表示するときは遠くに移動させておく
4)0ページに配置して、2ページ目を表示するときだけVisible、ほかのページを表示するときはInvisible

1)はできることはわかっているけど仕様変更なのでやりたくない。2)から試す。すると、1ページ目に置いた四角形は、0ページのボタンとか四角形を隠すことはできるが、0ページのWebエリアを隠せない。Webエリアは常に一番前に表示されてしまう。順番も4Dが制御しきれない部分のようです。左の図の2つあるWebエリアのうち、後ろの方を0ページに、前の方を1ページに配置したら、右の図のように1ページ目の四角形やボタンよりも前に表示されてしまう。これも驚きの結果だ。

 

3)はOK。ちょっとコードがトリッキーに見えるけど、これでも良しか。
4)もOK。こちらは仕様に納得感があり、コードはシンプル。これを採用。

マニュアルを見ると、次のように書いてあります。VISIBLEやMOVEで制御しろと言っているような...

Webエリアのプログラムによる管理
他の動的なフォームオブジェクトのように、Webエリアはオブジェクト名とテキスト型の変数名を持ちます。これらはWebエリアをプログラミングに よって処理する際に使用されます。 特にWebエリアに対して OBJECT SET VISIBLE コマンドと OBJECT MOVE コマンドを使用することができます。

4D: TEXT型のフィールドにインデックスを張るときの注意

TEXT型のフィールドにインデックスを張るときの注意

フィールドに保存した文字列を検索しても該当しない、という現象にはまりました。(はまりレベル3)

テーブルHBにテキスト型のフィールドを追加しました。そのフィールドにHBのすべてのレコードについて、メソッドで求めた文字列を保存しました。その保存した文字列で検索しても該当しない、のです。

1対N構造のテーブルがあって(テーブルHBとテーブルKJ)、N側(テーブルKJ)のラインナップが同じであるテーブルHBのレコードを探す、という機能を実装していたときのことです。ロジック的には、テーブル HBの各レコードについてテーブル KJをクエリして判定すればいいのですが、テーブルHBにはレコードが1万件以上あって、遅くてとても実用になりません。テーブルKJをキャッシュして配列に持たせても同様に遅い、という状況でした。

処理の高速化を図るため、テーブルHBに「HB_KJLINE」というフィールドを用意して、KJ_IDをコンマ区切りの文字列で連結して保存します。こうしておくと上記のクエリはテーブルHBだけをクエリすればよいことになります。検索時に遅いので保存時に一つ余計なフィールドを用意して検索のための値を保存しておく、というデータベース高速化の常套手段です。

高速化のためのコーディングですから、追加したHB_KJLINEにはインデックスを作成しました。HB_KJLINEの文字列は255文字を超えるでしょうからテキスト型です。そして実行、値はHB_KJLINEに入っていますが、あるはずの文字列で検索しても該当なし、です。

カレントテーブル表示(コマンド+Uキー)でクエリ(コマンド+Y)して、そのフィールドに入っている文字列で検索してみても、該当しません。一つレコードを保存してみると、保存したレコードだけ正常に該当します。

(4D Japanのサポートに電話して解決しました。)

原因はインデックスにありました。テキスト型のフィールドにインデックスを作成した場合、最初の1,024文字までしか結果が保証されない、という4Dの仕様です。HBには380個以上のKJを持つものがあり、この場合KJ_IDがコンマを入れて一つ4〜5文字とするとKJLINEの文字数は1,024文字を超えます。インデックスのチェックを外したら検索できるようになりました。

教訓1:

テキスト型のフィールドにはインデックスを作成しない。高速化を図る場合は別の方法を考えること。

ここで次の教訓も覚えておきましょう。

教訓2:

4Dでは、レコード数が32000件以上の場合、FInd in Arrayの該当レコード番号が保証されなくなる。(はまりレベル5)