add .SendKeys to an existing macro - excel

I have a code that would help me with printing a document from Excel.
It has a couple dialogue questions for adding serial number sequence and number of copies.
Unfortunately, it doesn't open the Print dialogue, where I can select a printer and it's preferences.
The code would just immediately print to my default printer.
I need to add some custom features like 2-side printing and stapling in the top left corner.
For that purpose I want to use .Sendkeys
I tried adding the string Application.SendKeys "%fpr" (my printer preferences dialogue) here and there inside the code to no avail.
Please help inserting the sting.
Alternatively - maybe there is a command for .PrintOut that I could add for 2-side printing and a staple finish?
Private Sub CommandButton1_Click()
Dim xCount As Variant
Dim xJAC As Variant
Dim xID As Variant
Dim xScreen As Boolean
Dim I As Long
On Error Resume Next
Application.SendKeys "%fpr"
LInput:
xJAC = Application.InputBox("Please enter the job number (Leave Out JAC):", "")
xCount = Application.InputBox("Please enter the number of copies you want to print:", "")
xID = Application.InputBox("Please enter the Starting ID of the product:", "")
If TypeName(xJAC) = "Boolean" Then Exit Sub
If TypeName(xCount) = "Boolean" Then Exit Sub
If TypeName(xID) = "Boolean" Then Exit Sub
If (xCount = "") Or (Not IsNumeric(xCount)) Or (xCount < 1) Or (xID < 1) Or (xCount = "") Or (Not IsNumeric(xID)) Then
MsgBox "error entered, please enter again", vbInformation, "Kutools for Excel"
GoTo LInput
Else
xScreen = Application.ScreenUpdating
Application.ScreenUpdating = False
For c = 0 To xCount - 1
ActiveSheet.Range("E2").Value = "JAC" & xJAC
ActiveSheet.Range("G2").Value = xID + c
ActiveSheet.PrintOut
Next
ActiveSheet.Range("E2").ClearContents
ActiveSheet.Range("G2").ClearContents
Application.ScreenUpdating = xScreen
End If
End Sub

Related

Return to a certain routine when an IF condition is not met

Facing an issue with coming up with a way to send back my code to a certain place when an IF condition is not met. In the code below, I have included an input box requiring data to be entered however through an IF condition I want to make sure atleast 8 digits are entered, If less than 8 digits are entered then I want to show a msg box "Error" and return to GL_Code position asking user to fill the inputbox again.
Dim GL_CY As Variant
Dim GL_Book As Workbook
GL_CY = Application.GetOpenFilename(Title:="Open GL", FileFilter:="Excel Files (*.xls*),*xls*")
Set GL_Book = Application.Workbooks.Open(GL_CY)
'Filtering Range
Dim GL_Code As Variant, GL_Rng As range, GL_LR As Long
Dim GL_Sheet As Worksheet
Set GL_Sheet = GL_Book.Worksheets(1)
GL_LR = GL_Sheet.range("B" & Rows.Count).End(xlUp).Row
GL_Code = Application.InputBox(Prompt:="Enter GL code to generate its activity ", Title:="Generate GL Activity", Type:=1)
If VBA.IsError(GL_Code) Then
GoTo ErrorHandle
ElseIf Len(GL_Code) < 8 Then
MsgBox "GL Code Not Entered", , "Error"
'Return To GL_Code
End If
Set GL_Rng = GL_Sheet.range("A4:R" & GL_LR).CurrentRegion.Offset(3, 0)
Relevant part of the issue is (Need a code for the commented part at the last line)
GL_Code = Application.InputBox(Prompt:="Enter GL code to generate its activity ", Title:="Generate GL Activity", Type:=1)
If VBA.IsError(GL_Code) Then
GoTo ErrorHandle
ElseIf Len(GL_Code) < 8 Then
MsgBox "GL Code Not Entered", , "Error"
'Return To GL_Code
Naqi,
This should do the trick, at least it worked on my machine. I had to put a phony ErrorHandle label in as you didn't show that in your code.
Option Explicit
Sub Test()
Dim GL_Code As String
Dim GoodEntry As Boolean
GoodEntry = False
Do
GL_Code = Application.InputBox(Prompt:="Enter GL code to generate its activity ", Title:="Generate GL Activity", Type:=1)
If (GL_Code = False) Then Exit Sub 'User pressed CANCEL!
If VBA.IsError(GL_Code) Then
GoTo ErrorHandle
Else
If Len(GL_Code) < 8 Then
MsgBox "GL Code Not Entered", , "Error"
'Return To GL_Code
Else
GoodEntry = True
End If
End If
Loop Until GoodEntry
ErrorHandle:
End Sub
HTH

