Kofax Transformation VBA 更新字段值的脚本

Kofax Transformation VBA Script to update field value

我并没有真正使用过 Kofax 技术,我有一个 Kofax 转换表单,其中包含 2 个不同选项卡上的字段。这是我必须在验证过程中进行交互的此表单的摘要。

在这些字段中,我尝试在验证阶段用验证规则更新其中一些内容。我只是创建了一个多字段验证规则并正确映射了字段。

有人提出了一个基本脚本来检查字段是否有效。基于这个脚本,我尝试了一些逻辑。 Objective是根据第二个字段的基本条件设置一个字段(为空且必填)的内容。 我的objective(稍后)将通过数据库调用根据“Siret”字段值填充/更新字段。 我的验证规则如下:我检查“Siret”字符串长度(它应该是一个 14 个字符的字符串)。如果这是真的,我将 Validation 设置为 true 并为另一个字段设置一个值。

Private Sub Validation_Validate(ByVal ValItems As CASCADELib.CscXDocValidationItems, ByVal pXDoc As CASCADELib.CscXDocument, ByRef ErrDescription As String, ByRef ValidField As Boolean)
   Dim strNAF As String
   Dim strSiret As String

   strNAF = ValItems.Item("NAF").Text
   strSiret = ValItems.Item("Siret").Text

   ' enter your own validation rule here
   If Len(strSiret) <= 14 Then
      pXDoc.Fields.ItemByName("NAF").Text = "GOOD JOB"
      ValidField = True
   Else
      ValidField = False
      ErrDescription = "Describe the error here"
   End If
End Sub

当我在“Siret”输入字段上按下回车键时,应该会发生此验证。它实际上似乎不起作用。我想知道这个阶段出了什么问题。

更改字段值的最佳位置取决于您的用例。 Kofax Transformation Modules 遵循独特的模式,您应该始终尝试遵循它。例如,当您发现自己将代码放在 AfterExtract 方法中时,您应该重新考虑——几乎总有更好的方法。对于 tl;dr,只需跳转到 在哪里设置值?

自然秩序

当您在 Validation 中观察一个字段时,以下是幕后发生的事情:

  1. 定位器检测信息(即一个或多个备选方案)。
  2. 定位器已分配给字段。该字段将始终保持最顶层的选择。默认情况下,如果只有一个置信度较高的备选方案,或者如果次佳备选方案的置信度降低 20%,则您的字段将有效。
  3. 您的字段可能有也可能没有与之关联的格式化程序。格式化程序可以使字段无效(如果需要,甚至有效)
  4. 您的字段可以是一个或多个验证规则的一部分。验证规则可以使字段有效或无效,但它们仅在格式化成功时触发。

示例

这是一个例子。假设您想检测日期,并且希望它们采用数据库格式 (yyyyMMdd)。您文档上的日期是美国格式 (MM/dd/yyyy),有两个,但第一个还有 "invoice date" 作为关键字。

  1. 您配置格式定位器以选择日期和关键字。定位器产生两个备选方案:100% 的 01/20/2020 和 0% 的 01/10/2020。
  2. 由于不考虑第二个备选方案(低于 10% 的阈值),该字段将保留第一个备选方案。
  3. 由于字段的第一个备选项处于置信状态 (80%),因此应用了格式。格式化程序将字段的值更改为 20200120,并且该字段仍然有效。
  4. 您配置了一种日期验证方法,并将该方法用于该字段。您检查日期是否在未来,假设今天是 1 月 19 日。该字段现在无效,因为 20200120 是未来的一天。

这让我们回到最初的问题 - 在哪里更改字段的值?可以在验证脚本中更改它,但请记住,这会破坏事物的自然顺序。更糟糕的是,如果格式化首先失败,您的代码将永远不会执行。

在哪里设置值?

根据用例,这里是我的建议:

  • 您需要在 KTM 中设置一个动态值、从外部系统获取值或任何其他不依赖于另一个 field/value 的内容:创建一个脚本定位器并将其 link 到您的场地。在脚本中,创建一个新的备选方案并将其设置为所需的值。您甚至可以使它依赖于其他定位器(因为定位器按顺序执行),但不依赖于其他字段(因为字段在所有定位器触发后填充)。
  • 您想标准化数值。例如,星期几应该用字母表示(SUN、MON、TUE 等)。您仍然希望用户输入数值(1 = SUN,2 = MON,3 = TUE)。创建一个脚本格式化程序并将其 link 添加到您的字段中。这里的好处是您不必重复自己(例如在脚本定位器中和稍后的验证中)。
  • 您想根据用户的交互更改值。您可以在验证中使用任何事件(例如 ButtonClicked、AfterFieldChanged 或 AfterFieldConfirmed),请记住瘦客户端验证不支持某些事件(例如 AfterFieldChanged)。请记住,您要更改指针而不是字段本身,因为验证方法可以被任意数量的字段使用。在您的示例中,pXDoc.Fields.ItemByName("NAF").Text = "GOOD JOB" 将违反此原则(即使验证方法可重用——您的规则现在与 NAF 字段相关联)。改为更改验证对象;例如ValItems.ItemByName("NAF").Text = "GOOD JOB"。另请记住,此时更改字段不会自动调用与您的字段关联的格式化程序,因此请确保提供已格式化的值。但是,您可以手动调用脚本中的格式化。

您的要求

现在,回到您最初的要求:

