MS-Access: Split content on delimiter and join with other table - ms-access

I am using MS-Access 2007 and need to make a query.
I cannot modify the architecture to achieve the required result.
I need to split and join the mainTable's "RelatedMaster" (comma separated IDs) to the "Name" field (as comma separated Names in the result) in masterTable.
Table 1 : masterTable
ID Name
1 N1
2 N2
3 N3
Table 2 : mainTable
ID Name RelatedMaster
1 M1 1,2
2 M2 1,3
3 M3 2,3
Required Result : resultQuery
ID Name RelatedMaster
1 M1 N1,N2
2 M2 N1,N3
3 M3 N2,N3
Please guide on how can i solve the problem.Thanks

As you realize at this point, it is bad design, but you can use a helper function:
Public Function GetNs(ByVal MasterIds As String) As Variant
Dim MasterValues As Variant
Dim Item As Integer
MasterValues = Split(MasterIds, ",")
' Lookup Name one by one.
For Item = LBound(MasterValues) To UBound(MasterValues)
MasterValues(Item) = DLookup("[Name]", "[Table 1]", "ID = " & MasterValues(Item) & "")
Next
GetNs = Join(MasterValues, ",")
End Function
Of course, for a large Table 1, you would open it as a recordset and find the values.

Related

Insert only enabled textboxes into MySQL in VB.Net

