选择最新记录并在 Excel 中创建新的唯一值表

1 excel vba

我有一个 Excel 表格,用于记录车辆通过企业内工作站的进度。一个给定的工作站可以被多次访问。

\n\n

车辆牌照号(Reg No)用于识别车辆,当车辆到达下一个新工作站时,用户会在电子表格中添加新行。除了注册号之外,每行还有一个记录 ID。

\n\n

此工作流程意味着将为给定的注册号创建多个记录行。

\n\n

当车辆上的所有工作完成后,记录将被剪切并存档在另一个工作表上。

\n\n

当前车辆表

\n\n

我想要创建的是另一个工作表选项卡上的汇总表,其中显示正在进行的车辆的所有行。如果车辆当前有一条记录,我想提取该记录行,如果车辆有多个记录,我想仅提取最后一个(最新的)记录行。

\n\n

我希望摘要成为基础数据表的 \xe2\x80\x9clive\xe2\x80\x9d 反映。

\n\n

通过搜索,我找到了在 Excel 中忽略重复项和创建新的唯一值列表的公式示例,但这些示例默认选择第一个重复值,而不是最后一个。\xe2\x80\x9clookup 最后匹配\xe2\x80\x9d 或 \xe2\x80\x9creturn 最后一个值\xe2\x80\x9d 上的搜索结果的共同点是用户必须定义​​他们正在搜索的项目。

\n\n

我想我需要一些不同的东西,因为我的 Reg No 列表不是静态的 - 它不断被添加和删除(存档)的 Reg No\xe2\x80\x99s 刷新。

\n\n

承认并理解 Excel 不是数据库,但如果我用数据库/SQL 术语思考,我的(菜鸟)查询可能类似于:\nSELECT row\nWHERE Reg No 是唯一的\nAND Record ID 是最大的

\n\n

你知道有什么方法可以在 Excel 中实现我想要的结果吗?

\n

jef*_*eir 6

您可以使用数据透视表和查找公式来完成此操作。下面是 Excel 表(又名 ListObject)中的一些简化数据,下面是数据透视表,右侧有合适的查找公式。

在此输入图像描述

数据透视表中包含 Reg No,值(聚合)区域中的 RecordID 字段设置为“Max”。因此,基本上它会显示每个 Reg No 的最大 RecordID 值,然后在右侧的列中,有一个 INDEX/MATCH 公式,用于在数据输入表中查找该 RecordID,并返回关联的 Stage。

它还不太活跃,因为您需要刷新数据透视表,并且需要确保已将查找公式复制得足够远以处理数据透视表的大小。

只需将 Worksheet_Activate 事件处理程序放入工作表中,您就可以轻松地自动执行刷新。像这样的东西: Private Sub Worksheet_Activate() Activesheet.PivotTables("PivotTable").PivotCache.Refresh End Sub

由于我们现在已经涉及了 VBA,您可能还需要一些代码来将公式复制到数据透视表旁边所需的行数。我会在适当的时候制作一些东西并将其发布在这里。

更新:我已经编写了一些代码来将表从属于数据透视表,以便数据透视表尺寸或位置的任何更改都将反映在阴影表的尺寸和位置中。这有效地为我们提供了一种将计算字段添加到数据透视表的方法,该字段可以引用该数据透视表之外的内容,就像我们在这里使用 INDEX/MATCH 查找所做的那样。我们将该功能称为计算表

如果数据透视表增长,计算表也会增长。如果数据透视表缩小,计算表也会缩小,并且其中的任何冗余公式都将被删除。以下是您的示例的外观:顶部的表来自输入表,其下方的数据透视表和计算表来自结果表。

在此输入图像描述

如果我转到输入表并添加更多数据,那么当我切换回结果表时,数据透视表会自动使用新数据进行更新,并且计算表会自动扩展以容纳额外的行: 在此输入图像描述

这是我用来自动化执行此操作的代码:

Option Explicit

Private Sub Worksheet_Activate()
    ActiveSheet.PivotTables("Report").PivotCache.Refresh
End Sub

Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)

    If Target.Name = "Report" Then _
        PT_SyncTable Target, ActiveSheet.ListObjects("SyncedTable")
End Sub


Sub PT_SyncTable(oPT As PivotTable, _
                oLO As ListObject, _
                Optional bIncludeTotal As Boolean = False)

    Dim lLO As Long
    Dim lPT As Long

    'Make sure oLO is in same row
    If oLO.Range.Cells(1).Row <> oPT.RowRange.Cells(1).Row Then
        oLO.Range.Cut Intersect(oPT.RowRange.EntireRow, oLO.Range.EntireColumn).Cells(1, 1)
    End If

    'Resize oLO if required
    lLO = oLO.Range.Rows.Count
    lPT = oPT.RowRange.Rows.Count
    If Not bIncludeTotal And oPT.ColumnGrand Then lPT = lPT - 1
    If lLO <> lPT Then oLO.Resize oLO.Range.Resize(lPT)


    'Clear any old data outside of oLO if it has shrunk
    If lLO > lPT Then oLO.Range.Offset(oLO.Range.Rows.Count).Resize(lLO - lPT).ClearContents

End Sub
Run Code Online (Sandbox Code Playgroud)

很酷的是,每当数据透视表更新时,代码都会自动调整计算表的大小,并且这些更新也会由您对数据透视表进行筛选而触发。因此,如果您仅过滤几个注册号码,您会看到以下内容: 在此输入图像描述