VBA code stopping when secondary workbook manually closed (waiting for user to close second workbook)

I'm looking to have primary workbook (WorkbookA), open a second workbook (WorkbookB) and test for a value within it. Value to match is in WorkbookA, cell B3 and is the number 1. Range to test in WorkbookB is "A:A".
If the value is not found, WorkbookB is reopened for the user to edit (will optimize to reduce opening/closing, any ideas on getting user input to resume would be appreciated after editing Workbook B), and the code in WorkbookA loops and retests if WorkbookB is still open every 10 seconds.
After the user edits WorkbookB to ensure the value is present, they close it (any better way to signal they are complete is welcomed so I don';t have to close and reopen the files. They are small, so it's not an issue for speed, just seems inefficient).
The assumption I had was that the code would then detect the workbook was closed and then continue code execution, but the VBA is stopping as soon as I select the X in the top right corner of Workbook B.
Would prefer not having separate code in personal.xls file because of multiple users.
Thanks,
Aaron
Code in Workbook A:
Global Const strWBb As String = "C:\Users\ashepherd\Desktop\WorkbookB.xlsx"
Global Const strRng As String = "A:A"
Sub Validate()
' ***************************** CHECK WORKBOOKB FOR 1 IN COLUMN A:A *****************************
' Verify presence on item in second workbook
searchItem = ThisWorkbook.Worksheets("Sheet1").Range("B3").Value
Do While Verify(searchItem, False) = False
Call Verify("", True)
Do While IsWorkBookOpen(strWBb) = True
endTime = DateAdd("s", 10, Now())
Do While Now() < endTime
DoEvents
Loop
Loop
Debug.Print "Workbook closed"
Loop
Debug.Print "search item found"
End Sub
Function Verify(item, OpenOnly As Boolean) As Boolean
' ****************************************************************************
' Open workbook B and verify that presence of item
' ****************************************************************************
Dim wbVerify As Workbook
Dim rng1 As Range
' ************************** OPEN FILE ************************************************
If IsFile(strWBb) Then
Set wbVerify = Application.Workbooks.Open(FileName:=strWBb, UpdateLinks:=False, IgnoreReadOnlyRecommended:=True) ' Open WorkbookB
wbVerify.Worksheets("Sheet1").Select
Else
MsgBox " File path incorrect. Unable to open.", vbCritical
Exit Function
End If
' ************************** TEST FOR ITEM ************************************************
If OpenOnly = True Then ' Only opening the file for read/write. Not testing values.
MsgBox "Opening workbook so values can be added. Close when additions completed."
Else
MsgBox ("Workbook B opened. Testing value for " & item & " in column A:A in Workbook B")
Set rng1 = Range(strRng).Find(item, , xlValues, xlWhole)
If Not rng1 Is Nothing Then
MsgBox item & " found !"
Verify = True
wbVerify.Close
GoTo item_found
Else
MsgBox (item & " not found in column A:A. Closing Workbook B. *****User will be promoted at this point to exit, or re-open the file to modify the values so search value is found in column A:A. Code SHOULD resume when Workbook B is closed. Currently VBA code execution in Workbook A is stopping when the 'X' is selected in top right window of Workbook B*****")
Verify = False
wbVerify.Close
End If
End If
Normal_exit:
Exit Function
item_found:
MsgBox "Verify code complete"
GoTo Normal_exit
End Function
Function IsWorkBookOpen(FileName As String)
Dim ff As Long, ErrNo As Long
On Error Resume Next
ff = FreeFile()
Open FileName For Input Lock Read As #ff
Close ff
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: IsWorkBookOpen = False
Case 70: IsWorkBookOpen = True
Case Else: Error ErrNo
End Select
End Function
Function IsFile(ByVal fName As String) As Boolean
'Returns TRUE if the provided name points to an existing file.
'Returns FALSE if not existing, or if it's a folder
On Error Resume Next
IsFile = ((GetAttr(fName) And vbDirectory) <> vbDirectory)
End Function
Final code:
Global Const strWBb As String = "C:\Users\ashepherd\Desktop\WorkbookB.xlsx"
Global Const strRng As String = "A:A"
Global Complete As Boolean
Sub Validate()
' ***************************** CHECK WORKBOOK_B FOR 1 IN COLUMN A:A *****************************
' Verify presence on item in second workbook
searchItem = ThisWorkbook.Worksheets("Sheet1").Range("B3").Value
Do While Verify(searchItem) = False
Complete = False
UserForm1.Show vbModeless ' USerform has a single button which changes the global "Complete" variable to true
Do While Complete = False
DoEvents
Loop
UserForm1.Hide
Debug.Print "Manual Edit Complete, retesting"
Loop
End Sub
Function Verify(item) As Boolean
' Modified to close only upon finding search item vs. reopening it.
' ****************************************************************************
' Open workbook B and verify that presence of item
' ****************************************************************************
Dim wbVerify As Workbook
Dim rng1 As Range
' ************************** OPEN FILE ************************************************
If IsFile(strWBb) Then
Set wbVerify = GetWorkbook(strWBb)
If Not wbVerify Is Nothing Then
Debug.Print wbVerify.Name
End If
wbVerify.Worksheets("Sheet1").Select
Else
MsgBox " File path incorrect. Unable to open.", vbCritical
Exit Function
End If
' ************************** TEST FOR ITEM ************************************************
Set rng1 = Range(strRng).Find(item, , xlValues, xlWhole)
If Not rng1 Is Nothing Then
Verify = True
GoTo item_found
Else
MsgBox (item & " not found in column A:A. A pop up form will show. Edit document and then hit RESUME button to continue checking. DO NOT exit via the close icon in the top right window of Excel as the code will stop running.")
Verify = False
End If
Normal_exit:
Exit Function
item_found:
'MsgBox (item & " found in WorkbookB, column A:A. Verify code complete")
wbVerify.Close Savechanges:=True
GoTo Normal_exit
End Function
Function IsFile(ByVal fName As String) As Boolean
'Returns TRUE if the provided name points to an existing file.
'Returns FALSE if not existing, or if it's a folder
On Error Resume Next
IsFile = ((GetAttr(fName) And vbDirectory) <> vbDirectory)
End Function
Public Function GetWorkbook(ByVal sFullName As String) As Workbook
' https://stackoverflow.com/questions/9373082/detect-whether-excel-workbook-is-already-open, modified to add ignorereadonly and update links
Dim sFile As String
Dim wbReturn As Workbook
sFile = Dir(sFullName)
On Error Resume Next
Set wbReturn = Workbooks(sFile)
If wbReturn Is Nothing Then
Set wbReturn = Application.Workbooks.Open(FileName:=sFullName, UpdateLinks:=False, IgnoreReadOnlyRecommended:=True)
End If
On Error GoTo 0
Set GetWorkbook = wbReturn
End Function