I am creating an inventory management system in VB.Net, where the basic function is the process incoming invoices. I would like to insert data into my remote MySQL database but only if the textbox is considered enabled. I have no issue inserting data into the database when I want it to insert all fields. But I would like to have checkboxes enable certain products and allow the employees to enter only specific items. The check boxes do enable and disable the text fields as required but when inserting data into the database it will enter null values for all product types and I don't want it doing that as it will mess up the invoicing system. Currently I tried an if then statement but the issue I ran into was that it wanted the not enabled textboxes to be defined.
Code for what I tried is:
Public Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
Dim mysqlconn as new MySqlConnection ("ServerConnection")
mysqlconn.Open()
dim mysqlCmd as new MysqlCommand
mysqlcmd.Connection = MysqlConn
mysqlcmd.CommandText = "Insert into Table_Name (Column1,Column2,Column3) Values (#rec1,#Rec2,#Rec3)"
If txtTextbox1.Enabled = True then
mysqlcmd.Parameters.AddWithValue("#Rec1",Column1.text)
End If
If txtTextBox2.Enabled = True then
mysqlcmd.Parameters.AddWithValue(#Rec2,Column2.text)
End IF
IF txtTextBox3.Enabled = True then
mysqlcmd.Parameters.AddWithValue(#Rec3,Column3.text)
End If
You can't just insert a column without a row. So if you will insert one column, you must insert all columns. If you don't want to add a value, then the column could be NULL or empty string, depending on the columns in the database. Also use Using and take the database work off the UI with Async/Await
Public Async Sub btnEnter_Click(sender As Object, e As EventArgs) Handles btnEnter.Click
' if your columns take NULL to mean no value
Await AddParams(
If(txtTextbox1.Enabled, Column1.Text, Nothing),
If(txtTextbox2.Enabled, Column2.Text, Nothing),
If(txtTextbox3.Enabled, Column3.Text, Nothing))
' else, if an empty string means no value
Await AddParams(
If(txtTextbox1.Enabled, Column1.Text, ""),
If(txtTextbox2.Enabled, Column2.Text, ""),
If(txtTextbox3.Enabled, Column3.Text, ""))
End Sub
Private Function AddParams(param1 As String, param2 As String, param3 As String) As Task
Return Task.Run(
Sub()
Using mysqlconn As New MySqlConnection("ServerConnection")
mysqlconn.Open()
Using mysqlCmd As New MySqlCommand("Insert into Table_Name (Column1,Column2,Column3) Values (#rec1,#Rec2,#Rec3)", mysqlconn)
mysqlCmd.Parameters.AddWithValue("#Rec1", param1)
mysqlCmd.Parameters.AddWithValue("#Rec2", param2)
mysqlCmd.Parameters.AddWithValue("#Rec3", param3)
End Using
End Using
End Sub)
End Function
If I understand your current design,
Table_Name
ID
Column1
Column2
Column3
1
abc
def
ghi
2
jkl
mno
pqr
An incomplete invoice has empty string or NULL when one column isn't enabled
ID
Column1
Column2
Column3
1
abc
NULL
ghi
2
NULL
mno
pqr
This is what this answer does.
If your database design is flexible, perhaps a better design would be
Invoice
ID
Name
1
Invoice 1
2
Invoice 2
InvoiceRec
ID
Name
1
Column1
2
Column2
3
Column3
InvoiceItem
ID
InvoiceID
InvoiceRecID
Value
1
1
1
abc
2
1
3
ghi
3
2
2
mno
4
2
3
pqr
Now you aren't storing any null when an item is not enabled. The SQL to select would then be
SELECT
i.Name InvoiceName
, ir.Name InvoiceRecName
, ii.Value Value
FROM InvoiceItem ii
INNER JOIN Invoice i ON i.ID = ii.InvoiceID
INNER JOIN InvoiceRec ir ON i.ID = ir.InvoiceRecID
WHERE i.Name = 'Invoice 1'
InvoiceName
InvoiceRecName
Value
Invoice 1
Column1
abc
Invoice 1
Column3
ghi
This would totally invalidate the code I wrote (except keep the Async and Using) and you'd need to query multiple tables before making multiple inserts, but the design would be normalized and database storage size would be reduced.
Further, you can build your UI from the metadata tables [Invoice] and [InvoiceRec] so if wanted to add another InvoiceRec to your business, you can add in SQL, and the UI will not need to be modified.

Return Unique Records for Field

We have an access database create a csv list in an access table for each userid that logs into a computer. The problem is that if a userid logs in multiple times on one computer, than the userid is duplicated.
SO let's say this is what the table structure looks like
computer DailyUsers
ABC-123 ml12, rs12, ml12, ml12, ee13
DEF-456 zx44, aa33, zx44
And this is what I want a query to return
Computer DailyUsers
ABC-123 ml12, rs12, ee13
DEF-456 zx44, aa33
I tried using both Group By and Distinct but that looks on a row by row basis, not a field basis
How can this be achieved in Access 2013?
You can create a custom function in VBA to return only the unique users.
Add this in a VBA module:
Option Compare Database
Option Explicit
Public Function DistinctOnly(txt As String)
Dim arr, v, rv As String
Dim d As Object
arr = Split(txt, ",")
If UBound(arr) > 0 Then
Set d = CreateObject("scripting.dictionary")
For Each v In arr
d(Trim(v)) = 1
Next v
rv = Join(d.keys, ",")
Else
rv = txt
End If
DistinctOnly = rv
End Function
Usage:
SELECT Table1.[ID], Table1.[Users], DistinctOnly(Table1.[Users]) as UsersX
FROM Table1;
Input data and query results:

Filtering Data from a specific column

Hello Everyone I am at a dilemma I am trying to find out a way to filter out certain data in a column field I have an idea on how to do this but I do not know the correct syntax to use. First here is the table and here is the code structure I would like to write.
for i=1 to length of column First Match
for j=1 to length of column Second Match
If ((value of the data in column First Match = 15) OR (value of the data in column FirstMatch = 1)) AND
((value of the data in column Second Match = 15) OR (value of the data in column Second Match = 1))
Then
Filter the data and append so the filtered datas are saved for both First Match and Second Match
end if
next
next
I am trying to filter out the data that is a 15 and 1 so that only data that have the values 0,2,3,4,5,6...14 will be shown for instance the information of john and steve will not be shown because both the first and second match fields have a 1 or 15 but the rest of data will be shown my form is a split form setup.
Is my method correct?
First Name Last Name First Match Second Match
James Matheson 0 2
Monroe Labonson 4 3
Barack Obama 2 5
Frederick Douglas 3 4
Steve MCGowan 1 1
John Seals 15 15
Mike Omalley 14 15
Set rs = CurrentDb.OpenRecordset("Table1")
Do While Not rs.EOF
If rs!Fields("First Match") > 1 And rs!Fields("First Match") < 15 And rs!Fields("Second Match") > 1 And rs!Fields("Second Match") < 15 Then
End If
Loop
With a better understanding (I hope) I've reproduced your data in Access and built a query that does what you seem to ask. The best way to see this is to create a new query, not add a table, and go directly to SQL view. Paste the following SQL statement (the one in quotes) in and replace matchFilter with your table name.
In your event code you can create a recordset based on the SQL:
Dim sSQL as string, rs as Recordset
sSQL = "SELECT matchFilter.[First Name], matchFilter.[Last Name], matchFilter.[First Match], matchFilter.[Second Match] " & _
"FROM matchFilter " & _
"WHERE ((([First Match]<>1 And [First Match]<>15 And [Second Match]<>1 And [Second Match]<>15)=True))"
Set rs = CurrentDB.OpenRecordset(sSQL)
' now do what you want
Wrong answer below!
Dim rs as Recordset
Set rs = CurrentDB.OpenRecordset("yourTableName")
Do While Not rs.EOF
If rs!Fields("col1") > 1 AND rs!Fields("col1") < 15 AND rs!Fields("col2") > 1 AND rs!Fields("col2") Then
'do what you have to do with filtered out records
End If
Loop
I have found the solution apparently it was just a misunderstanding because the first time I tried this code I thought it was wrong but it was because my field names did not have spaces in between the first time I wrote them.
Me.Filter = ""
Me.Filter = "[First Nam]<>'Jamie' AND [Last Nam]<>'Cartman'"
Me.FilterOn = True

VB6 variable recordset name

Is it possibile to access a recordset using a variable for the name ?
For example, i've a table with 10 fields called Name01,Name02,Name03.....Name10. I need to cycle through them so it would be nice to just use one instruction insted of repeating the same one with 10 different name.
This is the code i'm using now
Sal01 = rsUtility!Order01
Sal02 = rsUtility!Order02
....
Sal10 = rsUtility!Order10
This is what i would like to accomplish :
for i = 1 to 10
VariableName = "Order" & i
Sal(i) = rsUtility!VariableName
next i
Here you go:
for i = 1 to 10
VariableName = "Order" & i
Sal(i) = rsUtility(VariableName)
next i
Since your variables have a 2 digit ending, you gotta use a proper format and not just "Order" & i, because it will result in Order1 and not Order01
For i = 1 to 10
Sal(i) = rsUtility("Order" & Format(i,"00") )
Next i
The loop above will assign a value to a corresponding array element from DB variables in the range from Order01 to Order10 inclusive

Getting the value not the ID

I have a table tblInvestigators which contains a lookup field to display a list of names
A grant may have more than 1 investigator.
A requirement of my project is to list all investigators in a single cell next to the grant details, so i'd have:
Grant A | Name A, Name B, Name C
etc.
I have a VBA module that concatenates the investigators into 1 cell as follows:
'Concat Returns lists of items which are within a grouped field
Public Function c(strID As String, strAddMe As String) As String
Static prevID As String
Static strFinal As String
Static strLastAdded As String
If (strID = prevID And strAddMe <> strLastAdded) Then
strFinal = strFinal & ", " & strAddMe
Else
prevID = strID
strLastAdded = strAddMe
strFinal = strAddMe
End If
c = strFinal
End Function
And an access query that calls it (SQL):
SELECT g.grant_id, Max(c(g.grant_id,tblInvestigators.investigator)) AS Expr1
FROM tblGrants AS g LEFT JOIN tblInvestigators ON g.grant_id = tblInvestigators.grant_id
WHERE (((g.grant_id)=6))
GROUP BY g.grant_id;
When I run this, it returns a comma separated list, but it is a list of the ID numbers from the look up column (tblInvestigators.investigator)rather than the names. How can I get the names?
Chris
It is never a good idea to use look-up fields: http://www.mvps.org/access/lookupfields.htm
It is disguising the standard way of getting the results you want, which is to use a query to join the ID to the look-up table and return the description.
Have a look at this Does MS access(2003) have anything comparable to Stored procedure. I want to run a complex query in MS acceess