Tips about programming, tips about software and web development in general and links to cool/useful tech sites
2010-05-04
Notes: Border appearing around image, even though hotspot's border is disabled
2008-01-14
Notes: SelectAll in an embedded view does not work
When using the formula in an embedded view, no document is selected.
Solution:
Use a button with these formulas:
@Command([OpenView];"view_name");
@Command([ViewCollapseAll]);
@Command([ViewExpand]);
@Command([EditSelectAll]);
@Command([FileCloseWindow]);
@Command([ToolsRunMacro];"(dummy_agent_name)")
2008-01-10
Notes: Document has not yet been saved error.
Scenario:
Embedded view on a form (or page) has an action button that invokes a LS agent to work on selected documents. This works fine in a regular view.
Problem:
This action button returns the error: "Document has not yet been saved".
Solution:
In embedded views, the LS needs to be in the action button.
2007-11-08
Notes: When a space is not a space
A field that receives numbers (either is a number field or is a text field that receives input from a number field on a dialog box), contains spaces (ex: 1 000 or 27 000) that can't be removed with a @ReplaceSubstring(field_name; " "; "").
Cause:
The number field has the "Punctuated at thousand" option set, which, in some user settings, causes the insertion of a space within the number. But this space is not the common ASCII character 32, but a special one: the ASCII character 160.
Solution:
Use this code:
sSpace1:=@char(32);
sSpace2:=@char(160);
sNumber:=@ReplaceSubstring(field_name; sSpace1; "");
sNumber:=@ReplaceSubstring(sNumber; sSpace2; "");
2007-10-25
Notes: Insert a DocLink into a Rich Text Field while editing the document (without the need of saving it)
So, an alternative is to have a page with an embedded view showing the documents list from where the user will choose the document to link to, and then call this page on a dialog box.
On the page's QueryClose event, add this:
@Command([EditMakeDocLink])
And on the form where the RichTextField is, add a button or an Action with a formula similar to this:
@DialogBox( "pg_name" ; [AutoHorzFit] : [AutoVertFit] : [NoNewFields] :
[NoFieldUpdate] : [SizeToTable] : [ReadOnly] ; "Insert Doc Link" );
@Do
( @PostedCommand([EditGotoField];"rtf_field_name");
@PostedCommand([EditInsertText]; @NewLine);
@PostedCommand([EditInsertText]; "Document link: ");
@PostedCommand([EditInsertText]; @NewLine);
@PostedCommand([EditInsertText]; @NewLine);
@PostedCommand([EditLeft];"2"); @PostedCommand([EditPaste]))
Notes: View Entry's ColumnValues returns an array for a specific column
In this case the ColumnValues property of the NotesViewEntry class, will return an Array and the common way of obtaining it's value will fail.
To access the entry's column value weather it's an array or not, use this:
And then use it like this:Function getColValue (vCol As Variant) As String
If Isarray(vCol) Then
getColValue = Cstr(vCol(0))
Else
getColValue = Cstr(vCol)
End If
End Function
stringValue = getColValue(vwEntry.ColumnValues(1))
2007-10-03
Notes: Scheduled agents on server
http://your_server/your_db_path/your_db/your_agent?openAgent
Now just go to the server's log to check for debug and/or error messages.
2007-08-02
Notes: Change the size of PicklistCollection dialog box
«I have found out the ini for resize PickList Window:
"WindowSizePickKeywords"
However, the parameter is found in Notes6 rather than 5, so chk version before writing it.
You can enlarge the PickList Window size before calling @PickList and restore it after calling
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub AssignPickWinSize
'To enlarge the PickList WIndow Size by setting system Notes.INI
'Backup the sys one with the same name as a user setting($)
On Error Goto ErrH
Const delim = " "
Const key="WindowSizePickKeywords"
Dim tmpstr As String
Set ss = New NotesSession
'get the system variable
tmpstr=Trim(ss.GetEnvironmentString(key, True))
If Len(tmpstr) Then
'BackUp the environment var
Call ss.SetEnvironmentVar(key, tmpstr, False )
tmpArr= Fulltrim(Split(tmpstr, delim))
tmpArr(2)="1000"
tmpArr(3)="900"
tmpstr=Join(tmpArr, " ")
'Set
Call ss.SetEnvironmentVar(key, tmpstr, True)
End If
Exit Sub
ErrH:
Print "Err in setting picklist window size."
End Sub
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Sub RestorePickWinSize
'Restore the backup setting from the same name user setting($) in ini
On Error Goto ErrH
Const key="WindowSizePickKeywords"
Dim ss As NotesSession
Dim tmpstr As String
Set ss = New NotesSession
tmpstr=Trim(ss.GetEnvironmentString(key, False))
If Len(tmpstr) Then
'Reset the system
Call ss.SetEnvironmentVar(key, tmpstr , True )
'Clear the user one
Call ss.SetEnvironmentVar(key, "" , False )
End If
ErrH:
End Sub »
2007-05-23
Notes: a Smart Icon to update a field in a document
There's many ways to accomplish this. From the simplest to the most complex:
Example 1:
FieldToChange := @Prompt([OkCancelEdit]; "Field to Change"; "Enter the name of the field to change."; "");
TypeOfData := @Prompt([OkCancelList]:[NoSort]; "Type of Field"; "Is this field Text, Number or DateTime?"; "Text"; "Text":"Number":"DateTime");
NewValue:=@Prompt([OkCancelEdit];"New Value";"Enter the new value for this field";"");
@If(FieldToChange=""|TypeOfData="";@Do(@Prompt([Ok];"Error";"You did not enter all requested data. Process halted.");@Return(""));"");
NumberValue:=@TextToNumber(NewValue);
valueerror:=@IsError(@If(TypeOfData="Number";NumberValue;3));
@If(valueerror=1;
@Do(@Prompt([Ok];"Error";"You did not specify a number for the new value. Process halted.");@Return(""));
"");
DateError:=@If(TypeOfData="DateTime";@If(@Text(@TextToTime(NewValue))="";1;0);0)
;
@If(DateError=1;
@Do(@Prompt([Ok];"Error";"You did not specify a date/time for the new value. Process halted.");@Return(""));
"");
continue := @Prompt([YesNo];"Click yes to continue.";"This agent will change the value of the *"+ FieldToChange +"* field on the selected documents to *"+ NewValue + "* . Continue?");
@If(continue=1;"";@Return(""));
@SetField(FieldToChange;
@If(TypeOfData="Text";NewValue;
TypeOfData="Number";@TextToNumber(NewValue);
@TextToTime(NewValue)));
@All
Example 2:
(from: Datatribe Softwerks)
strUNID := @Text(@DocumentUniqueID);Example 3:
strFieldName := @Prompt([OkCancelEditCombo]; "Change Field Value"; "To change an existing Field, select the Field name." +
@Char(13) + "To create a new Field, enter the Field name." ;""; "":@DocFields);
strTmpCurrentValue := @If( @IsAvailable(strFieldName); @GetDocField(strUNID; strFieldName); "" );
strCurrrentValue := @If( @IsError(strTmpCurrentValue); ""; @Text(strTmpCurrentValue) );
strNewValue := @Prompt([OkCancelEdit]; "Change Field Value"; "Enter New Field Value: use semicolon (;) to separate multiple values for mulitvalue fields."; @Implode(strCurrrentValue;";"));
strFieldType := @Prompt([OkCancelList]; "Change Field Value"; "Select the Field Data Type";
"Text"; "Text" : "Time" : "Number" : "Text List" : "Number List" : "Time List":"Delete Field");
@If(
strFieldType = "Delete Field";
@SetField(strFieldName; @DeleteField);
strFieldType = "Time";
@SetField(strFieldName; @TextToTime(strNewValue));
strFieldType = "Number";
@SetField(strFieldName; @TextToNumber(strNewValue));
strFieldType = "Text List";
@SetField(strFieldName; @Trim(@Explode(strNewValue;";")));
strFieldType = "Number List";
@SetField(strFieldName; @TextToNumber(@Explode(@Trim(@ReplaceSubstring(strNewValue;" ";""));";")));
strFieldType = "Time List";
@SetField(strFieldName; @TextToTime(@Explode(strNewValue;";")));
@SetField(strFieldName; @Text(strNewValue))
)
(from: Datatribe Softwerks's comments)
REM {Get a listing of all the fields on the current document};Example 4:
List := @DocFields;
PromptLimit := 254;
REM {Possible data types to choose from.};
REM {I called Number Integer because use keyboard to select what you want with keyboard quicker.};
DataTypes := "Text" : "Date" : "Integer" : "Password" : "Name" : "Common Name" : "Abbreviate Name" : "Remove Field" : "Text Multi Value" : "Date Multi Value" : "Integer Multi Value" : "Name Multi Value" : "Common Name Multi Value" : "Abbreviate Name Multi Value" : "Upper Case Text" : "Lower Case Text" : "Proper Case Text" : "Upper Case Text Multi Value" : "Lower Case Text Multi Value" : "Proper Case Text Multi Value" ;
REM {Prompt for which field needs to be updated.};
EditField := @Prompt( [OkCancelList] ; @DbTitle + " - " + @ViewTitle ; "Select the field you wish to alter:" ; "Subject" ; List ) ;
REM {Prompt for which data type you would like the data to be};
REM {This needs to be done before value prompt to determine if the Picklist or any prompting needs to be used.};
DataType := @Prompt( [OkCancelList] : [NoSort] ; EditField + " - " + @DbTitle + " - " + @ViewTitle; "Please select the correct data type or action for field: " + EditField + "."; "Text" ; DataTypes );
REM {Based on what type of data is being entered different prompts will happen if any at all.};
RawValue := @If(
@Contains( DataType ; "Name Multi Value" ); @PickList( [Name] );
@Contains( DataType ; "Name" ) ; @PickList( [Name] : [Single] );
DataType = "Remove Field" ; "" ;
@Contains( DataType ; "Multi Value" ); @Prompt( [OkCancelEdit] ; EditField + " - " + @DbTitle + " - " + @ViewTitle; "Please enter the new desired value for: " + EditField + "." + @Char(13) + @Char(13) + "Seperated with ; for each value." ; @Abstract([TextOnly] ; PromptLimit ; "" ; @Text( EditField ) ) );
@Prompt( [OkCancelEdit] ; EditField + " - " + @DbTitle + " - " + @ViewTitle ; "Please enter the new desired value for: " + EditField + "." ; @Abstract([TextOnly] ; PromptLimit ; "" ; @Text( EditField) ) ) );
REM {If data conversion doesn't work then don't set field.};
@If(
DataType = "Date" ; @If( @SetField( EditField ; @TextToTime( RawValue ) ) );
DataType = "Integer" ; @If( @IsError( @TextToNumber( RawValue ) ) ; "" ; @SetField( EditField ; @TextToNumber( RawValue ) ) ) ;
DataType = "Common Name" ; @SetField( EditField ; @Name( [CN]; RawValue ) ) ;
DataType = "Abbreviate Name" ; @SetField( EditField ; @Name( [Abbreviate]; RawValue ) ) ;
DataType = "Password" ; @SetField( EditField ; @Password( RawValue ) ) ;
DataType = "Remove Field" ; @SetField( EditField ; @DeleteField ) ;
DataType = "Text Multi Value" ; @SetField( EditField ; @Explode( RawValue ; ";" ) ) ;
DataType = "Date Multi Value" ; @SetField( EditField ; @TextToTime( @Explode( RawValue ; ";" ) ) ) ;
DataType = "Integer Multi Value" ; @If( @IsError( @TextToNumber( @Explode( RawValue ; ";" ) ) ) ; "" ; @SetField( EditField ; @TextToNumber( @Explode( RawValue ; ";" ) ) ) ) ;
DataType = "Name Multi Value" ; @SetField( EditField ; @Explode( RawValue ; ":" ) ) ;
DataType = "Common Name Multi Value" ; @SetField( EditField ; @Name( [CN]; @Explode( RawValue ; ":" ) ) );
DataType = "Abbreviate Name Multi Value" ; @SetField( EditField ; @Name( [Abbreviate]; @Explode( RawValue ; ":" ) ) );
DataType = "Upper Case Text" ; @If( @SetField( EditField ; @UpperCase( RawValue ) ) );
DataType = "Lower Case Text" ; @If( @SetField( EditField ; @LowerCase( RawValue ) ) );
DataType = "Proper Case Text" ; @If( @SetField( EditField ; @ProperCase( RawValue ) ) );
DataType = "Upper Case Text Multi Value" ; @If( @SetField( EditField ; @UpperCase( @Explode( RawValue ; ";" ) ) ) );
DataType = "Lower Case Text Multi Value" ; @If( @SetField( EditField ; @LowerCase( @Explode( RawValue ; ";" ) ) ) );
DataType = "Proper Case Text Multi Value" ; @If( @SetField( EditField ; @ProperCase( @Explode( RawValue ; ";" ) ) ) );
@SetField( EditField ; RawValue )
);
""
(from: ChadSmiley Blog)
REM {Edit Document Fields 6.0.0 by Chad Schelfhout.};
REM {Visit http://www.chadsmiley.com/EditDocumentFields for the latest updates};
REM {Changable constants};
cEnableConfirmation := @True;
cFieldHistoryValues := 10;
cStandardSeparators := ":" : ";" : " ";
cPromptTitle := @DbTitle + " - " + @ViewTitle;
REM {Unchangable constants};
cProfileName := "ChadSmiley Tools";
cEditLastField := "edfLastField";
cEditLastFieldDataType := "edfLastFieldDataType";
cEditLastFieldDataTypeValue := "edfLastFieldDataTypeValue";
cEditLastSeparator := "%~%";
cValueListSeparator := "^";
cFromRawValueSeparator := "%@%";
cSemicolonReplace := "#SC#";
cMaxSearchForSelectedDocs := 5520;
cMaxUpdatedDocuments := 1000;
cArraySeparator := ";";
cNoteEntryLength := 11;
cPromptNewLineOne := @Char(13);
cPromptNewLineTwo := cPromptNewLineOne + cPromptNewLineOne;
cPromptTab := @Char(9);
cCategoryNoteID := "NT00000000";
cTextExtractList := "Text Left":"Text Left Back":"Text Right":"Text Right Back";
cNoPromptList := cTextExtractList:"Remove Field":"Unique":"Sort Ascending":"Sort Descending":"Implode":"Explode":"Proper Case Text":"Proper Case Text Multi Value":"Lower Case Text":"Lower Case Text Multi Value":"Upper Case Text":"Upper Case Text Multi Value":"Password Convert":"Trim":"Trim then Unique";
cErrorCheckCode := "@Implode( @Unique( @Explode( NoteIDList : ErrorNoteID ; cArraySeparator ; @False ) ) )";
cErrorInformation := "\"Error documents: \" + @Implode( @Unique( @Explode( ErrorNoteIDList ; cArraySeparator ; @False ) ) ; \", \" ) + cPromptNewLineOne + \"Not updated documents: \" + @Implode( @Unique( @Explode( ErrorNoteIDList ; cArraySeparator ; @False ) ) ; \", \" )";
REM {Data types|@Function execution};
DataTypesCombo := @Explode(
"Integer|@TextToNumber( RawValue )$"+
"Integer Multi Value|@TextToNumber( @Explode( RawValue ; Separator; @True) )$"+
"Date|@ToTime( RawValue )$"+
"Date Multi Value|@ToTime( @Explode( RawValue ; Separator; @True) )$"+
"Text|@Text( RawValue )$"+
"Text Multi Value|@Text( @Explode( RawValue ; Separator; @True) )$"+
"Text Left|@Left( @Text( @GetField( EditField[ef] ) ) ; ExtractValue )$"+
"Text Left Back|@LeftBack( @Text( @GetField( EditField[ef] ) ) ; ExtractValue )$"+
"Text Right|@Right( @Text( @GetField( EditField[ef] ) ) ; ExtractValue )$"+
"Text Right Back|@RightBack( @Text( @GetField( EditField[ef] ) ) ; ExtractValue )$"+
"Trim|@Trim( @Text( @GetField( EditField[ef] ) ) )$"+
"Trim then Unique|@Unique(@Trim( @Text( @GetField( EditField[ef] ) ) ) )$"+
"Name|RawValue$"+
"Name Multi Value|RawValue$"+
"Common Name|@Name( [CN]; RawValue )$"+
"Common Name Multi Value|@Name( [CN]; @Explode( RawValue ; \":\"; @True ) )$"+
"Upper Case Text|@UpperCase( @Implode( @Text( @GetField( EditField[ef] ) ) ) )$"+
"Lower Case Text|@LowerCase( @Implode( @Text( @GetField( EditField[ef] ) ) ) )$"+
"Proper Case Text|@ProperCase( @Implode( @Text( @GetField( EditField[ef] ) ) ) )$"+
"Upper Case Text Multi Value|@UpperCase( @Explode( @Text( @GetField( EditField[ef] ) ) ; Separator; @True ))$"+
"Lower Case Text Multi Value|@LowerCase( @Explode( @Text( @GetField( EditField[ef] ) ) ; Separator; @True) )$"+
"Proper Case Text Multi Value|@ProperCase( @Explode( @Text( @GetField( EditField[ef] ) ) ; Separator; @True) )$"+
"Replace Substring|@ReplaceSubstring( @GetField( EditField[ef] ); FromRawValue ; RawValue )$"+
"Replace|@Explode( @Replace( @GetField( EditField[ef] ) ; FromRawValue ; RawValue ) ; Separator ; @True )$"+
"Implode|@Implode( @Text( @GetField( EditField[ef] ) ) ; Separator )$"+
"Explode|@Explode( @Text( @GetField( EditField[ef] ) ) ; Separator; @True )$"+
"Formula|@Eval( RawValue )$"+
"Abbreviate Name|@Name([Abbreviate]; RawValue )$"+
"Abbreviate Name Multi Value|@Name( [Abbreviate]; @Explode( RawValue ; Separator; @True ) )$"+
"Password Set|@Password( RawValue )$"+
"Password Convert|@Password( @GetField( EditField[ef] ) )$"+
"Remove Field|@DeleteField$"+
"Unique|@Unique(@GetField( EditField[ef]))$"+
"+ Append Values|@If(" +
" @GetField(EditField[ef]) = \"\"; RawValue;" +
" @Contains(DefaultDataType; \"Date\");" +
" @If( @IsError( @ToTime( RawValue ) ) ;" +
" \"\" ;" +
" @SetField( EditField[ef] ; @GetField(EditField[ef]) : @TextToTime( @Explode( RawValue ; Separator ) ) ) ) ;" +
" @Contains(DefaultDataType; \"Integer\" );" +
" @If( @IsError( @TextToNumber( @Explode( RawValue ; Separator ) ) ) ;" +
" \"\" ;" +
" @SetField( EditField[ef] ; @GetField(EditField[ef]) : @TextToNumber( @Explode( RawValue ; Separator ) ) ) ) ;" +
" @SetField( EditField[ef] ; @GetField(EditField[ef]) : @Explode( RawValue ; Separator ) ) )$"+
"Sort Ascending|@Sort(@GetField(EditField[ef]) ; [Ascending] )$"+
"Sort Descending|@Sort(@GetField(EditField[ef]); [Descending])" ; "$" );
DataTypes := @Word( DataTypesCombo ; "|" ; 1 );
DataTypesAction := @Word( DataTypesCombo ; "|" ; 2 );
REM {Get a listing of all the fields on the current document};
List := @Sort( @DocFields );
REM {Look for last field modified in Profile Doc};
FieldList := @Explode( @GetProfileField( cProfileName ; cEditLastField ; @UserName ) ; cArraySeparator ; @True ) ;
REM {Get the list of forms and field that was updated using Edit Document Fields};
FieldListForms := @Word( FieldList ; cEditLastSeparator ; 1 );
FieldListField := @Word( FieldList ; cEditLastSeparator ; 2 );
FieldListLastIndex := @Member( Form; FieldListForms );
REM {If the FieldListLastIndex is greater than zero then set the last field to the what was in the profile document};
@If( FieldListLastIndex > 0;
@Do( LastField := FieldListField[ FieldListLastIndex ];
FieldList := @ReplaceSubstring( FieldList ; FieldList[ FieldListLastIndex ] ; "" ) );
LastField :="" );
REM {Prompt for which field needs to be updated. Loop until a field is selected or 'Cancel' is selected};
@DoWhile(
EditField := @Prompt( [OkCancelEditCombo] ; cPromptTitle ; "Select the field you wish to alter or enter a new field to add:" ; LastField ; @Trim( @Unique( List : LastField ) ) );
EditField = "" );
EditFieldPromptTitle := "Change '" + EditField + "' in " + cPromptTitle;
REM {This will allow the retrieval of the data type of the field that was last selected. Data is stored like Form+Field%~%DataType.};
FormFieldList := @Explode( @GetProfileField( cProfileName ; cEditLastFieldDataType ; @UserName ) ; cArraySeparator ; @True ) ;
FormFieldListFormField := @Word( FormFieldList ; cEditLastSeparator ; 1 );
FormFieldListDataType := @Word( FormFieldList ; cEditLastSeparator ; 2 );
FormFieldListFormulaCode := @ReplaceSubstring( @Word( FormFieldList ; cEditLastSeparator ; 3 ) ; cSemicolonReplace ; ";" );
FormFieldListIndex := @Member( Form + EditField; FormFieldListFormField );
@If( FormFieldListIndex > 0;
@Do( DefaultDataType := FormFieldListDataType[ FormFieldListIndex ];
FormFieldListFormulaCode := FormFieldListFormulaCode[ FormFieldListIndex ];
FormFieldList := @ReplaceSubstring( FormFieldList ; FormFieldList[ FormFieldListIndex ] ; "" ) );
DefaultDataType :="" );
REM {If there was no data type used for the field on the form the try to determine the data type};
DefaultDataType :=
@If( DefaultDataType != "" ;
DefaultDataType ;
@If(
@IsNumber( @GetField( EditField ) ) ;
@If( @Count( @GetField( EditField ) ) > 1 ;
"Integer Multi Value" ;
"Integer" ) ;
@IsTime( @GetField( EditField ) ) ;
@If( @Count( @GetField( EditField ) ) > 1 ;
"Date Mult iValue" ;
"Date" ) ;
@If( @Count( @GetField( EditField ) ) > 1 ;
"Text Multi Value" ;
"Text" )
)
);
REM {If the data type is a type of error then select the data type of text};
DefaultDataType := @IfError( DefaultDataType ; "Text" );
REM {Prompt for which data type you would like the data to be. This needs to be done before value prompt to determine if the Picklist or any prompting needs to be used.};
DataType := @Prompt( [OkCancelList] ; EditFieldPromptTitle; "Please select the correct data type or action for field: " + EditField + "."; DefaultDataType ; DataTypes );
REM {The DataTypeAction will contain the formula that will be executed to retrieve the new value};
DataTypeAction := DataTypesAction[ @Member( DataType ; DataTypes ) ];
REM {If formula was used on this field then use that instead of the fields value. Format the original value as text because the @Prompt command requires text.};
OriginalValue := @If( DataType = "Formula" & DefaultDataType = "Formula" & FormFieldListFormulaCode != "" ;
FormFieldListFormulaCode ;
@If( @Contains( DefaultDataType ; MultiValue ) ;
@Implode( @Text( @GetField( EditField ) ) ; cArraySeparator );
@Text( @GetField( EditField ) ) )
);
REM {This will allow the retrieval of history of values of the field. Data is stored like Form+Field+DataType%~%ValueList.};
FormFieldListDataTypeValues := @Explode( @GetProfileField( cProfileName ; cEditLastFieldDataTypeValue ; @UserName ) ; cArraySeparator ; @True ) ;
FormFieldListFormFieldDataType := @Word( FormFieldListDataTypeValues ; cEditLastSeparator ; 1 ) ;
FormFieldListValuesLists := @Word( FormFieldListDataTypeValues ; cEditLastSeparator ; 2 ) ;
FormFieldListDTIndex := @Member( Form + EditField + DataType; FormFieldListFormFieldDataType );
@If( FormFieldListDTIndex > 0;
@Do( FormFieldListValuesList := FormFieldListDataTypeValues[ FormFieldListDTIndex ];
FormFieldListValuesList := @ReplaceSubstring( @Trim( @Explode( FormFieldListValuesLists[ FormFieldListDTIndex ] ; cValueListSeparator ; @False ) ) ; cSemicolonReplace; ";" );
FormFieldListDataTypeValues := @ReplaceSubstring( FormFieldListDataTypeValues ; FormFieldListDataTypeValues[ FormFieldListDTIndex ] ; "" ) );
FormFieldListValuesList :="" );
REM {Prompt for additional fields and determine the string that they are searching for.};
@If( DataType = ("Replace Substring":"Replace" ) ;
@Do( EditField := @Unique( EditField : @Prompt( [OkCancelListMult] ; cPromptTitle ; "Select any addtional fields you wish to alter:" ; EditField ; List ) );
FromRawValue := @Prompt( [OkCancelEditCombo] ; EditFieldPromptTitle ; "Enter or select the text (case sensitive) to search for in: " + @Implode( EditField ; ", " ) + "." ; "" ; @Unique( @Word( FormFieldListValuesList ; cFromRawValueSeparator ; 2 ) ) ) );
@Do( EditField := EditField;
FromRawValue := "" )
);
REM { With the Edit combo there will be a list of standard seperators to choose from.};
Separator := @If( DataType = ("Implode":"Explode" ) ;
@Prompt( [OkCancelEditCombo] ; cPromptTitle ; "Enter or select the " + @If( DataType = "Implode" ; "separator" ; "separators" ) + ":" ; "" ; @Unique( @If( FormFieldListValuesList = "" ; cStandardSeparators ; FormFieldListValuesList : cStandardSeparators ) ) );
cArraySeparator );
REM {Determine the string to search for};
ExtractValue := @If( DataType = cTextExtractList ;
@Prompt( [OkCancelEditCombo] ; cPromptTitle ; "Enter or select the search string or string length:" ; @Subset( FormFieldListValuesList ; 1 ) ; @Unique( FormFieldListValuesList ) );
"" );
REM {Based on what type of data is being entered different prompts will happen if any at all.};
RawValue := @If(
@Contains( DataType ; "Name Multi Value" ) ; @PickList( [Name] );
@Contains( DataType ; "Name" ) ; @PickList( [Name] : [Single] );
DataType = ( cNoPromptList ) ; "" ;
@Contains( DataType ; "Multi Value" ) ; @Prompt( [OkCancelEditCombo] ; EditFieldPromptTitle; "Enter or select the new desired value for: " + @Implode( EditField ; ", " ) + "." + cPromptNewLineTwo + "Seperated with ; for each value." ; OriginalValue ; @Unique( OriginalValue : FormFieldListValuesList ) ) ;
@Contains( DataType ; "+ Append Values" ) ; @Prompt( [OkCancelEditCombo] ; EditFieldPromptTitle; "Enter or select values to append: " + @Implode( EditField ; ", " ) + "." + cPromptNewLineTwo + "Seperated with ; for each value." ; "" ; @Unique( FormFieldListValuesList ) ) ;
DataType = ("Replace Substring":"Replace" ) ; @Prompt( [OkCancelEditCombo] ; EditFieldPromptTitle ; "Enter or select the text to repalce with in: " + EditField + "." ; "" ; @Unique( @Word( FormFieldListValuesList ; cFromRawValueSeparator ; 1 ) ) ) ;
DataType = "Formula" ; @Do( @DoWhile(
OriginalValue := @Prompt( [OkCancelEditCombo] ; EditFieldPromptTitle ; "Enter or select the new desired formula for: " + EditField + "." ; OriginalValue ; @Unique( OriginalValue : FormFieldListValuesList ) );
tempReturnCheck := @CheckFormulaSyntax( OriginalValue );
@If( tempReturnCheck != "1"; @Prompt( [Ok] ; "Invalid Formula - " + EditFieldPromptTitle ;
"Invalid Formula entered: " +
cPromptNewLineTwo + cPromptTab + "Error: " + cPromptTab + cPromptTab + @Text( tempReturnCheck ) +
cPromptNewLineOne + cPromptTab + "Formula: " + cPromptTab + cPromptTab + OriginalValue ) ; "" );
tempReturnCheck != "1" );
OriginalValue );
@Prompt( [OkCancelEditCombo] ; EditFieldPromptTitle ; "Enter or select the new desired value for: " + EditField + "." ; OriginalValue ; @Unique( OriginalValue : FormFieldListValuesList ) )
);
REM {Store Field in Profile doc};
@SetProfileField( cProfileName ; cEditLastField ; @Unique( @Trim( FieldList : ( Form + cEditLastSeparator + EditField[1] ) ) ); @UserName );
REM {Store Data Type of Field in Profile doc};
@SetProfileField( cProfileName ; cEditLastFieldDataType ;
@Unique( @Trim( FormFieldList : ( Form + EditField[1] + cEditLastSeparator + DataType + cEditLastSeparator +
@ReplaceSubstring(
@If( DataType = "Formula" ; RawValue ; FormFieldListFormulaCode ) ;
";" ; cSemicolonReplace ) ) ) ) ;
@UserName );
REM {Store Data Value of Field in Profile doc};
@SetProfileField( cProfileName ; cEditLastFieldDataTypeValue ;
@Unique( @Trim( FormFieldListDataTypeValues : ( Form + EditField[1] + DataType + cEditLastSeparator +
@Implode(
@Subset(
@Unique(
@ReplaceSubstring(
@If( DataType = ("Implode":"Explode" ) ; Separator ;
DataType = cTextExtractList ; ExtractValue ;
DataType = ( "Replace Substring":"Replace" ) ; RawValue + cFromRawValueSeparator + FromRawValue ;
RawValue ) : FormFieldListValuesList ;
";" ; cSemicolonReplace ) ) ;
cFieldHistoryValues );
cValueListSeparator ) ) ) ) ;
@UserName );REM {If multi docs selected, only process those checked ... an unchecked doc cannot be NavNextSelected};
@Command([NavNextSelected]);
@UpdateFormulaContext;
REM {Store all Note IDs before manipulation in case field modifications cause categorized views or sorted columns to reorganize};
NoteIDList := @Text( @NoteID );
ErrorNoteIDList := "";
@Command([NavNextSelected]);
@UpdateFormulaContext;
REM {Start Looping Selected documents to gather all the documents that need to be updated.};
@While( ( @Left( NoteIDList ; cNoteEntryLength ) != ( @Text( @NoteID + cArraySeparator ) ) ) & ( @Length( NoteIDList ) <> 1 ; "s" ; "" ) + "." + cPromptTab + cPromptTab +
cPromptNewLineTwo + cPromptTab + "Field:" + cPromptTab + cPromptTab + EditField +
cPromptNewLineOne + cPromptTab + "Data type/action: " + cPromptTab + DataType +
cPromptNewLineOne + cPromptTab +
@If( DataType = ("Implode":"Explode" ) ; "Separator: " + cPromptTab + Separator ;
DataType = ("Text Left":"Text Left Back":"Text Right":"Text Right Back" ) ; "Search string: " + cPromptTab + ExtractValue ;
DataType = ("Replace Substring":"Replace" ) ; "Search string: " + cPromptTab + FromRawValue + cPromptNewLineOne + cPromptTab + "Replace string: " + cPromptTab + RawValue ;
DataType = cNoPromptList;
"" ;
"Value: " + cPromptTab + cPromptTab + @Text( RawValue ) ) +
cPromptNewLineTwo + "Would you like to continue?" );
@If( cEnableConfirmation ;
@Do(
@StatusBar( @Explode( tmpPrompt ; cPromptNewLineOne ; @True ) );
@If( @Prompt( [YesNo]; EditFieldPromptTitle ;
tmpPrompt );
"" ; @Return ( "" ) ) );
"" );
REM {Loop through selected docs taking each NoteIDList out of the list as it is processed};
DocUpdateCount := 0;
DocNavigationCount := 0;
@While( DocUpdateCount < @Elements( NoteIDList ) ; @If( @TextToNumber( @Text( @DocumentUniqueID ) ) != 0 ; @Do( NoteIDList := @Replace( NoteIDList ; @NoteID ; "" ) ; NotNoteIDList := NotNoteIDList : @NoteID; @For( ef := 1; ef <= @Elements( EditField ); ef := ef + 1; formulaResult := @Eval( DataTypeAction ); remark := " **REM** The values entered above will be applied to all selected doc. If data conversion doesn't work then don't set field."; @If( @IsError( formulaResult ); @Do( tmpPrompt := "Error with NoteID of " + @NoteID + ". Continue?" + cPromptTab + cPromptNewLineOne + cPromptTab + "Error: " + cPromptTab + cPromptTab + @Text( FormulaResult ) + cPromptNewLineOne + cPromptTab + "Formula: " + cPromptTab + cPromptTab + DataTypeAction + cPromptNewLineOne + cPromptTab + @If( @Contains( DataTypeAction ; "EditField[ef]" ) ; "EditField[ef]:" ; "Field:" + cPromptTab ) + cPromptTab + EditField[ef] + cPromptNewLineOne + cPromptTab + "Data type/action: " + cPromptTab + DataType + cPromptNewLineOne + cPromptTab + @If( DataType = ("Replace Substring":"Replace" ) ; "FromRawValue: " + cPromptTab + @Text( FromRawValue )+ cPromptNewLineOne + cPromptTab + "RawValue: " + cPromptTab + @Text( RawValue ) ; DataType = cNoPromptList; "" ; "RawValue: " + cPromptTab + @Text( RawValue ) ); @StatusBar( @Explode( tmpPrompt ; cPromptNewLineOne ; @True ) ); @If( @Prompt( [YesNo] ;"Error - " + EditFieldPromptTitle ; tmpPrompt ) ; ErrorNoteIDList := ErrorNoteIDList+ cArraySeparator + @Text( @NoteID ); @Return( @If( @Eval( cErrorCheckCode ) != "" ; @StatusBar( @Explode( @Eval( cErrorInformation ) ; cPromptNewLineOne ; @True ) ): @Prompt( [Ok] ; "Unable to Update - " + EditFieldPromptTitle ; @Eval( cErrorInformation ) ); "" ) ) ) ); @SetField( EditField[ef] ; formulaResult ) ) ); @If( DocNavigationCount > cMaxUpdatedDocuments ;
NoteIDList := "";
@Do(
DocUpdateCount := DocUpdateCount + 1;
@Command([NavNextSelected]);
@UpdateFormulaContext;
remark := " **REM** If we haven't processed all docs yet but the current doc is not in the NoteIDList list, keep looping ... if cnt exceeds MaxUpdatedDocuments assume infinite loop and stop ";
@If( DocUpdateCount < @Elements( NoteIDList ) & ( !@Member( @NoteID ; NoteIDList ) ) & ( !@Member( @NoteID ; NotNoteIDList) ); @While( (! @Member( @NoteID ; NoteIDList ) & DocNavigationCount <> 1; "s " ; " " ) + "on " + @Text( DocUpdateCount ) + " document" + @If( DocUpdateCount > 1 ; "s" ; "" ) + "." )
2007-05-05
Notes: How to update rich text in a document that's open and redisplay it without saving
«The code sample below shows how to write LotusScript code that makes changes to a rich text field in a document that the user is editing, and displays those changes immediately on-screen, without saving the changes. This also works if you need to repeat other operations that only occur when a document is opened, e.g. evaluating section editor formulas and computed subform formulas.
Here's the code, which should work in Notes 5.0.2 and higher:
Dim wksp As New NotesUIWorkspace
Dim session As New NotesSession
Dim uidoc As NotesUIDocument, uidocNew As NotesUIDocument
Dim doc As NotesDocument
Dim rti As NotesRichTextItem
Dim strFieldname As String
Set uidoc = wksp.CurrentDocument
uidoc.Refresh True ' do this if the rich text field is editable, to get the current contents in case user has modified them.
Set doc = uidoc.Document ' get the back-end document for the document open on screen.
strFieldname = uidoc.CurrentField ' remember the current field if any
Set rti = doc.GetFirstItem("fieldname") ' insert your fieldname here, generally "Body"
' Make your rich text changes here, for instance:
Call rti.AddNewLine(1, True)
Call rti.AppendText(Now & ": log entry.")
If session.NotesBuildVersion >= 190 Then
rti.Update ' ND6 only
Else
Call doc.ComputeWithForm(True, False) ' caution, as this may erase some field values if you have @Db functions in formulas.
End If
doc.SaveOptions = "0" ' make it possible to close the document without a "do you want to save" prompt. If this is a mail-in doc you may need to set MailOptions="0" also to avoid being prompted.
Call uidoc.Close(True)
Set uidocNew = wksp.EditDocument(True, doc, , , , True)
Delete uidoc
uidocNew.Document.RemoveItem("SaveOptions")
If strFieldname <> "" Then uidocNew.GotoField(strFieldname) ' return focus to field that was current before.
Note: this will cause Queryclose, Queryopen, Postopen (and so on) form events to trigger. Also, uidoc.Refresh will execute computed field formulas and input validations, so you should write the validation formulas to not return @Failure unless @IsDocBeingSaved | @IsDocBeingSent is true.»
in Notes/Domino 6 and 7 Forum
Notes: Design Synopsis in HTML format
«(...) But also, the Design Synopsis has never worked very well for large
designs ("Too many paragraphs") or for large blocks of LotusScript , whose code
does not appear in full. The most important limitation of the Design Synopsis,
though, in my estimation, is that the output is not customizable. (...) The
menu item Tools / DXL Utilities / Transformer... (...) it'll put up a
dialog very similar to the Design Synopsis dialog, with one important
difference: the opportunity to select an XML stylesheet (.xsl file) to transform
the DXL descriptions of the selected design elements into human-readable form as
an HTML file. »
in Best Practice Makes Perfect
2006-06-23
Windows (XP): Remove or delete a service
sc delete "<service name>"
2006-06-06
Notes: How to access .Net classes from LotusScript
Problem
You have created an object using Microsoft .Net and would like to create and use this object within LotusScript. How can this be done?
Solution
To create a .Net DLL that is accessible from LotusScript perform the following steps:
1. Create a C# Class Library Project with the following code:
using System;
public class MyTest
{
public string AppendStr(string s)
{
return s + " from inside the DLL";
}
}
Note: A Visual Basic Class Library could also be created.
2. To access this DLL from anywhere on the machine you will also need to create this DLL as a shared assembly and publish the your DLL to the Global Assembly Cache (GAC). Otherwise, the DLL will be created as a private assembly and you will only be able to create the object if the DLL is in the same directory as the calling program.
To create this DLL as a shared assembly you will need to generate a cryptographically strong name for the assembly. To do this start up the Visual Studio Command Line prompt, and enter the following command:
sn -k c:\MyTest.snk
This will create an Assembly Key File name at the location c:\MyTest.snk
3. Open the AssemblyInfo.cs file of the project include the following line:
[assembly: AssemblyKeyFile(@"c:\\MyTest.snk")]
Note: For Visual Basic you will need to include this tag instead: <assembly: AssemblyKeyFile(@"c:\\MyTest.snk")>
4. Build the project. This will build the project with the value of the Assembly Key File and allow it to be published as a Shared Assembly to the Global Assembly Cache.
5. Using the Visual Studio Command Line, change to the directory where the DLL was generated, then publish the DLL to the Global Assembly Cache using the following command:
GacUtil /i MyTest.dll
6. To make the objects in this DLL accessible via the COM interface, enter the following command:
regasm MyTest.dll
7. To access the object contained in this DLL using LotusScript use the following code:
Dim obj As Variant
set obj = CreateObject("MyTest")
MsgBox obj.AppendStr("This is")
The message box will display "This is from inside the DLL."
In short, once the shared assembly is published as a COM component, it can be instantiated in LotusScript using the CreateObject() function. With the exception of Step 7, all of the steps are all specific to the deployment process of Microsoft .Net components. For further information regarding any of these utilities you should refer to the Microsoft web site or Microsoft support.
2006-05-10
Domino: Session Authentication via Lotus Script
Print "<HTML>"
Print "<BODY TEXT=""FFFFFF"" BGCOLOR=""FFFFFF"" onLoad=""document.forms[0].submit()"">"
Print "<FORM METHOD=post ACTION=""/names.nsf?Login"" NAME=""_AlfaLogin"">"
Print "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0//EN"">"
Print "<HTML>"
Print "<INPUT NAME=""Username"" VALUE=""" + sUsername + """ TYPE=hidden maxlength=256>"
Print "<INPUT NAME=""Password"" VALUE=""" + sPassword + """ TYPE=hidden maxlength=500>"
Print "<INPUT NAME=""RedirectTo"" VALUE=" + sRedirectTo + " type=hidden>"
Print "</HTML>"
Print "</FORM>"
Print "</BODY>"
Print "</HTML>"
2006-03-27
Domino: Extend Authentication For Websites, Single Sign-on and Persistent Sessions
Ever wanted to be able to authenticate users on your Domino Web Server using a Web Service, against a MySQL database, a text file or some other external source? Or how about changing the default Domino behaviour so that user sessions remain active for days or weeks. It's easy and I'll show you how using Apache Tomcat and a simple Java Servlet.
More >
2006-01-12
Notes - LotusScript: function returning a notes document
You can either pass the database *and* the document and pass them both back, or you can declare the database globally .
2005-12-30
Notes - Web: Alignment of Checkboxes on the Web
Don't forget to mark this code as Pass-Thru HTML.
And now, on the checkbox field choices, this should be added to the end of the choice where the list should break to a new column:
</td><td valign="top">
Example of list:
-------------
apple | a
orange | or
strawberry [</td><td valign="top">] | s
pineapple | p
banana | b
other [</td><td valign="top">] | o
-----------------------
2005-12-29
Notes - Web: select all javascript function for checkboxes (multivalue too)
function selectAll(fieldname, bFlag) {
var checkField = document.forms[0].elements[fieldname];
if (checkField.length)
{
for (i=0; i<checkField.length; i++)
{
if (checkField[i].checked)
{
checkField[i].checked = bFlag;
}
}
}
else if (checkField.checked)
{
checkField.checked = bFlag;
}
}
2005-12-14
Notes - client: hide-when for layers
2005-12-06
Notes - Client: View autoframe
. Create a Frameset with only one Frame and call this Frame NotesView and select any view;
. In the database default Frameset, open the previously created Frameset in one of it's frames.
Now, when opening a view (through a link, for example), the database will force the default frameset to open "around" the view.