How to deal with a dash in an Excel VBA input variable?

I'm having some trouble with an Excel VBA macro and was hoping you could give me some advice on how to fix it. In the code below, when a user clicks a command button, an InputBox pops up and the user inputs a number in the form XXX-XXXXXX (e.g. 111-222222). Then, the macro takes the value from the column adjacent to button and uses the input variable to replace a certain part of the adjacent column's value. However, when I tried to run the macro and input a number such as 123-456789, nothing happens. I believe it has something to do with the dash that the user inputs, however I'm not sure how to fix it. Please help!
Sub CommandButtonTitleXXXdashXXXXXX_Click()
Application.ScreenUpdating = False
On Error Resume Next
Dim n As Integer
n = Worksheets("REVISIONS").Range("D3:D17").Cells.SpecialCells(xlCellTypeConstants).Count
If n = 15 Then
If MsgBox("Title revision box full. Add manually.", vbOKOnly, "Error") = vbOK Then
Exit Sub
End If
End If
Dim rs As Integer
rs = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row
Dim amount As String
Application.ScreenUpdating = True
amount = Application.InputBox("Enter case number:", "")
Application.ScreenUpdating = False
If amount = False Then
Exit Sub
Else
Dim newCell As String
newCell = Replace(Worksheets("TITLE").Range("A" & rs).Value, "XXX-XXXXXX", amount)
Worksheets("REVISIONS").Range("D17").End(xlUp).Offset(1, 0) = newCell
End If
End Sub
I would take your code to an extra step.
No need to declare amount as String. You can keep it as a Variant. Also like I mentioned in the comment above
Can your Case number be like #D1-1%#456? If not then you have an additional problem to handle ;)
See this example. I have commented the code so that you will not have a problem understanding it. Still if you do lemme know :) The other way would be to use REGEX to validate your Case ID. Let me know if you want that example as well.
Code
Sub Sample()
Dim amount As Variant
' 123-$456789 <~~ Invalid
' 123-4567890 <~~ Valid
' ABC-&456789 <~~ Invalid
' 456-3456789 <~~ Valid
amount = Application.InputBox("Enter case number:", "")
'~~> Check if user pressed cancel
If amount = False Then Exit Sub
'~~> Check if then Case ID is valid
If IsValidCaseNo(amount) Then
MsgBox amount
Else
MsgBox "Invalid case ID"
End If
End Sub
Function IsValidCaseNo(sAmount) As Boolean
Dim s As String
Dim i As Long, j As Long
s = sAmount
'
'~~> Initial basic checks
'
'~~> Check if the length is 11 characters
If Len(Trim(s)) <> 11 Then GoTo Whoa
'~~> Check if the string contains "-"
If InStr(1, s, "-") = 0 Then GoTo Whoa
'~~> Check if the 4th character is a "-"
If Mid(s, 4, 1) <> "-" Then GoTo Whoa
'~~> Loop through 1st 3 characters and check
'~~> If they are numbers
For i = 1 To 3
Select Case Asc(Mid(s, i, 1))
Case 48 To 57
Case Else: GoTo Whoa
End Select
Next
'~~> Loop through last 6 characters and check
'~~> If they are numbers
For i = 5 To 11
Select Case Asc(Mid(s, i, 1))
Case 48 To 57
Case Else: GoTo Whoa
End Select
IsValidCaseNo = True
Next
Whoa:
End Function
If you Dim amount as String, you can test it as a string:
Sub GetDash()
Dim amount As String
amount = Application.InputBox(Prompt:="Enter case number", Type:=2)
If amount = "False" Then
MsgBox "You cancelled"
End If
End Sub

