データウィンドウに対するDWItemStatusの研究と応用


(一)引用
PBはSybase社が発売した高速データベースフロント開発ソフトウェアです.
強力なデータ・ウィンドウ・テクノロジーとデータベース・アクセス機能で、多くのプログラマーに愛されています.
データウィンドウには、データ行と列の状態を記述する列挙変数DWItemStatusがあるが、実際の開発ではその存在を無視することが多い.
本人はその仕事のメカニズムと相応の操作関数によって実際の開発の中で柔軟に応用して、ソフトウェア製品の機能を完備します.
(二)動作メカニズム
DWItemStatusは、DataWindowのデータ行と列の変更ステータスとデータベースへの書き込み方法を示す列挙型変数です.
この列挙変数には4つの値があります:NotModified!,DataModified!, New!, NewModified!.

NotModified! データ・ウィンドウでデータ・ソースから取得したロー・データとカラム・データが変更されていないことを示します.

DatModified! データ・ウィンドウでデータ・ソースから取得した行データと列データが変更されたことを示します.

New! データウィンドウの行のデータが新しく挿入され、変更されていないことを示します.

NewModified! データウィンドウの行のデータが新しく挿入されたが変更されたことを示します.
上記の変更には、手動入力とSetItem関数での設定が含まれています.
この4つの値のうち
NotModifed!、DataModified!行と列の状態を表すことができます.
しかし
New!とNewModified!行の状態のみを表すことができます.
◆データが検索された場合:
データウィンドウがデータを取得すると、すべての行と列の状態がNotModifiedに初期化されます!
ある行の中の1列のデータが手入力で修正されたり、プログラムで修正されたりすると、この列の状態はDataModifiedになります!
1行に1列のステータスがDataModifiedである限り!では、この行の状態もDataModifiedになります!の
◆データが挿入された場合:
データウィンドウに1行挿入すると、その行の状態がNewに初期化されます!、この行のすべての列の状態はNotModifiedに初期化されます!.
この行の1列のデータが手動で入力されて変更されたり、プログラムによって変更されたりすると、この列の状態はDataModifiedになります!
新しく挿入された行の中に1列の状態がDataModifiedである限り!では、この行の状態はNewModifiedになります!の
データ・ウィンドウの設計時にカラムのデフォルト値が設定されている場合、ローが新しく挿入された場合、このカラムはDataModifiedになりません.
◆sql文の生成:
データウィンドウにデータを保存すると、行の状態によってsql文の生成方法が決まります.
行の状態がNewModifiedだとしたら!では、insert文を生成してデータベースにデータを挿入します.
行の状態がDataModifiedであれば!では、update文を生成して、データウィンドウで対応するデータを更新します.
(三)操作関数の説明
1.行と列のステータスの取得
プログラムでは、データウィンドウのGetItemStatusメソッドを使用して、行または列のステータスを取得できます.関数の原形は次のとおりです.

DWItemStatus DwControl.GetItemStatus(long row,integer column,DWBuffer DWBuffer) 
DWItemStatus DwControl.GetItemStatus(long row,string column,DWBuffer DWBuffer)

パラメータの説明:

row:ステータスのローを取得します.

column:ステータスの列を取得し、行全体のステータスの場合、このパラメータは0に設定します.

DWbuffer:行が存在するバッファ.

戻り値:行または列のステータス列挙値を指定します.いずれかのパラメータがnullの場合、nullが返されます.
2.行または列のステータスの変更
プログラムでは、データウィンドウのSetItemStatusメソッドで行または列の状態を変更できます.関数の原形は次のとおりです.

integer DwControl.SetItemStatus(long row,integer column,DWBuffer DWBuffer,DWItemStatus status)
integer DwControl.SetItemStatus(long row,string column,DWBuffer DWBuffer,DWItemStatus status)

パラメータの説明:

row:ステータスを設定する行

column:ステータスを設定する列.行全体の状態の場合、このパラメータは0に設定されます.

DWbuffer:行が存在するバッファ.

status:設定する新しいステータス.

戻り値:戻り1が正常に実行された場合、エラーが発生した場合は-1が返されます.いずれかのパラメータがnullの場合、nullが返されます.
SetItemStatusを呼び出すと、列のステータスをDataModified!から取得できます.NotModifiedに変更!逆にしてもいいです.
しかし、ローのステータスを変更するには、ローのステータスの変換テーブルを次に示します.
元の状態で新しい状態を指定

-              New!          New Modified!  Data Modified!  Not Modified!
New!           -             Yes            Yes             No
NewModified!   No            -              Yes             New!
DataModified!  NewModified!  Yes            -               Yes
NotModified!   Yes           Yes            Yes             -

