ms access updating field conditionally on form.activate - sql

My question concerns situations where custom code is required to auto-increment fields in MS Access, specifically with issues that arise from using such code in the OnActivate event.
I have a field [Group_ID] that auto-increments each time a new record is made using custom code in the OnCurrent and OnActivate events. Sometimes I need Group_ID to be incremented OnActivate, but sometimes I do not. In some cases users will actually use a "duplicate record" button to use the same Group_ID (along with most other fields) for a subsequent record. In situations like these, I'd like to set a condition for the OnActivate event that allows users to reference other forms or tables without re-querying Group_ID upon returning to the form to finish a record. Here is my code:
'increments Group_ID when a new record is made
Private Sub Form_Current()
If Me.NewRecord = True Then
Me.Group_ID = Nz(DMax("Group_ID", "All_sightings"), 1) + 1
End If
End Sub
'increments Group_ID when the form becomes active IF the value is no
longer max value + 1
Private Sub Form_Activate()
If Me.Group_ID = Nz(DMax("Group_ID", "All_sightings")) + 1 Then
Else
Me.Requery
End If
End Sub
What I would like to do is add an additional condition to the Form_Activate sub that checks whether a different field is already filled out (e.g. if the "duplicate" button was used) when the form re-activates after a user returns to a partially completed record. This field will not require any input from the user because it will be automatically filled when a user clicks the duplicate button. The field I have chosen is [UTM_x].
I have tried:
=IIF(Me.Group_ID = Nz(DMax("Group_ID", "All_sightings")) + 1 And Not IsNull(Me.UTM_x), "", Me.Requery)
And various other combinations of nested IIF() and IfThenElse statements, but have not had any luck. The form continues to requery every time on the OnActivate event when Group_ID is not more than (max+1). Any suggestions?

I played around with iif statements and more if-then-else statements, eventually finding a solution to my problem. Here it is:
Private Sub Form_Activate()
If Me.Group_ID = Nz(DMax("Group_ID", "All_sightings")) + 1 Then
'blank/do nothing because Group_ID is already max+1
ElseIf IsNull(UTM_x) Then
Me.Requery 'makes Group_ID max+1 because null UTM_x means it's a new record
Else
'blank/do nothing because Group_ID = max and this is a duplicated record
End If
End Sub

Related

Locking Previous Records in Access Database based on ID

I am trying to build a code where previous records in a certain form are locked for editing. This would be to allow users to create and edit new forms, but not change data from previous forms. I want to be able to allow users to access and edit the previous 5 forms, but lock the data in all forms previous to that.
I've tried several things, but as a novice VBA user, nothing has worked. I tried:
Private Sub Form_Load()
If Me.ID < 22 Then
Me.AllowEdits = False
Else
Me.AllowEdits = True
End If
End Sub
I used a dummy "22" to see if the code would work, but it just ended up locking all of the records, not just numbers 1-21, like I was trying to do.
I would like the "22" to be the value of the ID field in the most recent record. I would also like it to be: If Me.ID < (ID of most current record)-5
Is this possible?
Form_Loadis wrong event, as only raised once on startup withMe.IDbeing the first record. You have to check current selected record withForm_Currentevent.
Don't rely onIDbeing consecutive (e.g. caused by deletions). Select Top 5 IDs (sort decending) and get minimum.
Create as saved query (e.g. name it FormNameTop5ID, where FormName is name of form, TableName is table/query bound to form )
SELECT TOP 5 ID FROM TableName ORDER BY ID DESC
In the form create aForm_Currentevent
Private Sub Form_Current()
If Me.ID.Value < DMin("ID", "FormNameTop5ID") Then
Me.AllowEdits = False
Else
Me.AllowEdits = True
End If
End Sub

How to create Access User Form to both look up and add data

