Macro to run when cell text is met

S

sparx

Can a macro monitor and run when a specific cell is a specific text -
have a file that many users use - if they type say "View" then I need
macro to start say "Macro1" which is a macro to make worksheets visable
and if the cell is empty or says "Noview" then I need the same macro t
start say "Macro2" that that makes all worksheets hide ( very hidden )
When the file saves, I have a Before_Save that empties the specifi
cell in question so before exiting will clear the cell and hide al
worksheets then save the file so when the file is next used, they go
to type "View"
 
D

Dave Peterson

How does that cell change--is it the result of a formula or does the user type
something?

I used A1 on Sheet2 to hide Sheet1, sheet3, sheet5 and I based it on the user
typing something--not the result of a formula.

This is the code that goes behind the worksheet. Rightclick on the worksheet
tab that should have this behavior. Select view code and paste this in the code
window.

Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Intersect(Target, Me.Range("a1")) Is Nothing Then Exit Sub

Call HideUnhideThoseSheets(ShowThem:=CBool(LCase(Target.Value) = "view"))

End Sub

Then in a general module:

Option Explicit
Sub auto_open()
'this will cause the worksheet event to fire when the workbook opens
'and hide the sheets
ThisWorkbook.Worksheets("sheet2").Range("a1").Value = ""
End Sub
Sub HideUnhideThoseSheets(ShowThem As Boolean)

Dim mySheetNames As Variant
Dim wks As Worksheet
Dim iCtr As Long
Dim myVisible As Long

mySheetNames = Array("sheet1", "sheet3", "sheet5")

If ShowThem = True Then
myVisible = xlSheetVisible
Else
myVisible = xlSheetVeryHidden
End If

For iCtr = LBound(mySheetNames) To UBound(mySheetNames)
ThisWorkbook.Worksheets(mySheetNames(iCtr)).Visible = myVisible
Next iCtr

End Sub

I chose to put the resetting action in the code that gets run when the workbook
opens. Lots of times, I save a workbook and I still want to keep that workbook
open--and in the save "view" that I'm using.

If you're new to macros, you may want to read David McRitchie's intro at:
http://www.mvps.org/dmcritchie/excel/getstarted.htm
 
S

sparx

The cell changes as a result of a formula.
When I open my file, it always goes to one specific sheet then yo
press a keyboard shortcut and some text is written into the cell. Th
cell is locked but attached to the macro/formula is some code tha
unlocks worksheet puts the code in then relocks the worksheet. This i
where I would like to unhide all workbook sheets but only if the cel
condition someting other than 00-00-00-00-00-00 or 00:00:00:00:00:00
its the mac address scenario. If it see's all these zero's then I don
want the macro to fire up but if any one of those zero's is somethin
different then the macro to run the Unhidesheets macro.

When the file closes, it will revert to hiding all other worksheet
except the specific sheet
 
D

Dave Peterson

I'm confused about the how the cell is changing. If it's changing because of a
macro, then I think you could use the worksheet_change event.

If it changes because of a formula (based on a recalculation), you could use the
worksheet_calculate event.
 
S

sparx

Hello Dave, In my file, Ive got some code that looks for your mac
address - and one worksheet of my file is called "Access". At start up
this page is the first page seen because on file save its the last one
seen - and is locked. A specific cell in this worksheet shows your MAC
address when you press a shortcut key - the following code in a module:

Sheets("Access").Select
ActiveSheet.Unprotect Password:="something"
Range("E9:p9").Select
ActiveCell.FormulaR1C1 = "=getmacaddress()"
ActiveSheet.Protect Password:="something"

I have another piece of vba that runs, and when you type in a cell
=getmacaddress - will display your PC's mac address.
Ive attached a shortcut to the above code and then puts your mac
address in the cell. There is some other text you enter that must work
in conjunction with the mac address to make another cell either say
"Locked" or "Unlocked" - now if "Unlocked" all formula's in my file
works otherwise they dont. When the file saves, I have a Before_Save
that says the same code as above but clears the range("E9:p9") and then
saves the file but in doing so makes the file not work because all the
formula's then dont work. So what I want to do is say if the cell says
"Locked" because there is no mac address entered or the mac address is
00-00-00-00-00-00 or 00:00:00:00:00:00 then all other worksheets except
"Access" are very hidden and if a genuine code is entered and "Unlocked"
is displayed the all worksheets including "Access" are viewable and none
very hidden - confused?
 
