Update computed fields without validating - lotus-notes

I have a form with a field ItemNumber that has a validation forumla that ensures a value is entered.
In lotusscript i create a new document with that form, then depending on the value of a different computed field ItemProductFamilyType (computed based on a field of another doc) i might want to populate ItemNumber.
The issue i have is that if i look at the value of ItemProductFamilyType it's blank, because it's not yet been computed. It'll only have a value once a field is updated, then it's the document refreshed/re-computed.
I'm trying to use ComputeWithForm for this (with the raiseError parameter being a 1 or 0), however because of validation formulas on other fields it's not letting me.
So, how can i get computed fields to update their value without checking/erroring on validation formulas?

Try adding a validation control field. So, add a field called "runValidation". It's computed for display, as it's only required for UI form events handling. It's formula is straight forward
#ThisValue or runValidation
In the QueryRecalc event or whenever you want to set the value for ItemProductFamilyType set it to "1".
Sub Queryrecalc(Source As Notesuidocument, Continue As Variant)
On Error Goto errHandle
Dim doc As notesDocument
Set doc = source.Document
' go populate your fields like ItemProductFamilyType
doc.runValidation = "1"
Exit Sub
errHandle:
Messagebox Lsi_info(2) + " : " + Str(Err) + " - " + Error(Err) + ", at line " + Str(Erl)
Exit Sub
End Sub
The same idea works in the translation formula of ItemProductFamilyType
Field runValidation := "1";
#thisValue;
In the validation formula for ItemNumber include the "runValidation" field to manage when the field should validate.
#if(runValidation="1";#if(#trim(#ThisValue)="";#Failure("Enter value");#Success);#Success)
You should now be able safely call a Source.Refresh method without inadvertently triggering validation rules until the data is ready.

I'm not sure if there's a Lotus Notes-specific workaround for this, but one trick that would work in any system is to have another test in your validation formulas. Instead of saying just #If(FieldName != ""; #Failure; #Success), add another condition that you can control like #If(DoValidation = "Yes" & FieldName != ""; #Failure; #Success). Then you can control validation by controlling the value of the DoValidation item.
I often add #IsDocBeingSaved to the condition so that validation only fires when you are saving the document:
#If(#IsDocBeingSaved & FieldName != ""; #Failure; #Success)

Another thought, given the potential that the ComputeWithForm method is unreliable: Why not check the value in the other document using LotusScript? In fact, you could call that same code from the QueryRecalc event and update the ItemProductFamilyType item, sparing you the need to duplicate code.

Related

Delete a field value based on checkbox-Netsuite

