Linq Dynamic Error with Dynamic Where clause - vb.net

I have a four dropdownlists that are used to filter/order a gridview.
If any of the first 3 dropdowns have a selected value other than 0 the the WhereFlag is set to True. The fourth dropdown is used to dictate which column the grid is ordered by.
My code for databinding the gridview uses System.Linq.Dynamic and is shown below...
Dim dc As New DiaryDataContext
If WhereFlag = False Then
'This section works...
Dim AList = dc.D_AreaSubAreas _
.OrderBy(ddl_SortBy.SelectedValue)
Dim dl As List(Of D_AreaSubArea)
dl = AList.ToList
dl.Insert(0, New D_AreaSubArea With {.Ref = 0,
.Area = "",
.SubArea = "",
.Allocation = "Allocation...",
.Redundant = False})
gv_AreaSubArea.DataSource = dl
gv_AreaSubArea.DataBind()
'Gridview successfully binds
'If ddl_SortBy value is changed... Gridview binds OK.
Else
'This section gives error...
Dim WhereBuild As New StringBuilder
If ddl_AreaFilter.SelectedIndex <> 0 Then
WhereBuild.Append("Area = '" & ddl_AreaFilter.SelectedValue & "'")
AndFlag = True
End If
If ddl_SubAreaFilter.SelectedIndex <> 0 Then
If AndFlag = True Then
WhereBuild.Append(" AND ")
End If
WhereBuild.Append("SubArea = '" & ddl_SubAreaFilter.SelectedValue & "'")
AndFlag = True
End If
If ddl_AllocFilter.SelectedIndex <> 0 Then
If AndFlag = True Then
WhereBuild.Append(" AND ")
End If
WhereBuild.Append("Allocation = '" & ddl_AllocFilter.SelectedValue & "'")
End If
'ERROR HERE
Dim AList = dc.D_AreaSubAreas _
.Where(WhereBuild.ToString) _
.OrderBy(ddl_SortBy.SelectedValue)
'END ERROR
Dim dl As List(Of D_AreaSubArea)
dl = AList.ToList
dl.Insert(0, New D_AreaSubArea With {.Ref = 0,
.Area = "",
.SubArea = "",
.Allocation = "Allocation...",
.Redundant = False})
gv_AreaSubArea.DataSource = dl
gv_AreaSubArea.DataBind()
End If
The error I get is with the dynamic where clause. The error I get is
ParseException is unhandled by user code. Character Literal must contain exactly one character
It points to the query AList in the Else fork. The only difference between it and the query in the If fork is the addition of the Where clause... but I have been unable to deduce what is wrong with my code. AHA.

