Option Explicit
Public PlotName As String
Public PlotRange As Range
Sub Tester()
Range("TCKWH.V.1").Select
AddPlot ActiveSheet.Range("KWH_G_1")
End Sub
Sub AddPlot(rng As Range)
With ActiveSheet.Shapes.AddChart
PlotName = .Name
.Chart.ChartType = xlLineMarkers
.Chart.SetSourceData Source:=Range(rng.Address())
.Chart.HasTitle = True
.Chart.ChartTitle.Text = Range("KWH.G.1")
.Chart.Axes(xlValue, xlPrimary).HasTitle = True
.Chart.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = Range("KWH.G.1")
End With
Set PlotRange = rng
Application.EnableEvents = False
rng.Select
Application.EnableEvents = True
End Sub
Sub FixPlott(rng As Range)
Dim n As Long
With ActiveSheet.Shapes(PlotName)
For n = .SeriesCollection.Count To 1 Step -1
With .SeriesCollection(n)
If PlotName = "" Then
.Delete
End If
End With
Next n
End With
End Sub
Sub RemovePlot(rng As Range)
If Not PlotRange Is Nothing Then
If Application.Intersect(rng, PlotRange) Is Nothing Then
On Error Resume Next
rng.Parent.Shapes(PlotName).Delete
On Error GoTo 0
End If
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.ScreenUpdating = False
RemovePlot Target
Application.ScreenUpdating = True
End Sub
I need help with Sub FixPlott. I am trying to get it to delete the Legend Entries on the Legend Key. For example if I select Main Campus and South Hall there will be blank legend entries for dunblane and greensburg. Id like the legend just to show selected buildings.
Here you have a corrected version of your sub:
Sub FixPlott(PlotName As String)
Dim n As Long
With ActiveSheet.Shapes(PlotName).Chart
For n = .SeriesCollection.Count To 1 Step -1
With .SeriesCollection(n)
If .Name = "" Then
ActiveSheet.Shapes(PlotName).Chart.Legend.LegendEntries(n).Delete
End If
End With
Next n
End With
End Sub
I am not sure about the exact trigger you want to use. So I have included a simple string trigger; if the given SeriesCollection is called like trigger, the legend will be deleted.
Related
I have basic code that allows the values written to this cell to be summed while maintaining the cumulative value. So if I were to type "4" into the cell, and then type "10" into the cell, the result would be "14" (not just the second value entered of "10"). Here is what I have and I must say that it works.
#
Option Explicit
Dim oldvalue As Double
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Address = "$J$5" Then
On Error GoTo fixit
Application.EnableEvents = False
If Target.Value = 0 Then oldvalue = 0
Target.Value = 1 * Target.Value + oldvalue
oldvalue = Target.Value
fixit:
Application.EnableEvents = True
End If
End Sub
#
However, I want to apply this treatment to more than just cell J5. Say for example, I want the same code logic applied to cell R5 as well.
Thur far I have tried using
OR
and I have also tried using
If Not Intersect (Target, Range("J5:R5")) Is Nothing Then
But each of these approaches ties the two cells together (so that what I enter into one gets summed into both - each cell is summing values added to the other). I can't figure it out to save my life, so took to this forum in the hopes of finding someone smarter than me.
Maybe (this is assuming existing logic is correct....not sure why you set old value to 0 if Target = 0 and what value the *1 adds?)
Option Explicit
Dim oldvalueJ As Double
Dim oldValueR As Double
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
On Error GoTo fixit
Application.EnableEvents = False
Select Case Target.Address
Case "$J$5"
If Target = 0 Then oldvalueJ = 0
Target = Target + oldvalueJ
oldvalueJ = Target
Case "$R$5"
If Target = 0 Then oldValueR = 0
Target = Target + oldValueR
oldValueR = Target
End Select
fixit:
Application.EnableEvents = True
End Sub
This is a bit more dynamic by allowing you to add unlimited cells; it also validates user input
Standard Module
Option Explicit 'Generic Module
Public Const WS1_MEM_RNG = "C5,J5,R5" 'Sheet1 memory cells
Public prevWs1Vals As Object
Public Sub SetPreviousWS1Vals()
Dim c As Range
For Each c In Sheet1.Range(WS1_MEM_RNG).Cells
If Len(c.Value2) > 0 Then prevWs1Vals(c.Address) = c.Value2
Next
End Sub
Sheet1 Module
Option Explicit 'Sheet1 Module
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.CountLarge = 1 Then
If Not Intersect(Target, Me.Range(WS1_MEM_RNG)) Is Nothing Then GetPrevious Target
End If
End Sub
Private Sub GetPrevious(ByVal cel As Range)
Dim adr As String: adr = cel.Address
Application.EnableEvents = False
If Not IsError(cel.Value) And IsNumeric(cel.Value2) And Not IsNull(cel.Value) Then
If IsDate(cel.Value) Then
cel.NumberFormat = "General"
cel.Value2 = prevWs1Vals(adr)
Else
If cel.Value2 = 0 Then prevWs1Vals(adr) = 0
cel.Value2 = cel.Value2 + prevWs1Vals(adr)
prevWs1Vals(adr) = cel.Value2
End If
Else
cel.Value2 = prevWs1Vals(adr)
End If
Application.EnableEvents = True
End Sub
ThisWorkbook Module
Option Explicit 'ThisWorkbook Module
Private Sub Workbook_Open()
If prevWs1Vals Is Nothing Then Set prevWs1Vals = CreateObject("Scripting.Dictionary")
SetPreviousWS1Vals
End Sub
It can also enforce positives only
use commas to separate ranges, and add a Worksheet_SelectionChange() event to record the last user selected cell
Option Explicit
Dim oldvalue As String
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Intersect(Target, Range("J5,R5")) Is Nothing Then Exit Sub
If Target.Value = 0 Then Exit Sub
On Error GoTo fixit
Application.EnableEvents = False
Target.Value = Target.Value + oldvalue
fixit:
Application.EnableEvents = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.CountLarge = 1 Then oldvalue = Target.Value
End Sub
I have excel sheet with dropdown list and when I choose anything from the list
macro will vlookup for requested value. But when I want to remove values from those cells, that I select them and press delete, it will show me "#N/A" and the excel is frozen, I cant do anything. Could you advise me, how can I avoid it, please?
Option Explicit
Private Sub Worksheet_Change()
Dim Target As Range
Dim selectedNa As Integer, selectedNum As Integer
selectedNa = Target.Value
If Target.Column = 10 Then
selectedNum = Application.VLookup(selectedNa, ActiveSheet.Range("dropdown"), 2, False)
If Not IsError(selectedNum) Then
Target.Value = selectedNum
Else: Exit Sub
End If
Else: Exit Sub
End If
End Sub
Try the following:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim selectedNa As Long, selectedNum As Variant
If Target.Column = 10 And Not IsEmpty(Target) Then 'selectedNa <> vbNullString Then '
Application.EnableEvents = False
On Error GoTo errhand
selectedNa = Target.Value
selectedNum = Application.VLookup(selectedNa, ActiveSheet.Range("dropdown"), 2, False)
If Not IsError(selectedNum) Then
Target.Value = selectedNum
End If
Application.EnableEvents = True
End If
Exit Sub
errhand:
If Err.Number <> 0 Then
Application.EnableEvents = True
End If
End Sub
Change your posted code to
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Dim selectedNa As Integer, selectedNum As Integer
On Error GoTo EH
Application.EnableEvents = False
selectedNa = target.Value
If target.Column = 10 Then
selectedNum = Application.VLookup(selectedNa, ActiveSheet.Range("dropdown"), 2, False)
If Not IsError(selectedNum) Then
target.Value = selectedNum
End If
End If
EH:
Application.EnableEvents = True
Debug.Print Err.Number, Err.Description
End Sub
The code HAS TO be put into the sheet module.
Have a look at the immediate window after you have changed or deleted a value in your sheet.
It looks like this is what you want, based on the information provided:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim CheckCells As Range
Dim ChangedCell As Range
Set CheckCells = Intersect(Me.Columns(10), Target)
Application.EnableEvents = False
If Not CheckCells Is Nothing Then
For Each ChangedCell In CheckCells.Cells
If Len(ChangedCell.Value) > 0 And WorksheetFunction.CountIf(Me.Range("dropdown"), ChangedCell.Value) > 0 Then
ChangedCell.Value = WorksheetFunction.VLookup(ChangedCell.Value, Me.Range("dropdown").Resize(, 2), 2, False)
End If
Next ChangedCell
End If
Application.EnableEvents = True
End Sub
I am having problem to make this code work - any help is much appreciated! I know the issue is to do with the first line...I have a Private Sub Worksheet_Change(ByVal Target As Range) above this code to address other elements that I need VBA code for.
Private Sub HideAndUnhideRowsInOtherWorksheet()
For Each c In Worksheets("FlatStage").Range("A7:A32")
If c.Value = "" Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next
For Each c In Worksheets("Efficiency").Range("A7:A32")
If c.Value = "" Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next
For Each c In Worksheets("DayRate").Range("A7:A10,A14:A22,A25:A25,A28:A39")
If c.Value = "" Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next
For Each c In Worksheets("AddServ").Range ("A6:A8,A10:A11,A13:A17")
If c.Value = "" Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next
For Each c In Worksheets("Enhancement").Range("A6:A7")
If c.Value = "" Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next
End Sub
If you call the code from the above Worksheet_Change() it should work, but if you call your Sub from another module it will not be visible because it's declared as Private (to that particular module)
All you need to do is change Private to Public
(or move it to a new generic module and make it Public there)
On the other hand, the screen might flash while it is executing
To fix this turn off ScreenUpdating before the loops, and turn it back on after
But you can also reduce the code so it will be easier to maintain:
Option Explicit
Public Sub HideAndUnhideRowsInOtherWorksheet()
Application.ScreenUpdating = False
ToggleRows Worksheets("FlatStage").Range("A7:A32")
ToggleRows Worksheets("Efficiency").Range("A7:A32")
ToggleRows Worksheets("DayRate").Range("A7:A10,A14:A22,A25:A25,A28:A39")
ToggleRows Worksheets("AddServ").Range("A6:A8,A10:A11,A13:A17")
ToggleRows Worksheets("Enhancement").Range("A6:A7")
Application.ScreenUpdating = True
End Sub
Private Sub ToggleRows(ByRef colRng As Range)
If Not colRng Is Nothing Then
Dim c As Range
For Each c In colRng
c.EntireRow.Hidden = Len(c.Value2) = 0
Next
End If
End Sub
Or, even smaller and faster if you can use AutoFilter:
Private Sub FilterRows(ByRef colRng As Range)
If Not colRng Is Nothing Then
colRng.Parent.UsedRange.Columns(colRng.Column).AutoFilter 'Filter symbol in top cell
colRng.AutoFilter Field:=1, Criteria1:="<>"
End If
End Sub
This sub will unhide all rows in all worksheets
Public Sub UnhideAllRowsInAllWorksheets()
Dim ws As Worksheet
For Each ws In Worksheets
With ws.UsedRange
If ws.AutoFilterMode Then .AutoFilter 'ws.ShowAllData
.Rows.EntireRow.Hidden = False
End With
Next
End Sub
I'm working on an Excel worksheet and using VBA to complete and update information on the cells.
There are seven columns in the Excel table. Three of them are drop-down lists with Data Validation, which I used the following VBA code to fill them.
Private Sub TempCombo_KeyDown(ByVal _KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer)
'Ocultar caixa de combinação e mover a próxima célula com Enter e Tab
Select Case KeyCode
Case 9
ActiveCell.Offset(0, 1).Activate
Case 13
ActiveCell.Offset(1, 0).Activate
Case Else
'Nada
End Select
End Sub
These columns also work with autocomplete, using the code below:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim str As String
Dim cboTemp As OLEObject
Dim ws As Worksheet
Dim wsList As Worksheet
Set ws = ActiveSheet
Set wsList = Sheets(Me.Name)
Application.EnableEvents = False
Application.ScreenUpdating = False
If Application.CutCopyMode Then
'Permite copiar e colar na planilha
GoTo errHandler
End If
Set cboTemp = ws.OLEObjects("TempCombo")
On Error Resume Next
With cboTemp
.Top = 10
.Left = 10
.Width = 0
.ListFillRange = ""
.LinkedCell = ""
.Visible = False
.Value = ""
End With
On Error GoTo errHandler
If Target.Validation.Type = 3 Then
Application.EnableEvents = False
str = Target.Validation.Formula1
str = Right(str, Len(str) - 1)
With cboTemp
.Visible = True
.Left = Target.Left
.Top = Target.Top
.Width = Target.Width + 15
.Height = Target.Height + 5
.ListFillRange = str
.LinkedCell = Target.Address
End With
cboTemp.Activate
'Abrir a lista suspensa automaticamente
Me.TempCombo.DropDown
End If
errHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
Exit Sub
End Sub
Anytime I update any cell on a row, I want that the content of the seventh column of this row is updated with the current date.
I tried using the following code, but it only works with common cells, the ones that I manually type its content. I want the seventh column to be updated when I change the drop-down list selection also.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = 1 Then Exit Sub
Application.EnableEvents = False
Cells(Target.Row, "U").Value = Date
End Sub
Is there any way to update the content of the column as I said before? Even when I change the option selected in the drop-down list?
Your code is fine except that you need to turn events back on. You have stopped events from firing with this line: Application.EnableEvents = False but you never turn the event firings back on again. So your code will work the first time you change a cell, the Worksheet_Change event will fire as expected. However, within this sub you have set EnableEvents to false and then never set it back to true. So you have stopped all future events, including this one, from firing again in the future. Here is the solution:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row = 1 Then Exit Sub
Application.EnableEvents = False
Cells(Target.Row, "U").Value = Date
Application.EnableEvents = True
End Sub
Hye there.
I would like to ask for any ideas from anyone here.
I have a lot of checkboxes in a worksheet which I link with a chart in the same worksheet. I would like to make a function which run the same code for each of the checkboxes ( I have 24 check boxes overall) when it is click. If you have any idea or suggestion, do tell me.
Here is the idea of mine for the flow of the code. I just have the same flow of code.
Private Sub CheckBox1_Click()
On Error Resume Next
Sheets("REPORT").Activate
ActiveSheets.ChartObjects("STOCK MOVEMENT GRAPH").Activate
On Error GoTo 0
If CheckBox1.Value = False Then
ActiveChart.SeriesCollection(1).Delete
Else
ActiveChart.SeriesCollection.Add Source:=Sheets("REPORT").Range("B4:AB4")
End If
End Sub
Private Sub CheckBox2_Click()
On Error Resume Next
Sheets("REPORT").Activate
Worksheets("REPORT").ChartObjects("STOCK MOVEMENT GRAPH").Activate
On Error GoTo 0
If CheckBox2.Value = False Then
ActiveChart.SeriesCollection(2).Delete
Else
ActiveChart.SeriesCollection.Add Source:=Sheets("REPORT").Range("B5:AB5"), PlotBy:=xlRows
End If
End Sub
Thanks in advance. Regards.
You can pull out the common code into a standalone Sub:
Sub UpdateChart(rowNum As Long, AddingIt As Boolean)
Dim cht As Chart, s As Series, rng As Range, f, i
Set cht = Sheets("REPORT").ChartObjects("STOCK MOVEMENT GRAPH").Chart
'what's the data range?
Set rng = Sheets("REPORT").Range("B3").Offset(rowNum, 0).Resize(1, 2)
If AddingIt Then
'note: not checking if already added....
cht.SeriesCollection.Add Source:=rng
Else
For i = cht.SeriesCollection.Count To 1 Step -1
Set s = cht.SeriesCollection(i)
f = s.Formula
If InStr(f, rng.Address()) > 0 Then s.Delete
Next i
End If
End Sub
Then your checkbox code reduces to this:
Private Sub CheckBox1_Click()
UpdateChart 1, CheckBox1.Value
End Sub
Private Sub CheckBox2_Click()
UpdateChart 2, CheckBox2.Value
End Sub
'etc....