D

Dave Peterson

Why not just call the the getmacaddress() function directly from code and dump
the cell stuff altogether.

Then you could just look at was returned to do what you want.
 
S

sparx

Because if I was that clever, I would do that and wouldnt ask for help
on this excelforum site. Although I use Excel and am slowly learning
vba, I probably have a file that you could do in a third the code - as
I learn, I remove code and replace it for faster code and it works that
much better. I do use the =getmacaddress to be placed into a cell but
that is only half the access I want users to have - basically within an
office environment, if somebody wishes to use the file, they bring up
the mac address and then they have to type in some unlocking numbers
for that mac address - once all numbers match then all the formula's in
the file are programmed to then work using the =if line and it works
very well. People in an office enviornment has all sorts of access
denied ie, they cant go into network settings, change the screen size
etc - so I have made this file work in that environment - they give me
their mac address and I give them back the unlock code - the unlock
code is saved on their pc in the software - but if they give a copy to
somebody else on the network, they cant use the file cause their mac
address is different. This way, I get to control 99% of the users on
our network.
 
D

Dave Peterson

I'm not sure if this is closer....

This is in a General module (still):

Option Explicit
Sub HideUnhideThoseSheets(ShowThem As Boolean)

Dim mySheetNames As Variant
Dim wks As Worksheet
Dim iCtr As Long
Dim myVisible As Long

mySheetNames = Array("sheet1", "sheet3", "sheet5")

If ShowThem = True Then
myVisible = xlSheetVisible
Else
myVisible = xlSheetVeryHidden
End If

For iCtr = LBound(mySheetNames) To UBound(mySheetNames)
ThisWorkbook.Worksheets(mySheetNames(iCtr)).Visible = myVisible
Next iCtr

End Sub
Function GetMacAddress() As String
GetMacAddress = "00-00-00-00-00-00"
End Function

