Error 16: Expression Too Complex - Nested Select Case - vba

I am getting a "Run-Time Error 16: Expression Too Complex" for the sencond code block. I read online that the maximum allowed number of nested expressions is 8, but if nested statements are defined by every "Select Case," then I haven't yet hit that. Is it possible it's because the Cases are dependent upon a variable? The first code block shows the possible values of egapend, while the second shows the code that is returning the error. Thanks in advance for your help.
First:
Select Case ge1e2
Case Is <= 0
Select Case ge2e3
Case Is <= 0
egap18a = 0
egap18b = 0
Case Is > 0
egap18a = 0
egap18b = ge2e3
egapend = Sheet1.[z1IE]
End Select
Case Is > 0
Select Case ge2e3
Case Is <= 0
egap18a = ge1e2
egap18b = 0
egapend = Sheet1.[z1CZ]
Case Is > 0
Select Case ge1e2
Case Is >= 180
egap18a = ge1e2
egap18b = ge2e3
egapend = Sheet1.[z1CZ]
Case Is < 180
egap18a = ge1e2
egap18b = ge2e3
egapend = Sheet1.[z1IE]
End Select
End Select
End Select
Second:
Dim e1length As Long
Dim e2length As Long
Dim cp121 As Boolean
e1length = DateDiff("d", Sheet1.[z1CZ], Sheet1.[z1DA])
e2length = DateDiff("d", Sheet1.[z1IE], Sheet1.[z1IF])
Select Case extendedgap
Case True
Select Case egapend
Case Sheet1.[z1IE] 'end of egap is start of E2
Select Case e2length 'was borrower employed by E2 for more than 6 months?
Case Is >= 180
cp121 = True
Case Is < 180
Select Case ge1e2 'if not, was there a gap between E1 and E2
Case Is > 1
cp121 = False
Case Else
Select Case DateDiff("d", Sheet1.[z1IE], Sheet1.[z1DA]) 'If not, was employment between E1/E2 6 mos?
Case Is >= 180
cp121 = True
Case Is < 180
cp121 = False
End Select
End Select
End Select
Case Sheet1.[z1CZ] 'end of egap is start of E1
Select Case DateDiff("d", Sheet1.[z1CZ], Sheet1.[z1DA]) 'was borrower employed by E1 for at least 6 mos?
Case Is >= 180
cp121 = True
Case Is < 180
cp121 = False
End Select
End Select

It's really just a big nested conditional structure. Don't use Select...Case for that. Use it e.g. when you're looking at some enum value:
Select Case MsgBox("Yes, no, or cancel?", vbYesNoCancel)
Case vbYes
'stuff
Case vbNo
'stuff
Case vbCancel
'stuff
End Select
Refactoring step 1: Turn all these 2-branch Select...Case blocks into If...Else...End If blocks. That should already take care of the "expression too complex" compile error.
Refactoring step 2: Implement Boolean assignments as such:
For example in one place two places you have:
Select Case DateDiff("d", Sheet1.[z1IE], Sheet1.[z1DA]) 'If not, was employment between E1/E2 6 mos?
Case Is >= 180
cp121 = True
Case Is < 180
cp121 = False
End Select
Replace that with:
cp121 = (DateDiff("d", Sheet1.[z1IE], Sheet1.[z1DA]) >= 180)
Refactoring step 3: Extract functions and procedures out of the If and Else branches where applicable; eliminate the duplicated branches, Don't Repeat Yourself.
Once you have something that works, take it to Code Review for further refactoring and simplification ideas.

Related

VBA Select case 1 to 100 only taking 1

I'm trying to make a select case that identifies if a number is lower than 0, 1 to 100 or greater than 100, the thing is that is just doesn't work. Here's my code:
If IsNumeric(TxtTemp.Text) Then
Select Case TxtTemp.Text
Case Is <= 0
TxtEstado.Text = "Solid"
Case 1 To 100
TxtEstado.Text = "Liquid"
Case Is > 100
TxtEstado.Text = "Gas"
End Select
Else
TxtEstado.Text = ""
End If
I know that this is an easy thing to do, the thing is that the select case returns liquid only if the number received is equal to 1. If it is lower or equal to 0 it returns solid, but if it is equal or greater to 2, it returns gas. I don't understand what I'm doing wrong.
Maybe it is easier to use a function for this kind of conversion
Function chText(txt As String) As String
On Error GoTo EH
Dim resTxt As String
If IsNumeric(txt) Then
Select Case CDbl(txt)
Case Is <= 0
resTxt = "Solid"
Case 1 To 100
resTxt = "Liquid"
Case Is > 100
resTxt = "Gas"
End Select
Else
resTxt = ""
End If
chText = resTxt
Exit Function
EH:
chText = "Error"
End Function
Sub Tester()
Debug.Print chText("101")
' TxtEstado.Text = chText(TxtTemp.Text)
End Sub

