Using other workbook without opening it - vba

I created Excel macro, in which I'm searching current date in other, closed workbook and getting the number of the row where this date is. Everything works perfectly, but only if I'm opening this other workbook.
Is there a possibility to make the code works without opening this workbook? Or maybe it's possible to make this workbook not to appear, because I don't want it to appear on the screen?
I've tried many methods, e.g. Application.ScreenUpdating = false or ActiveWorkbook.Windows(1).Visible = False but it doesn't work the way I want it.

You need to create a new Excel Application to be able to hide the Window:
Dim xlApp As New Excel.Application 'New Excel Application
Dim xlWB As Excel.Workbook 'Workbook Object
xlApp.Visible = False 'Hide Application
Set xlWB = xlApp.Workbooks.Open("PATH TO FILE") 'Open File in new App
'do something here
xlWB.Sheets(1).Cells(1, 1).Value = "Hello, this is a Test"
xlWB.Close 'Close Workbook (Use SaveChanges:=True to save changes)
Set xlWB = Nothing 'Clear Object
xlApp.Quit 'Quit Excel App
Set xlApp = Nothing 'Clear Object

Related

Opening workbook from file and updating link in original workbook

I'm trying to write a macro in VBA, that will open another Workbook using a PathFile specified in a cell (this works), updates link in workbook in which macro is used (doesn't work) and closes the PathFile workbook (works)
This is a code:
Sub UpdateRaw()
Dim CurrWb As Workbook
Dim FilePath As String
Dim book As Excel.Workbook
Set CurrWb = ActiveWorkbook
FilePath = Range("I1").Value
Dim app As New Excel.Application
app.Visible = True 'so we can see whether correct file is being opened
Set book = app.Workbooks.Open(FilePath)
CurrWb.Activate
Worksheets("Raw_vs_Actual").EnableCalculation = False
Worksheets("Raw_vs_Actual").EnableCalculation = True
book.Close SaveChanges:=False
app.Quit
Set app = Nothing
End Sub
Going step by step I found that command CurrWb.Activate doesn't take me back to my original Workfile. My suspicion is that by opening new Excel Application I can't get back to the CurrWb (ActiveWorkbook). Is there a workaround? I need this so my INDIRECT function doesn't return #REF.
I'm using Excel 2010 in case it's important.
I think Set book = app.Workbooks.Open(FilePath) shall be enough, but if not refresh the workbook:
book.RefreshAll
for opened workbook. For the workbook that contains the macro, use
ThisWorkbook.RefreshAll

Run a macro using VBS on already opened excel

I would like to run a macro on an Excel using VBS code. My Excel will be always open. I am using below code for that.
Excel: main.xlsm, macro name: Inc
Option Explicit
Dim xlApp, xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("E:\Main.xlsm", 0, False)
xlApp.Run "Inc"
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
WScript.Quit
The problem is whenever I run the code, it looks like the Excel trying to open in read only mode. As soon as the VBS runs, I am getting "save changes window" and saving the sheet as a copy.
I would like to save the changes on the same sheet rather than saving it as a new copy.
Excel lets you save a copy because you create a new instance of Application object, so you open the workbook again in read-only mode. To get a reference to Application object of the particular running instance of Excel with already opened workbook you should use the following lines:
Set xlBook = GetObject("E:\Main.xlsm")
Set xlApp = xlBook.Application
instead of
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("E:\Main.xlsm", 0, False)
Then you just need to save that workbook with .Save.
You are creating a new Instance with Set xlApp = CreateObject("Excel.Application"), also the WB is then opened twice. Easiest fix, if you just close the WB before executing your code, then it should work fine. Also when closing use xlBook.Close SaveChanges:=True, no prompt should appear then.

Deleting empty worksheets

