I have a scenario in which there are three fields, based on the selection of First Field( 3 values in first field),the next field is getting values ( it is a dialogue list field) through DBcolumn. and then on the basis of selection of second field the third field is coming. All the above mentioned field are dialogue list field.
The issue is with multi selection, when ever multi values are selected out of first field the next fields are coming as DBColumn is used (due ot lesser values), but Since second filed has lots of values, we have to use DB Look up and here the multi selection is not fetching the data for corresponding filed.
Eg. I have a field named Database (having 3 values), and other two fields are Project(many values) and Brand.
I am using DBColumn to get Values in Project Field from Database field Selection (multi-selection), which I am getting properly (using #if), but after multi selection of Project Field (there are many values) I am not able to get values in next field (using DBLookup).
Please let me know any workaround....
First: Your code would have probably helped in solving this problem, although I think, it is not code- related:
Please check the field- property "refresh fields on keyword change" on the Project and the property "Refresh Choices on document refresh" on the Brand- Field.
If you do not get ANY- values whenever you select a second Project, then check, if your Key for Lookup is correctly used as an Multiple value for your DBLookup and that it does not try to lookup something like "value1;value2" instead of "value1" : "value2"...
Bets practice for debugging something like this, is to have a "BrandList" field, Computed for Display, hidden, with the DBLookup in it:
_viw := "YourViewName";
_crit := Project;
_col := 2;
REM "Don't do lookups, if project is empty";
#if( _crit = "" ; #Return( "" ) ; "" );
_lkp := #DBLookup( "" : "NoCache" ; _viw ; _crit ; _col );
#if( #IsError( _lkp ) ; "" ; _lkp );
And the let the brand point to this field (simply use the fieldname as Formula). that way you can easily debug the returned values.
In addition: If you are not sure, that there will be Brands for every Project you select, you need to add [FailSilent] to the lookup, otherwise the whole lookup will fail, if only one of the projects cannot be found... _lkp := #DBLookup( "" : "NoCache" ; _viw ; _crit ; _col; [Failsilent] );
BUT: Failsilent is very bad when debugging something, as you never get an error Message...
AND: For debugging purposes, you of course do NOT use the #IsError- line and simply return _lkp...
Related
I would like to write a script which goes to the first field of my layout, then evaluate if it is empty or not; if yes, it inserts "n.s." [not specified] and if it is not empty, it goes to the next field. And so on until the last field of my layout. In the end, it makes either a beep or a window appears saying "all done" (but this last part is optional and I can already do it).
My goal is to have a button which activates this script only when I press on it.
Up until now, I could make my script go from one field to another, but it would not write anything in the empty field it met... Aditionnally, most of the written function need a named target field and I would like to be able to go automatically from one field to another without having to change the target field name myself.
Here is my script at the moment:
Go to Field [Select/perform; Layout#1::Field#1]
If [IsEmpty ( Get ( ActiveFieldName ) )]
Insert Text [Select; "n.s."]
Go to Next Field
End If
Beep
It beeps but it doesn't write anything...
Or do you see a better solution ?
Not sure why you would need this, but if necessary, you could do it this way:
Go to Next Field
Set Variable [ $start; Value:Get ( ActiveFieldName ) ]
Loop
If [ IsEmpty ( Get ( ActiveFieldContents ) ) ]
Insert Text [ “n.s.” ]
End If
Go to Next Field
Exit Loop If [ Get ( ActiveFieldName ) = $start ]
End Loop
Beep
Note that this is (purposefully) not committing the record. And of course, all fields on the layout (or at least the fields that you want to include in this process) must be included in the tab order.
I find an interesting bug in a Dialog List field.
I am trying to create a list of years starting from this year minus 17 and have the list go backwards 30 years. (ex: 2003, 2002, 2001, 2000, ... 1973). I don't want to hardcode the options obviously since every year I would have to go back in and change it.
I created a simple Dialog List field and selected "Use formula for choices" and entered the following formula:
startYear := #Year(#Now)-17; #For( x:=1; x<=30; x:=x+1; temp[x] := startYear-x); temp
When I went to save it, it is rewritten as
startYear := #Year(#Now)-17; #For( x:=1; x<=30; x:=x+1; temp[x := startYear-x ]); temp
Obviously temp[x := startYear-x ] is not going to work but no matter what I try the editor keeps resetting the code to that.
Anyone know of a way to write this type of formula so that it will work and do what I want?
(Notes Designer 9.01 FP8)
First of all to answer your question: Assigning subscript of arrays like you do in Formula is not possible, see this excerpt from designer help (thanx #Richard Schwartz):
The subscript operator cannot be used on the left side of an assignment statement. That is, you cannot assign a value to a subscripted element. You must build the complete list and then assign it.
Second: I checked your formula, and if you put it in the "Value"- Formula of a field, then it is not modified by F9, only when putting it in the Dialog List Formula I can reproduce the same behaviour... But I would not mind: As it is not a valid formula at all, this imho can't be called "Bug".
So here is how your corrected formula could look like:
_startYear := #Year(#Now)-17;
#For( _x:=1; _x<=30; _x:=_x+1;
_temp := #Text(_startYear-_x);
_myArr := #Trim( _myArr : _temp )
);
_myArr
Don’t be confused because of the underscores: I use them to distinguish variables from fieldnames.
As Dialoglists store text, you need to convert the single values to text.
If you want the years in reverse order, then just change one line:
_myArr := #Trim( _temp : _myArr )
#Formula language -by the way- is quite cool regarding lists and one could have solved this in different ways. E.g. by using daterange and explode:
_start := #Adjust(#Today;-17;0;0;0;0;0);
_end := #Adjust(#Today;13;0;0;0;0;0);
_daterange := #TextToTime( "[" + #Text(_start) + "-" +
#Text(_end)+"]");
_allDates := #Explode( _dateRange );
#Text(#year(_allDates))
But I admit: as cool as it is, it is not really intuitive, but that would have been the solution in Notes 5 when there was no #For yet.
I am working on a document where I need to be able to test multiple options in an if statement to see if one of them are true to decide if a paragraph displays on the document. I have been trying to figure out why my OR formula is not returning a value for me to test and I am not sure why it is not showing anything when it is updating.
I have inserted a field and added a formula within that field that I am hoping will work with my If statement to show the proper paragraph contens.
When I use an Or statement, even one as simple as { OR(1=1) } and update and toggle the field I get no result. From what I have read I should get a 1 or a 0, but I don't seem to get either of these results. The line just ends up blank. When I test it with my If formula it always shows the false result, even when the Or contains a true result.
The formula I am currently working with is:
{ IF{ OR("$event.eventType.name}" = "Birthday", "$event.eventType.name}" =
"Conference" } "Yes" "No" }
If I update and toggle the Or field it shows blank, no result either true or false, and makes the If formula show as false event on results where it should show true. As I mentioned above I even tried setting it to 1=1 and still could not get it to show as true. Not sure if there is something I am missing in working with the formula.
Any suggestions would be appreciated.
It's not clear from your post what $event.eventType.name is. Presumably it's a field generated by an Addin. In that case, you should be able to use something like:
{IF{={IF{$event.eventType.name}= "Birthday" 1 0}+{IF{$event.eventType.name}= "Conference" 1 0}# 0}> 0 "Yes" "No"}
or:
{={IF{$event.eventType.name}= "Birthday" 1 0}+{IF{$event.eventType.name}= "Conference" 1 0} \# "'Yes',,'No'"}
Note: The field brace pairs (i.e. '{ }') for the above example are all created in the document itself, via Ctrl-F9 (Cmd-F9 on a Mac); you can't simply type them or copy & paste them from this message. Nor is it practical to add them via any of the standard Word dialogues. The spaces represented in the field constructions are all required. If your fields are a kind of mergefield, you'll need to insert 'MERGEFIELD ' at the start of each one, thus:
{MERGEFIELD $event.eventType.name}
I have a crystal report I need to modify to leave out duplicate rows by "name". So in Section Expert I am putting in a formula in Suppress and I cannot figure out how to compare the current name field being added to all the previous names that are in the group already. I was trying to use the Filter() function, but for the String array parameters I don't know what to enter that would be all of the other names previously added to the group. I need to compare the current name being added and see if it is already in the group so I can then compare another field called "date" and if the date of the field being added is more recent then the date of the duplicate name it will over write the row and only show the row with the most recent date.
Basically the question is how do I create an array with all the current fields already in the group(or does one exist already) so that I may use the Filter() function to see if the current name being added is already in that array of names added?
Well I figured it out, so for anyone who runs into this here is my solution.
first off I made a formula in the "formula fields" section that creates two arrays when reading the data from the database and keeps only one copy of each id and date in the record. Then for any other records that have the same id it will compare the date of that record to the record in the array with the same name and if the date is greater(later) then it will replace the date with the currently read in one. I named this formula field idArray.
Global StringVar Array idArray;
Global DateVar Array expArray;
BooleanVar addName;
NumberVar x;
StringVar idTest;
StringVar expDateTest;
whilereadingrecords;
(
addName := true;
for x := 1 to Ubound(idArray) step 1 do
(
if({hrpersnl.p_empno} = idArray[x]) then
(
addName := false;
if(Date({nemphist.enddate}) > expArray[x]) then
expArray[x] := Date({nemphist.enddate});
)
);
if(addName = true) then
(
reDim Preserve idArray[Ubound(idArray) + 1];
reDim Preserve expArray[Ubound(expArray) + 1];
idArray[Ubound(idArray)] := {hrpersnl.p_empno};
expArray[Ubound(expArray)] := Date({nemphist.enddate});
//idTest := idTest + ' ' + {hrpersnl.p_empno};
//expDateTest := expDateTest + ' ' + toText(Date({nemphist.enddate}));
);
//idTest
//Ubound(idArray)
//expDateTest
)
The commented out lines are what I used for testing to see how the arrays were building. I left them in there just as an example of how to debug crystal reports, since it doesn't come with a debugger.
The next step is to create a record suppression formula. In the Report menu I went to "section expert" and in the "Details" section of my group I clicked the little x-2 button next to the "Suppress (No Drill-Down)" option. I then inserted this code that looks at the current record's id and date and if the id is in the first array it will take its position and use that to retrieve the date from the second array and if the current record's date is less than the date we now know to be the max then it will suppress the record.
Global StringVar Array idArray;
Global DateVar Array expArray;
NumberVar x;
BooleanVar suppress := false;
for x := 1 to Ubound(idArray) do
(
if({hrpersnl.p_empno} = idArray[x]) then
if(Date({nemphist.enddate}) < expArray[x]) then
suppress := true;
);
if(suppress = true) then
true
else
false
Some lessons learned along the way...
Crystal Reports does global variables in a weird way. It took me a few hours of fudging around with them to figure out that you can basically use them anywhere in the report as long as you declare them in each section you put them in with the Global [vartype] "name" syntax. Even though you are re-declaring it each time Crystal does not remove the value of it or reset it or anything.
This operator ":=" is different than "=". The ":=" operator is used to set values for variables whereas the "=" seems to be used only for comparisons.
Crystal reports is really weird with its design. If you do want your formula field to return a specific variable or something you just type in that variable name without a ";" after it. Anything without a ";" after it is considered the end of the formula. So if you get this dumb "oh this code looks like its not part of the formula" error then it is because you didn't put a ";" after something and Crystal is assuming your function is ending at the location. But if you don't put a variable without a ";" after it your formula with just return "false" by default. So in my formula where I have //idTest
//Ubound(idArray)
//expDateTest
all I have to do is uncomment the variable I want to be returned and the formula will do so.
I have a problem in report studio. please help me to figure this out..
i have a optional prompt, i want to check whether the value is selected or not..
Please help how to check..
if (?parameter? is null ) then ('1') else ('2')
or
if (ParamDisplayValue('parameter') is null ) then ('1') else ('2')
Both the above are not working..
Suppose if i select any value in the prompt then the else part works and i get the result as 2, if i wont select anything then i'm not getting the result as 1
My guess, without doing extensive testing, is that an empty optional prompt doesn't exist at all and can't be compared to null. That said, I believe there's an easy fix.
Since you know that when you select an item '?parameter? is null' will return false, '?parameter? is not null' should return true and you can reverse the logic:
if (?parameter? is not null) then ('2') else ('1')
Try to put a conditional block. Set a block variable of type boolean with this expression:
ParamDisplayValue('myParam') is null
Then go to your conditional block again switch property "current block" to yes/no.
When yes (meaning that our block variable is true so the parameter is null) add a text item and just write "All".
When no add a text item with source type as report expression and write ParamDisplayValue('myParam')
P.S: there is also a way to count how many values the user selected (so as not to display all of them 1 by 1 but just show "62 values selected") but it needs some javascript and a hidden prompt field.
Use ParamCount
More details here:
http://joesanswers.blogspot.com.au/2008/09/checking-for-empty-parameters-in-cognos.html