Access VBA: New tables created in a loop causing error - ms-access

I'm grabbing field row from one table and creating a new table for each row. The new tables will have names equal to the row they correspond to.
Here is my code:
Option Compare Database
Public Function createTables()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim rst As DAO.Recordset
Dim fld As DAO.Field
Dim strSQL As String
strSQL = "Select SKUS from SKUS"
Set db = CurrentDb()
Set rst = db.OpenRecordset(strSQL)
Set fld = rst.Fields("SKUS")
'MsgBox fld.Value
rst.MoveFirst
Do While Not rst.EOF
Set tdf = db.CreateTableDef(fld.Value)
Set fld = tdf.CreateField("SKUS", dbText, 30)
tdf.Fields.Append fld
Set fld = tdf.CreateField("Count", dbInteger)
tdf.Fields.Append fld
db.TableDefs.Append tdf
rst.MoveNext
Loop
End Function
The problem is that after the first iteration of the code (the first table is created), it gives me an error "Invalid operation" pointing to the line
...
Set tdf = db.CreateTableDef(fld.Value)
...
Why do you think this is? I have a feeling its because I need to re set fld or rst, but I'm not sure.
Can anyone help me out with this?
Thanks!

It doesn't seem like you're reading any new tuples from rst, thus the CreateTableDef will be called with the same value repeatedly. Try changing this:
[...]
Set fld = rst.Fields("SKUS")
rst.MoveFirst
Do While Not rst.EOF
Set tdf = db.CreateTableDef(fld.Value)
[...]
Into this:
[...]
rst.MoveFirst
Do While Not rst.EOF
Set fld = rst.Fields("SKUS")
Set tdf = db.CreateTableDef(fld.Value)
[...]
...if your intention is to create one table based on every tuple in the SKUS table.

Related

Load pictures into attachment data type with linked file names in access

