Split string separated by commas in access - sql

I have a table tblPartnerships structured as
ID Partnerships
1 Finance, IT, Operations
2 Legal, Compliance, IT, HR
I need to extract all of the comma separated keywords from Partnerships column and put it in another mastertable with each word as a separate row so that it shows up as
Finance
IT
Operations
Legal
Compliance
IT
HR
I know there is a split function such as varList = Split(stTmp, ",") but i am completely lost how to iterate through the entire column tblPartnerships.Partnerships insert it into MasterTable.Rowheading
Any Access query or vba code will be highly appreciated

Create an Append query with a single parameter, the word to be imported. The query's source SQL should be something like this:
PARAMETERS [prmWord] Text (50);
INSERT INTO T ( Words )
SELECT [prmWord] AS _Word;
Where T is the name of your Table (master) and Words is the name of the Field.
Then just loop through the Partnerships recordset, split the value and import each word using the above query.
Sub SplitAndImport()
On Error GoTo ErrorTrap
Dim rs As DAO.Recordset
Set rs = CurrentDb().OpenRecordset("SELECT Partnerships FROM tblPartnerships;", dbOpenSnapshot)
With rs
If .EOF Then GoTo Leave
.MoveLast
.MoveFirst
End With
Dim arr As Variant
Dim i As Long, ii As Long
For i = 1 To rs.RecordCount
arr = Split(rs![Partnerships], ",")
For ii = LBound(arr) To UBound(arr)
With CurrentDb().QueryDefs("QueryName")
.Parameters("[prmWord]").Value = Trim(arr(ii))
.Execute dbFailOnError
End With
Next
rs.MoveNext
Next
Leave:
If Not rs Is Nothing Then rs.Close
On Error GoTo 0
Exit Sub
ErrorTrap:
MsgBox Err.Description, vbCritical
Resume Leave
End Sub

This may not work as accurately with your current database design.
You may try using multivalued fields. Later, if you want view multi values each on single row then use "AssignedTo" command.
SELECT [title], [lcs].[AssignedTo].[value] AS Expr1
FROM Product;
Where lcs is a multivalued field and title is a text field.

Related

how to get the last non empty column in ms access

so i have this huge database for my school project it goes like this
id
team
game1
score1
game2
score2
game3
score3
1
barca
vs real
2-1
vs bvb
5-2
vs atletic
0-3
2
real madrid
vs barca
1-2
vs betis
3-0
3
man city
vs man united
1-2
and i want to make a query that will give me only the last game of each team
in excel its easy but i cant do it in ms access
result that i need is
id
team
last game
1
barca
vs atletic
2
real madrid
vs betis
3
man city
vs man united
One thing that has been commented on is that your database design needs to be fixed - you don't go across (as you would in Excel), but down as extra rows in tables. There is a limit of 255 fields in an Access table that you need to be aware of.
However, if you decide to stick with this, a different way of approaching it would be to create a small VBA function that loops the fields backwards to get the answer that you need. Something like:
Function fLastMatch(lngTeamID As Long) As String
On Error GoTo E_Handle
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
Dim lngLoop1 As Long
Set db = DBEngine(0)(0)
strSQL = "SELECT * FROM tblFootball WHERE id=" & lngTeamID
Set rs = db.OpenRecordset(strSQL)
If Not (rs.BOF And rs.EOF) Then
For lngLoop1 = rs.Fields.Count - 2 To 2 Step -2
If Not IsNull(rs.Fields(lngLoop1)) Then
fLastMatch = rs.Fields(lngLoop1)
Exit For
End If
Next lngLoop1
End If
fExit:
On Error Resume Next
rs.Close
Set rs = Nothing
Set db = Nothing
Exit Function
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "fLastMatch", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume fExit
End Function
This works because the last (nth) field in the recordset is position n-1 as recordsets are 0-indexed (the first field is in position 0, the second field is position 1.....). This means that the last match field is in position n-2. So we start at this position in the fields and check if there is data. If there is, we have found the last match played and can exit the loop. If there is no data, then we go back two fields, to the previous match, and then repeat the checks.
You can then use this function in a query to get the answers that you require:
SELECT id, fLastMatch(id) AS LastMatch
FROM tblFootball;
This approach means that you don't need to worry about how many matches are included and add the correct number of Nzs in if this changes over time (which is a bad idea in a database).
Regards,
Assuming the missing values are null, you can use nz():
select id, team,
nz(game3, nz(game2, game1)) as last_game
from t;
Note that this would be simpler in any other database. The standard SQL function coalesce() takes multiple arguments:
select id, team,
coalesce(game3, game2, game1) as last_game
from t;

Excel VBA: Insert a column in an Array from an ADODB Result Set