I'm trying to write a code to delete empty worksheets in a workbook. So far I have been able to delete worksheets starting at the highest to the lowest using the code:
Dim i As Integer
Dim objExcel As Object = CreateObject("Excel.Application")
objExcel.Visible = True
objExcel.DisplayAlerts = False
Dim objWorkbook As Excel.Workbook = objExcel.Workbooks.Open(TextBox1.Text)
i = objWorkbook.Worksheets.Count
Do Until i = 2
objWorkbook.Worksheets(1).Delete()
i = i - 1
Loop
I had a look on the internet, but didn't find something that can be useful. Can anyone help me by guiding me to the right direction where I can obtain information on how to detect for empty worksheets in a single workbook using VB.net only.
Thank You
This should do the trick in vb.net
Private Sub DeleteBlankWorksheets(xlWorkBook As Excel.Workbook)
For i As Integer = xlWorkBook.Worksheets.Count To 1 Step -1
Dim ws As Excel.Worksheet = CType(xlWorkBook.Worksheets(i), Excel.Worksheet)
If Convert.ToInt64(ws.UsedRange.CountLarge) <= 1 Then
ws.Delete()
End If
Next
End Sub
Replace your entire loop with a call to this function, passing your objWorkBook object as the parameter.
Dim objExcel As Object = CreateObject("Excel.Application")
objExcel.Visible = True
objExcel.DisplayAlerts = False
Dim objWorkbook As Excel.Workbook = objExcel.Workbooks.Open(TextBox1.Text)
DeleteBlankWorksheets(objWorkbook)
'Add this to save the file
objWorkbook.Save()
objWorkbook.Close() 'closes the files
'If you have trouble with the file object being still opened, meaning you can see the EXCEL.exe in the task manager then add the following code
For Each instance As Process In Process.GetProcesses
If InStr(instance.MainWindowTitle, Textbox1.Text) <> 0 Then p.Kill()
Next
NOTE: It is better to make sure to dispose of all of your excel objects (applications, workbooks, worksheets, etc) than to kill processes. This will ensure all data is preserved as intended without side effects. If you find you have extra excel.exe instances running, make sure to double check everything is disposed and released properly.
This will do the job
Sub DeleteBlankWs()
Dim ws As Worksheet
For Each ws In Worksheets
If WorksheetFunction.CountA(ws.Cells) = 0 Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
Next ws
End Sub
I created an excel with 5 sheets, sheet 2 and 4 are empty, then I edited a micro and run it (F5 key or the green play icon)...

Powerpoint VBA to update links on excel files open by someone else without alerts

I have a powerpoint presentation that links to multiple large excel spreasheets. I want to update the links so my presentation as a whole is updated. However, I if click in Update All Link, my powerpoint crashes, probably because the linked excel files are large. So I would have to update manually each link so it will not crash.
This macro below will loop each linked object and update its link, however, if the file is currently open, it will pop a alert if I want to cancel, open read only or notify. The display alerts set to false will do nothing against it.
Sub linkupdate()
Application.DisplayAlerts = False
Dim osld As Slide
Dim oshp As Shape
For Each osld In ActivePresentation.Slides
osld.Select
For Each oshp In osld.Shapes
If oshp.Type = msoLinkedOLEObject Then
oshp.Select
oshp.LinkFormat.Update
End If
Next oshp
Next osld
Application.DisplayAlerts = True
End Sub
I have found that powerpoint opens an invisible excel aplication underneath it to update the links, however I could not grab this open instance with my vba and tell it to open the links readonly .
I want however for this do not happen if the file is open by someone else, but however I want it to automatically open the file for update as read-only.
Looking at your code, I am assuming all of this is being done from within the PowerPoint VBA editor. With that being said, let me explain why you're getting the Pop-up from the Excel application. When you wrote this line of code:
Application.DisplayAlerts = False
You're referring to the PowerPoint application, what you're meaning to do is to refer to the Excel application because I am assuming that the popup is happening there. In order to fix this, we need to create a reference to the Excel application. If I add the following code we can turn off the displays for the Excel application:
'Declare Excel Variables
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
'Create a new Excel Application, make it invisible, set the Excel Display alerts to False.
Set xlApp = New Excel.Application
xlApp.Visible = False
xlApp.DisplayAlerts = False
So now that we've handled the pop-up let's fix your link issue. To fix the link issue, we are going to open the Excel workbook that the link is referring to in the background. This way updating the links goes faster. If we don't open the workbook, I have had an instance where the update link process can easily take over 5 minutes.
However, to get the correct file name can be a little challenging if the object is a linked chart for example. We need to parse the file so that way it removes the worksheet name and the chart name. Here is how we do that:
'Get the Source File of the shape.
SourceFile = PPTShape.LinkFormat.SourceFullName
'We may need to parse the Source file because if it's linked to a chart, for example, we can get the following:
'C:\Users\NAME\ExcelBook.xlsx!Chart_One!
'We want it to look like the following:
'C:\Users\NAME\ExcelBook.xlsx
'This will parse the source file so that it only includes the file name.
Position = InStr(1, SourceFile, "!", vbTextCompare)
FileName = Left(SourceFile, Position - 1)
Next, we want to open the workbook, update the link, and then close the workbook. So we will add this section of code:
'This will open the file as read-only, and will not update the links in the Excel file.
Set xlWorkBook = xlApp.Workbooks.Open(FileName, False, True)
'Update the link
PPTShape.LinkFormat.Update
'Close the workbook and release it from memory.
xlWorkBook.Close
Set xlWorkBook = Nothing
Altogether here is how your code will look in order to update the links of all the different linked OLEObjects.
Sub UpdateLink()
'Declare PowerPoint Variables
Dim PPTSlide As Slide
Dim PPTShape As Shape
'Declare Excel Variables
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
'Create a new Excel Application, make it invisible, set the Excel Display alerts to False.
Set xlApp = New Excel.Application
xlApp.Visible = False
xlApp.DisplayAlerts = False
'Loop through each slide in the Presentation.
For Each PPTSlide In ActivePresentation.Slides
'Loop through Each Shape in the slide
For Each PPTShape In PPTSlide.Shapes
'If the Shape is a linked OLEObject.
If PPTShape.Type = msoLinkedOLEObject Then
'Get the Source File of the shape.
SourceFile = PPTShape.LinkFormat.SourceFullName
'We may need to parse the Source file because if it's linked to a chart, for example, we can get the following:
'C:\Users\NAME\ExcelBook.xlsx!Chart_One!
'We want it to look like the following:
'C:\Users\NAME\ExcelBook.xlsx
'This will parse the source file so that it only includes the file name.
Position = InStr(1, SourceFile, "!", vbTextCompare)
FileName = Left(SourceFile, Position - 1)
'This will open the file as read-only, and will not update the links in the Excel file.
Set xlWorkBook = xlApp.Workbooks.Open(FileName, False, True)
'Update the link
PPTShape.LinkFormat.Update
'Close the workbook and release it from memory.
xlWorkBook.Close
Set xlWorkBook = Nothing
End If
Next PPTShape
Next PPTSlide
'Close the Excel App & release it from memory
xlApp.Quit
Set xlApp = Nothing
End Sub
Also be careful when you paste objects into the PowerPoint slide, if you're using VBA to achieve this sometimes it can paste the link information incorrectly! When you go to update links nothing will change because the link is not correct and isn't actually referencing the item you want to update.