Select Case statement and data validation

I am trying to validate data ranges using the select case statement. I am having issues with the other nested select cases. Is this possible or am i wishfull thinking? Or should i separate the select case statements to be stacked?
For instance this is my code in vb:
Select Case intyear
Case 2000 To 2025
Select Case intmonth
Case 1 To 12
BlnDateValid = True
End Select
Select Case intDay
Case 1 To 31
BlnDateValid = True
End Select
Select Case intHours
Case 0 To 23
BlnDateValid = True
End Select
Select Case intAddDays
Case 0 To 60
BlnDateValid = True
End Select
Select Case intAddHours
Case 0 To 23
BlnDateValid = True
End Select
Case Else
BlnDateValid = False
End Select
If blnDatevalid = false then
MessagebBox.Show("Please check all fields and enter valid
data", "Invalid data", MessageBoxButtons.OK)
Unfortunately, the indenting making sense doesn't help the code make sense. The whole point of Select Case is to neatly select one of multiple cases. A Select Case with one case is bad code and you should be using an If statement instead. You should especially be using a If statement in this case because you can replace all those Select Case statements with a single If statement.
If Not (intyear >= 2000 AndAlso intyear <= 2025 AndAlso
intmonth >= 1 AndAlso intmonth <= 12 AndAlso
intDay >= 1 AndAlso intDay <= 31 AndAlso
intHours >= 0 AndAlso intHours <= 23 AndAlso
intAddDays >= 0 AndAlso intAddDays <= 60 AndAlso
intAddHours >= 0 AndAlso intAddHours <= 23) Then
MessagebBox.Show("Please check all fields and enter valid data", "Invalid data", MessageBoxButtons.OK)
End If
All the Select or If checks will still leave you vulnerable to non-sensical values like February 30. Better to actually attempt to create a DateTime value.
Dim d As DateTime
Dim t As TimeSpan
Try
d = New DateTime(intYear, intMonth, intDay, intHours, 0, 0)
t = New TimeSpan(intAddDays, intAddHours, 0, 0)
If t > (New TimeSpan(60, 23, 0, 0)) Then Throw New ArgumentOutOfRangeException()
Catch
MessagebBox.Show("Please check all fields and enter valid data", "Invalid data", MessageBoxButtons.OK)
End Try
or you can create a string and try parsing it:
If Not DateTime.TryParse($"{intYear}-{intMonth}-{intDay} {intHours}:00:00")
MessagebBox.Show("Please check all fields and enter valid data", "Invalid data", MessageBoxButtons.OK)
End If

VBA Select Case number to number greater than and less than

Sub ss()
Dim a As Double
a = 6.99999999
Select Case a
Case 0 To 7:
MsgBox "ok"
Case Else:
MsgBox "no"
End Select
End Sub
The Case 0 to 7 results in a check for a >= 0 and a <= 7. But what I want is a >= 0 and a < 7.
I also tried Case Is >=0, Is < 7.
How can I do this in a Select Case?
a = 6.99999999 should result in "ok"
a = 7 should result in "no"
select case true
case a >= 0 and a < 7
MsgBox "ok"
case else
MsgBox "no"
end select
But, unless you have more than two conditions, I would suggest you use an If instead.
Sub ss()
Dim a
a = 7
Select Case a
Case 7:
MsgBox "no"
Case 0 To 7:
MsgBox "ok"
Case Else:
MsgBox "no"
End Select
End Sub
Sub ss()
Dim a As Double
a = 6.99999999
Select Case a
Case 0 To 7:
If a = 7 Then
MsgBox "no"
Else
MsgBox "ok"
End If
Case Else:
MsgBox "no"
End Select
End Sub
I finally work out this solution. Thank you all!

Query Timeout Expired in SSAS Cube Processing

While migrating a cube from 2008 to 2014, we had a cube processing failure with the message "Query Timeout Expired : HYT00". I looked into the error information and found a certain query executing for more than an hour which is causing the issue. The query is,
SELECT [dbo_IndicatorFact].[PY] AS [dbo_IndicatorFactPY0_0],[dbo_IndicatorFact].[BP] AS [dbo_IndicatorFactBP0_1],[dbo_IndicatorFact].[RE] AS [dbo_IndicatorFactRE0_2],[dbo_IndicatorFact].[UCPY] AS [dbo_IndicatorFactUCPY0_3],[dbo_IndicatorFact].[UCBP] AS [dbo_IndicatorFactUCBP0_4],[dbo_IndicatorFact].[UCRE] AS [dbo_IndicatorFactUCRE0_5],[dbo_IndicatorFact].[GRPY] AS [dbo_IndicatorFactGRPY0_6],[dbo_IndicatorFact].[GRBP] AS [dbo_IndicatorFactGRBP0_7],[dbo_IndicatorFact].[GRRE] AS [dbo_IndicatorFactGRRE0_8],[dbo_IndicatorFact].[NRPY] AS [dbo_IndicatorFactNRPY0_9],[dbo_IndicatorFact].[NRBP] AS [dbo_IndicatorFactNRBP0_10],[dbo_IndicatorFact].[NRRE] AS [dbo_IndicatorFactNRRE0_11],[dbo_IndicatorFact].[GRC2] AS [dbo_IndicatorFactGRC20_12],[dbo_IndicatorFact].[AnalysisCategoryId] AS [dbo_IndicatorFactAnalysisCategoryId0_13],[dbo_IndicatorFact].[IndicatorTypeId] AS [dbo_IndicatorFactIndicatorTypeId0_14],[dbo_IndicatorFact].[IndicatorNameId] AS [dbo_IndicatorFactIndicatorNameId0_15],[dbo_IndicatorFact].[CategoryId] AS [dbo_IndicatorFactCategoryId0_16],[dbo_IndicatorFact].[CountryId] AS [dbo_IndicatorFactCountryId0_17],[dbo_IndicatorFact].[FiscalQuarterId] AS [dbo_IndicatorFactFiscalQuarterId0_18]
FROM
(
SELECT vwIndicatorFact.IndicatorId AS Id,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN vwIndicatorFact.PY ELSE CASE IndicatorFact_GRC2.PY WHEN 0 THEN 0 ELSE vwIndicatorFact.PY END END AS PY,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN vwIndicatorFact.BP ELSE CASE IndicatorFact_GRC2.BP WHEN 0 THEN 0 ELSE vwIndicatorFact.BP END END AS BP,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN vwIndicatorFact.RE ELSE CASE IndicatorFact_GRC2.RE WHEN 0 THEN 0 ELSE vwIndicatorFact.RE END END AS RE,
vwIndicatorFact.BPvsPY, vwIndicatorFact.BPvsPYpercent, vwIndicatorFact.REvsBP, vwIndicatorFact.REvsBPpercent, vwIndicatorFact.REvsPY,
vwIndicatorFact.REvsPYpercent,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN CASE vwIndicatorFact.IndicatorNameId WHEN 1 THEN 1000000 ELSE IndicatorFact_UC.PY END ELSE CASE IndicatorFact_GRC2.PY
WHEN 0 THEN 0 ELSE CASE vwIndicatorFact.IndicatorNameId WHEN 1 THEN 1000000 ELSE IndicatorFact_UC.PY END END END AS UCPY,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN CASE vwIndicatorFact.IndicatorNameId WHEN 1 THEN 1000000 ELSE IndicatorFact_UC.BP END ELSE CASE IndicatorFact_GRC2.BP
WHEN 0 THEN 0 ELSE CASE vwIndicatorFact.IndicatorNameId WHEN 1 THEN 1000000 ELSE IndicatorFact_UC.BP END END END AS UCBP,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN CASE vwIndicatorFact.IndicatorNameId WHEN 1 THEN 1000000 ELSE IndicatorFact_UC.RE END ELSE CASE IndicatorFact_GRC2.RE
WHEN 0 THEN 0 ELSE CASE vwIndicatorFact.IndicatorNameId WHEN 1 THEN 1000000 ELSE IndicatorFact_UC.RE END END END AS UCRE, vwIndicatorFact.IndicatorNameId,
vwIndicatorFact.CategoryId, vwIndicatorFact.AnalysisCategoryId, vwIndicatorFact.CountryId, vwIndicatorFact.FiscalQuarterId, vwIndicatorFact.IndicatorTypeId,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN IndicatorFact_GR.PY ELSE CASE IndicatorFact_GRC2.PY WHEN 0 THEN 0 ELSE IndicatorFact_GR.PY END END AS GRPY,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN IndicatorFact_GR.BP ELSE CASE IndicatorFact_GRC2.BP WHEN 0 THEN 0 ELSE IndicatorFact_GR.BP END END AS GRBP,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN IndicatorFact_GR.RE ELSE CASE IndicatorFact_GRC2.RE WHEN 0 THEN 0 ELSE IndicatorFact_GR.RE END END AS GRRE,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN IndicatorFact_NR.PY ELSE CASE IndicatorFact_GRC2.PY WHEN 0 THEN 0 ELSE IndicatorFact_NR.PY END END AS NRPY,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN IndicatorFact_NR.BP ELSE CASE IndicatorFact_GRC2.BP WHEN 0 THEN 0 ELSE IndicatorFact_NR.BP END END AS NRBP,
CASE vwIndicatorFact.IndicatorTypeId WHEN 1 THEN IndicatorFact_NR.RE ELSE CASE IndicatorFact_GRC2.RE WHEN 0 THEN 0 ELSE IndicatorFact_NR.RE END END AS NRRE,
IndicatorFact_GRC2.BP AS GRC2
FROM
dbo.vwIndicatorFact INNER JOIN
dbo.vwIndicatorFact AS IndicatorFact_UC ON vwIndicatorFact.IndicatorTypeId = IndicatorFact_UC.IndicatorTypeId AND
vwIndicatorFact.FiscalQuarterId = IndicatorFact_UC.FiscalQuarterId AND vwIndicatorFact.CountryId = IndicatorFact_UC.CountryId AND
vwIndicatorFact.CategoryId = IndicatorFact_UC.CategoryId AND IndicatorFact_UC.IndicatorNameId = 1 LEFT OUTER JOIN
dbo.vwIndicatorFact AS IndicatorFact_GR ON vwIndicatorFact.IndicatorTypeId = IndicatorFact_GR.IndicatorTypeId AND
vwIndicatorFact.FiscalQuarterId = IndicatorFact_GR.FiscalQuarterId AND vwIndicatorFact.CountryId = IndicatorFact_GR.CountryId AND
vwIndicatorFact.CategoryId = IndicatorFact_GR.CategoryId AND IndicatorFact_GR.IndicatorNameId = 3 AND
IndicatorFact_GR.AnalysisCategoryId = vwIndicatorFact.AnalysisCategoryId LEFT OUTER JOIN
dbo.vwIndicatorFact AS IndicatorFact_NR ON vwIndicatorFact.IndicatorTypeId = IndicatorFact_NR.IndicatorTypeId AND
vwIndicatorFact.FiscalQuarterId = IndicatorFact_NR.FiscalQuarterId AND vwIndicatorFact.CountryId = IndicatorFact_NR.CountryId AND
vwIndicatorFact.CategoryId = IndicatorFact_NR.CategoryId AND IndicatorFact_NR.IndicatorNameId = 5 AND
IndicatorFact_NR.AnalysisCategoryId = vwIndicatorFact.AnalysisCategoryId LEFT OUTER JOIN
dbo.vwIndicatorFact AS IndicatorFact_GRC2 ON IndicatorFact_GRC2.IndicatorTypeId = 2 AND vwIndicatorFact.FiscalQuarterId = IndicatorFact_GRC2.FiscalQuarterId AND
vwIndicatorFact.CountryId = IndicatorFact_GRC2.CountryId AND vwIndicatorFact.CategoryId = IndicatorFact_GRC2.CategoryId AND
IndicatorFact_GRC2.IndicatorNameId = 3 AND IndicatorFact_GRC2.AnalysisCategoryId = 2
)
AS [dbo_IndicatorFact]
This is basically multiple self joins on a particular view which contains 300k records. Our dba updated all the indexes and updated the stats, But we are still not able to execute this query quickly. If this query executes quicker, there's a chance that the cube will process quicker. The data in the view also has no inconsistencies. Need some advice on what could be the issue here.
Some background on this - this is part of migration project that we are working on. The old dev environment is able to execute the same query in about 20 seconds with similar number of records in the view. The new dev takes forever to execute the same query with the same view.
In your statement it can be anything: poor indexes, outdated statistics, bad statement, huge data....
I had similar problem and I've increased external command timeout in SSAS(it is 1 hour by default). Look here how to do it if you will not manage to optimize your query:
http://www.msbiguide.com/2013/01/how-to-increase-externalcommandtimeout-in-ssas/

Combining Case Statements in a View

I have these two case statements and can not for the life of me figure out how to combine them to show in a MSSQL view. Any help would be great.
CASE WHEN [ordertype] = '2' THEN [CommissionAmt1] * - 1 ELSE [CommissionAmt1] END
and
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN 0 ELSE CommissionAmt1 END
Just adding the first case to wherever the CommissionAmt1 is referenced in the second statement.
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CASE WHEN [ordertype] = '2' THEN
[CommissionAmt1] * - 1
ELSE
[CommissionAmt1]
END
END
Or going the other way. It was hard to understand which way the calculation needs to be performed. The only hint was []
CASE WHEN [ordertype] = '2' THEN
(
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CommissionAmt1
END
) * - 1
ELSE
CASE WHEN (is_member('Buyer') = 1 OR is_member('CustomerService') = 1) THEN
0
ELSE
CommissionAmt1
END
END
Either way, you would be able to save some calculations by sub querying the dependent value.
SELECT
*,
ValueWithDependant=CASE WHEN (Dependant>0) THEN (SomeValue / Dependant) ELSE NULL END
FROM
(
SELECT
X,Y,Z,
Dependant=CASE WHEN SomeValue=1 THEN 1 ELSE 0 END
FROM
SomeTable
)AS DETAIL