What's the "best" way to read (just read) an Excel file from within an Access 2007 application. I only want to loop trough the rows and put the data into an Access table.
I don't want a manually import (Get External Data dialog) but by VBA. The user gets a Form with a Browse button and then points to a Excel file with a defined content/format. After that the VBA code reads the data and puts it into the Access database.
You could try the DoCmd.TransferSpreadsheet method.
DoCmd.TransferSpreadsheet acImport, , "from_excel","C:\Access\demo.xls", True
That imports spreadsheet data into a table named from_excel, and assumes the first row of the spreadsheet contains field names. See Access help for TransferSpreadsheet or online here, for more details.
If you want to read the entire spreadsheet in, you can import an Excel spreadsheet directly into Access. See here or here.
You can also choose to link to the Excel spreadsheet instead of importing it. That way any changes to the Excel spreadsheet will be reflected in the linked table. However, you won't be able to make changes from within Access.
A third option is to write some VBA code within Access to open a recordset and read the spreadsheet in. See the answers from KeithG in this thread. You can do something like this to open the spreadsheet in VBA:
Dim xl As Excel.Application
Dim xlsht As Excel.Worksheet
Dim xlWrkBk As Excel.Workbook
Set xl = CreateObject("Excel.Application")
Set xlWrkBk = GetObject("H:/ggg.xls")
Set xlsht = xlWrkBk.Worksheets(1)
Try something like this:
Dim excelApp As Excel.Application
Dim workbook As Excel.Workbook
Dim worksheet As Excel.Worksheet
Set excelApp = CreateObject("Excel.application")
Set workbook = excelApp.Open("C:\someFileName.xls")
Set worksheet = workbook.Worksheets(1)
And then loop through the rows and columns, pull the data from the cells, and insert it into the database. (You can use the worksheet.cells method.) Try searching on google for code samples.
Hereafter my method to read an excel file and all the worksheet names:
Function listOfWorksheet(filename As String) As Collection
Set dbExcel = OpenDatabase(filename, False, True, "excel 8.0")
For Each TableDef In dbExcel.TableDefs
Debug.Print TableDef.Name
Next
End Function
Now, you can use the name of the worksheet to read the whole content:
Function ReadMyObjects(filename as String, wsName as String) As Collection
On Error GoTo label_error
Set results = New Collection
Dim countRows As Integer
Set dbExcel = OpenDatabase(filename, False, True, "excel 8.0")
Set excelRs = dbExcel.OpenRecordset(wsName, dbOpenSnapshot)
Do While Not excelRs.EOF
'Data Rows
Dim item As MyObject 'a custom object defined by you.
Set item = New MyObject
item.ABC = Nz(excelRs.Fields("COLUMN_ABC").Value, "")
item.DEF = Nz(excelRs.Fields("COLUMN_DEF").Value, "")
results.Add item
excelRs.MoveNext
Loop
excelRs.Close
Set ReadMyObjects= results
GoTo label_exit
label_error:
MsgBox "ReadMyObjects" & Err.Number & " " & Err.Description
label_exit:
End Function
Related
Here's one that's been bugging me for about a month...
I have a form that allows users to filter records, simple enough. But I want to give them the option to export the filtered records to Excel. I don't want to use the docmd.outputTo due to it won't filter the records, it puts all of the records in the file. I've looked around and found some code, but the problem is that it outputs EVERYTHING on the form. My goal is to output the filtered data into a new excel sheet. But I am still very new and struggling with the code. I am attaching the image for the error (Below) and the code
thanks for the help
enter image description here
Private Sub cmdExport_Click()
Dim xlApp As Object
Dim xlBook As Object
Dim rs As DAO.Recordset
Dim sql As String
Dim i As Integer
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Add
'This selects form
sql = Forms("ReportForm13").Form.RecordSource 'Your record source if not a subform
'Set rs = CurrentDb
For i = 1 To rs.Fields.Count
xlBook.Sheets(1).Cells(1, i) = rs.Fields(i - 1).Name 'Write Field names to Excel
Next i
xlBook.Sheets(1).Cells(2, 1).CopyFromRecordset rs 'Import the recordset data through Excel
' You can add whatever other formatting you want by running Excel VBA throught the xlApp object
xlApp.Visible = True
Set xlApp = Nothing
Set xlBook = Nothing
Set rs = Nothing
End Sub
You can use the filter in form as criteria in query and can instead export that query into excel. It will just export filtered records.
Yeah, exactly. It's basically what Hira Iftikhar said, and it looks like this.
Private Sub cboFilterIsCorporate_Click()
Dim strSQL As String
strSQL = Me.RecordSource
strSQL = "Select * From " & strSQL & " WHERE " & Me.Filter
With CurrentDb.QueryDefs("qryTest")
.SQL = strSQL
End With
' now export the query with critera to excel
Dim strOutFile As String
strOutFile = "C:\your_path\Test.xlsx"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, _
"qryTest", strOutFile, True
End Sub
Access View:
Excel Before:
Excel After:
click the form > add a button > click the button and click 'ok' then click 'cancel' > right-click the button and click 'Build Event' > click 'Code Builder' > finally...paste the code that I gave you into the Window that opens. Make a few very minor changes (should be obvious...the name of the click event). Now, you should be good to go!! Post back if you have additional questions!! Otherwise, please update my answer to acknowledge that this is helpful to others. Thanks!!
I am currently trying to use an access database which uses vba to generate Excel spreadsheets and AutoCAD drawings; I didn't write the code, and I don't have experience coding in this language. When generating an excel file, the code gets to the line MyXL.Parent.Windows(1).Visible = True, it gives the error. The excel file is generated, but is identical to the template.
The File and directory names are placeholders
Dim MyXL As Object
FileCopy "\Directory\Template", "\Directory\Filename"
' This copies an Excel file, first half, then renames it with the Sales order number
Set MyXL = GetObject("\Directory\Template")
' This opens the Excel file named in the upper code second half
MyXL.Application.Visible = True
MyXL.Application.WindowState = 3
' MyXL1.Activate
MyXL.Parent.Windows(1).Visible = True
MyXL.Parent.ActiveWindow.WindowState = 2
With MyXL.Worksheets(1)
End With
At this point it sets a lot of values (I assume) in the form .Range("T60").Value = Me![Text516]
MyXL.Worksheets(1).Activate
MyXL.Save
MyXL.Parent.Quit ' This is what you have to do to close the Application
'MyXL.Parent.Quit
' MyXL.Parent.ActiveWindow.WindowState = xlMinimized
' MyXL.Close
The possible duplicate relates to copying an excel spreadsheet, however this problem goes further than that
Edit: I made a mistake and previously had the line Set MyXL = GetObject("\SameDirectory\SameFilename") but it is actually Set MyXL = GetObject("\Directory\Template")
Example of working code to open an Excel workbook, edit, save to a new name.
Sub CopyExcel()
Dim xl As Excel.Application, xlw As Excel.Workbook
Set xl = CreateObject("Excel.Application")
'the following two lines have same result
Set xlw = xl.Workbooks.Open("C:\Users\June\MyStuff\Condos.xlsx", , True)
'Set xlw1 = xl.Workbooks.Add("C:\Users\June\MyStuff\Condos.xlsx")
'code to edit
xlw.SaveAs "C:\Users\June\MyStuff\Condos2.xlsx"
xl.Quit
End Sub
So i am using Opendateabase method in Ms Access to read the worksheet of a Excel workbook. Why do i get multiple entries for worksheets when I can only see one excel worksheet when i open the file.
So the system used to just import the excel workbook without checking the column names which meant after waiting 5-10mins of importing if the user didnt name his columns correctly the program would crash. I want this to check the column names before it imports which means VBA needs to know the name of the worksheet its importing.
Set db = OpenDatabase(Me.Text2.Value, True, False, "Excel 8.0")
For Each tbl In db.TableDefs
MsgBox tbl.Name 'Would be where the sheet name is picked
Next
db.Close
Set rstbl = CurrentDb.OpenRecordset("SELECT * FROM ImportColumnNames")
S = "SELECT * FROM [Excel 8.0;HDR=Yes;Database=" _
& Me.Text2 & "].[" & SheetName & "$] WHERE False;"
Now seeing as the file only has one worksheet called CLENAS i was expecting 1 answer however i got Sheet1$, CLENAS, CLENAS$ now i know it should be CLENAS but how do i make sure that VBA picks the right one.
Found the answer here: Read Excel file sheet names
Dim objExc As Object ' late
Dim objWbk As Object ' late
Dim objWsh As Object ' late
'Set objExc = New Excel.Application ' early
Set objExc = CreateObject("Excel.Application") ' late
Set objWbk = objExc.Workbooks.Open(pWorkBook)
For Each objWsh In objWbk.Worksheets
Debug.Print objWsh.Name
Next
Set objWsh = Nothing
objWbk.Close
Set objWbk = Nothing
objExc.Quit
Set objExc = Nothing
Below is the code which exports the query named 'LatestSNR' from Access to Excel;
Public Sub Expdata()
Dim rst As DAO.Recordset
Dim Apxl As Object
Dim xlWBk, xlWSh As Object
Dim PathEx As String
Dim fld As DAO.Field
PathEx = Forms("Export").Text14 'path comes from the directory given in form
Set Apxl = CreateObject("Excel.Application")
Set rst = CurrentDb.OpenRecordset("LatestSNR")
Set xlWBk = Apxl.Workbooks.Open(PathEx)
'xlWBk.ChangeFileAccess xlReadWrite
Set xlWBk = Workbook("PathEx")
Apxl.Visible = True
Set xlWSh = xlWBk.Worksheets("Metadatasheet")
xlWSh.Activate
xlWSh.Range("A2").Select
For Each fld In rst.Fields
Apxl.ActiveCell = fld.Name
Apxl.ActiveCell.Offset(0, 1).Select
Next
rst.MoveFirst
xlWSh.Range("A2").CopyFromRecordset rst
xlWSh.Range("1:1").Select
' selects all of the cells
Apxl.ActiveSheet.Cells.Select
' selects the first cell to unselect all cells
xlWSh.Range("A2").Select
rst.Close
Set rst = Nothing
' Quit excel
Apxl.Quit
End Sub
After the execution of code, the query is transferred to excel sheet and is viewed in 'Read only' mode. If I try to save it, a copy of the excel file is produced. Can the Excel be opened in Read/Write mode ? so as to save the workbook and also to transfer the query to same workbook repeatedly.
Normally, your exported Excel file should not be in read-only mode. Somewhere in your processing you are not ending the Excel instance properly. A good way to check is in your Task Manager under Processes and see if the EXCEL.EXE remains. If so, end the process and make the following code adjustments:
First, properly close and save your Excel file. Quit requires a save or not save confirmation of workbook since it means to Close the Excel application you initialized, not the target workbook. So add before Apxl.Quit:
xlWBk.Close True
Second, properly uninitialize your Excel objects to free computer resources. This is not required but simply good coding practice:
Set Apxl = Nothing
Set xlWBk = Nothing
Set xlWSh = Nothing
By the way, unless you do nuanced coding and formatting, there is a built-in Access to Excel function that exports field names and recordset together: DoCmd.TransferSpreadsheet.
I am building a form in Access that will allow a user to select an excel file, and then select a worksheet to import. I have code that allows a user to select an Excel file and it stores the filename in a control on the form.
Now I want to display the names of the worksheets that are in that file. I know how to do the import, what I don't know is how to get the worksheet names in the file and store them either in a table, or a listbox on the form so the user can select one. Sadly, although all the Excel files are supposed to have standard names for the worksheets, some of the sheets are off and that is why I want to display them.
I am using Office 2007.
Set oWkb = oXLApp.Workbooks.Open(FileName)
For Each oSh In oWkb.Worksheets
MsgBox oSh.Name
Next
oXLApp would be an instance of the Excel application, which you can get using Set oXLApp = CreateObject("Excel.Application").
Make sure you close your workbook when you are done getting the sheet names. I would probably store them in a collection or an array (instead of the MsgBox oSh.Name) so that you can collect them, close the workbook, and display them on your form using the contents of the collection.
In my testing, using an ADOX Catalog to retrieve the worksheet names appears significantly faster than opening an Excel application instance to enumerate the WorkSheets collection.
Public Sub List_WorksheetsAdox(ByVal pWorkBook As String)
Dim cat As Object 'ADOX.Catalog
Dim cn As Object 'ADO.Connection
Dim strConnect As String
Dim tbl As Object 'ADOX.Table
strConnect = "Provider=" & _
CurrentProject.Connection.Provider & ";" & _
"Data Source='" & pWorkBook & "';" & _
"Extended Properties=Excel 8.0;"
Set cn = CreateObject("ADODB.Connection")
cn.Open strConnect
Set cat = CreateObject("ADOX.Catalog")
Set cat.ActiveConnection = cn
For Each tbl In cat.Tables
Debug.Print tbl.Name
Next tbl
Set tbl = Nothing
Set cat = Nothing
cn.Close
Set cn = Nothing
End Sub
This approach will include the dollar sign after each sheet name, which may not be what you want. You could strip it off easily.
I tested using Excel 8.0 for my xls 2003 format workbook. It appears the Excel 2007 format would require "Excel 12.0" for Extended Properties. You can find more details at ConnectionStrings.com.
As in the other answers, you will want to do something more useful with tbl.Name other than Debug.Print it.
Note this approach will list both named ranges and worksheets. If that is an issue for you, you can distinguish between them based on whether or not the name includes a dollar sign ("$") on the end. Sheets have the dollar sign; named ranges do not.
Something like this?
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Set wb = Excel.Workbooks.Open("C:\MyBook.xls") ' Or whatever
For Each ws In wb.Worksheets
Debug.Print ws.Name
' This prints the name in the Immediate window.
' You'll want to do something useful with them instead.
Next ws
To use this, must set reference to Excel object library: Tools > References > set checkmark next to Microsoft Excel xx.0 Object Library.