6

我想用它们来比较 Excel 中的两个列表(列)以查找匹配项。由于这是一个相当复杂的操作,我过去曾在 Excel 中使用几个不同的函数(非 VBA)执行它,但事实证明它充其量是尴尬的,所以我想尝试一个多合一的VBA 解决方案,如果可能的话。

第一列包含不规则的名称(例如引用的昵称、“jr”或“sr”等后缀,以及“首选”版本的名字的括号)。此外,当出现中间名时,它们可能是名字或首字母。

第一列的顺序是:

 <first name or initial>
 <space>
 <any parenthetical 'preferred' names - if they exist>
 <space>
 <middle name or initial - if it exists>
 <space>
 <quoted nickname or initial - if it exists>
 <space>
 <last name>
 <comma - if necessary><space - if necessary><suffix - if it exists>

第二列的顺序是:

 `<lastname><space><suffix>,<firstname><space><middle name, if it exists>`

,没有第一列的“不规则”。

我的主要目标是将第一列“清理”成这个顺序:

 `lastname-space-suffix,firstname-space-preferred name-space-
 middle name-space-nickname`

虽然我在这里保留了“异常”,但我可能会在比较代码中使用某种“标志”来逐个提醒我它们。

我一直在尝试几种模式,这是我最近的:

["]?([A-Za-z]?)[.]?["]?[.]?[\s]?[,]?[\s]?

但是,我想允许姓氏和后缀(如果存在)。我已经用“全局”对其进行了测试,但是我不知道如何通过反向引用来分隔姓氏和后缀。

然后,我想比较两个列表之间的最后一个、第一个、中间的首字母(因为大多数名字只是第一个列表中的首字母)。

 An example would be:
 (1st list)
 John (Johnny) B. "Abe" Smith, Jr.
 turned into:
 Smith Jr,John (Johnny) B "Abe"
 or
 Smith Jr,John B

 and
 (2nd list)
 Smith Jr,John Bertrand
 turned into:
 Smith Jr,John B

 Then run a comparison between the two columns.

这个列表比较的一个好的起点或继续点是什么?


2012 年 4 月 10 日附录:

