Running an IF statement in MS VBA using a similar field from two tables - vba

I am trying to set a quantity value based on a sum of the current quantity and then subtracting an amount based on a quantity value in another table.
My current thought process is: If QuantityA is less than or equal to Quantity B then subtract QuantityA from Quantity B.
I am no expert on SQL and MS VBA, so I was wondering how I can make an if statement with the two different tables.
Private Sub Command23_Click()
If QuantityA <= QuantityB Then
QuantityB = QuantityB - QuantityA
Else
MsgBox "You can not hire that many" & ToolName & "as there is only" & [DEPARTMENT TOOLS (stocked)].Quantity & "available"
End If
MsgBox "Your hire request has been successful"
End Sub
Any help would be appreciated

You can achieve what you're asking by opening a recordset containing the results of a query and comparing the values returned by the query. In order to restrict the query to the proper quantities you need to pass in the ID of the tool you are checking.
#June7 is correct about saving calculated data. The only time you would want to save it is if you are keeping a log of events or if speed of join queries becomes an issue (unlikely given proper DB structure)
toolId might be stored in a text box control for example
Function Something_Click(toolId as string)
Dim rs as Recordset
' create a recordset containing data from the two tables
Set rs = CurrentDB.OpenRecordset("SELECT A.TOOL_QTY AS TOOL_QTY_A, " _
& " B.TOOL_QTY AS TOOL_QTY_B, A.TOOLNAME AS TOOLNAME" _
& " FROM TABLE1 AS A " _
& " INNER JOIN TABLE2 AS B ON A.TOOL_ID = B.TOOL_ID" _
& " WHERE A.TOOL_ID = '" & toolId & "'")
' compare the values in the table
If rs![TOOL_QTY_A] <= rs![TOOL_QTY_B] Then
' your true condition, for example
' MsgBox "Success"
Else
' your false condition, for example
' MsgBox "Oops, not enough of " & rs![TOOLNAME]
End If
' close the recordset
rs.close
End Function

Related

Retrieving most recent value in Microsoft Access form based on another value

