how to improve excel vba code of many ifs end ifs - vba

Private Sub Worksheet_Change(ByVal Target As Range)
If [C3] > 0 And [B3] > 0 And [B1] > 0 Then
Sheets("E-L1").Visible = True
Else
Sheets("E-L1").Visible = False
End If
If [C4] > 0 And [B4] > 0 And [B1] > 0 Then
Sheets("E-L2").Visible = True
Else
Sheets("E-L2").Visible = False
End If
If [C5] > 0 And [B5] > 0 And [B1] > 0 Then
Sheets("E-L3").Visible = True
Else
Sheets("E-L3").Visible = False
End If
If [C7] > 0 And [B7] > 0 And [B1] > 0 Then
Sheets("M-L1").Visible = True
Else
Sheets("M-L1").Visible = False
End If
If [C8] > 0 And [B8] > 0 And [B1] > 0 Then
Sheets("M-L2").Visible = True
Else
Sheets("M-L2").Visible = False
End If
If [C10] > 0 And [B10] > 0 And [B1] > 0 Then
Sheets("MIDPI-1").Visible = True
Else
Sheets("MIDPI-1").Visible = False
End If
If [C11] > 0 And [B11] > 0 And [B1] > 0 Then
Sheets("MIDPI-2").Visible = True
Else
Sheets("MIDPI-2").Visible = False
End If
If [C13] > 0 And [B13] > 0 And [B1] > 0 Then
Sheets("BR-1").Visible = True
Else
Sheets("BR-1").Visible = False
End If
If [C14] > 0 And [B14] > 0 And [B1] > 0 Then
Sheets("BR-2").Visible = True
Else
Sheets("BR-2").Visible = False
End If
If [C15] > 0 And [B15] > 0 And [B1] > 0 Then
Sheets("BR-3").Visible = True
Else
Sheets("BR-3").Visible = False
End If
If [C16] > 0 And [B16] > 0 And [B1] > 0 Then
Sheets("BR-4").Visible = True
Else
Sheets("BR-4").Visible = False
End If
If [C18] > 0 And [B18] > 0 And [B1] > 0 Then
Sheets("BR-LR1").Visible = True
Else
Sheets("BR-LR1").Visible = False
End If
If [C19] > 0 And [B19] > 0 And [B1] > 0 Then
Sheets("BR-LR2").Visible = True
Else
Sheets("BR-LR2").Visible = False
End If
If [C20] > 0 And [B20] > 0 And [B1] > 0 Then
Sheets("BR-LR3").Visible = True
Else
Sheets("BR-LR3").Visible = False
End If
If [C21] > 0 And [B21] > 0 And [B1] > 0 Then
Sheets("BR-LR4").Visible = True
Else
Sheets("BR-LR4").Visible = False
End If
If [C23] > 0 And [B23] > 0 And [B1] > 0 Then
Sheets("BR-SR1").Visible = True
Else
Sheets("BR-SR1").Visible = False
End If
If [C24] > 0 And [B24] > 0 And [B1] > 0 Then
Sheets("BR-SR2").Visible = True
Else
Sheets("BR-SR2").Visible = False
End If
If [C26] > 0 And [B26] > 0 And [B1] > 0 Then
Sheets("MOD-F1").Visible = True
Else
Sheets("MOD-F1").Visible = False
End If
If [C27] > 0 And [B27] > 0 And [B1] > 0 Then
Sheets("MOD-F2").Visible = True
Else
Sheets("MOD-F2").Visible = False
End If
If [C29] > 0 And [B29] > 0 And [B1] > 0 Then
Sheets("MOD-S1").Visible = True
Else
Sheets("MOD-S1").Visible = False
End If
If [C30] > 0 And [B30] > 0 And [B1] > 0 Then
Sheets("MOD-S2").Visible = True
Else
Sheets("MOD-S2").Visible = False
End If
End Sub
The above checks for 3 criteria for a worksheet to be visible, if all 3 is not satisfied, then worksheet is hidden
i.e. if the 3 criteria is met, then a certain worksheet will be visible
is there a better way of writing the above code?
seems to be redundant
too many ifs and end ifs
Many thanks

