When I click a button on my UserForm it goes to the relevant sheet (via .activate and then End Sub, but I have also tried .select) but I cannot edit the cell. However, when I click into the sheet normally via the bottom pane I can edit it again.
I have not found an excel log or process manager so I cannot see what macros could be running or data that is loading* and could be affecting this - does anyone have any idea of the possible reasons I can't edit cell values after using the UserForm?
Here's my code for the button in question (I added the Unload Me part in the hope it would stop any additional UserForm subs leftover:
Private Sub CommandButton1_Click()
Sheets("2H Campaigns View").Select
Unload Me
End Sub
*Our sheets use quite a bit of external data but if this were the case I assume clicking the bottom pane to edit wouldn't work either...
I have also tried shutting out of the UserForm (and nay possible macros its running) immediately after click with Unload Me but to no avail.
EDIT: I put a print to cell function (on a separate debug sheet) in at the end of each sub to check if there are any others running after the button is clicked, but it reads that the button (the above sub) is the last sub to run. Thus its safe to assume that the problem is unrelated to the below subs; isolated to either the button sub or something which the running of the button sub does to the settings for the workbook....
Other Subs used in this sheet (all under UserForm - cbSector_Change and UserForm_initalize draw sheet names in for two menus that categorize the pages; one is a sub menu of the other):
Private Sub cbSector_Change()
If cbSector.Value = "DIST" Then
With cbCampaign
.RowSource = Worksheets("Master Data").Range("G13").Value
.ListRows = Worksheets("Master Data").Range("H14").Value
.Value = Worksheets("Master Data").Range("b16").Value
End With
ElseIf cbSector.Value = "INDU" Then
With cbCampaign
.RowSource = Worksheets("Master Data").Range("gl7").Value
.ListRows = Worksheets("Master Data").Range("h17").Value
.Value = Worksheets("Master Data").Range("b16").Value
End With
ElseIf cbSector.Value = "CS" Then
With cbCampaign
.RowSource = Worksheets("Master Data").Range("gl8").Value
.ListRows = Worksheets("Master Data").Range("h18").Value
.Value = Worksheets("Master Data").Range("b16").Value
End With
End If
End Sub
Private Sub EButton_Click()
ThisWorkbook.Saved = True
ThisWorkbook.Close
End Sub
Private Sub SEButton_Click()
ThisWorkbook.Save
ThisWorkbook.Saved = True
ThisWorkbook.Close
End Sub
Private Sub UserForm_Initialize()
With cbSector
.RowSource = Worksheets("Master Data").Range("b13").Value
.ListRows = Worksheets("Master Data").Range("b14").Value
.Value = Worksheets("Master Data").Range("b12").Value
End With
End Sub
Private Sub cbSelect_Click()
If cbSector.Value = "(none)" Then
errormsg = "Please Select Sector"
ElseIf cbCampaign.Value = "(none)" Then
errormsg = "Please Select Campaign"
Else: errormsg = "nothing"
End If
If errormsg = "nothing" Then
Sheets(cbSector.Value & "_" & cbCampaign.Value).Select
Unload Me
Else: MsgBox (errormsg)
End If
End Sub
To launch the UserForm this code is attached to a button on all but one of the sheets in the workbook:
Public SheetSelected As Worksheet
Public errormsg As String
Sub CallUserForm()
nav.Show
End Sub
This is a partial answer to the last question you asked in the comments ("would there be any way to hack a manual sheet tab click in vba"?) I don't know how to do that directly, but here is an ugly hack which simulates using the Ctrl+PgUp and Ctrl+PgDn keyboard shortcuts to tab from one worksheet to another:
Sub PageToSheet(SheetName As String)
Dim here As Long, there As Long, i As Long
here = ActiveSheet.Index
there = Sheets(SheetName).Index
If here = there Then
Exit Sub
ElseIf here < there Then
For i = 1 To there - here
Application.SendKeys "^{PGDN}"
Next i
Else
For i = 1 To here - there
Application.SendKeys "^{PGUP}"
Next i
End If
End Sub
This won't work when the VBA editor is the active window. But if you launch the following test sub while the main Excel window is active it seems to work:
Sub test()
Dim s As String
s = InputBox("Enter name of sheet to go to")
PageToSheet s
End Sub
It would be better to try to track down the source of the bug that you are seeing and even experiment with transferring all data and code to a new workbook to make sure that you don't have an inexplicable corruption in the file itself (which is sometimes what is behind truly weird behavior). Still -- if you want to simulate manual page tabs you can via SendKeys.
Related
I already have a macro below that un-hides a worksheet at the click of a button and works okay. However I want this macro to be changed so that ONLY two users (whose usernames are "JSMITH" AND "DTAYLOR") are able to unhide this sheet called "Rates".
If someone else (whose username is not one of the two mentioned above) tries to unhide the sheet, I want Excel to display a message "you're not authorised to open this".
Moreover, I need to make sure that only those two users are able to un-hide in a traditional way without vba (eg by right-clicking on a visible worksheet tab and choose Unhide or from any worksheet tab, choose Format, Sheet, and then Unhide).
Could you please advise how to modify the following code to do the all the things described above?
I came up with this but it doesn't work:
Sub GoToRates_WS()
Select Case Environ$("username")
Case "jsmith", "taylor"
Worksheets("Rates").Visible = True
ThisWorkbook.Sheets("Rates").Activate
Case Else MsgBox "you're not authorised to open this"
End Select
End Sub
1- Open your ThisWorkbook code Module.
2- Paste this line at the top of it:
Private RatesVisible As Variant
3- find the following routine:
Private Sub Workbook_Open()
...
...
End Sub
Insert the following line just before the line End Sub:
RatesVisible = Worksheets("Rates").Visible
4- Delete your old routine GoToRates_WS
5- Copy the following code and paste it at the end of the code module:
Private Function privilegedUser() As Boolean
Select Case UCase(Environ$("username"))
Case "JSMITH", "DTAYLOR"
privilegedUser = True
Case Else
End Select
End Function
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
RatesVisible = Worksheets("Rates").Visible
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If Sh.Name <> "Rates" Then
RatesVisible = Worksheets("Rates").Visible
Exit Sub
End If
If privilegedUser Then
RatesVisible = Worksheets("Rates").Visible
Else
Worksheets("Rates").Visible = RatesVisible
End If
End Sub
Private Sub GoToRates_WS()
If privilegedUser Then
RatesVisible = xlSheetVisible
Worksheets("Rates").Visible = xlSheetVisible
Else
MsgBox "You are not authorized to open this worksheet"
End If
End Sub
I am currently doing a VBA code that needs to hide some sheets when the Excel file is closed and almost everything is working fine expects when I do the following steps:
make some change/insert data in the sheets
click the save button
make another change (that I do not want to save)
click to close the file and click not to save it
The problem is that I hide the sheets but since I do not save the file (because i do not want to save the changes made at step 3) the sheets are not hidden when I reopen the file. I cannot do this with the Workbook_open method because it is not allowed (at my project).
To do this I am rewriting the beforeclose method, as follows:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim Msg As String
Dim ireply As Integer
If Not Me.Saved Then
Msg = "Do you want to save the file?"
ireply = MsgBox(Msg, vbQuestion + vbYesNoCancel)
Select Case ireply
Case vbYes
Call hidesheets
Me.Save
Case vbNo
Me.Saved = True
Application.Quit
Case vbCancel
Cancel = True
Exit Sub
End Select
Else
Call hidesheets
Me.Save
End If
End Sub
Sub hidesheets()
ThisWorkbook.Sheets("Cars").Visible = xlVeryHidden
ThisWorkbook.Sheets("Brands").Visible = xlVeryHidden
ThisWorkbook.Sheets("Models").Visible = xlVeryHidden
ThisWorkbook.Sheets("Price").Visible = xlVeryHidden
End Sub
My questions is, it is possible just to save the hidden sheets configurations/settings without saving the information/data changed/inserted by the user?
PS: when I save the file and make any change the code works fine, i.e. hides the sheets.
Thank you all in advance
Regards
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
ThisWorkbook.Sheets("Cars").Visible = xlVeryHidden
ThisWorkbook.Sheets("Brands").Visible = xlVeryHidden
ThisWorkbook.Sheets("Models").Visible = xlVeryHidden
ThisWorkbook.Sheets("Price").Visible = xlVeryHidden
End Sub
You have to do the other way around
1) Set your workbook having those four sheets as very hidden per default
set them as such and then save your workbook to have it assume its default configuration
2) When you open it you make those sheets visible
Private Sub Workbook_Open()
ThisWorkbook.Sheets("Cars").Visible = True
ThisWorkbook.Sheets("Brands").Visible = True
ThisWorkbook.Sheets("Models").Visible = True
ThisWorkbook.Sheets("Price").Visible = True
End Sub
3) When you close it, you set those sheets back invisible
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'Your code to be processed upon closing the sheet
'...
Call hidesheets '<--| hide your sheets
End Sub
I've created a menu to navigate through sheets. But when I use one of the buttons to go to another sheet and type something in this another sheet the things that I type appear in the first one. Although when I use the tabs to jump to one sheet to another it works fine. Seems to be that the macro is considering a relative reference instead a absolute one.
Here's what my macro does (or at least should):
Private Sub cadastrar_clientes_Click()
Application.ScreenUpdating = False
Menu.Hide
Sheets("Clientes").Select
Range("A1048576").Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveCell.Select
End Sub
Notes:
I've tried to use ".activate" instead of ".select".
I've tried to use only "Sheets("Clientes").Select", even so the bug occurs.
To execute "Excel /unregserver" on the Windows CMD solved my problem once, but I couldn't do this again. It doesn't seems to work anymore.
I did a menu like this one once, but I didn't had these problems.
When the workbook opens the following code is executed:
Private Sub Workbook_Open()
Application.DisplayFullScreen = True
Application.DisplayFormulaBar = False
ActiveWindow.DisplayHeadings = False
ActiveWindow.DisplayGridlines = False
ActiveWindow.DisplayWorkbookTabs = False
End Sub
That's it. I hope that somebody could help me.
Replace all code on VBA module Menu with this (tested in the file you provided)
Option Explicit
Private Sub fechar_menu_Click()
Menu.Hide
End Sub
Private Sub novo_pedido_Click()
goToTab ActiveWorkbook.Worksheets("Novo pedido"), "B5"
End Sub
Private Sub ver_pedidos_Click()
goToTab ActiveWorkbook.Worksheets("Consultar pedido"), "F1"
End Sub
Private Sub cadastrar_clientes_Click()
goToTab ActiveWorkbook.Worksheets("Clientes")
End Sub
Private Sub cadastrar_produtos_Click()
goToTab ActiveWorkbook.Worksheets("Produtos")
End Sub
Private Sub cadastrar_transportadoras_Click()
goToTab ActiveWorkbook.Worksheets("Transportadoras")
End Sub
Private Sub painel_financeiro_Click()
goToTab ActiveWorkbook.Worksheets("Painel Financeiro"), "B3"
End Sub
Private Sub goToTab(ByRef ws As Worksheet, Optional cel As String = vbNullString)
Menu.Hide
Application.ScreenUpdating = False
With ws
.Activate
If Len(cel) = 0 Then
.Range("A" & .Rows.Count).End(xlUp).Offset(1, 0).Select
Else
.Range(cel).Select
End If
End With
Application.ScreenUpdating = True
End Sub
Well, I guess I know a lot more about the problem now. I've tested the workbook over various computers and came to the conclusion that the problem is within the Office 2013. I haven't seem this issue when running the 2007 or 2010 version. So far I haven't come to a solution. I would like to thanks Paul Bika for helping.
I'm trying to make an Excel Add-In to create a simple button when any workbook is opened, but I'm getting
Object variable or With Block variable not set
I think this is happening because technically there is no 'ActiveWorkbook' yet.
First thing I want to do is delete any buttons currently on the sheet. Then I want to place a button.
Anyone know how to make that happen?
Code
Private Sub Workbook_Open()
ActiveWorkbook.ActiveSheet.Buttons.Delete
Dim CommandButton As Button
Set CommandButton = ActiveWorkbook.ActiveSheet.Buttons.Add(1200, 100, 200, 75)
With CommandButton
.OnAction = "Test_Press"
.Caption = "Press for Test"
.Name = "Test"
End With
End Sub
I then have a Private Sub Test_Press() to display a MsgBox. The button is not being created though.
Credit goes to http://www.jkp-ads.com/Articles/FixLinks2UDF.asp
Note: I have another module I didn't post below, which houses the macro Project_Count I tied to the button I place on the workbook only if the workbook name is TT_GO_ExceptionReport
I also have a VBScript that downloads the Add-In, places it in the users addin folder, and installs it. If you want to know how to do that, leave a comment.
Code of Add-In that solved the problem:
ThisWorkbook
Option Explicit
Private Sub Workbook_Open()
' Purpose : Code run at opening of workbook
'-------------------------------------------------------------------------
'Initialise the application
InitApp
modProcessWBOpen.TimesLooped = 0
Application.OnTime Now + TimeValue("00:00:03"), "CheckIfBookOpened"
End Sub
Module 1 named modInit
Option Explicit
'Create a module level object variable that will keep the instance of the
'event listener in memory (and hence alive)
Dim moAppEventHandler As cAppEvents
Sub InitApp()
'Create a new instance of cAppEvents class
Set moAppEventHandler = New cAppEvents
With moAppEventHandler
'Tell it to listen to Excel's events
Set .App = Application
End With
End Sub
Module 2 named modProcessWBOpen
Option Explicit
'Counter to keep track of how many workbooks are open
Dim mlBookCount As Long
'Counter to check how many times we've looped
Private mlTimesLooped As Long
' Purpose : When a new workbook is opened, this sub will be run.
' Called from: clsAppEvents.App_Workbook_Open and ThisWorkbook.Workbook_Open
'-------------------------------------------------------------------------
Sub ProcessNewBookOpened(oBk As Workbook)
If oBk Is Nothing Then Exit Sub
If oBk Is ThisWorkbook Then Exit Sub
If oBk.IsInplace Then Exit Sub
CountBooks
'This checks to make sure the name of the new book matches what I
'want to place the button on
If oBk.Name = "TT_GO_ExceptionReport.xlsm" Then
Dim CommandButton As Button
Set CommandButton = Workbooks("TT_GO_ExceptionReport.xlsm").Sheets(1).Buttons.Add(1200, 100, 200, 75)
With CommandButton
.OnAction = "Project_Count"
.Caption = "Press for Simplified Overview"
.Name = "Simplified Overview"
End With
End If
End Sub
Sub CountBooks()
mlBookCount = Workbooks.Count
End Sub
Function BookAdded() As Boolean
If mlBookCount <> Workbooks.Count Then
BookAdded = True
CountBooks
End If
End Function
' Purpose : Checks if a new workbook has been opened
' (repeatedly until activeworkbook is not nothing)
'-------------------------------------------------------------------------
Sub CheckIfBookOpened()
If BookAdded Then
If ActiveWorkbook Is Nothing Then
mlBookCount = 0
TimesLooped = TimesLooped + 1
'May be needed if Excel is opened from Internet explorer
Application.Visible = True
If TimesLooped < 20 Then
Application.OnTime Now + TimeValue("00:00:01"), "CheckIfBookOpened"
Else
TimesLooped = 0
End If
Else
ProcessNewBookOpened ActiveWorkbook
End If
End If
End Sub
Public Property Get TimesLooped() As Long
TimesLooped = mlTimesLooped
End Property
Public Property Let TimesLooped(ByVal lTimesLooped As Long)
mlTimesLooped = lTimesLooped
End Property
Class Module named cAppEvents
' Purpose : Handles Excel Application events
'-------------------------------------------------------------------------
Option Explicit
'This object variable will hold the object who's events we want to respond to
Public WithEvents App As Application
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
'Make sure newly opened book is valid
ProcessNewBookOpened Wb
End Sub
Private Sub Class_Terminate()
Set App = Nothing
End Sub
something like this?
Option Explicit
Sub Button()
Dim cButton As Button
Dim rng As Range
Dim i As Long
ActiveSheet.Buttons.Delete
For i = 2 To 3 Step 2
Set rng = ActiveSheet.Range(Cells(i, 2), Cells(i, 2))
Set cButton = ActiveSheet.Buttons.Add(rng.Left, rng.Top, rng.Width, rng.Height)
With cButton
.OnAction = "Test_Press"
.Caption = "Press for Test " & i
.Name = "Test" & i
End With
Next i
End Sub
See Example here
I've got a workbook which runs a macro to show the userform Open1 as it opens, using the (very basic) code:
Private Sub Workbook_Open()
Open1.Show
End Sub
This does its job fine - each time I open the workbook, the userform pops up and runs perfectly.
But, I want the userform to appear the first time the workbook is opened only. Is there a way to allow this to happen?
You could use a dummy module which gets deleted the first time you open the spreadsheet...
Something like:
If ModuleExists("DummyModule") Then
Open1.Show
DoCmd.DeleteObject acModule, "DummyModule"
End If
Function ModuleExists(strModuleName As String) As Boolean
Dim mdl As Object
For Each mdl In CurrentProject.AllModules
If mdl.Name = strModuleName Then
ModuleExists = True
Exit For
End If
Next
End Function
Update: as stated, DoCmd isn't used in excel vba. That will teach me to write code without testing it!
The following updated code will work, but in order to access the VB environment, excel needs to be trusted.
There is a setting in the Trust Center>Macro Settings that you can tick for this code to work under Developer Macro Settings
As such, this may not be the way to go as it opens up the possibility of security issues...
Sub RemoveModule()
If ModuleExists("DummyModule") Then
Open1.Show
Dim vbCom As Object: Set vbCom = Application.VBE.ActiveVBProject.VBComponents
vbCom.Remove VBComponent:=vbCom.Item("DummyModule")
End If
End Sub
Function ModuleExists(strModuleName As String) As Boolean
Dim mdl As Object
For Each mdl In Application.VBE.ActiveVBProject.VBComponents
If mdl.Name = strModuleName Then
ModuleExists = True
Exit For
End If
Next
End Function
Try this:
If Sheets("Hide").Cells(1,1) = "1" Then
Open1.Show
Sheets("Hide").Cells(1,1) = "0"
End if
You must create the sheet Hide, and give the cell A1 the value 1, in that case the form will be shown.
After you create the sheet, hide it with this
Sheets("Hide").Visible = xlVeryHidden
And show it with this
Sheets("Hide").Visible = True
Here's an alternative bit of code that will persist between saves and allow you to reset it. No need to create a hidden sheet.
Put this in a module (invoke the DisplayFormIfFirstTime from your Workbook_Open event handler....)
Option Explicit
Private Const cMoniker As String = "FormHasBeenDisplayed"
Private Sub DisplayFormIfFirstTime()
If HasBeenOpened = False Then DisplayForm
End Sub
Public Sub DisplayForm()
MsgBox "Ok, its not a form but a dialog box...", vbInformation
End Sub
Public Function HasBeenOpened() As Boolean
Dim oName As Name
On Error Resume Next
Set oName = Application.Names(cMoniker)
On Error GoTo 0
If Not oName Is Nothing Then
HasBeenOpened = True
Else
Call Application.Names.Add(cMoniker, True, False)
End If
End Function
'Call this to remove the flag...
Public Sub ResetOpenOnce()
On Error Resume Next
Application.Names(cMoniker).Delete
End Sub
Based on the idea supplied by PaulG, I have coded an upgrade that will check for the name and if not found run a function, add the name and save the workbook for a more seemless approach to this problem...
Placed in ThisWorkbook
Private Sub Workbook_Open()
Run "RunOnce"
End Sub
Placed in a module
Sub RunOnce()
Dim Flag As Boolean: Flag = False
For Each Item In Application.Names
If Item.Name = "FunctionHasRun" Then Flag = True
Next
If Flag = False Then
Call Application.Names.Add("FunctionHasRun", True, False)
Application.DisplayAlerts = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
Call RunOnceFunction
End If
End Sub
Private Function RunOnceFunction()
Open1.Show
End Function
Sub ResetRunOnce()
For Each Item In Application.Names
If Item.Name = "FunctionHasRun" Then
Application.Names.Item("FunctionHasRun").Delete
Application.DisplayAlerts = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
End If
Next
End Sub