Report Builder 3.0: syntax error when trying to loop through list of report parameters - vba

I'm trying to do the following:
Provide a list of available values for a parameter. User can select multiple values or none.
If a certain value exists in the list of selected parameters, show the corresponding column. If not, hide the column.
To do this, I wrote a custom function that takes in an integer, checks if this integer exists in the list of parameters, and outputs False/True to hide/show the column.
Parameter Examples:
Label Value
Pallet 1
Item 2
.
.
.
nth-label n
The code: Report Builder 3.0 is saying that I have a syntax error on line 8, but I'm not sure what it could be.
dim parm_array() as String
dim col_num as Integer
dim i as Integer
function hide_column (ByVal col_num as Integer) as Boolean
parm_array = Split(Join(Report.Parameters!show.Value,","), ",")
for i in LBound(parm_array) To UBound(parm_array)
if col_num = CInt(parm_array(i)) then
hide_column = 0
exit for
else
hide_column = 1
end if
next
end function

You can do this directly in an expression with something like
=Array.IndexOf(Parameters!myParameter.Value, 1) > -1
Note: If you have left your parameter type as the default text then the expression will have to have the value quoted like this
=Array.IndexOf(Parameters!myParameter.Value, "1") > -1
or for readability we could use the parameter label instead of it's value
=Array.IndexOf(Parameters!myParameter.Label, "Pallet") > -1
You might need to reverse the result (i.e. <=-1) if the column visibility is doing the opposite of what you expected.

Related

Variable in Dlookup in Access 2016 returns runtime error 13 - type mismatch

The logic isn't complex. The application uses a temporary table into which data for a report is appended. Once the report has been run, the data is cleared. Initially, the client told me that he would enter all the data (by taking attendance of people attending an event) would be done at once. Now, that has changed. I lookup the max ID in the temp table - if the number of rows is greater than 0. I then want to use dlookup to let the client know where she left off lest they create more problems.
Here's the logic:
Dim VMax As Variant
Dim VNFind As String
VMax = DMax("foodpantryid", "signin_sheet_data") 'This works correctly
MsgBox VMax 'This works correctly
VNFind = DLookup("last_name", "Dat_household_member", "[household_id]" = VMax) 'I get the type mismatch/error 13 here.
MsgBox VNFind 'so this never works
Additional information:
Household_id is a long integer. When I change it to integer, I get an error 94 (invalid use of null).
I have tried setting VMax to variant, integer, and long. Still no success. I would think variant would have worked.
The DLookup works if I don't include "[household_id]" = VMax.
I've tried including the =VMax in "" and that fails as well. That produces a 2471 error.
You've put your = outside the string delimiters.
This means: say your ID is 5. Then the parameter is "[household_id]" = 5. That's a comparison between the string "[household_id]" and the number 5, which causes a type mismatch, because you can't compare strings to numbers unless the string can be cast to a number.
Instead, you should include the = in your string, and the DLookUp should be:
DLookup("last_name", "Dat_household_member", "[household_id] = " & VMax)
Or, better yet, use parameters. This avoids most typecasting and string concatenation errors.
TempVars!VMax = VMax
DLookup("last_name", "Dat_household_member", "[household_id] = TempVars!VMax")
TempVars.Remove "VMax"

What am I missing in this IsEmpty clause?

In an Excel VBA module I'm building, I have some code to execute if a table of out-of-gauge cargo contains anything. I initially wrote this:
If Not IsEmpty(Range("OOGData")) Then
...
Else
...
End If
But even when OOGData is empty, it keeps returning False. I've tried it with If IsEmpty(Range("OOGData")) = False Then` but that doesn't seem to make any difference. My current code is
If IsEmpty(Range("OOGData")) = False Then
...but that still activates with the empty range.
I've made sure there are no formulae, hidden values or anything that could be showing up.
Any idea what the problem could be?
According to this information:
Returns a Boolean value indicating whether a variable has been
initialized.
In your code you are not working with variable therefore you shouldn't expect correct value.
When checking single cell you should use Len() function instead:
If Len(Range("OOGData"))=0 Then
'cell is empty
When checking if range of cells is empty use this solution:
If WorksheetFunction.CountA(Range("OOGData"))=0 Then
'rabge is empty
The final alternative I can think of is to use loops.
I've decided to cheat. Instead of checking the list there, I've added a Boolean variable (bContainsOOG) that's set to True any time an OOG cargo item is added to the OOG list, and then the reporting sub checks against that instead. But thanks both of you for those suggestions, they'll come in handy in another bit I was getting stuck on. :-)
This is a function that I thinks very closely fits:-
' Function to determine the last (first blank/null/empty) cell in a series of data in either a column
' or row
' Usage :- DataSeriesEnd(w,r,b)
' where w is the name of the worksheet.
' r is the row or column as an integer
' b is a boolean (true/false) if true then processing a column, if false a row
Public Function DataSeriesEnd(Worksheet As String, rc_index As Integer, bycolumn As Boolean) As Integer
Dim cv As Variant
For DataSeriesEnd = 1 To 500
If bycolumn Then
cv = Worksheets(Worksheet).Cells(DataSeriesEnd, rc_index)
Else
cv = Worksheets(Worksheet).Cells(rc_index, DataSeriesEnd)
End If
If IsNull(cv) Or IsEmpty(cv) Or cv = "" Then Exit For
Next DataSeriesEnd
' Position to previous cell (i.e. this one is empty)
DataSeriesEnd = DataSeriesEnd - 1
End Function
Note! There is a limit of 500 rows/columns