Private Sub Worksheet_Change(ByVal Target As Range)
Dim rowsIndex As Variant, sheetNames As Variant
rowsIndex = Array(3,4,5,7,8,10)
sheetNames = Array("E-L1","E-L2","E-L3","M-L1","M-L2","MISPI-1")
Dim index As Long
For index = LBound(rowsIndex) To UBound(rowsIndex)
Sheets(sheetNames(index)).Visible = Cells(rowsIndex(index), 2) > 0 And Cells(rowsIndex(index), 3) > 0 And Cells(1,2) > 0
Next
End Sub
Just fill those two arrays up with all your rows indexes and corresponding sheet names

Anytime you have something like:
If [C3] > 0 And [B3] > 0 And [B1] > 0 Then
Sheets("E-L1").Visible = True
Else
Sheets("E-L1").Visible = False
End If
You can shorten it. Since this :
( [C3] > 0 And [B3] > 0 And [B1] > 0 )
...returns True or False (without an If). ...and if it's True you want Visible=True. Therefore:
Sheets("E-L1").Visible = ( [C3] > 0 And [B3] > 0 And [B1] > 0 )
...is the equivalent. That will make a big change in all the similar sections.
Something that used to seem like a waste of time to me but actually is an important habit is proper spacing and indenting (especially when sharing your code with others of forums!).
There are various Simple example loose rules at ultimately the "style" is up to you, just make sure it's organized whatever it is.
For example, this:
Sub myExample
If [C29] > 0 And [B29] > 0 And [B1] > 0 Then
Sheets("MOD-S1").Visible = True
Else
Sheets("MOD-S1").Visible = False
End If
End Sub
Should be:
Sub myExample
If [C29] > 0 And [B29] > 0 And [B1] > 0 Then
Sheets("MOD-S1").Visible = True
Else
Sheets("MOD-S1").Visible = False
End If
End Sub
One more thing, do not get in the habit of using shorthand like [A1]+[B2]. That form of cell references is full of potential issues, and is mean for us in the immediate window for debugging, not as part of your code.
There are a few "proper" ways you can do it , the most common being, instead of:
[A1]
(declare at least one worksheet at the beginning of the procedure)
Dim ws as Worksheet
Set ws = Worksheets("mySheetName")
...and then you refer to the cell like:
ws.Ramge("A1")
It may seem like a lot more typing but there are important reasons for it. Proper organization will save you (and those you show your code to!) from headaches in the long run.
If you'd like to make that change and update the code in your question, we can take another look.

Slight variation to DisplayName's code which I think is pretty good.
Range B1 was common to all conditions, so why not place that as your first condition, and remove it from the rest of your code. Your ranges came in pairs so add them to an array. I placed all of the first half of the pair in the first half of the array so that you can make use of /2 as a Mod value to get the second half of the array values. The sheets array should of course equal your /2 value
Sub sheetVisibility()
On Error GoTo NoSheet
Dim ranges As Variant, sheets As Variant, arrayLen As Integer
If ([B1] > 0) Then
ranges = Array("C3", "C4", "C5", "C6", _
"B3", "B4", "B5", "B6")
arrayLen = UBound(ranges) / 2
sheets = Array("Sheet1", "Sheet2", "Sheet3", "Sheetx")
For i = 0 To UBound(ranges) Mod arrayLen
sheets(sheets(i)).Visible = (Range(ranges(i)) > 0 And Range(ranges(i + arrayLen)) > 0)
Next i
End If
End
NoSheet:
End Sub

Related

VB.NET Count bits, 1's are counted as 1, Zero's are counted together in a sequence between 1's