I've queried an MS-Access database from within VBA, and returned the result set to an array, as follows:
Sub ChartData()
Dim cn As Object
Dim rs As Object
Dim strSql As String
Dim strConnection As String
Set cn = CreateObject("ADODB.Connection")
' Hard code database location and name
strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\server1\myDB.mdb"
' Construct SQL query
strSql = "TRANSFORM Count(Names) AS CountOfNames SELECT Ticker FROM Pricing GROUP BY Ticker PIVOT Source; "
' execute the query, and return the results to the rs object
cn.Open strConnection
Set rs = cn.Execute(strSql)
' Copy the result set to an array
Dim myArr() As Variant
myArr = rs.GetRows
' Close the connection
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
...
End Sub
Next, I'd like to insert one column into myArr, which has dynamic dimensions. I've attempted to use ReDim Preserve for this purpose, but learned that ReDim Preserve will only allow changing the first dimension. For example, the following code results in the Run-time error, Subscript out of range:
Sub ChartData()
...
Dim newRowCount As Integer
Dim newColCount As Integer
newRowCount = UBound(myArr, 2) + 1
newColCount = UBound(myArr, 1) + 2
ReDim Preserve myArr(newColCount, newRowCount) ' Run-time error here
End Sub
Is there an elegant way to work-around this ReDim Preserve limitation to insert a column without wiping the data?
Thanks!
Consider adjusting SQL query at the source as suggested by #TimWilliams in the comments which avoids memory overhead and use of manipulating data objects.
Crosstab queries use an aggregate groupby within its structure which you can easily add scalar values including empty, numeric, or string values (which will be the same across all rows):
TRANSFORM Count(Names) AS CountOfNames
SELECT Ticker, NULL As EmptyColumn, 1 As AllOnesColumn, 'SQL in Excel' As AllStringColumn
FROM Pricing
GROUP BY Ticker
PIVOT Source;
Alternatively, save the crosstab query as a stored query object in Access database and run a typical select statement in Excel ADO connection referencing the stored query. Again, you can add scalar columns as needed:
SELECT storedquery.*, NULL As EmptyColumn, 1 As AllOnesColumn,
'SQL in Excel' As AllStringColumn
FROM storedquery

Query every table in an Access Database?

All tables in a certain database have the exact columns, so I'm wondering if there is a way I can query all of them at once for a specific few columns that I know every table will have. The reason I want to do this is that the number of tables in the database will constantly be growing, and I don't want to have to every day go and change my query to accommodate the names of the new tables.
Help is appreciated as always
In that case, try ADO:
Function ListTablesContainingField(SelectFieldName) As String
'Tables returned will include linked tables
'I have added a little error coding. I don't normally do that
'for examples, so don't read anything into it :)
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim strTempList As String
On Error GoTo Error_Trap
Set cn = CurrentProject.Connection
'Get names of all tables that have a column called <SelectFieldName>
Set rs = cn.OpenSchema(adSchemaColumns, _
Array(Empty, Empty, Empty, SelectFieldName))
'List the tables that have been selected
While Not rs.EOF
'Exclude MS system tables
If Left(rs!Table_Name, 4) <> "MSys" Then
strTempList = strTempList & "," & rs!Table_Name
End If
rs.MoveNext
Wend
ListTablesContainingField = Mid(strTempList, 2)
Exit_Here:
rs.Close
Set cn = Nothing
Exit Function
Error_Trap:
MsgBox Err.Description
Resume Exit_Here
End Function
From: http://wiki.lessthandot.com/index.php/ADO_Schemas
You might like to consider a table of tables, if you have not already got one, that lists the linked Excel tables and holds details of archive dates etc, because you will run into limits at some stage.

VBA to Trim all Cells in an Access Table