How can I find the shape that is selected in group box in Excel?

I have a group box with option buttons in it and I need to find out which one of them is selected in VBA. I have been browsing MSDN for hours now and I can't find a solution.
There has to be a way to find the selected option button. Possibly find the group by name and for-each through each option button?
Here's what seems to be a working solution.
(Nod to KazJaw for Dim ... As OptionButton. this seems to be the key to get .GroupBox to work)
Function WhichOption(shpGroupBox As Shape) As OptionButton
Dim shp As OptionButton
Dim shpOptionGB As GroupBox
Dim gb As GroupBox
If shpGroupBox.FormControlType <> xlGroupBox Then Exit Function
Set gb = shpGroupBox.DrawingObject
For Each shp In shpGroupBox.Parent.OptionButtons
Set shpOptionGB = shp.GroupBox
If Not shpOptionGB Is Nothing Then
If shpOptionGB.Name = gb.Name Then
If shp.Value = 1 Then
Set WhichOption = shp
Exit Function
End If
End If
End If
Next
End Function
Use it like this
Sub test()
Dim shpOpt As OptionButton
Set shpOpt = WhichOption(Worksheets("Sheet1").Shapes("Group Box 1"))
Debug.Print shpOpt.Name
End Sub
If you really need to check OptionButton which are grouped (Grouped in the way we group any type of shape) you could go with this code:
Sub Grouped_into_UnitType()
Dim i!
'grouped into 'UnitType' Shape
For i = 1 To ActiveSheet.Shapes("UnitType").GroupItems.Count
With ActiveSheet.Shapes("UnitType").GroupItems(i).ControlFormat
If .Value = 1 Then
MsgBox "Chosen item: " & i
End If
End With
Next i
End Sub
Edit having in mind the following picture the code above will solve the problem if we have Option Buttons which are group in the way we group any Shapes placed in the sheet.
The code under the picture will find which option button is selected if they are located within GroupBox. Code check the name of the group in which OptionButton is located.
Important Note! the code below didn't work until I switched Excel off and run it again.
Sub Grouped_into_GroupBox_UnitType()
Dim OB As OptionButton
For Each OB In ActiveSheet.OptionButtons
'check if grouped into 'UnitType' Shape
If OB.GroupBox.Name = "UnitType" Then
If OB.Value = 1 Then
MsgBox "Chosen item: " & OB.Name & _
vbNewLine & _
"Alt text: " & OB.ShapeRange.AlternativeText
End If
End If
Next
End Sub
Lets say you have two standard option buttons:
To check if its "on" use:
Dim opt As Shape
Set opt = Worksheets("Sheet1").Shapes("Option Button 1")
If opt.ControlFormat.Value = xlOn Then
Debug.Print "option is ""on"" value of 1"
Else
Debug.Print "option is ""off"" value of -4146"
End If
To get its alternat text use:
Debug.Print "Alternate Text is: " & opt.AlternativeText
For a large amount of options the "FormControlType" property can be used:
Dim s as Shape
For Each s In Worksheets("Sheet1").Shapes
If s.FormControlType = xlOptionButton Then
If s.ControlFormat.Value = xlOn Then
Debug.Print "option is ""on"" value of 1"
Else
Debug.Print "option is ""off"" value of -4146"
End If
Debug.Print "Alternate Text is: " & s.AlternativeText
End If
Next
If you wanted a particular group:
Dim s As Shape, o
For Each s In Worksheets("Sheet1").Shapes
If s.FormControlType = xlOptionButton Then
Set o = s.OLEFormat.Object
If o.GroupBox.Name = "Group Box 3" Then
If s.ControlFormat.Value = xlOn Then
Debug.Print "Option is ""on"" value of 1"
Else
Debug.Print "Option is ""off"" value of -4146"
End If
Debug.Print "Alternate Text is: " & s.AlternativeText
Debug.Print "Group: " & o.GroupBox.Name
End If
Set o = Nothing
End If
Next

