文本到列 - 具有不同数量空格的统一响应
Text to columns - Uniform response with different numbers of Spaces
我有一个电子表格,其中 A 列是姓名列表。其中一些名字有头衔(例如,John Doe 先生、Jane Doe 小姐、Jane Bloggs 夫人、Cllr Joe Bloggs 等),有些名字没有(只有 Joe Doe、John Bloggs、Jane Doe 等)。我被要求将名字分成三列 - 标题、名字、姓氏。
当我尝试简单的 "text to columns" 时,有标题的地方没问题,但没有标题的地方,名字默认为标题列。
有没有办法将数据拆分到正确的单元格中,或者这对某人来说是否需要大量的手动工作?
如果我必须这样做,那么我使用'Text to columns'。之后我按第三列排序。
现在所有只有 2 个值的行都一个接一个地列出。我标记所有这些行的第一列,按 'Ctrl + or' 或单击鼠标右键和 select 'insert cells'。然后系统会询问您是喜欢向下移动还是向右移动。 Select向右移动,一个单元格随心所欲地排列。
您可以使用 VBA 来完成此操作。
您将创建两个不同的数组。第一个是您的原始数据(您的单列)preArr()
,以及将写回工作表 postArr()
的新数组,该数组已针对三列 ReDim postArr(..., 1 To 3)
.
首先,测试来自 preArr(i, 1)
的字符串是否包含已知的称呼。如果是,则将第一个拆分字符串添加到 postArr(, 1)
- 否则您将不会向此列添加任何内容。
Side Note: You can add additional salutations to this line:
.Pattern = "^(?:MRS?|MS|MIS+|CLLR|DR)\.?\s"
This is a regular expression, but just add another |
separator for additional checks. I combined MR and MRS into one group, the ?
makes the S
optional in case you were wondering.
这是完整的程序:
Option Explicit
Sub splitOnNames()
Dim preArr(), postArr(), ws As Worksheet, preRng As Range
Set ws = Selection.Parent
Set preRng = Selection
preArr = preRng.Value
If UBound(preArr, 2) > 1 Then
MsgBox "This can only be done on a single column!", vbCritical
Exit Sub
End If
ReDim postArr(LBound(preArr) To UBound(preArr), 1 To 3)
Dim i As Long, x As Long, tmpArr
For i = LBound(preArr) To UBound(preArr)
If preArr(i, 1) <> "" Then
tmpArr = Split(preArr(i, 1))
If testSalutation(preArr(i, 1)) Then
postArr(i, 1) = tmpArr(0)
postArr(i, 2) = tmpArr(1)
For x = 2 To UBound(tmpArr) 'Some last names have two names
postArr(i, 3) = Trim(postArr(i, 3) & " " & tmpArr(x))
Next x
Else
postArr(i, 2) = tmpArr(0)
For x = 1 To UBound(tmpArr) 'Some last names have two names
postArr(i, 3) = Trim(postArr(i, 3) & " " & tmpArr(x))
Next x
End If
Erase tmpArr
End If
Next i
With preRng
Dim postRng As Range
Set postRng = ws.Range(ws.Cells(.Row, .Column), _
ws.Cells(.Rows.Count + .Row - 1, .Column + 2))
postRng.Value = postArr
End With
End Sub
Private Function testSalutation(ByVal testStr As String) As Boolean
With CreateObject("VBScript.RegExp")
.IgnoreCase = True
.Pattern = "^(?:MRS?|MS|MIS+|CLLR|DR)\.?\s"
testSalutation = .Test(testStr)
End With
End Function
现场观看:
我有一个电子表格,其中 A 列是姓名列表。其中一些名字有头衔(例如,John Doe 先生、Jane Doe 小姐、Jane Bloggs 夫人、Cllr Joe Bloggs 等),有些名字没有(只有 Joe Doe、John Bloggs、Jane Doe 等)。我被要求将名字分成三列 - 标题、名字、姓氏。
当我尝试简单的 "text to columns" 时,有标题的地方没问题,但没有标题的地方,名字默认为标题列。
有没有办法将数据拆分到正确的单元格中,或者这对某人来说是否需要大量的手动工作?
如果我必须这样做,那么我使用'Text to columns'。之后我按第三列排序。 现在所有只有 2 个值的行都一个接一个地列出。我标记所有这些行的第一列,按 'Ctrl + or' 或单击鼠标右键和 select 'insert cells'。然后系统会询问您是喜欢向下移动还是向右移动。 Select向右移动,一个单元格随心所欲地排列。
您可以使用 VBA 来完成此操作。
您将创建两个不同的数组。第一个是您的原始数据(您的单列)preArr()
,以及将写回工作表 postArr()
的新数组,该数组已针对三列 ReDim postArr(..., 1 To 3)
.
首先,测试来自 preArr(i, 1)
的字符串是否包含已知的称呼。如果是,则将第一个拆分字符串添加到 postArr(, 1)
- 否则您将不会向此列添加任何内容。
Side Note: You can add additional salutations to this line:
.Pattern = "^(?:MRS?|MS|MIS+|CLLR|DR)\.?\s"
This is a regular expression, but just add another
|
separator for additional checks. I combined MR and MRS into one group, the?
makes theS
optional in case you were wondering.
这是完整的程序:
Option Explicit
Sub splitOnNames()
Dim preArr(), postArr(), ws As Worksheet, preRng As Range
Set ws = Selection.Parent
Set preRng = Selection
preArr = preRng.Value
If UBound(preArr, 2) > 1 Then
MsgBox "This can only be done on a single column!", vbCritical
Exit Sub
End If
ReDim postArr(LBound(preArr) To UBound(preArr), 1 To 3)
Dim i As Long, x As Long, tmpArr
For i = LBound(preArr) To UBound(preArr)
If preArr(i, 1) <> "" Then
tmpArr = Split(preArr(i, 1))
If testSalutation(preArr(i, 1)) Then
postArr(i, 1) = tmpArr(0)
postArr(i, 2) = tmpArr(1)
For x = 2 To UBound(tmpArr) 'Some last names have two names
postArr(i, 3) = Trim(postArr(i, 3) & " " & tmpArr(x))
Next x
Else
postArr(i, 2) = tmpArr(0)
For x = 1 To UBound(tmpArr) 'Some last names have two names
postArr(i, 3) = Trim(postArr(i, 3) & " " & tmpArr(x))
Next x
End If
Erase tmpArr
End If
Next i
With preRng
Dim postRng As Range
Set postRng = ws.Range(ws.Cells(.Row, .Column), _
ws.Cells(.Rows.Count + .Row - 1, .Column + 2))
postRng.Value = postArr
End With
End Sub
Private Function testSalutation(ByVal testStr As String) As Boolean
With CreateObject("VBScript.RegExp")
.IgnoreCase = True
.Pattern = "^(?:MRS?|MS|MIS+|CLLR|DR)\.?\s"
testSalutation = .Test(testStr)
End With
End Function