将具有重复项的行换行

发布于 2024-11-06 09:22:43 字数 246 浏览 4 评论 0原文

我得到的数据如下所示:

BOB  | 4
BOB  | 3
BOB  | 7
MARY | 1
JOE  | 2
JOE  | 1
MIKE | 6

我希望最终得到如下所示的数据:

BOB  | 4 | 3 | 7
MARY | 1 |   |
JOE  | 2 | 1 |
MIKE | 6 |   |

问题是,如何解释名称出现的可变次数?

I've got data that looks like this:

BOB  | 4
BOB  | 3
BOB  | 7
MARY | 1
JOE  | 2
JOE  | 1
MIKE | 6

I want to end up with data that looks like this:

BOB  | 4 | 3 | 7
MARY | 1 |   |
JOE  | 2 | 1 |
MIKE | 6 |   |

The problem is, how do I account for the variable number of times a name shows up?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

呆橘 2024-11-13 09:22:43

我想出了以下代码。感觉还可以更干净一点。

这适用于工作表上任何选定的数据块(假设它已预先排序)。它在同一区域的同一张纸上输出。

Sub WrapDuplicates()
    Dim data(), i As Long, startCell As Range, rwCnt As Long, col As Long

    data = Selection //pull selected data into an array
    Set startCell = Selection.Cells(1, 1) //Get reference to write results to
    Selection.ClearContents //remove original data
    startCell = data(1, 1) //Output first name
    startCell.Offset(0, 1) = data(1, 2) //Output first value

    rwCnt = 0
    col = 2

    For i = 2 To UBound(data) //Loop through array and check if name is same or not and output accordingly
        If data(i, 1) = data(i - 1, 1) Then
            startCell.Offset(rwCnt, col) = data(i, 2)
            col = col + 1
        Else
            rwCnt = rwCnt + 1
            col = 2
            startCell.Offset(rwCnt, 0) = data(i, 1)
            startCell.Offset(rwCnt, 1) = data(i, 2)
        End If
    Next i
End Sub

I came up with the following code. It feels like it could be cleaner.

This will work for any selected block of data on your sheet (assuming it is pre-sorted). It outputs on the same sheet in the same area.

Sub WrapDuplicates()
    Dim data(), i As Long, startCell As Range, rwCnt As Long, col As Long

    data = Selection //pull selected data into an array
    Set startCell = Selection.Cells(1, 1) //Get reference to write results to
    Selection.ClearContents //remove original data
    startCell = data(1, 1) //Output first name
    startCell.Offset(0, 1) = data(1, 2) //Output first value

    rwCnt = 0
    col = 2

    For i = 2 To UBound(data) //Loop through array and check if name is same or not and output accordingly
        If data(i, 1) = data(i - 1, 1) Then
            startCell.Offset(rwCnt, col) = data(i, 2)
            col = col + 1
        Else
            rwCnt = rwCnt + 1
            col = 2
            startCell.Offset(rwCnt, 0) = data(i, 1)
            startCell.Offset(rwCnt, 1) = data(i, 2)
        End If
    Next i
End Sub
初心未许 2024-11-13 09:22:43

我假设您想在基于帖子中的 excel-vba 标签的代码中执行此操作。

我还假设数据按名称排序,或者您可以在代码执行之前按名称排序。

源位于工作表 1 中,目标位于工作表 2 中。代码位于 Excel VBA 中。我使用您的示例数据进行了测试,将此子例程放入 Excel 代码隐藏的 ThisWorkbook 部分并按播放键。

目标标头每次都会被重写,从性能角度来看这并不理想,但我认为否则不是问题。您可以将其包装在 if 语句中,该语句检查目标列索引 = 2(如果出现问题)。

Sub ColumnsToRows()

Dim rowHeading
Dim previousRowHeading
Dim sourceRowIndex
Dim targetRowIndex
Dim targetColumnIndex


sourceRowIndex = 1
targetRowIndex = 1
targetColumnIndex = 2

rowHeading = Sheet1.Cells(sourceRowIndex, 1)
previousRowHeading = rowHeading

While Not rowHeading = ""

    If Not previousRowHeading = rowHeading Then
        targetRowIndex = targetRowIndex + 1
        targetColumnIndex = 2
    End If

    Sheet2.Cells(targetRowIndex, 1) = rowHeading
    Sheet2.Cells(targetRowIndex, targetColumnIndex) = Sheet1.Cells(sourceRowIndex, 2)
    previousRowHeading = rowHeading

    sourceRowIndex = sourceRowIndex + 1
    targetColumnIndex = targetColumnIndex + 1
    rowHeading = Sheet1.Cells(sourceRowIndex, 1)

Wend

End Sub

我是一名开发人员,而不是 Excel 专家。可能有一些 Excel 函数、数据透视表或其他一些 Excel 魔法可以自动为您执行此操作。

I'm assuming you want to do this in code based on the excel-vba tag in your post.

I'm also assuming the data is sorted by name, or you are OK with sorting it by name before the code executes.

Source is in sheet 1, target is in sheet 2. Code is in Excel VBA. I tested with your sample data, dropping this subroutine in the ThisWorkbook section of the Excel codebehind and pressing play.

The target header gets rewritten every time, which isn't ideal from a performance perspective, but I don't think is a problem otherwise. You could wrap it in an if statement that checks the target column index = 2 if it becomes a problem.

Sub ColumnsToRows()

Dim rowHeading
Dim previousRowHeading
Dim sourceRowIndex
Dim targetRowIndex
Dim targetColumnIndex


sourceRowIndex = 1
targetRowIndex = 1
targetColumnIndex = 2

rowHeading = Sheet1.Cells(sourceRowIndex, 1)
previousRowHeading = rowHeading

While Not rowHeading = ""

    If Not previousRowHeading = rowHeading Then
        targetRowIndex = targetRowIndex + 1
        targetColumnIndex = 2
    End If

    Sheet2.Cells(targetRowIndex, 1) = rowHeading
    Sheet2.Cells(targetRowIndex, targetColumnIndex) = Sheet1.Cells(sourceRowIndex, 2)
    previousRowHeading = rowHeading

    sourceRowIndex = sourceRowIndex + 1
    targetColumnIndex = targetColumnIndex + 1
    rowHeading = Sheet1.Cells(sourceRowIndex, 1)

Wend

End Sub

I'm a developer, not an Excel guru. There may be some Excel function, pivot table, or some other Excel magic that does this for you automatically.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文