Input Box Error Handling

I am having trouble handling the error associated with a input box "Cancel" click. Or in otherwords, it returns an error within the sub if the value of the input is null. I have tried looking around and still can't seem to get it quite right. Here is my attempt:
Private Sub bttnSavingsExpected_Click()
Dim expected() As String
Dim nPeriods As Integer
Dim counter As Integer
Dim savings As Single
With ActiveSheet.Range("A13")
nPeriods = Range(.Offset(1, 0), .End(xlDown)).Rows.Count
End With
ReDim expected(1 To nPeriods)
counter = 1
For counter = 1 To nPeriods
expected(counter) = Range("A13").Offset(counter, 0).Value
Next
TryAgain:
On Error GoTo ErrH
counter = 1
For counter = 1 To nPeriods
savings = InputBox("How much savings do you expect from " & expected(counter) & "?", "Savings?", Range("A13").Offset(counter, 1).Value)
If savings = "" Then
Exit Sub
Else
Range("A13").Offset(counter, 1).Value = savings
End If
Next
Exit Sub
ErrH:
MsgBox "Please enter value. If the default value is desired then please click 'OK'.", vbOKOnly, "Do Not Click Cancel"
GoTo TryAgain
End Sub
With this attempt, the MsgBox is displayed the first click whether there is a input or not and even if I click "Ok". The second try of clicking "OK" or "Cancel" leads to being kicked back to the editor.
You've got Dim savings As Single and If savings = "" Then. Thats always going to error
Try using Dim savings As Variant
Make sure the variable for the Inbox is set at "", then test the value for False. Much easier than anything else I have seen:
Sub WolfPackURL_input()
Dim TheURL As String
Dim SaveURL As Hyperlink
Set savedURL = Sheets("Data").Range("I1")
TheURL = ""
TheURL = Application.InputBox("Input the Sign-Up URL", "Wolfpack Weekly Players URL", "http://something", 1)
If TheURL = "False" Then
Exit Sub
End If
ThisWorkbook.Worksheets("Data").Activate
Sheets("Data").Range("I1").Hyperlinks.Delete
Sheets("Data").Range("I1").ClearContents
Sheets("Data").Range("I1").Clear
ActiveSheet.Hyperlinks.Add anchor:=Sheets("Data").Range("I1"), Address:=TheURL, ScreenTip:="Open file", TextToDisplay:=TheURL
End Sub

Resources