Access VBA - Argument not optional - backcolor - ms-access

I have a table where the user can select a colour scheme for their database
ID | Colour | SelectedScheme
---|------------|--------------
1 | 136,207,39 | Yes
Then on my form I have the following on the current events tab
Dim RGBcolor As Long
RBGcolor = DLookup("Colour", "SelectedScheme")
Me.boxheader.BackColor = RGB(RGBcolor)
but I'm getting the Argument not optional error. any idea?

Arguments of RGB function are numeric, not string, and there should be 3 of them:
RGB(136,207,39)
You are trying to pass one string argument.
You can use Split function for extracting color values from string:
Me.boxheader.BackColor = RGB(Split(RGBcolor,",")(0),Split(RGBcolor,",")(1),Split(RGBcolor,",")(2))

The Dlookup function accepts these arguments:
FieldName: a field, calculation, control on a form, or function that you wish to return;
TableName: the set of records. This can be a table or a query name;
Criteria (Optional): It is the WHERE clause to apply to the TableName.
And the RGB functions accepts these three:
red: the red component of the color;
green: the green component of the color;
blue: the blue component of the color.
I would suggest you to use three different columns for the component color in your table:
ID | ColourR | ColourG | ColourB | SelectedScheme
---|---------|---------|---------|---------------
1 | 136 |207 | 39 | Yes
Your event can be written as this:
Me.boxheader.BackColor = RGB(
DLookup("ColourR", "SchemaTableName", "SelectedScheme=TRUE"),
DLookup("ColourG", "SchemaTableName", "SelectedScheme=TRUE"),
DLookup("ColourB", "SchemaTableName", "SelectedScheme=TRUE")
)
this will select the color from the table SchemaTableName where the field SelectedScheme is set to true.

The RGB() function expects 3 numbers, but your code supplies a single string value. That is the cause of the "Argument not optional" compile error.
Construct a new string which includes the RGB() function plus your string of numbers. Submit that new string to Eval() ...
Me.boxheader.BackColor = Eval("RGB(" & RBGcolor & ")")

Related

How to handle empty values in multi parameter SSRS field

I'm trying to modify a report that uses a multi value parameter (a|b|c|d). That parameter is split into multiple columns. The expression on the first column is =Split(Fields!AlternateVendorDetails.Value.ToString(),"|")(0). If that field is blank in the query, the field in the column is blank, which is right. However, the other columns evaluate to an error (=Split(Fields!AlternateVendorDetails.Value.ToString(),"|")(1)). I've tried =IIF(Fields!AlternateVendorDetails.Value.ToString()='','',Split(Fields!AlternateVendorDetails.Value.ToString(),"|")(1)), and I'm not sure what else will work.
SSRS evaluates expressions even when using Iif conditions and that causes the error.
You need custom code to overcome the limitation.
You can create a function that takes the string, the delimiter and array item index, and returns the value if string is not empty and value index exists
Public Function GetArrayItem( s As String, d As String, i As Integer) As String
If s = "" Or Split(s, d).Length < i+1 Then
Return Nothing
Else
Return Split(s, d)(i)
End If
End Function
I ended up putting a COALESCE(value1 | value2 | value3,' | | ') in the query. That created the necessary fillers to set the values to blank.

SSRS Iif Evaluates True and False

