Access VBA - OrderBy with multiple field - sql

I wonder how I should do this. Actually, I have some subform and, by clicking on the title, I want the recordset of this subform to orderby. This is an example of what I do:
Private Sub sigle_cours_Label_Click()
If (Me.OrderBy = "COU.sigle_cours") Then
Me.OrderBy = "COU.sigle_cours DESC"
Else
Me.OrderBy = "COU.sigle_cours"
End If
Me.OrderByOn = True
End Sub
My problem is this one : I want to OrderBy with sigle_cours AND num_cours but it don't work. I try this but there's no way to sort by DESC :
Private Sub sigle_cours_Label_Click()
If (Me.OrderBy = "COU.sigle_cours,COU.num_cours") Then
Me.OrderBy = "COU.sigle_cours DESC,COU.num_cours DESC"
Else
Me.OrderBy = "COU.sigle_cours,COU.num_cours"
End If
Me.OrderByOn = True
End Sub
How should I do this?

When you assign a string value to the OrderBy property, Access may transform it ... so won't exactly store what you expect. In your case, I suspect Access adds a space after the comma, so if you include this in your Form's code ...
Me.OrderBy = "COU.sigle_cours,COU.num_cours"
Debug.Print "Me.OrderBy='" & Me.OrderBy & "'"
You might see this in the Immediate Window ...
Me.OrderBy = 'COU.sigle_cours, COU.num_cours'
Actually I'm not positive that is the explanation for your problem. Nevertheless I suspect you're more likely to find joy by pattern-matching the current OrderBy value instead of testing for an exact match to a fixed string. Try it this way:
Private Sub sigle_cours_Label_Click()
If (Me.OrderBy Like "*DESC*") Then
Me.OrderBy = "COU.sigle_cours, COU.num_cours"
Else
Me.OrderBy = "COU.sigle_cours DESC, COU.num_cours DESC"
End If
Me.OrderByOn = True
End Sub

Related

Conditional increasing ID in ms access formular

i have a ms access formular where there are given several Information. For "Status" Combobox there are several options like "1","2","3","4". If "4" is selected in "cbx_Status" then I want to add in Textbox "txt_ID_Order" an automatically increased ID and give an Order Time in textbox "txt_OrderTime". That's why I wrote this and works well:
Private Sub Form_BeforeUpdate(Cancel As Integer)
If Me.cbx_Status.Value = "4" Then
Me.txt_OrderTime = Now()
Me.txt_ID_Order = DMax("[ID_Order]", "tblX") + 1
Else:
Me.txt_ID_Order=""
Me.txt_OrderTime = ""
End If
End Sub
However, if Status "4" is for some reason changed and again selected , I want to keep that old ID. But right know wenn i do that, it's still increasing ID.
How can I fix it?
Thanks
Check for a value:
Private Sub Form_BeforeUpdate(Cancel As Integer)
If Me!cbx_Status.Value = "4" Then
If IsNull(Me!txt_OrderTime.Value) Then
Me!txt_OrderTime.Value = Now()
Me!txt_ID_Order.Value = DMax("[ID_Order]", "tblX") + 1
End If
Else
Me!txt_ID_Order.Value = Null
Me!txt_OrderTime.Value = Null
End If
End Sub
Not sure about the logic though; if you select anything else than 4, the textboxes will be cleared.

Using a Date filtered value from a SubForm on the MainForm

