+ Reply to Thread
Results 1 to 3 of 3

Thread: VBA Hangs While Copying to Access DB using ADO

  1. #1
    Registered User
    Join Date
    05-05-2011
    Location
    Houston, TX
    MS-Off Ver
    Excel 2010
    Posts
    2

    VBA Hangs While Copying to Access DB using ADO

    Hello,

    I'm trying to import data from Excel into an Access 2007 DB using ADO. Sometimes the data will create a new record, other times it will be updating an existing record, based on a unique ID to each row in Excel. When updating, it proceeds quickly. However, when adding, as the database has grown larger in size, the code hangs up specifically on the .AddNew command in section (c) below.

    Here is the code -- can anyone help me figure out a solution that speeds it up?

    Thanks,
    Michael

    
    Public Sub run()
    
        StoreDataAccess "A", ThisWorkbook.Path & "\rawdata.accdb", "RawData, RawData2, CalcData"
    
    End Sub
    
    Public Sub StoreDataAccess(SourceFilePrefix As String, TargetFile As Variant, TargetSheet As String)
    
    ' ==================================================================================
    '
    ' All necessary variables to store data
    '
        Dim cn As ADODB.Connection  'Will not work without reference to Microsoft ActiveX Data Objects
        Dim rs As ADODB.Recordset   'Will not work without reference to Microsoft ActiveX Data Objects
        Dim szConnect As String, szSQL As String, SrcIDSQL As String
        Dim lDB_RecCount As Long, SrcRecordsCount As Long, SrcRow As Long, SourceID As Long, dTempVal As Double
        
        Dim xlCalc As XlCalculation
        Dim i As Integer, j As Integer
        Dim bUpdate As Boolean
        
    '   Change settings to improve performance
    '
        With Application
            xlCalc = .Calculation
            .Calculation = xlCalculationManual
            .EnableEvents = False
            .ScreenUpdating = False
        End With
    
    ' ==================================================================================
    '
    '   Identify how many records need to be copied from external DataSheet
    '
        Select Case SourceFilePrefix                                            'Set the ActiveCell
            Case "A"
                Range("A2").Activate
                SrcIDSQL = "Src1"
            Case "B"
                Range("A12").Activate
                SrcIDSQL = "Src2"
        End Select
        
        SrcRecordsCount = Range(ActiveCell, ActiveCell.End(xlDown)).Count       'Count the number of records
    
    ' ==================================================================================
    '
    '   Create the connection string to DataSheet, connect, count number of existing records
    '
    '
        szConnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                    "Data Source=" & TargetFile & "; Mode=Share Deny None;"
    
        Set cn = CreateObject("ADODB.Connection")
        cn.Open szConnect
        
        Set rs = CreateObject("ADODB.Recordset")
        szSQL = "SELECT Count(RawData.ID) AS CountOfID FROM RawData"
        rs.Open szSQL, cn, adOpenForwardOnly
        If Not rs.EOF Then lDB_RecCount = rs.Fields(0).Value
        rs.Close
        
    ' ==================================================================================
    '
    '   We cycle through the Datasheet in a couple steps
    '   a) First, initialize settings for each source record
    '   b) Next, we check to see if the source ID already exists in the database
    '   c) Finally, we either add or update, depending on the results of steps (b) 
    '
        For SrcRow = 0 To SrcRecordsCount - 1
            
        ' ==========================================================================
        ' (a)
        '
        '   Initialize the recordset / reset the AddOrUpdate flag / identify the Source's unique ID
        '
            Set rs = Nothing
            Set rs = CreateObject("ADODB.Recordset")
            bUpdate = False
            SourceID = ActiveCell.Offset(SrcRow, 0).Value
            
        ' ==========================================================================
        ' (b)
        '
        '   We create a SQL string, to check if the SourceID exists in the database;
        '   if exists, then we set the AddOrUpdate flag
        '
            szSQL = "Select " & SrcIDSQL & " from " & TargetSheet & " where " & SrcIDSQL & " = " & SourceID
            rs.Open szSQL, cn, adOpenStatic
            If rs.RecordCount > 0 Then bUpdate = True
            rs.Close
            
            Set rs = Nothing
            Set rs = CreateObject("ADODB.Recordset")
            
            
        ' ==========================================================================
        ' (c)
        '
        '   Based on the results of (b), we set the Field values, and then add
        '   or update records in the database accordingly
        '
            With rs
                If bUpdate = True Then
                    szSQL = "select * from " & TargetSheet & " where " & SrcIDSQL & " = " & SourceID
                    .Open szSQL, cn, adOpenKeyset, adLockOptimistic
                Else
                    szSQL = "Select * from " & TargetSheet
                    .Open szSQL, cn, adOpenDynamic, adLockOptimistic
               ' THE NEXT LINE IS WHERE THE PROGRAM HANGS
                    .AddNew
               End If
                
                Select Case SourceFilePrefix
                
                ' ===================================================================
                ' (d) First case, A imported data
                '
                    Case "A"
    
                    ' Add a bunch of values
                        .Fields("Field1").Value = ActiveCell.Offset(SrcRow, 1)
                        .Fields("Field2").Value = ActiveCell.Offset(SrcRow, 2)
                    '   etc
                
                ' ===================================================================
                ' (e) Second case, B imported data
                '
                    Case "B"
                        
                    ' Add a bunch of values
                        .Fields("Field1").Value = ActiveCell.Offset(SrcRow, 1)
                        .Fields("Field2").Value = ActiveCell.Offset(SrcRow, 2)
                    '   etc
        
                End Select
                
                ' ===================================================================
                ' (h) Finally, we need to set the Foreign Key value, for new records
                '
                ' Because our database has > 255 fields, we have to split our records across multiple
                ' tables; as a result, we need to set the Primary Key of our main table, RawData, as
                ' the Foreign Key of all other related tables in the database
                '
                
                If bUpdate = False Then
                    .Fields("RawData2.ID") = .Fields("RawData.ID").Value
                    .Fields("CalcData.ID") = .Fields("RawData.ID").Value
                End If
                
                .Update
                .Close
                
            End With
        Next SrcRow
        
        
    ' ==================================================================================
    '
    '   Finally, we wrap up and restore all of our settings
    '
        Set rs = Nothing
        cn.Close
        Set cn = Nothing
        With Application
            .Calculation = xlCalc
            .EnableEvents = True
            .ScreenUpdating = True
        End With
        
    End Sub
    Last edited by ribbon; 06-10-2011 at 11:29 AM.

  2. #2
    Forum Contributor
    Join Date
    07-13-2007
    Posts
    151

    Re: VBA Hangs While Copying to Access DB using ADO

    I'm certainly not an expert in this area, but am trying to learn these techniques myself so I read your post.

    The thing that jumps out at me is that when the record already exists, you are opening a recordset that contains just that record (efficient), whereas when its a new record, you open a recordset that contains the entire table. As your DB grows, this will inevitably cause performance issues. This might explain why it continues to work well on updating existing records but is becoming increasing slow when adding new records.

    Instead of opening a recordset of the whole table, and then using the .addnew method, as an alternative have you tried creating and UPDATE query SQL string and then executing the query against the table to add the record to the Table(s)?

  3. #3
    Registered User
    Join Date
    05-05-2011
    Location
    Houston, TX
    MS-Off Ver
    Excel 2010
    Posts
    2

    Re: VBA Hangs While Copying to Access DB using ADO

    I've thought about it -- but the record I'm adding (in some cases) contains hundreds of fields, which would make for a very long, very complicated (and unreadable) SQL statement. So I was hoping there was a solution that would not require me to do that.

    Any other thoughts?

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.2.0