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
Related
I have a power query function, e.g. getData with one parameter filename
Can I invoke that function directly in a vba variable? Something like:
Sub MyTest()
Dim MyVar
MyVar = ThisWorkbook.Queries("getData").Invoke("mytable.xls")
MsgBox "The Value is " & MyVar
End Sub
I use Excel 2016
Unfortunately, you cannot load the Power Query result to a VBA variable. You have to first load it to the sheet.
Here is a thread, where a Microsoft employee confirms that:
Link to Microsoft Employee relating to that issue
Contrary to the link in the accepted answer, it is possible to get an array from a query if you load the query to the data model. It can be a pain, and there are lots of pitfalls (spaces in table names, and I haven't tested where the query output is a list or otherwise not a table).
These functions aren't cleaned up, but they have given me success, and show where to poke around.
Function GetModelADOConnection()
'We just need the ADOConnection; the rest is for perusal
Set wbConnections = ThisWorkbook.Connections
Set Model = ThisWorkbook.Model
Set ModelDMC = Model.DataModelConnection
Set ModelDMCMC = ModelDMC.ModelConnection
Set GetModelADOConnection = ModelDMCMC.ADOConnection
End Function
Sub ListConnectionTables()
'Run this to dump a list of available tables in the immediate window, so you can see what you'll need to query
'https://learn.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/schemaenum
Set conn = GetModelADOConnection
Set TablesSchema = conn.OpenSchema(20)
Debug.Print "TABLE_SCHEMA", "TABLE_NAME", "COLUMN_NAME" 'headers for immediate window
Do While Not TablesSchema.EOF
Set ColumnsSchema = conn.OpenSchema(4, Array(Empty, Empty, "" & TablesSchema!TABLE_NAME))
Do While Not ColumnsSchema.EOF
If TablesSchema!TABLE_SCHEMA <> "$SYSTEM" Then
Debug.Print TablesSchema!TABLE_SCHEMA, TablesSchema!TABLE_NAME, ColumnsSchema!COLUMN_NAME
End If
ColumnsSchema.MoveNext
Loop
TablesSchema.MoveNext
Loop
End Sub
Function GetRecordSetFromConnection(TABLE_NAME)
'Requires that connection is added to data model.
'Watch out for table names with spaces in them - would need additional handling
'Use the ListConnectionTables function provided above to try to sniff out what to use for the TABLE_NAME, and additional trial and error may be needed
Set conn = GetModelADOConnection
Set rs = CreateObject("ADODB.RecordSet")
rs.Open "SELECT * From $" & TABLE_NAME & ".$" & TABLE_NAME, conn
Set GetRecordSetFromConnection = rs
End Function
If you succeed in getting your query into a recordset, then hopefully you know where to go from there. The simplest way to turn that into an array is with myRecordSet.GetRows(). That gives a transposed version of the table, but for help from there it will just require some Googling.
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.
i Have a table Tools where there are 15 yes/no fields. User checks which tools were used in an event. Could be one or more, or none. There are other fields in the table, but all the relevant field names start with tblTool
In report I'd like to display the tools in single line, Something like 'Tools used: hammer, chisel...'
My current solution for this is a bunch of if statements that check each item and add it to the variable if it's positive. My question is this, is there a simpler way? some kind of a loop that would check all the field names in a certain table that start with the same string?
might have solved this
txt = ""
Set db = CurrentDb()
Set rs1 = db.OpenRecordset("Select * from ops where opID = " & Me.opID)
Dim fld As DAO.Field
For Each fld In rs1.Fields
If Left(fld.Name, 5) = "opImp" Then
If fld = True Then
txt = txt & fld.Name
End If
End If
Next
Set fld = Nothing
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.
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