Open/Close Workbook in Userform - excel

In a Userform I want to open another workbook (than the active one)
Part of my code:
Private Sub cmbKontoPos1_Change()
Workbooks.Open Filename:=filename1
'Here should of course be some code, but it is not now
Workbooks(filename1).Close SaveChanges:=False
Open-command works.
But the Close-command gives error:
Error no '9'
Index out of bounds
(I get the error-message in Swedish, hope I translate correct)
What is it I do not understand?

Quick fix is to have a global Workbook Variable so you can assign it on Open and use it on other UserForm Events, the example below has two Buttons and one opens while the other one closes the Workbook. Tested and working.
You can see the Dim secondWorkbook outside the UserForm buttons this is to make it global. On the first button I assign the Opened workbook to that Variable and i can close it later.
Dim secondWorkbook As Workbook
Private Sub CommandButton1_Click()
'Open WB
Dim filename1 As String
filename1 = "F:\WorkbookPath\WBName.xlsx"
Set secondWorkbook = Workbooks.Open(filename1)
End Sub
Private Sub CommandButton2_Click()
'Close WB
secondWorkbook.Close False
End Sub
You can also use this variable to make changes to the workbook like: secondWorkbook.Worksheets(1).Range("A1").Value = "Test" as long as it is still open of course.

Related

Is there a possibility to run a macro in an excel-file (data-source) when data connection is refreshed by another excel-file (data-target)?

a lot of users in our network use an excel-workbook (.xlsm [office 2010]) created from a template.
Now, there are some important changes I've to do in the template and I want all the users to update their workbook but i'd like to avoid to contact all of them.
So, my Idea is to make an auto-update (copying the contents of their workbooks into new created workbooks and delete the former version).
Unfortunately there are no update-macros in the existing workbooks but they reference to a macro in another workbook.
Each time they open their workbooks the data connections become refreshed automatically.
Can I use this refreshing event to trigger a macro in the (data-source) excel-file (maybe by creating a WithEvents-class module)?
You can do something along these lines, where the user opens a workbook, but its job is to control the version. You can change this to have the code modify sheets etc.
The text file, correct, contains ver9, the workbook contains ver8 in the ver_cont worksheet.
Function get_version() As String
Open "c:\workspace\test_ver.txt" For Input As #1
Input #1, get_version
Close #1
End Function
Function check_version()
If get_version = Worksheets("Ver_cont").Range("a1") Then
' Open the workbook here
Else
' Copy the workbook
' Then open it
End If
End Function
You can try this. It uses withevents and runs when the data is updated.
First, you need to create a class name "clsQueryTable" and put this code in it
Option Explicit
Public WithEvents QTQueryTable As Excel.QueryTable
Private Sub QTQueryTable_BeforeRefresh(blnCancel As Boolean)
'Set blnCancel to true to stop the refresh
Debug.Print blnCancel
End Sub
Private Sub QTQueryTable_AfterRefresh(ByVal blnSuccess As Boolean)
'blnSuccess can be used to check for refresh success.
' I would put your update code here!
Debug.Print blnSuccess
End Sub
Then, you can put this code in your workbook_open event on ThisWorkbook
Option Explicit
Dim colQueryTables As Collection
Private Sub Workbook_Open()
Dim shtMySheet As Worksheet
Dim clsQT As clsQueryTable
Dim qtMyQuery As QueryTable
Dim loMyList As ListObject
Dim conn As WorkbookConnection
Set colQueryTables = New Collection
For Each shtMySheet In ThisWorkbook.Worksheets
For Each loMyList In shtMySheet.ListObjects
Set clsQT = New clsQueryTable
Set clsQT.QTQueryTable = loMyList.QueryTable
colQueryTables.Add clsQT
Next loMyList
Next shtMySheet
For Each conn In Connections
conn.Refresh
Next
End Sub

VBA - Opening a workbook and remembering it for other macros

