【问题标题】:Separating data and placing in individual worksheets Excel VBA [closed]分离数据并放入单个工作表 Excel VBA [关闭]
【发布时间】:2012-08-11 11:09:29
【问题描述】:

我有一个大型数据集,其中包含以下形式的 80K 条目:

        Name                        Date           Value
        1T17_4H19_3T19_3T21_2_a_2   09-Aug-11   -9.3159
        1T17_4H19_3T19_3T21_2_a_2   10-Aug-11   -6.9662
        1T17_4H19_3T19_3T21_2_a_2   11-Aug-11   -3.4886
        1T17_4H19_3T19_3T21_2_a_2   12-Aug-11   -1.2357
        1T17_4H19_3T19_3T21_2_a_2   15-Aug-11   0.1172
        5 25_4Q27_4T30_4H34_3_3_3   19-Jun-12   -2.0805
        5 25_4Q27_4T30_4H34_3_3_3   20-Jun-12   -1.9802
        5 25_4Q27_4T30_4H34_3_3_3   21-Jun-12   -2.8344
        5 25_4Q27_4T30_4Q32_a_a_a   25-Sep-07   -0.5779
        5 25_4Q27_4T30_4Q32_a_a_a   26-Sep-07   -0.8214
        5 25_4Q27_4T30_4Q32_a_a_a   27-Sep-07   -1.4061

这些数据都包含在一个工作表中。我希望 excel 根据名称分隔数据,然后将每个时间序列放在同一工作簿中的单独工作表中。 VBA 可以做到这一点吗?

【问题讨论】:

  • 使用 VBA 相当容易。您应该做的第一件事是录制宏并手动将数据移动到您想要的位置。您可以修改录制的宏以满足您的需要。
  • 明确地说,您希望将此数据放在一个工作表中,并根据名称将其放置在单独的工作表中。对吗?
  • 也许只下载 ASAP 实用程序?我有自己的代码来执行此操作,但这个工具看起来非常有用:asap-utilities.com/blog/index.php/2010/02/11/…
  • 我忘记了这是一个付费实用程序,尽管您可以获得 90 天的试用期。这是一个示例工作簿的链接,可以满足您的需求:blog.contextures.com/archives/2012/02/21/…
  • Remnant- 是的,这完全正确。餐饮部主管 - 当我按名称排序时,我不确定如何通过 VBA 执行此操作,即使通过记录宏,因为数据都是相邻的。感谢您的链接道格!不幸的是,我在 Mac 上,它是一个仅限 Windows 的程序......否则它看起来很理想!

标签: excel worksheet-function vba


【解决方案1】:

如果您想录制宏以查看发生了什么,请按照以下步骤操作:

  1. 打开宏记录器
  2. 按名称对数据进行排序
  3. 从名字复制数据
  4. 将其粘贴到另一张纸上(如果需要,请添加另一张纸)
  5. 为工作表命名
  6. 下一个名字重复

我还编写了一些代码供您开始使用。为此,您需要将数据选项卡命名为“MasterList”。代码按名称对 MasterList 上的行进行排序,然后为列表中的每个唯一名称创建一个新工作表并将适当的数据复制到新工作表,重复该过程直到所有名称都复制到新工作表。

将此代码添加到模块并运行DispatchTimeSeriesToSheets 过程。

Sub DispatchTimeSeriesToSheets()
    Dim ws As Worksheet
    Set ws = Sheets("MasterList")
    Dim LastRow As Long

    LastRow = Range("A" & ws.Rows.Count).End(xlUp).Row

    ' stop processing if we don't have any data
    If LastRow < 2 Then Exit Sub

    Application.ScreenUpdating = False
    SortMasterList LastRow, ws
    CopyDataToSheets LastRow, ws
    ws.Select
    Application.ScreenUpdating = True
End Sub

Sub SortMasterList(LastRow As Long, ws As Worksheet)
    ws.Range("A2:C" & LastRow).Sort Key1:=ws.Range("A1"), Key2:=ws.Range("B1")
End Sub

