John,
Thanks. What I thought was a solution turned out to be false. The column names were listed alphabetical instead of in the order they appear in the table to so the data was going to the wrong fields :-(. I've cobbled together a partial work around, the only requirement is that there be at least one record defined in the database. Before I post that code and ask a different question, I'll try to address your comments.
I am writing the code in Word, because that is what I know and the final product will be a Word template add-in. I don't know how to write code in Access or know if there is such a thing as a Access template Add-in. I don' t know how to create Com addins and I don't want to learn at this point.
Here is the code that is working best so far. It has one unresolved issue.
The Access data base has two tables "Table1" and "Table2" Table1 has four fields, the default "ID" autonumber fields, and three shorttext fields Field1, Field2 and Field3. Table2 has three shorttext fields Field1, Field2 and Field3 (I deleted the default ID field).
Both databases have 0 records
When I run Sub Demo, the attempt to write data to Table1 errors because there 1) The number of query items does not match the number of fields in the database and, 2) there is no record to parse for column names. The attempt to write data to Table2 is successful
If I manually add a record to Table1 and run Sub Demo again then data is written to both tables as expected.
The remaining question is: Is there a way to determine the column names of a table "in the order they appear in the table" if the database is empty (contains 0 records)? All of the other methods I've found return the column names in alphabetical order.
Option Explicit
Const strDBFile As String = "D:\Demo Database.accdb"
Sub Demo()
DemoWriteToDB "Table1"
DemoWriteToDB "Table2"
End Sub
Sub DemoWriteToDB(strTableName As String)
Dim oConnection As Object
Dim strConnection As String
Dim arrData(2) As String
Dim rsRecords As ADODB.Recordset, rsColumns As ADODB.Recordset
Dim lngINdex As Long, lngColumns As Long
Dim strColumnNames As String, strSQL As String
arrData(0) = "111"
arrData(1) = "222"
arrData(2) = "333"
strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strDBFile & ";"
Set oConnection = New ADODB.Connection
With oConnection
On Error GoTo Err_Connect
.Open strConnection
Set rsRecords = CreateObject("ADODB.Recordset")
rsRecords.Open "SELECT * From " & strTableName & ";", oConnection, adOpenStatic
'Create columns record set.
Set rsColumns = .OpenSchema(adSchemaColumns, Array(Empty, Empty, "" & strTableName))
'Get columns count.
lngColumns = 0
Do While Not rsColumns.EOF
lngColumns = lngColumns + 1
rsColumns.MoveNext
Loop
'It appears that the only way to get the column names in the order that appear in the table _
is to use the fields name property. This requires there to be at least one record.
If rsRecords.RecordCount > 0 Then
rsRecords.MoveFirst
'If the number of columns in the table don't match the number of data elements in the data array then _
then we have to write to target columns by name:
If Not UBound(arrData) + 1 = lngColumns Then
'Get the column names.
strColumnNames = ""
rsRecords.MoveFirst
For lngINdex = 0 To lngColumns - 1
strColumnNames = strColumnNames & ", " & rsRecords.Fields(lngINdex).Name
Next
'If an autonumber "ID" column exists, we need to strip it out.
strColumnNames = Replace(strColumnNames, ", ID", "")
If Left(strColumnNames, 2) = ", " Then
strColumnNames = Mid(strColumnNames, 3, Len(strColumnNames) - 2)
End If
End If
End If
rsRecords.Close
rsColumns.Close
End With
strSQL = fcnGetStrSQL(strTableName, arrData, strColumnNames)
oConnection.Execute strSQL
lbl_Exit:
Set oConnection = Nothing
Set rsRecords = Nothing
Set rsColumns = Nothing
Exit Sub
Err_Connect:
Select Case Err.Number
Case -2147467259
MsgBox "The number of data elements in the extracted data do not match the number of fields in the data base." & vbCr + vbCr _
& "This is often the result of the default ""ID"" autonumber field in an Access database." & vbCr + vbCr _
& "This condition cannot be resolved because there are no records in the database to evaluate." & vbCr + vbCr _
& "To resolve this issue, you can manually define the first record in your database and try again."
Case Else
MsgBox Err.Number & " " & Err.Description
End Select
Resume lbl_Exit
End Sub
Function fcnGetStrSQL(strTableName As String, varData, strHeadings) As String
Dim strField_Values As String
Dim strData As String
Dim lngINdex As Long
'Initialize SQL statement variable values.
strField_Values = ""
For lngINdex = 0 To UBound(varData)
'Get field data
strData = varData(lngINdex)
'Build SQL statement.
Select Case lngINdex
Case Is = UBound(varData)
strField_Values = strField_Values & "'" & strData & "'"
Case Else
strField_Values = strField_Values & "'" & strData & "'" & ", "
End Select
Next lngINdex
If Not strHeadings = vbNullString Then
fcnGetStrSQL = "INSERT INTO " & strTableName & " (" & strHeadings & ") VALUES (" & strField_Values & ")"
Else
fcnGetStrSQL = "INSERT INTO " & strTableName & " VALUES (" & strField_Values & ")"
End If
Cleanup:
lbl_Exit:
Exit Function
End Function