夜雨聆风学习资料网

ARTICLE · 1145729

Excel VBA一键台账归档,保留最新记录,旧数据自动移入历史归档表

Excel VBA一键台账归档,保留最新记录,旧数据自动移入历史归档表
场景说明
很多做库存台账、每日业务记录、设备台账的朋友会遇到:
同一个编号(A列主键)有多条多次录入记录,只需要在主台账保留最新一条记录,更早的记录不能删除,全部移到【历史归档】工作表存放。
✅ 功能特点
1. 数组版,大数据量不卡顿,不用单元格Copy,速度快
2. 以A列为唯一匹配主键(物料编号/订单号)
3. 主表【台账】:每个编号仅保留时间最新一行
4. 旧记录自动剪切到【历史归档】,不会丢失数据
5. 自动判断工作表是否存在,不存在就新建
6. 自带表头,归档表自动延续原有表头
7. 增加【归档时间】列,标记这条数据什么时候被归档
示例数据预览(公众号配图文字说明,你可以直接做成表格截图)
【台账】原始数据
运行宏之后:
台账表只保留最新:001(9.10)、002(9.08)
历史归档表存入:001(9.01),附带归档时间
VBA完整代码可直接复制
vba    
Sub 台账自动归档_保留最新记录()
    Dim wsMain As Worksheet, wsArchive As Worksheet
    Dim arrData, arrNew, arrOld
    Dim dict As Object
    Dim lastRow As Long, lastCol As Long
    Dim i As Long, kNew As Long, kOld As Long
    Dim keyID As String, updateDate As Date
    Dim flag As Boolean
    '关闭屏幕刷新,提速
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    On Error GoTo ErrHandle
    '绑定主表【台账】
    Set wsMain = ThisWorkbook.Worksheets("台账")
    '判断归档表是否存在,不存在新建
    flag = False
    For Each ws In ThisWorkbook.Worksheets
        If ws.Name = "历史归档" Then
            Set wsArchive = ws
            flag = True
            Exit For
        End If
    Next ws
    If flag = False Then
        Set wsArchive = ThisWorkbook.Worksheets.Add(After:=wsMain)
        wsArchive.Name = "历史归档"
        '复制表头
        wsMain.Rows(1).Copy wsArchive.Range("A1")
        wsArchive.Range(wsArchive.Cells(1, wsMain.Columns.Count + 1)).Value = "归档时间"
    End If
    '读取台账全部数据到数组
    lastRow = wsMain.Cells(wsMain.Rows.Count, "A").End(xlUp).Row
    lastCol = wsMain.Cells(1, wsMain.Columns.Count).End(xlToLeft).Column
    If lastRow < 2 Then
        MsgBox "台账没有可处理的数据!", vbInformation
        GoTo EndSub
    End If
    arrData = wsMain.Range(wsMain.Cells(1, 1), wsMain.Cells(lastRow, lastCol)).Value
    '字典:key=编号,存储最新行信息
    Set dict = CreateObject("Scripting.Dictionary")
    dict.CompareMode = vbTextCompare
    '第一轮遍历:找出每个编号的最新记录
    For i = 2 To UBound(arrData)
        keyID = Trim(arrData(i, 1))
        If keyID <> "" Then
            updateDate = CDate(arrData(i, 4)) 'D列为更新时间列,可自行修改
            If Not dict.Exists(keyID) Then
                dict(keyID) = Array(i, updateDate)
            Else
                If updateDate > dict(keyID)(1) Then
                    dict(keyID) = Array(i, updateDate)
                End If
            End If
        End If
    Next i
    '第二轮拆分:最新记录放进arrNew,旧记录放进arrOld
    ReDim arrNew(1 To dict.Count + 1, 1 To lastCol)
    ReDim arrOld(1 To UBound(arrData), 1 To lastCol)
    '表头写入
    For i = 1 To lastCol
        arrNew(1, i) = arrData(1, i)
    Next i
    kNew = 1
    kOld = 0
    For i = 2 To UBound(arrData)
        keyID = Trim(arrData(i, 1))
        If keyID <> "" Then
            '判断当前行是否是该编号最新行
            If dict(keyID)(0) = i Then
                kNew = kNew + 1
                For j = 1 To lastCol
                    arrNew(kNew, j) = arrData(i, j)
                Next j
            Else
                kOld = kOld + 1
                For j = 1 To lastCol
                    arrOld(kOld, j) = arrData(i, j)
                Next j
            End If
        End If
    Next i
    '回写主台账表(只保留最新)
    wsMain.Range(wsMain.Cells(1, 1), wsMain.Cells(lastRow, lastCol)).ClearContents
    wsMain.Range("A1").Resize(kNew, lastCol).Value = arrNew
    '旧数据追加到历史归档表,附带归档时间
    If kOld > 0 Then
        Dim archLastRow As Long
        archLastRow = wsArchive.Cells(wsArchive.Rows.Count, "A").End(xlUp).Row + 1
        wsArchive.Range("A" & archLastRow).Resize(kOld, lastCol).Value = arrOld
        wsArchive.Cells(archLastRow, lastCol + 1).Resize(kOld, 1).Value = Now()
    End If
    MsgBox "归档完成!" & vbCrLf & "台账保留最新记录:" & kNew - 1 & "条" & vbCrLf & "本次归档旧数据:" & kOld & "条", vbInformation
EndSub:
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Set dict = Nothing
    Exit Sub
ErrHandle:
    MsgBox "出错:" & Err.Description, vbCritical
    Resume EndSub
End Sub
⚙️ 参数修改说明
1. 主键列:A列:用A列编号判断是不是同一条台账,不用改。如果你的编号在B列,把代码里所有 arrData(i,1) 改成 arrData(i,2) 
2. 时间列:D列:代码默认D列是更新日期,用来判断哪一条是最新。你的日期在C列,修改 arrData(i,4) → arrData(i,3) 
3. 工作表名称:主表固定叫【台账】,归档表【历史归档】,名字不一样需要修改代码对应位置
4. 归档自动新增一列:归档时间,记录什么时候移入归档,方便追溯
📝 如果有需要追加功能:支持手动设置保留N条最新记录(比如保留最近3条,其余归档)可以关注我私信留言。
VBA专业开发,每日分享实用小技巧,关注我不迷路。
VBA一键按条件自动提取数据(文员、生产统计专用)
VBA一键拆分工作表!按列自动分Sheet/分独立文件,十万行数据不卡顿
Excel VBA|多个文件,批量合并数据导入到当前表
Excel VBA 双向台账:按A列匹配,有则更新、无则新增(数组高速版)
VBA一键对比两个Excel文件|自动识别相同-差异数据,不同单元格填充颜色

相关学习资料