I have a spreadsheet set up with large text entries stored for selective copy-and-paste into another application; I am trying to devise a simple way for the user to (selectively) copy the text from any cell into the Clipboard, so that they can easily paste it into another application; all the while protecting the integrity of the source material.
The following code WORKS as desired:
**Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim OutputObject As DataObject
Dim CellText As String
CellText = Target.Text
Set OutputObject = New DataObject
OutputObject.SetText CellText
OutputObject.PutInClipboard
End Sub**
However, the result of the double-click leaves the cellpointer inside the cell (in EDIT mode), which puts the contents of the cell at risk of being overwritten.
Inserting "CANCEL = True" should solve the problem by cancelling the effects of the double-click, leaving the cell SELECTED but not in EDIT mode. However this results in the Clipboard being empty as nothing pastes into the outside application (Notepad).
The exact same code -- for some inexplicable reason -- DOES NOT work as expected within the Worksheet_SelectionChange(ByVal Target As Range) subroutine!?!?!
I have also tried creating an ActiveX button on the spreadsheet; the button uses relative direction logic to determine which cell's text to copy, but AGAIN ... nothing pastes into the outside application (Notepad).
Any thoughts?
Using SendKeys in an Event Procedure
SendKeys statement
You could add the following to your Worksheet BeforeDoubleClick event code.
The Code
With Application
.ScreenUpdating = False
.SendKeys "{ENTER}{UP}"
.ScreenUpdating = True
End With
Related
I've created a drop down menu through data validation for workbook navigation. The following is a snippet of code I have for the drop down box to change worksheets in the workbook:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then _
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets("Imported Data").Visible = False
End Sub
The code is meant to hide all other worksheets that are accessible by the drop down list besides the one selected. I have about 10 tabs and this code has worked perfectly to achieve the basic goal of navigation. However, some pages have formulas and when you update data in the cells meant for calculations the workbook jumps to a random worksheet in the workbook that is not at all referenced in this sub.
Is there some way to have my worksheets not try to do anything with this sub unless the dropdown menu itself is changed?
Bonus (less important) Question: is there a way to make the drop box default to (blank) unless the menu itself is accessed?
Then _
The space followed by an underscore _ means that the current statement isn't finished yet but continues on the next line. Right now the last 3 lines will run whenever there is a change in the worksheet. Put the entire code in If-Endif.
Also avoid unnecessary use of On Error Resume Next. Use proper error handling.
You need to make the sheet visible before you activate it and not vice versa.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets("Imported Data").Visible = False
End If
Letscontinue:
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
is there a way to make the drop box default to (blank) unless the menu itself is accessed?
If you have created it with Data Valdation then insert a blank value in the list.
I've read various posts about using VBA to prevent format changes to spreadsheets caused by the user pasting data.
I didn't like the approaches binding CTRL+V to a macro because the user may not use the shortcut, and some examples had the effect of pasting into any cell that was subsequently clicked on.
I've had most success with the code from https://www.mrexcel.com/board/threads/vba-for-pastespecial-values-only.355553/ which uses the undo function. This works (although it's a little slow) for copy and paste within the workbook, and with single or multiple cells, but not from other instances of Excel or other programs.
I found Excel vba paste special method fails whenever i try to paste which works with pastes into a single cell.
Is there a way to combine the two and achieve the aim of preventing paste from any source changing cell(s) formatting?
I think I've written something useful that seems to work well for me.
I didn't implement your suggestion as it seemed fairly complex, and I found another forum post with a slightly different form of the 'undo' based scripts that worked well for copy and paste of text or single cells, or ranges from within an instance of excel or from external programs. I've combined that with the more common version I'd found which deals with 'Auto Fill' events too, and I've added some other little enhancements.
I've acknolwedged the other forum posts which I used too. Here it is in case it is of use to other people. I'm not an expert and I expect the code could be improved, but it does what I need.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
'Prevents user changing cell formatting by undoing the paste and pasting the value only without formatting
'Macro restricted to run on paste events to prevent the pasting of formats into the spreasheet, but not run on delete or type events
'Works with ranges and individual cells, both within the workbook Excel instance and from other instances or external programs
'A combination of:
'https://www.mrexcel.com/board/threads/force-paste-special-values.230718/
'https://stackoverflow.com/questions/45135039/excel-vba-code-to-force-values-only-paste-causes-strange-behavior-when-pasting-o
'And:
'https://answers.microsoft.com/en-us/msoffice/forum/all/how-do-you-lock-formats-but-allow-data-entry/afccc43e-e191-417f-826c-d10a464a1b9a?page=4
'A disadvantage of many macros, including this one, is that the undo history is cleared
'Macro can be disabled for spreadsheet developement by changing the Devel value used in the first IF statement of the macro
Dim Devel As Boolean
Devel = "False" 'Remember to set back to False after spreadsheet development work
If Devel = "False" Then
'In normal user mode, prevent pastes etc from changing formatting
Dim SavedVal As Variant
Dim UndoString As String
Dim srce As Range
On Error GoTo ErrHan
'Detect 'Paste' and 'Auto Fill' events in the undo list and only continue macro if these are found
UndoString = Application.CommandBars("Standard").Controls("&Undo").List(1) 'This always gives an error on spreadsheet open as the undo list is empty, but the error handling deals with it
If Left(UndoString, 5) <> "Paste" And UndoString <> "Auto Fill" Then
Exit Sub
End If
'Save the pasted value for later. This form and the use of type Variant is important in the flexibility of this macro
SavedVal = Target.Value
'Switch off events to prevent infinite loop
Application.EnableEvents = False
'Switch off screen updates
Application.ScreenUpdating = False
'Undo the user's paste
Application.Undo
'Handle 'Auto Fill' events differently. These can use the Target.PasteSpecial approach
If UndoString = "Auto Fill" Then
Set srce = Selection
srce.Copy
Target.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Application.SendKeys "{ESC}"
Union(Target, srce).Select
Else
'Set target value. This form works with all selected data which the Target.PasteSpecial approaches don't
Target.Value = SavedVal
End If
Else
'In Devel mode so the developer can unlock the spreadsheet and change formats when pasting
End If
ErrExit:
'Remember to re-enable events
Application.EnableEvents = True
'Re-enable screen updates
Application.ScreenUpdating = True
Exit Sub
ErrHan:
Resume ErrExit
End Sub
I have a worksheet_change macro embedded in two sheets within my workbook. They are there to prevent anyone making changes to the sheets. However, I still want the data within the sheets to be refreshed every so often. This does not work.
Two sheets within the workbook are connected via a query to another workbook. Essentially those sheets are a copy of the sheets within the other workbook.
I have embedded Code1 into the two worksheets. This is to prevent anyone making changes to the worksheet but still allow them to view the sheet and copy data from it. It brings up an message box and then undoes the change made by the user. This works fine and I am happy with it.
At the same time I want to be able to refresh the workbook so that the connected sheets are up to date with respect to the other workbook that they are connected to.
To do this I have added a button into the workbook called "Refresh". This button calls Code2. This was done with the intention of disabling events so that the worksheet_change macro is paused to allow for the data to be refreshed.
However, this does not work as the worksheet_change macro still works. I.e after clicking the button, the workbook is refreshed and then any update is undone and the message box is displayed - which isn't what I need.
CODE1
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
' The variable KeyCells contains the cells that will
' cause an alert when they are changed.
Set KeyCells = Range("A1:Z1000")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
With Application
.EnableEvents = False
.Undo
.EnableEvents = True
End With
' Display a message when one of the designated cells has been
' changed.
' Place your code here.
MsgBox "DO NOT MODIFY THIS SHEET - Any necessary modifications should be made in 'Master Invoice Template' and this sheet will automatically be updated!"
End If
End Sub
CODE2
Sub refresh()
On Error GoTo ErrorHandler
Application.EnableEvents = False
ThisWorkbook.RefreshAll
ErrorHandler:
Application.EnableEvents = True
End Sub
I have scoured the internet for a solution and pretty much everything that I find points me in the direction of enableevents=false, but as described in my post this does not work. Do I need to change the method of solving my problem or am I doing something wrong within my code?
I suspect the undo line of code is causing the problem, but I am not sure!
Any help would be greatly appreciated!
I think I have figured out what was wrong with the code; correct me if I am wrong. The data was taking too long to refresh when Code2 was ran. This meant that the Application.EnableEvents = Ture in Code2 took effect before the data could be fully refreshed and when it finally did complete its update, the Worksheet_Change event was triggered.
I tried using DoEvents after the RefreshAll command but this didn't work either. I have used what I found in this post to work around the problem and the refresh button now works!
Specifically the code that helped is below: I replaced Code2 with this:
Sub Refresh_All_Data_Connections()
For Each objConnection In ThisWorkbook.Connections
'Get current background-refresh value
bBackground = objConnection.OLEDBConnection.BackgroundQuery
'Temporarily disable background-refresh
objConnection.OLEDBConnection.BackgroundQuery = False
'Refresh this connection
objConnection.Refresh
'Set background-refresh value back to original value
objConnection.OLEDBConnection.BackgroundQuery = bBackground
Next
MsgBox "Finished refreshing all data connections"
End Sub
Please let me know if my logic in explaining why the code didn't work is correct - I am still new to VBA and would like to understand the problem fully!
While Navigating my sheet I use the F5+[enter] to navigate back to the cell that I hyperlinked from on a different sheet in the same workbook.
I have now made an Activex button to act as a back button but I need the script to make it do an F5+[enter] when clicked on.
I have lots of hyperlinks from different areas that go to one specific sheet and I basically want the Activex button to return the cursor back from whence it came.
Any help would be appreciated
Thank you
*****Sorry My fault I meant Active X Button*****
Edited and re tagged. Much appreciated
Since application.goto function stores the last reference as default you can simply bind a key for the following command
Application.Goto
This is not the perfect solution but it will do what you want. All you need to do is add this line to button_click.
As a general note, mimicking the actions of the keyboard through VBA involves using the Application.SendKeys command. In your specific case, the code would be:
Application.SendKeys "{F5}"
Application.Wait (Now + TimeValue("00:00:01"))
Application.SendKeys "~" 'The tilde is the Enter key
Generally, I prefer not to use this methodology. On my computer, for example, the third line of code runs before the first line has completed its action. In that case, I'm sitting with the Go To dialog box on my screen. That's why I separate the two lines with a call for the system to delay processing.
EDIT: (I think I cut off part of my original post)
In my opinion, your best bet is to allow Excel to handle the flow back to the hyperlink cells. The also opens up the possibility to move back beyond just the last cell. Below is a loose example of the code, which should be adapted.
In a module, enter the below code:
Public strLastSheet(1 To 10) As Worksheet
Public strLastRange(1 To 10) As Range
Public nLastCell As Integer
Public nCurrentIndex As Integer
Sub SelectLastHyperlinkedCellFoShizzle()
strLastSheet(nCurrentIndex).Activate
strLastRange(nCurrentIndex).Select
If nCurrentIndex <= 1 Then
'Do Nothing
Else
nCurrentIndex = nCurrentIndex - 1
End If
End Sub
In the ThisWorkbook code, enter the following:
Private Sub Workbook_Open()
nLastCell = 0
nCurrentIndex = 0
End Sub
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh As Object, ByVal Target As Hyperlink)
nLastCell = nLastCell + 1
Set strLastSheet(nLastCell) = Sh
Set strLastRange(nLastCell) = Target.Parent
nCurrentIndex = nLastCell
End Sub
This is set to store the previous 10 hyperlink addresses. It should be further modified to disallow entries beyond 10 into the array, and perhaps shift the previous entries down the array.
want to use a Spin button (ActiveX Control) to show a previous or next sheet. When the button is clicked the event is successfully triggered and the desired sheet is activated but it holds some elements (commands, graphs, etc.,) from the original sheet and shows these as an appending picture.
Sample code for Down button event :
Private Sub SpinButton_JumpToWeek_SpinDown()
Dim sh_num As String
Dim tmp_num As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
SpinButton_JumpToWeek.Value = Range("B27").Value - 1
tmp_num = SpinButton_JumpToWeek.Value
' Activate desired KTx sheet
sh_num = "KT" & tmp_num
Range("F27").Value = "" 'reset to blank
Sheets(sh_num).Activate
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
To override this effect I have to manually select (activate) another sheet and then again select the desired sheet. I tried also to automatize this workaround with a macro, but unfortunately it does not work.
It is interesting that this problem do not occur if I execute code in Debug mode (using breakpoint and the stepping line by line).
Surprisingly, I do not have such problem if I try to show the previous/next sheet by writing a value (sheet name index) into a defined cell (i.e. using the Worksheet_Change event). The desired page is correctly shown. See photos.
Sample code for this evententer image description here:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim sh_num As String
Application.ScreenUpdating = False
Application.EnableEvents = False
If Range("F27").Value > 0 Then
' Activate desired KTx sheet
sh_num = "KT" & Range("F27").Value
Range("F27").Value = "" 'reset to blank
Sheets(sh_num).Activate
End If
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I need to use the Spin button because it is faster and allow me to skip some sheets (for example if these do not have data).
The problem occurs in both 32 and 64-bit Excel.
Do somebody an idea why this problem is occurring and a workaround? Do I have to change some settings or system properties in Excel? Any help would be highly appreciated.
#mehow
I append my commenst here due to large number of words.
I followed your suggestion and tried the example of a UserForm with inserted active control “Microsoft Office Spreadsheet”. I found out that this would not be a good solution for my case, because the response of such sheet is relatively slow (even on a fast PC like mine) when user inserts values into cells. Furthermore, this would greatly complicate my fairly simple *.xlsm workbook, which has more than 50 sheets (1 sheet for each week, the contents of these sheets are then linked to a main sheet), and completely meets my basic necessities (with the exception of this spin button of course).
In my opinion there is probably necessary to manipulate some kind of system property (like for e.g. Application.ScreenUpdating trick), but I do not have enough VBA knowledge to find it.
To clearly explain my question I would need to share my sample workbook, but I do not know how to upload it to this forum. Unfortunately, I am not able upload/show images successfully on this forum (due to my low rating), which would also help a lot.
BTW, I cannot see images on other questions of this forum, too. . Could this problem occur due to missing plugins in a web browser?
You can use a simple trick... before the "Application.screenupdating = true" you can insert the two lines:
ActiveWindow.SmallScroll Down:=-100
ActiveWindow.SmallScroll Up:=100