VBA save Excel file as .xls from Access - vba

Hi, I have to perform Import from Excel file into Access DB, without duplicates. Only way that this can be done is by creating table where you can Import Excel data, and then append It to destination table by buiilding a Query. Problem is that this Excel file has to be .xls format, none other format is working for me (don't know why). How can I do that from Access - desirable without opening Excel workbook, just change It's extension file name ? This is what I tried (I receive error : " object doesn't support this property or method")
Dim XFile As Excel.Application
Set XFile = CreateObject("Excel.Application")
XFile.Workbooks.Open "C:\Users\Mike\Desktop\Copy.xlsx", True
XcelFile.SaveAs Filename:="C:\Users\Mike\Desktop\Copy.xlsx", FileFormat:=56
XFile.Workbooks.Close
End Sub
As you see, I need to save from .xlsx, It's default format for Excel 2013.
Any help much appreciated !!

Thanks #Porcupine911, that worked, even without opening workbook :)
Dim XcelFile As Excel.Application
Dim wb As Excel.Workbook
Set XcelFile = New Excel.Application
Set wb = XcelFile.Workbooks.Open("Filepath here")
wb.SaveAs Filename:="Filename here, with different destination and desirable extension", FileFormat:=56
wb.Close
Set XcelFile = Nothing
End Sub

Related

Using Workbooks object with absolute address while the workbook is not opened [duplicate]

I want to search through existing Excel files with a macro, but I don't want to display those files when they're opened by the code. Is there a way to have them open "in the background", so to speak?
Not sure if you can open them invisibly in the current excel instance
You can open a new instance of excel though, hide it and then open the workbooks
Dim app as New Excel.Application
app.Visible = False 'Visible is False by default, so this isn't necessary
Dim book As Excel.Workbook
Set book = app.Workbooks.Add(fileName)
'
' Do what you have to do
'
book.Close SaveChanges:=False
app.Quit
Set app = Nothing
As others have posted, make sure you clean up after you are finished with any opened workbooks
If that suits your needs, I would simply use
Application.ScreenUpdating = False
with the added benefit of accelerating your code, instead of slowing it down by using a second instance of Excel.
To open a workbook as hidden in the existing instance of Excel, use following:
Application.ScreenUpdating = False
Workbooks.Open Filename:=FilePath, UpdateLinks:=True, ReadOnly:=True
ActiveWindow.Visible = False
ThisWorkbook.Activate
Application.ScreenUpdating = True
Using ADO (AnonJr already explained) and utilizing SQL is possibly the best option for fetching data from a closed workbook without opening that in conventional way. Please watch this VIDEO.
OTHERWISE, possibly GetObject(<filename with path>) is the most CONCISE way. Worksheets remain invisible, however will appear in project explorer window in VBE just like any other workbook opened in conventional ways.
Dim wb As Workbook
Set wb = GetObject("C:\MyData.xlsx") 'Worksheets will remain invisible, no new window appears in the screen
' your codes here
wb.Close SaveChanges:=False
If you want to read a particular sheet, need not even define a Workbook variable
Dim sh As Worksheet
Set sh = GetObject("C:\MyData.xlsx").Worksheets("MySheet")
' your codes here
sh.Parent.Close SaveChanges:=False 'Closes the associated workbook
Even though you've got your answer, for those that find this question, it is also possible to open an Excel spreadsheet as a JET data store. Borrowing the connection string from a project I've used it on, it will look kinda like this:
strExcelConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & objFile.Path & ";Extended Properties=""Excel 8.0;HDR=Yes"""
strSQL = "SELECT * FROM [RegistrationList$] ORDER BY DateToRegister DESC"
Note that "RegistrationList" is the name of the tab in the workbook. There are a few tutorials floating around on the web with the particulars of what you can and can't do accessing a sheet this way.
Just thought I'd add. :)
A much simpler approach that doesn't involve manipulating active windows:
Dim wb As Workbook
Set wb = Workbooks.Open("workbook.xlsx")
wb.Windows(1).Visible = False
From what I can tell the Windows index on the workbook should always be 1. If anyone knows of any race conditions that would make this untrue please let me know.
The problem with both iDevlop's and Ashok's answers is that the fundamental problem is an Excel design flaw (apparently) in which the Open method fails to respect the Application.ScreenUpdating setting of False. Consequently, setting it to False is of no benefit to this problem.
If Patrick McDonald's solution is too burdensome due to the overhead of starting a second instance of Excel, then the best solution I've found is to minimize the time that the opened workbook is visible by re-activating the original window as quickly as possible:
Dim TempWkBk As Workbook
Dim CurrentWin As Window
Set CurrentWin = ActiveWindow
Set TempWkBk = Workbooks.Open(SomeFilePath)
CurrentWin.Activate 'Allows only a VERY brief flash of the opened workbook
TempWkBk.Windows(1).Visible = False 'Only necessary if you also need to prevent
'the user from manually accessing the opened
'workbook before it is closed.
'Operate on the new workbook, which is not visible to the user, then close it...
Open the workbook as hidden and then set it as "saved" so that users are not prompted when they close out.
Dim w As Workbooks
Private Sub Workbook_Open()
Application.ScreenUpdating = False
Set w = Workbooks
w.Open Filename:="\\server\PriceList.xlsx", UpdateLinks:=False, ReadOnly:=True 'this is the data file were going to be opening
ActiveWindow.Visible = False
ThisWorkbook.Activate
Application.ScreenUpdating = True
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
w.Item(2).Saved = True 'this will suppress the safe prompt for the data file only
End Sub
This is somewhat derivative of the answer posted by Ashok.
By doing it this way though you will not get prompted to save changes back to the Excel file your reading from. This is great if the Excel file your reading from is intended as a data source for validation. For example if the workbook contains product names and price data it can be hidden and you can show an Excel file that represents an invoice with drop downs for product that validates from that price list.
You can then store the price list on a shared location on a network somewhere and make it read-only.
Open them from a new instance of Excel.
Sub Test()
Dim xl As Excel.Application
Set xl = CreateObject("Excel.Application")
Dim w As Workbook
Set w = xl.Workbooks.Add()
MsgBox "Not visible yet..."
xl.Visible = True
w.Close False
Set xl = Nothing
End Sub
You need to remember to clean up after you're done.
In excel, hide the workbooks, and save them as hidden. When your app loads them they will not be shown.
Edit: upon re-reading, it became clear that these workbooks are not part of your application. Such a solution would be inappropriate for user workbooks.

VBA on new Excel file

I receive reports almost daily in spreadsheet form. I have a macro code that will take out certain portions of the spreadsheet and put it into a new spreadsheet.
I want to know if there's a way to run that macro without having to manually copy paste it into each new file I receive.
Sub CopyItOver()
Dim newbook As Workbook
Set newbook = Workbooks.Add
ThisWorkbook.Worksheets("sheet1").Range("fe1:fh1").Copy Destination:=newbook.Worksheets("Sheet1").Range("A1:D1")
ThisWorkbook.Worksheets("sheet1").Range("IZ1:JI1").Copy Destination:=newbook.Worksheets("Sheet1").Range("E1")
ThisWorkbook.Worksheets("sheet1").Range("JK1:JL1").Copy Destination:=newbook.Worksheets("Sheet1").Range("O1")
ThisWorkbook.Worksheets("sheet1").Range("KA1:KJ1, Kl1, KR1, KT1").Copy Destination:=newbook.Worksheets("Sheet1").Range("Q1")
ThisWorkbook.Worksheets("sheet1").Range("fe328:fh328").Copy Destination:=newbook.Worksheets("Sheet1").Range("A2")
ThisWorkbook.Worksheets("sheet1").Range("IZ328:JI711").Copy Destination:=newbook.Worksheets("Sheet1").Range("E2")
ThisWorkbook.Worksheets("sheet1").Range("JK328:JL711").Copy Destination:=newbook.Worksheets("Sheet1").Range("O2")
ThisWorkbook.Worksheets("sheet1").Range("KA328:KJ711, KL328:KL711, KR328:KR711, KT328:KT711").Copy Destination:=newbook.Worksheets("Sheet1").Range("Q2")
Columns("E").ColumnWidth = 15
Columns("Q").ColumnWidth = 15
End Sub
When you create a macro and select the option to save to your personal macro workbook it is available every time you start Excel. Or create a custom toolbar button and attach the macro to it, it will always be there...
You can create small .vbs file which you can run (by double click) and it will run your macro automatically on your spreadsheet.
First of all export your working macro to some location. And then copy paste below lines in a text file and save it as .vbs file.
Dim fso, xlApp, xlBook
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = False
Set xlBook = xlApp.Workbooks.Open(fileToUse)
xlApp.VBE.ActiveVBProject.VBComponents.Import "Path to your .bas file"
xlApp.Run "Name of your Sub"
xlBook.Save
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
Set fso = Nothing
Just change the path in the file.
Like schwack said, you can put the macro in your personal macro workbook and it will always be available, or put it in a workbook that you have open alongside the report workbooks you are receiving. But you will need to change the macro code so it doesn't use the 'ThisWorkbook' object. You could simply use 'ActiveWorkbook' instead.

MS Access VBA convert query output to Excel format but not saving anywhere

I've been trying to use transfer spreadsheet methods but they appear to require an output path.
I just need to find out how to take a given query and simply "open up" an Excel file that contains the query output. I don't need the file actually saved anywhere.
You can open up your file without saving it by creating an Excel instance (or grabbing an existing one) and using the CopyFromRecordset function of the Excel.Range object.
This assumes your data are in an ADO recordset. You need to have references to Microsoft Excel XX.0 Object Library and Microsoft ActiveX Data Objects X.X Library` (if you are using ADO. If you use DAO then use whatever DAO reference you need)
I use this to grab an an Excel app or create a new one is Excel is not open already. I use WasANewInstanceReturned to figure how I need to clean up the Excel resources at the end. (Obviously I don't want to quit Excel if it is being use by something else).
Function GetExcelApplication(Optional ByRef WasANewInstanceReturned As Boolean) As Excel.Application
If ExcelInstanceCount > 0 Then
Set GetExcelApplication = GetObject(, "Excel.Application")
WasANewInstanceReturned = False
Else
Set GetExcelApplication = New Excel.Application
WasANewInstanceReturned = True
End If
End Function
Then grab that instance
Dim ApXL As Excel.Application, WasANewInstanceReturned as Boolean
Set ApXL = GetExcelApplication(WasANewInstanceReturned)
Add a workbook
Dim wbExp As Excel.Workbook
Set wbExp = ApXL.Workbooks.Add
Grab the first sheet
Dim wsSheet1 As Excel.Worksheet
Set wsSheet1 = wbExp.Sheets(1)
Put your recordset's field names in the first row
Dim fld As ADODB.Field
Dim col As Integer
col = 1
With wsSheet1
For Each fld In rst.Fields
.Cells(1, col).Value = fld.Name 'puts the field names in the first row
End With
col = col + 1
Next fld
End With
Then move the data just below the field names
wsSheet1 .Range("A2").CopyFromRecordset rst
Voila! You have an excel file open, with your data that has not been saved anywhere!
I usually set ApXL.ScreenUpdating = False before doing any of this and ApXL.ScreenUpdating = True at the end.
I'll let you stitch this together for your needs.
The file must be saved somewhere for Excel to open it.
If the dataset is small enough, you can use copy/paste (no file here). Otherwise, just use the %TEMP% folder for the file location.
Edit:
One simple way to get the TEMP folder is to use =Environ("TEMP")
I open and export a query from access to excel. First I created a worksheet in excel and saved it. Then I created a module in the vba part of Access (2013):
Option Compare Database
' Testtoexporttoexcel'
Function ExportQuerytoExcel()
On Error GoTo ExportQuerytoExcel_Err
' Exports the query to excel to a sheet named Nameofyoursheet
DoCmd.TransferSpreadsheet acExport, 10, "nameofyourquery", "yourPath:\nameofyourworkbook", False, "Nameofyour worksheet"
ExportQuerytoExcel_Exit:
Exit Function
ExportQuerytoExcel_Err:
MsgBox Error$
Resume ExportQuerytoExcel_Exit
End Function
-----then add another function that says:
Option Compare Database
Function OpenExcelFromAccess()
'Opens Excel to the chart
Dim MYXL As Object
Set MYXL = CreateObject("Excel.Application")
With MYXL
.Application.Visible = True
.workbooks.Open "Yourpath:\nameofyourworkbook"
End With
'Application.Quit
End Function
hope this helps, this is my first time answering a question.
Aloha

overwrite a csv file using vba

There are a number of similar posts but nothing that does exactly what I want as simply as it needs to be for me to understand
I want to use Access 2007 VBA to open a csv file and replace the column headings row ie:
OldColumn1,OldColumn2
1,2
with
NewColumn1,NewColumn2
1,2
ie without disturbing the rump of data.
Then save and close.
I have tried this code, but it deletes my data:
Sub WriteFile()
Dim OutputFileNum As Integer
Dim PathName As String
PathName = Application.ActiveWorkbook.Path
OutputFileNum = FreeFile
Open PathName & "\Test.csv" For Output Lock Write As #OutputFileNum
Print #OutputFileNum, "NewCol1" & "," & "NewCol2"
Close OutputFileNum
End Sub
Import or link to the .csv so that you have the recordset in your Access 2007 databases.
Write a query with NewColumn[x] as an alias for OldColumn[x].
Write vba code to use TransferText functionality or make a macro to do the same to export your query as a .csv file (overwriting the original csv if you want/need).
Obviously, there are plenty of bonus things you could do to automate and reproduce this concept for any number or types of files. But the above solution should work in an all MS Access environment.
Let me know if you would like details on any of these steps.
Further to my earlier comment, please see the method which uses the Excel reference:
Public Sub EditCsv()
Dim xlApp As Object
dim xlWbk As Object
Dim xlWst As Object
Set xlApp = CreateObject("Excel.Application")
Set xlWbk = xlApp.Workbooks.Open ".../Test.csv" 'Amend this to your needs
Set xlWst = xlWbk.Sheets(1)
'This assumes the columns are at the beginning of the file
xlWst.Range("A1") = "My New Column Name"
xlWst.Range("B1") = "My New Second Column Name"
xlWbk.Close -1 'Close and save the file here
xlApp.Quit
Set xlApp = Nothing
Set xlWbk = Nothing
Set xlWst = Nothing
End Sub

How will this variable respond

I'm using Excel VBA but I think this is quite a generic question.
I have the following declaration
Public newReport As Excel.Workbook
Later in the code, after I've opened and named an xlsx file MyBook.xlsx I point this variable at the file:
Set newReport = Excel.Workbooks("MyBook.xlsx")
I'm getting slightly confused again re. variable behaviour.
If I later have MyBook.xlsx open and I execute ActiveWorkbook.SaveCopyAs and give it a new name say MyBookNew.xlsx will the variable newReport be pointed at the new workbook?
Example of related code is the following:
Public newReport As Excel.Workbook
Sub FileExperiment()
Set newReport = Excel.Workbooks.Add
newReport.SaveAs ThisWorkbook.Path & "\MyBook.xlsx"
Set newReport = Excel.Workbooks("MyBook.xlsx")
ActiveWorkbook.SaveCopyAs ThisWorkbook.Path & "\MyNewBook.xlsx"
newReport.Close False
End Sub
newReport will be unchanged.
Cut from the help file, regarding the command SaveCopyAs:
Saves a copy of the workbook to a file but doesn't modify the open workbook in memory.