Auto add primary key in Access form [duplicate] - ms-access

I am using an MS Access append query to append inventory transactions to my ERP database (MYSQL).
Please advise how I would go about to modify my query to automatically insert the next sequential transaction ID (primary key) into the Inventory_transaction table, with ability to append multiple records at once.
My existing query works fine, but only when I append just one record.
I usually need to append multiple records simultaneously. Each record needs to have a unique sequential transaction ID (primary key). There would be multiple users using this app simultaneously, so I need minimal chance of duplicate a key violation, to prevent roll backs. I tried appending without using a primary key to see if my database would automatically assign a transaction ID, but unfortunately this this ERP field is not an auto-number and I cant modify the table structure...
Below are 2 queries.
This one currently works for generating a transaction ID for just one record.
SELECT Max([SYSADM_INVENTORY_TRANS].[TRANSACTION_ID])+1 AS new_inventory_transaction_ID
FROM SYSADM_INVENTORY_TRANS;
The 2nd query is the append query that contains the first query and I would much appreciate it if someone can modify the query so the user has ability to append multiple records at once with a unique transaction ID.
INSERT INTO SYSADM_INVENTORY_TRANS ( TRANSACTION_ID, WORKORDER_TYPE,
WORKORDER_BASE_ID, WORKORDER_LOT_ID, WORKORDER_SPLIT_ID, WORKORDER_SUB_ID,
OPERATION_SEQ_NO, REQ_PIECE_NO, PART_ID, TYPE, CLASS, QTY, COSTED_QTY,
TRANSACTION_DATE, WAREHOUSE_ID, LOCATION_ID, USER_ID, POSTING_CANDIDATE,
ACT_MATERIAL_COST, ACT_LABOR_COST, ACT_BURDEN_COST, ACT_SERVICE_COST,
CREATE_DATE, ADD_BURDEN, COUNT_SEQUENCE, DESCRIPTION )
SELECT T.new_inventory_transaction_ID, S.WORKORDER_TYPE, D.WORKORDER_BASE_ID,
D.WORKORDER_LOT_ID, D.WORKORDER_SPLIT_ID, D.WORKORDER_SUB_ID, D.OPERATION_SEQ_NO,
D.PIECE_NO, D.auto_issue_part_ID, S.TYPE, S.CLASS, D.[total_auto_issue Qty],
0 AS Expr6, Date() AS Expr1, D.BACKFLUSH_WHS_ID, D.BACKFLUSH_LOC_ID,
"SYSADM" AS Expr3, S.POSTING_CANDIDATE, S.ACT_MATERIAL_COST, S.ACT_LABOR_COST,
S.ACT_BURDEN_COST, S.ACT_SERVICE_COST, Date() AS Expr2, S.ADD_BURDEN,
S.COUNT_SEQUENCE, "ENTERED WITH ACCESS APP" AS Expr5
FROM tbl_static_autoissue_data AS S,
tbl_dynamic_autoissue_data AS D,
qry_transaction_ID_generator AS T;

Here are some notes that may help you towards your goal, however life would be a lot easier and a lot safer with autonumbers. This is VBA as you mention MS Access.
Function NextTranNumber(ByRef FirstTran As Long, _
ByRef LastTran As Long, Optional BlockSize = 1)
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strSQL As String
Dim lngResult As Long
Dim strCon As String
lngResult = 0 'assume fail
strCon = TestCon ''Connection to back-end
cn.Open strCon
rs.CursorType = adOpenKeyset
rs.LockType = adLockPessimistic
rs.CursorLocation = adUseServer
''Where BEInfo is a single line table that holds a transaction seed
strSQL = "SELECT ASeqNumber FROM BEInfo"
rs.Open strSQL, cn, , , adCmdText
'Note this is ADO, so no rs.Edit
FirstTran = rs!ASeqNumber + 1
rs!ASeqNumber = rs!ASeqNumber + BlockSize
rs.Update
LastTran = rs!ASeqNumber
rs.Close
Set rs = Nothing
End Function
Sub TransactionProcessing()
Dim FirstTran As Long
Dim LastTran As Long
Dim db As Database
Dim sSQL As String
Dim Block As Long
Dim rs As DAO.Recordset
Set db = CurrentDb
'Existing temporary table
sSQL = "DELETE FROM FETempTrans"
db.Execute sSQL, dbFailOnError
'The records to be added to the main table
sSQL = "INSERT INTO FETempTrans ( ID, AText ) SELECT 0 AS ID, AText FROM Table1"
db.Execute sSQL, dbFailOnError
Block = db.RecordsAffected
'Reserve a transaction block based on the temp table count
NextTranNumber FirstTran, LastTran, Block
Set rs = db.OpenRecordset("FETempTrans")
Do While Not rs.EOF
rs.Edit
rs!ID = FirstTran
rs.Update
FirstTran = FirstTran + 1
rs.MoveNext
Loop
If FirstTran - 1 = LastTran Then
'compare the temp set to the main table
'if it passes, update the main table
Else
'fail
End If
End Sub

