似乎NAV的潜在本质是抵制要求填充字段是强制性的。在我们的业务逻辑的情况下,必须填充某些字段以使数据有效。例如,客户记录必须至少包含姓名和电话号码。我搜索了很多地方,但没有找到合适的解决方案。那怎么能实现呢?
答案 0 :(得分:4)
在努力寻找一种简洁的方法来要求填充卡片上的某些字段后,我想出了以下内容,它(到目前为止)正在为我工作。我开始意识到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触发器中放置正确的逻辑,以便执行验证并且Ctrl + PgUp或Ctrl + PgDn仍然起作用(注意:我在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;
我认为就是这样。自定义表的详细信息完全取决于您希望如何编写代码。验证代码单元可以是您想要的。使用表允许在不更改任何逻辑的情况下添加或删除必填字段,并且可以将此“通用”验证逻辑放在任何页面上。关键是卡上的两个触发器,并有一个通用的验证例程来调用。
答案 1 :(得分:1)
我在表单(经典客户端)上使用了此代码,但OnNextRecord代码中存在一个错误。
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);
答案 2 :(得分:0)
OnNextRecord函数中还有另一个错误:
OnNextRecord(...)
IF CheckManditoryFields = TRUE THEN BEGIN
Customer := Rec;
CurrentSteps := Customer.NEXT(Steps);
IF CurrentSteps 0 THEN
Rec := Customer;
EXIT(CurrentSteps);
END ELSE
EXIT(Steps);
页面(或表单)的源表上设置的过滤器不会复制到执行步骤的记录中。因此,您可以导航到不在过滤器中的记录。
而是将Rec分配给客户,您应该复制它:
OnNextRecord(...)
IF CheckManditoryFields THEN BEGIN
Customer.COPY(Rec);
CurrentSteps := Customer.NEXT(Steps);
IF CurrentSteps 0 THEN
Rec := Customer;
EXIT(CurrentSteps);
END ELSE
EXIT(Steps);