NAVの根底にある性質は、フィールドへの入力を必須にすることを要求することに抵抗することであるように思われます。ビジネスロジックの場合、データを有効にするには、特定のフィールドに入力する必要があります。たとえば、顧客レコードには少なくとも名前と電話番号が必要です。多くの場所を検索しましたが、適切な解決策が見つかりませんでした。では、これはどのように達成できますか?
3 に答える
カードの特定のフィールドにデータを入力する必要がある簡潔な方法を見つけるのに苦労した後、次の方法を思いつきました。NAV は必須フィールドを持つべきではないと感じ始めましたが、ビジネス ロジックには必要です。とにかく、ここに行きます...
第一歩: - さまざまな検証ロジック用のコードユニットがあり、必須のテーブルとそのフィールドをリストするカスタム テーブルを読み取る関数を追加しました。この関数は、テーブル番号、キー フィールド、および「作成モード」を取ります。テキストの「完了ステータス」値を返します。検証中のレコードのテーブルを見つけました。必須フィールドをループし、フィールドにデータが入力されていない場合は、不完全なフィールドのリストに追加します。不完全なフィールドのリストが空の場合、完了ステータスは「完了」です。不完全なフィールドのリストが入力されている場合、不足しているフィールドを示すメッセージが表示され、ユーザーは新しいレコードの作成をキャンセルするか、(新規または既存の) レコードにとどまって不足しているデータを入力するかを選択できます。完了ステータスは「削除」に設定されます 作成をキャンセルするには、または「戻る」を使用して記録にとどまります。ロジックは次のとおりです。
CheckMadatoryFields(TableNumber : Integer;KeyField : Code[10];CreateMode : Boolean) Completion Status : Text[30]
// Read the 'LockoutFields' table to find the manditory fields for the table passed in.
LockoutFields.RESET;
LockoutFields.SETRANGE("Table No.", TableNumber);
LockoutFields.SETFILTER("Filter ID", 'MANDITORY_FIELD');
// Get a record reference for the table passed in
RecRef.OPEN(TableNumber);
RecRef.SETVIEW('WHERE("No." = FILTER(' + KeyField + '))');
// Set this to done, i.e. data is complete (don't delete by mistake).
CompletionStatus := 'done';
IF RecRef.FINDFIRST THEN BEGIN
// Check the record's manditory field(s) listed in the 'LockoutFields' table to see if they're blank.
IF LockoutFields.FINDSET THEN BEGIN
REPEAT
FldRef := RecRef.FIELD(LockoutFields."Field No.");
IF FORMAT(FldRef.VALUE) = '' THEN
FldList := FldList + ' - ' + FldRef.CAPTION + '\';
UNTIL LockoutFields.NEXT = 0;
END;
IF FldList <> '' THEN BEGIN
// If creating the record, add the 'Cancel Create' message, otherwise don't.
IF CreateMode THEN
DeleteRecord := CONFIRM(Text_ManditoryField + '\' + FldList + '\' + Text_CancelCreate, FALSE)
ELSE BEGIN
DeleteRecord := FALSE;
MESSAGE(Text_ManditoryField + '\' + FldList, FALSE);
END;
// Return a 'delete' status when deleting, or a 'return' status to stay on the record.
IF DeleteRecord THEN
CompletionStatus := 'delete'
ELSE
CompletionStatus := 'return';
END;
END;
RecRef.CLOSE;`
ステップ 2: - 必須フィールドを確認するカード (私の場合は顧客カード) で、上記のコードユニットで検証関数を呼び出す関数を追加しました。また、OnQueryClosePage トリガーにロジックを追加して、ローカル関数を呼び出しました。ユーザーが必須フィールドに入力するか、顧客の作成をキャンセルしないと顧客カードを閉じることができなかったため、これはすべて正常に機能しました。秘訣は、検証が実行され、Ctrl+PgUp または Ctrl+PgDn が引き続き機能するように、OnNextRecord トリガーに正しいロジックを配置することでした (注: mibuso のどこかでこのビットを見つけました。どうもありがとう!)。ロジックは次のとおりです。
OnNextRecord(...)
IF CheckManditoryFields = TRUE THEN BEGIN
Customer := Rec;
CurrentSteps := Customer.NEXT(Steps);
IF CurrentSteps <> 0 THEN
Rec := Customer;
EXIT(CurrentSteps);
END;
OnQueryClosePage(...)
EXIT(CheckManditoryFields);
CheckMandatoryFields() ExitValue : Boolean
// Check for manditory fields on this table. If there are missing manditory
// fields, the user can cancel this create, in which case, a 'TRUE' value is
// returned and we'll delete this record.
ExitValue := TRUE;
IF Rec."No." <> '' THEN BEGIN // This is blank if user quits immediately after page starts.
CompletionStatus := HHValidation.CheckManditoryFields(18,Rec."No.",CreateMode);
IF (CompletionStatus = 'delete')
AND (CreateMode = TRUE) THEN // User cancelled create (not edit), delete the record and exit.
Rec.DELETE(TRUE)
ELSE
IF CompletionStatus = 'done' THEN // User completed manditory fields, OK to exit.
ExitValue := TRUE
ELSE
ExitValue := FALSE; //User did not complete manditory fields and wants to return and add them.
END;
それくらいだと思います。カスタム テーブルの詳細は、どのようにコーディングするかによって異なります。検証コード単位は、希望どおりにすることができます。テーブルを使用すると、ロジックを変更せずに必須フィールドを追加または削除でき、この「汎用」検証ロジックを任意のページに配置できます。重要なのは、カード上の 2 つのトリガーと、呼び出す共通の検証ルーチンがあることです。
このコードをフォーム (クラシック クライアント) で使用しましたが、OnNextRecord コードに 1 つのエラーがあります。
OnNextRecord(...)
IF CheckManditoryFields = TRUE THEN BEGIN
Customer := Rec;
CurrentSteps := Customer.NEXT(Steps);
IF CurrentSteps <> 0 THEN
Rec := Customer;
EXIT(CurrentSteps);
END;
CheckMandatoryFields が FALSE を返す状況についても説明する必要があります。そうしないと、次のレコードを要求すると、空のレコードが表示されます。次のようになります。
OnNextRecord(...)
IF CheckManditoryFields = TRUE THEN BEGIN
Customer := Rec;
CurrentSteps := Customer.NEXT(Steps);
IF CurrentSteps <> 0 THEN
Rec := Customer;
EXIT(CurrentSteps);
END ELSE
EXIT(Steps);