Related

db.OpenRecordset returns something that isn't a recordset; but run as queries they do

I'm trying to generate a bill by route, so I've broken it down by customers belonging to a specific route, and then for each customer totaling their weekly rates to compile a monthly rate.
The problem is, even opening a recordset with a SELECT * IN [table] returns nothing, so there must be some glaring error. Here's my code, I'd be very appreciative if someone could set me straight.
Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rs3 As DAO.Recordset
Dim custNo As Integer
Dim month_total_v As Integer
Dim weekTotal As Integer
Dim weekStart As Date
Dim sql As String
'sql = "SELECT cust_no FROM Roster WHERE route = Forms![routeBill]![route]"
Set rs = CurrentDb.OpenRecordset("SELECT CUST_NO FROM Roster WHERE ROUTE = 'Forms![routeBill]![route]'")
month_total_v = 0
MsgBox ("Boop.")
If Not (rs.EOF) Then
rs.MoveFirst
Do Until rs.EOF = True
MsgBox ("Boop.")
custNo = rs!CUST_NO
Set rs2 = CurrentDb.OpenRecordset("SELECT wk_rate, wk_strt_dt FROM Roster WHERE wk_strt_dt >= Forms![routeBill]![Text53] AND wk_strt_dt <= Forms![routeBill]![Text4] AND cust_no = custNo")
If Not (rs2.EOF And rs2.BOF) Then
rs2.MoveFirst
Do Until rs2.EOF = True
MsgBox "Boop."
weekStart = WK_STRT_DT
month_total_v = month_total_v + rs2!WK_RATE
Set rs3 = CurrentDb.OpenRecordset("SELECT * FROM monthTotal where cust_no = custNo and billMonth=month(weekStart) and billYear=year(weekStart)") 'specify date ranges to pick from to shorten query
If rs3.EOF Then
sql = "INSERT INTO monthTotal (cust_no, month_total, billMonth, billYear) VALUES (custNo, month_total_v, month(weekStart), year(weekStart))" 'Append, record does not exist
DoCmd.RunSQL sql
Else
sql = "UPDATE monthTotal SET month_total = month_total_v WHERE cust_no = custNo AND billMonth = month(weekStart) AND billYear = year(weekStart)" 'Update, record exists
DoCmd.RunSQL sql
End If
rs2.MoveNext
Loop
Else
'pass
End If
rs.MoveNext
Loop
End If
This query will not return any records when none of the stored ROUTE values contain the literal text, 'Forms![routeBill]![route]' ...
SELECT CUST_NO FROM Roster WHERE ROUTE = 'Forms![routeBill]![route]'
Elsewhere you have a WHERE clause which includes AND cust_no = custNo. But, since custNo is a VBA variable, the db engine doesn't know anything about it and will interpret it to be the name of a parameter for which you haven't supplied a value.
You can avoid those types of problems by using a parameter query in a DAO.QueryDef. Then supply the parameter values (from form controls, VBA variables, whatever ...) and use the QueryDef.OpenRecordset method to load your recordset.
Here is a simple example ...
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rs As DAO.Recordset
Dim strSelect As String
strSelect = "SELECT CUST_NO FROM Roster WHERE ROUTE = [which_route]"
Set db = CurrentDb
Set qdf = db.CreateQueryDef(vbNullString, strSelect)
qdf.Parameters("which_route").Value = Forms![routeBill]![route]
Set rs = qdf.OpenRecordset
With rs
If .BOF And .EOF Then
MsgBox "no matches found"
Else
.MoveLast
MsgBox .RecordCount & " matches"
End If
.Close
End With
Note the parameter query technique avoids the need to add quotes around text values (and then also cope with text values which may include quotes within them) and format Date/Time values and enclose them within # delimiters.
The problem is here:
FROM Roster WHERE wk_strt_dt >= Forms![routeBill]![Text53] AND wk
You should outquote Forms![routeBill]![Text53]:
FROM Roster WHERE wk_strt_dt >= " & Forms![routeBill]![Text53] & " AND wk
You also need to get the dates right:
WHERE wk_strt_dt >= #" & Format(Forms![routeBill]![Text53], "yyyy\/mm\/dd") & "# AND wk_strt_dt ... etc