Looking to count bits in a sequence.
1's are counted as 1, Zero's are counted together in a sequence between 1's
If you look at this picture
The output should be 2,1,5,1,1,3,2,1
Here is my code it works on 80% of numbers sometimes it messes up.
dim bitmask() as byte
redim bitmask(15)
bitmask(0) = 0
bitmask(1) = 0
bitmask(2) = 1
bitmask(3) = 0
bitmask(4) = 0
bitmask(5) = 0
bitmask(6) = 0
bitmask(7) = 0
bitmask(8) = 1
bitmask(9) = 1
bitmask(10) = 0
bitmask(11) = 0
bitmask(12) = 0
bitmask(13) = 1
bitmask(14) = 0
bitmask(15) = 1
Public Function GetBitCount() As Byte()
Dim count As Byte = 0
Dim bitcounts As New List(Of Byte)
Dim indexOfNext As Integer = 0
Dim totalCounted As Integer = 0
While True
indexOfNext = Array.IndexOf(bitmask, CByte(1), indexOfNext + 1)
If indexOfNext > 0 Then
If indexOfNext - totalCounted = 1 Then
bitcounts.Add(2)
bitcounts.Add(1)
ElseIf indexOfNext - totalCounted > 0 Then
bitcounts.Add(IIf(totalCounted > 0, indexOfNext - totalCounted, indexOfNext))
ElseIf indexOfNext - totalCounted > 1 Then
bitcounts.Add(2)
bitcounts.Add(1)
Else
bitcounts.Add(1)
bitcounts.Add(1)
End If
If totalCounted = 0 Then bitcounts.Add(1)
totalCounted = indexOfNext + 1
Else
Exit While
End If
End While
If totalCounted - 1 > 2 AndAlso totalCounted - 1 < bitmask.Length - 1 Then
bitcounts.Add(1)
bitcounts.Add((bitmask.Length - 1) - (totalCounted - 1))
ElseIf totalCounted - 1 <= 2 AndAlso totalCounted - 1 < bitmask.Length - 1 Then
bitcounts.Add((bitmask.Length - 1) - (totalCounted - 1))
Else
bitcounts.Add(1)
End If
If count > 0 Then bitcounts.Add(count)
Return bitcounts.ToArray()
End Function
Solution
Public Function GetBitCount() As Byte()
Dim i As Integer = 0
Dim count As Byte = 0
Dim bitcounts As New List(Of Byte)
For i = 0 To bitmask.Length - 1
If bitmask(i) = 1 Then
bitcounts.Add(count)
count = 0
End If
count += 1
Next
If count > 0 Then bitcounts.Add(count)
Return bitcounts.ToArray()
End Function

SQL Server Query equivalent of excel formula

In my excel cellA to F are holding integer values.
IF(COUNTIFS(cellA:cellD,">0")=0,0,IF(COUNTIFS(cellA:cellD,">0")<=IF(AND(OR(cellE>=0),
cellE>0,cellF>0),1,0),"Y",0))
How can I convert the above excel formula into MSSQL query.
Note: In my SQL table named “MyData” the columns are as below and in brackets are corresponding cells in my excel.
You can check this below script works for you or not. If not, some adjustment should done the trick for you as all logic are there that you can be re-used
SELECT
CASE
WHEN
(
CASE WHEN 'CollE(CellA)' > 0 THEN 1 ELSE 0 END +
CASE WHEN 'CollE(CellB)' > 0 THEN 1 ELSE 0 END +
CASE WHEN 'CollE(CellC)' > 0 THEN 1 ELSE 0 END +
CASE WHEN 'CollE(CellD)' > 0 THEN 1 ELSE 0 END
) = 0
THEN "0"
WHEN
(
CASE WHEN 'CollE(CellA)' > 0 THEN 1 ELSE 0 END +
CASE WHEN 'CollE(CellB)' > 0 THEN 1 ELSE 0 END +
CASE WHEN 'CollE(CellC)' > 0 THEN 1 ELSE 0 END +
CASE WHEN 'CollE(CellD)' > 0 THEN 1 ELSE 0 END
) <= (CASE WHEN 'CollE(CellE)' > 0 AND 'CollF(CellF)' > 0 THEN 1 ELSE 0 END)
THEN "Y"
ELSE "0"
END
FROM your_table_name

Why does the following Integer type variable output -1?

Sub Test()
Dim iX As Integer
iX = 1 = 1
'Out put is -1
MsgBox iX
End Sub
Because if you compare 1 with a 1 this is True so 1 = 1 is True and True is considered as -1 in VBA by definition and you write this result into your variable iX.
This iX = 1 = 1 is evaluated the same as iX = (1 = 1) and this is iX = True and since iX is Integer the True is converted into a numeric value -1.
By definition in VBA:
True is -1
False is 0
But in Excel formulas
True is 1
False is 0

