Solved

Access97 and Custom counters

Posted on 1998-12-27
7
297 Views
Last Modified: 2012-05-04
I'm building a multi-user database with custom counter. (I have referenced KB article Q140908) Unlike their example, however, I cannot store the next number, since it uses the month (i.e., if the last number issued is 1998-12-101, the next number issued would be 1998-12-102 if issued this month or 1999-01-01 if issued next month.)

My problem comes when trying to find the last number issued. As suggested in the KB article, I use a separate table to store the last number instead next number.

With two computers on my desk, I've tried testing ways to allow one instance of the database to have exclusive access to this table while trying to get the other to one wait until the first one was done, but to no avail. (Using "On Error" to trap the 3260 error and looping until it went away. The only thing I've managed to do was to lock out neither or both intances at once!)

This is my first foray into multi user databases, basically working with bound forms up until now. Accessing tables with code instead of bound forms is my weak area, so I don't know if there is some sort of "exclusive" switch or option I'm missing on the
Set MyTable = MyDB.OpenRecordset("Counter Table")
statement, which Microsoft assumes you'll use or what.

Any leads (or answers) would be greatly apprectiated.
-Thanks
0
Comment
Question by:scottk122798
  • 3
  • 3
7 Comments
 

Author Comment

by:scottk122798
ID: 1972152
Edited text of question
0
 
LVL 10

Accepted Solution

by:
brewdog earned 100 total points
ID: 1972153
It sounds like you need to do two things:
1.  Locate the last "counter" used and increment it appropriately
2.  Make sure that that counter number isn't taken twice (by different users)

Here's how I'd approach it . . .

    Dim rs As Recordset
    Dim strCounter As String
    Dim strLast As String
    Dim strNext As String
   
    Set rs = CurrentDb().OpenRecordset("tblCounter", , dbDenyRead)
               'this prevents other users from even reading the counter until I'm done
    strLast = rs(0)
    If Left$(strLast, 4) = Year(Date) Then
        strCounter = Left$(strLast, 4) & "-"
    Else
        strCounter = Year(Date) & "-"
    End If
   
    If Mid$(strLast, 6, 2) = Month(Date) Then
        strCounter = strCounter & Mid$(strLast, 6, 2) & "-"
       strNext = CInt(Right$(strLast, 3)) + 1
        Select Case Len(strNext)
            Case 1
                strCounter = strCounter & "00" & strNext
            Case 2
                strCounter = strCounter & "00" & strNext
            Case 3
                strCounter = strCounter & strNext
        End Select
    Else
        strCounter = strCounter & Month(Date) & "-001"
    End If
       
    txtCounter = strCounter
    rs.Edit
    rs(0) = strCounter
    rs.Update
    rs.Close

This will get your next counter value, updating the counter table at the same time. And with the table locked, even for read access, you should be able to avoid the same number being taken twice. You would, of course, need to error trap the routine to retry multiple times before giving up on getting the next autonumber.

I wasn't sure what you were going to do with the new counter number, so I put it into a text box on the form and then updated the counter table. You could modify that, obviously.

Is this what you were looking for?

brewdog
0
 

Author Comment

by:scottk122798
ID: 1972154
Thanks for your reply Brewdog, however, it didn't completely work!

