Adding Command Button allowing user to view hidden sheet - vba

I am new to using Macros/VB in excel and in need of some help (in the simplest way you can instruct me)
I have a workbook with two sheets. I have already created a form on sheet 1 which will allow users to enter data which then is populated within a hidden sheet (sheet2).
I would like to add a button on sheet 1 for the user to view the hidden "list data" they have entered in sheet 2 but they cannot be able to edit the data - only view it.
Any help would be greatly appreciated.

Insert a shape (I prefer this over an ActiveX control) on the sheet with your form. I named the shape "Show data" and gave that same caption to the button. Now add the following code to a standard code module (one which VBE names like "Module1").
Option Explicit
Sub ShowData_Click()
' 25 Jul 2017
With ThisWorkbook.Worksheets("Jeanette")
.Visible = xlSheetVisible
.Activate
End With
End Sub
Change the name of the worksheet with the data to the name you have given that sheet in your project. Then right-click on the button (shape) and select "Assign macro". Assign the "ShowData_Click" macro. Now, when you click the button the hidden sheet will become visible and be activated.
In the code sheet for the data sheet (which is normally hidden), add the following to procedures.
Option Explicit
Dim ThisSheet As String
Private Sub Worksheet_Activate()
' 25 Jul 2017
ThisSheet = ActiveSheet.Name
End Sub
Private Sub Worksheet_Deactivate()
' 25 Jul 2017
On Error Resume Next
Worksheets(ThisSheet).Visible = xlSheetVeryHidden
End Sub
The first one will run whenever the sheet is activated which happens when the new button is pressed. It will remember the name of the sheet. This is so that you don't need to hard-code the name.
The second procedure will run whenever you activate another sheet in the workbook. It will hide the sheet again. So, you show the sheet by pressing the button and hide the sheet by selecting another sheet.
I'm not a friend of Excel's protection. So, I suggest another way to prevent users from modifying the data. Here is the code. Install it on the same code sheet where you already have the Activate and Deactivate procedures.
Private Sub Worksheet_Change(ByVal Target As Range)
' 25 Jul 2017
Static ShowMsg As Integer
With Application
.EnableEvents = False
.Undo
ShowMsg = ShowMsg + 1
If (ShowMsg Mod 3) = 1 Then
MsgBox "Data in this sheet may not be modified." & vbCr & _
"Your changes have been removed.", _
vbInformation, "Invalid action"
End If
.EnableEvents = True
End With
End Sub
This code will undo any change the user makes. The user will receive a message to this effect each third time he/she tries to modify something.

Related

Double click event in the excel sheet column to fill all textboxes of a Userform

I am trying to use double-click event of worksheet to populate a all textboxes in a userform with value when click on a specific column in the double-clicked row.
Eg: I have 6 columns
ID Project Approval tool status feedback
1 A1 yes 123 ongoing good
2 B2 no 456 stop bad
When I double-click on any cell in the column ID, userform with a textbox will pop up with the textbox filled with the value from the all columns (Project, Aprroval, tool, Status, Feedback) the row which was double-clicked. SO, when I double-click on "1" in column ID a userform should pop up with textbox value "A1", "yes", "123", "ongoing", "good".
this is my code so far i am trying for the double click Event.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, CANCEL As Boolean)
Dim UserForm2 As frm_Update
If Target.Column = 1 Then
Set UserForm2 = New frm_Update
CANCEL = True
With UserForm2
Dim wks As Worksheet
Set wks = ThisWorkbook.Worksheets("Sheet1")
wks.Activate
.txtProject = Cells(Target.Row, 2)
.txtapproval = Cells(Target.Row, 3)
.txttool = Cells(Target.Row, 4)
.txtstatus = Cells(Target.Row, 5)
.txtfeedback = Cells(Target.Row, 6)
Me.Show
End With
End If
End Sub
i used this Double click event as a reference to my Problem but I am not able to solve the Problem. My userform is not opening when i run the Code.
Me in the event routine of a sheet refers to the worksheet, not to the form. As a worksheet has not Show-method, you should get a runtime error.
Simple change the line to .Show should display the form.
To avoid such errors, always put Option explicit at the top of all modules. If you do, you would get a compiler error Method or data member not found

Disable alert when manually deleting a sheet

Is there a way in VBA to disable the alert that pops up when MANUALLY deleting a sheet (right click sheet and delete)? I have seen Application.DisplayAlerts = False, however this seems to only work for me when deleting a sheet using VBA (Sheets("Sheet1").delete). I am trying to disable the alert for the whole workbook when you manually right click on a sheet and click delete. Thanks.
In case anyone else is looking for the same scenario:
...eliminate the need to confirm deleting a sheet when presenting the
workbook in meetings. While going through the sheets I often double
click on pivot tables to view detail, and I would like to eliminate
the pop-up alert when I delete the generated sheet...
If new sheets are generated only when double-clicking a pivot table, this might be a suitable solution
Placed in ThisWorkbook, the code bellow will delete any new sheets, when selecting a different sheet
Option Explicit
'Place this code in ThisWorkbook module
'Expects that all new sheets are generated by double-clicking a pivot table
Private pivotWs As Worksheet
Private Sub Workbook_NewSheet(ByVal Sh As Object)
Set pivotWs = Sh
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
If Not pivotWs Is Nothing Then
If Sh.Name = pivotWs.Name Then
Application.DisplayAlerts = False
pivotWs.Delete
Set pivotWs = Nothing
Application.DisplayAlerts = True
End If
End If
End Sub