作为旁注,我需要删除昵称中的引号和首选名称中的括号。我可以将分组的引用进一步分解为子组(在下面的示例中)吗?

 (?:  ([ ] \( [^)]* \)))?  # (2) parenthetical 'preferred' name (optional) 
 (?:  ([ ] (["'] ) .*?) \6 )? # (5,6) quoted nickname or initial (optional) 

我可以这样分组吗:

 (?:(([ ])(\()([^)]*)(\))))? # (2) parenthetical 'preferred' name (optional) 
 not sure how to do this one -  # (5,6) quoted nickname or initial (optional) 

我在“Regex Coach”和“RegExr”中尝试了它们,它们工作得很好,但在 VBA 中,当我想要返回的反向引用如 \11,\5 时返回的只是名字、数字一和逗号(例如“Carl1”)。我回去看看有没有错别字。谢谢你的帮助。


2012 年 4 月 17 日附录:

我忽略了一个名字“情况”,那就是由两个或多个单词组成的姓氏,例如“St Cyr”或“Von Wilhelm”。
是否会添加以下内容

 `((St|Von)[ ])?

在你提供的这个正则表达式中工作?

 `((St|Von)[ ])?([^\,()"']+)

我在 Regex Coach 和 RegExr 中的测试不太奏效,因为替换返回“St”,前面有一个空格。

4

2 回答 2

2

这是一个可能有用的正则表达式,它将按以下顺序为您提供 6 个捕获组:名字、首选名称、中间名、昵称、姓氏、后缀。

([a-z]+)\.?\s(?:(\([a-z]+\))\s)?(?:([a-z]+)\.?\s)?(?:("[a-z]+")\s)?([a-z]+)(?:,\s([a-z]+))?

这是一个解释:

([a-z]+)\.?\s          # First name, followed by optional '.' (required)
(?:(\([a-z]+\))\s)?    # Preferred name, optional
(?:([a-z]+)\.?\s)?     # Middle name, optional
(?:("[a-z]+")\s)?      # Nickname, optional
([a-z]+)               # Last name, required
(?:,\s([a-z]+))?       # Suffix, optional

因此,例如,您可以通过组合这样的组来John (Johnny) B. "Abe" Smith, Jr.变成,也可以使用.Smith Jr,John (Johnny) B "Abe"\5 \6,\1 \2 \3 \4Smith Jr,John B\5 \6,\1 \3

于 2012-03-30T23:52:23.767 回答
2

重做 -

这是不同的方法。它可能适用于您的 VBA,这只是一个示例。我在 Perl 中对此进行了测试,效果很好。但是,我不会展示 perl 代码,
只展示正则表达式和一些解释。

这是一个两步过程。

  1. 规范化列文本
  2. 做主解析

规范化过程

  • 获取列值
  • 去掉所有点.- 全局搜索\.,替换为空''
  • 将空格变成空格 - 全局搜索\s+,替换为单个空格[ ]

(请注意,如果无法正常化,无论尝试什么,我都看不到成功的机会)

主要解析过程

规范化列值(对两列都执行)后,通过这些正则表达式运行它。

第 1 列正则表达式

^
  [ ]?
  ([^\ ,()"']+)                        # (1)     first name or initial          (required)
  (?:  ([ ] \( [^)]* \))    )?         # (2)     parenthetical 'preferred' name (optional)
  (?:
       ([ ] [^\ ,()"'] )               # (3,4)   middle initial OR name         (optional)
       ([^\ ,()"']*)                   #         name and initial are both captured
  )?
  (?:  ([ ] (["'] ) .*?) \6 )?         # (5,6)   quoted nickname or initial     (optional)
  [ ]  ([^\ ,()"']+)                   # (7)     last name                      (required)
  (?:
        [, ]* ([ ].+?) [ ]?            # (8)     suffix                         (optional)
      | .*?
  )?
$

更换取决于你想要什么。
定义了三种类型(根据需要替换$\

  1. 1a型全中-$7$8,$1$2$3$4$5$6
  2. 类型 1b 中间声母 -$7$8,$1$2$3$5$6
  3. 类型 2 中间首字母 -$7$8,$1$3

转换示例:

Input (raw)               = 'John (Johnny) Bertrand "Abe" Smith, Jr.  '
Out type 1 full middle    = 'Smith Jr,John (Johnny) Bertrand "Abe"'
Out type 1 middle initial = 'Smith Jr,John (Johnny) B "Abe"'
Out type 2 middle initial = 'Smith Jr,John B'

第 2 列正则表达式

^
  [ ]?
  ([^\ ,()"']+)                  # (1)     last name                      (required)
  (?: ([ ] [^\ ,()"']+) )?       # (2)     suffix                         (optional)
  ,
  ([^\ ,()"']+)                  # (3)     first name or initial          (required)
  (?:
      ([ ] [^\ ,()"'])           # (4,5)   middle initial OR name         (optional)
      ([^\ ,()"']*)
  )?
  .*
$

更换取决于你想要什么。
定义了两种类型(根据需要替换$\

  1. 1a型全中-$1$2,$3$4$5
  2. 类型 1b 中间声母 -$1$2,$3$4

转换示例:

Input                     = 'Smith Jr.,John Bertrand  '
Out type 1 full middle    = 'Smith Jr,John Bertrand'
Out type 1 middle initial = 'Smith Jr,John B'

VBA 替换帮助

这适用于非常旧的 Excel 副本,创建一个 VBA 项目。
这是为显示示例而创建的两个模块。
他们都做同样的事情。

第一个是所有可能替换类型的详细示例。
第二个是仅使用类型 2 比较的精简版本。

如您所知,我以前没有做过 VB,但它应该很简单
,您可以了解替换是如何工作的,以及如何在 excel
列中绑定。

如果您只是进行平面比较,则可能需要执行一次 col 1 val
,然后检查第 2 列中的每个值,然后转到
第 1 列中的下一个 val,然后重复。

最快的方法是创建 2 个额外的列,将尊重的
列 val 转换为类型 2(变量 strC1_2 和 strC2_2,参见示例),然后将它们复制
到新列。
之后,您不需要正则表达式,只需比较列,找到匹配的行,
然后删除 type-2 列。

详细 -

Sub RegexColumnValueComparison()

' Column 1 and 2 , Sample values
' These should probably be passed in values
' ============================================
strC1 = "John (Johnny)   Bertrand ""Abe""   Smith, Jr.  "
strC2 = "Smith Jr.,John Bertrand  "

' Normalization Regexs for whitespace's and period's
' (use for both column values)
' =============================================
Set rxDot = CreateObject("vbscript.regexp")
rxDot.Global = True
rxDot.Pattern = "\."
Set rxWSp = CreateObject("vbscript.regexp")
rxWSp.Global = True
rxWSp.Pattern = "\s+"

' Column 1 Regex
' ==================
Set rxC1 = CreateObject("vbscript.regexp")
rxC1.Global = False
rxC1.Pattern = "^[ ]?([^ ,()""']+)(?:([ ]\([^)]*\)))?(?:([ ][^ ,()""'])([^ ,()""']*))?(?:([ ]([""']).*?)\6)?[ ]([^ ,()""']+)(?:[, ]*([ ].+?)[ ]?|.*?)?$"

' Column 2 Regex
' ==================
Set rxC2 = CreateObject("vbscript.regexp")
rxC2.Global = False
rxC2.Pattern = "^[ ]?([^ ,()""']+)(?:([ ][^ ,()""']+))?,([^ ,()""']+)(?:([ ][^ ,()""'])([^ ,()""']*))?.*$"

' Normalize column 1 and 2, Copy to new var
' ============================================
strC1_Normal = rxDot.Replace(rxWSp.Replace(strC1, " "), "")
strC2_Normal = rxDot.Replace(rxWSp.Replace(strC2, " "), "")


' ------------------------------------------------------
' This section is informational
' Shows some sample replacements before comparison
' Just pick 1 replacement from each column, discard the rest
' ------------------------------------------------------

' Create Some Replacement Types for Column 1
' =====================================================
strC1_1a = rxC1.Replace(strC1_Normal, "$7$8,$1$2$3$4$5$6")
strC1_1b = rxC1.Replace(strC1_Normal, "$7$8,$1$2$3$5$6")
strC1_2 = rxC1.Replace(strC1_Normal, "$7$8,$1$3")

' Create Some Replacement Types for Column 2
' =====================================================
strC2_1b = rxC2.Replace(strC2_Normal, "$1$2,$3$4$5")
strC2_2 = rxC2.Replace(strC2_Normal, "$1$2,$3$4")

' Show Types in Message Box
' =====================================================
c1_t1a = "Column1 Types:" & Chr(13) & "type 1a full middle    - " & strC1_1a
c1_t1b = "type 1b middle initial - " & strC1_1b
c1_t2 = "type 2 middle initial - " & strC1_2
c2_t1b = "Column2 Types:" & Chr(13) & "type 1b middle initial - " & strC2_1b
c2_t2 = "type 2 middle initial - " & strC2_2

MsgBox (c1_t1a & Chr(13) & c1_t1b & Chr(13) & c1_t2 & Chr(13) & Chr(13) & c2_t1b & Chr(13) & c2_t2)

' ------------------------------------------------------
' Compare a Value from Column 1 vs Column 2
' For this we will compare Type 2 values
' ------------------------------------------------------
If strC1_2 = strC2_2 Then
   MsgBox ("Type 2 values are EQUAL: " & Chr(13) & strC1_2)
Else
   MsgBox ("Type 2 values are NOT Equal:" & Chr(13) & strC1_2 & " != " & strC1_2)
End If

' ------------------------------------------------------
' Same comparison (Type 2) of Normalized column 1,2 values
' In esscense, this is all you need
' ------------------------------------------------------
If rxC1.Replace(strC1_Normal, "$7$8,$1$3") = rxC2.Replace(strC2_Normal, "$1$2,$3$4") Then
   MsgBox ("Type 2 values are EQUAL")
Else
   MsgBox ("Type 2 values are NOT Equal")
End If

End Sub

仅类型 2 -

Sub RegexColumnValueComparison()

' Column 1 and 2 , Sample values
' These should probably be passed in values
' ============================================
strC1 = "John (Johnny)   Bertrand ""Abe""   Smith, Jr.  "
strC2 = "Smith Jr.,John Bertrand  "

' Normalization Regexes for whitespace's and period's
' (use for both column values)
' =============================================
Set rxDot = CreateObject("vbscript.regexp")
rxDot.Global = True
rxDot.Pattern = "\."
Set rxWSp = CreateObject("vbscript.regexp")
rxWSp.Global = True
rxWSp.Pattern = "\s+"

' Column 1 Regex
' ==================
Set rxC1 = CreateObject("vbscript.regexp")
rxC1.Global = False
rxC1.Pattern = "^[ ]?([^ ,()""']+)(?:([ ]\([^)]*\)))?(?:([ ][^ ,()""'])([^ ,()""']*))?(?:([ ]([""']).*?)\6)?[ ]([^ ,()""']+)(?:[, ]*([ ].+?)[ ]?|.*?)?$"

' Column 2 Regex
' ==================
Set rxC2 = CreateObject("vbscript.regexp")
rxC2.Global = False
rxC2.Pattern = "^[ ]?([^ ,()""']+)(?:([ ][^ ,()""']+))?,([^ ,()""']+)(?:([ ][^ ,()""'])([^ ,()""']*))?.*$"

' Normalize column 1 and 2, Copy to new var
' ============================================
strC1_Normal = rxDot.Replace(rxWSp.Replace(strC1, " "), "")
strC2_Normal = rxDot.Replace(rxWSp.Replace(strC2, " "), "")

' Comparison (Type 2) of Normalized column 1,2 values
' ============================================
strC1_2 = rxC1.Replace(strC1_Normal, "$7$8,$1$3")
strC2_2 = rxC2.Replace(strC2_Normal, "$1$2,$3$4")

If strC1_2 = strC2_2 Then
   MsgBox ("Type 2 values are EQUAL")
Else
   MsgBox ("Type 2 values are NOT Equal")
End If

End Sub

Paren/报价响应

As a side note, I will need to eliminate the quotes from the nicknames and the parentheses from the preferred names.

如果我理解正确..

是的,您可以分别捕获引号和括号内的内容。
它只需要一些修改。下面的正则表达式能够用或不带引号和/或括号 或其他形式 来
制定替换。

下面的示例提供了制定替换的方法。

非常重要的注意事项

如果您正在谈论从
匹配的正则表达式中删除引号“”和括号 (),那么也可以这样做。它需要一个新的正则表达式。

唯一的问题是首选/中间/昵称之间的所有区别
都被抛到了窗外,因为它们是位置和定
界的(即:(首选)中间“昵称”)。

考虑到这一点将需要像这样的正则表达式子表达式

(?:[ ]([^ ,]+))?   # optional preferred
(?:[ ]([^ ,]+))?   # optional middle
(?:[ ]([^ ,]+))?   # optional nick

并且,它们是可选的,丢失所有位置参考并使中间初始
表达式无效。

尾注

正则表达式模板(用于制定替换字符串)

^
  [ ]?

# (required) 
   # First
   #  $1  name
   # -----------------------------------------
    ([^\ ,()"']+)                 # (1) name     

# (optional)
   # Parenthetical 'preferred'
   #  $2    all
   #  $3$4  name
   # -----------------------------------------
    (?: (                         #  (2)   all  
           ([ ]) \( ([^)]*) \)    #  (3,4) space and name
        )
    )?  

# (optional)
  # Middle
  #   $5    initial
  #   $5$6  name
  # -----------------------------------------
    (?:  ([ ] [^\ ,()"'] )       #  (5) first character
         ([^\ ,()"']*)           #  (6) remaining characters

    )?                                   

# (optional)
   # Quoted nick                       
   #  $7$8$9$8  all
   #  $7$9      name
   # -----------------------------------------
    (?: ([ ])                    # (7) space
        (["'])                   # (8) quote
        (.*?)                    # (9) name
        \8 
    )?

# (required)
   #  Last
   #  $10  name
   # -----------------------------------------
    [ ] ([^\ ,()"']+)            # (10) name

# (optional)
   # Suffix 
   #  $11  suffix
   # -----------------------------------------
    (?:    [, ]* ([ ].+?) [ ]?   # (11) suffix
        |  .*?
    )?
$

VBA 正则表达式(第 2 版,在我的 VBA 项目中从上面测试)

rxC1.Pattern = "^[ ]?([^ ,()""']+)(?:(([ ])\(([^)]*)\)))?(?:([ ][^ ,()""'])([^ ,()""']*))?(?:([ ])([""'])(.*?)\8)?[ ]([^ ,()""']+)(?:[, ]*([ ].+?)[ ]?|.*?)?$"


strC1_1a  = rxC1.Replace( strC1_Normal, "$10$11,$1$2$5$6$7$8$9$8" )
strC1_1aa = rxC1.Replace( strC1_Normal, "$10$11,$1$3$4$5$6$7$9" )
strC1_1b  = rxC1.Replace( strC1_Normal, "$10$11,$1$2$5$7$8$9$8" )
strC1_1bb = rxC1.Replace( strC1_Normal, "$10$11,$1$3$4$5$7$9" )
strC1_2   = rxC1.Replace( strC1_Normal, "$10$11,$1$5" )

示例输入/输出可能性

Input (raw)                 = 'John (Johnny) Bertrand "Abe" Smith, Jr.  '

Out type 1a  full middle    = 'Smith Jr,John (Johnny) Bertrand "Abe"'
Out type 1aa full middle    = 'Smith Jr,John Johnny Bertrand Abe'
Out type 1b  middle initial = 'Smith Jr,John (Johnny) B "Abe"'
Out type 1bb middle initial = 'Smith Jr,John Johnny B Abe'
Out type 2   middle initial = 'Smith Jr,John B'

Input (raw)                 = 'John  (Johnny)  Smith, Jr.'

Out type 1a  full middle    = 'Smith Jr,John (Johnny)'
Out type 1aa full middle    = 'Smith Jr,John Johnny'
Out type 1b  middle initial = 'Smith Jr,John (Johnny)'
Out type 1bb middle initial = 'Smith Jr,John Johnny'
Out type 2   middle initial = 'Smith Jr,John'


Input (raw)                 = 'John  (Johnny)  "Abe" Smith, Jr.'

Out type 1a  full middle    = 'Smith Jr,John (Johnny) "Abe"'
Out type 1aa full middle    = 'Smith Jr,John Johnny Abe'
Out type 1b  middle initial = 'Smith Jr,John (Johnny) "Abe"'
Out type 1bb middle initial = 'Smith Jr,John Johnny Abe'
Out type 2   middle initial = 'Smith Jr,John'


Input (raw)                 = 'John   "Abe" Smith, Jr.'

Out type 1a  full middle    = 'Smith Jr,John "Abe"'
Out type 1aa full middle    = 'Smith Jr,John Abe'
Out type 1b  middle initial = 'Smith Jr,John "Abe"'
Out type 1bb middle initial = 'Smith Jr,John Abe'
Out type 2   middle initial = 'Smith Jr,John'

回复:4/17 关注

last names that have 2 or more words. Would the allowance for certain literal names, rather than generic word patterns, be the solution?

实际上,不,它不会。在这种情况下,对于您的表单,允许姓氏中有多个单词
会将空格字段分隔符注入姓氏字段。

但是,对于您的特定表格,可以这样做,因为唯一的障碍是该
"nick"字段丢失时。当它缺失并且中间名中只有一个单词时
,会出现 2 个排列。

希望您可以从下面的 3 个正则表达式和测试用例输出中获得解决方案。正则表达式从捕获中删除了空间分隔符。因此,您可以使用
Replace 方法组合替换,或者仅存储捕获缓冲区以与
其他列的捕获方案的结果进行比较。

Nick_rx.Pattern (template)

* This pattern is multi-word last name, NICK is required 

^
  [ ]?

   # First (req'd)
    ([^\ ,()"']+)              # (1) first name

   # Preferred first
    (?: [ ]
       (                       # (2) (preferred), -or-
         \( ([^)]*?) \)        # (3) preferred
       )
    )?  

   # Middle
    (?: [ ]
        (                      # (4) full middle, -or-
          ([^\ ,()"'])         # (5) initial
          [^\ ,()"']*
        )
    )?

   # Quoted nick (req'd)
     [ ]
     (                         # (6) "nick",
       (["'])   # (7) n/a        -or-
       (.*?)                   # (8)  nick
       \7
     )

   # Single/Multi Last (req'd)
    [ ]
    (                          # (9) multi/single word last name
      [^\ ,()"']+
      (?:[ ][^\ ,()"']+)*
    )

   # Suffix 
    (?: [ ]? , [ ]? (.*?) )?   # (10) suffix

  [ ]?
$

-----------------------------------

FLs_rx.Pattern (template)

* This pattern has no MIDDLE/NICK, is single-word last name,
* and has no permutations.

^
  [ ]?

   # First (req'd)
    ([^\ ,()"']+)              # (1) first name

   # Preferred first
    (?: [ ]
       (                       # (2) (preferred), -or-
         \( ([^)]*?) \)        # (3)  preferred
       )
    )?  

   # Single Last (req'd)
     [ ]
     ([^\ ,()"']+)             # (4) single word last name

   # Suffix 
    (?: [ ]? , [ ]? (.*?) )?   # (5) suffix

  [ ]?
$

-----------------------------------

FLm_rx.Pattern (template)

* This pattern has no NICK, is multi-word last name,
* and has 2 permutations.
* 1. Middle as part of Last name.
* 2. Middle is separate from Last name.

^
  [ ]?

   # First (req'd)
    ([^\ ,()"']+)              # (1) first name

   # Preferred first
    (?: [ ]
       (                       # (2) (preferred), -or-
         \( ([^)]*?) \)        # (3)  preferred
       )
    )?  

   # Multi Last (req'd)
    [ ]
    (                         # (4) Multi, as Middle + Last,
                              # -or-
       (?:                         # Middle
          (                        # (5) full middle, -or-
             ([^\ ,()"'])          # (6) initial
             [^\ ,()"']*
          )
          [ ]
       )
                                   # Last (req'd)
       (                           # (7) multi/single word last name
          [^\ ,()"']+
          (?:[ ][^\ ,()"']+)* 
       )
    )

   # Suffix 
    (?: [ ]? , [ ]? (.*?) )?   # (8) suffix

  [ ]?
$

-----------------------------------

Each of these regexes are mutually exclusive and should be checked
in an if-then-else like this (Pseudo code):

str_Normal = rxDot.Replace(rxWSp.Replace(str, " "), "")

If  Nick_rx.Test(str_Normal) Then
     N_1a  = rxWSp.Replace( Nick_rx.Replace(str_Normal, "$9 $10 , $1 $2 $4 $6 "), " ")
     N_1aa = rxWSp.Replace( Nick_rx.Replace(str_Normal, "$9 $10 , $1 $3 $4 $8 "), " ")
     N_1b  = rxWSp.Replace( Nick_rx.Replace(str_Normal, "$9 $10 , $1 $2 $5 $6 "), " ")
     N_1bb = rxWSp.Replace( Nick_rx.Replace(str_Normal, "$9 $10 , $1 $3 $5 $8 "), " ")
     N_2   = rxWSp.Replace( Nick_rx.Replace(str_Normal, "$9 $10 , $1 $5 "), " ")

     ' see test case results in output below
Else

If FLs_rx.Test(str_Normal) Then

     FLs_1a  = rxWSp.Replace( FLs_rx.Replace(str_Normal, "$4 $5 , $1 $2 "), " ")
     FLs_1aa = rxWSp.Replace( FLs_rx.Replace(str_Normal, "$4 $5 , $1 $3 "), " ")
     FLs_2   = rxWSp.Replace( FLs_rx.Replace(str_Normal, "$4 $5 , $1 "), " ")

Else

If FLm_rx.Test(str_Normal) Then

   ' Permutation 1:
     FLm1_1a  = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$4 $8 , $1 $2 "), " ")
     FLm1_1aa = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$4 $8 , $1 $3 "), " ")
     FLm1_2   = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$4 $8 , $1 "), " ")

  ' Permutation 2:
     FLm2_1a  = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$7 $8 , $1 $2 $5 "), " ")
     FLm2_1aa = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$7 $8 , $1 $3 $5 "), " ")
     FLm2_1b  = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$7 $8 , $1 $2 $6 "), " ")
     FLm2_1bb = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$7 $8 , $1 $3 $6 "), " ")
     FLm2_2   = rxWSp.Replace( FLm_rx.Replace(str_Normal, "$7 $8 , $1 $6 "), " ")

  ' At this point, the odds are that only one of these permutations will match 
  ' a different column.

Else

     ' The data could not be matched against a valid form
End If

-----------------------------

Test Cases

Found form 'Nick'
Input (raw)                 = 'John1 (JJ) Bert "nick" St Van Helsing ,Jr '
Normal                      = 'John1 (JJ) Bert "nick" St Van Helsing ,Jr '

Out type 1a  full middle    = 'St Van Helsing Jr , John1 (JJ) Bert "nick" '
Out type 1aa full middle    = 'St Van Helsing Jr , John1 JJ Bert nick '
Out type 1b  middle initial = 'St Van Helsing Jr , John1 (JJ) B "nick" '
Out type 1bb middle initial = 'St Van Helsing Jr , John1 JJ B nick '
Out type 2   middle initial = 'St Van Helsing Jr , John1 B '

=======================================================

Found form 'Nick'
Input (raw)                 = 'John2 Bert "nick" Helsing ,Jr '
Normal                      = 'John2 Bert "nick" Helsing ,Jr '

Out type 1a  full middle    = 'Helsing Jr , John2 Bert "nick" '
Out type 1aa full middle    = 'Helsing Jr , John2 Bert nick '
Out type 1b  middle initial = 'Helsing Jr , John2 B "nick" '
Out type 1bb middle initial = 'Helsing Jr , John2 B nick '
Out type 2   middle initial = 'Helsing Jr , John2 B '

=======================================================

Found form 'Nick'
Input (raw)                 = 'John3 Bert "nick" St Van Helsing ,Jr '
Normal                      = 'John3 Bert "nick" St Van Helsing ,Jr '

Out type 1a  full middle    = 'St Van Helsing Jr , John3 Bert "nick" '
Out type 1aa full middle    = 'St Van Helsing Jr , John3 Bert nick '
Out type 1b  middle initial = 'St Van Helsing Jr , John3 B "nick" '
Out type 1bb middle initial = 'St Van Helsing Jr , John3 B nick '
Out type 2   middle initial = 'St Van Helsing Jr , John3 B '

=======================================================

Found form 'First-Last (single)'
Input (raw)                 = 'John4 Helsing '
Normal                      = 'John4 Helsing '

Out type 1a  no middle      = 'Helsing  , John4  '
Out type 1aa no middle      = 'Helsing  , John4  '
Out type 2                  = 'Helsing  , John4 '

=======================================================

Found form 'First-Last (single)'
Input (raw)                 = 'John5 (JJ) Helsing '
Normal                      = 'John5 (JJ) Helsing '

Out type 1a  no middle      = 'Helsing  , John5 (JJ) '
Out type 1aa no middle      = 'Helsing  , John5 JJ '
Out type 2                  = 'Helsing  , John5 '

=======================================================

Found form 'First-Last (multi)'
Input (raw)                 = 'John6 (JJ) Bert St Van Helsing ,Jr '
Normal                      = 'John6 (JJ) Bert St Van Helsing ,Jr '

Permutation 1:
Out type 1a  no middle      = 'Bert St Van Helsing Jr , John6 (JJ) '
Out type 1aa no middle      = 'Bert St Van Helsing Jr , John6 JJ '
Out type 2                  = 'Bert St Van Helsing Jr , John6 '
Permutation 2:
Out type 1a  full middle    = 'St Van Helsing Jr , John6 (JJ) Bert '
Out type 1aa full middle    = 'St Van Helsing Jr , John6 JJ Bert '
Out type 1b  middle initial = 'St Van Helsing Jr , John6 (JJ) B '
Out type 1bb middle initial = 'St Van Helsing Jr , John6 JJ B '
Out type 2   middle initial = 'St Van Helsing Jr , John6 B '

=======================================================

Found form 'First-Last (multi)'
Input (raw)                 = 'John7 Bert St Van Helsing ,Jr '
Normal                      = 'John7 Bert St Van Helsing ,Jr '

Permutation 1:
Out type 1a  no middle      = 'Bert St Van Helsing Jr , John7 '
Out type 1aa no middle      = 'Bert St Van Helsing Jr , John7 '
Out type 2                  = 'Bert St Van Helsing Jr , John7 '
Permutation 2:
Out type 1a  full middle    = 'St Van Helsing Jr , John7 Bert '
Out type 1aa full middle    = 'St Van Helsing Jr , John7 Bert '
Out type 1b  middle initial = 'St Van Helsing Jr , John7 B '
Out type 1bb middle initial = 'St Van Helsing Jr , John7 B '
Out type 2   middle initial = 'St Van Helsing Jr , John7 B '

=======================================================

Form  ***  (unknown)
Input (raw)                 = ' do(e)s not. match ,'
Normal                      = ' do(e)s not match ,'

=======================================================
于 2012-03-31T01:34:32.427 回答