So I have a table in access with file names I have been using as links in a form to view pictures. I would like to move these into an attachment database of photos so I can distribute the database to others without having to copy the file path names too.
I started some code to try it but not sure how to loop through the file paths because I have specific images I choose.
Here is an example of some of the data...so I would take the Tassel photo filepath and upload the picture to column PhotoT with datatype attachment.
EDIT:
I updated my code to get this to work. I added in a column import to the previous table. and added in seperate coding sections for each column. It works great! My database increased in size to 1.7gb. It was originally only 30mb with 60mb of pictures to update. Not sure where all the storage went too. The speed is a lot faster and its now self contained so thats great. If i had anymore picture i would have had to figure something else out haha
Option Compare Database
Option Explicit
Sub test()
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim rsA As DAO.Recordset
Dim fld As DAO.Field
Dim tdf As DAO.TableDef
Dim rstChild As Recordset2
Dim strsql As String
Dim noRows As String
Dim Tasselpath As String
'''''''''''''''''''''''''''''
'add columns to table
'''''''''''''''''''''''''''''
If DoesTblFieldExist("InbredPicPaths", "PE") = False Then
Set dbs = CurrentDb
Set tdf = dbs.TableDefs("InbredPicPaths")
Set fld = tdf.CreateField("PT", dbAttachment)
tdf.Fields.Append fld
Set fld = tdf.CreateField("PS", dbAttachment)
tdf.Fields.Append fld
Set fld = tdf.CreateField("PE", dbAttachment)
tdf.Fields.Append fld
Set fld = tdf.CreateField("PBR", dbAttachment)
tdf.Fields.Append fld
Set tdf = Nothing
End If
'''''''''''''''''''''''''''''
'Tassel
'''''''''''''''''''''''''''''
Set dbs = CurrentDb
strsql = "SELECT InbredPicPaths.* FROM InbredPicPaths WHERE (((InbredPicPaths.Tassel)<>''))"
Set rst = dbs.OpenRecordset(strsql)
'Set fld = rst("Tassel")
Set rstChild = rst.Fields("PT").Value
If rstChild.RecordCount <= 0 Then
'Navigate through the table
Do While Not rst.EOF
'Get the recordset for the Attachments field
Tasselpath = rst!Tassel
rst.Edit
Set rsA = rst.Fields("PT").Value
rsA.AddNew
rsA("FileData").LoadFromFile Tasselpath
rsA.Update
rsA.Close
rst.Update
'Next record
rst.MoveNext
Loop
End If
'''''''''''''''''''''''''''''
'silk
'''''''''''''''''''''''''''''
' Set dbs = CurrentDb
strsql = "SELECT InbredPicPaths.* FROM InbredPicPaths WHERE (((InbredPicPaths.Silk)<>''))"
Set rst = dbs.OpenRecordset(strsql)
'Set fld = rst("Silk")
Set rstChild = rst.Fields("PS").Value
If rstChild.RecordCount <= 0 Then
'Navigate through the table
Do While Not rst.EOF
'Get the recordset for the Attachments field
Tasselpath = rst!Silk
rst.Edit
Set rsA = rst.Fields("PS").Value
rsA.AddNew
rsA("FileData").LoadFromFile Tasselpath
rsA.Update
rsA.Close
rst.Update
'Next record
rst.MoveNext
Loop
End If
'''''''''''''''''''''''''''''
'Braceroot
'''''''''''''''''''''''''''''
'Set dbs = CurrentDb
strsql = "SELECT InbredPicPaths.* FROM InbredPicPaths WHERE (((InbredPicPaths.BraceRoot)<>''))"
Set rst = dbs.OpenRecordset(strsql)
'Set fld = rst("BraceRoot")
Set rstChild = rst.Fields("PBR").Value
If rstChild.RecordCount <= 0 Then
'Navigate through the table
Do While Not rst.EOF
'Get the recordset for the Attachments field
Tasselpath = rst!BraceRoot
rst.Edit
Set rsA = rst.Fields("PBR").Value
rsA.AddNew
rsA("FileData").LoadFromFile Tasselpath
rsA.Update
rsA.Close
rst.Update
'Next record
rst.MoveNext
Loop
End If
'''''''''''''''''''''''''''''
'Ear
'''''''''''''''''''''''''''''
'Set dbs = CurrentDb
strsql = "SELECT InbredPicPaths.* FROM InbredPicPaths WHERE (((InbredPicPaths.Ear)<>''))"
Set rst = dbs.OpenRecordset(strsql)
' Set fld = rst("Ear")
Set rstChild = rst.Fields("PE").Value
If rstChild.RecordCount <= 0 Then
'Navigate through the table
Do While Not rst.EOF
'Get the recordset for the Attachments field
Tasselpath = rst!Ear
rst.Edit
Set rsA = rst.Fields("PE").Value
rsA.AddNew
rsA("FileData").LoadFromFile Tasselpath
rsA.Update
rsA.Close
rst.Update
'Next record
rst.MoveNext
Loop
End If
rst.Close
Set rst = Nothing
Set rsA = Nothing
Set dbs = Nothing
Set rstChild = Nothing
End Sub
So from the picture it looks like you need to iterate through the rows of a table with a column containing the url of a file and then attach that file to an attachment type column in the same file. Assuming:
Here is code that does that.
Public Sub MovethroughTableAttachingPhotos(TableName As String, urlColumnName As String, attachmenttypeColumnName As String)
'adapted from https://learn.microsoft.com/en-us/office/vba/access/concepts/data-access-objects/work-with-attachments-in-dao
Dim db As Database
Set db = CurrentDb
Dim rsTable As Recordset
Dim rsPhotos As Recordset
Set rsTable = db.OpenRecordset(TableName)
rsTable.MoveFirst 'avoids an error
Dim currentURL As String
Do Until rsTable.EOF
currentURL = rsTable(urlColumnName)
rsTable.Edit
Set rsPhotos = rsTable.Fields(attachmenttypeColumnName).value
rsPhotos.AddNew
rsPhotos.Fields("FileData").LoadFromFile (currentURL)
rsPhotos.Update
rsPhotos.Close 'placing here avoids an error
rsTable.Update
rsTable.MoveNext
Loop
'clean up
rsTable.Close
Set rsPhotos = Nothing
Set rsTable = Nothing
Set db = Nothing
End Sub
'to call the subroutine : MovethroughTableAttachingPhotos "Photos", "PhotoAddress", "PhotoAttachment"

How to cycle through record set and update table field values based on record set?

I am importing similar tables into a MS Access database to combine them into a larger data set. The first row of most of the columns are date fields. During import when the first row becomes field names, some of these dates stay dates "January-2018" and some of them become numbers "44001". I am writing a code to reference any numbers that are store as the field names and turn them into date values (ex. 44001 to January-2018).
Private Sub Command0_Click()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim rs As DAO.Recordset
Dim CurrentHead As String
Dim UpdateHead As String
Set db = CurrentDb
Set tdf = db.TableDefs("PL_1")
Set rs = db.OpenRecordset("TableUpdates")
rs.MoveFirst
Do While Not rs.EOF
For Each fld In tdf
If fld.Name = CurrentHead Then
fld.Name = UpdateHead
End If
rs.MoveNext
Loop
db.Close
Set db = Nothing
Set fld = Nothing
Set tdf = Nothing
MsgBox "Changed"
End Sub

ms access for each field

