Open Excel file for reading with VBA without display - excel

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

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.

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. :)

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.

Related

code added to a xlsm worksheet while saving in VBA keeps diapearing

I build a xlsm file that takes a database of a few hundred lines as input, processes them and outputs a few seperate .xlsm files, each containing some rearanged part of the input.
I would like to add a simple "Worksheet_BeforeDoubleClick" sub to each of the generated output files.
when working through the input, at the end of the for loop, I do the following:
Dim numLines As Integer
Set CodeCopy = ThisWorkbook.VBProject.VBComponents("Module2").CodeModule
numLines = CodeCopy.CountOfLines
NewBook.VBProject.VBComponents("Sheet1").CodeModule.AddFromString CodeCopy.Lines(1, numLines)
AccessMode:=xlExclusive, _
ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges, _
FileFormat:=xlOpenXMLWorkbookMacroEnabled
NewBook.Saved = False
NewBook.SaveAs Filename:="cw_" & cw & "_" & myVendors(N), _
ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges, _
FileFormat:=52
NewBook.Close
If I add a break before the "NewBook.Close", everything seems to work. The split file is shown as a seperate project and "Sheet2" contains the required code.
If I let the sub resume, the file is closed but if I reopen it manually the code is gone.
If I instead stop at the "NewBook.Close" and save the split file seperately the code remains in the file.
I have no idea why your code is gone after save - however, I generally think writing code using the VBE is not a good idea. And you need to allow this in the Trust Center Settings where it is usually disabled (for good reasons).
It is much easier to put the code into a template worksheet that sits in your workbook where your code sits. When create the new workbook, you simply copy this template sheet into it and voilà, all the code is copied with it. You can also put some formatting into the template - no need to do the formatting via code.
If you want, you can completely hide the template sheet - you just have to temporarily set it to visible before you copy it (use Application.ScreenUpdating = False to prevent flicker).
If you use the Copy-method of a worksheet without parameters, Excel will create a new Workbook with only this sheet. Of course, you can also create the new Workbook and use the Copy-method with Before or After-parameter.
Const TemplateSheetName = "Template"
With ThisWorkbook.Sheets(TemplateSheetName)
Application.ScreenUpdating = False
Dim saveVisibility As Long
saveVisibility = .Visible§
.Visible = xlSheetVisible
.Copy
.Visible = saveVisibility
Application.ScreenUpdating = True
End With
Dim newWb As Workbook, newWS As Worksheet
Set newWb = Workbooks(Workbooks.Count)
Set newWS = newWb.Sheets(TemplateSheetName)
newWS.Name = "MyNewDataSheet" ' You should assign a new name to the sheet

Workbook object persists after closing and workbook reopens on any subsequent excel action after the workbook has been closed

I have an excel workbook that acts as a Launchpad for other excel based tools allow the user to launch multiple instances of the same tool I am forcing the new tools to open in a new excel instance each time by setting a new application. The code then also passes some data from the launchpad into the tools as well.
Unfortunately for some users, currently only a handful from some 20-30 that have used the system, if they close the launchpad workbook it seems to persist in that instance of excel (It remains visible in the VBE project explorer). What's stranger is that whatever they now do in any workbook that remains opened in that instance of excel e.g.type into a cell and press return, the launchpad is re-opened. They have to completely shut down excel to stop the issue.
I release all the objects used in the routine that opens the tools so it can not be this, I am wondering if this is necessary given I am opening the workbooks and wanting to leave them open for the user?
My Code:
Public Sub LaunchTool()
Dim WB1 As Workbook
Dim WS1 As Worksheet
Dim WT1 As Workbook
Dim EA1 As New Application
Application.DisplayAlerts = False
'Define workbook aliases
Set WT1 = ActiveWorkbook
EA1.Workbooks.Open Filename:=PathString, IgnoreReadOnlyRecommended:=True,
ReadOnly:=True
Set WB1 = EA1.ActiveWorkbook
Set WS1 = WB1.Worksheets("Import")
WB1.Windows(1).Visible = True
EA1.Visible = True
'pass on some values
WB1.Sheets("Control").Range("Dev_Flag") =
WT1.Sheets("Param").Range("Dev_Flag")
Set WT1 = Nothing
Set WS1 = Nothing
Set WB1 = Nothing
Set EA1 = Nothing
Application.DisplayAlerts = True
End Sub
The Application.DisplayAlerts = False is to suppress the Microsoft Excel is waiting for another application to complete an OLE action alert that sometimes pops up during the loading.
I have tried the following in the ThisWorkbook module:
Private WithEvents XL As Excel.Application
Private Sub XL_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
Set XL = Nothing
Workbooks.Open ThisWorkbook.FullName
ThisWorkbook.Close False
End Sub
But no luck!
For most users, everything works fine but some users as I described cannot successfully close down the launchpad and then unless they close excel completely or at least the instance that the launchpad was open in then any user action begins to trigger the launchpad to reopen.
Thanks.
After much deliberation, I realised that the issue was not being driven by the objects but rather that I had an Application.OnKey trigger that was being set but never released and this was causing the workbook to persist, releasing the OnKey trigger in the WorkbookBeforeClose routine has solved it nicely.
Thank you for your help.

Workbook will not close with VBA unless opened manually

