Continuous Press on Command Button - vba

If my mouse is pressed continuously on the Spin Button, the increment keeps happening. However, the Command Button requires me to click again and again. How can I have the Command Button behave in a similar fashion to that of a Spin Button?
Private Sub CommandButton2_Click()
Label1.Caption = Int(Label1.Caption) + 10
End Sub
Private Sub spbSpinButton_Change()
spbSpinButton.Min = 100
spbSpinButton.Max = 200
spbSpinButton.SmallChange = 10
Label1.Caption = spbSpinButton.Value
End Sub

You can't do it with the Click event, but if you keep track of MouseUp and MouseDown you can trigger a loop. Something like this:
Add a module
Put this code in the module. Give the module any name, but it is referred to as Module1 below.
#If VBA7 Then
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 'For 64 Bit Systems
#Else
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
In your Form
Put this in your Module
Dim ButtonDown As Boolean
Private Sub UserForm_Activate()
ButtonDown = False
End Sub
Private Sub CommandButton1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ButtonDown = True
IncrementCounter
End Sub
Private Sub CommandButton1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
ButtonDown = False
End Sub
Sub IncrementCounter()
If ButtonDown Then
Label1.Caption = Int(Label1.Caption) + 10
DoEvents
Module1.Sleep 100
IncrementCounter
End If
End Sub
The Module1.Sleep 100 says wait 100 milliseconds. Adjust to your need.

Related

Display Excel sheet with macro inside form

I got application in .net and I would like to display excel sheet with macro inside my form. I found code that display excel file inside panel and everything works ok but once I run macro its frozen. If I will not run macro Its work fine.
Imports excel = Microsoft.office.interop.excel
Imports office = Microsoft.office.core
Public Class Form1
Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const WM_SYSCOMMAND As Integer = 274
Private Const SC_MAXIMIZE As Integer = 61488
Private Sub btnShowExcel_Click(sender As Object, e As EventArgs) Handles btnShowExcel.Click
Dim sExcelFileName = "D:\123.xlsm"
Dim oExcel As New Excel.Application
oExcel.DisplayAlerts = False
oExcel.Workbooks.Open(sExcelFileName)
oExcel.Application.WindowState = excel.XlWindowState.xlNormal
oExcel.Visible = True
SetParent(oExcel.Hwnd, pnlExcel.Handle)
SendMessage(oExcel.Hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
End Sub
End Class
Could anyone help me to change this code or find different one so I could display excel file with macro and macro will work without any problem.
Thanks
Regards
Mark

Display always full screen in excel with vba

I want that my excel xml always display in full screen view.
For this I code the next:
Private Sub Workbook_Open()
Application.WindowState = xlMaximized
ActiveWindow.WindowState = xlMaximized
Application.DisplayFullScreen = True
End Sub
It is working fine until I minimize excel, once I maximize again It shows in normal view mode, how to proceed? Any suggestion? The main idea is to remove the tool bars as I don't want user to interact with them.
Paste this into the workbook module. It will maximize the windows whenever it gets resized:
Private Sub Workbook_WindowResize(ByVal Wn As Window)
ActiveWindow.WindowState = xlMaximized
End Sub
There is an event that you can trap I'd try adding this to your ThisWorkbook module
Option Explicit
Private mbToggle As Boolean
Private mlPriorState(-1 To 0) As XlWindowState
Private Sub Workbook_WindowResize(ByVal Wn As Window)
mlPriorState(mbToggle) = Wn.WindowState
mbToggle = Not mbToggle
If Wn.WindowState = xlNormal And mlPriorState(mbToggle) <> xlMaximized Then
ActiveWindow.WindowState = xlMaximized
End If
End Sub
Though this may only work on windows that represent the worksheet/workbook. I'd try this first; other solutions involving Windows API are way more complicated.
Folded in some feedback. This code works for me.
Workbook_Activate will bring full screen mode while other will bring back normal mode.
Private Sub Workbook_Activate()
On Error Resume Next
With Application
.DisplayFullScreen = True
.CommandBars("Worksheet Menu Bar").Enabled = False
End With
End Sub
Private Sub Workbook_Deactivate()
On Error Resume Next
With Application
.DisplayFullScreen = False
.CommandBars("Worksheet Menu Bar").Enabled = True
End With
End Sub
EDIT
you shouldn't 'modify' the way Windows works at a system level. However, if you really, really must; add the following to a new module and call the SetStyle procedure.
That code is offered UNTESTED'as is' - the API is a way to modify Windows at a system level and can be dangerous (sudden crashes, data file corruption...) if you do not know what you are doing.
VB:
Option Explicit
'Related Windows API functions
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Long, ByVal bRevert As Long) As Long
Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function SetFocus Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hWndLock As Long) As Long
'Window style constants
Private Const GWL_STYLE As Long = (-16) '// The offset of a window's style
Private Const GWL_EXSTYLE As Long = (-20) '// The offset of a window's extended style
Private Const WS_CAPTION As Long = &HC00000 '// Title bar bit
Private Const WS_SYSMENU As Long = &H80000 '// System menu bit
Private Const WS_THICKFRAME As Long = &H40000 '// Sizable frame bit
Private Const WS_MINIMIZEBOX As Long = &H20000 '// Minimize box bit
Private Const WS_MAXIMIZEBOX As Long = &H10000 '// Maximize box bit
Private Const WS_EX_TOOLWINDOW As Long = &H80 '// Tool Window: small titlebar bit
'Constant to identify the Close menu item
Private Const SC_CLOSE As Long = &HF060
Public Sub SetStyle()
Dim lStyle As Long, hMenu As Long
'Get the basic window style
lStyle = GetWindowLong(Application.hWnd, GWL_STYLE)
If lStyle = 0 Then
MsgBox "Unable to determine application window handle...", vbExclamation, "Error"
Exit Sub
End If
'// Build up the basic window style flags for the form
'// Uncomment the features you want...
'// Set it True to enable, FALSE to disable
'// The first 2 are obvious, ThickFrame controls if the Window is sizable or not.
'// SetBit lStyle, WS_CAPTION, True
'// SetBit lStyle, WS_SYSMENU, False
'// SetBit lStyle, WS_THICKFRAME, False
SetBit lStyle, WS_MINIMIZEBOX, False
SetBit lStyle, WS_MAXIMIZEBOX, False
'Set the basic window styles
SetWindowLong Application.hWnd, GWL_STYLE, lStyle
'Get the extended window style
lStyle = GetWindowLong(Application.hWnd, GWL_EXSTYLE)
'// Handle the close button differently
'// If Close button is wanted
'// hMenu = GetSystemMenu(Application.hWnd, 1)
'// Not wanted - delete it from the control menu
hMenu = GetSystemMenu(Application.hWnd, 0)
DeleteMenu hMenu, SC_CLOSE, 0&
'Update the window with the changes
DrawMenuBar Application.hWnd
SetFocus Application.hWnd
End Sub
'// Set or clear a bit from a style flag
Private Sub SetBit(ByRef lStyle As Long, ByVal lBit As Long, ByVal bOn As Boolean)
If bOn Then
lStyle = lStyle Or lBit
Else
lStyle = lStyle And Not lBit
End If
End Sub