Running excel macros only on one sheet

Hi Iam new to writing VBA code and need assistance. My VBA code and Macro works fine as long as I am on the active sheet.
My Problem:
My VBA code and macro, stops running automatically, when i change from the active sheet to another within the same workbook and
My VBA code and macro, stops running automatically, when i open a new excel workbook
Solution required:
Run the VBA code and macro only on desired worksheet and prevent it from running on other worksheets and workbooks.
Background:
I have an excel file, named "Net Weight" with two sheets. sheet 1 is named : "weight", sheet 2: is named "base data".
sheet 1 is used as a user input form.
In sheet 1- cell B1 : user will type in a product code , in cell E1: a look up formula will place the description of the product code using the data from sheet 2
I have setup a VBA code and macro that does the following:
As soon as a user inputs a product code into cell B1, in sheet 1, sheet 1 is saved as PDF file into a predefined folder location data from cell B1 and E1
A macro saves and overwrties the PDF file every 10 seconds.
This process is repeated every time a new product code is entered
There are no buttons on sheet 1, everything is done automatically.
Here is my current code:
Sheet 1: set as Worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$1" Then
Call Macro1
End If
End Sub
Module 1 macro : set as general
Sub Macro1()
Application.DisplayAlerts = False
If ThisWorkbook.Name = "Nett Weight.xlsm" And ActiveSheet.Name = "Weight" Then
Sheets("Weight").ExportAsFixedFormat Type:=xlTypePDF, _
Filename:="C:\Nett weight\" & Range("B1 ").Text & Range(" E1").Text
Application.OnTime Now + TimeValue("00:00:10"), "Macro1"
Else
Exit Sub
End If
End Sub
First, you need to create a public variable to hold your timer, otherwise you'll never be able to cancel it so it will continue trying to fire even when your workbook is closed. You should also create a public variable to store when the timer is running, so you can check before creating a new timer.
At the top of a code module put:
Public nextTime As Date
Then in your Workbook_BeforeClose() event method (within ThisWorkbook), disable the existing timer so it doesn't keep trying to fire after the workbook is closed.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next ' Continue with next line of code if we encounter an error
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=False
On Error GoTo 0 ' Resume error-trapping
End Sub
In Macro1() you should explicitly and directly reference your workbook components - ThisWorkbook always refers to the workbook the code is running from, so you don't need your If statement. Then you set the nextTime and activate the timer using that variable if it is not already running.
Sub Macro1()
Dim sht As Worksheet ' Creates a variable to hold your Weight worksheet
Set sht = ThisWorkbook.Sheets("Weight") ' Sets the reference
Application.DisplayAlerts = False
sht.ExportAsFixedFormat Type:=xlTypePDF, Filename:="C:\Nett weight\" & sht.Range("B1").Text & sht.Range("E1").Text ' Remember to preceed Range with sht. to explicitly reference the range of your Weight worksheet
On Error Resume Next ' Continue with next line of code if we encounter an error
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=False
On Error GoTo 0 ' Resume error-trapping
nextTime = Now + TimeSerial(0, 0, 10) ' Adds 10 seconds to Now
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=True
timerIsRunning = True
Application.DisplayAlerts = True ' Remember to enable alerts at the end of code
End Sub
Your Worksheet_Change() event method can stay as is. Now if there is a change in B1 it will call Macro1(). Macro1() will save the Weight worksheet as a PDF regardless of whether the workbook or worksheet is active, and create a new timer to re-run Macro1() every 10 seconds after deactivating an existing timer. When you're finished with the workbook, you close it and the existing timer is also deactivated.
EDIT:
Fortunately (as it fixes a spreadsheet of my own) I have figured out why the solution I originally provided wasn't working. Placing the Public variables under ThisWorkbook meant they no longer held their values after code execution. The remedy was to place them in a module instead. Once that was sorted out, I also realised that when the timer fires to call Macro1() it will throw an error when trying to unschedule the existing timer (as none exists unless Macro1() was called ad hoc by the Worksheet_Change() event).
Long story short: Public variables have been moved to a code module, and the timerIsRunning flag has been removed entirely and errors when attempting to unschedule the timer are simply ignored in the event that no timer exists.

Input Box on workbook open

