The users dynamically generate queries in a form, and the results are shown in a listbox on the same form. The listbox can have anywhere from 1 to 12 columns.
The users want the results of this query to be able to be exported to Excel. I believe not saving the file is preferred but whatever works will work.
I have currently found two methods, each with its own problem(s)
1
myExApp.visible = True
myExApp.Workbooks.Add
Set myExSheet = myExApp.Workbooks(1).Worksheets(1)
If myExApp.Ready = True Then
For i = 1 To Me!listDynamicSearchResult.ColumnCount
Me!listDynamicSearchResult.BoundColumn =
Me!listDynamicSearchResult.BoundColumn + 1
For j = 1 To Me!listDynamicSearchResult.ListCount
myExSheet.Cells(j, i) = Me!listDynamicSearchResult.ItemData(j - 1)
Next j
Next i
Me!listDynamicSearchResult.BoundColumn = 0
End If
Which works fine, but becomes exponentially slow, for obvious reasons.
That method also causes an error when the user clicks within the now open Excel sheet.
Coupled with how slow it is, it is very likely that the user will cause an error, trying to manipulate the form before the looping is completed.
2
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "test", "I:\\test.xls"
That method involves saving the query made dynamically to a saved query on click.
The issue with this is that the columns don't get formatted and excel reads everything as strings rather than the data type, whereas in the first method the data types are read correctly.
Are there any ways to mitigate the issues or is there a more efficient way to do this?
SOLUTION (Currently Formats As String)
Set xlApp = New Excel.Application
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Worksheets(1)
xlApp.visible = True
strFile = CurrentProject.FullName
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile & ";"
Set cn = CurrentProject.AccessConnection
Set rs = CreateObject("ADODB.recordset")
With rs
Set .ActiveConnection = cn
.Source = Me!listDynamicSearchResult.RowSource
.Open
End With
With xlWs
.QueryTables.Add Connection:=rs, Destination:=.Range("A1")
.QueryTables(1).Refresh
End With
You could make a ListObject in excel with an external data source that's the same as the RowSource of the Listbox.
Private Sub Command2_Click()
Dim xlApp As Excel.Application
Dim xlWb As Excel.Workbook
Dim xlWs As Excel.Worksheet
Dim xlLo As Excel.ListObject
Set xlApp = GetObject(, "Excel.Application")
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Worksheets(1)
Set xlLo = xlWs.ListObjects.Add(xlSrcExternal, "OLEDB;" & CurrentProject.Connection, , xlYes, xlWs.Range("A3"))
xlLo.QueryTable.CommandType = xlCmdSql
xlLo.QueryTable.CommandText = Me.listDynamicSearchResult.RowSource
DoCmd.Close acForm, Me.Name
End Sub
I couldn't refresh the list in the Excel until I closed the form in Access. So you may have some permissions issues to deal with.
Try generating a XML file. Here an example: http://blogs.msdn.com/b/brian_jones/archive/2005/06/27/433152.aspx
PS About first method. To avoid users clicks you can hide Excel. Also you can speed up Excel (see functions below). Use Prepare() before putting data and Ended() after it or in case of error.
Public Sub Prepare()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
Application.DisplayStatusBar = False
Application.DisplayAlerts = False
End Sub
Public Sub Ended()
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
ActiveSheet.DisplayPageBreaks = True
Application.DisplayStatusBar = True
Application.DisplayAlerts = True
End Sub
Please refer to this site for all possible methods as well as advantages/disadvantages of them. For your problem , I would prefer to use DAO method. The example codes are also in this site.
Way to transer data from access to excel
While you import Cell by Cell, you can format any Row, Column, Cell as you wished. For Example:
xlActiveSheet.Cells(4,5).Characters(2).Font.ColorIndex = 5
or
xlActiveSheet.Columns("A:AZ").EntireColumn.AutoFit
or
xlActiveSheet.Range(xlActiveSheet.Cells(1, 1), xlActiveSheet.Cells(1, rec1.Fields.count)).Interior.ColorIndex = 15
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.