◆表のyesは、変更が可能であることを意味します.たとえば、ローの現在のステータスがNotModifiedであることを確認します.SetItemStatusを呼び出して行のステータスをNewに変更!はい、変えることは成功します.
◆表のnoは、変更が不可能であることを意味します.例えば、現在の状態がNewModifiedである行を!SetItemStatusを呼び出して行のステータスをNewに変更!いいえ、変えることは成功しません.
◆表中yesでもnoでもないセルは,変更の具体的な結果を示す.例えば、現在の状態がNewModifiedである行を!SetItemStatusを呼び出して行の状態をnoModifiedに変更します!の場合、行の状態はNewModifiedではありません!noModifiedでもない!ニューになりました!.
◆ある行の状態がnoModifiedになったら!あるいはNew!,この行のすべての列の状態がnoModifiedになります.
◆表のいくつかの状態の変更が禁止されている場合、このプロセスをいくつかのステップに分けて完了することができます.如:ニューを先に!DataModifiedに変更!さらにnot Modifiedになります!の
(3)実際の開発でDWItemStatusを用いた例を2つ挙げる
例1:
実際の開発では、ウィンドウを閉じる前に変更したデータを保存するようにユーザーに注意するために、ウィンドウのclosequeryイベントに次のコードを書きます.

int li_ret
if ( dw_1.deletedcount() + dw_1.Modifiedcount() ) > 0 then
    li_ret = messagebox( "  !", "       ,    ?", question!, yesnocancel! )
    if li_ret=1 then
        if dw_1.update() = 1 then
            commit ;
            return 0
        else
            rollback;
            messagebox( "  !", "     !,         !" )
            return 1
        end if
    elseif li_ret = 2 then
        return 0
    elseif li_ret = 3 then
        return 1
    end if
end if

これにより、ユーザーにデータの保存を促すことができますが、データウィンドウにローを挿入した後、ユーザーが変更していなくても、このローの一部のフィールドの値を設定するためにSetItem関数を呼び出します.
プログラムはユーザーに保存を促すこともあります.このような状況が発生すると,ユーザはしばしばわけがわからず,戸惑う.
どのようにしてプログラムの中でこのような状況を避けることができますか?
1つの方法は、SetItemを呼び出した後、新しい挿入行の状態をSetItemStatusでNotModifiedに再設定することです.(上の表に対応して、結果はNew!)
これにより、ModifiedCount関数が変更データ行を統計する場合、この行は計上されません.具体的なコードは以下の通りです.

int li_Newrow
li_Newrow = dw_1.insertrow(0)
dw_1.SetItem(li_Newrow,"sex",1)
dw_1.SetItem(li_Newrow,"birth",today())
dw_1.SetItem(li_Newrow,0,primary!,NotModified!)

例2:
ユーザがデータを保存しているとき,ユーザに何個のデータを保存しているかを教えるために,プログラムでsqlcaの
sqlnrowsの値.コードは次のとおりです.

if dw_1.update() = 1 then
    li_updatenum = sqlca.sqlnrows
    commit using sqlca;
    messagebox("  ", "   " + string(sqlca.sqlreturndata)) + "   !" )
else
    rollback using sqlca;
    messagebox("  ", "       ,       !" )
end if

これにより,ユーザにどれだけのレコードが保存されているかを教えることができるが,これは正確ではない.ユーザは、更新されたレコードの数、新しく挿入されたレコードの数、削除されたレコードの数をより明確に知りたい場合がある.
このとき,データ行の状態に応じて更新されたレコードの数,新たに挿入されたレコードの数を統計する必要がある.
具体的な方法は、保存前にすべてのデータ行を巡ってNewModifiedを統計することです!ステータスラインとDataModified!ステータスライン、
前者は新しく挿入されたデータ行、後者は更新されたデータ行、さらにDeletedCount()関数で削除されたレコード数を取得します.詳細なコードは以下の通りです.

int li_newnow = 0, li_updaterow = 0, li_delrow, i = 1
DWItemStatus l_status
dw_1.accepttext()
do while i <= dw_1.rowcount()
    l_status = dw_1.GetItemStatus( i, 0, primary! )
    i++
    if l_status = DataModified! then
        li_updaterow ++
    elseif l_status = NewModified! then
        li_newnow ++
    end if
loop
li_delrow = dw_1.deletedcount( )
if dw_1.update() = 1 then
    commit using sqlca;
    if li_updaterow > 0 or li_newnow > 0 or li_delrow > 0 then
        messagebox( "  ", "    !~r~n   "&
            + string(li_updaterow) + "   !~r~n"&
            + "   " + string(li_newnow)+"   !~r~n"&
            + "   " + string(li_delrow)+"   !")
    else
        messagebox("  ","       !")
    end if
else
    rollback using sqlca;
    messagebox("  ","       ,       !")
end if

以上のコードを用いて,ユーザに更新されたレコードの数,追加されたレコードの数を正確に伝えることができる.これにより、ユーザは自分の操作をより明確にすることができる.