Nested IF statements in Hive

I'm looking to replicate an if statement into my Hive code. Essentially, I have spend from 2014-2018 for a corresponding client, I'm trying to understand the last year the client stopped spending with us and what the loss in $ is based on the previous year's spend. I can't do a CASE statement since there's a couple of variables that I'm looking at for every IF statements but I'm open to suggestions!
If (FY_2014 > 0, (If(FY_2015 = 0, FY_2014,0)), 0) as '2014to2015'
If (FY_2015 > 0, (If(FY_2016 = 0, FY_2015,0)), 0) as '2015to2016'
If (FY_2016 > 0, (If(FY_2017 = 0, FY_2016,0)), 0) as '2016to2017'
If (FY_2017 > 0, (If(FY_2018 = 0, FY_2017,0)), 0) as'2017to2018'
Thanks in advance for your help guys!
I think this would work exactly the same with less conditions.
case when FY_2014 > 0 AND FY_2015 = 0 then FY_2014 else 0 end as "2014to2015",
case when FY_2015 > 0 AND FY_2016 = 0 then FY_2015 else 0 end as "2015to2016",
case when FY_2016 > 0 AND FY_2017 = 0 then FY_2016 else 0 end as "2016to2017",
case when FY_2017 > 0 AND FY_2018 = 0 then FY_2017 else 0 end as "2017to2018"
How about a nested case?
case when FY_2014 > 0 then case when FY_2015 = 0 then FY_2014 else 0 end else 0 end as "2014to2015",
case when FY_2015 > 0 then case when FY_2016 = 0 then FY_2015 else 0 end else 0 end as "2015to2016",
case when FY_2016 > 0 then case when FY_2017 = 0 then FY_2016 else 0 end else 0 end as "2016to2017",
case when FY_2017 > 0 then case when FY_2018 = 0 then FY_2017 else 0 end else 0 end as "2017to2018"

multiple VBA if statements triggering different event

Sorry i think this is pretty basic but I was wondering if somebody could tell me why only 1 of these IF statements seem to run. The 3rd IF statement for the "CASH" option works but the other 2 unfortunately don't.
Sub HideUnhide_Discount()
If Range("Payment_Option") = "Subscription" Then
Range("MnthD_Row").EntireRow.Hidden = False
Range("MnthD").Value = 0
Else
Range("MnthD_Row").EntireRow.Hidden = True
End If
If Range("Payment_Option") = "Lease" Then
Range("OOD_Row").EntireRow.Hidden = False
Range("Leasing_Info").EntireRow.Hidden = False
Range("OOD").Value = 0
Else
Range("OOD_Row").EntireRow.Hidden = True
Range("Leasing_Info").EntireRow.Hidden = True
End If
If Range("Payment_Option") = "Cash" Then
Range("OOD_Row").EntireRow.Hidden = False
Range("MnthD_Row").EntireRow.Hidden = False
Range("OOD").Value = 0
Else
Range("OOD_Row").EntireRow.Hidden = True
Range("MnthD_Row").EntireRow.Hidden = True
End If
End Sub
Try replacing your multiple If >> Else condition with the Select Case below:
Sub HideUnhide_Discount()
' first reset all rows to be visible , later according to the value, unhide specific rows
Range("MnthD_Row").EntireRow.Hidden = True
Range("OOD_Row").EntireRow.Hidden = True
Range("Leasing_Info").EntireRow.Hidden = True
Select Case Range("Payment_Option")
Case "Subscription"
Range("MnthD_Row").EntireRow.Hidden = False
Range("MnthD").Value = 0
Case "Lease"
Range("OOD_Row").EntireRow.Hidden = False
Range("Leasing_Info").EntireRow.Hidden = False
Range("OOD").Value = 0
Case "Cash"
Range("OOD_Row").EntireRow.Hidden = False
Range("MnthD_Row").EntireRow.Hidden = False
Range("OOD").Value = 0
End Select
End Sub