I am trying to get the last entry of an allready filtered SubForm and place that single value on the MainForm. The entry should also be between a Date_0 and Date_1 alltough Date_1 is not allways specified (in that case simply get the last entry from the SubForm). So you get a more graphical idea (this is a simplification of the real Form):
MainForm:
Date_0
Date_1
ValueToGet
2020/12/23
2021/02/27
Value from Subform
SubForm:
Dates
Values
2020/12/20
1200
2020/12/23
1189
2021/01/25
1173
2021/02/20
1165
2021/03/12
1333
The value to collect from the SubForm would be, in this example, the fourth entry (between Date_0 and Date_1, and last entry in that Date range). The value is then stored in a txtBox in the MainForm as the Form Loads. I know the solution is probably setting a SQL filter on the txtBox, but I do not know how to do this. Any help would be greatly appreciated. Thanks in advance!
You can try below sub-
Private Sub cmdGetResult_Click()
Dim strFilter As String
Dim rs As DAO.Recordset
Me.Refresh
strFilter = "[Dates] BETWEEN #" & Me.Date_0 & "# AND #" & Me.Date_1 & "#"
Forms![Form1]![subformTest].Form.Filter = strFilter
Forms![Form1]![subformTest].Form.FilterOn = True
Set rs = Me.subformTest.Form.RecordsetClone
rs.MoveLast
Me.txtValueToGet = rs!values
Forms![Form1]![subformTest].Form.FilterOn = False
Set rs = Nothing
End Sub
The OnLoad event may be too early, but something like this should work:
Private Sub Form_Current()
Dim Records As DAO.Recordset
Dim Value As Long
Dim Found As Boolean
Set Records = Me!NameOfYourSubformControl.Form.RecordsetClone
If Records.RecordCount > 0 Then
Records.FindFirst "[Dates] >= #" & Format(Me!Date_0.Value, "yyyy\/mm\/dd") & "#"
If Records.NoMatch Then
' No dates to look up.
Else
If IsNull(Me!Date_1.Value) Then
Records.MoveLast
Value = Records!Values.Value
Found = True
Else
While Records.EOF = False And Found = False
If Records!Dates.Value >= Me!Date_1.Value Then
Value = Records!Values.Value
Found = True
End If
Records.MoveNext
Wend
End If
End If
End If
Records.Close
If Found = True Then
Me!ValueToGet.Value = Value
End If
End Sub

.FilterOn Method Not Working

K Access guru's. I have a module that requery's a main form, then set's a filter based on a value in a field, and requery's the subforms with that filter. The problem is when I set subform.FilterOn = True, it doesnt do anything and returns False. I'd rather not upload the whole solution. But heres a screenshot of the code with the highlighted part showing the discrepancy. Below is the code for copy/paste purposes. Why is this not working?
Private Sub Combo7_AfterUpdate()
Dim strSQL As String
Application.Echo False
strSQL = "[APN] = " & Str(Nz(Me![Combo7], 0))
DoCmd.ApplyFilter wherecondition:=strSQL
Me![Combo22].Requery
Me![Combo22] = Me![Text24]
Dim val As String
Dim subform1 As Form
Dim subform2 As Form
Dim subform3 As Form
val = Me![Text24]
Set subform1 = Me.qPayment_subform.Form
Set subform2 = Me.qRefundWriteOff_subform.Form
Set subform3 = Me.qRetnCHK_subform.Form
subform1.FilterOnLoad = True
subform2.FilterOnLoad = True
subform3.FilterOnLoad = True
subform1.FilterOn = True
subform2.FilterOn = True
subform3.FilterOn = True
subform1.Filter = "PeriodID = " & val
subform2.Filter = "PeriodID = " & val
subform3.Filter = "PeriodID = " & val
subform1.Requery
subform2.Requery
subform3.Requery
Application.Echo True
End Sub
Give subform container control a name different from the object it holds. For instance, if the form is named frmOrderDetails name the container ctrDetails. Then maybe using the container name in setting the object variables will work. If not, consider eliminating the variables and just referencing the container name.
With Me
...
.ctrDetails.Form.FilterOn = True
...
End With
I know this means repeating .Form but it will be fast edit.
In any case, set the Filter property before FilterOn.
Also, FilterOnLoad and Requery are not necessary.

Extracting the First (Oldest) Value from Dataset Based on Column Value