I have an access form that contains two subforms. The main form has three dropdown fields that allow the user to pick what data is displayed in the two linked subforms. The dropdown fields are all unbound as they are referenced in the datasource of the main form.
The SQL of the datasource for the main form is as follows:
SELECT tbl_RptPeriod.RptPrdID, tbl_BusUnits.UnitID, tbl_Categories.CategoryID, tbl_Categories.CategoryTitle, tbl_Categories.CategoryGroup, tbl_Categories.Inactive, tbl_Categories.RptPrdID, tbl_Categories.UnitID
FROM tbl_RptPeriod INNER JOIN (tbl_BusUnits INNER JOIN tbl_Categories ON tbl_BusUnits.UnitID = tbl_Categories.UnitID) ON tbl_RptPeriod.RptPrdID = tbl_Categories.RptPrdID
WHERE (((tbl_RptPeriod.RptPrdID)=[Forms]![Compliance]![cmbReportPeriod]) AND ((tbl_BusUnits.UnitID)=[Forms]![Compliance]![cmbBusinessUnit]) AND ((tbl_Categories.CategoryID)=[Forms]![Compliance]![CategoryTitle]));
This works perfectly to look up records. However, I want the users to be able to add new records to the ones they are looking up. That doesn't work as it should.
I can add records, but then the form elements that I am using to look up the data, specifically RptPrdID,UnitID, and CategoryID are not being populated in the table, thus the new records are unassociated and don't show up if you go to look for them again in the main form after closing it or moving to another record.
This makes sense in so far as the form elements I am using in the "WHERE" criteria of the SQL are unbound, but of course, if I add a new record, I want it to be correctly matched. The user must be able to find the records he adds if he looks up the same criteria again.
Question:
How can I get new records entered in the subforms to have RptPrdID,UnitID, and CategoryID filled in?
UPDATE
SELECT tbl_Activity.CategoryID AS CategoryID_X, tbl_Activity.RptPrdID AS RptPrdID_X, tbl_Activity.UnitID AS UnitID_X, tbl_Categories.SortKey, tbl_Categories.CategoryTitle, tbl_Categories.CategoryGroup, tbl_Categories.Inactive, tbl_Categories.Inactive, tbl_BusUnits.Unit_Name, tbl_RptPeriod.Rep_Month_Nr, tbl_RptPeriod.Rep_Month_Name, tbl_RptPeriod.Rep_Year
FROM tbl_RptPeriod INNER JOIN (tbl_Categories INNER JOIN (tbl_BusUnits INNER JOIN tbl_Activity ON tbl_BusUnits.UnitID = tbl_Activity.UnitID) ON tbl_Categories.CategoryID = tbl_Activity.CategoryID) ON tbl_RptPeriod.RptPrdID = tbl_Activity.RptPrdID
WHERE (((tbl_Activity.CategoryID)=[Forms]![Compliance_EXPERIMENT]![cmbCategoryTitle]) AND ((tbl_Activity.RptPrdID)=[Forms]![Compliance_EXPERIMENT]![cmbReportPeriod]) AND ((tbl_Activity.UnitID)=[Forms]![Compliance_EXPERIMENT]![cmbBusinessUnit]))
ORDER BY tbl_Categories.SortKey;
I had to change the query somewhat, but the key fields are still the same ones, though they are now on a different table.
Private Sub Form_BeforeInsert(Cancel As Integer)
Me.RptPrdID_X = Me.cmbReportPeriod
Me.UnitID_X = Me.cmbBusinessUnit
Me.CategoryID_X = Me.cmbCategoryTitle
End Sub
Add code for filling those 3 fields in Before Insert event of main form
Private Sub Form_BeforeInsert(Cancel As Integer)
Me.RptPrdID = Me.cmbReportPeriod
Me.UnitID = Me.cmbBusinessUnit
Me.CategoryID = Me.CategoryTitle
End Sub

