大家好,提前感谢你们的见解
我的 Excel 数据如下所示
Cell A1 Cell B1
x | y | z 1 | 2 | 3
我需要对两者进行匹配并创建如下数据集:
x 1
y 2
z 3
希望这有点道理...
起始数据超过 20K 行。单元格 A1 和 B1 中的数据都是分隔的,但它们并不总是包含相同数量的元素,但它们始终具有相同数量的元素它们之间, 例如:
Cell A2 Cell B2
d | e 5 | 6
Cell A3 Cell B3
f | g | h | i 7 | 8 | 9 | 10
我最终需要修改所有数据,使其看起来像下面这样 - 例如,将字母和数字放在单独的列中
Column H Column I
x 1
y 2
z 3
d 5
e 6
f 7
g 8
h 9
i 10
希望这能让你理解!我自己都搞糊涂了……
我尝试过将文本切换为列,并尝试使用数据透视表,但没有成功。任何提示都将不胜感激!
编辑:应该补充一点,以上是虚拟数据,我的真实数据不是固定长度的。
edit2(非常抱歉)-我附上了一张截图,希望能更好地解释我需要什么……前两行是我所拥有的,从第 7 行开始在截图中正是我需要的。
答案1
并不理想,但这是一种实现任务的非 vba 方法。
首先,确定数据中可以看到的最大值数量。假设是 4。在当前的 A 列和 B 列之间插入 4+1 (5) 列。
其次,使用文本到列向导来分隔数据(您有条形分隔符,因此通过向导可以轻松实现)。对两个数据集执行此操作。因此,每个单元格将具有唯一的值。
现在您应该有两“组”数据。
选择集合 1 (A1:D3),然后右键单击并将名称定义为“first_value”。
选择集合 2 (F1:I3),然后右键单击并将名称定义为“second_value”。
接下来输入以下公式:
L1: =INDEX(first_value,1+INT((ROW(A1)-1)/COLUMNS(first_value)),MOD(ROW(A1)-1+COLUMNS(first_value),COLUMNS(first_value))+1)
M1: =INDEX(second_value,1+INT((ROW(F1)-1)/COLUMNS(second_value)),MOD(ROW(F1)-1+COLUMNS(second_value),COLUMNS(second_value))+1)
将公式向下拖动到您需要的位置,直到收到 #REF 错误。
现在您需要决定如何处理空行。它们目前在 L 和 M 列中都有 0。您可以将这些完整的列复制到另一张表,粘贴为特殊值以删除公式,然后对这些 0 执行额外的清理。排序和删除是一种选择。只要 0 0 的组合永远不是真实数据,那么这可能是删除它的最简单方法。如果您的实际数据中恰好有 0 0,那么您需要修改公式。
答案2
请尝试下面的代码。
使用方法 - 选择要转换的单元格范围。选定的范围必须有 2 列。
Option Explicit
Public Sub SplitAndPivot()
Dim r As Range
Dim msg_result As Integer
Dim msg_title As String
Dim exit_suffix As String
Dim rw As Range
Dim nms As String
Dim ids As String
Dim new_sheet As Worksheet
Dim new_sheetname As String
Dim new_sheetrow As Integer
Dim arr_nms() As String
Dim arr_ids() As String
Dim arr_i As Integer
Dim ws As Worksheet
Dim sheet_prefix As String
sheet_prefix = "SplitAndPivot"
msg_title = "Split and pivot"
exit_suffix = vbCrLf & "No transformation done."
msg_result = MsgBox("Do you want to remove " & sheet_prefix & " sheets created earlier?", vbYesNoCancel, msg_title)
If msg_result = 6 Then
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
If Left(ws.Name, Len(sheet_prefix)) = sheet_prefix Then
ws.Delete
End If
Next ws
Application.DisplayAlerts = True
Application.ScreenUpdating = True
ElseIf msg_result = 2 Then
MsgBox "You selected Cancel or closed the message box." & exit_suffix, vbInformation, msg_title
Exit Sub
End If
msg_result = MsgBox("Have you selected the cells you want to transform?", vbYesNoCancel, msg_title)
'Yes = 6
'No = 7
'Cancel = 2
'X = 2
If msg_result <> 6 Then
MsgBox "You selected No, Cancel or closed the message box." & exit_suffix, vbInformation, msg_title
Exit Sub
End If
Set r = Selection
If r.Columns.Count <> 2 Then
MsgBox "You must select a range with two columns." & exit_suffix, vbCritical, msg_title
Exit Sub
End If
Application.ScreenUpdating = False
new_sheetname = sheet_prefix & "_" & Format(Now(), "YYYYMMDD_HHmmSS")
Set new_sheet = ThisWorkbook.Worksheets.Add
With new_sheet
.Name = new_sheetname
.Cells(1, 1) = "Name"
.Cells(1, 2) = "ID"
.Cells(1, 3) = "SourceRange"
End With
new_sheet.Name = new_sheetname
new_sheetrow = 2
'Iterate through each selected row, split the values and pivot them on to the new sheet
For Each rw In r.Rows
nms = rw.Cells(1, 1)
ids = rw.Cells(1, 2)
Debug.Print "Processing:", rw.Address, nms, ids
arr_nms = Split(nms, " | ")
arr_ids = Split(ids, " | ")
If UBound(arr_nms) <> UBound(arr_ids) Then
Application.ScreenUpdating = True
MsgBox "Number of ID elements is different to number of Name elements in range " & rw.Address & exit_suffix, vbCritical, msg_title
Exit Sub
End If
For arr_i = 0 To UBound(arr_nms)
Debug.Print arr_i, arr_nms(arr_i), arr_ids(arr_i)
With new_sheet
.Cells(new_sheetrow, 1) = arr_nms(arr_i)
.Cells(new_sheetrow, 2) = arr_ids(arr_i)
.Cells(new_sheetrow, 3) = rw.Address
End With
new_sheetrow = new_sheetrow + 1
Next arr_i
Next rw
Application.ScreenUpdating = True
MsgBox "Finished transforming selected range.", vbOKOnly, msg_title
End Sub
答案3
这也可以通过 Power Query 来实现,可在 Windows Excel 2010+ 和 Excel 365(Windows 或 Mac)中使用
使用 Power Query
- 在数据表中选择一些单元格
Data => Get&Transform => from Table/Range
或者from within sheet
- 当 PQ 编辑器打开时:
Home => Advanced Editor
- 记下表格姓名在第 2 行
- 将下面的 M 代码粘贴到您所看到的位置
- 将第 2 行的表名改回最初生成的表名。
- 阅读评论并探索
Applied Steps
以了解算法
let
//change next line to reflect actual data source in your workbook
Source = Excel.CurrentWorkbook(){[Name="Table14"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Col A", type text}, {"Col B", type text}}),
//create a "List" from each column
//then create a "Table" from the two lists
Result = Table.FromColumns(
{List.Combine(List.Transform(#"Changed Type"[Col A], each Text.Split(_,"|")))} &
//Transform Col B values to numbers depending on your actual data
{List.Transform(
List.Combine(List.Transform(#"Changed Type"[Col B], each Text.Split(_,"|"))), each Number.From(_))},
type table[Col A=text, Col B=Int64.Type])
in
Result