I'm using Access 2013 and exporting data to an exisitng Excel 2010 workbook. I'm using the following code (passing the query, worksheet and excel filename). It all works great:
Public Function SendTQ2XLWbSheetSizeRange(strTQName As String, strSheetName As String, strFilePath As String)
' strTQName is the name of the table or query you want to send to Excel
' strSheetName is the name of the sheet you want to send it to
' strFilePath is the name and path of the file you want to send this data into.
Dim rst As DAO.Recordset
Dim ApXL As Object
Dim xlWBk As Object
Dim xlWSh As Object
Dim fld As DAO.Field
Dim strPath As String
Const xlCenter As Long = -4108
Const xlBottom As Long = -4107
On Error GoTo err_handler
strPath = strFilePath
Set rst = CurrentDb.OpenRecordset(strTQName)
Set ApXL = CreateObject("Excel.Application")
Set xlWBk = ApXL.Workbooks.Open(strPath)
ApXL.Visible = True
Set xlWSh = xlWBk.Worksheets(strSheetName)
xlWSh.Activate
xlWSh.Range("A5").Select
For Each fld In rst.Fields
ApXL.ActiveCell = fld.Name
ApXL.ActiveCell.Offset(0, 1).Select
Next
rst.MoveFirst
xlWSh.Range("A6").CopyFromRecordset rst
xlWSh.Range("1:1").Select
' This is included to show some of what you can do about formatting. You can comment out or delete
' any of this that you don't want to use in your own export.
With ApXL.Selection.Font
.Name = "Arial"
.Size = 12
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
End With
ApXL.Selection.Font.Bold = True
With ApXL.Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.MergeCells = False
End With
' selects all of the cells
ApXL.ActiveSheet.Cells.Select
' does the "autofit" for all columns
ApXL.ActiveSheet.Cells.EntireColumn.AutoFit
' selects the first cell to unselect all cells
xlWSh.Range("A1").Select
rst.Close
Set rst = Nothing
Exit_SendTQ2XLWbSheet:
Exit Function
err_handler:
DoCmd.SetWarnings True
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_SendTQ2XLWbSheet
End Function
Now I have a requirement to export another query to a different workbook within the same Excel file. The problem is the code above opens the Excel file, so if I then call the procedure again, it then opens an additional read-only copy of the Excel. How do I get around this? It total I will need to perform 3 exports to 3 different worksheets within 1 Excel file. Can anyone help?
I'd use three procedures. The first just identifies which file to open and which query goes on which sheet.
This will place Query1 on Sheet1, Query2 on Sheet2. It uses a ParamArray so you can add as many sheet/query pairs as you like:
Public Sub ProcessExcel()
SendToExcel "<full path to Excel file>", "Sheet1", "Query1", "Sheet2", "Query2"
End Sub
The second procedure sets a reference to Excel, opens the workbook and then starts processing the ParamArray. The sheet name is used to create a reference to the actual sheet which is then passed to the next procedure.
Public Sub SendToExcel(sFilePath As String, ParamArray ShtQry() As Variant)
Dim oXL As Object 'Ref to Excel.
Dim oWB As Object 'Ref to workbook.
Dim x As Long 'General counter
'Get or create reference to Excel.
On Error Resume Next
Set oXL = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
Err.Clear
On Error GoTo Err_Handle
Set oXL = CreateObject("Excel.Application")
End If
On Error GoTo Err_Handle
Set oWB = oXL.Workbooks.Open(sFilePath)
For x = LBound(ShtQry) To UBound(ShtQry) Step 2
SendTQ2XLWbSheetSizeRange oWB.worksheets(CStr(ShtQry(x))), CStr(ShtQry(x + 1))
Next x
Exit Sub
Err_Handle:
End Sub
The final procedure opens the recordset and pastes everything onto the correct sheet:
Public Sub SendTQ2XLWbSheetSizeRange(oWrkSht As Object, sTQName As String)
Dim rst As DAO.Recordset
Dim db As DAO.Database
Dim x As Long
Set db = CurrentDb
Set rst = db.OpenRecordset(sTQName)
With oWrkSht
'Place field headings.
For x = 0 To rst.Fields.Count - 1
.cells(5, x + 1) = rst.Fields(x).Name
Next x
'Place values.
.Range("A6").CopyFromRecordset rst
End With
rst.Close
Set rst = Nothing
Set db = Nothing
End Sub
I've missed out plenty of error checks in the code - ensure the sheet exists, that the array holds sheet/query pairs and lots I haven't even considered.
Note: Not a single Select or Activate in sight - just reference the sheet.
This doesn't sound right: 'export another query to a different workbook within the same Excel file'. How about exporting the contents of different tables to one single Excel file, but placing the results of each table to a separate sheet in the same Excel file. You can easily modify the code to export queries to separate Excel sheets, instead of exporting tables.
Option Compare Database
Option Explicit
Private Sub Command0_Click()
Dim strFile As String
Dim varItem As Variant
strFile = InputBox("Designate the path and file name to export to...", "Export")
If (strFile = vbNullString) Then Exit Sub
For Each varItem In Me.List0.ItemsSelected
DoCmd.TransferSpreadsheet transferType:=acExport, _
spreadsheetType:=acSpreadsheetTypeExcel9, _
tableName:=Me.List0.ItemData(varItem), _
FileName:=strFile
Next
MsgBox "Process complete.", vbOKOnly, "Export"
End Sub
Private Sub Form_Open(Cancel As Integer)
Dim strTables As String
Dim tdf As TableDef
' Reference: MS DAO 3.6
' Properties > All > Row Source Type = Value List
For Each tdf In CurrentDb.TableDefs
If (Left(tdf.Name, 4) <> "MSys") Then
strTables = strTables & tdf.Name & ","
End If
Next
strTables = Left(strTables, Len(strTables) - 1)
Me.List0.RowSource = strTables
End Sub
Add a ListBox to a form, and a button on the same form, and run it that way.
Thanks to everyone for their kind words and suggestions. I've gone with #Cody G. 2nd suggestions and just closed the excel file each time, so just adding
xlWBk.Close True
Set xlWBk = Nothing
ApXL.Quit
Set ApXL = Nothing
Each time.
Related
I'm running a query from Access and exporting the results to Excel. Works just like I expect it to. What I would like to do next is manipulate the Excel file (autofit columns, format fields, etc.). I've manipulated Excel worksheets countless times from Excel. However this is the first time, doing it from Access. Below is the code I'm using. The query and export run great.
My issue is I'm unable to select / activate / manipulate Excel. Currently, the only Excel file open is the query result. However, I'm sure my user's will have multiple Excel files open, so I'll need to program for that situation as well.
DoCmd.OutputTo acOutputQuery, "Query1", acFormatXLSX, , True
Set xlapp = GetObject(, "Excel.Application")
MyReport = ""
MyReport = xlapp.workbooks(w).Name
xlapp.Workbook(MyReport).Activate
xlapp.Workbook(MyReport).worksheets(1).Activate
Range(xlapp.Workbook(MyReport).worksheets(1).cells(1, 1), xlapp.Workbook(MyReport).worksheets(1).cells(1, 1)).Select
Any help or suggestions would be greatly appreciated. Thanks in advance for your assistance.........
You can start with something like this. Have fun!
With EarlyBinding:
Sub Access_ControlExcelWorkbook_EarlyBinding()
On Error GoTo errHandler
Dim appExcel As New Excel.Application
Dim xWb As Excel.Workbook
Dim xWs As Excel.Worksheet
Dim xRng As Excel.Range
Dim wbPath As String: wbPath = "YourWorkbookPath"
' Exit if workbook don't exist
If Len(Dir(wbPath)) = 0 Then Exit Sub
' Open workbook
Set xWb = appExcel.Workbooks.Open(wbPath)
' Show Excel
appExcel.Visible = True
' Sheet to control
Set xWs = xWb.Worksheets("Sheet1")
' Range to control
Set xRng = xWs.Range("A10")
' Write value in range
xRng.Value = "Control from Access"
' Auto fit columns
xWs.Cells.EntireColumn.AutoFit
' Save workbook
xWb.Save
exitRoutine:
' Close workbook
xWb.Close False
' Close Excel
appExcel.Quit
Exit Sub
errHandler:
Debug.Print Err.Description
Resume exitRoutine
End Sub
With Late Binding:
Public Const xlCenter = -4108
Sub Access_ControlExcelWorkbook_LateBinding()
On Error GoTo errHandler
Dim appExcel As Object
Dim xWb As Object
Dim xWs As Object
Dim xRng As Object
Dim wbPath As String: wbPath = "YourWorkbookPath"
' Exit if workbook don't exist
If Len(Dir(wbPath)) = 0 Then Exit Sub
' Create an instance od Excel
Set appExcel = CreateObject("Excel.Application")
' Copy the rest of the code from early Binding
' Center column G
xWs.Columns("G:G").HorizontalAlignment = xlCenter
End Sub
I have modified the code from Macro to export MS Word tables to Excel sheets to copy a sequential interval of tables (e.g. 1 to 4) instead of copying all tables, as in the original code.
But I cannot figure out how to copy a selection of tables in the Word document (e.g. tables 1, 3, 7, 8).
Help to tweak the relevant section of code much appreciated!
'For tableStart = 1 To tableTo '<- copies all tables
For tableStart = 1 To 4 '<- copies sequential interval of tables
With .tables(tableStart)
.Range.Copy
Target.Activate
Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
'ActiveSheet.Paste <- pastes with formatting
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Next tableStart
The entire macro is:
Sub ImportWordTables()
Dim WordApp As Object
Dim WordDoc As Object
Dim arrFileList As Variant, FileName As Variant
Dim tableNo As Integer 'table number in Word
Dim tableStart As Integer
Dim tableTot As Integer
Dim Target As Range
On Error Resume Next
arrFileList = Application.GetOpenFilename("Word files (*.doc; *.docx),*.doc;*.docx", 2, _
"Browse for file containing table to be imported", , True)
If Not IsArray(arrFileList) Then Exit Sub '<-user cancelled import file browser
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = False
Range("A:AZ").ClearContents
Set Target = Worksheets("MySheet").Range("A1")
For Each FileName In arrFileList
Set WordDoc = WordApp.Documents.Open(FileName, ReadOnly:=True)
With WordDoc
tableNo = WordDoc.tables.Count
tableTot = WordDoc.tables.Count
If tableNo = 0 Then
MsgBox WordDoc.Name & "Contains no tables", vbExclamation, "Import Word Table"
End If
'For tableStart = 1 To tableTo '<- copies all tables
For tableStart = 1 To 4 '<- copies interval of tables
With .tables(tableStart)
.Range.Copy
Target.Activate
Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
'ActiveSheet.Paste <- pastes with formatting
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Next tableStart
.Close False
End With
Next FileName
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub
You could supply the list of tables as an array. I added this to the restructured code below. You provide a variant containing an array of the table numbers you want to copy to the ImportWordTables sub. I'll leave it to you to modify the code by making the parameter optional so that you either copy all tables or the tables in the list.
Option Explicit
Public Enum TableImportError
NoTables
UnexpectedIndex
End Enum
Public Sub ImportWordTables(ByVal ipTableList As Variant)
Dim arrFileList As Variant
If Not TryGetFileNameList(arrFileList) Then Exit Sub
Dim WordApp As Object
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = False
' the range should be qualified by the relevant wb/ws
Range("A:AZ").ClearContents
Dim FileName As Variant
For Each FileName In arrFileList
Dim WordDoc As Object
Set WordDoc = WordApp.Documents.Open(FileName, ReadOnly:=True)
Dim myReason As TableImportError
If Not TryImportTables(WordDoc, ipTableList, myReason) Then
Select Case myReason
Case TableImportError.NoTables
MsgBox WordDoc.Name & "Contains no tables", vbExclamation, "Import Word Table"
Case TableImportError.UnexpectedIndex
MsgBox WordDoc.Name & "Unexpected index", vbExclamation, "The table indexes exceed the total table count. No tables copies"
End Select
End If
Next FileName
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub
Private Function TryGetFileNameList(ByRef opFileList As Variant) As Boolean
On Error Resume Next
opFileList = Application.GetOpenFilename("Word files (*.doc; *.docx),*.doc;*.docx", 2, _
"Browse for file containing table to be imported", , True)
On Error GoTo 0
TryGetFileNameList = IsArray(opFileList)
End Function
Private Function TryImportTables(ByRef ipDoc As Word.Document, ByVal ipTableList As Variant, ByRef opReason As TableImportError) As Boolean
TryImportTables = False
If ipDoc.Tables.Count = 0 Then
opReason = TableImportError.NoTables
Exit Function
End If
Dim myTable As Variant
For Each myTable In ipTableList
If myTable > ipDoc.Tables.Count Then
opReason = TableImportError.UnexpectedIndex
Exit Function
End If
Next
For Each myTable In ipTableList
With ipDoc.Tables.Item(myTable)
.Range.Copy
' replaced Target by worksheet refernce
' ideally this item should be passed as a parameter
' or second best defined as a module level variable.
'
' worksheets should be qualified by the relevant wb
With Worksheets("MySheet")
.Activate
.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
Set .Range("A1") = .Range("A1").Offset(.Rows.Count + 2, 0)
'.Paste
End With
End With
Next
TryImportTables = True
End Function
The code above compiles and doesn't give any unexpected Code Inspection warning by the free and fantastic Rubberduck addin for VBA. However as its a radical restructuring I can't guarantee it will work exactly as you previous code so please do check if you decide to use it.
Set this code of yours as a Function that you call from the Main Sub with the a TableIndex
With .tables(tableIndex)
.Range.Copy
Target.Activate
Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
'ActiveSheet.Paste <- pastes with formatting
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Set the tableIndex variable as a Random number assigned from the collection of tables in the Word document. You'll have to decide how many times you will iterate thru the code so you get the random sample size you want but the basic code might look like this:
Sub ReturnRandomNumber()
Dim TableIndex As Integer
Dim WordDoc As Word.Document
Randomize
TableIndex = Int((WordDoc.Tables.Count * Rnd) + 1)
CopyRandomTable WordDoc, TableIndex
End Sub
Function CopyRandomTable(ByRef WordDoc As Word.Document, ByRef TableIndex As Integer)
With WordDoc.Tables(TableIndex)
.Range.Copy
Target.Activate
Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
'ActiveSheet.Paste <- pastes with formatting
Set Target = Target.Offset(.rows.Count + 2, 0)
End With
End Function
The RND function might also return the same table index so you should think about how you might want to deal with that ... like possibly setting up an array of table indexes already used and then act accordingly.
For more information about Randomize and the RND function here is a Microsoft Article on the RND Function.
Solved, but input box and memory capacity issue still to be fixed.
Replace With .tables(tableIndex) section in my first example above with the following:
'For array
Dim tables() As Variant
Dim tableCounter As Long
tables = Array(1, 3, 7) '<- define array manually here
For tableCounter = LBound(tables) To UBound(tables)
With .tables(tables(tableCounter))
.Range.Copy
Target.Activate
'Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False '<- gives RAM capacity problems!
ActiveSheet.Paste '<- pastes with formatting
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Next tableCounter
My issue is after I have imported a table from Microsoft Word into Excel by creating an OLEObject, it won't let me copy and paste the table into excel. It continually keeps pasting whatever was last copied on my clipboard into the first cell. Currently my code asks the user for the file name, opens that file as an OLEObject in the active excel sheet, and then pastes the incorrect information into cell A1. It's not copying and pasting what's inside the Word OLEObject.
Sub Macro1()
Dim FName As String, FD As FileDialog
Dim ExR As Range
Set FD = Application.FileDialog(msoFileDialogOpen)
FD.Show
If FD.SelectedItems.Count <> 0 Then
FName = FD.SelectedItems(1)
Else
Exit Sub
End If
ActiveSheet.OLEObjects.Add(fileName:=FName, Link:=False, DisplayAsIcon:=False).Select
Selection.Verb Verb:=xlPrimary
Range("A1").Select
ActiveSheet.Paste
End Sub
Thank you!
From Word to Excel, should be something like this.
Sub ImportFromWord()
'Activate Word Object Library
'Dim WordApp As Word.Application
Dim WordDoc As Word.Document
Set WordApp = CreateObject("word.application") ' Open Word session
WordApp.Visible = False 'keep word invisible
Set WordDoc = WordApp.Documents.Open("C:\Users\your_path_here_\WordFile.docx") ' open Word file
'copy third row of first Word table
WordDoc.Tables(1).Rows(3).Range.Copy
'paste in Excel
Range("A1").PasteSpecial xlPasteValues
WordDoc.Close 'close Word doc
WordApp.Quit ' close Word
End Sub
Or this.
Sub GetTables()
FName = Application _
.GetOpenFilename("Word Files (*.doc), *.doc")
Set WordObject = GetObject(FName)
First = True
RowCount = 2
For Each Tble In WordObject.tables
For i = 1 To 22
If First = True Then
Data = Tble.Rows(i).Cells(1).Range
'Remove cell markers
Cells(1, i) = Left(Data, Len(Data) - 2)
End If
Data = Tble.Rows(i).Cells(2).Range.Text
'Remove cell markers
Cells(RowCount, i) = Left(Data, Len(Data) - 2)
Next i
RowCount = RowCount + 1
First = False
Next Tble
WordObject.Close savechanges = False
End Sub
Using the code from the link How to preserve source formatting while copying data from word table to excel sheet using VB macro? , I've only been able to get the code to work when the macro pastes my Word table in a whole new separate workbook. When clicking a command button that's within the excel workbook that I want to import the Word table to, the table never pastes into the sheet called "Scraping Sheets" I've messed around with the code, but the closest thing I could get was placing the entire table into one cell with all formatting lost.
Private Sub CommandButton22_Click()
Dim oWordApp As Object, oWordDoc As Object
Dim FlName As String
Dim tbl As Object
FlName = Application.GetOpenFilename("Word files (*.Doc*),*.Doc*", , _
On Error Resume Next
Set oWordApp = GetObject(, "Word.Applicaton")
If Err.Number <> 0 Then
Set oWordApp = CreateObject("Word.Application")
End If
Err.Clear
On Error GoTo 0
oWordApp.Visible = True
Set oWordDoc = oWordApp.Documents.Open(FlName)
Set tbl = oWordDoc.Tables(1)
Dim wb As Workbook, ws As Worksheet
Set wb = Workbooks.Open(""C:\Users\xxxx\Desktop\292 Int'l_Weekly_Win_Loss_YYYY MM DD TEMPLATE.xlsm"")
Set ws = wb.Sheets("Scraping Sheet")
tbl.Range.Copy
ws.Range("A1").Activate
ws.Paste
MsgBox "Successfully Added File!"
End Sub
I wrote this VBA code to generate a report from data in an Access table and dump it into Excel with user friendly formatting.
The code works great the first time. But if I run the code again while the first generated Excel sheet is open, one of my subroutines affects the first workbook instead of the newly generated one.
Why? How can I fix this?
I think the issue is where I pass my worksheet and recordset to the subroutine called GetHeaders that prints the columns, but I'm not sure.
Sub testROWReport()
DoCmd.Hourglass True
'local declarations
Dim strSQL As String
Dim rs1 As Recordset
'excel assests
Dim xlapp As excel.Application
Dim wb1 As Workbook
Dim ws1 As Worksheet
Dim tempWS As Worksheet
'report workbook dimentions
Dim intColumnCounter As Integer
Dim lngRowCounter As Long
'initialize SQL container
strSQL = ""
'BEGIN: construct SQL statement {
--this is a bunch of code that makes the SQL Statement
'END: SQL construction}
'Debug.Print (strSQL) '***DEBUG***
Set rs1 = CurrentDb.OpenRecordset(strSQL)
'BEGIN: excel export {
Set xlapp = CreateObject("Excel.Application")
xlapp.Visible = False
xlapp.ScreenUpdating = False
xlapp.DisplayAlerts = False
'xlapp.Visible = True '***DEBUG***
'xlapp.ScreenUpdating = True '***DEBUG***
'xlapp.DisplayAlerts = True '***DEBUG***
Set wb1 = xlapp.Workbooks.Add
wb1.Activate
Set ws1 = wb1.Sheets(1)
xlapp.Calculation = xlCalculationManual
'xlapp.Calculation = xlCalculationAutomatic '***DEBUG***
'BEGIN: Construct Report
ws1.Cells.Borders.Color = vbWhite
Call GetHeaders(ws1, rs1) 'Pastes and formats headers
ws1.Range("A2").CopyFromRecordset rs1 'Inserts query data
Call FreezePaneFormatting(xlapp, ws1, 1) 'autofit formatting, freezing 1 row,0 columns
ws1.Name = "ROW Extract"
'Special Formating
'Add borders
'Header background to LaSenza Pink
'Fix Comment column width
'Wrap Comment text
'grey out blank columns
'END: Report Construction
'release assets
xlapp.ScreenUpdating = True
xlapp.DisplayAlerts = True
xlapp.Calculation = xlCalculationAutomatic
xlapp.Visible = True
Set wb1 = Nothing
Set ws1 = Nothing
Set xlapp = Nothing
DoCmd.Hourglass False
'END: excel export}
End Sub
Sub GetHeaders(ws As Worksheet, rs As Recordset, Optional startCell As Range)
ws.Activate 'this is to ensure selection can occur w/o error
If startCell Is Nothing Then
Set startCell = ws.Range("A1")
End If
'Paste column headers into columns starting at the startCell
For i = 0 To rs.Fields.Count - 1
startCell.Offset(0, i).Select
Selection.Value = rs.Fields(i).Name
Next
'Format Bold Text
ws.Range(startCell, startCell.Offset(0, rs.Fields.Count)).Font.Bold = True
End Sub
Sub FreezePaneFormatting(xlapp As excel.Application, ws As Worksheet, Optional lngRowFreeze As Long = 0, Optional lngColumnFreeze As Long = 0)
Cells.WrapText = False
Columns.AutoFit
ws.Activate
With xlapp.ActiveWindow
.SplitColumn = lngColumnFreeze
.SplitRow = lngRowFreeze
End With
xlapp.ActiveWindow.FreezePanes = True
End Sub
When Cells and Columns are used alone, they refer to ActiveSheet.Cells and ActiveSheet.Columns.
Try to prefix them with the targeted sheet:
Sub FreezePaneFormatting(xlapp As Excel.Application, ws As Worksheet, Optional lngRowFreeze As Long = 0, Optional lngColumnFreeze As Long = 0)
ws.Cells.WrapText = False
ws.Columns.AutoFit
...
End Sub
Okay, I figured out the issue here. I guess I can't use the ".Select" or "Selection." when I'm working with an invisible, non updating workbook. I found that when I changed some code from automated selecting to simply directly changing the value of cells, it worked out.
OLD:
startCell.Offset(0, i).Select
Selection.Value = rs.Fields(i).Name
NEW:
ws.Cells(startCell.Row, startCell.Column).Offset(0, i).Value = rs.Fields(i).Name
Here I have some VBA code that outputs a ton of files into Excel files. My question is, from this, is there anyway for it to Format the excel file a bit? What I would like to do is make the Columns bold and make the columns fit the size of the header as well.
Sub OutPutXL()
Dim qdf As QueryDef
Dim rs As DAO.Recordset
Set qdf = CurrentDb.QueryDefs("OutputStudents")
Set rs = CurrentDb.OpenRecordset("Teachers")
Do While Not rs.EOF
qdf.SQL = "SELECT * FROM Students WHERE contact='" & rs!contact & "'"
''Output to Excel
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel8, _
qdf.Name, "C:\Users\chrisjones\Documents\ProjectionsFY14\Teachers\" _
& rs!contact & ".xls", True
rs.MoveNext
Loop
End Sub
this is a quick and dirty combination of Phil.Wheeler's Code and my previous input, for me this is working. Don't forget to add Excel's Object Library in your Access-Macro.
Sub doWhatIWantTheDirtyWay()
pathToFolder = "C:\Users\Dirk\Desktop\myOutputFolder\"
scaleFactor = 0.9
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = False
objExcel.DisplayAlerts = False
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFso.GetFolder(pathToFolder)
For Each objFile In objFolder.Files
If objFso.GetExtensionName(objFile.path) = "xls" Then
Set objWorkbook = objExcel.Workbooks.Open(objFile.path)
For Each sh In objWorkbook.Worksheets
If sh.UsedRange.Address <> "$A$1" Or sh.Range("A1") <> "" Then
With sh
columncount = .Cells(1, 256).End(xlToLeft).Column
For j = 1 To columncount
With .Cells(1, j)
i = Len(.Value)
.ColumnWidth = i * scaleFactor
.Font.Bold = True
End With
Next
End With
End If
Next
objWorkbook.Close True
End If
Next
objExcel.Quit
End Sub
Yes it is possible! This is hacked together from one of my codes, might need a bit of editing before it works...
'This deals with Excel already being open or not
On Error Resume Next
Set xl = GetObject(, "Excel.Application")
On Error GoTo 0
If xl Is Nothing Then
Set xl = CreateObject("Excel.Application")
End If
Set XlBook = GetObject(filename)
'filename is the string with the link to the file ("C:/....blahblah.xls")
'Make sure excel is visible on the screen
xl.Visible = True
XlBook.Windows(1).Visible = True
'xl.ActiveWindow.Zoom = 75
'Define the sheet in the Workbook as XlSheet
Set xlsheet1 = XlBook.Worksheets(1)
'Then have some fun!
with xlsheet1
.range("A1") = "some data here"
.columns("A:A").HorizontalAlignment = xlRight
.rows("1:1").font.bold = True
end with
'And so on...
I have come across this problem a couple of times as well. As #Remou said, you will need to open excel to format xls files, this modification of your code silently opens Excel and that should get you in the right direction. Remember to add a reference to the Microsoft Excel Object Library in your VBA project.
Sub OutPutXL()
Dim qdf As QueryDef
Dim rs As DAO.Recordset
Dim xl as Excel.Application
Dim wb as Object
Dim strFile as string
Set qdf = CurrentDb.QueryDefs("OutputStudents")
Set rs = CurrentDb.OpenRecordset("Teachers")
Set xl = New Excel.Application
xl.DisplayAlerts = False
Do While Not rs.EOF
qdf.SQL = "SELECT * FROM Students WHERE contact='" & rs!contact & "'"
'Output to Excel
strFile = "C:\Users\chrisjones\Documents\ProjectionsFY14\Teachers\" & rs!contact & ".xls"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel8, qdf.Name, strFile, True
'Start formatting'
Set wb = xl.Workbooks.Open(strFile)
With wb.Sheets(qdf.name)
'Starting with a blank excel file, turn on the record macro function'
'Format away to hearts delight and save macro'
'Past code here and resolve references'
End With
wb.save
wb.close
set wb = Nothing
rs.MoveNext
Loop
xl.quit
set xl = Nothing
End Sub
You could (depending on the number of files) make a template for each file you are outputting. In the long run if someone needs to change the formatting they can change the template which is going to be easier on you now that you don't have to sift through a bunch of excel formatting garbage. You could even let a qualified end user do it.
It's one of the biggest problems I have with excel sheets if I wrote the VBA I am responsible until I die for it. This way (in theory) they should be able to change a column, without changing how the data is outputted, just presented without you.
+1 To open the excel file itself and format it using that automation though.