Hide Delete Button in Gridview if RowID links to Foreign Key [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
VB.NET - I've found other questions related to this, but none specifically to my situation. I'm dealing with only two tables - "task" and "task_run."
I have a Gridview with rows listing certain "tasks." They come from the "task" table and each task has a "tsk_id." I want to have a delete button for each task (row) and only want the delete button visible for that row if the task does not have a run associated with that task from the "task_run" table. (i.e. I do not want the user to be able to delete that task if it has already been run.)
table1 - "task"
PKY = "tsk_id"
table2 - "task_run"
PKY = "run_id"
FKY = "run_tsk_id"
I assume I need to have a template field in my gridview and have the delete button conditionally show based on whether there are rows in the run table associated with that particular task Id, but am stuck on how to do this. Hopefully this makes sense. Any help is appreciated. Thanks!
You first get the task_Id from Task_run table accordingly user if exist otherwise return zero value , and placed this Task_Id in gridview on Label or textbox or hidden field with visible=false property if you not showing to user,
use this command for checking Task have already run or not by user.
SELECT ext.* , ISNULL((SELECT top 1 run_tsk_id
FROM task_run WHERE run_tsk_id = ext.tsk_id),0) AS CheckId
FROM task ext
then use the gridview RowDataBound event to hide or show the delete button conditionally, code as.
Protected Sub Grid_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim lblCheckId As Label = DirectCast(e.Row.FindControl("lblCheckId"),Label)
Dim deleteButton As Button = DirectCast(e.Row.FindControl("btnDelete"), Button)
If CInt(lblCheckId.Text) > 0 Then
deleteButton.Visible = False
Else
deleteButton.Visible = True
End If
End If
End Sub
If you already have your tables in a DataSet (ds say), you can add a relation via
ds.Relations.Add(name, parentColumn, childColumn, createConstraints)
For example:
ds.Relations.Add(
name,
ds.Tables("task").Columns("tsk_id"),
ds.Tables("task_run").Columns("run_tsk_id"),
True)
Alternatively, you could add a "task_run_count" as a property of table task via a subquery:
SELECT ...,
(SELECT COUNT(*) FROM task_run WHERE run_tsk_id = task.tsk_id) AS [task_run_count]
FROM task
The DataSource which you are binding to to the grid should also have Task run count. Then you can use the RowDataBound event to show or hide the button.
Protected Sub Grid_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim taskRunCount As Integer = Convert.ToInt16(e.Row.Cells(0).Text) ''The Cells[0] should be which ever column you have Task run count
Dim deleteButton As Button = DirectCast(e.Row.FindControl("DeleteButton"), Button)
If taskRunCount > 0 Then
deleteButton.Visible = False
Else
deleteButton.Visible = True
End If
End If
End Sub

ms-access 2003 combo box population

I have an entry form with a sub. I have three combo boxes that work together. combo 1 sets up with vba and an after event combo 2 and on into three. They work fine independently of the main form, but when I sue the form as a sub the cascade stops working.
Forms
Main Form Name "1A-Event Entry"
SubForm Name "1B-Event sub"
ComboBox 1 (After Update)
Private Sub Category_AfterUpdate()
Me.Type = Null
Me.Type.Requery
Me.Type = Me.Type.ItemData(0)
End Sub
ComboBox 2 (SQL)
SELECT Type.ID, Type.Type, Type.Category
FROM Type
WHERE (((Type.Category)=[Forms]![1B-Event sub]![Category]))
ORDER BY Type.Type;
CombBox2 (After Update)
Private Sub Type_AfterUpdate()
Me.Detail1 = Null
Me.Detail1.Requery
Me.Detail1 = Me.Detail1.ItemData(0)
End Sub
ComboBox3 (SQL)
SELECT Detail.ID, Detail.Detail, Detail.Type
FROM Detail
WHERE (((Detail.Type)=[Forms]![1B-Event sub]![Type]))
ORDER BY Detail.Detail;
I am sure is has something to do with the Form/ Subform scripting in the SQL, but it escapes me.
As a subform, you need a different reference:
WHERE Type.Category=[Forms]![1A-Event Entry]![Subform Control Name Here].Form![Category]
When a form is run as a subform of another form, you must refer to the subform control.

IF the sum of a column is <= 0 then

I am making a till system for a project in access and I have hit a block.
Background
There are numerous forms covered in buttons. clicking a button adds data to a table (TblCurSale) including description and price of item. each form also has a "total" button which sends you to the payment screen, doing so copies the data from the TblCurSale to another table (TblCalc)
TblCalc has columns SaleID, Item(name of item), SalePrice. the report auto adds the sale price column
The total form has two sub reports on it, the TBLCurSale and TblCalc.
On the total screen there is a text filed in which users an input money and then press pay which inputs that figure into the TblCalc as a negative number and then refreshes the page so the new total comes up. at the bottom of the subreport.
Problem
I need an IF vba code so that I can put it so that when the total of the SalePrice column <= 0 I can run a few lines of code. what I have so far is below, so any help would be greatly appreciated.
Private Sub Pay_Click()
Dim SQLPay As String
Dim SQLToTable As String
Dim SQLMoney As Variant
SQLPay = "INSERT INTO TblCalc(SalePriceTotal) VALUES (-'" & TxtPayment & "')"
SQLToTable = "INSERT INTO TblTotalSale (CurrentSaleID, SalePrice, Item) SELECT CurrentSaleID, SalePrice, Item FROM TblCurrentSale"
SQLMoney = "IF (SUM(SalePriceTotal) FROM TblCalc) <= 0 SELECT '1' ELSE '0'"
DoCmd.SetWarnings False
DoCmd.RunSQL SQLPay
DoCmd.RunSQL SQLMoney
If SQLMoney = 1 Then
DoCmd.RunSQL SQLToTable
Me.TxtPayment = ""
Me.Refresh
DoCmd.OpenReport "rptCalc"
Else
Me.TxtPayment = ""
Me.Refresh
Me.Refresh
End If
DoCmd.SetWarnings True
End Sub
I think you would be better to structure it like a transaction table. So instead of inserting the payment into a separate table, add another row to the TblTotalSale with an Item description of "Payment" and the value as a negative number. You can then simply sum the SalePrice column to give you the balance outstanding. It also allows you to record multiple payments against the one sale.
wrt to the negative sale, I think you should put some validation code on your form to prevent users from entering negative item prices, (in the beforeInsert and beforeUpdate events on the form)