The error points to the place where the LINQ query is evaluated and, as the message says, the problem is that a character is expected but several characters were provided.
Check whenever ddl_AreaFilter.SelectedValue, ddl_SubAreaFilter.SelectedValue or ddl_AllocFilter.SelectedValue actually contain a character or a string. If they contain more than one character, you should replace ' with \" when building the where condition, for instance:
WhereBuild.Append("Area = """ & ddl_AreaFilter.SelectedValue & """")
EDIT
You must make sure that the type of the value contained in each SelectedValue string match the corresponding database type. For instance, if the database column is a numeric type, the string content will be casted to a numeric type.
When you specify the value in the comparison using quotes, you are indicating that the type on the right side of the comparison is either character or string (depending on whenever you use single or double quotes, respectively).
So, what are the Area, SubArea and Allocation types in the database?
Single character: the value in your query should be around single quotes: Area = 'value'
Strings (for instance, varchar):you must use double quotes: Area = "value"
Other: then you should use no quotes: Area = value

Related

SSRS Distinct LookupSet Issue

I apologize for the long post but I'm losing my mind here. I've tried looking this up but I keep getting error messages on any suggested fixes on this thread:
SSRS distinct lookupset function
I've even tried to completely recreate a similar data set in that question but keep getting issues.
This is the data set I created.
Using this in the expression box, and grouping by itemID, rackID, UseByDate
Join(LookupSet(Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!CustomerSeqNo.Value
, "PickingList"), ",")
I get
but I would like to remove the duplicates in the LookupSet so it would just display "1".
I tried the first 2 options in that link above but they both provided an error message:
Public Shared Function RemoveDuplicates(m_Array As Object()) As String()
System.Array.Sort(m_Array)
Dim k As Integer = 0
For i As Integer = 0 To m_Array.Length - 1
If i > 0 AndAlso m_Array(i).Equals(m_Array(i - 1)) Then
Continue For
End If
m_Array(k) = m_Array(i)
k += 1
Next
Dim unique As [String]() = New [String](k - 1) {}
System.Array.Copy(m_Array, 0, unique, 0, k)
Return unique
End Function
with this expression:
=Join(Code.RemoveDuplicates(LookupSet(Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value
, Fields!CustomerSeqNo.Value
, "PickingList")), ",")
returns this warning:
[rsRuntimeErrorInExpression] The Value expression for the textrun 'CustomerSeqNo.Paragraphs[0].TextRuns[0]' contains an error: Operator '&' is not defined for type 'Integer' and type 'CalculatedFieldWrapperImpl'. and this error
The other solution doesn't even deploy. Any help here?
Luckily for you #JMG, I just had to do this for a customer!
Here's the function:
public function DistinctValues(input() as Object) as string
dim newList as String
for each n as string in input
if InStr(newList, cstr(n) + ", ") = false
newList += cstr(n) + ", "
end if
next
return left(newList, len(newList) -2)
end function
So what it's doing is parsing through each value in the array. We are going to insert each unique value into a comma delimited string. Before doing so, we just check the string with InStr to see if that value already exists.
Make sure you cast the return value to string via CSTR(Fields!CustomerSeqNo.Value) to avoid any datatype issues. Your code should look something like this.
Code.DistinctValues(LookupSet(Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value, Fields!itemId.Value & Fields!UseByDate.Value & Fields!rackId.Value, CSTR(Fields!CustomerSeqNo.Value), "PickingList"))

Using Ms Access VBA, how do I check the value of a variable to see if it has a value other than "', "

I have a variable with a string...and I want to know if it contains any value other than single quote, comma and a space ("', ") I'm using vba in excel.
for example, i have a varible strA = "'test', 'player'"
I want to check to see if strA has any characters other than "', " (single quote, comma and space).
Thanks
Here is a strategy based on Count occurrences of a character in a string
I don't have vba handy, but this should work. The idea is to remove all these characters and see if anything is left. text represents your string that is being tested.
Dim TempS As String
TempS = Replace(text, " " , "")
TempS = Replace(TempS, "," , "")
TempS = Replace(TempS, "'" , "")
and your result is Len(TempS>0)
Another approach is to use recursion by having a base case of false if the string is empty, if the first character is one of the three call ourselves on the rest of the string, or if not the value is true. Here is the code
function hasOtherChars(s As String) As Boolean
hasOtherChars=false
if (len(s)=0) then
exit function
end if
Dim asciiSpace As Integer
asciiSpace = Asc(" ")
Dim asciiComma As Integer
asciiComma= Asc(",")
Dim asciiApostrophe As Integer
asciiApostrophe = Asc("'")
Dim c as Integer
c = Asc(Mid$(s, 1, 1))
if ((c=asciiSpace) or (c=asciiComma) or (c=asciiApostrophe)) then
hasOtherChars = hasOtherChars(Mid$(s,2))
else
hasOtherChars=true
end if
End function
Again I am borrowing from the other thread.

Find a string between 1 or 2 sets of parenthesis

I'm looking for a way in VB to find a string between two characters,
"(" and ")".
For example, for the string...
"THIS IS (ONE) AND THIS IS (TWO)"
....I would like for a variable to store the characters between the
second set of parenthesis, e.g.
strMyString = "TWO".
But if the string to search only contains one set of parenthesis, to
store this instead. e.g.
strFirstString = "THIS IS (ONE)"
strMyString = "ONE"
As a preliminary answer, you can use this function to find the string within the last pair or brackets in your test string. If the brackets are in the wrong order or if brackets are missing it will throw an exception.
Private Function StringInLastBracketPair(testString As String) As String
Dim startBracket, endBracket As Integer
startBracket = testString.LastIndexOf("(") + 1
endBracket = testString.LastIndexOf(")")
If startBracket >= endBracket Or startBracket = 0 Or endBracket = -1 Then
Throw New System.Exception("String is not formatted properly : " & testString)
End If
StringInLastBracketPair = stringToTest.Substring(startBracket, endBracket - startBracket)
End Function

MS Access 2007 & SQL: SELECT ... IN ('get', 'list', 'of', 'variables', 'from', 'form'")

In a form a user makes choices using checkboxes.
Then VBA commands collect these choices into a string with comma separated numbers:
Dim choices As String
If (Me!choice1) Then
choices = "1,"
End If
If (Me!choice2) Then
choices = choices & "2,"
End If
Then these choices are saved in an invisible text field:
Me!choices.Value = choices (e.g. "1, 2, 5")
Then a report is open and it's source is a query:
SELECT ... FROM ... WHERE MyTable.MyVariable In (Forms!MyForm!choices) doesn't work.
If I manually write "1, 2, 5" in the query instead of Forms!MyPage!choices then it works.
Have also tried changing the string to other formats '1','2','5' and '1,2,5'
The reference to the variable is correctly spelled. So, how do I send this string to such a query?
Are you sure you removed the last comma in choices variable? It seems, based on the code you provided, that you have 1,2,5, instead of 1,2,5
Try to change this line:
Me!choices.Value = choices
into this solution:
Me!choices.Value = left(choices, len(choices)-1)
At the module level, Dim is equivalent to Private. As such, the expression Forms!MyForm!choices cannot see it. The 'quick fix' would be to change Dim to Public. However, a better solution would be to add a public accessor method. Further, there is no need to use an invisible text box - either just use a private string variable as the backing store, or don't cache the value at all. E.g.,
Option Explicit
Const MaxChoiceCount = 4 ' or whatever it actually is
Const ChoiceControlPrefix = "chkChoice" ' ditto
Private mChoices As String
Property Get Choices() As String
Choices = mChoices
End Property
Private Sub UpdateChoices()
Dim S As String, I As Integer
For I = 1 To MaxChoiceCount
If Me.Controls(ChoiceControlPrefix & I).Value Then S = S & I & ","
Next I
mChoices = Left$(S, Len(S) - 1)
End Sub
or
Option Explicit
Const MaxChoiceCount = 4 ' or whatever it actually is
Const ChoiceControlPrefix = "chkChoice" ' ditto
Function Choices() As String
Dim S As String, I As Integer
For I = 1 To MaxChoiceCount
If Me.Controls(ChoiceControlPrefix & I).Value Then S = S & I & ","
Next I
Choices = Left$(S, Len(S) - 1)
End Property

is it possible to use 2 parameters with dataview.rowfilter? How?

It works with 1 parameter (i_index) but if I also use i_datum, I get an error like: "Conversion from string "park_id = 100" to type 'Long' is not valid."
Public Function detail_kalender(ByVal i_index As Int16, ByVal i_datum As Date) As DataRowView
Dim dv As DataView
Dim anyrow As DataRowView
dv = New DataView
With dv
.Table = myds.Tables("kalender")
.AllowDelete = True
.AllowEdit = True
.AllowNew = True
.RowFilter = "park_id = " & i_index And "datum =" & i_datum
End With
anyrow = dv.Item(0) 'geeft de eerste rij van de dataview dv
' Simple bind to a TextBox control
dv = mydt_parken.DefaultView
Return anyrow
dv.Dispose()
dv = Nothing
End Function
Looking at the code you have there for the row filter, it will translate to:
.RowFilter = "park_id = 100datum = something"
Notice the lack of space between the park_id and next field. You also need to add "and" (I think?)
Try:
.RowFilter = String.Format("park_id = {0} and datum = {1}", i_index.Tostring, i_datum.ToString)
You may need to tinker this to include apostrophes depending on the types of your data (i.e. change to
... and datum = **'**{1}**'**
if it's a string)
EDIT: In response to your comment.
Have a look on this page for some useful tips. For dates you use the # symbols.
.RowFilter = String.Format("park_id = {0} and datum = #{1}#", i_index.Tostring, i_datum.ToString)
EDIT: In response to your second comment ( formatException"String was not recognized as a valid DateTime." ):
This is a little trickier. I'll list a possible quick solution, but by no means the best solution.
Dim customDateFormat As String = "MM/dd/yyyy hh:mm:ss"
.RowFilter = String.Format("park_id = {0} and datum >= #{1}# and datum <= #{2}#",
i_index.ToString,
New DateTime(i_datum.Year, i_datum.Month, i_datum.Day, 0, 0, 0).ToString(customDateFormat),
New DateTime(i_datum.Year, i_datum.Month, i_datum.Day, 23, 59, 59).ToString(customDateFormat))
Basically, the chances are that when you compare your date's to the date times in the database, you want to ignore the time? (Making an assumption here). One way of doing this is to compare your database data with your date, ensuring it is between 00:00 AM and 23:59:59 PM.
I've included a customDateFormat string which you can tamper if you need to, in order to reflect your locale. I know that date constants ignore locale, but I've no idea what it does inside the RowFilter as a string, and whether the database locale has any effect on it. If the above doesn't work, you can change the date format string to match your locale to see if that helps.
Try using instead:
.RowFilter = "park_id = " & i_index & " And datum =" & i_datum