RecordSet and Ms Access 2007

I have a query that has CustID with mutiple Business affiliated with the CustID. I can't use Dlookup because it only returns one variable. I want to show on a form that for this custID, here are all the businesses it's affiliated it. I want the Businesses to show up into a field (business) in another table on the form.
I started out by this
Public Sub OpenRecordset()
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("Q:businesses")
Do While Not rs.EOF
T:Custinfo!business = NAME (I am lost in between on how to identify the custid and place the businesses into the table field as a Dlookup)
rs.movenext
Loop
rs.Close
Set rs = Nothing
db.Close
End Sub
I keep looking at other examples but can't seem to tie together where the dlookup replacement will take place and how will you have to put this on a form as a datasheet?
You don't need a DLookup. You could do one of two things:
1) Use a listbox and set the recordsource equal to your query (assuming Q:businesses has been appropriately defined to give the businesses as a result)
2) Still need your query to be appropriate, but you could create a string with all of the businesses in it:
Public Sub OpenRecordset()
Dim db As Database
Dim rs As Recordset
Dim StrBusinesses As String
Set db = CurrentDb
Set rs = db.OpenRecordset("qryBusinesses")
If rs.EOF and rs.BOF Then
MsgBox("No businesses exist for this Customer")
Exit Sub 'Or do whatever else you want if there are no matches
Else
rs.MoveFirst
End If
StrBusinesses = ""
Do While Not rs.EOF
StrBusinesses = StrBusinesses & rs!Business & ", "
rs.movenext
Loop
rs.Close
StrBusinesses = Left(StrBusinesses, Len(StrBusinesses) - 2)
Forms!MyForm.MyField = StrBusinesses 'Set the field equal to the string here
Set rs = Nothing
db.Close
End Sub
Of course this assumes that the query "Q:Business" is defined to get the appropriate info such as:
SELECT custID, business FROM tblBusinesses WHERE custID = X
where "X" is the custID you are looking for.
If you need to set the query dynamically, you will need to set a querydef.
EDIT to include querydef code***********************
Also changed the name of the query to "qryBusinesses" in the code above and below as I'm not sure whether you can make a query with a colon in it.
To set the querydef, put this at the beginning of the code:
Dim qdf As QueryDef
Set qdf = CurrentDb.QueryDefs("qryBusinesses")
qdf.SQL = "SELECT custID, business FROM tblBusinesses" _
& " WHERE custID = " & Forms!MyForm.CustID 'replace with actual form and field
This assumes that i) qryBusinesses exists already,
ii) custID is a number field
EDIT**************
If you define the query to look at the form itself, you would not need to set the sql, so if the query were defined (either in VBA or through the query wizard) as:
qdf.sql = "SELECT custID, business FROM tblBusinesses" _
& " WHERE custID = Forms!MyForm.CustID"
then you would not need to redefine the sql. However, it is a bit more dynamic to put the custID into the qdf itself as it is easier to debug any issues as you can see the exact sql that is being run in the original method.

insert query with sequential primary key