Count characters between two empty space to dashes() in vba

How do I get the length of character between beginning with space and ending with * Here is the image. Column B shows the total len before dasher(-) and my code
Sub xn()
Dim x As Integer
x = 1
If Worksheet("Sheet1").Range("A"& x).len(Right," ") Or _
Worksheet("Sheet1").Range("A"&x)len(Left,"-") Then
len(totallen)
End If
x = x + 1
End Sub
The code posted has multiple issues:
Worksheet is not a valid object - you need to use Worksheets.
.len is not a property of a Range object.
Even in .len was a property of a Range, you would need a
de-reference operator (aka '.') in here: Range("A"&x)len(Left,"-")
If you intend to use the function Len(), it only takes one argument.
You apparently are trying to loop, but you need to use either a For
or For Each loop - it won't loop automatically when you increment x
at the bottom of the sub.
Right is a function, but you're calling it without arguments and they are not optional.
Similarly, Left is a function, but you're also calling it without
the required arguments.
totallen is not declared anywhere, so Len(totallen) will assume
that totallen is a Variant (default for undeclared variables), then
cast it to a String, and then always return 0 because it has never
been given a value.
Anything else I may have missed.
The solution is to use the InStr function. It returns the location in a string of a given sub-string.
Sub xn()
Dim x As Long
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Worksheets("Sheet1")
For x = 1 To sheet.Range("A" & sheet.Rows.Count).End(xlUp).Row
sheet.Cells(x, 2) = InStr(1, sheet.Cells(x, 1), "-") - 1
Next x
End Sub
I'd also recommend taking a look at the MSDN article on Looping Through a Range of Cells (2003 vintage, but still valid), and Error Finding Last Used cell In VBA.

Comparing one dataset to another dataset in vb.net

I have two data set in my code. I need to compare that second data set
with first data set My first data set returns this result below:-
FirstDs:-
MaxUpdatedPrepped MaxUpdatedSent MaxUpdatedStamped
1900-01-01 1900-01-01 1900-01-01
And my second data set returns below:-
SecondDS:-
MaxUpdatedPrepped MaxUpdatedSent MaxUpdatedStamped
1900-01-01 1900-01-01 2014-11-11
I need to compare that both result and return alert like "Not matched" if the both first data set value is not match with second data set value. I tried a lot but i could get only wrong answer
For i As Integer = 0 To DsMaxDates1.Tables(0).Rows.Count - 1
Dim found As Boolean = False
For j As Integer = 0 To ds.Tables(0).Rows.Count - 1
If DsMaxDates1.Tables(0).Rows(i)(0).ToString = ds.Tables(0).Rows(j)(0).ToString Then
found = True
End If
Next
If found = False Then
ASPNET_MsgBox("Another User Working in Same Account. Please Click Reset.")
End If
Next
This above result returns true instead of false.
You should never change the type of your data unless it's absolutely necessary. Treat dates as Date, integers as Integer, strings as String, decimals as Decimal, etc. The ToString method is mostly used when you want to display the data to the user.
With that being said, you're not comparing datasets, you're comparing datatables.
The reason as to why it returns True is because you only compare the first column. You need to compare all the columns. If your table doesn't contain complex data types like byte arrays then the simplest way is to use LINQ combined with Enumerable.SequenceEqual.
The following code assumes that each table contains the same number of rows and columns.
''Uncomment to unleash the one-liner:
'Dim notEqual As Boolean = (From i As Integer In Enumerable.Range(0, DsMaxDates1.Tables(0).Rows.Count) Where (Not DsMaxDates1.Tables(0).Rows(i).ItemArray.SequenceEqual(ds.Tables(0).Rows(i).ItemArray)) Select True).FirstOrDefault()
Dim notEqual As Boolean = (
From i As Integer In Enumerable.Range(0, DsMaxDates1.Tables(0).Rows.Count)
Where (Not DsMaxDates1.Tables(0).Rows(i).ItemArray.SequenceEqual(ds.Tables(0).Rows(i).ItemArray))
Select True
).FirstOrDefault()
If (notEqual) Then
ASPNET_MsgBox("Another User Working in Same Account. Please Click Reset.")
End If
You can expand this even further by creating a reusable extension method:
Public Module Extensions
<System.Runtime.CompilerServices.Extension()>
Public Function SequenceEqual(table1 As DataTable, table2 As DataTable) As Boolean
Return (((((Not table1 Is Nothing) AndAlso (Not table2 Is Nothing))) AndAlso ((table1.Rows.Count = table2.Rows.Count) AndAlso (table1.Columns.Count = table2.Columns.Count))) AndAlso ((table1.Rows.Count = 0) OrElse (Not (From i As Integer In Enumerable.Range(0, table1.Rows.Count) Where (Not table1.Rows(i).ItemArray.SequenceEqual(table2.Rows(i).ItemArray)) Select True).FirstOrDefault())))
End Function
End Module
Then you can simply do as follows:
If (Not DsMaxDates1.Tables(0).SequenceEqual(ds.Tables(0))) Then
ASPNET_MsgBox("Another User Working in Same Account. Please Click Reset.")
End If