I'd like to create a macro that will:
Open a browser window to select a saved workbook (let's call it WB1)
In the same macro assign WB1 some form of reference that will allow it to be referenced by other macros
I can achieve step 1 via the following code:
Sub Add_New_Survey()
Dim pathString As String
Dim resultWorkbook As Workbook
Dim found As Boolean
pathString = Application.GetOpenFilename(fileFilter:="All Files (* . xl*) , *.xl* ")
' check if it's already opened
For Each wb In Workbooks
If InStr(pathString, wb.Name) > 0 Then
Set resultWorkbook = wb
found = True
Exit For
End If
Next wb
If Not found Then
Set resultWorkbook = Workbooks.Open(pathString)
End If
End Sub
This will open the workbook. I then need to perform a number of data preparation activities on WB1 which I would like to automate. Is there a way to reference WB1 as I open it from the browser so the following macros know to look on WB1 specifically?
Many thanks
Welcome to SO. Your object resultWorkbook is linked to Workbooks.Open(pathString), so as long as you dont unlink it with Set resultWorkbook = Nothing, you can reference that workbook always on any sub, (but declare the variable as Public first in the module, outside of all subs).
To declare a Variable as Public, please read:
How do I declare a global variable in VBA?

Excel 2016 VBA workbook activates but then deactivates

I have a weird situation that I haven't been able to find the solution for.
I am dealing with large amounts of data on multiple workbooks that need to be opened (let's say 3 workbooks). I need a Userform to be able to interact with all 3 workbooks.
I have made a ComboBox able to do that by when the userform is initialized, it will add the names of the workbooks to the Combobox:
'* initialize the userform *'
Private Sub UserForm_Initialize()
Dim wb As Workbook
'* get the name of all the workbooks and add to the combobox '*
For Each wb In Application.Workbooks
Me.PrimaryBook_ComboBox.AddItem wb.name
Next wb
Me.PrimaryBook_ComboBox = ActiveWorkbook.name
End Sub
Upon a change, it will activate that workbook:
Private Sub PrimaryBook_ComboBox_Change()
Application.ScreenUpdating = True
Dim wb As Workbook
If Me.PrimaryBook_ComboBox <> "" Then
Set wb = Workbooks(Me.PrimaryBook_ComboBox.Text)
wb.Activate
End If
Application.ScreenUpdating = False
End Sub
(this userform has two refedits in it)
When I select another workbook in the combobox, it brings that workbook to the front as it should. But immediately as I click into one of my RefEdit boxes, it goes back to the original workbook opened first.
Here's another part I don't understand, when I load this in Excel 2010 it's flawless. I can select which workbook I want and click on the RefEdit and that workbook will remain activated.
Is there something I'm missing? Any tips and/or tricks that I did not think of?
Thank you
[delete , posted solution did not fix problem]

Saving a different workbook that is opened

I have a workbook (WorkbookA.xlsm) that I open. Upon being opened, this opens WorkbookB.xlsm.
'ThisWorkbook code of WorkbookA.xlsm
Private Sub Workbook_Open()
Dim wb As Workbook
Application.ScreenUpdating = False
Set wb = Workbooks.Open(Filename:="C:\WorkbookB.xlsm")
wb.Windows(1).Visible = False
End Sub
After "B" being opened, a script is called that also sets off a timer.
The script in B changes some data on A. I want to add something after the script is called to automatically save WorkbookA.xlsm as it is (without any prompts).
'ThisWorkbook code of WorkbookB.xlsm
Private Sub Workbook_Open()
Call Script
'looking for something in here to save WorkbookA
End Sub
Since you know the name of the workbook you want saved ("WorkbookA.xlsx"), you can reference it directly with a save method:
Workbooks("WorkbookA.xlsx").Save
You can use the Workbook.Save method to save your workbook. It'll be something like
wb.Save
or
ActiveWorkbook.Save
if you know that your current workbook is the active one. Save doesn't let you change the filename - if you want that, use SaveAs instead.
Try something similar to this:
For each w in Application.Workbooks
If w.Name = "WorkbookA" Then
w.Save
Exit For
End if
Next w
You need to find the workbook you want or set it prior in your code since you want the save code to be called from workbookB. If you were to call it from workbookA, you could use ActiveWorkbook.Save

Set Workbook Variable from Userform Combobox

I am creating a macro for my co-workers. They get a file daily and at the end of the day have to copy certain information to another workbook. The macro is to take care of the copying. I want to have a userform with a combobox popup that contains a list of current open workbooks so it knows which file to copy from. How do I set it up so that the selection made there sets a workbook variable with that selection?
What I'm trying to do is:
Sub CopySub()
Dim wb As Workbook
UserForm1.Show
Set wb = Workbooks(ComboBox1.Value)
....Rest of Copy and Paste Code
Below is the code for the userform:
Private Sub OK_Click()
'Take user selection and continue copy and paste code
UserForm1.Hide
End Sub
Private Sub Cancel_Click()
'Cancel everything, end all code
End
End Sub
Private Sub UserForm_Activate()
'Populate list box with names of open workbooks.
Dim wb As Workbook
For Each wb In Workbooks
ComboBox1.AddItem wb.Name
Next wb
End Sub
Your code isn't working now because CopySub doesn't know what\where ComboBox1 is. Also, if the user clicks the form's X to close it instead of pressing the cancel button or clicks the OK button without selecting a workbook, CopySub will keep running.
There are a couple different ways to get the form information. The simplest with your current code is to properly reference ComboBox1 and add a simple test.
Sub CopySub()
Dim wb As Workbook
UserForm1.Show
If UserForm1.ComboBox1.Value = "" Then
Exit Sub
End If
Set wb = Workbooks(UserForm1.ComboBox1.Value)
' rest of code goes here
End Sub
Something else to think about though is ways to make your macro quicker and easier to run. If the only thing on your form is a Combobox for selecting the workbook and users will be starting the macro from a keyboard-shortcut or from the menu, consider having the macro ask if they want to run the macro on the active workbook. Clicking Yes to a question is a lot faster than having to click a dropdown box, select the workbook, and then click OK.
Sub CopySub()
Dim wb As Workbook
If MsgBox("Do you want to run the macro on '" & ActiveWorkbook.Name & "'?", vbQuestion + vbYesNo) = vbYes Then
Set wb = ActiveWorkbook
Else
UserForm1.Show
If UserForm1.ComboBox1.Value = "" Then
Exit Sub
End If
Set wb = Workbooks(UserForm1.ComboBox1.Value)
End If
' rest of code goes here
End Sub
After further searching I found the answer, and its the same as what mischab points out, I didn't create a global variable so there was no way for my userform to communicate with the subroutine. I solved this by declaring a variable with scope for the whole workbook as such:
Public wb1 As String
Sub CopySub()
Dim wbCAR As Workbook
UserForm1.Show
Set wbCAR = Workbooks(wb1)
....Rest of code
and by setting the userform code to such:
Private Sub OK_Click()
wb1 = ComboBox1.Value
UserForm1.Hide
End Sub
Private Sub Cancel_Click()
Unload Me
End
End Sub
Private Sub UserForm_Activate()
'Populate list box with names of open workbooks.
Dim wb As Workbook
For Each wb In Workbooks
ComboBox1.AddItem wb.Name
Next wb
End Sub

Resources