I have a form built for the team to log calls made to customers. They may have multiple calls with the same customer who all have a unique ID assigned. I've built a form so that the team member can select a customer ID in the combo box and then using VBA, unbound text boxes will display the customer's name, phone number, and address (which is stored on a customer demographics table). All of this part so far has been working just fine.
My problem is that there is a text box on my form where team members can insert notes about the call. I've been asked by the team lead to make it so that when the customerID is selected, that notes box automatically populates with the last call's notes, and that team members can enter add on more notes. So for example in the last call on 4/1, the notes were "4/1 - Spoke to customer, order is on the way", and now it's 4/8, they're calling customer and want to see the last notes, the box should show that note from 4/1. Is there a way to do this? I've tried using the combo box option tying this to the customer ID combo box but can't quite get it to work. Thank you!
SELECT Notes,
CustID FROM (SELECT Call1.CustID,
Count(*) AS Rank,
Call1.DateCalled, Call1.Notes FROM Call AS Call1
INNER JOIN Call AS Call2 ON Call1.CustID = Call2.CustID
WHERE ((Call2.DateCalled>=Call1.DateCalled))
GROUP BY Call1.CustID, Call1.DateCalled ORDER BY 1, 2) WHERE Rank=1) AS Call ON CustTable.CustID=Call.[CustID]
Below is some VBA code that gets the last set of notes (by using TOP/ORDER BY DateCalled DESC) for the current customer as selected in a combo box where DateCalled doesn't equal the current call date (shown in txtDateCalled):
Private Sub Combo0_AfterUpdate()
On Error GoTo E_Handle
Dim db As DAO.Database
Dim rsData As DAO.Recordset
Dim strSQL As String
Set db = DBEngine(0)(0)
strSQL = "SELECT TOP 1 Notes " _
& " FROM Call " _
& " WHERE CustID=" & Me!Combo0 _
& " AND DateCalled<>" & Format(txtDateCalled, "\#mm\/dd\/yyyy\#") _
& " ORDER BY DateCalled DESC;"
Set rsData = db.OpenRecordset(strSQL)
If Not (rsData.BOF And rsData.EOF) Then
Me!txtLastNotes = rsData!Notes
Else
Me!txtLastNotes = ""
End If
sExit:
On Error Resume Next
rsData.Close
Set rsData = Nothing
Set db = Nothing
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "frmCall!Combo0_AfterUpdate", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
In order to populate the other text boxes, which are based on the Customer table, you may want to look at adding the columns to the combo box, with their ColumnWidth set to 0 (so the user can't see them), and then set these text boxes to use the hidden columns.
Regards,

How to make a field in access show the current value in the table, and accept input, but not update the table

I have been tasked with designing an Access front end for a SQL database I built. Unfortunately my VBA and Access knowledge are not as strong as they should be and I have run into a roadblock.
Currently I'm working on a script that will identify and flag high dollar assets that are entered into the database through the form. I have the update code written, but when I enter in a high value in the field the act of updating the value in the form and the update script itself clash and there is a 'Write Conflict'.
I can unbind the field in the form and that resoles the write conflict, but then the user first browsing to the record won't see the current value in the table.
My question: is there a way to have a field in a form show the value in a table, accept input, but not write the input to the table and leave the writing to the update query. If it helps I have included the update action I have written.
Private Sub Cost_AfterUpdate()
Dim CostCheck As String
CostCheck = "Update dbo_Purchasing SET Capitolasset = -1, COST = " & Me.Cost & " " & _
"Where itemMaster = " & Me.ItemMaster & " and " & Me.Cost & " >= " & 5000 & ""
DoCmd.RunSQL CostCheck
Me.Refresh
End Sub
It seems that you are trying to set the Capitolasset flag of the current record to -1 if the Cost entered is >= 5000. If so, you don't need to run an extra query, just update the Capitolasset value according to the Cost entered:
Private Sub Cost_AfterUpdate()
If IsNumeric(Me.Cost) Then
If Me.Cost >= 5000 Then
Me.Capitolasset = -1
Else
Me.Capitolasset = 0
End If
End If
End Sub
This will update the field before the record is saved.

Date Order in Cross Tab Query - use Separate Table to Sort

I have a cross tab query with 'mmm-yyyy' formatted dates for Fields in the Columns.
I have used the below Design to create the query.
Cross Tab Design View
The problem I am having is the dates are not sorting correctly from Dec-17 down to Jul-16 in descending order. This is going to be a dynamic query with months changing every month so I want to use an additional table of data to do the sorting (as opposed to entering a list of month names in the Properties window).
How would I fix my query to get it to do this please?
Thanks for your help
Unfortunately, no matter how joined tables are sorted, crosstab will sort columns by default in alphabetical order, hence Apr, Dec, ... begins the order. To change or even filter column order in crosstabs, you would specify values in PIVOT Col IN () clause of SQL statement.
Since you need a dynamic query consider creating a querydef in VBA to update the SQL behind the crosstab where you dynamically update the PIVOT Col IN () clause. Of course, pass begin and end dates as needed or by parameters:
Public Sub BuildCrossTab()
Dim db As Database
Dim qdef As QueryDef
Dim strSQL As String, dates As String
Dim i As Integer, monthsDiff As Integer
Set db = CurrentDb
' DELETE PREVIOUS SAVED QUERY
For Each qdef in db.QueryDefs
If qdef.Name = "AccuralsCrosstabQ" Then
db.Execute "DROP Table " & qdef.Name, dbFailOnError
End If
Next qdef
' LOOP THROUGH ALL MONTHS BACKWARDS
dates = "("
monthsDiff = DateDiff("m", #7/1/2016#, #12/1/2016#)
For i = monthsDiff To 0 Step -1
dates = dates & " '" & Format(DateAdd("m", i, #7/1/2016#), "mmm-yyyy") & "',"
Next i
dates = dates & ")"
dates = Replace(dates, ",)", ")")
' PREPARE SQL STRING
strSQL = "TRANSFORM SUM(a.[Amount $]) AS SumAmount" _
& " SELECT a.Company, a.[Accrual ID], SUM(a.[Amount $]) As [Total Amount $]" _
& " FROM [Accruals Raw Data] a " _
& " GROUP BY a.Company, a.[Accrual ID]" _
& " PIVOT Format(a.[Posted Date], ""mmm-yyyy"")" _
& " IN " & dates
' CREATE QUERY
Set qdef = db.CreateQueryDef("AccuralsCrosstabQ", strSQL)
Set qdef = Nothing
Set db = Nothing
End Sub

Access query updatable fields with group by

I want to create a split form based on a query where the fields are all grouped. The split form will not let me update the records because they are grouped. For instance let's say 10 records all had the same data in a field called "Company Name". Is there any way to make the query updatable such that when I change the data for "Company Name" on the grouped entry it will change for all of the records that are grouped?
Thanks
it is definitively not possible to update a grouped query.
The reason is, that a grouped query cannot contain the key (if you include it, you have no more a grouping, as the key is unique ...)
So Access has no clue, what is grouped and which records should be updated
What you have to do is:
create a form based on the query
add an event "on double-click" to the field you want to change
program a dialog to ask for new value
fire an sql to update
here a sample for steps 2-4
Private Sub DOK_DokumentNr_DblClick(Cancel As Integer)
Dim newvalue As Variant
Dim sSQL As String
newvalue = InputBox("enter new value", "DOC-Number", Me!DOK_DokumentNr.OldValue)
If newvalue <> Me!DOK_DokumentNr.OldValue Then
sSQL = "UPDATE T_Dokument SET DOK_DokumentNr = '" & newvalue & "' "
sSQL = sSQL & "WHERE DOK_DokumentNr = '" & Me!DOK_DokumentNr.OldValue & "'"
DoCmd.SetWarnings False ' to prevent the standard message for modifying data
DoCmd.RunSQL sSQL
DoCmd.SetWarnings True ' reset warnings to default
End If
End Sub

Comparing a virtual child's filters to parent table

I haven't a clue as to how to do this. I'm using Access 2007, and coding in VBA and SQL.
Table A has Data, accounts and amounts. Users can use form B to access subsets of the data in A, say, all the rows with amounts between $50 and $100.
When the user is looking at a row, I need to know if there are any other rows with the same account that are excluded from their view. In other words, I need to know if there are rows visible in the parent that aren't visible in the child.
I think a solution is to determine what filters are active on their view, and then I can use dcount to compare. I don't know how to get at the filters that are active in their view, though. And there may be an easier way - I am out of my depth here.
Let us assume that TableA has a primary key ID. Using the current event for the FormB:
Dim rs AS DAO.Recordset
dAmt = Me.Amount
sAcc = Me.Account
''Get a list of visible IDs
With Me.RecordsetClone
.MoveFirst
Do While Not .EOF
If !Amount=dAmt And !Account=sAcc Then
sIDs = sIDs & "," & .ID
End If
.MoveNext
Loop
End with
''Other IDs
sSQL = "SELECT * FROM TableA "
& "WHERE Amount = " & dAmt _
& "Account = '" & sAcc _
& "' ID Not In (" & Mid(sIDs,2) & ")"
CurrentDB.CreateQueryDef("NewQ",sSQL")
Docmd.OpenQuery NewQ
The above is untested, and as it stands, will only run once, if it runs at all, because a new query is created, rather than an existing query being edited.