Your method yielded better results than mine; my method never yielded different numbers. With your method, I only got duplicate numbers about every sixth time. (I have two PC's on my desk to test the worst case scenario.)

My original "On Error" tested for 3260 and on 3260 sent the user back to the "Set rs = CurrentDb().OpenRecordSet("tblLastNumber",,dbDenyRead)" statement because I assumed this statement is what would cause the error. (Any other error halts execution in the standard way.)  As a flag to show me who was waiting, I put a visible counter on the form, incremented by the waiting. No increment. Suspicious, I Then put a message box (the Most reliable indicator, I've found) before I even test for 3260. Duplicate number or not, the message box never comes up! So, as far as I can tell, the "On Error" portion never gets executed and the table isn't being opened exclusively.

Again, any help appreciated

P.S. Thanks for coding for a fact I left out (duh!). Year, Month and Sequence are three separate fields, not one. The only other change I made was to refer to the three fields as rs!intYear, rs!intMonth, etc. instead of rs(0), rs(1), etc.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 10

Expert Comment

by:brewdog
ID: 1972155
that's strange . . . I would think the DenyRead would take care of that . . .

All right, I just tested it on mine, and it worked fine (with two "users" at least):

Private Sub cmdCounter_Click()
    On Error GoTo CounterError

    rs.LockEdits = True

GetCounter:
    strLast = rs(0)
    If Left$(strLast, 4) = Year(Date) Then
        strCounter = Left$(strLast, 4) & "-"
    Else
        strCounter = Year(Date) & "-"
    End If
   
    Select Case Len(Month(Date))
        Case 1
            strMonth = "0" & Month(Date)
        Case 2
            strMonth = Month(Date)
    End Select

    If Mid$(strLast, 6, 2) = strMonth Then
        strCounter = strCounter & strMonth & "-"
       strNext = CInt(Right$(strLast, 3)) + 1
        Select Case Len(strNext)
            Case 1
                strCounter = strCounter & "00" & strNext
            Case 2
                strCounter = strCounter & "00" & strNext
            Case 3
                strCounter = strCounter & strNext
        End Select
    Else
    End If
       
    txtCounter = strCounter
    rs.Edit
    rs(0) = strCounter
    rs.Update
 Exit Sub
CounterError:
    Select Case Err.Number
        Case 3260
            Resume GetCounter
        Case Else
            MsgBox "Error " & Err.Number & ", " & Err.Description, vbInformation, "Unexpected"
            Exit Sub
    End Select
End Sub

The other things I did were to put the Dim statements at the general declarations level for the form (at least the recordset variable should be put there) and then set the recordset (without the DenyRead) at the Form_Load event. Like I said, it worked fine for me. Let me know if it works for you, too, Scott.

brewdog
0
 

Author Comment

by:scottk122798
ID: 1972156
Brewdog,
Apologies for not replying sooner. A staffing shortage made me 'popular.'
I hate to say it, but the new code worked worse! I could get a duplicate number almost everytime! By recoding it this way, I was able to get the duplications down to 50%:

Private Sub cmdGetNumber_Click()
On Error GoTo Err_cmdGetNumber_Click
    Dim rsLastCaseNumber As Recordset
    Dim intYearIn As Integer
    Dim intYearCurrent As Integer
    Dim intYearOut As Integer
    Dim intMonthIn As Integer
    Dim intMonthCurrent As Integer
    Dim intMonthOut As Integer
    Dim intSequenceIn As Integer
    Dim intSequenceOut As Integer
 
    Set rsLastCaseNumber = CurrentDb().OpenRecordset("tblLastCaseNumber", , dbDenyRead)
    'Set rsLastCaseNumber = CurrentDb().OpenRecordset("tblLastCaseNumber")
    rsLastCaseNumber.LockEdits = True
   
GetCounter:
    intYearIn = rsLastCaseNumber(0)
    intMonthIn = rsLastCaseNumber(1)
    intSequenceIn = rsLastCaseNumber(2)
   
    If intYearIn = Year(Date) Then
        If intMonthIn = Month(Date) Then
            intYearOut = Year(Date)
            intMonthOut = Month(Date)
            intSequenceOut = intSequenceIn + 1
        Else
            intYearOut = Year(Date)
            intMonthOut = Month(Date)
            intSequenceOut = 1
        End If
    Else
        intYearOut = Year(Date)
        intMonthOut = Month(Date)
        intSequenceOut = 1
    End If
   
    rsLastCaseNumber.Edit
    rsLastCaseNumber(0) = intYearOut
    rsLastCaseNumber(1) = intMonthOut
    rsLastCaseNumber(2) = intSequenceOut
    rsLastCaseNumber.Update
    rsLastCaseNumber.Close
    Me![txtYear] = intYearOut
    Me![txtMonth] = intMonthOut
    Me![txtSequence] = intSequenceOut


Exit_cmdGetNumber_Click:
    Exit Sub

Err_cmdGetNumber_Click:
    Select Case Err.Number
        Case 3260
            Resume GetCounter
        Case Else
            MsgBox "Error" & Err.Number & ", " & Err.Description, vbInformation, "Unexpected"
            Exit Sub
        End Select
End Sub

It seems as if making it redefine everytime and closing after execution helped. The oddity is that it's a perfect 50 ratio; duplicate, non-duplicate, duplicate, non-duplicate...
Since yours works with the code you supplied, I'm beginning to think it's a setting rather than code.
-Scott
0
 
LVL 10

Expert Comment

by:brewdog
ID: 1972157
So yours actually saved the duplicates? That's strange . . . don't suppose I could get a copy of your db (only the relevant parts) to test on my machine? I'm at dbrewer@uhc.com if you want to send one. I know both of us would like to be finished with this question! :)
0
 
LVL 1

Expert Comment

by:Moondancer
ID: 6875655
GREETINGS!

This question was awarded, but never cleared due to the JSP-500 errors of that time.  It was "stuck" against userID -1 versus the intended expert whom you awarded.  This corrects the problem and the expert will now receive these points; points verified.

Please click on your Member Profile and select "View Question History" to navigate through any open or locked questions you may have to update and finalize them.  If you are an EE Pro user, you can also choose Power Search to find all your open questions.

This is the Community Support link, if help is needed, along with the link to All Topics which reflects many TAs recently added.  Also in the Community Support link is a question on how experts can help, if they wish, on the cleaning of old and abandoned questions.

http://www.experts-exchange.com/jsp/qList.jsp?ta=commspt
http://www.experts-exchange.com/jsp/zonesAll.jsp
 
Thank you,
Moondancer
Moderator @ Experts Exchange
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Today's users almost expect this to happen in all search boxes. After all, if their favourite search engine juggles with tens of thousand keywords while they type, and suggests matching phrases on the fly, why shouldn't they expect the same from you…
Regardless of which version on MS Access you are using, one of the harder data-entry forms to create is one where most data from previous entries needs to be appended to new records, especially when there are numerous fields and records involved.  W…
Familiarize people with the process of utilizing SQL Server functions from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Ac…
Learn how to number pages in an Access report over each group. Activate two pass printing by referencing the pages property: Add code to the Page Footers OnFormat event to capture the pages as there occur for each group. Use the pages property to …

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now