I don't have a great deal of experience working with DataSets and haven't been able to find the best way of achieving what I want to achieve.
I basically create a DataSet using a SQL Query and then I am trying to find a Specific Value in the 'Field' column and then if there is a 'Y' in the 'Flag' (as apposed to a 'N') Column on the same Row then I want it to change a check box's state to Checked as well as updating a labels text.
What I have seems to work however if no data is returned I get the below error:
Object reference not set to an instance of an object
If I change the code slightly from .FirstOrDefault() to .First() I get this error:
Sequence contains no elements
The part of the code that appears to be causing the problem is listed below. If you need to know anything else I will add it in.
Dim sSQL As String
sSQL =
<SQL>
SELECT MAX(UpdateTime) AS UpdateTime FROM AdminCS_Data_Current
WHERE UpdateUser = |##UpdateUser|
</SQL>
sSQL = Replace(sSQL, "##UpdateUser", AdminCB.Text)
Me.LastUserUpdate.Text = "Last Action: " & Format(ReturnDatabaseValue(sSQL, "UpdateTime", "Data"), "dd/MM/yyyy HH:mm:ss")
Dim EmployeeDataset As New DataSet
Try
sSQL =
<SQL>
SELECT * FROM AdminCS_Data_Current
WHERE UpdateUser = |##UpdateUser| AND CONVERT(DATE, UpdateTime) = CAST(GETDATE() AS DATE)
ORDER BY UpdateTime ASC
</SQL>
sSQL = Replace(sSQL, "##UpdateUser", AdminCB.Text)
EmployeeDataset = ReturnDataSet(sSQL, "Data")
If EmployeeDataset IsNot Nothing Then
Dim eData = EmployeeDataset.Tables(0)
If (eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag")) IsNot Nothing Then
If eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag").ToString.Trim = "Y" Then
TShtY.CheckState = CheckState.Checked
TShtTime.Text = Format(eData.Select("Field = 'Timesheets Checked'").First()("UpdateTime"), "HH:mm:ss")
Else
TShtN.CheckState = CheckState.Checked
End If
End If
' The above two IF statements would be repeated several times on each change of "Field"
End If
It would appear that this code has introduced not just iunefficiency but also a bug:
If (eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag")) IsNot Nothing Then
If eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()("Flag").ToString.Trim = "Y" Then
TShtY.CheckState = CheckState.Checked
TShtTime.Text = Format(eData.Select("Field = 'Timesheets Checked'").First()("UpdateTime"), "HH:mm:ss")
Else
TShtN.CheckState = CheckState.Checked
End If
End If
It should have been written like this in the first place:
Dim row = eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()
If row IsNot Nothing Then
If row("Flag").ToString.Trim = "Y" Then
TShtY.CheckState = CheckState.Checked
TShtTime.Text = Format(row("UpdateTime"), "HH:mm:ss")
Else
TShtN.CheckState = CheckState.Checked
End If
End If
Easier to read, more efficient and avoids that nasty bug.
Also, I'd much rather see this:
Dim row = eData.Select("Field = 'Timesheets Checked'").FirstOrDefault()
If row IsNot Nothing Then
If row("Flag").ToString.Trim = "Y" Then
TShtY.Checked = True
TShtTime.Text = CDate(row("UpdateTime").ToString("HH:mm:ss")
Else
TShtN.Checked = True
End If
End If
You should never use the CheckState of a Checkbox unless it's tri-state, which maybe yours are but I doubt it. As for Format, we're not in VB6 anymore Toto.

VB GetAsyncKeyState, combobox selected keys

I'm trying to do an action, when specific keys, selected by the user, are pressed.. but I don't know how to do It.
Is there any easiest way to to this:
If ComboBox1.SelectedItem = "F8"
If GetAsyncKeyState(Keys.F8) Then
'something
End If
ElseIf ComboBox1.SelectedItem = "F9"
If GetAsyncKeyState(Keys.F9) Then
'something
End If
ElseIf ComboBox1.SelectedItem = "F10"
If GetAsyncKeyState(Keys.F10) Then
'something
End If
End If
'and other more..
I tried
Dim asd as String
asd = ComboBox1.Text
If ComboBox1.Text Then
If GetAsyncKeyState(Keys.kj) Then
'something
End If
End If
One simple way is to put everything in a Dictionary, using it you can check the specified keyboard key by the Dictionary key.
First, declare this at class level (outside any sub or function):
Dim Hotkeys As New Dictionary(Of String, Keys) From { _
{"F8", Keys.F8}, _
{"F9", Keys.F9}, _
{"F10", Keys.F10} _
}
Then when you are going to check if the specified key was pressed you'd just do:
If GetAsyncKeyState(Hotkeys(ComboBox1.SelectedItem.ToString())) Then
'Some code here
End If
To add more keys you just keep adding rows to the Dictionary.
{"<key alias>", Keys.<key value>}, _
<key alias> (without the <> brackets) must be exactly the same as the respective item in the ComboBox.
And a final note: every row should end with }, _ except for the last one, which includes no comma } _.
Hope this helps!