MSDN states that SSRS will evaluate both the true and false part of an Iif statement regardless of which one is returned. This seems to make Iif completely useless in regard to error avoidance. In other words, you cannot use Iif to skirt around an error, so essentially any operation you choose to include must always be valid regardless of the conditions. Honestly, what good is this?
So my question is... Does SSRS have other ways of evaluating conditions besides Iif?
Here is my example. I just want to be able to return Left without grabbing the first character of the match.
=Iif
(
InStr(Fields!SearchField.Value, Fields!Criteria.Value) <= 1,
"",
Left(Fields!SearchField.Value, InStr(Fields!SearchField.Value, Fields!Criteria.Value)-1)
)
However, what is happening here is that InStr(Fields!Criteria.Value, Fields!Criteria.Value)-1 is evaluating to 0 in some cases, which is perfectly fine until the FALSE part of the statement tries to deduct 1 from it and pass it into the InStr function. InStr cannot accept -1 as the number of characters to return.
An oversimplification of this is as follows. Assume you have a situation where Value can never fall below 0 without throwing an error.
Iif (Value > 0, Value = Value -1, 0)
Trying to use Iif to force the value not to fall below 0 does not work because all of these statements get evaluated even if they do not meet the conditions.
Trying to use InStr to get an index on a match, and Left to build a substring based on that index fails because of this. I have no idea how to completely avoid the condition.
I too thought Switch would work, but upon testing it did not. As far as I can tell, custom code is the only way to go. I tested the function below which worked for my few test cases.
Public Function TruncateWord(ByVal str As String, ByVal criteria As String) As String
If str.Contains(criteria) Then
Return Left(str, InStr(str, criteria) - 1)
Else:
Return ""
End If
End Function
I tested with the below 5 basic strings, searching for "d", and got the following results:
+-----------------+
| String | Result |
+-----------------+
| asdf | as |
| asd | as |
| as | |
| da | |
| ad | a |
+-----------------+
So this appears to work for all 3 possible cases (InStr returns > 1, InStr returns 1, and InStr returns 0) from my limited testing.
Here is the final result from C Black's suggestion to use custom code. I had eventually hoped to use the segment of the string to format the match in a different color in the opposite column. I had to add some html tags. It works perfectly. Thank you all for your assistance.
Code block:
Public Function ParseMatch (ByVal FullString As String, ByVal Criteria As String) As String
Dim Segment(2) As String
Dim Result As String
If FullString.ToUpper.Contains(Criteria.ToUpper)
Segment(0) = Left(FullString, InStr(Ucase(FullString), Ucase(Criteria) )-1 )
Segment(1) = Criteria
Segment(2) = Right(FullString, Len(FullString) - Len(Segment(0)) - Len(Criteria))
Result = Segment(0) & "<b><FONT color=blue>" & Segment(1) & "</FONT></b>" & Segment(2)
Else
Result = FullString
End If
Return Result
End Function
Report cell:
=Code.ParseMatch(Fields!Defendants.Value, Fields!Firm_Client_Name.Value)
If the name is found in the list of defendants, it colors the text blue in that field and bolds it.
Use SWITCH
SWITCH stops evaluating expression as soon as the first True is found. Switch works with pairs (an expression to evaluate and a result if it's true). The final True acts like an else.
=SWITCH
(
InStr(Fields!SearchField.Value, Fields!Criteria.Value) <= 1, "",
True, Left(Fields!SearchField.Value, InStr(Fields!Criteria.Value, Fields!Criteria.Value)-1)
)
I rewrote it for readability:
=Switch
(
InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value) = 0, "",
InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value) = 1, "",
True, Left(Fields!Defendants.Value, InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value)-1)
)
' 0 = Error
' 1 =
' >1 = substring based on criteria
1 and >1 are correct, but I still get the error when the InStr evaluates to 0.
The thing is, I have to tell the Left function -1 or it will return the first letter of the delimiter, which I do not want. Even though the condition of InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value) = 0 is true, instead of returning "" for the column, it returns an error. This tells me it is still being evaluated despite it being outside of the specified condition.
If I omit the -1 within the Left function, no error results. Yet I get substring + first letter of delimiter.
I work with sensitive information, so I cannot give specific results of the strings.

Progress 4GL: Cannot READ-JSON the JSON that was written

I am having a problem with Progress READ-JSON where it is not accepting the JSON that was output by WRITE-JSON. We are using TRACKING-CHANGES with a dataset with a nested data-relation.
OUTPUT TO "debug.txt".
DEFINE VARIABLE lcString AS LONGCHAR NO-UNDO.
DEFINE VARIABLE hdsBox AS HANDLE NO-UNDO.
DEFINE VARIABLE lOk AS LOGICAL NO-UNDO.
DEFINE TEMP-TABLE ttEmployee NO-UNDO
BEFORE-TABLE ttEmployeeBefore
FIELD eid AS INTEGER
FIELD empname AS CHAR.
DEFINE TEMP-TABLE ttBox NO-UNDO
BEFORE-TABLE ttBoxBefore
FIELD eid AS INTEGER SERIALIZE-HIDDEN
FIELD boxid AS INTEGER
FIELD boxdesc AS CHAR.
DEFINE DATASET dsBox FOR ttEmployee, ttBox
DATA-RELATION relat1 FOR ttEmployee, ttBox RELATION-FIELDS (ttEmployee.eid, ttBox.eid) NESTED.
CREATE ttEmployee.
CREATE ttBox.
ASSIGN ttEmployee.eid = 1
ttEmployee.empname = "Ian"
ttBox.eid = 1
ttBox.boxid = 10
ttBox.boxdesc = "Ians box".
hdsBox = DATASET dsBox:HANDLE.
ASSIGN TEMP-TABLE ttEmployee:TRACKING-CHANGES = YES
TEMP-TABLE ttBox:TRACKING-CHANGES = YES.
CREATE ttBox.
ASSIGN ttBox.eid = 1
ttBox.boxid = 11
ttBox.boxdesc = "Stewarts box"
/*ttEmployee.empname = "Stewart"*/ .
ASSIGN lOk = hdsBox:WRITE-JSON("LONGCHAR", lcString,FALSE , "UTF-8", FALSE, FALSE, TRUE).
ASSIGN TEMP-TABLE ttEmployee:TRACKING-CHANGES = NO
TEMP-TABLE ttBox:TRACKING-CHANGES = NO.
MESSAGE lOk ERROR-STATUS:GET-MESSAGE(1) SKIP.
MESSAGE STRING(lcString) SKIP.
ASSIGN lOk = hdsBox:READ-JSON("LONGCHAR":U, lcString, "EMPTY":U) NO-ERROR.
MESSAGE lOk ERROR-STATUS:GET-MESSAGE(1) SKIP.
This example generates the following output:
yes
{"dsBox":{"prods:hasChanges":true,"ttEmployee":[{"eid":1,"empname":"Ian","ttBox":[{"boxid":10,"boxdesc":"Ians box"},{"prods:id":"ttBox96513","prods:rowState":"created","boxid":11,"boxdesc":"Stewarts box"}]}],"prods:before":{}}}
no Error parsing JSON: expected string, but found bracket. (15358)
If I take out the comment on line 35, then it works, which leads me to believe it is a Progress bug.
I am using OpenEdge 11.4.
This is a Progress bug. To fix, I need to insert a meaningless field into the before-table of the JSON.
"prods:before":{"Progress11.4bug":"Need this string or Progress will barf"}
Progress doesn't like the before-table to be empty for some reason.

