I'm trying to build a protected worksheet where one of the cells has the following qualities:
Double-clicking the cell populates it with "hello".
The cell can only be blank or contain the word "hello".
So I decided to put validation on the cell, and write a worksheet_beforeDoubleClick() event.
Let's say it's cell A1. Starting with a blank worksheet, in B1 I enter "hello", and I set A1's validation as a list with range B1:B2.
My double-click event code is as follows:
Private Sub worksheet_beforedoubleclick(ByVal Target As Range, Cancel As Boolean)
If Target.Row = 1 And Target.Column = 1 Then
Target.Value = "hello"
End If
End Sub
This code and validation works fine while the sheet is unprotected; the cell populates with "hello" when double-clicked.
However, once the sheet is protected, double-clicking on cell A1 turns the mouse pointer into an hourglass until I press Esc or click on another cell; the cell does not populate with the word "hello".
Any idea what's going on?
When you protect the sheet, check the "Edit Objects" checkbox and it will work. Don't know quite why, but it will.
Thanks Doug for a lead in the right direction. For future reference, a good VBA snippet for this is:
ActiveSheet.Protect UserInterfaceOnly:=True, DrawingObjects:=False
This will protect the sheet, but allow macros to edit the sheet, as well as clear up the conflict described here.
While the answers above with unprotecting the drawing objects works, the end solution with respect to the user being able to right click and edit drawing object shapes is not always acceptable.
My work around was to use a checkbox to the left of the cell and add a macro that did what my double click action originally was doing.
Related
I have a picturebox on my form. When I click on it, I want it to preform a function (in this case, setting a value to a variable). I, however, have not found any way to do this.
The picturebox, should during runtime, when clicked, set a value to a variable.
I have considered putting a textbox over the picturebox and making it transparent, but I have not found a way to make textboxes transparent via visual basic. There should be a more direct way available?
Can I get some help? Thanks.
You can double click on the picture box and it will bring up the code. From there insert the code you want
Private sub picture1_click()
End sub
code that will show a message box after inserting data on the last cell of a column in datagrid. my program runs like this, when i click a button, a value will be added to the first cell then will triggered rs.MoveNext, when i click again the button the same process takes place, the problem is that when i reach the last cell and click the button again, the data i put on the last cell just replace with the new one. please help me with a code that will stop rs.MoveNext if i reach the end of file.
Try using MsgBox "Finished" without using the brackets ("").
UPDATE3 - SOLVED with reservations, please see my solution below; leaving it open since the cause of the problem is unclear, and I don't know how robust the solution is.
UPDATE1: here's the short short version.
Currently, after .setEditText on a QComboBox, I get this:
so the next thing you type will overwrite 'Team '.
But the desired effect is this (unhighlighted / unselected), so that the next thing you type will be appended to 'Team ' instead of overwriting it:
Thanks for any help. The rambling details are below, which is the original post:
(this is all PyQt 5.4)
UPDATE2:
Apparently python doesn't think anything is actually selected:
self.entryForm.ui.teamField.lineEdit().setText("Team ")
print("selected text:"+self.entryForm.ui.teamField.lineEdit().selectedText())
prints "selected text:" and nothing else. To make sure that's working:
self.entryForm.ui.teamField.lineEdit().setText("Team ")
self.entryForm.ui.teamField.lineEdit().setSelection(0,4)
print("selected text:"+self.entryForm.ui.teamField.lineEdit().selectedText())
prints "selected text:Team"
So that might be why many of the methods that affect selection are not working as expected (.deselect(), .setSelection(5,5), etc, and even some of the other methods give unexpected behavior, i.e. cursorForward(False,1) or cursorBackward(False,1) and such.
Original post:
This is for a radio log GUI, so keyboard interactions must be minimal and intuitive. openNewEntryForm (below) is called as a slot from a pushbutton on the main application GUI window:
self.ui.pushButton.clicked.connect(self.openNewEntryDialog)
It can also be called using a keyPressEvent in the same class:
def keyPressEvent(self,event):
if type(event)==QKeyEvent:
print("QKeyEvent:"+str(event.key()))
if event.key()==Qt.Key_T:
self.openNewEntryDialog('t')
event.accept()
else:
event.ignore()
Here's the method in question:
def openNewEntryDialog(self,key=None):
self.entryDialog=newEntryDialog()
if key=='t':
self.entryDialog.ui.to_fromField.setCurrentIndex(1)
self.entryDialog.ui.teamField.setFocus()
self.entryDialog.ui.teamField.setEditText("Team ")
if self.entryDialog.exec_():
self.newEntry(self.entryDialog.getValues()) # adds the log entry
so, the intended key press sequence is (from the main application GUI window):
a single keyboard press of 't' will open the entryForm, set the to_fromField to index 1 (which happens to be "TO"), give focus to teamField (also a QComboBox), set its text to "Team " and set itself up so that the very next keypress will appear as the text following "Team " in teamField.
So, starting from the main app GUI again, the plan is that typing 't3' should open the new entry window, set the to_fromField to "TO", and set the teamField to "Team 3", ready for a keypress of the tab key to move on to the next field in the entryForm.
The problem is that the teamField.setEditText("Team ") call leaves all of the text highlighted/selected, so that a subsequent key press of '3' would replace "Team " with "3"; I'm looking for a way to unhighlight/unselect "Team " but leave the cursor active at the right of that string, so that the subsequent key press of '3' would make the entire string "Team 3".
Ideas? Thanks in advance.
You can access the line-edit of the combo box, and then remove the selection:
self.entryDialog.ui.teamField.setEditText("Team ")
self.entryDialog.ui.teamField.lineEdit().deselect()
UPDATE:
The above code is correct, but it seems that the dialog will then clobber it when it initialises the focus handling for its child widgets after it is shown. If a dialog is opened with exec(), it will start its own event-loop, and some events (including focus events) will only be processed after it is fully shown. This is why it may appear that some changes made to child widgets before the dialog is shown are being ignored.
One way to work around this is to use a single-shot timer to ensure the changes are only attempted after the dialog is shown.
So add a method to the entry dialog class something like this:
def resetUI(self, key):
if key == 't':
self.ui.to_fromField.setCurrentIndex(1)
self.ui.teamField.setFocus()
self.ui.teamField.setEditText('Team ')
QtCore.QTimer.singleShot(0, self.ui.teamField.lineEdit().deselect)
and then use it like this:
def openNewEntryDialog(self, key=None):
self.entryDialog = newEntryDialog()
self.entryDialog.resetUI(key)
if self.entryDialog.exec_():
self.newEntry(self.entryDialog.getValues())
SOLVED with reservations, see UPDATE3 in the original post.
So, with the initial text all highlighted, tests show that it didn't actually think anything was selected. This solution was just stumbled upon by trial and error, fiddling with setting and clearing focus, selecting text and trying deselect:
def openNewEntryDialog(self,key=None):
self.entryForm=newEntryDialog()
if key=='t':
self.entryForm.ui.to_fromField.setCurrentIndex(1)
self.entryForm.ui.teamField.lineEdit().setFocus()
self.entryForm.ui.teamField.lineEdit().setText("Team ")
self.entryForm.ui.teamField.lineEdit().setSelection(5,1)
Notice there are two spaces after 'Team' and the second one is intentionally selected. Then the very next keypress will overwrite that second space; that is basically the desired behavior.
Anyway it looks like something bizarro with the selection scheme; one way to look at this is that the highlight isn't really a selection, but, if you set a valid real selection then it will override the original highlighted 'pseudo-selection'. The original highlighting behaves like a selection in that a keypress will replace everything that's highlighted, but, not like a selection in that the selection methods reveal that there is no 'selection', see UPDATE2 in the original post.
Can anyone help explain this behavior? I'd like to build some more confidence in it before accepting this coincidental answer.
Thanks
I have recently been asked if I could make a macro in Excel VBA that will allow a user to type in two numbers and have it automatically drop to the next row. The purpose of this is so they can type in grades for a test two numbers at a time without pressing enter since they aren't great at typing.
When I first heard this he mentioned it was Visual Basic, so I figured I'd just use a TextChanging or TextChanged event in the cell range and have it work off that. However, I haven't been able to find any such event or anything resembling it in the documentation thus far. The first thing that I came across was Workbook_Change, but that only changes after you press enter which is useless to me. Someone else mentioned there is such an event, but couldn't name it directly and I haven't been able to find what they were talking about.
If anyone has any information on if such an event exists or is possible I'd love to know.
The Excel version is 2007 as far as I'm aware.
This, in my opinion, requires a non-programming solution. I absolutely sympathize - it is tough to watch people get old - but you have to draw the line somewhere - for their sake and yours. The enter key is the most basic part of a computer. You could probably write a macro that would automatically hit enter on every even(or odd depending) keystroke in excel - but you're going to run into other problems like not being able to use delete normally. And what if you do want to put a string of text in a cell(like the student's name)? Perhaps it is time to find a non-programming solution. By that I mean someone should have a candid conversation with him about how he wants to solve the problem. Personally, I would offer to type the numbers in for him, as I am accustomed to the number pad - but it is probably better to be more direct and start to discuss retirement.
See this discussion about the limitations of cell edit mode in excel:
http://www.mrexcel.com/forum/excel-questions/524860-call-macro-every-keystroke.html
If you're really heart-set on a programming solution, I would recommend some kind of keystroke logging add-in.
Good Luck.
You could use the Worksheet_SelectionChange event. It is triggered without enter, but it would be triggered a lot.
You could however also create a special user-form for typing in the data, but this might be more work than necessary.
The main problem with using my suggested event is, you will need it as trigger and trigger it yourself, when selecting the next row, so disable event handling before changing the selection.
Edit:
This is a quick solution (paste this into the vba-code of the desired worksheet):
Private Const clngColumnRightToLastGrade = 5
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Column = clngColumnRightToLastGrade Then
Application.EnableEvents = False
'offset selection, one row down, two cols to left
Target.Offset(1, -2).Select
Application.EnableEvents = True
End If
End Sub
This will set you one row down and to column C, everytime your selection changes to column E (=5).
You don't have to use a constant of course, you could specify the column to sense in the workbook, so your user might modify it easier by himself.
To make this as an optional feature, you could extend it to autogenerated code. What I have in mind is like a Ribbon-Button, which opens a setupForm to configure, and a Ribbon-Button to activate the configuration, which would place this code in the configured sheet. But this might be a bit over the top.
In Excel 2003, (may be different in Excel2007 ?!) the WorkSheet_Change event is triggered every time the value of a cell is changed wether it is by pressing enter, delete, selecting an other cell after modifying a cell or even when a vba script changes the value of a cell.
I would do something like that:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RefRange As Range
Set RefRange = Intersect(ActiveSheet.Columns("??????????"), ActiveSheet.UsedRange)
If Not Intersect(Target, RefRange) Is Nothing Then
Target.Offset(0, 1).EntireColumn.Range("A1").Select
'Target.Offset(0, 1).EntireColumn.Range("A65536").End(xlUp).Offset(1,0).Select
End If
End Sub
Is there a method such that a user can click on the form itself, and in doing so remove focus from whatever object (textbox, combobox, etc) currently has it? Basically, can focus be uniformly removed from everything at once?
Setting the focus to the form itself does not work.
I thought about doing the old "hide a placeholder button behind another object" trick, but I'm really not a fan of that.
Thanks!
In VB6 a PictureBox can get focus, even if it does not contain any control.
In your case you can put a PictureBox with TabStop false, BorderStyle set to 0, TabIndex set to 0 behind every other control but not containing any focusable control and stretch it to ScaleWidth by ScaleHeight at run-time.
You have to put the labels and any windowless control in this background PictureBox too.
This way when the user clicks "on the form" the focus will "go away". With "no focus" Tab key will focus first control (the one with TabIndex set to 1).
When a form is active, something generally HAS to have focus. It sounds like you're just wanting to not "show" that a particular control has focus.
If that's the case, it's going to depend on the controls. Some have properties that control whether or not the specific control "indicates" its focus in some way.
But the built in Windows controls will always show their focus state unless you subclass them
Given this problem. I'd probably put a button on the form , then move it offscreen when the form loads. Make sure it's not a tab stop, but then when you want to hide focus, set focus specifically to the button, make sure the button is STILL in the tab order, even though it's not a tab stop, so the user can press tab while on the button and end up somewhere logical.
Don't have VB handy, but could you simply remove TabStop?
for x = 1 to me.Controls.count
me.Controls(x).TabStop = 0
next
I have a picturebox and a control on a form.
Private Sub cmdButton_Click
PictureBox.setFocus
Exit sub
End sub
The control doesn't change its appearance, nor does the picturebox.
Of course you'll need to add an If-Then clause if you want the control to respond normally sometimes.