How to move Excel data to Access using VBA and late binding (no ADO, no DAO) - DoCmd.TransferSpreadsheet runtime error 424?

StackOverflow https://stackoverflow.com/questions/12164924

Question

I am trying to create a macro that will regularly move 25,000 - 35,000 lines in Excel, to an Access database. As I understand it, if I'm working in an environment where people using the macro have different versions of Excel and Access (I happen to be using 2007), I'm best off using late binding, because it avoids problems with different references and versions,etc. - once it works, it works (even though it's slower).

I'm trying to get the following code to work in Excel VBA:

Sub TransferToDB()
Dim acApp As Object

ssheet = "C:\Documents and Settings\yk\Desktop\Open Invoice Summary 322 - 2012-07-17.xlsx"
ssrange = "AllData!A1:M28323"

Set acApp = CreateObject("Access.Application")
    acApp.OpenCurrentDatabase ("C:\Documents and Settings\yk\Desktop\Open Invoice Summary.accdb")
    acApp.Visible = True
    acApp.UserControl = True
    DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, OpenInvoices, ssheet, True, ssrange
    acApp.CloseCurrentDatabase
    acApp.Quit
Set acApp = Nothing


End Sub

When the macro gets to the DoCmd.TransferSpreadsheet line, it stops with an error:

Runtime error 424:

Object required

This routine in Excel gets called from another routine that gathers information from many worksheets in a large workbook, and dumps it all in a sheet called "AllData" in that workbook. I keep seeing references online to this DoCmd.TransferSpreadsheet method, but I can't seem to find any cut-and-paste code that works...

  1. Why does the routine keep crashing at that point?
  2. Is it even possible to transfer date from Excel to Access without using ADO or DAO?
  3. Is it true that late binding prevents problems, or is it better to use ADO?

Thanks - your help is much appreciated!

Was it helpful?

Solution

This feels a little obvious, but I believe the actual cause of your error message is this:

DoCmd is an object. Here's an exert from the help file Application.DoCmd Property

You can use the DoCmd property to access the read-only DoCmd object and its related methods. Read-only DoCmd. Syntax

expression.DoCmd

expression A variable that represents an Application object.

In other words, you need to use acApp.DoCmd instead of just DoCmd. Otherwise, your code has no way of knowing what DoCmd means because it is not part of Excel.

I'll chime in on the other questions now as well.

  1. I'm sure it is, though I don't know how Docmd.TransferSpreadSheet is implemented and it may use DAO or ADO without user involvement.

  2. Late binding is often necessary if you are implementing any solution with VBA that uses different Office applications than the one being used IF you have a newer version of Office than any of your users. In my experience, early binding works fine for upgrading from 2003 to 2010, but once you've made the change you can't go back. Any updates to a legacy VBA will automatically update the references to the current references and destroy version compatibility. So if you use early binding and update before your users, you'll need to switch to late-binding or stop supporting your system.

OTHER TIPS

Without a reference set for the Access type library, Excel doesn't know about the Access named constants, acImport and acSpreadsheetTypeExcel9. Use those constants' values instead of their names for the TransferSpreadsheet method.

If OpenInvoices is the literal Access table name, add quotes. But if OpenInvoices is the name of a variable which holds the name of the Access table, you don't need the quotes.

DoCmd.TransferSpreadsheet 0, 8, "OpenInvoices", ssheet, True, ssrange

So to answer the 3 parts of your question:

  1. I suspect it crashed without quotes around OpenInvoices because Excel found no variable named OpenInvoices, so tried to give TransferSpreadsheet nothing as the table name.
  2. Yes, sort of. I think your TransferSpreadsheet approach should work with the revisions suggested in these answers. However, I also think TransferSpreadsheet uses DAO.
  3. Late binding can prevent certain types of problems. But you must then use values for the respective constants instead of their names, or redefine them as constants in your procedure. Late binding vs. ADO is a confusing question to me. It's not an either/or thing ... when I use ADO, I almost always use late binding with it to avoid deployment problems due to early binding with a specific ADO version.

Table name should be a string.

acSpreadsheetTypeExcel9 = 8
acImport = 0
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, _
    "OpenInvoices", ssheet, True, ssrange
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top