#VALUE error with Excel VBA Function

In my Excel spreadsheet I have two columns.
A contains strings with the values 'Yes', 'No' or 'Maybe'.
B contains strings with a year in.
I need a function to determine the number of occurrences of a year in column B, where the equivalent value in column A is 'Yes'.
I currently have the following code:
Function CountIfYearAndValue(Rng As Range, YNM As String, Year As String) As Integer
Dim count As Integer
count = 0
For Each c In Rng.Cells
If (StrComp(Abs(c.Value), Year, vbTextCompare) = 0) And (StrComp(Cells(c.Row, A), YMN, vbTextCompare) = 0) Then count = count + 1
Next
CountIfYearAndValue = count
End Function
The idea of this code is that we iterate through every cell in the range given (a range on column B) and check if the year is equal to the Year parameter. And if the equivalent cell on column A is equal to the YNM parameter we increment the count variable.
For some reason this code does not work when I use the following parameter:
=CountIfYearAndValue('Years'!B1:B7,"Yes","Year 7")
It just does the #VALUE error and refuses to display any outcome.
Any help would be much appreciated.
Edit: All of the values in both cells are on of an unformatted datatype ('General') and no cells are blank.
It sounds like you are reinventing the wheel... There already is a built in function (advantage: being much faster than a UDF) that does exactly what you are after. It is called COUNTIFS()
All YESes for Year 7 in rows 1 to 10.
=COUNTIFS(B1:B10, "Year 7",A1:A10, "Yes")
I just had a quick look at your code and I think there are possibly a few reasons why your original code is not working as expected.
YNM is a valid column name therefore it should not be used as a variable name. You should avoid naming your variables like that - give it a more meaningful name
YNM != YMN as you had it in your code (see function definition and then the misspelled version in the StrComp() function)
Year is a valid VBA built in function, therefore once again you should avoid using it as a variable name as you're exposing yourself to a naming collision.
Add Option Explicit at the top of your module. This requires you to Dimension all you variables. It's always recommended for many many reasons.
rng variable is of Range type therefore you do not need to explicitly add the .Cells property to it. Even though it may help in some cases - at a bit more advanced level you may face some runtime type compatibility issues. ( runtime may convert your rng Range variable to a 2D array etc )
Added an explicit conversion in the second StrComp() function around the c.Offset(0, -1) as you don't want the runtime to (rare but still possible) convert your Yes to a Boolean data type. Explicit conversion to a String just gives you that extra protection ;p (lol)
therefore, something like this returns the correct value
Function CountIfYearAndValue(rng As Range, choice As String, myYear As String) As Long
Dim count As Long
count = 0
Dim c As Range
For Each c In rng
If (StrComp(c, myYear, vbTextCompare) = 0) And (StrComp(CStr(c.Offset(0, -1)), choice, vbTextCompare) = 0) Then
count = count + 1
End If
Next c
CountIfYearAndValue = count
End Function
Right, I hope this helps you understand bits and pieces :) any questions please leave a comment