Insert text string through other macro with Excel VBA - vba

I'm having an issue and dont know if this is possible to be done.
I need to insert a string variable through another macro that is protected and can't access the VBA code.
At my code, I intend to send a string when call the protected macro (with application.run "macroname"). This protected macro prompts a selection window to select a file. I pretend to automatically insert at macro's prompt my string and send "ENTER" command to open the desire file.
Is this possible to be done?

If I understood you correctly, this is what you are looking for:
1) Locked workbook (VBA module is protected) contains e.g. the following macro:
Public Sub Test(sInput As String)
ActiveCell.Value = sInput
MsgBox sInput
End Sub
What you are trying to do, is to call this Test macro, but you don't know how to pass parameter (correct me if I got this wrong).
This is how you do it:
Sub RunProtectedMacro()
Dim vResult As Variant
vResult = Application.Run("'" & LockedWorkbook.Name & "'!Test", "some string argument")
End Sub

Related

Run a VBA routine from VBA IDE?

I want to get a list of routines from a VBA project, then run the macros selected by the user.
The image below shows the native "Macros" box. I want to extend this functionality to multiple macros across multiple documents.
I found this link which solves the first part of the problem. Now that I have my list, how do I run a selected routine by name?
Hello and welcome to SO
Below is code sample how to execute VBA macro using code. You need to add some form to select documents and macros for execute. This depends on your implementation.
Sub RunMacroUsingCode()
Dim vbaProjectName As String
vbaProjectName = "InventorVBA"
Dim vbaModuleName As String
vbaModuleName = "m_Tests"
Dim vbaMacroName As String
vbaMacroName = "RunMultipleMacrosTestCall"
Dim vbaProject As InventorVBAProject
For Each vbaProject In ThisApplication.VBAProjects
If vbaProject.name = vbaProjectName Then Exit For
Next
Dim vbaModule As InventorVBAComponent
For Each vbaModule In vbaProject.InventorVBAComponents
If vbaModule.name = vbaModuleName Then Exit For
Next
'Using result is optional
Dim result As Variant
Call vbaModule.InventorVBAMembers(vbaMacroName).Execute(result)
End Sub
Function RunMultipleMacrosTestCall()
Call MsgBox("TEST")
RunMultipleMacrosTestCall = True
End Function

VBA Word Macro to Allow User to Select and Copy Text Multiple Times

