I have code in workbook A that opens and does stuff to workbook B. Code runs fine when workbook A and B are the only excel files open (or if workbook A is the only file open). However, if I open up any additional workbook (call it workbook C), the macro does not run correctly. It doesn't cause an error message, it just runs to completion without doing any of the "stuff" it's supposed to do (the stuff is basically finding things in workbook B and pasting them into workbook A).
FWIW, I have done the following simple experiment:
Open all 3 workbooks (A, B, & C)
select workbook C so that it is active and the front window
run the code workbookB.sheet1.activate (this is not verbatim, I know this code as written will fail)
When I do the above test, it doesn't even make workbook B the active workbook. Again, it doesn't cause excel to throw an error message, it just runs and leave workbook C as the active workbook.
Edit: I've tested more, the code below should change the value of a cell in workbook B, but instead is putting the value into workbook C. I am very confused, since workbook C is not referenced in any way (the module is in workbook A)
Sub test()
Dim wb As Workbook
Set wb = Workbooks.Open("U:\workbookB.xlsx")
wb.Worksheets("ED").Range("Z1").Value = "TEST"
End Sub
Edit 2: The issue was occurring when Workbook A and B had been open for several hours, and Workbook C was recently opened. I closed workbook B then re-ran the code and it is working correctly. This leading me to believe that there IS some sort of issue with multiple instances of excel opening. While this is hopefully low-risk, I am still curious if anyone has some way I could code around it as a precaution? Thanks!
There is a subtle bug (I hesitate to call it that, but that's what it looks like) you need to watch out for.
If the workbook you're trying to open via code is already open then occasionally you will see some unexpected behavior (such as the return value from Workbooks.Open() being assigned to ThisWorkbook instead of the file you expect).
For example the code below runs in "Tester.xlsm" and is opening "EmptyTest.xlsx", but if that file is already open, the Workbooks.Open call fails to correctly assign the wb variable, and it ends up pointing at "Tester.xlsm". That can cause problems.
To replicate,
open Excel
open "EmptyTest.xlsx"
open "Tester.xlsm"
run "Tester" sub
Test code:
Sub Tester()
Dim wb As Workbook
'with "EmptyTest" already open
Set wb = Workbooks.Open("C:\Tester\EmptyTest.xlsx")
Debug.Print wb.Name '>> Tester.xlsm - oops!
'close"EmptyTest" before proceeding
Workbooks("EmptyTest.xlsx").Close False
'with "EmptyTest" closed
Set wb = Workbooks.Open("C:\Tester\EmptyTest.xlsx")
Debug.Print wb.Name '>>EmptyTest.xlsx - OK
End Sub
Totally reproducible on my system (win10/Office 365)
I think your problem is that you are opening Workbook B. You state, if you close and re-open it then it works.
Therefore, any changes you have made to Workbook B will be lost as it will re-open the original workbook. (Auto Save does not actually save the workbook, it saves a separate copy.)
You need instead to check if the workbook is already open and only re-open it if it is not currently open.
(Very rough code)
Sub test()
Dim wb As Workbook
For Each wb In ThisWorkbook.Application.Workbooks
If wb.Path & "\" & wb.Name = "U:\workbookB.xlsx" Then Exit For
Next
If wb.Path & "\" & wb.Name <> "U:\workbookB.xlsx" Then Set wb = ThisWorkbook.Application.Workbooks.Open("U:\workbookB.xlsx")
wb.Worksheets("ED").Range("Z1").Value = "TEST"
End Sub
But (as others have said) you should really check that there are no other instances of Excel running and account for them also.
Related
I have created an Excel workbook that uses Userforms as a Menu for users, meaning that they don't interact with the workbook itself. Usually, this is opened by double click with works perfectly.
Now, I would like to open this file from another excel file and to prevent users from being locked into the target workbook (since the userform is modal), I am opening it in a new instance.
I have looked into various methods (among them https://www.mrexcel.com/forum/excel-questions/570562-vba-open-another-instant-excel-run-macro.html), where I found code that seems to be working and also starts the Auto_Open-code (previous attempts opened the file but did not start the code) BUT since the target file has application-closing-code integrated (due to also being opened via double click), it gives me a runtime error (440) upon closing the target workbook since I believe that the Application.Quit-command is interrupting the Run-command and causing the error.
I also found someone with a similar problem (between access and excel but I believe its basically the same thing for this case) at https://access-programmers.co.uk/forums/showthread.php?t=153101 but the suggestion of putting the closing code into the calling file does not work for me, since the target file gets opened independent from the calling file half the time.
Is there any way around this or maybe another method to open the target workbook from another excel workbook and also run the code after opening?
Also, if that is an option, maybe there is a way to always open the target file (no matter the source) in a new instance that does not involve administrator rights at all (because I don't have any)?
The relevant code pieces are as follows:
Source file (opening the target file):
Dim aExcel As Application
Dim wbTarget As Workbook
Dim sReturn As String
Dim sArg As String
Dim sFile As String
' File to be opened
sFile = "C:\file.xlsm"
' Neue Instance
Set aExcel = New Application
With aExcel
.Visible = True
' WB-Reference for opening of WB
Set wbTarget = aExcel.Workbooks.Open(sFile)
sArg = "'" & wbTarget.Name & "'!ModPublic.Auto_Open"
' Run Code within Targetfile (bc code does not start otherwise)
aExcel.Run sArg
' Not reached due to runtime error:
'aExcel.Quit
End With
Target File (gets open via auto_open and does its thing - afterwards gets closed via [x] on the userform):
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
' [x] is clicked (CloseMode = 0)
If CloseMode <> 1 Then
' deactivate Cancel
Cancel = 1
' 1 wb is open, save file and quit application
If Application.Workbooks.Count = 1 Then
ActiveWorkbook.Saved = True
Application.Quit
' more than 1 is open, save file and close wb
Else
ActiveWorkbook.Close SaveChanges:=True
End If
End If
End Sub
Maybe a bit of a workaround, but can you create a global variable in the target workbook, which specifies that the workbook is actually opened from the source workbook? And then use the global variable in the QueryClose sub with an if statement around Application.Quit?
We have 2 different files with basic vlookup infos:
Source file is: JP2-CSV CRAWLER
Destination file is: JP2-CATEGORIES
We are trying to copy one full column from the Source file to the first column of the destination file automatically ( It should work when opening it or using it)
That's our code:
Sub Copysubcat()
Dim wbSource As Workbook
Dim wbDestination As Workbook
Set wbSource = Workbooks.Open( _
Filename:="C:\Users\user\Desktop\crawler file\JP2-CSV CRAWLER.xlsx")
Set wbDestination = Workbooks("C:\Users\user\Desktop\crawler file\JP2-CATEGORIES.xlsx")
wbSource.Sheets("CSV Crawler").Range("P2:P10000").Copy
wbDestination.Sheets("Cats & Subcats").Range("A2:A10000").PasteSpecial (xlPasteValues)
Application.CutCopyMode = False
ActiveWorkbook.Save
End Sub
We are having an error "Subscript out of range"
Anybody could help on that?
Workbooks isn't a method, so it cannot take any parameters. This is class, which represents workbooks, which contains methods to handle them. One of them is Open which you will need in this case. So you'll need to switch this:
Set wbDestination = Workbooks("C:\Users\user\Desktop\crawler file\JP2-CATEGORIES.xlsx")
to this:
Set wbDestination = Workbooks.Open("C:\Users\user\Desktop\crawler file\JP2-CATEGORIES.xlsx")
Also, there is an event such as opening the workbook, you can place your corrected code there, so the macro would run every time this event is raised (i.e. on every opening). If you are using standard VBA development environment in Excel, click on This_workbook on right side (in tree view), you will have to dropdown lists at the top, in the one on the left choose Workbook, in the other one select Open (this is list of events, that is raised by Workbook). Then, inside generated method place youre code :)
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
Good day all:
I'm trying to use a ActiveX command button to copy excel worksheets into another file. Here's the background:
I have excel log sheets that are being filled up every day. The logs have a set criterion (A, B, C, etc.) being run daily. While we still want to keep the logs in a daily file, I want a command button to be able to export to another workbook as a master file (e.g. "A_Masterfile", "B_Masterfile", etc.).
I've tried researching, but all these requirements come from different sites/pages. But since the method they use are so different, I'm having a hard time trying to get all Syntax to fit so that one code can do everything.
As a rundown, here's what I want it to do:
Export active worksheet to another workbook
a) If workbook exists, copy sheet to end of workbook
b) If workbook does not exist, create workbook and copy sheet
Destination workbook is based on a cell (criterion A, B, etc.)
Destination workbook might be in a different folder as source worksheet/workbook
Based on what I'm researching so far, this is what I'm turning up with.
When simply copying, this is what I read, but I could not get it to work.
ActiveSheet.Copy After:=Workbooks("Destination.xlsx").Worksheets(Worksheets.Count)
For Creating New File, this is what I read, but even from the original site, they said the problem was it copies the whole workbook, not just one specific sheet.
ActiveWorkbook.SaveAs "C:\path\Destination.xlsx"
Finally, I read about concatenation to create "Destination" file name based on a cell value. However, I got so lost with all the syntax. I tried simply copy pasting but I couldn't get it to work.
This is quite a bit to ask. Thanks so much in advance for all your help!
Please let me know if I can clarify anything.
P.S. Extra note: I've done some QBasic and MATLAB and a tiny bit of JAVA programming in school, so I got the logic part down. But I am quite new to VBA syntax, so extra information would be appreciated. :)
Update:
I just learned about "Record Macro" and I tried using it
I got this from it and it works:
Sheets("SourceSheet").Select
ActiveSheet.CheckBoxes.Add(639, 30, 58.8, 16.8).Select
ActiveSheet.CheckBoxes.Add(639.6, 44.4, 58.8, 16.8).Select
ActiveSheet.CheckBoxes.Add(639.6, 61.2, 58.8, 16.8).Select
ActiveSheet.OptionButtons.Add(1279.8, 37.8, 20.4, 18).Select
ActiveSheet.OptionButtons.Add(1280.4, 57, 21.6, 17.4).Select
Sheets("SourceSheet").Copy After:=Workbooks("DestinationMasterFile.xlsx").Sheets(1)
Windows("SourceWorkBook.xlsm").Activate
It works, but only put it after the first sheet instead of putting it in the end. I know it comes from the .Sheets(1), but I don't know how to write it otherwise. Thanks.
I have done a lot more research and trial and error, and I came up with a working code. This might be messy, but it works. Any further improvements are appreciated.
Private Sub CommandButton1_Click()
'Code for Locking
Sheets("W").Unprotect
Range("A1:BZ125").Locked = True
Sheets("W").Protect Password:="hello"
'Code for Copying
'Declarations
Dim Wk As Workbook
Dim FName As String
Dim FNameTwo As String
Dim FilePath As String
Dim TestStr As String
Dim wb As Workbook
'Initializing Constants
Set wb = ThisWorkbook
FName = "C:\Users\PHReyesDa\Desktop\" & Range("BO1") & ".xlsx"
FNameTwo = Range("BO1") + ".xlsx"
'If statement Setup (if exist)
FilePath = FName
TestStr = ""
On Error Resume Next
TestStr = Dir(FilePath)
On Error GoTo 0
'If statement
If TestStr = "" Then
'If not existing, create new file
MsgBox "File didn't exist yet; new file created"
Set Wk = Workbooks.Add
Application.DisplayAlerts = False
Wk.SaveAs Filename:=FName
Application.DisplayAlerts = True
Workbooks(FNameTwo).Close SaveChanges:=True
End If
'Reopens Master File
Workbooks.Open FName
wb.Activate
'Find number of worksheets in destination workbook to worksheet could be copied to end of workbook
Dim Num As Integer
Num = Workbooks(FNameTwo).Worksheets.Count
'Copy source worksheet to (the end of) destination workbook
Sheets("W").Select
Sheets("W").Copy After:=Workbooks(FNameTwo).Worksheets(Num)
'Close and save new workbook, confirmation of successful copy
Workbooks(FNameTwo).Close SaveChanges:=True
MsgBox "Worksheet successfully exported and saved to master file"
End Sub
I have a directory with list of Workbooks, I want to loop through them withouth opening them and update a Cell in a certain Sheet
I have tried to use
Dim wb As Workbook
Set wb = Workbooks("Z:\dir\bla.xls") 'THIS WILL COME TRHOUGH WHEN I LOOP
Set ws2 = wb.Sheets("TestSheet") 'SHEET NAME
Set CurCell_2 = ws2.Range("A1")
CurCell_2.Value = 5
The Problem comes it only works when I have the Workbook already open. I can use:
Workbooks.Open
But then It opens up in the background and takes to long to run through them all.
Can anyone help please
You cannot do that without opening the workbooks. However, I have found in my case that using Application.EnableEvents and setting it to false sped up greatly the process because we have macros on workbook open event.