I'm facing a problem that I really don't understand.
I created a macro that opens a workbooks, reads some information in it, and closes it.
To open the workbook, I use these lines:
Path = Func_Use_File_DialogOpen()
If Path <> "" Then
Set wb_chosen = Application.Workbooks.Open(Path, UpdateLinks:=0)
ElseIf Path = "" Then
MsgBox ("Error, start again")
Exit Sub
End If
For your information, the variable Path contains the whole path of the file, with the extension.
Example: Path= C:\Users\alex\Desktop\file.xlsm
On my computer, the macro works perfectly, it opens the worbook, and I can use it with my variable called wb_chosen
But when I send my macro to a coworker, he gets the error
"RUNTIME ERROR 91: Object variable or With Block variable not set"
How is that possible? when I try to debug the macro on his computer, I see that the variable path is perfectly fine (like on my computer), but the variable wb_chosen is nothing
so the problem is on the line :
Set wb_chosen = Application.Workbooks.Open(Path, UpdateLinks:=0)
Could it be the Application.Workbooks that doesn't work?
I really need this macro to work on every computer, is there a parameter to change on Excel? should I just put this instead?
Workbooks.Open(Path)
FYI, here are some other details about the code
The workbook is declared like this
Public wb_chosen As Workbook
the function Func_Use_File_DialogOpen() is as follow:
Public Function Func_Use_File_DialogOpen() As String
On Error GoTo lblErr
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Show
Func_Use_File_DialogOpen = .SelectedItems(1)
End With
Exit Function
lblErr:
MsgBox Err.Description, vbCritical, "Error"
Func_Use_File_DialogOpen = vbNullString
End Function
The variable Path is a string that store the full path of the file. When I run the code on my computer, i have
Path=\\cm\TA\PNL\10 - octobre\pnl_Octobre.xlsm
Related
I have a VBA script in Excel which works fine but when saved as script_name.vbs and executed in cmd/powershell as cscript.exe script_name.vbs it throws the error:
dir_path\script_name.vbs(30, 37) Microsoft VBScript compilation error: Expected ')'
Firstly I apologise. This seems like a well-worn question but no answer I could find explains any reasons why my particular VBA script won't work.
I learnt that you cannot Dim As when running vbs on the cmd line so I removed that, and then got the above error. No question I found seems to indicate to me as to why.
Help much appreciated!
Thanks
FYI: The macro is to iterate through all files which have passwords in a folder and
Attempt a number of any possible passwords to open the file
Same again for workbook protection passwords
Unhide all worksheets
Save the file
Move onto the next file
Sub BAUProcessVBA()
Dim wb
Dim ws
Dim myPath
Dim myFile
Dim myExtension
Dim i
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
myPath = "C:\blah\dir\"
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Do While myFile <> ""
'Set variable equal to opened workbook
Debug.Print myFile
On Error Resume Next
Set wb = Workbooks.Open(Filename:=myPath & myFile, Password:="pw1", IgnoreReadOnlyRecommended:=True, ReadOnly:=False)
Set wb = Workbooks.Open(Filename:=myPath & myFile, Password:="pw2", IgnoreReadOnlyRecommended:=True, ReadOnly:=False)
On Error GoTo 0
'Ensure Workbook has opened before moving on to next line of code
DoEvents
'Remove workbook protection and, unhide all tabs, save the file
On Error Resume Next
wb.Unprotect "pw1"
wb.Unprotect "pw2"
On Error GoTo 0
On Error Resume Next
wb.Password = ""
On Error GoTo 0
For Each ws In wb.Worksheets
ws.Visible = xlSheetVisible
Next ws
'Save and Close Workbook
Application.CutCopyMode = False
wb.Close SaveChanges:=True
Application.EnableEvents = False
'Ensure Workbook has closed before moving on to next line of code
DoEvents
'Get next file name
myFile = Dir
Loop
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
You seem under the impression that Visual Basic for Applications vba and Visual Basic Script vbscript are identical languages. That is not the case. They may be more closely related than Visual Basic .Net vb.net and VBA or VBS, but they are still different languages.
Which is why we have different tags for all of them.
Now, to tackle your question:
VBA has got the Microsoft Office Object Library reference, which means native support for office objects.
Application doesn't exist in vbs, so you need to create that object: Set Application = WScript.CreateObject("Excel.Application")
Excel constants don't exist:
xlCalculationManual = -4135, xlCalculationAutomatic = -4105 and xlSheetVisible = -1
Dir doesn't exist, so you need to create a FileSystemObject
Named arguments don't exist, so you need commas:
Set wb = app.Workbooks.Open(myPath & myFile, , False, , "pw1", , True)
And DoEvents doesn't exist either.
To solve this problem I have used Python to open Excel and execute the Macro I want. Below is a function that should work for anyone.
Things I have learnt: If you have VBA code in Excel and want to run it without Excel then you cannot just save this as a .vbs and execute it on the command line with cscript.exe.
VBS and VBA are different languages.
Therefore, a quick tutorial for those stuck at the same problem but are unfamiliar with Python:
Download and install Python ensuring python is added to PATH. This script was written and successfully executed with Python 3.8 64-bit for Windows. https://www.python.org/downloads/
Save the below in a file called run_macro.py
On the last line of run_macro.py, with no indentation, type what is below within Code2
Carrying on with Code2: Inside of the quotes 'like this' type in what it's asking for. The filepath_incl_filename must contain the full path AND the filename whereas filename must contain ONLY the filename. Yes, it must be provided like this.
Copy the filepath where run_macro.py is located and press win+r and type 'cmd' to open the cmd terminal, then type cd <filepath from clipboard> and press enter
Now type python run_macro.py
So long as you get no errors and it appears to "freeze" then that means it's working. Otherwise, you will need to debug the errors.
Code:
import win32com.client as wincl
def run_excel_macro(filepath_incl_filename=r'raw_filepath', filename='', module_name='', macro_name=''):
"""
:param filepath_incl_filename: Must be r'' filepath to dir with filename but also include the filename in the filepath (c:\etc\folder\wb_with_macro.xlsm)
:param filename: Filename of xlsm with the Macro (wb_with_macro.xlsm)
:param module_name: Found inside 'Modules' of macros within that workbook
:param macro_name: The 'sub name_here()' means macro is called 'name_here'
:return: Nothing. Executes the Macro.
"""
# script taken from: https://stackoverflow.com/questions/19616205/running-an-excel-macro-via-python
# DispatchEx is required in the newest versions of Python.
excel_macro = wincl.DispatchEx("Excel.application")
workbook = excel_macro.Workbooks.Open(Filename=filepath_incl_filename, ReadOnly=1)
excel_macro.Application.Run(f"{filename}!{module_name}.{macro_name}")
# Save the results in case you have generated data
workbook.Save()
excel_macro.Application.Quit()
del excel_macro
Code2
run_excel_macro(
filepath_incl_filename=r'',
filename='',
module_name='',
macro_name=''
)
I have a workbook that is password protected and I’d like to create a read only copy that other users can view on a different location on the network drive.
I know it’s a strange request as the other people could open the original as read only, but we don’t want them to know the location of the original or have anything to do with it, should they figure out my colleagues password.
The other issue we had was that people were opening as read only and it was still telling my colleague that it was locked by another user and he needs it for most of the day so that issue is annoying
Thanks in advance
What you could do is add the following event procedure to the ThisWorkbook module:
Const RemotePath As String = "D:\YourRemoteLocation\"
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
On Error GoTo CleanUp
If Success And InStr(ThisWorkbook.Name, "Copy of ") = 0 Then
Dim CopyFullName As String
CopyFullName = RemotePath & "Copy of " & ThisWorkbook.Name
Application.EnableEvents = False
Dim fso As FileSystemObject 'Requires the Microsoft Scripting Runtime Library
Set fso = New FileSystemObject
fso.CopyFile Source:=ThisWorkbook.FullName, Destination:=CopyFullName
Dim ReadOnlyWorkbook As Workbook
Set ReadOnlyWorkbook = Workbooks.Open(Filename:=CopyFullName)
Application.DisplayAlerts = False
ReadOnlyWorkbook.SaveAs Filename:=CopyFullName, Password:=""
Application.DisplayAlerts = True
ReadOnlyWorkbook.Close SaveChanges:=False
End If
CleanUp:
Application.EnableEvents = True
Application.DisplayAlerts = True
Set fso = Nothing
End Sub
This code will run every time the workbook is saved and export the current file to the remote location. Then it will open the copy and save it as a workbook without password.
Note that I've added InStr(ThisWorkbook.Name, "Copy of ") = 0 as a condition to the If-statement. Instr returns the position where a substring (arg2) appears in the main string (arg1) or zero if the substring is absent from the main string. In this context, we want it to be zero since we don't want to run the code in the workbook copy.
In this method, the owner of the original file will have to supply their password every time they save. You could automate this by passing the password as an argument to the Open method like this:
Set ReadOnlyWorkbook = Workbooks.Open( _
Filename:=CopyFullName, _
Password:="MyPassword")
However, the password would then be accessible by people looking into the VBA code.
Alternatively you could get the password from a local file that wouldn't be accessible from the Network, but then the file path would be visible.
And if the remote folder is not already set to be Read-only mode, you can make sure that people opening the remote version of the file do so in Read-Only mode by adding the following event procedure after the previous one.
Private Sub Workbook_Open()
If InStr(ThisWorkbook.Name, "Copy of ") = 0 Then
ThisWorkbook.ChangeFileAccess Mode:=xlReadOnly
End If
End Sub
Obviously this will only work if they enable macros.
When running the below VBA script, macro checkin, I am getting the error 'Method or Data Member Not Found. Can someone please help identify the issue?
Sub checkin()
Dim docCheckIn As String
docCheckIn = "File Location and Name"
Call UseCheckIn(docCheckIn)
End Sub
Sub UseCheckIn(docCheckIn As String)
docCheckIn = "File Location and Name"
' Determine if workbook can be checked in.
If Workbooks.CanCheckIn(docCheckIn) = True Then
Workbooks.checkin docCheckIn
Else
MsgBox "Unable to check in this document at this time."
End If
End Sub
Looks like Workbooks.CanCheckIn(docCheckIn) = True is the problem. What are you trying to achieve? What's CanCheckIn meant to be?
/edit:
Workbooks(docCheckIn).CanCheckIn will work but the docCheckIn must be a workbook name, not full path. Alternatively set the workbook as object using your docCheckIn path and use WbObj.CanCheckIn
/edit2:
bear in mind that the Workbooks.checkin docCheckIn will have to be changed the same way to either Workbooks("workbookname.xls").checkin or WbObj.checkin
To set workbook object:
Set WbObj = Workbooks("workbookname.xls") 'if it's open
Set WbObj = Workbooks.Open(docCheckIn) 'if it isn't open
Goal: Use open function to allow user to run commands on whichever file they choose to open across multiple functions(path is in a public function).
This is the initial function that prompts the user to select a file. That file path is saved in the variable "path". I made the function public with the intention of using "path" in multiple areas(globalization).
Public Function OpenFile1() As String
On Error GoTo Trap
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.Title = "Open Sterling Shipment History" 'Name for file
.Filters.Clear
.ButtonName = " Open "
.AllowMultiSelect = False
End With
If fd.Show <> 0 Then OpenFile1 = fd.SelectedItems(1)
Leave:
Set fd = Nothing
On Error GoTo 0
Exit Function
Trap:
MsgBox Err.Description, vbCritical
Resume Leave
Dim path As String
path = OpenFile1() 'Calls in file
If path <> vbNullString Then Debug.Print path
Workbooks.Open (path)
'rename the path variable for each function
'so that I can call in different files with that name
End Function
This is an excerpt of the second function that attempts to call the file path from the variable "path", use it to open the workbook and alter the workbook.
Sub Shipment_History()
Call OpenFile1
Dim sshist As Workbook
Set sshist = Workbooks.Open(path)
Columns("E:E").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
I also tried:
Sub Shipment_History()
Call OpenFile1
Workbooks.Open(path)
My issue is it isn't allowing me to open "path".
The error states
"Run-time error '1004': Sorry, we couldn't find. Is it possible it was
moved, renamed or deleted?"
Since the function returns a string (path) and it is publicly available, you dont need a public variable to store the path.
Declare the path variable locally and set it's value to the value (path) returned from the function:
Sub Shipment_History()
Dim path as string
path = OpenFile1()
If path <> vbNullString Then Workbooks.Open(path)
End Sub
p.s. Remove everything after Resume Leave except the End Function statement.
path must be declared outside any Function or Subscript as a public String, the function doesnt need to be public, its the variable.
Try this on a module:
Public path As String
Function setPathValue(ByVal dataPassed As String)
path = dataPassed
End Function
Sub givePathVal()
setPathValue ("This is path value")
End Sub
Sub showPathVal()
MsgBox path
End Sub
I'm stuck. I'm running an array to open selected files, which do open, but once I begin to attempt to add processing code I can't seem to activate the sheets I want. I try and debug on strShName and the variable never gets populated, always null, but the variable ExpRptFileName(N) does get populated with the full path and file name.ext.
I'm wondering if the path should be removed (which I've tried with several variations but it fails) or if the type of loop I'm using is hanging me up.
In the following code, the variable ExpRptID is null; doesn't pull the data from the sheet......while the variable ExpRptFileName(N) contains the proper path, file name, and file ext.
Here's the code:
ExpRptFileNameInLoop = Right(ExpRptFileName(N), Len(ExpRptFileName(N)) - InStrRev(ExpRptFileName(N), Application.PathSeparator, , 1))
If bIsBookOpen(ExpRptFileNameInLoop) = False Then
Set mybook = Nothing
On Error Resume Next
Set mybook = Workbooks.Open(ExpRptFileName(N))
On Error GoTo 0
If Not mybook Is Nothing Then
Workbooks.Open ExpRptFileName(N)
Dim ExpRptID As String
ExpRptID = Sheets("Expense Report").Range("R3").Value
Exit Sub
Function bIsBookOpen(ByRef szBookName As String) As Boolean
' ************** Notes here
On Error Resume Next
bIsBookOpen = Not (Application.Workbooks(szBookName) Is Nothing)
End Function