【问题标题】:Custom AutoNumber自定义自动编号
【发布时间】:2015-12-22 02:55:39
【问题描述】:

我正在将 Excel 电子表格转换为 Access 数据库。我是 Access 的新手,虽然我通过当地的培训公司参加了几门课程。在我正在转换的电子表格中,我们目前使用一个“跟踪”号来标识每个主记录(将在我的新主表中),其格式为“YY-XXXX”,其中“YY”是当前的 2 -digit 年份,“XXXX”是从 0001 开始的序列号,每年最多可达 9999。因此,2014 年的最后一条记录可能是 14-1025,而 2015 年的第一条记录是 15-0001。

为了与我的旧数据保持一致,我想使用相同的编号系统。我知道我可以生成一个标准的自动编号作为主键(无论如何我也可以这样做,但是我希望在我在表单中创建新记录时让这个 YY-XXXX 字段自动排序。那么,你会如何推荐一种方法来做到这一点?

我的第一个想法是创建和合并两个字符串,一个将当前日期转换为两位数的文本字段,另一个转换为序列的自动编号?我已经玩过这个并且无法得到任何工作。我不太擅长 VBA 代码,所以一直在尝试创建表、字段和表达式。但也许 VBA 是唯一的方法。

虽然我不知道如何执行此操作,但一个可接受的选项可能包括使用六位数长且仅在前两位数后用破折号格式化的自动编号,以及一种轻松重新开始编号的方法,即在明年 1 月 1 日,将自动编号设置为 160001(格式为 16-0001)。

有什么好主意吗?

【问题讨论】:

    标签: ms-access vba ms-access-2010


    【解决方案1】:

    我已经建立了好几次类似的系统。连接两个值总是比分开它们更简单。正如您所提到的,为您的 PK 使用自动编号。然后创建两个单独的整数(不是文本)字段 - TrackYear、TrackSequence 并在两者的组合上设置唯一索引。 在表单的 BeforeUpdate (NOT BeforeInsert) 事件中添加以下内容:

    If Me.NewRecord Then
    ME!TrackYear = Format(Date,"YY")
    Me!TrackSequence = Nz(DMax("TrackSequence",<yourTable>,"TrackYear=" & Format(Date,"YY")),0) + 1
    End If
    

    根据您的表创建一个查询,包括所有字段,以及另一个计算列 TrackingNbr:TrackYear & "-" & Format(TrackSequence,"0000")。 在您想查看 TrackingNbr 的任何地方,使用此查询。 对于从 Excel 工作表导入,您需要拆分现有数字,但这是一次性的。您可以在 Excel 中编写公式,也可以在 Access 中的追加查询中执行,以您更熟悉的方式执行。

    【讨论】:

    • 我喜欢你的想法。几年前还得建立这个系统,但愚蠢的年轻我相信IT部门说双键会有很大的性能问题。您的系统在 ACCESS 中遇到过性能问题吗?
    • 没有双键(使用您的术语)。 PK 是自动编号,而不是唯一索引。对于任何子表,FK 将加入父表的自动编号,而不是两个字段。至于 IT 的评论(如果它是双键),这取决于。数字键的性能通常优于文本字段,那么单个文本字段或两个数字字段哪个更好?视情况而定!
    • 我不认为你真的需要创建查询,因为在 Access 2013 中,你可以在表中创建一个计算字段,并设置它的计算表达式来连接其他两个字段在同一个排。 (您也可以使用数据宏来填充“普通字段”。
    • Ups,是的,我明白了。我读过你的意思是“唯一索引”,而不是PK。好的,我忘了它被称为“复合密钥”不要经常使用...谢谢信息。
    • ( cc: @HarveyFrench ) - 计算字段和数据宏确实可以分别使用 Access DAO 和 Application 对象的 SaveAsText/LoadFromText 方法从代码中进行操作。
    【解决方案2】:

    由于您的 Tracking Number 是标准格式并用 0 填充,因此应该很容易获取每个给定年份的最后一个,拆分两部分,增加序列部分,然后返回下一个。

    我会这样做。

    将其粘贴到新模块中。 (请务必将 MainTable 更改为您的主表的名称,并将 TRACKING_NO 更改为您的跟踪号列名称)

    Function GetNextTrackingNo(Optional nYear As Long = 0) As String 'be sure to pass nYear as 2 digit year if you ever use that option!
      Dim strLastTN As String     'get the last tracking number per given year
      Dim nSEQ As Long
    
      If nYear = 0 Then nYear = Year(Now) - 2000 'year was not passed so use current year; -2000 should be fine until year 2100
    
      'Get the last Tracking number for the given year
      strLastTN = Nz(DMax("TRACKING_NO", "MainTable", "Left([TRACKING_NO],2) = '" & nYear & "'"), 0)
    
      'get the sequence number from the string
      nSEQ = CLng(Right(strLastTN, 4))
    
      'increment the sequence so you get the next one.
      nSEQ = nSEQ + 1
    
      'you might want to have a check here to see if next sequence is greater than 9999!
    
      'return the next tracking number in the desired format
       GetNextTrackingNo = Format(nYear, "00") & "-" & Format(nSEQ, "0000")
    
    End Function
    

    你可以在另一个函数中测试它:

    Function TestGetNextTrackingNo()
    
      MsgBox GetNextTrackingNo 'show the next tracking number for this year
      MsgBox GetNextTrackingNo(14)  ' show the next tracking number for last year
      MsgBox GetNextTrackingNo(16) 'show next tracking number for next year
    
    End Function
    

    您可以使用 Form_BeforeInsert 在表单中使用该功能(将 TRACKING_NO 更改为您的跟踪号列名称)

    Private Sub Form_BeforeInsert(Cancel As Integer)
      Me.TRACKING_NO = GetNextTrackingNo
    End Sub
    

    或者如果您想在当前记录中使用日期字段来指定年份,请使用:

    Private Sub Form_BeforeInsert(Cancel As Integer)
      Me.TRACKING_NO = GetNextTrackingNo  Year(me.MyDateControl)-2000
    End Sub
    

    【讨论】:

    • 请注意,仅当记录永远不会更改日期时才适合使用 Form_BeforeInsert!如果您可能更改日期,您应该使用 Form_BeforeUpdate。
    • 这是很好的代码和很好的解决方案。值得补充的是,我不建议使用跟踪号作为主键。我会使用访问自动编号字段作为 PK。此外,在跟踪号上创建唯一索引。我想非常强烈地建议您始终使用自动编号字段作为主键。有这么多好处。我总是把它命名为 ID。我将其他表中的任何外键命名为 TheTableNameWithTheFieldID。例如 MyMainTableID。这真的很有帮助,因为您可以轻松查看发生了什么!
    猜你喜欢
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    相关资源
    最近更新 更多