I have a requirement where if the user unchecks the checkbox the vale of certain field should be cleared while he saves it.
To be printed is a checkbox
Check # is field.
If the user unchecks the "To be Printed" checkbox the check # field should be clear while he saves the page.
This should be a user event and will be it be after submit funtion?
How do i achieve this?
Here you have two options to deal with your requirement.
1) You can write a Client script as #John mentioned above on his comment and on field change you can clear out those field values which you don't want to save upon your form submission.
2) Write a before submit function and validate the checkbox field value, if it is unchecked then clear out those fields, which you don't want to save.
I would recommend using user event before submit script to set field value as null, as client script may not fire if data entry point is through csv import, suitescript, etc.
if (nlapiGetFieldValue(TO_BE_SUBMITTED_FIELD_ID) == 'F'){
nlapiSetFieldValue('tranid', null);`
}
If you wish, You may write additional client script to disable/clear the field if value of checkbox is set to false, for better UX.
For sequence number I would say, use the below code (I am assuming sequence numbers are pure numbers)
if (nlapiGetFieldValue(TO_BE_SUBMITTED_FIELD_ID) == 'T'){
//search in descending order (use this code in your same before submit script)
var search = nlapiCreateSearch(RECORD_TYPE, ['mainline', 'is', 'T'], new nlobjSearchColumn('tranid').setSort(true));
var results = search.runSearch();
var records = results.getResults(0, 1);
var nextTranId = praseInt(records[0].getFieldValue('tranid'), 10) + 1;
nlapiSetFieldValue(tranid, nextTranId);
}

Checking what a value is in SSJS

I have this block of code in SSJS that I'm doing some field validation stuff:
thisDoc is a NoteXspDocument
fld = the name of a field
var thisValue = thisDoc.getValue(fld);
print("Check Text = " + thisValue);
print("Is is a Date " + (thisValue === Date))
when I run it the log has this:
Check Text = 09/10/15 12:00 PM
Is is a Date false
In this code I do not know what the datatype is of the fld which is a field name. I check the backend document and get the NotesItem.Type() and this field is of type text 1280 in the backend, but the NotesXspDocument has a date. I need to determine what the data type is thisValue sure acts like a NotesDateTime object, but I'm doing something wrong somewhere.
I think the issue might be the difference between a NotesDateTime and a java.util.Date but they drive me up the wall.
Further Edit --
The problem is that I have an Array of field names var Fields:Array that I then loop through and get fld = Fields[n] so when I get the value of the field it could be anything Text, Date, Number so when I do var thisValue = thisDoc.getValue(fld) or thisDoc.getItemValue(fld) I need to figure out what kind of value I have. I guess I could put the getItem..... inside a try until I find one that works but that seems like a less than optimum solution.
Try instanceof Date.class. What you've got is not checking the data type of thisValue against the underlying class, instead it's checking the object itself.
Because the field that I am retrieving can be just about anything I use
var thisValue = thisdoc.getValue(fld);
i had a lot of trouble then determining what kind of data I had. It could be a null Date/Number/String So the first thing I did was find out what the backend data type was:
var thisItem:NotesItem = thisDoc.getDocument().getFirstItem(fld);
var type:Integer = thisItem.getType()
This helps somewhat if the field has been previously set, but if it is a new document or the field has not received a value yet it will be type 1280 or text and probably null.
So my fisrt test is for null or "". then it becomes a bit tougher because I need to test for some values. In all my comboboxs I add the text "--- Select ?????" as the first item in the list so I tried to get a substring of "---" but because of variance in the datatype I needed to put that in a try:
try{
if (thisValue.substring(0,3) == "---"){
print("have null Prefix");
rtn = false;
errMsg.push("The field " + fld + " is a Required Field please enter a value");
break;
}catch(e){ etc
I then wrapped the various other datatype tests in trys and now I have it working.
Might be a better way but this works.
Use .getItemValue() to return a vector array, then test the data type. You can also try .getItemValueString() to return a text string or .getItemValueDate() or .getItemValueDateTime() to return date/time.
Since getItemValue() returns an array, use subscript to get the first element:
var thisValue = thisDoc.getItemValue(fld);
var thisIsDate = (thisValue[0] instanceof Date);
print("Check Text = " + thisValue[0]);
print("Is this a Date ? " + thisIsDate;

How to get the old value in an OnChange function in LotusScript?

I have a field called StartDate, and the field's OnChange function has a loop similar to this:
Set doc = view.GetFirstDocument
While Not (doc Is Nothing)
If (doc.Username = somevalue) Then
If (doc.StartDate(0) = specialdate) Then
' Do something here
End if
End if
Set doc = view.GetNextDocument(doc)
Wend
My problem is that doc.StartDate holds the new value of the field but I want the old one. How do I get the field's previous value? Basically I need to compare the field's old value with its new value.
Define a global variable like "StartDateOld" in form's (Global) / (Declarations).
Assign the value of field "StartDate" to this variable in PostOpen event.
You can use the old value in variable "StartDateOld" in OnChange event then.
Don't forget to set the changed value to "StartDateOld" at the end of OnChange event's code.
This works for a document in edit mode. I don't really understand what you want to achieve with your code running through the view though...

Get members of a group in Lotus Domino

I retrieve names from a group using formula, and put them in a field of type Names this way:
#Name([CN];NAME)
I want to manipulate this data in my code, but using Lotusscript. Can't find it at Google or Lotus Domino's Help. Is there a way I can handle this?
In LotusScript there is a class named "NotesName" to do such manipulations.
If there is a field named "NAME" in you document, then the code would look like:
Dim doc as NotesDocument
Dim nnName as NotesName
'Somehow get the document, using ws.CurrentDocument.document
'or db.UnprocessedDocments.GetFirstDocument, depends on your situation
Set nnName = New NotesName( doc.GetItemValue("NAME")(0) )
Whatyourlookingfor = nnName.Common
If NAME is a Multivalue then you would have to write a loop to get the common- name for every element in the array doc.GetItemValue("NAME")
The next time you have a question, check out the language cross reference in the help...
There it tells you, what the LotusScript- Pendant for #Name is.
Please try with below suggestion for getting list of person names from group.
First need to check the availability of searching group on names.nsf (All the groups are available on "($VIMGroups)" view.
if the group is available means you need to get the list of values from "Members" item
The members item have variant(list) values. So need to iterate the members for getting each value
Please refer the below sample code:
Set namesDb=session.GetDatabase(db.Server,"names.nsf")
Set groupVw=namesDb.GetView("($VIMGroups)")
Set groupDoc=groupvw.GetDocumentByKey("groupname")
persons= groupDoc.members
Forall person In persons
Msgbox person
End Forall
You can use the Evaluate method. It will return you the result of a Notes Formula:
Dim result as Variant
formula$ = "#Name([CN];NAME)"
result = Evaluate(formula$)
If the formula needs to be evaluated within the context of a document, you can pass that document as a second parameter to the method.
More info here

Cascading list boxes, with multi-select

I wound up modifying the source from a publically posted POC: http://datacogs.com/datablogs/archive/2007/08/26/641.aspx, which is a custom field definition for cascading drop downs. The modifications were to allow parent-child list boxes where a user can multiselect for filtering and selecting the values to be written back to a SharePoint list. I got the parent-child cascading behavior working, but the save operation only takes the first value that is selected from the list box. I changed the base type for the custom field control from "SPFieldText" to "SPMultiLineText", along with changing the FLD_TYPES field definition values from:
Text to Note and this did not work. So, I changed the field control base type to "SPFieldMultiChoice" and the FLD_TYPES to "MultiChoice" and still get the same result, which is only the first value that's selected, writing to the SharePoint list.
Does anyone have any idea how to get a custom field with multiple selections to write those multiple selections to a SharePoint list?
Thanks for taking the time to read through my post.
Cheers,
~Peter
I was able to accomplish this by inheriting from SPFieldLookup and overriding its internal handling of AllowMultipleValues:
In your FLDTYPES_*.xml set <ParentType>LookupMulti</ParentType>
In your extension of SPFieldLookup, be sure to override AllowMultipleValues (always true), FieldValueType (probably typeof(SPFieldLookupValueCollection)) and FieldRenderingControl. I also set base.LookupField = "LinkTitleNoMenu", though in retrospect I'm not sure why. :)
In your field editor control's OnSaveChange(), set the field's Mult value to true.
To set Mult, you can either string manipulation on field.SchemaXml:
string s = field.SchemaXml;
if (s.IndexOf(" Mult=", StringComparison.OrdinalIgnoreCase) < 0)
field.SchemaXml = s.Insert(s.IndexOf("/>", StringComparison.Ordinal), " Mult=\"TRUE\" ");
Or use reflection:
var type = field.GetType();
var mi = type.GetMethod("SetFieldBoolValue", BindingFlags.Instance | BindingFlags.NonPublic);
mi.Invoke(field, new object[] { "Mult", true });
It's been a while, so I might be forgetting something, but that should be most of it.

Resources