Sub CopyDataToSheets(LastRow As Long, src As Worksheet)
    Dim rng As Range
    Dim cell As Range
    Dim Series As String
    Dim SeriesStart As Long
    Dim SeriesLast As Long

    Set rng = Range("A2:A" & LastRow)
    SeriesStart = 2
    Series = Range("A" & SeriesStart).Value
    For Each cell In rng
        If cell.Value <> Series Then
            SeriesLast = cell.Row - 1
            CopySeriesToNewSheet src, SeriesStart, SeriesLast, Series
            Series = cell.Value
            SeriesStart = cell.Row
        End If
    Next
    ' copy the last series
    SeriesLast = LastRow
    CopySeriesToNewSheet src, SeriesStart, SeriesLast, Series

End Sub

Sub CopySeriesToNewSheet(src As Worksheet, Start As Long, Last As Long, _
                                                        name As String)
    Dim tgt As Worksheet

    If (SheetExists(name)) Then
        MsgBox "Sheet " & name & " already exists. " _
        & "Please delete or move existing sheets before" _
        & " copying data from the Master List.", vbCritical, _
        "Time Series Parser"
        End
    End If

    Worksheets.Add(After:=Worksheets(Worksheets.Count)).name = name
    Set tgt = Sheets(name)

    ' copy header row from src to tgt
    tgt.Range("A1:C1").Value = src.Range("A1:C1").Value

    ' copy data from src to tgt
    tgt.Range("A2:C" & Last - Start + 2).Value = _
        src.Range("A" & Start & ":C" & Last).Value
End Sub

Function SheetExists(name As String) As Boolean
    Dim ws As Worksheet

    SheetExists = True
    On Error Resume Next
    Set ws = Sheets(name)
    If ws Is Nothing Then
       SheetExists = False
    End If
End Function

【讨论】:

  • 这也很有效。谢谢你。录制宏的问题是系列的长度不同,所以第 (3) 部分会引起问题吗?但是您的代码确实很有效。谢谢!
  • @Mary,宏记录器绝对只是一个起点。您的问题解决起来很有趣——很高兴它对您有用。
  • 您好,餐饮主管和@Remnant。是否可以使用此代码以完全相同的方式分隔数据,除了根据名称中的第二个(或第三个)元素(例如 1T17_4H19_3T19_3T21_2_a_2 中的 4H19?)。因此,在创建的每张工作表中,每个名称都会有一列包含第二个元素(该列将像以前一样包含时间序列)。你们用一点代码就能做的事情真是太棒了!
  • 你可以。查找 Mid 函数并将其用于名称。这是一个很好的链接:techrepublic.com/article/…
【解决方案2】:

我尝试了这段代码,它对我有用。

这将拆分数据(基于唯一名称)并将其粘贴到一个单独的工作表中,该工作表的名称将与 A 列中的名称相同。

Sub SplitData()
    Dim DataMarkers(), Names As Range, name As Range, n As Long, i As Long

    Set Names = Range("A2:A" & Range("A1").End(xlDown).Row)
    n = 0

    DeleteWorksheets

    For Each name In Names
        If name.Offset(1, 0) <> name Then
            ReDim Preserve DataMarkers(n)
            DataMarkers(n) = name.Row
            Worksheets.Add(After:=Worksheets(Worksheets.Count)).name = name
            n = n + 1
        End If
    Next name

    For i = 0 To UBound(DataMarkers)
        If i = 0 Then
            Worksheets(1).Range("A2:C" & DataMarkers(i)).Copy Destination:=Worksheets(i + 2).Range("A1")
        Else
            Worksheets(1).Range("A" & (DataMarkers(i - 1) + 1) & ":C" & DataMarkers(i)).Copy Destination:=Worksheets(i + 2).Range("A1")
        End If
    Next i
End Sub

Sub DeleteWorksheets()
    Dim ws As Worksheet, activeShtIndex As Long, i As Long

    activeShtIndex = ActiveSheet.Index

    Application.DisplayAlerts = False
    For i = ThisWorkbook.Worksheets.Count To 1 Step -1
        If i <> activeShtIndex Then
            Worksheets(i).Delete
        End If
    Next i
    Application.DisplayAlerts = True
End Sub

我在这段代码中所做的是:

  1. 删除除具有初始数据表的工作表之外的所有工作表
  2. 向下处理“名称”列并创建一个“标记”数组,指示每个数据拆分的位置
  3. 创建一个新工作表并根据数组中的值将数据复制到其中

【讨论】:

  • 效果很好!谢谢!正是我需要的。感谢您的帮助。
猜你喜欢
  • 2011-03-16
  • 1970-01-01
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
相关资源
最近更新 更多