I am trying to come up with some vba code to open an input box automatically as soon as the workbook is opened and have the user enter a date and then have the date placed in the A1 cell. I have written the code below but the input box is not pulling up at all it just opens the workbook and moves on.. not sure what is happening. Any and all help is appreciated.
Thanks!
Option Explicit
Private Sub workbook_open()
Dim cellvalue As Variant
Dim ws As Worksheet
Set ws = Worksheets("Workbench Report")
ReShowInputBox: cellvalue = Application.InputBox("Please Enter Todays Date (dd/mm/yyyy)")
If cellvalue = False Then Exit Sub
If IsDate(cellvalue) And CDate(cellvalue) < Date Then
ws.Range("A1").Value = DateValue(cellvalue)
Else: MsgBox ("Invalid Date!")
GoTo ReShowInputBox
End If
End Sub
Your code triggers upon the Workbook opening for me. Try these steps.
Open up Excel and Save As, changing the extension to .XSLM
Open up the VBA Editor (ALT + F11)
In the left-hand window, locate your macro file (the one you just created and named - it's in brackets after "VBA Project"), drilldown to "This Workbook" and double-click it.
Paste your code into the right-hand window
Save the file and re-open.
See attached diagram.
By the way, "cellValue = false" should probably be cellValue = "" since InputBox is returning a string and not a boolean value.
For Workbook_Open events the script needs to reside in the private module (ThisWorkbook)
From Ozgrid:
the Workbook_Open event is a procedure of the Workbook Object and as
such, the Workbook_Open procedure MUST reside in the private module of
the Workbook Object (ThisWorkbook).

Is there a way to have a scrollable list that is editable?

Following this video I have a spreadsheet that has a "Edit History" box on it that scrolls up and down. It uses a forms control scroll box and a list on a secondary sheet to create a scrollable list. The problem with this is that you cannot then edit the information in the scroll box (you must edit it on the secondary sheet).
I have VBA that automatically enters the person's name into the scrollbox when they edit any part of the sheet, and then enters "Note:" below that. I want the person to be able to edit the "Note:" box so that they can enter the reason they are editing the sheet:
John Smith and James Appleseed are previous users of this sheet. When Wayne Smith comes in to edit the sheet, as soon as he makes a change, it adds "Wayne Smith" and "Note:" to the sheet. (I already have this part working using VBA).
Because of the way that the scroll able list is implemented, it is actually all just formulas within this edit history box. If I double click "Note:" to try and edit it, this is what appears:
But what I want to happen is the ability to edit the "Note:" box (without having to switch to the secondary sheet where the list is actually stored). Essentially I want to make a scroll able text box that is also directly editable, and works with VBA.
Is there any way to do this?
I put together a working example of how to do this.
You can download the workbook here.
This method uses two sheets in a workbook... Sheet1 for the listbox and listboxdata for the data. Sheet1 can be called anything you like.
It would probably be wise to hide the listboxdata sheet.
On Sheet1 you need a Forms Control scrollbar. Use the Name Box to rename it: ScrollBar1. Assign to it the Scroll() procedure.
All of the code for this app should be placed in the Sheet1 code module:
Option Explicit
Private Const LISTBOX_SCROLLBAR = "scrollbar1"
Private Const LISTBOX_DATASHEET = "listboxdata"
Private Const LISTBOX_DATAHEADR = "a1"
Private Const LISTBOX_SCROLLMAX = 50
Private Const LISTBOX_SCROLLMIN = 1
Private Sub Scroll()
Dim ListBoxRows&, n&, ndx&, v
On Error Resume Next
With Shapes(LISTBOX_SCROLLBAR)
SetProps ndx
ListBoxRows = .BottomRightCell.Row - .TopLeftCell.Row
v = ThisWorkbook.Sheets(LISTBOX_DATASHEET).Range(LISTBOX_DATAHEADR).Resize(ListBoxRows).Offset(ndx)
Application.EnableEvents = False
.TopLeftCell(, 0).Resize(ListBoxRows) = v
End With
Application.EnableEvents = True
End Sub
Private Sub Update(Target As Range)
With Shapes(LISTBOX_SCROLLBAR)
If Target.Column = .TopLeftCell(, 0).Column Then
If Target.Row >= .TopLeftCell.Row And Target.Row <= .BottomRightCell.Row Then
If Target.Count = 1 Then
ThisWorkbook.Sheets(LISTBOX_DATASHEET).Range(LISTBOX_DATAHEADR).Offset(.ControlFormat.Value + Target.Row - .TopLeftCell.Row) = Target
Else
Scroll
End If
End If
End If
End With
End Sub
Private Sub SetProps(Optional ndx&)
With Shapes(LISTBOX_SCROLLBAR).ControlFormat
.Min = LISTBOX_SCROLLMIN
.Max = LISTBOX_SCROLLMAX
ndx = .Value
End With
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Update Target
End Sub
Private Sub Worksheet_Activate()
SetProps
End Sub
That's it.
No formulas required in the listbox and any changes made to the cells in the listbox will be written to the source data and kept.