2

So I navigated to the following MSDN Resource Page that addresses how to use ADO objects. My problem is that I cannot get it to work.

What I am trying to do is open a CSV file and read it line-by-line, then create SQL INSERT statements to insert the records into an existing Table in Access 2010. I have tried to find an easier method of doing this, but this appears to be my only option. doing this with the included tools, but so far, I haven't had any luck.

The main issue here is that I have CSV files with inconsistent headings. I want to import 5 files into the same table, but each file will be different depending on which fields contained data. Those fields with no data in them were ignored during the extract. This is why I can't use something like DoCmd.TransferText.

So, now I need to create a script that will open the text file, read the headers in the first line and create a SQL INSERT statement dependent on the configuration of that particular file.

I have a feeling that I have a good handle on how to appraoch the issue, but no matter what I try, I can't seem to get things working using ADO.

Could anyone explain how I can achieve this? My sticking point is getting the Access DB to receive information from the CSV files via ADO.

toolshed
  • 1,919
  • 9
  • 38
  • 50
  • Your approach seem correct. Post what you have so far (section that is failing) and the community should be able to help you better. – Pynner May 09 '12 at 05:45

2 Answers2

3

Instead of reading the CSV file line-by-line, then doing something with each line, I think you should open the file as an ADO recordset. And open a DAO recordset for your Access destination table.

You can then iterate through the fields in each row of the ADO recordset and add their values into a new row of the DAO recordset. As long as the destination table includes fields with the same names and compatible data types as the CSV fields, this can be fairly smooth.

Public Sub Addikt()
#If ProjectStatus = "DEV" Then
    ' needs reference for Microsoft ActiveX Data Objects
    Dim cn As ADODB.Connection
    Dim fld As ADODB.Field
    Dim rs As ADODB.Recordset
    Set cn = New ADODB.Connection
    Set rs = New ADODB.Recordset
#Else ' assume PROD
    Const adCmdText As Long = 1
    Const adLockReadOnly As Long = 1
    Const adOpenForwardOnly As Long = 0
    Dim cn As Object
    Dim fld As Object
    Dim rs As Object
    Set cn = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")
#End If
    Const cstrDestination As String = "tblMaster"
    Const cstrFile As String = "temp.csv"
    Const cstrFolder As String = "C:\share\Access"
    Dim db As DAO.Database
    Dim rsDao As DAO.Recordset
    Dim strConnectionString As String
    Dim strName As String
    Dim strSelect As String

    strConnectionString = "Provider=" & _
        CurrentProject.Connection.Provider & _
        ";Data Source=" & cstrFolder & Chr(92) & _
        ";Extended Properties='text;HDR=YES;FMT=Delimited'"
    'Debug.Print strConnectionString
    cn.Open strConnectionString

    strSelect = "SELECT * FROM " & cstrFile
    rs.Open strSelect, cn, adOpenForwardOnly, _
        adLockReadOnly, adCmdText

    Set db = CurrentDb
    Set rsDao = db.OpenRecordset(cstrDestination, _
        dbOpenTable, dbAppendOnly + dbFailOnError)

    Do While Not rs.EOF
        rsDao.AddNew
        For Each fld In rs.Fields
            strName = fld.Name
            rsDao.Fields(strName) = rs.Fields(strName).value
        Next fld
        rsDao.Update
        rs.MoveNext
    Loop

    rsDao.Close
    Set rsDao = Nothing
    Set db = Nothing
    rs.Close
    Set rs = Nothing
    cn.Close
    Set cn = Nothing
End Sub

This is the Declarations section of the module where I saved that procedure:

Option Compare Database
Option Explicit
#Const ProjectStatus = "DEV" '"DEV" or "PROD"

Change the values for these constants to test it on your system:

Const cstrDestination As String = "tblMaster"
Const cstrFile As String = "temp.csv"
Const cstrFolder As String = "C:\share\Access"

Note the folder name does not include a trailing backslash.

You will want to adapt that procedure to pass the file name as a parameter instead of leaving it as a constant. And, if your CSV files are stored in more than one directory, you will want to pass the folder name as a parameter, too.

Hopefully showing you how to do it for one file will be enough and you can then take it from here to handle all your CSV files. Also consider adding error handling.

HansUp
  • 95,961
  • 11
  • 77
  • 135
  • Quick question about this method. Why are you using both ADO and DAO? Can you not create two ADO connections? Or does DAO have a more robust feature-set for MS programs? I'll try this later tonight. If I can get it to work for one file, I have a script I can use to iterate all folders/files already that I'll just call the working function from. I'll let you know how things pan out, and thanks for the help! – toolshed May 09 '12 at 11:27
  • 1
    DAO can be considerably faster than ADO for data stored in Jet/ACE. – HansUp May 09 '12 at 11:37
  • One more question for you. What's up with the If statement at the top? – toolshed May 10 '12 at 00:55
  • Those are conditional compile directives. With that code in a module, place your cursor on `#If`, then press F1 to read the help topic details. Basically I wanted to show you how ADO can be used with early binding (under DEV block) or late binding (under PROD) block. I use `#Const ProjectStatus` to switch between them. Early binding is convenient during development, but requires a reference. I switch to late binding for production and remove the reference. – HansUp May 10 '12 at 01:03
0

I think the previous answer is unnecessarily complicated. All you need to do it send an XMLHTTP request. That fetches the CSV data as a string, which can then be parsed into a table.

I've posted a VBA subroutine that does that in an answer to a similar question. Documentation of where I found the techniques is in the code comments. I've run it in Access 2019, and it works.

NewSites
  • 1,402
  • 2
  • 11
  • 26