I am trying to set all Nulls in a table (tblIdea) to NS but the following code throws an 'Object Required' error and highlights the line starting with 'If.'
Sub CommitNS()
Dim db As dao.Database
Dim tdf As dao.TableDef
Dim fld As dao.Field
Set db = CurrentDb
Set tdf = db.TableDefs("tblIdea")
For Each fld In tdf.Fields
If fld Is Null Then
fld = "NS"
End If
Next fld
Set tdf = Nothing
Set db = Nothing
End Sub
You miss the actual update:
Sub CommitNS()
Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim fld As DAO.Field
Dim Update As Boolean
Set db = CurrentDb
Set rst = db.OpenRecordset("Select * From tblIdea")
While Not rst.EOF
For Each fld In rst.Fields
If IsNull(fld.Value) Then
Update = True
Exit For
End If
Next
If Update = True Then
' Record needs update.
rst.Edit
For Each fld In rst.Fields
If IsNull(fld.Value) Then
fld.Value = "NS"
End If
Next
rst.Update
Update = False
End If
rst.MoveNext
Wend
rst.Close
Set fld = Nothing
Set rst = nothing
Set db = Nothing
End Sub

Change all values in a field in a MS Access database to a constant

I have a MS Access database with 100 tables, each has a field named "M_ID"
I want all the values in the field named "M_ID" in each table to be set to a constant, for example "1"
how can I do that using VBA?
You can loop through each table and run an update statement with docmd.ExecuteSQL. Like this:
Option Explicit
Option Compare Database
Sub ClearAllFields()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim fdf As DAO.Field
Set db = CurrentDb
DoCmd.SetWarnings False
For Each tdf In db.TableDefs
If Not (tdf.Name Like "MSys*" Or tdf.Name Like "~*") Then
For Each fdf In tdf.Fields
If fdf.Name = "M_ID" Then DoCmd.RunSQL "update " + tdf.Name + " set M_ID = 1"
Next
End If
Next
Set tdf = Nothing
Set db = Nothing
DoCmd.SetWarnings True
End Sub

How do you overwrite a table created in VBA?

I'm creating a table in VBA within a loop and when I run the code a table is created.
But the next time I run it, an error comes up telling me that the table exists and the remainder of the code is not executed.
How can I have it overwrite the existing table (from the previous run)?
Here is my code:
Option Compare Database
Public Function createTables()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim rst As DAO.Recordset
Dim fld As DAO.Field
Dim strSQL As String
strSQL = "Select SKUS from SKUS"
Set db = CurrentDb()
Set rst = db.OpenRecordset(strSQL)
Set fld = rst.Fields("SKUS")
'MsgBox fld.Value
rst.MoveFirst
Do While Not rst.EOF
Set tdf = db.CreateTableDef(fld.Value)
Set fld = tdf.CreateField("SKUS", dbText, 30)
tdf.Fields.Append fld
Set fld = tdf.CreateField("Count", dbInteger)
tdf.Fields.Append fld
db.TableDefs.Append tdf
rst.MoveNext
Loop
End Function
Can anyone help me out please?
Thanks!
I would simply delete the table before attempting to recreate it:
db.TableDefs.Delete fld.Value
You can check if the table exists with the following function.
Public Function TableExists(TabName As String) As Boolean
Dim db As DAO.Database
Dim Sdummy As String
Set db = CurrentDb()
On Error Resume Next
Sdummy = db.TableDefs(TabName).Name
TableExists = (Err.Number = 0)
End Function
If the function returns true, then issue following sql statement:
DROP TABLE SKUS
The usual method is to test then delete temp table, requiring more code and recordkeeping for calling procedures that run multiple maketables.
Here is a procedure that is all inclusive, gleaning the source table name from maketable, then deleting before recreating. Also returns number of new records.
Public Function fcnMakeTableForce(strMTQuery As String) As Integer
On Error GoTo ErrorExit
'Runs maketable, deleting the resulting temp table contained in the query (if it
'exists) beforehand. Also returns the number of records in new temp table
Dim dbs As Database
Dim strSQL As String
Set dbs = CurrentDb
'Get SQL from MakeTable
strSQL = dbs.QueryDefs(strMTQuery).sql
'Get target table from SQL:
intINTOPos = InStr(strSQL, "INTO [") + 5
intFROMPos = InStr(strSQL, "FROM [") - 3
strTargetTable = Mid(strSQL, intINTOPos + 1, intFROMPos - intINTOPos - 1)
'Clear target table if it exists
If (DCount("*", "MSysObjects", "[Name] = """ & strTargetTable & """")) > 0 Then
CurrentDb.TableDefs.Delete (strTargetTable)
End If
dbs.Execute strMTQuery
intRecordsAdded = DCount("*", strTargetTable)
fcnMakeTableForce = intRecordsAdded
NormalExit:
Exit Function
ErrorExit:
MsgBox "Error: " & Err.Description & vbCr & vbCr & "in Function: fcnMakeTableForce"
Resume NormalExit
End Function