How to make a resizable UserFrom?

I do not know how to make the simplest in the world resizable UserForm. What I have seen on different forum threads are terrible behemots (huge as the Universe libraries doing too much). But I need a simple, one stroke solution and I hope it exists. At this moment I have this code:
Dim myForm As UserForm1
Set myForm = New UserForm1
myForm.Caption = "Attributes"
myForm.Show
And I have UserForm_Initialize() which does some extra work. What is horrible (unreasonable?) is that by default a form is not resizable.
Here's a simple guide on how to make a userform drag and re-sizable.
http://www.mrexcel.com/forum/excel-questions/558649-userform-movable-resizable.html
Here is transcribed solution from
https://www.mrexcel.com/board/threads/resize-a-userform.485489/
I have tested it and it works
First add these declaration to your header
'Declaration for form resize
Private Declare Function GetActiveWindow Lib "user32.dll" () As Long
Private Declare Function SetLastError Lib "kernel32.dll" (ByVal dwErrCode As Long) As Long
Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Add this sub to your form
Private Sub MakeFormResizable()
'Written: August 02, 2010
'Author: Leith Ross
'Summary: Makes the UserForm resizable by dragging one of the sides. Place a call
' to the macro MakeFormResizable in the UserForm'
'from https://www.mrexcel.com/board/threads/resize-a-userform.485489/
Dim lStyle As Long
Dim hWnd As Long
Dim RetVal
Const WS_THICKFRAME = &H40000
Const GWL_STYLE As Long = (-16)
hWnd = GetActiveWindow
'Get the basic window style
lStyle = GetWindowLong(hWnd, GWL_STYLE) Or WS_THICKFRAME
'Set the basic window styles
RetVal = SetWindowLong(hWnd, GWL_STYLE, lStyle)
'Clear any previous API error codes
SetLastError 0
'Did the style change?
If RetVal = 0 Then MsgBox "Unable to make UserForm Resizable."
End Sub
And finally call this sub from your Userform_Activate
Private Sub UserForm_Activate()
MakeFormResizable
End Sub

Position Userform differently for each ActiveCell clicked

