【问题标题】:Kofax Transformation VBA Script to update field valueKofax 转换 VBA 脚本以更新字段值
【发布时间】:2020-01-22 21:07:35
【问题描述】:

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

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

提出了一个基本脚本来检查字段是否有效。基于这个脚本,我尝试了一些逻辑。目标是根据第二个字段的基本条件设置一个字段的内容(为空且必填)。 我的目标(稍后)将是通过数据库调用根据“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”输入字段上按回车键时,应该会进行此验证。它实际上似乎不起作用。我想知道这个阶段出了什么问题。

【问题讨论】:

    标签: vba kofax


    【解决方案1】:

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

    自然秩序

    当您在验证中观察一个字段时,幕后会发生以下情况:

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

    示例

    这是一个例子。想象一下,您想要检测日期,并且希望它们采用数据库格式 (yyyyMMdd)。您文件上的日期是美国格式(MM/dd/yyyy),有两个,但第一个除了“发票日期”作为关键字。

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

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

    在哪里设置值?

    根据用例,以下是我的建议:

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

    您的要求

    现在,回到你原来的要求:

    目标是根据第二个字段的基本条件设置一个字段的内容(为空且必填)。 我的目标(稍后)将是填写/ 使用数据库根据“Siret”字段值更新字段 称呼。我的验证规则如下:我检查“Siret”字符串 长度(它应该是一个 14 个字符的字符串)。如果这是真的,我设置 验证为 true 并将其他字段设置为值。

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

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

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

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

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

    【讨论】:

    • 感谢您的回答。我希望我能做到这一点。我关心的空白字段是 NAF 字段。
    【解决方案2】:

    感谢 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
    

    【讨论】:

    • 太棒了!几个想法:不要使用 AfterFieldConfirmed,而是将其转换为验证方法。这将使您的项目更加透明,无需转到脚本,并且不需要 ValidStrFieldUnValidStrField(这就是验证规则为您所做的)。此外,不要使用 ADODB,而是查看关系数据库支持(这可以在脚本中使用)。这样,凭据就会被移动到更显眼的位置,并且可以在 GUI 而不是脚本中进行更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多