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

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.

Related

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.

Change print method from PDF to default printer for a form printout

Hi I am trying to get the print out of a userform. While printing its always prompting to save the userform (a prompt box is being displayed). I don't want it.
I want to get the printout directly after choosing the printer without saving it.
Code below:
Private Sub CommandButton2_Click()
CommandButton2.Visible = False
CommandButton1.Visible = False
Application.Dialogs(xlDialogPrinterSetup).Show
Me.PrintForm
CommandButton2.Visible = True
CommandButton1.Visible = True
End Sub
You may not like this answer, because it involves more workt, but you probably want the userform to add the data into a formatted worksheet and then use the printout method of the worksheet.
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/sheets-printout-method-excel
Worksheets.("yourWorksheet").printout _
activeprinter:= yourPDFprinter, _
PrintTofFile:= True, _
PrToFileName:= filePathAndName
If you want to do it through the UserForm, you're probably going to end up making a bunch of Windows API calls.
At the end of your code you can force a workbook to close without saving any changes, type the following code in a Visual Basic module of that workbook:
Sub Auto_Close()
ThisWorkbook.Saved = True
End Sub
Because the Saved property is set to True, Excel responds as though the workbook has already been saved and no changes have occurred since that last save.
EDIT:
Now I know what you're after I am going to presume you've created a button press for your form, so I think something like https://www.mrexcel.com/forum/excel-questions/544657-specifying-printer-printing-userform-using-vba.html . This will help you with what you want, as it will show you how to change the default print method, form PDF.

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.

VBA: Code not running after ToggleFormsDesign

I have the following code in VBA (MS Word), that is meant to run after I click in a button, named cmdFormPreencher inserted in my Document:
Private Sub cmdFormPreencher_Click()
'
If ActiveDocument.FormsDesign = False Then
ActiveDocument.ToggleFormsDesign
End If
'
ThisDocument.cmdFormPreencher.Select
ThisDocument.cmdFormPreencher.Delete
ActiveDocument.ToggleFormsDesign
'
UserForm2.Show
End Sub
The purpose of the code above is to delete that button inserted in my document.
But when I run the code only the button is selected. When I tried to figure out what is happening by debugging, it showed me the code runs until ActiveDocument.ToggleFormsDesign and not running the code remaining
Is this a bug of VBA, or am I doing something wrong? If so, how can I get around this problem?
Thanks!
Note: The ActiveX button is not in Header and Footer. The Text Wrap is set to In Front of Text
Edit:
When I try to run a macro, activating FormDesign, Selecting the ActiveX button and then deleting, I get this code:
Sub Macro1()
'
' Macro1 Macro
'
'
ActiveDocument.ToggleFormsDesign
ActiveDocument.Shapes("Control 52").Select
Selection.ShapeRange.Delete
ActiveDocument.ToggleFormsDesign
End Sub
But when I run this code nothing happens...
This is by design. When an Office application is in Design Mode code should not run on an ActiveX object that's part of the document.
I take it this is an ActiveX button and in that case, it's a member of the InlineShapes or Shapes collection - Word handles it like a graphic object. It should be enough to delete the graphical representation, which you can do by changing it to display as an icon instead of a button.
For example, for an InlineShape:
Sub DeleteActiveX()
Dim ils As word.InlineShape
Set ils = ActiveDocument.InlineShapes(1)
ils.OLEFormat.DisplayAsIcon = True
ils.Delete
End Sub
You just have to figure out how to identify the InlineShape or Shape. You could bookmark an InlineShape; a Shape has a Name property.
EDIT: Since according to subsequent information provided in Comments you have a Shape object, rather than an InlineShape, the following approach should work:
Dim shp As word.Shape
Set shp = ActiveDocument.Shapes("Shape Name") 'Index value can also be used
shp.Delete
Note that Word will automatically assign something to the Shape.Name property, but in the case of ActiveX controls these names can change for apparently no reason. So if you identify a control using its name instead of the index value it's much better to assign a name yourself, which Word will not change "on a whim".
Activate Design Mode.
Click on the control to select it
Go to the VB Editor window
Ctrl+G to put the focus in the "Immediate Window"
Type the following (substituting the name you want), then press Enter to execute:
Selection.ShapeRange(1).Name = "Name to assign"
Use this Name in the code above

VBA How do you copy and paste in a Userform using right-click?

I want to allow users to be able to paste values into TextBoxes in a userForm in VBA. You can use Ctrl-v just fine, but not everyone knows how to do that.
How do I enable copy and pasting using a right-click menu?
I realize this is an old post but I believe there is a more efficient method.
Userform Contextual Menu class code
http://www.andypope.info/vba/uf_contextualmenu.htm
There are even sample excel spreadsheets for the code examples.
The class module handles the construction of the contextual menu, the capture of right clicking in textboxes and the actual Cut. Copy and Paste actions. The class makes use of the userform's ActiveControl object. The code even handles controls within container controls such as Frames and Multipage.
The follow Initialization code, from the userform, shows how simple it is to define and use the class object. You only need declare a variable to the object and then set a reference for each textbox you want to have contextual menu capabilities. You can loop through all controls and automatically reference each textbox.
Private m_colContextMenus As Collection
Private Sub UserForm_Initialize()
Dim clsContextMenu As CTextBox_ContextMenu
Dim cTRL as Control
Set m_colContextMenus = New Collection
For Each cTRL In Me.Controls
Select Case TypeName(cTRL)
Case "TextBox"
'MsgBox cTRL.Name & ": " & Me.Controls(cTRL.Name).Value
Set clsContextMenu = New CTextBox_ContextMenu
With clsContextMenu
Set .TBox = Me.Controls(cTRL.Name)
Set .Parent = Me
End With
m_colContextMenus.Add clsContextMenu, CStr(m_colContextMenus.Count + 1)
Case Else
'MsgBox TypeName(cTRL) & ": " & cTRL.Name
End Select
Next
End Sub
Download example workbook which contains both .xls and .xlsm files
This may be of interest: http://word.mvps.org/faqs/userforms/AddRightClickMenu.htm