Access开发:用窗体 Timer 做数字滚动动画

2.jpg

Hi,大家好!

做首页统计或经营看板时,数字通常是直接显示出来的。数据本身没问题,但刚打开窗体时,几组 KPI 一下子跳到最终值,视觉上会有点生硬。

我用 Access 自带的窗体 Timer 做了一个数字递增动画:窗体打开时,数字从 0 平滑走到目标值;点击按钮,也可以重新播放。这里做的是数字计数滚动,不是每个数位上下翻动的机械字轮,代码不依赖 ActiveX 控件或外部动画库。

第一步:新建窗体

打开 Access,新建一个窗体,先改名为 frmCounterAnimation。

在窗体上放两个控件。控件名称必须先设置准确,后面的代码会直接引用它们:

控件类型名称标题其他设置
标签lblKpi0字号 32、加粗、居中、边框设为透明
命令按钮cmdPlay重新播放放在数字下方,便于测试

标签不绑定表字段,只负责显示动画过程中的数字。布局完成后,切换到设计视图继续设置事件。

1.png

第二步:打开窗体事件

选中窗体,在属性表的“事件”页中设置:

  • 加载时:[事件过程]

  • 计时器时:[事件过程]

  • 计时器间隔:0

再选中 cmdPlay 按钮,把它的 单击时 设置为 [事件过程]。

这里把计时器间隔设为 0,是为了让计时器先保持关闭。稍后由 VBA 在启动动画时设置刷新频率,动画结束后再自动关闭。

第三步:声明动画需要的变量

右键窗体,选择“生成器”,打开窗体的 VBA 模块。先把下面这段放到模块顶部:

Option Compare DatabaseOption ExplicitPrivate Const TIMER_INTERVAL_MS As Long = 20Private Const SECONDS_IN_DAY As Double = 86400#Private m_FromValue As DoublePrivate m_EndValue As DoublePrivate m_CurrentValue As DoublePrivate m_StartedAt As DoublePrivate m_DurationSeconds As DoublePrivate m_IsAnimating As Boolean

TIMER_INTERVAL_MS 控制界面刷新间隔,m_FromValue 和 m_EndValue 分别保存起始值、目标值,m_CurrentValue 保存当前显示值。m_StartedAt 记录动画开始时间,这样程序可以根据真实经过时间计算进度。

第四步:添加启动动画的过程

继续在同一个窗体模块中加入下面两个过程。

Public Sub StartCounterAnimation(ByVal targetValue As Double, _        Optional ByVal durationMs As Long = 1200)    If durationMs <= 0 Then        m_CurrentValue = targetValue        m_IsAnimating = False        Me.TimerInterval = 0        Me!lblKpi.Caption = Format$(m_CurrentValue, "#,##0")        Exit Sub    End If    m_FromValue = m_CurrentValue    m_EndValue = targetValue    m_StartedAt = Timer    m_DurationSeconds = CDbl(durationMs) / 1000#    m_IsAnimating = True    Me.TimerInterval = TIMER_INTERVAL_MSEnd SubPrivate Sub SetCounterToStart()    m_CurrentValue = 0#    Me!lblKpi.Caption = Format$(m_CurrentValue, "#,##0")End Sub

调用 StartCounterAnimation 4805, 1500,表示数字在 1500 毫秒内滚动到 4,805。第二个参数可以省略,省略后使用默认的 1200 毫秒。

SetCounterToStart 用来把数字归零,方便窗体加载和按钮重播时复用。

第五步:让窗体打开时开始播放

找到 Form_Load 事件,替换成下面的代码:

Private Sub Form_Load()    Me.TimerInterval = 0    SetCounterToStart    StartCounterAnimation 4805, 1500End Sub

窗体打开后,先显示 0,然后启动计时器。这里的 4805 只是演示目标值,实际使用时可以传入订单数、客户数或销售额等统计结果。

第六步:编写 Timer 事件

Timer 事件是动画真正执行的地方。加入下面代码:

Private Sub Form_Timer()    Dim elapsedSeconds As Double    Dim progress As Double    Dim easedProgress As Double    If Not m_IsAnimating Then        Me.TimerInterval = 0        Exit Sub    End If    elapsedSeconds = Timer - m_StartedAt    If elapsedSeconds < 0# Then        elapsedSeconds = elapsedSeconds + SECONDS_IN_DAY    End If    progress = elapsedSeconds / m_DurationSeconds    If progress >= 1# Then        m_CurrentValue = m_EndValue        m_IsAnimating = False        Me.TimerInterval = 0    Else        easedProgress = 1# - (1# - progress) * (1# - progress) * (1# - progress)        m_CurrentValue = m_FromValue + (m_EndValue - m_FromValue) * easedProgress    End If    Me!lblKpi.Caption = Format$(m_CurrentValue, "#,##0")End Sub

每次事件触发,程序先计算已经过了多少时间,再计算当前应该显示的数字。progress 到达 1 后,数字直接设置为目标值并关闭计时器。

代码中的缓动公式是:

$E(t)=1-(1-t)^3$

其中 $t$ 从 0 逐渐增加到 1。它会让数字先快后慢,接近目标值时自然停下。

第七步:添加重新播放按钮

最后把按钮的单击事件改成下面的代码:

Private Sub cmdPlay_Click()    SetCounterToStart    StartCounterAnimation 4805, 1500End Sub

保存窗体代码,切换到窗体视图测试。正常情况下,打开窗体或点击“重新播放”时,数字都会从 0 递增到 4,805,约 1.5 秒结束。

如果要换成真实统计值,可以先查询数字,再调用动画过程。例如:

Dim totalOrders As LongtotalOrders = DCount("*", "T_Orders")SetCounterToStartStartCounterAnimation totalOrders, 1500

示例中的 T_Orders 是订单表名,需要替换成自己项目里的真实名称。统计金额时使用 DSum,并把变量类型改为 Currency 或 Double,显示格式可调整为 #,##0.00。

无标题项目.gif

使用时要注意什么

动画只负责显示,统计数据最好在启动前一次算好,不要把查询、循环或大量数据处理放进 Form_Timer。TimerInterval 的单位是毫秒,Windows 也不能保证事件每 20 毫秒准时触发,因此不要拿它做精确计时。

一个窗体同时滚动一两个数字比较合适。数字太多会频繁重绘标签,反而让界面卡顿。这个示例也只做数字计数滚动,不是数位逐列翻转;需要翻页式机械效果时,可以使用 WebBrowser 或其他专门的界面组件。


技术培训

  • Access VBA 从入门到精通(线上/线下均可)

  • Access + SQL Server 企业级开发实战

  • Access 系统性能优化与架构设计

  • AI + Access 融合开发专题培训

定制开发

  • 企业 ERP / CRM / 进销存 / WMS / MES 等系统开发

  • 旧 Access 系统升级、性能优化与架构重构

  • AI 能力集成到现有 Access 业务系统

技术支持

  • 代码审查与重构建议

  • 疑难问题远程诊断

  • 一对一技术辅导