I have a UserForm of a MonthView and DTPicker that will populate when certain cells are clicked.
I have the form positioned directly below the first cell.
I would like it positioned right below each active cell that I tell it to activate on.
My activate code to position the userform:
Private Sub UserForm_Activate()
With frmCalendar
.Top = Application.Top + 340
.Left = Application.Left + 330
End With
End Sub
My worksheet selection change code, which will launch the userform upon certain cell clicks:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("H10,H15")) Is Nothing Then
frmCalendar.Show
End If
End Sub
I know there are add-ins that help do this, but I'd like to figure out how to position the user form right below the cells mentioned above (H10, H14, H15) without using an add-in.
I changed the Activate Sub code
Private Sub UserForm_Activate()
With frmCalendar
.Top = ActiveCell.offset(31).Top
.Left = ActiveCell.offset(1).Left
End With
End Sub
This moves it slightly below and slightly to the right of the cell, but when I try it on another cell is moves further down but stays the same distance to the right. This still is messy.
Is there no way to position this form directly below the ActiveCell using these methods?
You are using the correct Event macro. I placed a TextBox in the worksheet and with this macro
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim s As Shape
Set s = ActiveSheet.Shapes(1)
s.Top = ActiveCell.Offset(1, 1).Top
s.Left = ActiveCell.Offset(1, 1).Left
End Sub
I can get the TextBox to move just to the right and just below the activecell.
I found http://www.vbaexpress.com/forum/archive/index.php/t-22038.html and developed this which I've used:
Sub showUform(iRow&, iCol&)
Dim x11!, y11!
ActiveSheet.Cells(iRow, iCol).Select
x11 = ActiveWindow.PointsToScreenPixelsX(ActiveSheet.Cells(1, 1))
y11 = ActiveWindow.PointsToScreenPixelsY(ActiveSheet.Cells(1, 1))
UserForm1.Left = x11 + ActiveSheet.Cells(iRow, iCol).Left
UserForm1.Top = y11 + ActiveSheet.Cells(iRow, iCol).Top
UserForm1.Show
End Sub
Sub FormToActCell(UF As Object, Optional RaD$ = "ACAD", Optional Topw% = 102, _
Optional TopH% = -120)
' form to Active cell or RaD as range address ,offsets topW topH
Dim Px&, Py&, Zoomp!
If RaD = "ACAD" Then RaD = ActiveCell.Address
Set CellToRange = Range(RaD)
With CellToRange ' get point about object to
Px = (.Left + .Width * Topw / 100)
Py = (.Top + .Height * TopH / 100)
End With
Zoomp = ActiveWindow.Zoom / 100
With UF ' assuming screen as normal pts to pix of 3:4
.Left = Px * Zoomp + ActiveWindow.PointsToScreenPixelsX(0) * 0.75
.Top = Py * Zoomp + ActiveWindow.PointsToScreenPixelsY(0) * 0.75
End With
End Sub
Please see the answer I provided to this question as I believe this question is the same.
How do I properly align UserForm next to active cell
by declaring the GetDeviceCaps , GetDC , ReleaseDC functions , I repositioned the userform next to each the clicked activecell .
(I checked the codes in 32-bit and 64-bit versions of Excel)
Type POINTAPI
X As Long
Y As Long
End Type
#If VBA7 Then
Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDc As LongPtr, ByVal nIndex As Long) As Long
Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDc As LongPtr) As Long
Dim hDc As LongPtr
#Else
Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDc As Long, ByVal nIndex As Long) As Long
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDc As Long) As Long
Dim hDc As Long
#End If
...
Source of codes & sample file

Closing Excel after inactivity, even in edit mode

I'm not sure this is possible I didn't really find anything when I was searching for an answer online. I have a macro in place where it will close after 5 minutes of inactivity. Works like a charm except when the user is editing a cell the timer does not start, therefore it will not close because of this. Is there a way for excel to have a timer for how long the user is in edit mode then it will take them out of it. Once out of edit mode the macro will start the 5 minutes of inactivity. Any help is greatly appreciated!
HERE IS THE WORKBOOK MODULE
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Me.Saved = True
End Sub
Private Sub Workbook_Open()
start_Countdown
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
stop_Countdown
start_Countdown
End Sub
HERE IS THE STANDARD MODULE
Option Explicit
Public Close_Time As Date
Sub start_Countdown()
Close_Time = Now() + TimeValue("00:05:00")
Application.OnTime Close_Time, "close_WB"
End Sub
Sub stop_Countdown()
Application.OnTime Close_Time, "close_WB", , False
End Sub
Sub close_wb()
ThisWorkbook.Close True
End Sub
You will need some kind of process monitor/task terminator outside of VBA to do this because VBA is "locked out" while the user is in input mode.
You can try this:
Public Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long) As Long
Public TimerID As Long
Public TimerSeconds As Single
Sub StartTimer()
TimerSeconds = 5*60 ' how often to "pop" the timer (5 minutes in the example).
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub
Sub EndTimer()
On Error Resume Next
KillTimer 0&, TimerID
End Sub
Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _
ByVal nIDEvent As Long, ByVal dwTimer As Long)
' call here whatever you want to call
End Sub
This always work even in edit mode, dont forget to call StartTimer to start and EndTimer before quitting...