I am using an MS Access append query to append inventory transactions to my ERP database (MYSQL).
Please advise how I would go about to modify my query to automatically insert the next sequential transaction ID (primary key) into the Inventory_transaction table, with ability to append multiple records at once.
My existing query works fine, but only when I append just one record.
I usually need to append multiple records simultaneously. Each record needs to have a unique sequential transaction ID (primary key). There would be multiple users using this app simultaneously, so I need minimal chance of duplicate a key violation, to prevent roll backs. I tried appending without using a primary key to see if my database would automatically assign a transaction ID, but unfortunately this this ERP field is not an auto-number and I cant modify the table structure...
Below are 2 queries.
This one currently works for generating a transaction ID for just one record.
SELECT Max([SYSADM_INVENTORY_TRANS].[TRANSACTION_ID])+1 AS new_inventory_transaction_ID
FROM SYSADM_INVENTORY_TRANS;
The 2nd query is the append query that contains the first query and I would much appreciate it if someone can modify the query so the user has ability to append multiple records at once with a unique transaction ID.
INSERT INTO SYSADM_INVENTORY_TRANS ( TRANSACTION_ID, WORKORDER_TYPE,
WORKORDER_BASE_ID, WORKORDER_LOT_ID, WORKORDER_SPLIT_ID, WORKORDER_SUB_ID,
OPERATION_SEQ_NO, REQ_PIECE_NO, PART_ID, TYPE, CLASS, QTY, COSTED_QTY,
TRANSACTION_DATE, WAREHOUSE_ID, LOCATION_ID, USER_ID, POSTING_CANDIDATE,
ACT_MATERIAL_COST, ACT_LABOR_COST, ACT_BURDEN_COST, ACT_SERVICE_COST,
CREATE_DATE, ADD_BURDEN, COUNT_SEQUENCE, DESCRIPTION )
SELECT T.new_inventory_transaction_ID, S.WORKORDER_TYPE, D.WORKORDER_BASE_ID,
D.WORKORDER_LOT_ID, D.WORKORDER_SPLIT_ID, D.WORKORDER_SUB_ID, D.OPERATION_SEQ_NO,
D.PIECE_NO, D.auto_issue_part_ID, S.TYPE, S.CLASS, D.[total_auto_issue Qty],
0 AS Expr6, Date() AS Expr1, D.BACKFLUSH_WHS_ID, D.BACKFLUSH_LOC_ID,
"SYSADM" AS Expr3, S.POSTING_CANDIDATE, S.ACT_MATERIAL_COST, S.ACT_LABOR_COST,
S.ACT_BURDEN_COST, S.ACT_SERVICE_COST, Date() AS Expr2, S.ADD_BURDEN,
S.COUNT_SEQUENCE, "ENTERED WITH ACCESS APP" AS Expr5
FROM tbl_static_autoissue_data AS S,
tbl_dynamic_autoissue_data AS D,
qry_transaction_ID_generator AS T;
Here are some notes that may help you towards your goal, however life would be a lot easier and a lot safer with autonumbers. This is VBA as you mention MS Access.
Function NextTranNumber(ByRef FirstTran As Long, _
ByRef LastTran As Long, Optional BlockSize = 1)
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strSQL As String
Dim lngResult As Long
Dim strCon As String
lngResult = 0 'assume fail
strCon = TestCon ''Connection to back-end
cn.Open strCon
rs.CursorType = adOpenKeyset
rs.LockType = adLockPessimistic
rs.CursorLocation = adUseServer
''Where BEInfo is a single line table that holds a transaction seed
strSQL = "SELECT ASeqNumber FROM BEInfo"
rs.Open strSQL, cn, , , adCmdText
'Note this is ADO, so no rs.Edit
FirstTran = rs!ASeqNumber + 1
rs!ASeqNumber = rs!ASeqNumber + BlockSize
rs.Update
LastTran = rs!ASeqNumber
rs.Close
Set rs = Nothing
End Function
Sub TransactionProcessing()
Dim FirstTran As Long
Dim LastTran As Long
Dim db As Database
Dim sSQL As String
Dim Block As Long
Dim rs As DAO.Recordset
Set db = CurrentDb
'Existing temporary table
sSQL = "DELETE FROM FETempTrans"
db.Execute sSQL, dbFailOnError
'The records to be added to the main table
sSQL = "INSERT INTO FETempTrans ( ID, AText ) SELECT 0 AS ID, AText FROM Table1"
db.Execute sSQL, dbFailOnError
Block = db.RecordsAffected
'Reserve a transaction block based on the temp table count
NextTranNumber FirstTran, LastTran, Block
Set rs = db.OpenRecordset("FETempTrans")
Do While Not rs.EOF
rs.Edit
rs!ID = FirstTran
rs.Update
FirstTran = FirstTran + 1
rs.MoveNext
Loop
If FirstTran - 1 = LastTran Then
'compare the temp set to the main table
'if it passes, update the main table
Else
'fail
End If
End Sub

Append Records From Passthrough Query to Local Table