I am working on a VBA script with Microsoft Word that allows the user to select text that will be be copied to the clipboard so that it can exported to an Excel file. The user will make a number of selections and finally indicate he/she is done when the contents of the clipboard will be copied to a template Excel file.
There are two forms: the first (UserForm1 in the code below) queries the user for the Word filename. The filename variable is passed to the second form. The second form (frmModeLessForInput) is a modeless form. The behavior I need is that program control goes to the second form with two buttons "Continue" and "Done".
The user is allowed to navigate the document and place the cursor anywhere in the document. Then when "Continue" is pressed the form will call a subroutine (Highlight_Sentence) to copy the selected text to a "clipboard" variable. When "Done" is pressed control will be passed to called main module which will then copy the clipboard to the Excel file.
Below is the code. I have noted with comments where I am trouble with the code. One problem is the variables defined as Public in the ThisDocument module are not defined in the userforms and their subroutines.
The second problem is in the main module that the frmModelessForInput is supposed to be displayed and control is not supposed to be transferred to next statement {MsgBox "Sentences will now be copied to Excel file"....this is where I will put the code to copy the clipboard to the Excel file.} but the message appears before the frmModelessForInput form is run...thus the clipboard will be empty.
The third problem is that in frmModelessForInput form the statement str_clipboard = str_clipboard + str_clipboard_line is not working. Each time the "Continue" button is pushed str_clipboard loses it previous contents.
Any assistance in resolving these problems is appreciated. As VBA programming is a sideline for me I am still learning.
Note this an updated question Pause VBA Word macro, allow user to make a selection, and restart where it left off adding some more detail on the requirement and the sample code.
MAIN MODULE:
Option Explicit
Public str_clipboard As String
Public txt_active_document As String
Public i_how_many_sentences As Integer
Private Sub Test_master_macro()
UserForm1.Show
i_how_many_sentences = 0
Call DisplayModeless
MsgBox "Sentences will now be copied to Excel file" 'Problem: this msg displays before the frmModelessForInput is displayed
End Sub
Sub DisplayModeless()
Dim frm As frmModelessForInput
Set frm = New frmModelessForInput
With frmModelessForInput
.str_word_doc_filename = txt_active_document
.str_no_copied = "0"
.Show False
End With
Set frm = Nothing
End Sub
USERFORM1: form has field for user entering the document filename to user (str_filename) and a command button to close form (cmd_start_selecting_text)
Private Sub cmd_start_selecting_text_Click()
'User enters filename on form for use in frmModelessForInput subroutine
txt_active_document = UserForm1.str_filename 'Problem: VBA reports txt_active_document as undefined even though it is a Public variable
Unload Me
End Sub
FRMMODELESSFORINPUT: Form displays filename of Word file entered in UserForm1 and how many sentences have been copied to the clipboard
Option Explicit
Private Sub cmdContinue_Click()
Dim str_clipboard, str_clipboard_line As String
Call Highlight_Sentence(str_clipboard_line)
i_how_many_sentences = i_how_many_sentences + 1 'Problem: VBA reports i_how_many_sentences as undefined even though it is a Public variable
frmModelessForInput.str_no_copied = i_how_many_sentences 'Same Problem
str_clipboard = str_clipboard + str_clipboard_line 'Problem: each time I select a new text/sentence str_clipboard does not contain the contents of the previous selection
End Sub
Private Sub cmdDone_Click()
Me.Hide
End Sub
Private Sub UserForm_Activate()
'Position the form near the top-left of the window
'So that the user can work with the document
Me.Top = Application.ActiveWindow.Top + 15
Me.Left = Application.ActiveWindow.Left + 15
End Sub
Private Sub Highlight_Sentence(clipboard As String)
'This sub extends the selection to the entire sentence and copies the selection, the page number on which the selection is contained and the filename to the clipboard variable
Dim txt_sentence, txt_page_no As String
With Selection
' Collapse current selection.
.Collapse
' Expand selection to current sentence.
.Expand Unit:=wdSentence
End With
txt_sentence = Selection.Text
txt_page_no = Selection.Information(wdActiveEndPageNumber)
clipboard = txt_active_document & vbTab & txt_page_no & vbTab & txt_sentence & vbCrLf 'Problem: VBA reports txt_active_document as undefined even though it is a Public variable
End Sub
From what you stated you are running this from the ThisDocument Class Module and unless you fully qualify your references to those Public variables with the Class Name that is why you cannot access them from the UserForms Class Modules.
If you are going to leave your "Main Module" code in the ThisDocument Class Module then whenever you reference those Public variable you need to add ThisDocument.str_clipboard to the command.
I recommend however, to place your Main Module in a general Module such as NewModule and if you need to run it at a Document_Open event that you put a call to the Main Module and its Public variables in the Private Sub Document_Open event of the ThisDocument Class Module.
Your Msgbox is appearing at the wrong time because you are displaying a modeless user form, which means the VBA script thread continues to run after the UserForm is displayed. Move the Msgbox to the UserForm_Activate routine of the second UserForm you are displaying or move it to the Click_Done routine of the first UserForm before you Hide or Unload it.
Finally, you are not really using the Clipboard and using that term makes your code confusing in my opinion. I think you should rename it. Your code also appears to just be building one continuous string of text. Is that really what you want to do? Or, do you really mean to capture each selected text string and ultimately place each into separate cells within an Excel Worksheet? If that is the case, use an Array for the separate text strings.

My shortcut key will not allow me to run a message box