I'm relatively experienced with Object oriented programming, but this is my first time ever working in Office with VBA and I'm entirely stumped by the syntax. I've been doing some searching and messing with it for the past hour or so, but have been trouble actually getting a macro that runs successfully and does what I need.
I'm attempting to loop through every cell in an Access table and apply the Trim function to the contents of that cell and, as a bonus, I'd like to remove all extra spaces in the string (if any). I.e. " Trim this__string " would simply become "Trim this string" (I used the underscore there to represent individual, multiple spaces since StackOverflow didn't want to show my multiple spaces).
Any code example of doing something like this, or at least something to get me close and then I can tinker with it, would be greatly appreciated. Thanks!
You can remove leading and trailing spaces with the Trim() function in a query.
UPDATE YourTable
SET text_field = Trim(text_field);
If you will be doing this from within an Access session, you could use Replace() to replace a sequence of two spaces with a single space.
UPDATE YourTable
SET text_field = Replace(text_field, ' ', ' ');
However you may need to run that Replace() query more than once to get all the contiguous space characters down to only one.
You could also do a regular expression-based replacement with a user-defined function. I don't know if that's worth the effort, though. And a user-defined function is also only available from within an Access application session.
I overlooked the "every cell in a table" aspect. That makes this more challenging and I don't think you can solve it with a standard macro or query. You can however use VBA code to examine the TableDef, and iterate through its fields ... then call your Trim and/or Replace operations on any of those fields whose data type is text or memo.
Here's a rough code outline to identify which fields of a given table are text type.
Public Sub FindTextFields(ByVal WhichTable As String)
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Set db = CurrentDb
Set tdf = db.TableDefs(WhichTable)
For Each fld In tdf.Fields
If fld.Type = dbText Or fld.Type = dbMemo Then
Debug.Print "Do something with " & fld.Name
End If
Next
Set fld = Nothing
Set tdf = Nothing
Set db = Nothing
End Sub
Option Compare Database
Private Sub Command3_Click()
Call findField(Text1.Value)
End Sub
Public Function findField(p_myFieldName)
Dim db As Database, _
tb As TableDef, _
fd As Field
'''''''''Clearing the contents of the table
DoCmd.RunSQL "delete * from Field_Match_Found"
Set db = CurrentDb
For Each tb In db.TableDefs
For Each fd In tb.Fields
If fd.Name = p_myFieldName Then
strsql = "INSERT INTO Field_Match_Found Values (""" & tb.Name & """, """ & fd.Name & """)"
DoCmd.RunSQL strsql
End If
Next fd
Next tb
Set fd = Nothing
Set tb = Nothing
Set db = Nothing
If DCount("Account_number", "Field_Match_Found") = 0 Then
MsgBox ("No match was found")
Else
MsgBox ("Check Table Field_Match_Found for your output")
''''''''''making textbox blank for next time
Text1.Value = ""
End Function

Delete record based on text found in a field (

I normally do most of this work in Excel 2007, but I do not think excel is the right tool for managing the data that I need to process. So I am trying to convert an excel spreadsheet to an Access 2007 db which I can do with no problem, but before doing anything to the spreadsheet I go through the process of cleaning up the data in it in order to use the resulting information. In excel I use a macro such as the following
Sub deletedExceptions_row()
Dim i As Long
Dim ws As Worksheet
On Error GoTo whoa
Set ws = Sheets("data")
With ws
For i = .Cells.SpecialCells(xlCellTypeLastCell).Row To 1 Step -1
If .Cells(i, 3) = "" Or _
VBA.Left(.Cells(i, 3), 4) = "511-" Or _
VBA.Left(.Cells(i, 3), 5) = "CARL-" Then
.Rows(i).Delete
End If
Next i
End With
Exit Sub
whoa:
MsgBox "Value of i is " & i
End Sub
to remove unnecessary records in the spreadsheet how would I accomplish the same thing in Access 2007.
The macro is looking for particular parts or rather the first few characters of the record's 3rd field in order to determine if the whole record needs to be removed (ex. 511-QWTY-SVP or CARL-52589-00). In all there about 180 such character types that affect 1000's of rows that need to be removed from the spreadsheet, but I would like to replicate that same process in Access 2007, but do not know how.
Thank you all for your assistance with this problem
Within Access you can execute a DELETE statement to discard rows where the value in a field is an empty string ("") or matches one of your patterns.
DELETE FROM YourTable
WHERE
YourField = ""
OR YourField ALike "511-%"
OR YourField ALike "CARL-%";
With YourField indexed, that pattern matching in the WHERE clause offers a potentially large performance improvement over a query using the Left() function such as your spreadsheet macro used. IOW, the following query would require the db engine to run those Left() expressions on every row of YourTable. But with the query above and YourField indexed, the db engine could simply select the matching rows ... which can easily be an order of magnitude faster.
DELETE FROM YourTable
WHERE
YourField = ""
OR Left(YourField, 4) = "511-"
OR Left(YourField, 5) = "CARL-";
Sub DeleteRows(strVal as string)
strVal = Trim(strVal)
if strVal = "" then exit sub
dim dbs as Database
set dbs = CurrentDB
dbs.execute "Delete * FROM YOURTABLE where YOURFIELD Like '" & strVal & "*'"
set dbs = Nothing
End Sub
then call it for each item
DeleteRows("Carl-")
DeleteRows("511-")
Given that you have 180 possible problem rows, it may make sense to create a problem list table. For example:
ExcelImport
ID ARow
1 Carl-abdre
2 511-ferw2
3 wywr-carl
4 123-456
ProblemList
Problem
511-
Carl-
Query
DELETE
FROM ExcelImport
WHERE ExcelImport.ID In (
SELECT ID
FROM ExcelImport, ProblemList
WHERE ARow Like [Problem] & "*" Or ARow & ""="")
ExcelImport after query
ID ARow
3 wywr-carl
4 123-456
You manage database data using the SQL language. For Access, check:
http://msdn.microsoft.com/en-us/library/bb177896%28v=office.12%29.aspx
Sub DeleteX()
Dim dbs As Database, rst As Recordset
Set dbs = OpenDatabase("Northwind.mdb")
dbs.Execute "DELETE * FROM " _
& "Employees WHERE Title ALike 'FOOBAR-%';"
dbs.Close
End Sub