Why is Access form giving me the error message "A column number has been specified more than once in the order list"? The related queries open fine - forms

I'm working on an Access database with a SQL Server back end. Some times when I open a particular form, I get an Error 3146 "Column has been specified more than once in the order by list."
There are several possible queries that might feed into this form but I checked and ran them all individually and they run fine, so it's something in the form but I'm not sure. Below is a screen shot of the Data Properties window. My hypothesis is that "Order By" property (which I did not populate manually) is not being cleared out when the form closes, and thus when the form is re-opened, that in effect puts in the same columns twice.
I can temporarily solve the problem by opening up the form and clearing those Filter and Order By fields. That solves it for a while but intermittently it will happen again so there's probably one other thing I'm overlooking. I put in code in the Form close event to set the orderby="" but even that doesn't totally solve it.
Here is the code that opens the form from the main menu (frmProdSched is the form in question)
Private Function OpenProdSched(RunQuery, RunCaption)
DoCmd.OpenForm "frmProdSched", , RunQuery, "", , acNormal
Forms!frmProdSched.Caption = RunCaption
gScheduleRptQry = RunQuery
Me.Refresh
End Function
and then the code that is in the Form_Current event
Private Sub Form_Current()
On Error Resume Next
Dim strForm As String
Dim strForm1 As String
Dim strWhere As String
strForm = "frmSubmittalStatus"
strForm1 = "frmProdSched"
strWhere = "StatusJobno = " & Me.JOBNO & ""
If IsLoaded(strForm) Then
If Forms(strForm).Filter = strWhere Then
Forms(strForm1).SetFocus
Else
DoCmd.Close acForm, strForm
DoCmd.OpenForm FormName:=strForm, WhereCondition:=strWhere
Forms(strForm1).SetFocus
End If
End If
End Sub
I tried adding this code to the Form Close event and it seemed to work most of the time but it still intermittently happens
Private Sub Form_Close()
Me.Filter = ""
Me.OrderBy = ""
End Sub
I'm not sure what to check next. Any ideas?

Related

How to retrieve a count of all records where a Date field is within the next year, and store it in a variable?