I have a workbook that I open with VBA, modify said workbook, and then close said workbook. So far what I have is:
Sub OpenandModify()
application.screenupdating = false
workbooks.open Filename:="FilePath\WkbkName.xlsm"
*Modify Workbook
Workbooks("WkbkName.xlsm").close SaveChanges:=True
application.screenupdating = true
End Sub()
If I run the macro with the workbook already open, the macro works correctly and closes the workbook mentioned above. However, if the workbook is not already open, then the file remains open after the modification (Note, the modifications take place so I do not think it is an issue with the Workbook.Open). Any ideas?
Thanks in advance.
After playing around more with my workbook. I seem to have found the issue. In the modify code portion, I have another subroutine that adds a worksheet from a workbook different than WkbkName.xlsm. If the sheet already exists it gets added as Sheet(2) and the workbook will not close. If the worksheet does not exist then the workbook opens and modifies correctly and shuts. I still do not understand why it acts like this so if anyone has any ideas it would be greatly appreciated.
For now, I just plan to add a check for duplicate worksheets and exit the sub if it happens.
Some of the problems you've encountered may be due to the code getting confused with which workbook it's working on.
Use a variable to hold a reference to your workbook and use only that throughout the code:
Sub OpenandModify()
Dim wrkBk As Workbook
Application.ScreenUpdating = False
'Open the workbook and assign it to wrkBk variable.
Set wrkBk = Workbooks.Open(Filename:="FilePath\WkbkName.xlsm")
'Modify Workbook
With wrkBk
.Worksheets("Sheet1").Range("A1") = "Modified!"
End With
wrkBk.Close SaveChanges:=True
Application.ScreenUpdating = True
End Sub

Periodically store changes of shared workbook into an isolated workbook

I have two workbooks, a shared "xlsx" file A which stores data and no-sharing "xlsm" file B which contains my macros. I would like maintain periodic tracking of changes in file A and password-protect this change history. I know there is a "Track Changes" feature in file A and it could create a separate sheet containing the change history. However, this sheet is within workbook A, which is being shared. Is there a way to write a macro in B to periodically extract this change history from A, put it into a "xlsx" file C with password?
The point here is I would like to prevent the change history to be compromised. Only I have access to it. Note that I can not make file A "macro enabled" and write macro in it.
Thank.
When you open the Shared WB, update the change info, then copy the History sheet
Sub Demo()
Dim wbShared As Workbook
Dim wbHistory As Workbook
Set wbHistory = Application.Workbooks.Open( _
Filename:="\\Path\To\Your\History\FileC.xlsx", _
Password:="Password")
Set wbShared = Application.Workbooks.Open( _
FileName:="\\Path\To\Your\Shared\FileA.xlsx")
' Generate History Sheet (maybe change xlAllChanges to suit needs)
With wbShared
.HighlightChangesOptions _
When:=xlAllChanges, _
Who:="Everyone"
.ListChangesOnNewSheet = True
End With
' Copy out History to FileC
wbShared.Worksheets("History").Copy After:=wbHistory.Sheets(wbHistory.Sheets.Count)
' Clean Up
wbShared.Close False
wbHistory.Close True
End Sub
Using your private workbook, you can use macros to open the shared workbook and copy the sheet into the private workbook again.
EDIT: Sorry, I missed the part about saving it into a file C.
Here is to get you started:
Sub wbCopy()
Dim sharedWb, myWb As Workbook
Dim sharedWs As Worksheet
Set myWb = New Workbook
Workbooks.Open Filename:="192.168.0.10\sharedWorkbook.xls", ReadOnly:=True
Set sharedWb = "sharedWorkbook.xls"
Set sharedWs = sharedWb.Worksheets(2)
sharedWs.Copy myWb.Worksheets(Sheets.Count)
Workbooks("sharedWorkbook.xls").Close
myWb.SaveAs Filename:="File C.xls"
End Sub

If disabling macro on excel file you can not copy a sheet from one workbook to another

I am using this function to copy a sheet from a Workbook to another Workbook.
I works, but it seems that if I disable the macros from Workbook,
it can not copy the sheet anymore.
If I chage this line : m_objExcel.AutomationSecurity = msoAutomationSecurityForceDisable
to this m_objExcel.AutomationSecurity = msoAutomationSecurityByUI
it works but gets a warning message.
Also if I comment the line it works perfectly but with macros On.
Private Sub CopyFunction()
Set m_objExcel = New Excel.Application 'creare obiect
m_objExcel.DisplayAlerts = False
g_secAutomation = m_objExcel.AutomationSecurity
m_objExcel.AutomationSecurity = msoAutomationSecurityForceDisable
m_objExcel.Visible = True
Dim CopyFrom As Workbook
Dim CopyTo As Workbook
Dim CopyThis As Object
Set CopyFrom = m_objExcel.Workbooks.Open("D:\FromFile.xls")
Set CopyTo = m_objExcel.Workbooks.Open("D:\ToFile.xls")
Set CopyThis = CopyFrom.Sheets(1) ''Sheet number 1
CopyThis.Copy After:=CopyTo.Sheets(1)
m_objExcel.Workbooks(CopyTo.FullName).Save
CopyFrom.Close
CopyTo.Close
m_objExcel.Workbooks.Close
MsgBox "ok"
End Sub
I am using it from Access and work with a Excel file.
What is the problem?
Is there a way to still be able to copy a sheet from a workbook to another, and have the macros disabled?
That's what the disable macro is typically for: Security.
It is meant for your own protection; in case you receive a workbook from an unknown author, this person may want to send you harmful software.
Imagine for example that code starts deleting files as soon as you open the workbook.
Disabling macro's prevents this and allows you to look into code before you decide to execute it.
As a solution, the user can trust you as author while you sign your project as developer.
I suggest that you check out this link:
http://msdn.microsoft.com/en-us/library/aa190098(v=office.10)
(You can decide to turn off the security entirely (Enable macro's), but this is generally not recommended.)
I found that the problem is here:
m_objExcel.Workbooks(CopyTo.Name).Save

Resources