ActionScript: Specification of the is operator

I am having trouble googling for the expected behavior of the is operator in AS3. What I need to know is what should happen if the left side is null.
I know it is possible to test, and get empirical results, but I need to know what the specification says, and cannot find it anywhere.
You were not looking hard enough.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/operators.html#is
"Evaluates whether an object is compatible with a specific data type, class, or interface."
Because null is kinda SPECIAL CASE and "The Null data type is special in that it is not associated with a class" you will get false while using it with in operator.
The ActionScript 3 Language Specification says the following about the is operator:
The is operator checks to see if the value on the left is a member of
the type on the right. For user-defined types and most built-in types,
is returns true if the value is an instance of a class that is or
derives from the type on the right, otherwise it returns false.
Since null belongs to the special type Null which can't be extended and cannot be used on the right side of the is operator, the is operator will always return false.
| Value | String | Number | int | uint | Boolean | Object |
|-------|--------|--------|-------|-------|---------|--------|
| null | false | false | false | false | false | false |
You can find a bit more about how is operator works from this Adobe article:
It shows this example:
if (xParam is String) { /* do some String things */ }
else if (xParam is Number) { /* do some Number thing */ }
It shows that is operator is for type-checking. Consider var myNumber : dataType = new dataType. Now is the unknown dataType classed as Number?, int?, String? or Bitmap? This method allows you to create function code that anticipates what data format is input and can deal accordingly.
You dont use is to check for a null but alternatively you can use the == equality operator.
if (xParam == null) { /* do IS NULL things */ }
else { /* do some IS NOT NULL thing */ }

Display the non selected parameter in SSRS

In case of Multi-valued parameters,we usually use join function to display the selected values into a Text-box.But what if I wanted Show only the non selected parameters?IE If there are 10 values in the drop down list of a parameter and I selected the first 5 and wanted to display only the remaining 5 parameter instead of the first 5.What do i do?
I have created a multivalue parameter with the name Param which has had its labels and values set like so:
Label Value
====== =====
Label1 1
Label2 2
Label3 3
Label4 4
Label5 5
I then created the following code in the Report Properties --> Code menu:
'Global array objects to hold the total and selected values
Private Dim parameterList() AS string
Private Dim selectedParameters() AS string
'populates the list of all parameters using split and returns the input string
Public Function SetParameterList(nextParameter as String) AS String
parameterList = Split(nextParameter ,",")
Return nextParameter
End Function
'populates the list of selected parameters using split and returns the input string
Public Function SetSelectedParameters(delimitedParameters as String) AS String
selectedParameters = Split(delimitedParameters,",")
Return delimitedParameters
End Function
'Returns the not selected parameters
Public Function GetNotSelectedParameters() AS String
Dim notSelected As String
Dim i as Integer
Dim x as Integer
'Loop through each value in the all parameters array...
For i = 0 to parameterList.GetUpperBound(0)
'...for each one of those values check it against the selected parameters
For x = 0 to selectedParameters.GetUpperBound(0)
'Where there is a match, set the all parameters value to a string unlikely to be a genuine parameter value
IF parameterList(i) = selectedParameters(x) Then
parameterList(i) = "!*!"
End IF
Next
Next
'Join the all parameters array back into a string
notSelected = Join(parameterList, ", ")
'Remove the !*! values added earlier from the middle and the end of the string
notSelected = Replace(notSelected, "!*!, ", "")
notSelected = Replace(notSelected, ", !*!", "")
Return notSelected
End Function
To use this code I created 3 textboxes with the following expressions:
=Code.SetParameterList(Join(LookUpSet(1,1,Fields!ParamLabel.Value,"DataSet1"),","))
=Code.SetSelectedParameters(Join(Parameters!Param.Label, ","))
=Code.GetNotSelectedParameters()
Note: to hide the output of any of these textboxes, you could set the function return value to be "".
I imagine my code could be improved upon significantly, but this gets the job done and should at least point you in the right direction.
First create a multivalued parameter ("param1"), with available values ranging from 1 to 10.
Then create a query (query1), which returns the parameters from 1 to 10 filtering out the
selected values from "param1" -> where query1.col NOT IN (#param1)
Then create another multivalued parameter("param2"), set a default value (get values from a query) point to "query1" to fill in the unselected values
use a text box with the following code "=Join(Parameters!param1.Value,",")"
To make query1 you can use unions.
You will get back the values not selected,