I have an Access Database and I'm using a pass through query to return records from an AS400 table. The connection string and pass through query work fine, but now I'm trying to populate the results of the p-t query into a local table within the db and my code is timing out. This is my first attempt at ADO so I'm disclaiming my code with "I'm not 100% sure what I'm doing!". Could you look at this and see if there is something obvious that I'm doing wrong? Any direction would be appreciated. Thank you in advance.
Sub mod_ADODBConnect()
Const NewTableName = "MyNewTable"
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim db As DAO.Database
Dim sSQL1 As String
Dim sSQL2 As String
sSQL1 = "SELECT ITMNUM, ITMDS, ITPKDS, MJCMCD, SBCMCD, STATUS, PRITIN, OGEXDT from PDBLLIB007.BLPMST07"
sSQL2 = "INSERT INTO ' & NewTableName & ' SELECT [" & sSQL1 & "].* from [" & sSQL1 & "]"
Set cn = New ADODB.Connection
cn.Open "Driver={Client Access ODBC Driver (32-bit)};" & _
"System=DC007; Uid=XXXXX; Pwd=XXXXXX; MgDSN=0; ConnType=2;" & _
"BlockSize=512; MaxFieldLen=2048; LazyClose=1; Prefetch=1; QueryTimeOut=0; Translate=1"
Set rs = New ADODB.Recordset
rs.Open sSQL1, cn, adOpenDynamic, adLockOptimistic
Do While Not rs.EOF
rs.MoveNext
Loop
Set db = CurrentDb
db.Execute ("sSQL2")
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
Set db = Nothing
End Sub
You have a pass-through query which works fine and returns the rows you want. Now you want to store those rows in a new local (Jet/ACE) table. Seems to me a simpler approach would be to use the pass-through as the data source in a new "make table" query.
SELECT * INTO MyNewTable FROM YourPassThruQuery;
Oops, looks like you meant to append those rows to an existing table.
INSERT INTO MyNewTable
SELECT * FROM YourPassThruQuery;
If the table structures don't match, you can use field lists for both tables.
INSERT INTO MyNewTable (fld1, fld2)
SELECT first_field, second_field FROM YourPassThruQuery;

How to compare two access databases to compare database records

How can i compare two MS ACCESS 2007 databases.Both databases contain same tables with same feilds ad structure.i need to compare the record values between two databases to detect any difference in record values.
ACCESS 2007 Database1
serial no. | NAME | ADDRESS
1 smith street 1
2 john street 4
3 alix street 8
ACCESS 2007 Database2
serial no.| NAME | ADDRESS
1 smith street 1
2 jhn stret 4
3 alix street 8
I need a VBA code for ms access that can detect the differece of records,just as the records at serial number two.
First thing you should do is link in one of the tables to the other database, e.g link the Database 2 table into database one (this allows both to be queried together) then you could use this simple example with concatenation to determine if all the fields strung together match based on the serial number:
SELECT T1.*, T2.*
FROM Table1 As T1, Table2 As T2
WHERE T2.[serial no.] = T1.[serial no.]
AND T2.[NAME] & T2.[ADDRESS] <> T1.[NAME] & T1.[ADDRESS]
You could also specify the columns with each of their own condition if you prefer.
NOTE: This is assuming you are only looking for differences where the serial no matches, if you also need to identify records that may appear in one table but not the other then you will need to use an "Un-matched" query, the query designer can help you with this or post back and I can update my answer.
Option Compare Database
Private Sub Command4_Click()
Dim tablename1, tablename2 As String
tablename1 = Text0.Value
tablename2 = Text2.Value
'On Error GoTo Err_cmdValidateGeneralInfo_Click
Dim F As DAO.Field
Dim rs As DAO.Recordset
Dim rs1 As DAO.Recordset
Set curDB = CurrentDb()
'If Me.DateModified = Date Then
'Adds new employees to the TT_GeneralInfo table in the FTEI_PhoneBook.mdb - which is used thru out the AP databases.
' DoCmd.OpenQuery "qryEmpData_TT_General"
strsql = "Select * from " & tablename1
Set rs = curDB.OpenRecordset(strsql)
strsql1 = "Select * from " & tablename2
DoCmd.CopyObject , "Unmatched_records", acTable, tablename1
curDB.Execute "DELETE FROM Unmatched_records"
Set rs1 = curDB.OpenRecordset(strsql1)
Do Until rs.EOF
For Each F In rs.Fields
If rs.Fields(F.Name) <> rs1.Fields(F.Name) Then
'rs.Edit
strsql = "Select * into test from " & tablename1 & " where " & F.Name & " = """ & rs.Fields(F.Name) & """"
DoCmd.RunSQL strsql
If DCount(F.Name, "test") <> 0 Then
GoTo append_unmatch
'appending unmacthed records
append_unmatch:
strsql2 = "insert into Unmatched_records Select * from test"
DoCmd.RunSQL strsql2
'if record doesnt match move to next one
GoTo Nextrecord
End If
' rs.Fields(F.Name) = rs1.Fields(F.Name)
' rs.Update
End If
Next F
Nextrecord:
rs.MoveNext
rs1.MoveNext
Loop
'To check whether tables matched or not
Dim rs2 As DAO.Recordset
strsql3 = "select * from Unmatched_records"
Set rs2 = curDB.OpenRecordset(strsql3)
For Each F In rs2.Fields
If DCount(F.Name, "Unmatched_records") <> 0 Then
MsgBox ("The two tables didnt match. Check table test for unmatching reocrds.")
Else
MsgBox ("Tables match!")
End If
Exit Sub
Next F
rs2.Close
End Sub