I am fairly new to MS Access, but have a decent understanding of databases, with some knowledge of SQL.
I am creating a database in Access. On a main form that users will see first, I need to display a count of all records from my Case table, which have a StatuteOfLimitation date that is within the next year.
My goal was to create a label describing the information, with a button below it. The button will open a report of all of the records (this part is working fine), and I wanted the caption for the button to display the total count of how many records meet the criteria.
The only way I can think to do it, is to retrieve the count and store it into a variable. From there, I should be able to set the caption to the variable value.
I have seen a few methods of retrieving a count and storing it in a variable, but all that I found only stored a count of EVERY record, without filtering for the date range.
This was the best that I could think of, but it is not working:
Private Sub Form_Load()
Dim oneYearFromToday As TempVars
SET TempVars!oneYearFromToday = (SELECT COUNT(StatuteOfLimitation) FROM Case
WHERE StatuteOfLimitation <= DateAdd("yyyy", 1, Date());
End Sub
DCount() provides a simple approach for "How to retrieve a count of all records where a Date field is within the next year"
Dim lngCount As Long
lngCount = DCount("*", "Case", "[StatuteOfLimitation] <= DateAdd('yyyy', 1, Date())")
Then you can use that count in your command button's Caption property. Say the button is named cmdOpenReport ...
Me!cmdOpenReport.Caption = "Report " & lngCount & " cases"
If you want the count in a TempVar instead of a regular Long variable, declare it As TempVar (just one) instead of As TempVars (a collection). And when you assign the value to it, don't use Set.
Dim oneYearFromToday As TempVar
TempVars!oneYearFromToday = DCount("*", "Case", "[StatuteOfLimitation] <= DateAdd('yyyy', 1, Date())")
I probably wouldn't use a tempvar to store your variable. you can try something like below using the DAO.
Private sub Form_Load()
dim rst as dao.recordset
dim strSQL as string
'Creates query string
strsql = "SELECT Count(StatueOfLimitation) as RecordCount " & _
"FROM Case " & _
"WHERE (((StatueOfLimitation) <= DateAdd('yyyy',1,date())));"
'Opens the query string into a recordset
set rst = currentdb.openrecordset(strsql)
'Change Labelnamehere isnto the name of the label control on your form
'Change what ever saying you want here to something you want the label to display
me.labelnamehere.caption = "What ever saying you want here " & rst![RecordCount] 'Don't need a variable storage is you can use the result here
rst.close 'closes recordset
set rst = nothing 'Clears memory
EndCode: 'Ensures clean up is successful
If not rst is nothing then
rst.close
set rst = nothing
end if
end sub
If this doesn't work for you, please let me know and I'll do some more digging.
I'm not able to comment on HansUp's answer, but to change a label caption in VBA you need to open the form in Design view. It's not something I typically do, my personal preference is to use an unbound text box with labels that don't change, but I have done it in one database to update the time/date and user for the last email sent.
The code would look like this:
DoCmd.OpenForm "yourformname", acDesign, , , , acHidden
Forms![yourformname]![yourlabelname].Caption = "There are " & TempVars!onYearFromToday & " cases to view."
DoCmd.Close acForm, "yourformname", acSaveYes
DoCmd.OpenForm "yourformname", acNormal
It's a bad idea to use a button for info display. That's not the purpose of a button.
Use a textbox and set its ControlSource:
=DCount("*","[Case]","[StatuteOfLimitation]<=DateAdd("yyyy",1,Date()))
It will fill by itself, and the button is free to open the report at any time.

Deleting the first record on continuous form in MS Access 2013

I have a "remove" button on a continuous form that performs the following SQL when clicked:
Dim strSQL As String
strSQL = "Delete SLIDE_NAME, COB_TITLE, COB_ID, COB_CATEGORY " _
& "FROM tbl_SLIDE_LIST " _
& "WHERE SLIDE_NAME='" & strSlideName & "' AND COB_TITLE='" & strCOB_TITLE & "';"
CurrentDb.Execute (strSQL)
The button sits on the continuous form like so:
There must be some sort of initialization I need to perform to make this work properly -
I can delete the 2nd and 3rd records with no problem, but if I click the "remove" button on the first record, the subform becomes blank, as if I deleted all records - (which is not actually the case). Then if I reselect the "Test Slide" to look at what actually happened, I receive the error "The data has been changed" Another user edited this record and saved the changes before you attempted to save your changes.
What is happening here and what do I need to do to make this work correctly?
If you delete a record with SQL, the form doesn't know about it. You need to do Me.Requery afterwards.
Much simpler would be to run DoCmd.RunCommand acCmdDeleteRecord.
From http://access.mvps.org/access/RunCommand/codeex/50-223.htm :
'Code from Microsoft Knowledge Base Adapted by Terry Wickenden
Private Sub cmdDelete_Click()
On Error GoTo Err_cmdDelete_Click
DoCmd.SetWarnings False
If MsgBox("Confirm deletion of the record?", vbQuestion + vbYesNo + vbDefaultButton2, "Delete?") = vbYes Then
DoCmd.RunCommand acCmdSelectRecord ' I think this isn't needed
DoCmd.RunCommand acCmdDeleteRecord
End If
Exit_cmdDelete_Click:
DoCmd.SetWarnings True
Exit Sub
Err_cmdDelete_Click:
MsgBox Err.Description
Resume Exit_cmdDelete_Click
End Sub

Setting focus to a subform gives the error 2449 (there is an invalid method in an expression) - VBA - Access 2013

-----------UPDATE---------
I figured out how to get the focus on my subform. If it is a subform then :
ParentFormName = frm.Parent.Name
SubFormName = frm.Name
Forms(ParentFormName).Form(SubFormName).SetFocus
This seems to work (although Andre451's post is more effective). But this resulted in the underlying problem of my subform causing the suspended state. My subform is relatively big (194 records) and when doing a MoveFirst/Last on the recordset of larger records I get the error 3021 (no current record). This probably has something to do with the entire recordset of the subform isn't loaded on the load event of the main form. Smaller recordsets can be looped faster so won't generate the error (this is just an assumption though).
The new question is: How can I avoid the 3021 error and let the subform records load entirely so I can move through them with either:
DoCmd.RunCommand acCmdRecordsGoToLast
OR
frm.RecordsetClone.MoveLast
----------------------------------------------------------------------------------
A while a go we migrated our Access data to a SQL server with still using the Access as the frontend. We did this by linking the SQL Server tables with Access and this all works (almost) fine. Recently however we encountered a problem with Access queries getting in suspended state on the SQL server (mainly happens on queries in combo boxes).
After some research we figured out that this could be solved by looping through the query records on the load of the form (so by doing a simple acCmdRecordsGoToLast and acCmdRecordsGoToFirst) and this seems to work.
So to counter this suspended state we added to each forms load an init that runs through the records of the recordsource and rowsource (the main forms recordsource, the comboxes rowsource etc.).
So on a forms load:
modFunctions.InitForm(Me)
This init is in a module and looks like this:
Dim InitFormResult As Boolean
InitFormResult = InitFormRecordSource(frm) ' Initialize the recordsource of the form
InitFormComboBoxes frm ' Initialize all the comboboxes on the form
InitFormCommandButton frm ' Initialize all the buttons on the form
The first init of the forms RecordSource (where the error happens) looks like this:
Public Function InitFormRecordSource(frm As Form) As Boolean
If frm.RecordSource <> "" Then ' if recordsource found
On Error GoTo ErrHandler
frm.SetFocus
DoCmd.RunCommand acCmdRecordsGoToLast
DoCmd.RunCommand acCmdRecordsGoToFirst
GoTo EndSuccess
ErrHandler:
MsgBox (Err.Number)
Debug.Print "ERROR during InitFormRecordSource in form : " & frm.Name
InitFormRecordSource = False
Exit Function
EndSuccess:
InitFormRecordSource = True
Else
InitFormRecordSource = True
End If
End Function
To run through the forms recordset with First and Last it needs to have the focus. This all works great for one form but it doesn't for Subforms in a main form. In subforms we want to counter the suspended state as well by also running through the subforms records, though when using the above code we keep getting the error 2449.
After some research I encountered this post: Module Function frm.setfocus runtime 2449 error which is more or less the same problem. So I figured out that a subform needs to be given it's focus in a different way, yet all my efforts to do this won't work.
What I tried so far:
If frm.RecordSource <> "" Then ' if recordsource found
On Error GoTo ErrHandler
Dim HasParent As Boolean
Dim sParentForm
HasParent = TypeName(frm.Parent.Name) = "String"
If HasParent = True Then 'The form is a subform
'sParentForm = frm.Parent
'sParentForm.frm.SetFocus
'frm.Parent.frm.SetFocus
'sParentForm!frm.SetFocus
Else
frm.SetFocus
End If
DoCmd.RunCommand acCmdRecordsGoToLast
DoCmd.RunCommand acCmdRecordsGoToFirst
GoTo EndSuccess
The tried fixes are all commented out in the above code. The HasParent does work, with this I can check if the form is a subform (it has a parent) or not and setting the focus differently.
Though I can't seem to get the focus on the subform and I don't quite know how to get it fixed!
I have had a similar problem, queries on Sql Server 2008 R2 going into a "ASYNC_NETWORK_IO" wait state, until the last record was loaded.
My solution: don't use the form itself to go to the last record, but its .RecordsetClone:
frm.RecordsetClone.MoveLast

update through vba new record, currently opened in a form

I have a question regarding updating new record through VBA.
First - the assumptions.
I've made a form called "assortment", that displays a set of records and a sobreport that shows related invntory. I've put the button on it: "Add new record". This opens the second form "inventory_details" that is intended to enter and view the inventory spcific data. That inventory is of that specific assortment type. So - I've passed the assortment_id to the inventory_details form through the DoCmd.OpenForm like:
DoCmd.OpenForm stFormName, , , , acFormAdd, , Me.assortment_id
The data source of the "inventory_details" form is a query that contains the assortment table joined to the inventory table by the inventory_id. What is the best way to add this id passed by an OpenArgs to the currently opened new record and refresh the form to show related assortment data?
I was trying to do this like:
Private Sub Form_Open(Cancel As Integer)
Dim assortmentId As Integer
If (Not IsNull(Me.OpenArgs)) Then
assortmentId = Me.OpenArgs()
Set rst = Me.Recordset
rst.Edit
rst.assortment_id_assortment = assortmentId
Me.Requery
End If
End Sub
but it gives me an error "3021 " No current record"...
Here are some suggestions,
. Make sure you define the variable rst
. Check for EOF Condition to make sure your recordset contains rows
If rst.EOF Then
MsgBox "The Recordset is empty."
End If
. Why clone an MS-Access recordset?

Enable Save button on different tabs when a form opens

I have a tab control on a form, and a couple different tabs have save buttons on them. Once the user saves data (via SQL statements in VBA), I set the .enabled = false so that they cannot use this button again until moving to a brand new record (which is a button click on the overall form).
so when my form open i was going to reference a sub that enabled all these save buttons because the open event would mean new record. though i get an error that says it either does not exist, or is closed.
any ideas?
thanks
EDIT:
Sub Example()
error handling
Dim db as dao.database
dim rs as dao.recordset
dim sql as string
SQL = "INSERT INTO tblMain (Name, Address, CITY) VALUES ("
if not isnull (me.name) then
sql = sql & """" & me.name & ""","
else
sql = sql & " NULL,"
end if
if not insull(me.adress) then
sql = sql & " """ & me.address & ""","
else
sql = sql & " NULL,"
end if
if not isnull(me.city) then
sql = sql & " """ & me.city & ""","
else
sql = sql & " NULL,"
end if
'debug.print(sql)
set db = currentdb
db.execute (sql)
MsgBox "Changes were successfully saved"
me.MyTabCtl.Pages.Item("SecondPage").setfocus
me.cmdSaveInfo.enabled = false
and then on then the cmdSave needs to get re enabled on a new record (which by the way, this form is unbound), so it all happens when the form is re-opened. I tried this:
Sub Form_Open()
me.cmdSaveInfo.enabled = true
End Sub
and this is where I get the error stated above. So this is also not the tab that has focus when the form opens. Is that why I get this error? I cannot enable or disable a control when the tab is not showing?
You cannot use the form open event to manipulate controls, they have not been initiated at that stage. Use the form load event.
It should never be necessary to set focus to a tab, or even to reference it when working with a control. You will notice that controls must have names unique to the form, and adding a tab does not change this.
I suggest you set some form-level variables: booBtn_1_enabled as Boolean, booBtn_2_enabled as Boolean. Set these to T or F as needed; obviously, all T when the form is opened. Pick a form event (possibly the Current event, but preferably one that is triggered less often) that reviews these variables and sets the controls accordingly:
Me.btnBtn_1.Enabled = booBtn_1_enabled
Me.Repaint
Something like that, but obviously Me.btnBtn_1 may need a more complicated reference.