(I don't know what GetMacAddress does).

And this is behind the ThisWorkbook Module:

Option Explicit
Private Sub Workbook_Open()
With Sheets("Access")
.Unprotect Password:="something"
.Range("E9").Formula = "=getmacaddress()"
.Protect Password:="something"
End With

If GetMacAddress = "00-00-00-00-00-00" _
Or GetMacAddress = "00:00:00:00:00:00" Then
'just to make sure!
Call HideUnhideThoseSheets(ShowThem:=False)
Else
Call HideUnhideThoseSheets(ShowThem:=True)
End If

End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

Dim CurShowingState As Boolean

CurShowingState = CBool(Me.Worksheets("sheet1").Visible = xlSheetVisible)

Call HideUnhideThoseSheets(ShowThem:=False)

Application.EnableEvents = False
'save it with the sheets hidden
Me.Save
Application.EnableEvents = True

If CurShowingState Then
'show them if they were visible
Call HideUnhideThoseSheets(ShowThem:=True)
End If

'tell excel that the workbook hasn't been changed
'since the last save
Me.Saved = True

End Sub

The before_save code checks one sheet to see what the current view is. Then it
hides the sheets (no matter what), and then if sheet1 was visible, it unhides
them all (listed in that General module).

And finally, it tells excel to consider the workbook saved--and no changes have
been made. (That might be a lie -- if the worksheets were shown, but it's ok to
lie to excel in some cases.

Any closer????
 
S

sparx

Dave, I have not tried your vba as yet but will do some time today - I
must thank you for your time in writing the code as sometimes I can
understand that you are guessing what others have already written. As
at this moment in time my current code for "ThisWorkboo" is:

Option Explicit

Private Sub Workbook_Open()

Application.EnableEvents = True
Run "DisableCut"
Run "Find_Disable_Commands"
Run "DisableMoveorCopy"
UnhideSheets

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As
Boolean)

Sheets("Access").Select
ActiveSheet.Unprotect Password:="Somethinginthisarea"
Range("E9:p9").Select
Selection.ClearContents
ActiveSheet.Protect Password:="Somethinginthisarea"

'sourced from Nick Hodge's post at
http://www.adras.com/VBA-Excel-File-SaveAs.t469-5.html
'to stop it going into an endless "before save" loop by stopping _
Excel from "seeing" the save events in this macro.
Application.EnableEvents = False 'press F9 on this line
'Creating variables for use later
Dim FilePath As String
Dim NewFileName As String
Dim CurrentFileName As String
'to stop file saving (effectively telling Excel that you pressed a
cancel button)
Cancel = True
'to check how file was being saved & save as you want it to save.
Select Case SaveAsUI
Case False
ThisWorkbook.Save
Case True
'to identify variables
FilePath = ThisWorkbook.Path
NewFileName = "Book1 - Old.xls" '*
CurrentFileName = ThisWorkbook.name
'to save a copy & inform user.
ActiveWorkbook.SaveCopyAs FilePath & "\" & NewFileName '*
MsgBox "A copy of """ & CurrentFileName & """" & " is now saved, in
the same directory, as """ & NewFileName & """."
End Select
'to reset Excel's ability to "see" events such as save
Application.EnableEvents = True

End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)

Run "EnableCut"
Run "Find_Enable_Commands"
Run "EnableMoveorCopy"
HideSheets

End Sub

Private Sub HideSheets()
Dim sht As Object

Application.ScreenUpdating = False

ThisWorkbook.Sheets("Information").Visible = xlSheetVisible

For Each sht In ThisWorkbook.Sheets

If sht.name <> "Information" Then sht.Visible = xlSheetVeryHidden

Next sht

Application.ScreenUpdating = True

Application.EnableEvents = False
ThisWorkbook.Save
Application.EnableEvents = True

End Sub

Private Sub UnhideSheets()
Dim sht As Object

Application.ScreenUpdating = False

For Each sht In ThisWorkbook.Sheets

sht.Visible = xlSheetVisible

Next sht

ThisWorkbook.Sheets("Information").Visible = xlSheetVeryHidden

Application.ScreenUpdating = True

End Sub

As you can see, there is another piece of code that when you press
"SaveAs" creates a backup of the file automatically for you. I kept
getting loops when saving - the reason for my original query - The
getmacaddress code is below - it simply looks at your PC's MAC address
and displays it.

Option Explicit

Private Const NCBASTAT As Long = &H33
Private Const NCBNAMSZ As Long = 16
Private Const HEAP_ZERO_MEMORY As Long = &H8
Private Const HEAP_GENERATE_EXCEPTIONS As Long = &H4
Private Const NCBRESET As Long = &H32

Private Type NET_CONTROL_BLOCK 'NCB
ncb_command As Byte
ncb_retcode As Byte
ncb_lsn As Byte
ncb_num As Byte
ncb_buffer As Long
ncb_length As Integer
ncb_callname As String * NCBNAMSZ
ncb_name As String * NCBNAMSZ
ncb_rto As Byte
ncb_sto As Byte
ncb_post As Long
ncb_lana_num As Byte
ncb_cmd_cplt As Byte
ncb_reserve(9) As Byte 'Reserved, must be 0
ncb_event As Long
End Type

Private Type ADAPTER_STATUS
adapter_address(5) As Byte
rev_major As Byte
reserved0 As Byte
adapter_type As Byte
rev_minor As Byte
duration As Integer
frmr_recv As Integer
frmr_xmit As Integer
iframe_recv_err As Integer
xmit_aborts As Integer
xmit_success As Long
recv_success As Long
iframe_xmit_err As Integer
recv_buff_unavail As Integer
t1_timeouts As Integer
ti_timeouts As Integer
Reserved1 As Long
free_ncbs As Integer
max_cfg_ncbs As Integer
max_ncbs As Integer
xmit_buf_unavail As Integer
max_dgram_size As Integer
pending_sess As Integer
max_cfg_sess As Integer
max_sess As Integer
max_sess_pkt_size As Integer
name_count As Integer
End Type

Private Type NAME_BUFFER
name As String * NCBNAMSZ
name_num As Integer
name_flags As Integer
End Type

Private Type ASTAT
adapt As ADAPTER_STATUS
NameBuff(30) As NAME_BUFFER
End Type

Private Declare Function Netbios Lib "netapi32" (pncb As
NET_CONTROL_BLOCK) As Byte

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(hpvDest As _
Any, ByVal hpvSource As Long, ByVal cbCopy As Long)

Private Declare Function GetProcessHeap Lib "kernel32" () As Long

Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long,
ByVal _
dwFlags As Long, ByVal dwBytes As Long) As Long

Private Declare Function HeapFree Lib "kernel32" (ByVal hHeap As Long,
ByVal dwFlags _
As Long, lpMem As Any) As Long

Public Function GetMACAddress() As String
Dim x As Integer
Dim tmp As String
Dim pASTAT As Long
Dim NCB As NET_CONTROL_BLOCK
Dim AST As ASTAT

NCB.ncb_command = NCBRESET
Call Netbios(NCB)

NCB.ncb_callname = "* "
NCB.ncb_command = NCBASTAT

NCB.ncb_lana_num = 0
NCB.ncb_length = Len(AST)

pASTAT = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS Or
HEAP_ZERO_MEMORY, NCB.ncb_length)

If pASTAT = 0 Then
Debug.Print "memory allocation failed!"
Exit Function
End If

NCB.ncb_buffer = pASTAT
Call Netbios(NCB)

CopyMemory AST, NCB.ncb_buffer, Len(AST)

For x = 0 To 5
tmp = tmp & Right$("00" & Hex(AST.adapt.adapter_address(x)), 2) &
"-"
Next x

tmp = Left(tmp, Len(tmp) - 1)

HeapFree GetProcessHeap(), 0, pASTAT

GetMACAddress = tmp

End Function
 
D

Dave Peterson

Good luck.
Dave, I have not tried your vba as yet but will do some time today - I
must thank you for your time in writing the code as sometimes I can
understand that you are guessing what others have already written. As
at this moment in time my current code for "ThisWorkboo" is:

Option Explicit

Private Sub Workbook_Open()

Application.EnableEvents = True
Run "DisableCut"
Run "Find_Disable_Commands"
Run "DisableMoveorCopy"
UnhideSheets

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As
Boolean)

Sheets("Access").Select
ActiveSheet.Unprotect Password:="Somethinginthisarea"
Range("E9:p9").Select
Selection.ClearContents
ActiveSheet.Protect Password:="Somethinginthisarea"

'sourced from Nick Hodge's post at
http://www.adras.com/VBA-Excel-File-SaveAs.t469-5.html
'to stop it going into an endless "before save" loop by stopping _
Excel from "seeing" the save events in this macro.
Application.EnableEvents = False 'press F9 on this line
'Creating variables for use later
Dim FilePath As String
Dim NewFileName As String
Dim CurrentFileName As String
'to stop file saving (effectively telling Excel that you pressed a
cancel button)
Cancel = True
'to check how file was being saved & save as you want it to save.
Select Case SaveAsUI
Case False
ThisWorkbook.Save
Case True
'to identify variables
FilePath = ThisWorkbook.Path
NewFileName = "Book1 - Old.xls" '*
CurrentFileName = ThisWorkbook.name
'to save a copy & inform user.
ActiveWorkbook.SaveCopyAs FilePath & "\" & NewFileName '*
MsgBox "A copy of """ & CurrentFileName & """" & " is now saved, in
the same directory, as """ & NewFileName & """."
End Select
'to reset Excel's ability to "see" events such as save
Application.EnableEvents = True

End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)

Run "EnableCut"
Run "Find_Enable_Commands"
Run "EnableMoveorCopy"
HideSheets

End Sub

Private Sub HideSheets()
Dim sht As Object

Application.ScreenUpdating = False

ThisWorkbook.Sheets("Information").Visible = xlSheetVisible

For Each sht In ThisWorkbook.Sheets

If sht.name <> "Information" Then sht.Visible = xlSheetVeryHidden

Next sht

Application.ScreenUpdating = True

Application.EnableEvents = False
ThisWorkbook.Save
Application.EnableEvents = True

End Sub

Private Sub UnhideSheets()
Dim sht As Object

Application.ScreenUpdating = False

For Each sht In ThisWorkbook.Sheets

sht.Visible = xlSheetVisible

Next sht

ThisWorkbook.Sheets("Information").Visible = xlSheetVeryHidden

Application.ScreenUpdating = True

End Sub

As you can see, there is another piece of code that when you press
"SaveAs" creates a backup of the file automatically for you. I kept
getting loops when saving - the reason for my original query - The
getmacaddress code is below - it simply looks at your PC's MAC address
and displays it.

Option Explicit

Private Const NCBASTAT As Long = &H33
Private Const NCBNAMSZ As Long = 16
Private Const HEAP_ZERO_MEMORY As Long = &H8
Private Const HEAP_GENERATE_EXCEPTIONS As Long = &H4
Private Const NCBRESET As Long = &H32

Private Type NET_CONTROL_BLOCK 'NCB
ncb_command As Byte
ncb_retcode As Byte
ncb_lsn As Byte
ncb_num As Byte
ncb_buffer As Long
ncb_length As Integer
ncb_callname As String * NCBNAMSZ
ncb_name As String * NCBNAMSZ
ncb_rto As Byte
ncb_sto As Byte
ncb_post As Long
ncb_lana_num As Byte
ncb_cmd_cplt As Byte
ncb_reserve(9) As Byte 'Reserved, must be 0
ncb_event As Long
End Type

Private Type ADAPTER_STATUS
adapter_address(5) As Byte
rev_major As Byte
reserved0 As Byte
adapter_type As Byte
rev_minor As Byte
duration As Integer
frmr_recv As Integer
frmr_xmit As Integer
iframe_recv_err As Integer
xmit_aborts As Integer
xmit_success As Long
recv_success As Long
iframe_xmit_err As Integer
recv_buff_unavail As Integer
t1_timeouts As Integer
ti_timeouts As Integer
Reserved1 As Long
free_ncbs As Integer
max_cfg_ncbs As Integer
max_ncbs As Integer
xmit_buf_unavail As Integer
max_dgram_size As Integer
pending_sess As Integer
max_cfg_sess As Integer
max_sess As Integer
max_sess_pkt_size As Integer
name_count As Integer
End Type

Private Type NAME_BUFFER
name As String * NCBNAMSZ
name_num As Integer
name_flags As Integer
End Type

Private Type ASTAT
adapt As ADAPTER_STATUS
NameBuff(30) As NAME_BUFFER
End Type

Private Declare Function Netbios Lib "netapi32" (pncb As
NET_CONTROL_BLOCK) As Byte

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(hpvDest As _
Any, ByVal hpvSource As Long, ByVal cbCopy As Long)

Private Declare Function GetProcessHeap Lib "kernel32" () As Long

Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long,
ByVal _
dwFlags As Long, ByVal dwBytes As Long) As Long

Private Declare Function HeapFree Lib "kernel32" (ByVal hHeap As Long,
ByVal dwFlags _
As Long, lpMem As Any) As Long

Public Function GetMACAddress() As String
Dim x As Integer
Dim tmp As String
Dim pASTAT As Long
Dim NCB As NET_CONTROL_BLOCK
Dim AST As ASTAT

NCB.ncb_command = NCBRESET
Call Netbios(NCB)

NCB.ncb_callname = "* "
NCB.ncb_command = NCBASTAT

NCB.ncb_lana_num = 0
NCB.ncb_length = Len(AST)

pASTAT = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS Or
HEAP_ZERO_MEMORY, NCB.ncb_length)

If pASTAT = 0 Then
Debug.Print "memory allocation failed!"
Exit Function
End If

NCB.ncb_buffer = pASTAT
Call Netbios(NCB)

CopyMemory AST, NCB.ncb_buffer, Len(AST)

For x = 0 To 5
tmp = tmp & Right$("00" & Hex(AST.adapt.adapter_address(x)), 2) &
"-"
Next x

tmp = Left(tmp, Len(tmp) - 1)

HeapFree GetProcessHeap(), 0, pASTAT

GetMACAddress = tmp

End Function
 
Top