my actual code is :
Option Explicit
Sub SaveMailActiveSheetAsPDFIn2016()
'Ron de Bruin : 1-May-2016
'Test macro to save/mail the Activesheet as pdf with ExportAsFixedFormat with Mail
Dim FileName As String
Dim FolderName As String
Dim Folderstring As String
Dim FilePathName As String
Dim strbody As String
'Check for AppleScriptTask script file that we must use to create the mail
If CheckAppleScriptTaskExcelScriptFile(ScriptFileName:="RDBMacMail.scpt") = False Then
MsgBox "Sorry the RDBMacMail.scpt is not in the correct location"
Exit Sub
End If
'My example sheet is landscape, I must attach this line
'for making the PDF also landscape, seems to default to
'xlPortait the first time you run the code
ActiveSheet.PageSetup.Orientation = xlLandscape
'Name of the folder in the Office folder
FolderName = "TempPDFFolder"
'Name of the pdf file
FileName = "Order " & [C1] & " " & Format(Date, "dd-mm-yyyy") & ".pdf"
Folderstring = CreateFolderinMacOffice2016(NameFolder:=FolderName)
FilePathName = Folderstring & Application.PathSeparator & FileName
'Create the body text in the strbody string
strbody = "Hi " & [C2] & "," & vbNewLine & vbNewLine & _
"Please find attached our new order" & vbNewLine & _
vbNewLine & _
"Thanks"
'expression A variable that represents a Workbook, Sheet, Chart, or Range object.
'Not working if you change activeworkbook, always save the activesheet
'Also the parameters are not working like in Windows
ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, FileName:= _
FilePathName, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False
'Call the MacExcel2016WithMacMailPDF function to save the new pdf and create the mail
'When you use more mail addresses separate them with a ,
'Look in Mail>Preferences for the name of the mail account or signature
'Account name looks like this : "Your Name <your#mailaddress.com>"
MacExcel2016WithMacMailPDF subject:=[C6] & Format(Date, "dd/mm/yy"), _
mailbody:=strbody, _
toaddress:=[C3], _
ccaddress:=[C4], _
bccaddress:=[C5], _
attachment:=FilePathName, _
displaymail:=True, _
thesignature:="", _
thesender:=""
End Sub
I would like that all cells from E column in the print area =0 not to be displayed and that the sheet shrinks itself (like deleting the lines were =0), this before creating the .pdf document and opening mailbox.
I dunno if I'm clear enough sorry
Thank you for your help though
Assuming column E of Sheet1 is the one you want to hide if filled with zeros:
Sub hideZeroFilledColumn()
Dim rng As Range
Set rng = ThisWorkbook.Worksheets("Sheet1").Range("E:E")
rng.EntireColumn.Hidden = (Excel.WorksheetFunction.Count(rng) = _
Excel.WorksheetFunction.CountIf(rng, "0"))
End Sub
Or, if you want to hide just the lines when cell value in column E:E is 0:
Sub hideLineWithZero()
Dim WS As Worksheet
Set WS = ThisWorkbook.Worksheets("Sheet1")
Dim strColumn As String
strColumn = "E" 'If the column you want to check is "E:E"
'Getting first row of printarea and setting "rngPrintStart" to that row in column strColumn
Dim rngPrintStart As Range
'The split is used to separate the start and end of the PrintArea address
'Here we take component "0" of the split, so the start part of the PrintArea
Set rngPrintStart = Range(Split(WS.PageSetup.PrintArea, ":")(0))
Set rngPrintStart = WS.Range(strColumn & rngPrintStart.Row)
'Getting last row of printarea and setting "rngPrintEnd" to that row in column strColumn
Dim rngPrintEnd As Range
'The split is used to seperate the start and end of the PrintArea address
'Here we take component "1" of the split, so the end part of the PrintArea
Set rngPrintEnd = Range(Split(WS.PageSetup.PrintArea, ":")(1))
Set rngPrintEnd = WS.Range(strColumn & rngPrintEnd.Row)
'Merging rngPrintStart and rngPrintEnd ranges from printarea in column strColumn
Dim rngPrintColumnE As Range
Set rngPrintColumnE = WS.Range(rngPrintStart, rngPrintEnd)
Dim rng As Range
Dim rngToHide As Range
'looking in all cells from rngPrintColumnE
For Each rng In rngPrintColumnE
'checking if cell value is equal to 0 and is not empty
If (rng.Value2 = 0) And (rng.Value2 <> "") Then
'Building the range to be hidden
If rngToHide Is Nothing Then 'For the first time when "rngToHide" is not yet set
Set rngToHide = rng
Else
Set rngToHide = Union(rngToHide, rng)
End If
End If
Next rng
'to hide the rows from the previously built range
rngToHide.Rows.EntireRow.Hidden = True
End Sub
I'm assuming you want to hide column E if all the values in it are zero?
Do a sum of the values into another cell (X99 in my example) then use the following code:
With ActiveSheet
If .Range("X99").Value = 0 Then
.Range("e:e").EntireColumn.Hidden = True
Else
.Range("e:e").EntireColumn.Hidden = False
End If
End With
Edit:
You can use Abs(Min(E:E))>0 instead of Sum if you have negative values
For some reason I can't add another answer so here goes with another edit.
To hide rows that have zero in the e column:
Dim i As Integer
Dim pa As Range
Dim ecolnumber As Integer
ecolnumber = 5
Set pa = Range(ActiveSheet.PageSetup.PrintArea)
For i = 0 To pa.Rows.Count
Dim ecell As Range
Set ecell = pa(i, ecolnumber)
ecell.EntireRow.Hidden = ecell.Value = 0
Next
Note the ecolnumber, you may have to change it to reference the correct column.
After you have done all your stuff you can unhide the rows with:
For i = 0 To pa.Rows.Count
Set ecell = pa(i, ecolnumber)
ecell.EntireRow.Hidden = False
Next
Related
a kind soul made me this code for another question i asked. But im thinking about text recognition. So i got a data input in sheet1, there is some headers for each column in the data input, and i want to sort by specific header names, copy them, and paste the two rows of the columns which header matches my keywords, in sheet2. Pasting the data in sheet2, should be at the first two lines available, like here in my code already. Really want to keep most of the code as possible and then maybe only change the sub where i copy the two rows in a specific range. Would appreciate the help:)
Option Explicit
Sub call_copy_sub_ranges()
Dim ws1 As Worksheet, wsOut As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Ark1")
Set wsOut = ThisWorkbook.Worksheets("Ark2")
Dim ar
ar = Array("HeaderA", "HeaderB", "HeaderC", "HeaderD", "HeaderE", _
"HeaderF", "HeaderG", "HeaderH", "HeaderI", "HeaderJ", "HeaderK", _
"HeaderL", "HeaderM", "HeaderN", "HeaderO", "HeaderP", "HeaderQ", _
"HeaderR", "HeaderS", "HeaderT", "HeaderU", "HeaderV", "HeaderW", _
"HeaderX", "HeaderY", "HeaderZ", "HeaderAA", "HeaderAB", "HeaderAC", _
"HeaderAD", "HeaderAE", "HeaderAF", "HeaderAG", "HeaderAH", "HeaderAI", _
"HeaderAJ", "HeaderAK", "HeaderAL", "HeaderAM", "HeaderAN", "HeaderAO", _
"HeaderAP", "HeaderAQ", "HeaderAR", "HeaderAS", "HeaderAT", "HeaderAU", _
"HeaderAV", "HeaderAW", "HeaderAX", "HeaderAY")
wsOut.Range("A1:AY1").Value = ar
copy_sub_ranges ws1, wsOut
MsgBox "Done"
End Sub
Sub copy_sub_ranges(ByVal ws1 As Worksheet, ByVal wsOut As Worksheet)
Dim rng As Range, rngOut As Range, ar, s
ar = Array("S2:S3", "BF7:BH8", "BI9:CC10", _
"CD9:CQ9", "CR9:CS10", "CT9:CV9", "CW9:CW10", "CX10", "EE9:EI10")
' target
Set rngOut = wsOut.Cells(wsOut.Rows.Count, 1).End(xlUp)
If Not IsEmpty(wsOut.Range("A1").Text) Then
Set rngOut = rngOut.offset(1, 0)
End If
For Each s In ar
Set rng = ws1.Range(s)
Debug.Print rng.Address, rngOut.Address
rng.Copy rngOut
Set rngOut = rngOut.offset(0, rng.Columns.Count)
Next
' underline
Set rng = wsOut.Cells(wsOut.Rows.Count, 1).End(xlUp)
With rng.Resize(1, rngOut.Column - 1).Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.ColorIndex = 0
.Weight = xlMedium
End With
End Sub
You could execute an SQL statement on your worksheet, or on a range within the worksheet. This would allow you to trivially select only specific columns, and sort by specific columns.
Add a reference (Tools -> References...) to Microsoft ActiveX Data Objects; choose the latest version (usually 6.1).
Then you could write code similar to the following:
Dim sql As String
sql = _
"SELECT HeaderA, HeaderG, HeaderP " & _
"FROM [Sheet1$] " & _
"ORDER BY HeaderQ, HeaderR"
' If your data is only in a specific range, you can limit to that range:
'sql = _
' "SELECT HeaderA, HeaderG, HeaderP " & _
' "FROM [Sheet1$B5:AA17] " & _
' "ORDER BY HeaderQ, HeaderR"
Const filepath As String = "C:\path\to\excel\file.xlsx"
Dim connectionString As String
connectionString = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=""" & filepath & """;" & _
"Extended Properties=""Excel 12.0;HDR=Yes"""
Dim rs As New ADODB.Recordset
rs.Open sql, connectionString
ThisWorkbook.Worksheets("Ark2").Range("A1").CopyFromRecordset rs
Note that there's nothing preventing you from using an array of strings as the selected columns, or as the sort fields; use the Join function to combine the field names into a comma-separated string:
Dim fieldnames() As String
fieldnames = Array("HeaderB", "HeaderC", "HeaderD")
Dim sortnames() As String
sortnames = Array("HeaderM", "HeaderN", "HeaderO")
sql = _
"SELECT " & Join(fieldnames, ", ") & " " & _
"FROM [Sheet1$] " & _
"ORDER BY " & Join(sortnames, ", ")
fieldnames and sortnames could be populated from different cells:
Dim sheet As Worksheet
Set sheet = Worksheets("Sheet1")
fieldnames = Array(sheet.Range("A1").Value, sheet.Range("B1").Value))
I am using a userform to update existing data on a worksheet. I can
create new records just fine. I created an update userform with a
combobox to search for the names. It pulls the persons data just fine and I am able to change the information. But when I go to click the update button, an error occurs. Before it was adding a totally new line which I did not want to happen so I adjusted my code. I just want to update an existing line of data with the edited information.
I have tried to use the MATCH function in VBA after it was replicating records.
Private Sub Update_record_Click()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Master")
Dim n As Long
Dim empname As String
empname = Application.Match(VBA.CStr(Me.Update_record.Value),
sh.Range("C:C"), 0)
sh.Range("A" & empname).Value = Me.First_Name.Value
sh.Range("B" & empname).Value = Me.Last_Name.Value
sh.Range("D" & empname).Value = Me.MainPX.Value
sh.Range("E" & empname).Value = Me.AltPX.Value
sh.Range("F" & empname).Value = Me.Job_Role.Value
sh.Range("G" & empname).Value = Me.WristBand.Value
sh.Range("H" & empname).Value = Me.Team.Value
sh.Range("I" & empname).Value = Me.Unit.Value
Range("A2:J" & n).Sort key1:=Range("A2:A" & n), order1:=xlAscending,
Header:=xlNo
Me.First_Name.Value = ""
Me.Last_Name.Value = ""
Me.MainPX.Value = ""
Me.AltPX.Value = ""
Me.Job_Role.Value = ""
Me.WristBand.Value = ""
Me.Team.Value = ""
Me.Unit.Value = ""
MsgBox "Record has been updated", vbInformation
End Sub
This is where the application is erroring out...It stops here....on this line
empname = Application.Match(VBA.CStr(Me.Update_record.Value),
sh.Range("C:C"), 0)
So the data never gets updated to the row. Below are two screen shots... one of the worksheet and one of the userform.
There are three ways that I can immediatley think to go about it. I haven't tested the first two so let me know if you face any problem.
WAY ONE
Dim fName As String
Dim lName As String
Dim NameToSearch As String
Dim RecRow As Long
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Master")
fName = FirstNameTextbox.Value '<~~ First Name textBox
lName = LastNameTextbox.Value '<~~ Last Name textBox
NameToSearch = fName & ", " & lName
empname = Application.WorksheetFunction.Match(NameToSearch, sh.Range("C:C"), 0)
WAY TWO
This method uses .Find.
Dim fName As String
Dim lName As String
Dim NameToSearch As String
Dim aCell As Range
Dim ws As Worksheet
Dim RecRow As Long
fName = FirstNameTextbox.Value
lName = LastNameTextbox.Value
NameToSearch = fName & ", " & lName
Set ws = ThisWorkbook.Sheets("Master")
With ws
Set aCell = .Columns(3).Find(What:=NameToSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
RecRow = aCell.Row '<~~ This is the row where the data is
Else
MsgBox SearchString & " not Found"
End If
End With
WAY THREE (I prefer This)
Insert a column in the worksheet in Col A and call it ID. This will have unique serial numbers(row numbers?). When reading the item, read that as well and when writing it back to the cells, use that ID to write back. No need to search for the record using Match or .Find
In this case you will always update the row (ID + 1) assuming, the serial number starts at 1 from row 2.
I am working on a program that will create coversheets for projects.
All source data is held on the 'data' tab, and using lookups it is populated on the '1034' tab
Cell P2 on sheet '1034' contains the Project#, and after saving that form to PDF, should be set to the next value in the range of projects in 'data'
Below is what I have so far
Sub Generate1034()
'Select Project # Cell, set value to start
Range("P2").Value = Range(Application.Worksheets("Data").Range("A3"))
'Set range on 'data' from A3:(empty cell)
Range (Application.Worksheets("Data").Range("A3").Select)
Do Until IsEmpty(ActiveCell)
'Save Parameters
Application.Worksheets("1034").Range("P2") = Format(x, "000")
Dim SaveName As String
SaveName = ActiveSheet.Range("P33").Text
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=ActiveWorkbook.Path & "\1034\" & _
SaveName & ".pdf"\
'Set P2 to the next value in range
Range("P2").Value = Range(Application.Worksheets("Data").Range("A3"))
Loop
End Sub
This is the previous code that it was running on, but I would like to make it a bit more flexible if the size of the range changes.
This would lookup '001' on data, and return the value from colB
Sub SaveAs()
For x = 1 To 5
Application.Worksheets("1034").Range("P2") = Format(x, "000")
Dim SaveName As String
SaveName = ActiveSheet.Range("P33").Text
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=ActiveWorkbook.Path & "\1034\" & _
SaveName & ".pdf"
Next x
End Sub
I have the following code that allows me to search through the data on a table by using the option buttons I created that match the table headings. I can set the search criteria to be exact matches or partial. However, what I would like is to be able to search through different columns in the table without always having to go into the VBA code to toggle this option on and off. i.e some columns I would like an exact match, others I would like partial.
Any help on where I can amend the code below?
Sub SearchBox()
Dim myButton As OptionButton
Dim SearchString As String
Dim ButtonName As String
Dim sht As Worksheet
Dim myField As Long
Dim DataRange As Range
Dim mySearch As Variant
'Load Sheet into A Variable
Set sht = ActiveSheet
'Unfilter Data (if necessary)
On Error Resume Next
sht.ShowAllData
On Error GoTo 0
'Filtered Data Range (include column heading cells)
'Set DataRange = sht.Range("E5:H200") 'Cell Range
Set DataRange = sht.ListObjects("Table1").Range 'Table
'Retrieve User's Search Input
'mySearch = sht.Shapes("UserSearch").TextFrame.Characters.Text 'Control Form
mySearch = sht.OLEObjects("Hello").Object.Text 'ActiveX Control
'mySearch = sht.Range("A1").Value 'Cell Input
'Determine if user is searching for number or text
If IsNumeric(mySearch) = True Then
SearchString = "=" & mySearch
Else
'change this to =* if you want to search for anything that containts mysearch rather than just mysearch
SearchString = "=*" & mySearch & "*"
End If
'Loop Through Option Buttons
For Each myButton In sht.OptionButtons
If myButton.Value = 1 Then
ButtonName = myButton.Text
Exit For
End If
Next myButton
'Determine Filter Field
On Error GoTo HeadingNotFound
myField = Application.WorksheetFunction.Match(ButtonName, DataRange.Rows(1), 0)
On Error GoTo 0
'Filter Data
DataRange.AutoFilter _
Field:=myField, _
Criteria1:=SearchString, _
Operator:=xlAnd
'Clear Search Field
'sht.Shapes("UserSearch").TextFrame.Characters.Text = "" 'Control Form
sht.OLEObjects("Hello").Object.Text = "" 'ActiveX Control
'sht.Range("A1").Value = "" 'Cell Input
Exit Sub
'ERROR HANDLERS
HeadingNotFound:
MsgBox "The column heading [" & ButtonName & "] was not found in cells " & DataRange.Rows(1).Address & ". " & _
vbNewLine & "Please check for possible typos.", vbCritical, "Header Name Not Found!"
End Sub
Sub ClearFilter()
'PURPOSE: Clear all filter rules
'Clear filters on ActiveSheet
On Error Resume Next
ActiveSheet.ListObjects(1).AutoFilter.ShowAllData
On Error GoTo 0
End Sub
Modify and try the below:
Option Explicit
Sub test()
Dim ws As Worksheet
Dim SearchValue As String, FullReport As String
Dim rng As Range, cell As Range
'What i m looking for
SearchValue = "Test"
'Where to look for
Set rng = ThisWorkbook.Worksheets("Sheet1").UsedRange
For Each cell In rng
If cell.Value = SearchValue Then
If FullReport = "" Then
FullReport = "The word " & SearchValue & " appears in " & "Column " & cell.Column & ", Row " & cell.Row & "."
Else
FullReport = FullReport & vbNewLine & "The word " & SearchValue & " appears in " & "Column " & cell.Column & ", Row " & cell.Row & "."
End If
End If
Next cell
MsgBox FullReport
End Sub
If you have a fixed list of columns, then simply move the code where you set the SearchString below the part where you determine which column you want to search and check the selected field against this list. However, I would suggest to put this is a separate function:
Function getSearchString(searchVal as variant, searchFieldName as string)
If IsNumeric(searchVal) Then
getSearchString = "=" & searchVal
ElseIf searchFieldName = "MyField1" _
Or searchFieldName = "MyField2" _
Or (... List all fields where you want to search partial) Then
getSearchString = "=*" & searchVal & "*"
Else
getSearchString = "=" & searchVal
End If
End Function
You call the function after setting the var ButtonName.
searchStr = getSearchString(mySearch, ButtonName)
(you can of course think about a more sophisticated way to determine if or if not to use partial searching - or maybe add a CheckBox to let the user choose)
I am very new to VBA and coding in general. I am struggling with this bit of code where I would like to copy the data in row A in sheet "System 1" and use it in my validation list. However, with this current bit of code, it seems that I am getting the row data from my current sheet and not from sheet "System 1"
What am I doing wrong here? What's the best practice when referring to other sheets to optimise the speed sheet of excel?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim range1 As Range, rng As Range
Set Sheet = Sheets("System 1")
Set range1 = Sheets("System 1").Range("A1:BB1")
Set rng = Range("M2")
With rng.Validation
.Delete 'delete previous validation
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Formula1:="='" & Name & "'!" & .range1.Address
End With
This code should give you a good start. Fix and adjust to your needs. Study the customize sections of the code carefully. The WSChange should work perfectly except maybe there is something weird about those public variables (you can always put them into the procedure ... and the events are ... I don't get them, but I will soon enough.
You cannot use a range from a different worksheet to use it as a validation range (similar to conditional formatting, that is for Excel 2003), so you have to define a name to use as a range.
This one goes into a module. I just couldn't see it in the worksheet:
Option Explicit
Public strMain As String
Public Const cStrValList As String = "ValList" 'Validation List Name
Sub WSChange()
'-- Customize BEGIN --------------------
'Name of the main worksheet containing the validation RANGE.
'*** The worksheet should be defined by name so that this script can be run ***
'*** from other worksheets (Do NOT use the Activesheet, if not necessary). *** ***
Const cStrMain As String = "Main" 'If "" then Activesheet is used.
'Name of the worksheet containing the validation LIST.
Const cStrSys As String = "System 1"
'*** The next two constants should be defined as first cell ranges, so when ***
'*** adding new data, the last cell could be calculated again and the data *** ***
'*** wouldn't be 'out of bounds' (outside the range(s)).
'Validation RANGE Address. Can be range or first cell range address.
Const cStrMainRng As String = "$M$2" 'orig. "$M$2"
'Validation LIST Range Address. Can be range or first cell range address.
Const cStrSysRng As String = "$A$1" 'orig. "$A$1:$BB$1"
'-- Customize END ----------------------
strMain = cStrMain
Dim oWsMain As Worksheet
Dim oRngMain As Range
Dim oWsSys As Worksheet
Dim oRngSys As Range
Dim oName As Name
Dim strMainRng As String
Dim strMainLast As String
Dim strSysRng As String
Dim strSysLast As String
'---------------------------------------
On Error GoTo ErrorHandler 'No error handling so far!
'---------------------------------------
'Main Worksheet
If cStrMain <> "" Then 'When cStrMain is used as the worksheet name.
Set oWsMain = ThisWorkbook.Worksheets(cStrMain)
Else 'cStrMain = "", When ActiveSheet is used instead. Not recommended.
Set oWsMain = ThisWorkbook.ActiveSheet
End If
With oWsMain
If .Range(cStrMainRng).Cells.Count <> 1 Then
strMainRng = cStrMainRng
Else
'Calculate Validation Range Last Cell Address
strMainLast = .Range(Cells(Rows.Count, _
.Range(cStrMainRng).Column).Address).End(xlUp).Address
'Calculate Validation Range and assign to a range variable
strMainRng = cStrMainRng & ":" & strMainLast 'First:Last
End If
Set oRngMain = .Range(strMainRng) 'Validation Range
End With
'---------------------------------------
'System Worksheet
Set oWsSys = Worksheets(cStrSys) 'Worksheet with Validation List
With oWsSys
If .Range(cStrSysRng).Cells.Count <> 1 Then
strSysRng = cStrSysRng
Else
'Calculate Validation Range Last Cell Address
strSysLast = .Range(Cells(.Range(cStrSysRng).Row, _
Columns.Count).Address).End(xlToLeft).Address
'Calculate Validation Range and assign to a range variable
strSysRng = cStrSysRng & ":" & strSysLast 'First:Last
End If
Set oRngSys = .Range(strSysRng) 'Validation List Range
End With
'---------------------------------------
'Name
For Each oName In ThisWorkbook.Names
If oName.Name = cStrValList Then
oName.Delete
Exit For 'If found, Immediately leave the For Each Next loop.
End If
Next
ThisWorkbook.Names.Add Name:=cStrValList, RefersTo:="='" & cStrSys _
& "'!" & strSysRng
With oRngMain.Validation
.Delete 'delete previous validation
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=" & cStrValList
End With
'---------------------------------------
ProcedureExit:
Set oRngMain = Nothing
Set oRngSys = Nothing
Set oWsSys = Nothing
Set oWsMain = Nothing
Exit Sub
'---------------------------------------
ErrorHandler:
'Handle Errors!
MsgBox "An error has occurred.", vbInformation
GoTo ProcedureExit
'---------------------------------------
End Sub
And some 'eventing', not so good, but I've run out of patience.
This actually goes into the 'System 1' worksheet. You should maybe figure out something like that for the 'main' sheet.
Option Explicit
Public PreviousTarget As Variant
Private Sub Worksheet_Change(ByVal Target As Range)
'MsgBox Target.Cells.Count
'-- Customize BEGIN --------------------
Const cStr1 = "Validation List Change"
Const cStr2 = "Values have changed"
Const cStr3 = "Previous Value"
Const cStr4 = "Current Value"
'-- Customize END ----------------------
Dim str1 As String
'Values in the NAMED RANGE (cStrValList)
'Only if a cell in the named range has been 'addressed' i.e. a cell is
'selected and you start typing or you click in the fomula bar, and then
'enter is pressed, this will run which still doesn't mean the value has
'been changed i.e. the same value has been written again... If the escape
'key is used it doesn't run.
If Not Intersect(Target, Range(cStrValList)) Is Nothing Then
If Target.Cells.Count > 1 Then
WSChange
MsgBox "Cannot handle multiple cells, yet."
Else
'Check if the value has changed.
If PreviousTarget <> Target.Value Then 'The value has changed.
WSChange
str1 = cStr1 & vbCrLf & vbCrLf & cStr2 & ":" & vbCrLf & vbCrLf & "'" & _
Target.Address & "' " & cStr3 & " = '"
str1 = str1 & PreviousTarget & "'" & vbCrLf & "'" & Target.Address
str1 = str1 & "' " & cStr4 & " = '" & Target.Value & "'."
MsgBox str1, vbInformation
Else 'The value has not changed.
End If
End If
Else 'The cell range is out of bounds.
End If
'Values in the NAMED RANGE ROW outside the NAMED RANGE (cStrValList9
Dim strOutside As String
'Here comes some bad coding.
strOutside = Range(cStrValList).Address
strOutside = Split(strOutside, ":")(1)
strOutside = Range(strOutside).Offset(0, 1).Address
strOutside = strOutside & ":" _
& Cells(Range(strOutside).Row, Columns.Count).Address
If Not Intersect(Target, Range(strOutside)) Is Nothing Then
If Target.Cells.Count > 1 Then
WSChange
MsgBox "Cannot handle multiple cells, yet."
Else
If PreviousTarget <> Target.Value Then 'The value has changed.
If strMain <> "" Then
WSChange
Else
MsgBox "You have to define a worksheet by name under 'cStrMain'."
End If
End If
End If
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'This gets the 'previous' Target value. This is gold concerning the speed of
'execution. It's a MUST REMEMBER.
PreviousTarget = Target.Value
End Sub
Sub vallister()
MsgBox Range(cStrValList).Address
End Sub
Sub sdaf()
End Sub