Workbooks.Open returns different file than Filename

I am having the strangest problem. I was writing the below code on my laptop the other day and it worked fine. Now, I am testing it on my desktop and it's stopped working.
First, here's my code
Dim oApp As Application
Dim oWb As Workbook
Set oApp = New Application
oApp.Visible = True
Set oWb = oApp.Workbooks.Open(Filename:="C:\myFile.xlsx", ReadOnly:=True)
debug.print oWb.name
'returns "SOLVER.XLAM"
' "SOLVER.XLAM" is not "myFile.xlsx'
debug.print oApp.Workbooks.Count
'returns 1
debug.print oApp.Workbooks(1).name
'returns "myFile.xlsx"
Now, I know that solver is an add in, and it gets loaded in the new application upon creating it... but how does it perform this switcheroo? I can still get to the correct file, but I don't want to risk it on the coincidence that there is only 1 file in my Application object (or that the first file is the one I loaded)
Additional Info
I am calling executing this macro from within an excel instance and I wish to open a separate excel instance and then open particular workbook ("C:\myFile.xlsx") inside that other instance.
The key problem I'm having is that when I open the other instance and then add the workbook and set it to my oWb variable... somehow, when I later call that oWb variable it refers to something different from what I had set it to.
'This is how it makes me feel:
Dim x As Integer
x = 5
Debug.Print x
' 12
I think if you just refine your code a bit to ensure you are doing exactly what you want, you will be fine. Since it's unclear whether you are calling the code from within Excel or another MS Office Application, I placed to subs below.
Run this if running it in Excel:
Option Explicit
Sub insideXL()
Dim oWb As Workbook
Set oWb = Workbooks.Open("C:\myFile.xlsx", ReadOnly:=True)
Debug.Print oWb.Name
Debug.Print Workbooks.Count
Debug.Print Workbooks(1).Name
oWb.Close false
Set oWb = Nothing
End Sub
Run this if running in another program. I use early binding, but you could use late binding as well, if you wish:
Sub outsideXL()
'make sure Microsoft Excel X.X Object Library is checked in Tools > References
Dim oApp As Excel.Application
Set oApp = New Excel.Application
Dim oWb As Excel.Workbook
Set oWb = oApp.Workbooks.Open("C:\myFile.xlsx", ReadOnly:=True)
oApp.Visible = True
Debug.Print oWb.Name
Debug.Print Workbooks.Count
Debug.Print Workbooks(1).Name
oWb.Close = True
Set oWb = Nothing
Set oApp = Nothing
End Sub
I found that this (which worked in 2007):
wb = excel.Workbooks.Open(filename, False, True)
needs to be written
excel.Workbooks.Open(filename, False, True)
wb = excel.ActiveWorkbook
for 2010