The Objective is to set the content of a field (which is empty and required) based on a basic condition on the second field. My objective (later) will be to fill / update the fields based on the “Siret” field value with a database call. My validation rule is the following : I check the “Siret” string length (it should be a 14 chars string). If this is true, I set the Validation to true and set the other field a value.

这取决于您是否希望您的用户能够在验证期间更改第二个字段。如果没有,请寻找脚本定位器。请注意,脚本定位器可以有两个子字段,每个子字段可以分配给不同的字段。

如果您的用户应该能够更改它,请进行多字段脚本验证。这两个字段都应该是验证的一部分,长度检查应该是您要做的第一件事。然后,如果 Siret 超过 14 个字符,发出数据库调用。

关于 DRY 和通用设计的一句话

不知道您的确切要求,这里有一些关于可重用性的想法。假设 Siret 并不总是由用户手动键入 - 事实上,定位器可能会拾取所述文本。这是您要创建调用数据库并返回结果的特定方法的地方。请注意,KTM 原生支持关系数据库,您甚至可以在脚本中访问此模型。

另一种选择是使用本地或远程模糊数据库以及数据库定位器(同样,如果您的文档中存在 Siret)。

感谢 Wolfgang 和我的团队,我终于解决了我的问题。 这是用于管理它的代码:

Private Sub ValidationForm_AfterFieldConfirmed(ByVal pXDoc As CASCADELib.CscXDocument, ByVal pField As CASCADELib.CscXDocField)

   Select Case pField.Name
         Case "FieldNameInForm"
            ' simple check if field empty
            If(pXDoc.Fields.ItemByName("FieldNameInForm").Text <> "") Then
               completeForm(pXDoc, pXDoc.Fields.ItemByName("FieldNameInForm").Text)
            End If
      End Select
End Sub


Private Sub completeForm(ByVal pXDoc As CASCADELib.CscXDocument, ByVal myString As String)

   'define required properties
   Dim rs As ADODB.Recordset
   Dim cn As ADODB.Connection
   Dim sqlRequest As String
   Dim dbHostServer As String
   Dim dbUsername As String
   Dim dbPassword As String
   Dim dbName As String
   Dim dbConnString As String

   'Retrieve information for DB Connection (in ScriptVariables.xml)
   dbHostServer = "localhost"
   dbUsername = "root"
   dbPassword = "root"
   dbName = "mydatabase"

   'build the connection string and open connection to database
   dbConnString = "Provider=MSDASQL;Driver={MySQL ODBC 5.3 Unicode Driver};
   dbConnString = dbConnString & "Server=" & dbHostServer & ";"
   dbConnString = dbConnString & "UID=" & dbUsername & ";"
   dbConnString = dbConnString & "PWD=" & dbPassword & ";"
   dbConnString = dbConnString & "database=" & dbName

   'Create recordset and set connection
   'Prapare the db connection
   Set rs = New ADODB.Recordset : : Set cn=New ADODB.Connection

   cn.ConnectionString = dbConnString : cn.Open

   'build query with concatenation
   sqlRequest = "SELECT field1, field2, field3 FROM table"
   sqlRequest = sqlRequest & " where fieldN= '" & myString & "'

   'Execute the SQL request
   Set rs = cn.Execute(sqlRequest)

   ' if the recordset returns a result
   If (rs.EOF Or rs.BOF) Then
      rs.MoveFirst

      pXDoc.Fields.ItemByName("formField1").Text = CStr(rs.Fields("field1"))
      Call ValidStrField("formField1", pXDoc.Fields.ItemByName("field1").Text, pXDoc)

      pXDoc.Fields.ItemByName("formField2").Text = CStr(rs.Fields("field2"))
      Call ValidStrField("formField2", pXDoc.Fields.ItemByName("field2").Text, pXDoc)

      pXDoc.Fields.ItemByName("formField3").Text = CStr(rs.Fields("field3"))
      Call ValidStrField("Commune", pXDoc.Fields.ItemByName("field3").Text, pXDoc)

   'ifthe recordset do not return a value, we set to Undefined
   Else
      pXDoc.Fields.ItemByName("formField1").Text = "Undefined"
      pXDoc.Fields.ItemByName("formField2").Text = "Undefined"
      pXDoc.Fields.ItemByName("formField3").Text = "Undefined"
      MsgBox("No result found in database")
   End If

   ' Close connection & recordset
   rs.Close : Set rs = Nothing
   cn.Close  : Set cn=Nothing    
End Sub

' methods To validate Fields
Private Sub ValidStrField(ByVal StrItem As String,ByVal StrVal As String,ByVal pXDoc As CASCADELib.CscXDocument)
      pXDoc.Fields.ItemByName(StrItem).Text = StrVal
      pXDoc.Fields.ItemByName(StrItem).ExtractionConfident = True
      pXDoc.Fields.ItemByName(StrItem).Confidence = 100.00
      pXDoc.Fields.ItemByName(StrItem).ForcedValid = False
      pXDoc.Fields.ItemByName(StrItem).Valid = True
End Sub

Private Sub UnValidStrField(ByVal StrItem As String,ByVal StrVal As String,ByVal pXDoc As CASCADELib.CscXDocument)
      pXDoc.Fields.ItemByName(StrItem).Text = StrVal
      pXDoc.Fields.ItemByName(StrItem).ExtractionConfident = False
      pXDoc.Fields.ItemByName(StrItem).Confidence = 0.00
      pXDoc.Fields.ItemByName(StrItem).ForcedValid = True
      pXDoc.Fields.ItemByName(StrItem).Valid = False
End Sub