I'm currently trying to create a Print Button on one of my worksheets. I need it to print that worksheet as well as another one. Both of the names are "Budget Sheet" and "Listed Commitments Sheet" without the quotation marks.
I created the button without hassle, but I know very little about Macros so I still need the code. I've tried multiple solutions, but nothing seems to work. I've recently tried to use this Code, but it hasn't worked. What am I doing wrong? What code could I possibly use instead?
Private Sub CommandButton1_Click()
Function PrintMultipleSheets()
Sheets(Array("Budget Sheet", "Listed Commitments Sheet")).PrintOut
End Function
End Sub
It comes up with an error that says "Compile Error: Expected End Sub".
The code doesn't compile, because you can't have a Function inside a Sub.
Get ride of the line Function PrintMultipleSheets() and get rid of End Function. It should work I think. You'll end up with:
Private Sub CommandButton1_Click()
Sheets(Array("Budget Sheet", "Listed Commitments Sheet")).PrintOut
End Sub
Just a simple loop with a print call:
Sub forEachWs()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
Call printSheet(ws)
Next
End Sub
Function pasteContents(ws as Worksheet)
ActiveSheet.PrintOut
End Function
Related
I have a Macro (the name is Test() ) from the Module1, and normally to call this Macro, i am using the code :
Call Module1.Test
But i am looking to a VBA code to call my Macro Test from Module1 until certain lines of code
Example stop the runing when the macro is arriving to the line 900
Thanks for your help
I'm not sure, but I can guess that you might want to run the Test() subroutine in different parts:
Sub Test(Optional stop_at_900 = False)
Debug.Print vbTab & "do the first part of the code"
'other code
900: If stop_at_900 Then Exit Sub ' 900 label is not needed, it is placed here for labeling
Debug.Print vbTab & "do the rest of the code"
'other code
End Sub
Sub UsageExample()
Debug.Print "Doing full Test() code..." ' usual (full) use
Call Test
Debug.Print "Doing Test() code until 900 line..." '
Call Test(stop_at_900:=True) 'partial use
End Sub
This question already has an answer here:
Dynamic Function Calls in Excel VBA
(1 answer)
Closed 7 years ago.
This is my test code
Sub dotask()
Dim qusub As String
qusub = Worksheets("Task List").Range("C2").Value
MsgBox qusub
Application.Run qusub
End Sub
Sub msg1()
MsgBox "sub msg1"
End Sub
Sub msg2()
MsgBox "sub msg2"
End Sub
Sub msg3()
MsgBox "sub msg3"
End Sub
Sub msg4()
MsgBox "sub msg4"
End Sub
All of this is contained in a single standard module. I've read Trying to call a Sub with a String - VBA and wrote my code according to what I found there (i.e. using Application.Run). Cell C2 of Task List worksheet contains "msg3" at the moment. When I execute sub "dotask" I first get a message box saying "msg3" as I want but then I get the following error message:
Run-time error '1004':
Cannot run the macro 'msg3'. The macro may not be available in this workbook or all macros may be disabled.
I'm working on Excel 2010 and the file is .xlsm - what should I do to get my code to execute as I want it?
just ran it over here. msg1 seems to be a reserved word... change it to something else and it works fine =)
Using GetRef, you give the reference to the sub.
See my question here for example
EDIT: following the suggestions in the comments, here part of the solution to this question.
sub one(para)
WScript.Echo para & " from one"
end sub
sub two(para)
WScript.Echo para & " from two"
end sub
sub main(subname, para)
Dim f : Set f = GetRef(subname)
f para
end sub
main "one", "test" '=>test from one
Here is my issue, I have subs that work when I tested them with the sheet unlocked, but when I locked the sheet to protect certain cells from being selected or deleted/altered, the subs error out. So I need to add a part to my sub that unlocks, runs the main code, then re-locks the sheet.
I am looking for something like this
Sub Example ()
Dim sample as range
set sample as range("A3:Z100")
Application.ScreenUpdating = false
UN-PROTECT CODE
'Existing sub code here
RE-PROTECT CODE
Application.ScreenUpdating = True
End Sub
I am however unaware on what the code to achieve this should look like. I have tried researching and all I found was incomplete code that based on the comments, didn't work all the time. I did find a suggestion to upon error, have an error handler re-protect the sheet, but not sure how to write this either. Any suggestions?
Oh, and the people who will be using this sheet will not have access to the sheet password. I plan to have the module its self password protected and the subs attached to buttons. So placing the Sheet unlock password in the sub would be ok if it is needed.
Posting my original comment as an answer.
If you use the macro recorder and then protect & unprotect sheets, it will show you the code.
EDIT: Added the below.
If you attempt to unprotect a sheet that is not protected you will get an error. I use this function to test if a sheet is protected, store the result in a Boolean variable and then test the variable to see if a) the sheet must be unprotected before writing to it and b) to see if the sheet should be protected at the end of the proc.
Public Function SheetIsProtected(sheetToCheck As Worksheet) As Boolean
SheetIsProtected = sheetToCheck.ProtectContents
End Function
Do you need it to remove passwords? This worked for me
Sub macroProtect1()
Sheet1.Unprotect Password:="abc"
'Enable error-handling routine for any run-time error
On Error GoTo ErrHandler
'this code will run irrespective of an error or Error Handler
Sheet1.Cells(1, 1) = UCase("hello")
'this code will give a run-time error, because of division by zero. The worksheet will remain unprotected in the absence of an Error Handler.
Sheet1.Cells(2, 1) = 5 / 0
'this code will not run, because on encountering the above error, you go directly to the Error Handler
Sheet1.Cells(3, 1) = Application.Max(24, 112, 66, 4)
Sheet1.Protect Password:="abc"
ErrHandler:
Sheet1.Protect Password:="abc"
End Sub
had a similar problem and found this code on the web:
Sub protectAll()
Dim myCount
Dim i
myCount = Application.Sheets.Count
Sheets(1).Select
For i = 1 To myCount
ActiveSheet.Protect "password", true, true
If i = myCount Then
End
End If
ActiveSheet.Next.Select
Next i
End Sub
Sub Unprotect1()
Dim myCount
Dim i
myCount = Application.Sheets.Count
Sheets(1).Select
For i = 1 To myCount
ActiveSheet.Unprotect "password"
If i = myCount Then
End
End If
ActiveSheet.Next.Select
Next i
End Sub
Note that it is designed to protect / unprotect all sheets in the workbook, and works fine. Apologies, and respect, to the original author, I can't remember where I found it (But I don't claim it)...
The most common object that is Protected is the Worksheet Object This make it possible to preserve formulas by Locking the cells that contain them.
Sub Demo()
Dim sh As Worksheet
Set sh = ActiveSheet
sh.Unprotect
' DO YOUR THING
sh.Protect
End Sub
Here's my very simple technique for situations that don't require a password (which are most situations that I run into):
Dim IsProtected As Boolean
IsProtected = SomeWkSh.ProtectContents: If IsProtected Then SomeWkSh.Unprotect
'Do stuff on unprotected sheet...
If IsProtected Then SomeWkSh.Protect
You can, of course, simplify the syntax a bit by using a With SomeWkSh statement but if the "Do stuff..." part refers to properties for methods of a larger, spanning With statement object, then doing so will break that functionality.
Note also that the Protect method's Contents parameter defaults to True, so you don't have to explicitly specify that, although you can for clarity.
I have a userform to call a macro in a separate module when a button is clicked. I get the following error: "Run-time error '450': Wrong number of arguments or invalid property assignment"
In troubleshooting I removed the arguments and changed the dummy macro I was calling to not take arguments, but I get the same error.
Public Sub btnSubmit_Click()
Dim Description As String
Dim Priority As String
If (checkCleared.Value = False) Then
MsgBox ("Please certify that all sensitive informationhas been removed and then submit")
Exit Sub
Else
'Description = formScreen.txtDesc.Value
'Priority = formScreen.comboPriority.Value
'Application.Run ThisOutlookSession!postScreenedEmail(Priority, Description)
Application.Run ThisOutlookSession!postScreenedEmail
End If
End Sub
In the separate module:
Public Sub postScreenedEmail() '(Priority As String, Description As String)
MsgBox ("postScreened")
'MsgBox ("Priority is: " & Priority & " and Description is " & Description)
End Sub
I have tried other methods of calling the macro such as "Call postScreenedEmail()" but it cant see the macro then. My end goal is just to grab values from the userform and pass them to the other macro so they can be used with the API I am working with.
Edit: I may have mixed my terminology, this is the hierarchy I am working with (can't post pic with my rep). That being said I tried to do the call with just Application.Run "postScreenedEmail", Priority, Description and it changed nothing
-Project1(VbaProject.OTM)
-Microsoft Outlook Objects
| ThisOutlookSession
-Forms
| formScreen
|
-Modules
Module1
Try:
call postScreenedEmail
instead of:
Application.Run ThisOutlookSession!postScreenedEmail
Since your sub is public, vba should be able to find it without the module reference.
If this works, add the reference again (makes your code more readable, especially for others, as ckuhn203 pointed out in the comments) and see if it breaks. If so, that's where the problem is.
EDIT:
Are you sure you're referencing the right module?
If I try:
-Project1(VbaProject.OTM)
-Microsoft Outlook Objects
| ThisOutlookSession
-Modules
| Module1
in Module1:
Sub jzz()
Debug.Print "test"
End Sub
and in ThisOutlookSession:
Sub test()
Call Module1.jzz
End Sub
it works. No problem. Using:
Application.Run Module1.jzz
instead of Call trows a compile error.
Even:
Sub test2()
Call ThisOutlookSession.test
End Sub
from Module1 works, without problems.
Can you run such small tests to try to get the references right?
Try this... Application.Run takes a string for procedure name, and then comma-separated list of parameters/arguments:
Application.Run "Procedure_Name", arg1, arg2, arg3
So I think this should work:
Application.Run "ThisOutlookSession!postScreenedEmail", Priority, Description
I'm trying to figure out a way to call a VBScript function using vba in Excel, and then pass a value back to excel-vba. See below
VBA within Excel
Sub RunTest()
Dim objString as String
'Begin Pseudocode
objString = Call VBScript Function Test()
'End Pseudocode
MsgBox objString `from VBS
End Sub
VBScript
Function Test
Test = "Hello World"
End Function
I know this may seem strange because I could just write the function in VBA, but we had an office patch pushed out and it completely killed the functionality of one of my macros for some reason. Strange thing is, I can run the exact same code within any other office program, just not excel. As a work around, I moved the function that crashes excel to word and I pull it using application.run, but I prefer to not have to do that, as opening a the word application to run my macro slows my process way down.
Any help is appreciated, thank You
Ok, I feel a litte dirty :)
This code has two key parts:
the vbs Uses GetObject and the full host workbook path to re-attach to the file containing the VBA that called the VBS
the VBS adds a value to a specific worksheet in the host VBA file to trigger the Worksheet_Change event to fire, running VBA with the string passed from the VBS.
Step 1: Regular Excel code module
Sub VBA_to_VBS_to_VBA()
Shell "wscript c:\temp\myvbs.vbs", vbNormalFocus
End Sub
Step 2: myvbs
Dim xlApp
Dim xlSht
On Error Resume Next
Set xlApp = GetObject("c:\temp\mybook.xlsx").Application
Set xlSht = xlApp.Sheets("vbs sheet")
On Error GoTo 0
If Not xlSht Is Nothing Then
xlSht.Range("A1").Value = "hello world"
Else
wscript.echo "sheet not found"
End If
Step 3: Sheet code for vbs sheet in your Excel File
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox [a1].Value, vbCritical, "VBS insertion"
End Sub
Try syntax like:
Sub Test()
Shell "cscript c:\TestFolder\sample.vbs", vbNormalFocus
End Sub