New to this site and access.
I am trying to create a database to keep track of a master log. Need help with sequential numbering. I currently have the following tables.
PO Table
POID - Autonumber(PK)
PODate - Date/Time
Supplier - String
Item Table
ItemID - Autonumber(PK)
POID - Ingeter(FK)
ItemDescription - String
Quantity - Integer
MasterLog Table
MasterLogID - Autonumber(PK)
ItemID - Integer(FK)
PieceNumber - Integer ( 1,2,3 ... etc)
MFG - String
Process - String
Length - Integer
MfgIDNum - String (ABD123XTY-1234)
I am trying to automate the data entry of the PieceNumber field. So when you enter a new PO and add items to it, once received. It will add a row to the masterlog table starting at piece number 1 through how ever many pieces we have. We number the pieces based on the items we purchased.(i.e. with Item 1 we purchased 100 pieces. So I would have Item 1 piece 1 through 100.) Then we are able to add the other data to the table. Just trying to reduce some data entry time and avoid some mistakes in the numbering of this field.
Any ideas?
Something like this would be a very simple way of doing it. You'd have to have a predefined table called Numbers with integers starting from 1 to however high a quantity you might have:
INSERT INTO MasterLog (ItemID, PieceNumber)
SELECT Item.ItemID, Numbers.Number
FROM Item, Numbers
WHERE (Item.ItemID = Forms!Items!ItemID) AND
(Numbers.Number <= Item.Quantity)
ORDER BY Numbers.Number
If you wanted to add the pieces one by one you could default the PieceNumber field on the related form. Make sure you default MasterLog.ItemID as well:
=Nz(DMax("[PieceNumber]","[MasterLog]","[ItemID] = " & Forms!Items!ItemID), 0) + 1
For a VBA solution try something like this:
Dim db As Database
Dim strSQL As String
Dim frm As Form
Dim i As Integer
Set db = CodeDb()
Set frm = Forms!Items
If frm!Quantity > 0 Then
For i = 1 To frm!Quantity
strSQL = "INSERT INTO MasterLog (ItemID, PieceNumber) " & _
"SELECT " & frm!Item & " AS ItemID, " & _
i & " AS PieceNumber"
db.Execute strSQL, dbFailOnError
Next i
End If
Set db = Nothing
All of these presume a form displaying your current item called Items.
Related
I have imported an existing excel file and created it as table 'Product' in access. It already has rows of existing data. I have created a form based on the table for data entry.
I would like to enter multiple values in the ProductNo cell separated by a comma ( as shown below)
PID (PK - Autonum)
PCR
ProductNo
Title
Unit
Dept
Date
Comments
PCR1
p210en, p213es, p217er
PCR1 title description
2
D1
1/23/21
fdsfsdf
and saving the record, it has to split the cell values and save it as multiple records in the backend product table.
PID (PK - Autonum)
PCR
ProductNo
Title
Unit
Dept
Date
Comments
PCR1
p210en
PCR1 title description
2
D1
01/23/2021
fdsfsdf
PCR1
p213es
PCR1 title description
2
D1
01/23/2021
fdsfsdf
PCR1
p217er
PCR1 title description
2
D1
01/23/2021
fdsfsdf
I don't want to edit the existing data in Product. It correctly reflects only one value in the ProductNo. I want to update only the values entered in the form.
I have looked for similar vba codes and found ones that modifies data in the existing table.
I have worked with SQL before but not much with Access/VBA code. I have programming knowledge. Any help is appreciated. Thank you :)
Updated -- Possible Solution:
So this is what I have done. I have a created a temporary table 'TempProduct' that I have used to input the data and when I click on save button, I have the following vba code that splits the cell data in multiple records and adds it to the original table.
enter code here
Option Compare Database
Private Sub Command11_Click()
Dim db As Database
Dim rs1 As Recordset
Dim rs2 As Recordset
Set db = CurrentDb()
Dim sqlStr, fieldStr As String
Dim i As Integer
sqlStr = "Select PCR, ProductNo, Title, Unit, Dept, Date, Comments from TempProduct"
Set rs1 = db.OpenRecordset(sqlStr)
Set rs2 = db.OpenRecordset("Product")
Do While Not rs1.EOF
fieldStr = rs1.Fields(1)
If InStr(fieldStr, ",") > 0 Then
myString = Split(fieldStr, ",")
For i = LBound(myString) To UBound(myString)
rs2.AddNew
rs2!PCR = rs1!ECRNo
rs2!ProductNo = myString(i)
rs2!Title = rs1!Title
rs2!Unit = rs1!Unit
rs2!Dept = rs1!Dept
rs2!Date = rs1!Date
rs2!Comments=rs1!Comments
rs2.Update
Next i
Else
rs2.AddNew
rs2!PCR = rs1!ECRNo
rs2!ProductNo = rs1!ProductNo
rs2!Title = rs1!Title
rs2!Unit = rs1!Unit
rs2!Dept = rs1!Dept
rs2!Date = rs1!Date
rs2!Comments=rs1!Comments
rs2.Update
End If
rs1.MoveNext
Loop
DoCmd.RunSQL ("Delete * from TempProduct")
End Sub
And it kind of works. Though the multiple records are pushed from the form into the product table only when a new record is added again. i.e. the first record entered in the form are split and entered into the product table only after the second set of records are entered in the form.
Any suggestions as how I can push the records immediately. Thanks a bunch.
As the title says I'm trying to sort a DataGridView into 3 Columns using data from MYSQL. So far I managed to populate 2 of the 3 columns with the correct data using:
'Load Shift Report Data
Dim Com2 As MySqlCommand
Connection.Open()
Dim Shift_Status As String = "OPEN"
Com2 = New MySqlCommand("SELECT Item0, Item1, Item2, Item3, Item4, Item5, Item6, Item7, Item8, Item9, Item10,
Item11, Item12, Item13, Item14, Item15, Item16, Item17
FROM tbl4ShiftReport WHERE USER_ID= '" + User_ID + "' AND Shift_Status= '" + Shift_Status + "';", Connection)
Com2.CommandType = CommandType.Text
Dim MSDA2 As New MySqlDataAdapter(Com2)
Dim DT2 As New DataTable()
MSDA2.Fill(DT2)
Connection.Close()
If DT2.Rows.Count >= 1 Then
Dim DT3 As New DataTable()
For i As Integer = 0 To DT2.Rows.Count + 1
DT3.Columns.Add()
Next
For i As Integer = 0 To DT2.Columns.Count - 1
DT3.Columns("Column2").DataType = GetType(Decimal)
DT3.Columns("Column3").DataType = GetType(Byte())
DT3.Rows.Add()
DT3.Rows(i)(0) = DT2.Columns(i).ColumnName
Next
For i As Integer = 0 To DT2.Columns.Count - 1
For j As Integer = 0 To DT2.Rows.Count - 1
DT3.Rows(i)(j + 1) = DT2.Rows(j)(i)
Next
Next
DataGridView2.DataSource = DT3
This is only working because I'm only getting one set of the Data and their Column names in the db and sorting them into the Data Table and then making this the data source for the datagrid.
But the third set of data for the third column in the datagrid, which I'm not getting yet in this example, are ftp links stored as strings to display in this third column as thumbnails. These links are in a separate table in mysql and I can reference them to the corresponding data however I'm unsure on how to accommodate this into the winforms table.
With this said my first question would be how can I sort this third column into the data table? Right now I'm basically putting the column names in column 1 and the data in column 2 but this third set of data I dont know how to sort it. I'm thinking making an if statement that if the column name starts with "item" put it in column 2 and if it starts with "img" put it in column 3 but still i need to sort that item1 goes with img1 and so on.
My second question would be once I sort the data how can I download the images and display them in that third column.
Thank you in advance!
I am building an inventory database that needs to track individual items. Each item has a unique number associated with it. However, we receive these items in bulk quantities, and distribute them likewise. I have set up a data entry form to input the start of the item number range, and the end of the item number range. For example, the item range would look something like this -- 1056-56701 through 1056-56800. The item number is always 4 digits followed by a dash and 5 digits. I am looking to expand the range that is put into my data entry form, so that each individual item number within the range is saved to my table. In this case-- 1056-56701, 1056-56702, 1056-56703, 1056-56704....156-56800. I also need to save the corresponding info for each item range as it is saved as an individual number. That would include things like 'date received', 'size', etc.
I have read some other responses to similar problems, but I still can't get this to function properly. Any thoughts?
An example of the design you might need:
MASTER
------
Prefix Int (primary key)
SuffixBegin String
SuffixEnd String
ItemDescription String
DateReceived Date
Size String
. . . more columns for any other data common to the entire "batch"
DETAIL
------
ID Int (primary key)
Prefix Int (foreign key, related to the same-named column in the Master table)
Suffix String (values such as "56701", "56702", etc.)
. . . more columns for whatever data you need to store about unique suffix items
You could then find data for a specific item something like this (pseudo-SQL, untested):
SELECT M.ItemDescription, D.SomeSuffixSpecificData
FROM MASTER M, DETAIL D
WHERE M.Prefix = (the Prefix you're interested in)
AND D.Suffix = (the Suffix you're interested in)
JOIN M.Prefix = D.Prefix
You can use a function like this to list and add your items:
Public Function AddBulk(ByVal First As String, ByVal Last As String) As Integer
Dim Items As Integer
Dim Item As Integer
Dim BulkId As String
' Open your inventory table.
' Set rs = CurrentDb.OpenRecordset("Select Top 1 * From Inventory")
For Item = Split(First, "-")(1) To Split(Last, "-")(1)
BulkId = Split(First, "-")(0) & "-" & Item
Debug.Print Items, BulkId
' Insert code to add one record to your inventory table.
' rs.AddNew
' rs!BulkId.Value = BulkId
' rs!OtherField.Value = somevalue
' rs.Update
Items = Items + 1
Next
' rs.Close
AddBulk = Items
End Function
I have two tables which can be represented by this query (I have made this query the Recordsource of the form):
SELECT tblrcmtask.id, tblrcmtask.rcmtask,tblrcmtaskoptions.id,
tblrcmtaskoptions.rcm_id,
tblrcmtaskoptions.rcmtaskoptions
FROM tblrcmtask
INNER JOIN tblrcmtaskoptions
ON tblrcmtask.id=tblrcmtaskoptions.rcm_id
I want the user to be able to add new entries into these table via a form in access 2007.
Columns tblrcmtask.id and tblrcmtaskoptions.id are the primary keys of the tables tblrcmtask and tblrcmtaskoptions respectively.
I do not understand how do I create new ID in both the tables while the user adds new entries.The user can add only tblrcmtaskoptions.rcmtaskoptions and tblrcmtask.rcmtask in the form.Also, there are multiple rows in the table tblrcmtaskoptions for each tblrcmtask.id.
I want the user to be able to add new rows in the table tblrcmtaskoptions for an existing tblrcmtask.id
I tried using dropdowns for these two but I am facing problem while creating the new ID as Maximum of the ID + 1.
Dim MyRecords As DAO.Recordset
Dim Myfield As DAO.Fields
SQL = "SELECT Max(tblRCMTASK.ID) AS MaxOf_RCMTASKID FROM tblRCMTASK;"
Set MyRecords = dbTHIS.OpenRecordset(SQL)
Set Myfield = MyRecords.Fields
Me.txtRCMTASKID = Myfield("MaxOf_RCMTASKID") + 1
Me.txtRCMTASKID.DefaultValue = Myfield("MaxOf_RCMTASKID") + 1
MyRecords.Close
End If
Dim MyRecords1 As DAO.Recordset
Dim Myfield1 As DAO.Fields
SQL = "SELECT Max(tblRCMTASKOPTIONS.ID) AS MaxOf_RCMOPTIONSID FROM tblRCMTASK;"
Set MyRecords = dbTHIS.OpenRecordset(SQL)
Set Myfield1 = MyRecords1.Fields
Me.txtRCMOPTIONSID = Myfield1("MaxOf_RCMOPTIONSID") + 1
Me.txtRCMOPTIONSID.DefaultValue = Myfield("MaxOf_RCMOPTIONSID") + 1
MyRecords1.Close
I am getting an error which says you can't asign a value to this object and points to this line: Me.txtRCMTASKID = Myfield("MaxOf_RCMTASKID") + 1
How do I do this?
Access gives you trouble when trying to do operations on an autonumber field. If you would like to do these kinds of operations, you may be better off just using a regular number as a PK.
To get a recently inserted autonumber field to insert the same number in a related table, this is the VBA:
assuming recordset and database are declared, rs and db
dim id as integer
set db = CurrentDb
set rs = db.openrecordset("firstTable", dbOpenDynaSet)
With rs
.addNew
.Fields("field1").Value = Me.control1 'adds to column1 of your table the value of control1
.Fields("field2").Value = Me.control2
.update 'updates the record. If it is an autonumber, it will be automatically assigned. I will show you how to access this for your next insert
end with
'To get the autoID of the entry we just inserted, do this
id = db.OpenRecordSet("SELECT##IDENTITY")(0)
'Now you have the autoID of the recent insertion, so you may use it for your next one.
This is a classic form/subform set up. Create a form based solely on tblrcmtask with a subform tblrcmtaskoptions. The link child and master fields should be set to the common id. The wizards will do this for you. There is no code required. The id will be automatically added by the link fields.
You can see an example for in the 2007 version of the Northwind sample database.
I'm using MS Access with a MySQL database. One table has records which represent 'documents':
Table: doc
Primary Key: doc_id
These records can be linked together via a link table:
Table: link
Primary Key: link_id
Foreign Key: doc_id_A
Foreign Key: doc_id_B
Thus the records may be linked in a chain, eg Doc A linked to Doc B, which is linked to Doc C, etc, and also, Doc A may be linked to any number of other documents.
In reality, the 'family' of inter-related documents wouldn't exceed 20 records.
I'm looking for an efficient MySQL proc, or VBA function - or a query - to find all the members of a 'family' for one specified record.
Any suggestions would be most welcome!
So the link table gives a self join to doc, you absolutely need a doc to be able to:
Link to itself
... as many times as it likes
Link to another doc
... multiple times
Be separately linked to by the same other doc
... multiple times
Store information about the link
So your link table could have 10 separate links 1-1, 1-1, 1-1, 1-2, 1-2, 1-2, 2-1, 2-1, 2-1, 2-2 etc. with just 2 docs in the 'family'.
I expect when you look at this list you will probably think that you don't need most of them, a lot of the inefficiency in your solution might be coming from this unnecessary flexibility. My favoured suggestion would be to start with a strict hierarchy and build minimally from there.
But here is my answer anyway, it's tested and working in Access-2010 and local tables. ADODB should work just as well with linked tables.
Option Compare Database
Option Explicit
Const MaxInFamily = 30
'Requires a reference to "Microsoft ActiveX Data Objects 2.x Library" (VBA Menu: Tools, references)
Function GetFamily(id As Long) As Long()
Dim Found(MaxInFamily) As Long
Dim MaxFound As Integer
Dim CurrentSearch As Integer
Dim Sql As String
Dim rs As New ADODB.Recordset
Found(1) = id
MaxFound = 1
For CurrentSearch = 1 To MaxInFamily
If CurrentSearch > MaxFound Then Exit For
Sql = "SELECT doc_id_2 as NewID FROM link WHERE doc_id_1 = " & Found(CurrentSearch) _
& " AND doc_id_2 NOT IN (" & ArrayToCsv(Found, MaxFound) & ")" _
& " UNION " _
& " SELECT doc_id_1 FROM link WHERE doc_id_2 = " & Found(CurrentSearch) _
& " AND doc_id_1 NOT IN (" & ArrayToCsv(Found, MaxFound) & ")"
rs.Open Sql, CurrentProject.Connection
Do While Not rs.EOF
MaxFound = MaxFound + 1
Found(MaxFound) = rs("NewID").Value
rs.MoveNext
Loop
rs.Close
Next CurrentSearch
GetFamily = Found
End Function
Function ArrayToCsv(SourceArray() As Long, ItemCount As Integer) As String
Dim Csv As String
Dim ArrayIndex As Integer
For ArrayIndex = 1 To ItemCount
Csv = Csv & SourceArray(ArrayIndex)
If ArrayIndex < ItemCount Then Csv = Csv & ", "
Next ArrayIndex
ArrayToCsv = Csv
End Function
Duplicated results and queries are avoided by excluding items already found at the server, and as the link is unidirectional I've used a UNION query to look both ways at once. At most it'll do MaxInFamily round trips to the server.
Unfortunately, it cannot be done in MySQL given such a table structure as MySQL does not support recursive queries. I suggest to explore the answers in Mysql recursion? - there is some advice as to how to store the data in MySQL to be able to write such queries.
You also have three other options:
In case you know the max. depth of such families, and it's not huge, you can still achieve it with mySQL. For a depth of 3 levels, it would look like this:
SELECT A.doc_id_a as a, B.doc_id_a a_child, C.doc_id_a as a_sub_child
FROM links as A, links as B, links as C
WHERE A.doc_id_a = your_doc_id AND
A.doc_id_b = B.doc_id_a AND
B.doc_id_b = C.doc_id_a
Following the same logic, you can add as many layers as you need. The only thing is - you'll need to get result from all columns and find unique values (and there can be many rows, if the relationship is not 1-1 all the time).
A second option is to do this in VBA. I do not know enough to provide the code, but essentially it could look like this (a recursive approach):
family = array();
family = getFamily('your_doc_id', family);
function getFamily(id) {
children = DB->getColumn('SELECT doc_id_b FROM links WHERE doc_id_a = ?', id);
if (empty(children)) return family;
else {
foreach (children as child) {
family[] = getFamily(child);
}
}
}
Lastly, you can switch to PostgreSQL, which supports recursive queries :)
(http://www.postgresql.org/docs/8.4/static/queries-with.html).
I had a similar problem some time ago. Instead of creating links between the documents I used a separate table containing the families:
Table: LinkTable
PK: LinkId, DocumentID
FK: DocumentID
Instead of having pairs of document IDs, each time you create a new family, you introduce a new LinkId.
LinkId | DocumentID
1 | 7
1 | 9
1 | 13
2 | 4
2 | 22
2 | 23
2 | 30
3 | 6
3 | 80
Here you have three families with the document IDs:
{ 7, 9, 13 },
{ 4, 22, 23, 30 },
{ 6, 80 }
It is easier to retrieve families, however it requires a somewhat more complicated logic for inserting and removing documents to and from families.