Previous versions of this code had no message box, which sometimes resulted in the wrong workbook being closed. I added an okcancel message box to keep this from happening, but the message box doesn't show up when I use a shortcut key to open it. What am I missing?
Sub openerQuick()
Dim myfile As String
Dim clientID As String
Dim PDSfilename As String
Dim myopener As Variant
clientID = ActiveCell
PDSfilename = ActiveCell.Offset(0, 1)
myfile = "N:\DOWNLOAD\FILEDIR\" & clientID & "\original\" & PDSfilename
Set wbOpener = Workbooks.Open(myfile)
If MsgBox("Okay to close?", vbOKCancel) = vbOK Then
ActiveWorkbook.Close
End If
End Sub
I doubt the MsgBox itself has anything to do with losing the macro shortcut key.
Shortcut keys are defined by a hidden member attribute value, and the VBE has a tendency to lose member attributes when you rewrite a method's signature, or rewrite a module*; it's possible that modifying the code caused the previously existing attribute to somehow get lost.
Remove the module from the project, pick "Yes" when prompted whether to export or not
Open the exported file in Notepad++ your favorite text editor
Locate the procedure
Add the attribute if it's not there
Save the file if it was changed, re-import into the project
The member attribute should look something like this:
Public Sub OpenerQuick()
Attribute OpenerQuick.VB_ProcData.VB_Invoke_Func = "A\n14"
'...code....
End Sub
That exact attribute associates Ctrl+Shift+A to the macro; change the A for whichever letter rocks your boat to change the shortcut.
When you record a macro in Excel and specify A for a shortcut key, the macro recorder automatically adds this hidden attribute for you.
* Rubberduck's module rewriters have that very problem and it's driving me nuts.
In a module write the following 2 subs:
Public Sub OpenerQuick()
If MsgBox("Okay to close?", vbOKCancel) = vbOK Then ActiveWorkbook.Close
End Sub
Public Sub InitiateMe()
Application.OnKey "{a}", "OpenerQuick"
End Sub
Run only InitiateMe. Now, when you press a, InitiateMe would be triggered.

How can assign macro that is in WorkSheet module and has several arguments to a command button for Insert new TableRow in protected Sheet?

I have a Command button in my Worksheet ("Sheet1"), under a Table.
My sheet is protected and I need let user add new rows.
Bellow macro was wrote for do that: (This is in a WorkSheet module)
Sub TblNewLine(Sht As String, Tbl As String, Pass as String, Filtering As Boolean, Pivot As Boolean)
if Nor Pass = vbNullString then
Dim strP as String
strP = InputBox ("Please input Password","Password")
if Not strP = Pass Then
if not strP = vbNullString Then MsgBox "Wrong Password!", vbCritical, "Error!"
Exit Sub
End If
End If
Sheets(Sht).Unprotect
Sheets(Sht).ListObjects(Tbl).ListRows.Add
Sheets(Sht).Protect AllowFiltering:=Filtering, AllowUsingPivotTables:=Pivot
End Sub 'TblNewLine
for example: arguments are:
sht:= "sheet1", Tbl:="PvtReport", Pass:="", Filtering:=True, Pivot:= True
Thus I need assign this macro to prepared command button that is under Table.
And passing arguments with pressing button.
In assign macro form, I cant find above macro in Macro names combo box.
How can I assign above macro and its related arguments to a command button?
Or is there any better solution for Insert new row to protected sheet Table?
Try something like below:
Sub Button1_Click()
Call TblNewLine("Sheet1", "PvtReport", True, True)
End Sub
Sub TblNewLine(Sht As String, Tbl As String, Filtering As Boolean, Pivot As Boolean)
Sheets(Sht).Unprotect
Sheets(Sht).ListObjects(Tbl).ListRows.Add
Sheets(Sht).Protect AllowFiltering:=Filtering, AllowUsingPivotTables:=Pivot
End Sub
EDIT :
See image for reference
With great thanks from Mrig's guidance; For more explanation I Present whats i reached, as an answer:
there is a way for passing arguments with Command button, that I read in QA Collective's Answer for a related question.
At first i encountered 'cannot run Macro' error from Microsoft Excel, but when I closed and open workbooks document, looked Macro name field in Assign Macro was changed as bellow and my subroutine called truly by passing constants with click on button.
'FileName.xlsm'!'TblNewLine "SheetName", "tblReminder","",True,False'
Please not that ' character for enclose subroutine name and arguments list string, both in twisted '.
in above example, my sub needs 5 arguments so they pass with each command button that want calling this sub.
The point about assign macro that has no arguments, and there is in Worksheet module is there are listed below of Asign Macro combo list and not in order of subroutines are in other modules.
if subroutine macros has argument, there not listed in Asign Macro and should input them in related field as above example i explained.

Running code from VBA to VBScript back to VBA

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