Validating Attachment in Richtext field - lotus-domino

I am using below code to validate the Attachment in Richtext field.
If I will not used Call source.Refresh(True)
then validation is not working, but this code is also refreshing document everytime querysave is called in buttons.
So is there any option or any other idea so that I should not user this Refresh part or entire code to validate .
If anybody have more efficient code then please share this.
If Source.Document.YesNo20(0)="Yes" Then
Call source.Refresh(True)
Dim rtitem As NotesRichTextItem
Set rtitem = source.Document.GetFirstItem( "Atchmnt20" )
NotesEmbeddedObjectArray = rtitem.EmbeddedObjects
If Isempty ( NotesEmbeddedObjectArray ) Then
Messagebox "Please enter an attachment in 20a. As you selected option Yes"
continue=False
Exit Sub
End If
End If

There's a way in LotusScript to check attachments presence even for new (not saved) documents.
Create a hidden computed field, for instance AttachmentNames with formula:
#If(#AttachmentNames!=""; "1"; "");
In LotusScript do the following:
'in new documents Form field may be empty
If doc.Form(0) = "" then
doc.Form = "YourFormAlias"
End If
'computing doc contents with the form
call doc.ComputeWithForm(false, false)
If doc.AttachmentNames(0) = "" then
MsgBox "Please attach a file",,"Attention"
Continue = False 'if you are running this code in QuerySave
Exit Sub
End If

Validating rich text fields in Lotus Notes is a bit of a dark art, but can you not just do this? (where doc is the back-end):
If(doc.HasEmbedded) Then Continue = True
There are other things you can do. Check this Lotus Developer Domain post, which covers attachments, text, embedded objects, all sorts:
http://www-10.lotus.com/ldd/nd6forum.nsf/0/8b3df10667d355768525719a00549058

Can you validate RT field with formula?
I created a hidden field below my rich text field with this Input Validation formula:
REM {Validate just when saving};
#If(!#IsDocBeingSaved; #Return(#Success); "");
REM {Should contain some file};
_filenames := #AttachmentNames;
#If(
#Elements(_filenames)=0;
#Return(#Failure("You should attach at least one file"));
#Success);

Assuming that you want to avoid the Refresh because it takes too long, here is what you may want to look at and if feasible, try to change:
Maybe you can use the "Entering" event of the RichText field in conjunction with a global variable (in the form) to skip the Refresh in your code, if the RichText field wasn't touched at all.
Are there keyword fields with "Refresh choices on document refresh" option enabled that may be safe to disable? Or even place a button that would bring up a dialog and populate the field with the selected keyword(s) - refreshing the choices won't be neccessary then, as you can always present up-to-date choices through #DbColumn/#DbLookup or NotesUIWorkspace.PickListStrings.
Is there any code (LotusScript or Formula) in "Queryrecalc" and/or "Postrecalc" form events that may be possible to optimize? For example by using a global variable (in the form) as a flag whether to execute the code in Queryrecalc/Postrecalc - set it to false just before calling Refresh in your code, then set it back to true (because this Refresh only serves to update the RichText field to the backend document).

Related

Button to check for missing values in a MainForm and Subforms in MS Access

New to Access (still), have only basic VBA skills.
I've got 3 subforms (subfrm_PackingSteps1 , subfrm_MetalDetection and subfrm_Weights - the first 2 are continuous and the other one is single form) within a main form (frm_daily_packing_record) that users go through and input data. The user should be able to input data in no particular order, and only at the end there would be a button to confirm that the user is ready to save this form.
I'd like to have this button on the main form that checks each control (in main form and subforms) for empty values. I found and adjusted a code to check the recordset of one of the continuous forms (see below), but I can't figure out:
how to include a code that checks each control instead of manually adding all of them (I've used a function before that utilises the Tag property, but can't add it to this)
how to keep the button in the main form while checking the controls/recordsets in the other subforms.
Thanks in advance.
Private Sub ConfirmBtn_Click()
Dim blnSuccess As Boolean
blnSuccess = True
Me.Recordset.MoveFirst
Do While Not Me.Recordset.EOF
If IsNull(Me.pc) Or IsNull(Me.InnerP) Then
blnSuccess = False
Exit Do
End If
Me.Recordset.MoveNext
Loop
If blnSuccess = True Then
MsgBox "You may proceed to save this record"
Else
MsgBox "You still have some empty fields to fill in!", vbCritical + vbOKOnly, "Empty Fields!"
End If
End Sub
I personally don't like this because it is too code-heavy and can easily break when the form is modified.
Instead may I suggest doing it slightly different, for each field have vba code .ondirty or .onupdate and do the validation checking right as the user is actually on that field.
This has 2 benefits, it is creating the validation when you are creating each form field and it STOPS the user right when their first mistake or bad data is entered. The last thing I want is to enter 50 fields, scroll to the bottom, submit fails then scroll back and try to find where the mistake was. If validation is done while the user it doing the actual data entry, when you get to the bottom you should have valid data and the submit should succeed without further testing.
Less code to debug and timely messages to the user if an error is caught!

Word VBA SelectContentControlsByTag collection out of order?

I'm working on a Word template form using ContentControl fields for drop down lists. I made a macro to take each content control tagged "required" and check if it's showing placeholder text. If it is, it throws up a message box asking the user to fill in the required fields, and IDEALLY jumps to the bookmark for that content control box.
After a lot of iteration and troubleshooting, it can in fact do that, but I've noticed that the Collection of required fields is in..... a random order. I tested this by adding another content control dropdown named "jimmy" at the bottom of the Word document and then looked in the collection and saw it was in the middle of all the other required fields.
Does anyone know how the "SelectContentControlsByTag" method decides on its order, and if there's a robust way to make it use the order that they're placed in the document? I have a decent amount of coding experience but I'm entirely self-taught as far as VBA goes, so I'd appreciate the help!
Here is my current code (Doc is set in Document_New, and the bookmark jump isn't in currently, I'm just checking the order in VBA/the message box)
Set reqFields = Doc.SelectContentControlsByTag("required")
For Each iField In reqFields
If iField.ShowingPlaceholderText Then
Dim Msg, Style, Title, Response
Msg = "The dropdowns marked with * cannot be left blank. Do you want to select a response before exiting? Box: " & iField.Title ' Define message.
Style = vbYesNo + vbCritical + vbDefaultButton1 ' Define buttons.
Title = "Warning: Empty fields" ' Define title.
' Display message.
Response = MsgBox(Msg, Style, Title)
If Response = vbYes Then
Doc.Saved = False: SendKeys "{ESC}"
'iField.Range.Select
Exit Sub
End If
'Exit For
End If
'Exit Sub
Next iField
Sorry for being 10 months late in answering!
When you use .selectcontentcontrolsbytag VBA will loop through the existing content controls by .ID to pull out the tag name. So if you want your ("tag").item(1) to be ordered you first need to put your content controls in ascending order by .ID number.

How to use UserForm CheckBox to change Control Content CheckBox in Word Document?

I created an UserForm with a checkbox 'cbxYes' and a Content Control checkbox 'docCbx' in the Word document. I want to be to check off the checkbox 'cbxYes' in UserForm that then changes the Content Control checkbox in the Word document.
So the input is from the UserForm checkbox and the output is the Content Control checkbox.
I have tried multiple searches on how to do this, but I could not find exactly what I needed. Most of the searches were related to Excel. And honestly, I don't know what I'm doing. Please. The correct help is greatly appreciated.
Private Sub cbxYes_Click()
Dim oCC As ContentControl
If cbxYes.value = True Then
cbxYes.value = "True"
ActiveDocument.docCbx_Yes.value = True
Else
cbxYes.value = "False"
ActiveDocument.docCbx_Yes.value = False
End If
End Sub
The error I got was:
run-time error '438': Object doesn't support this property or method.
The code shown in the question would be for ActiveX checkboxes, rather than content controls. (Just to make things really complicated, Word also has checkbox form fields that need yet another code syntax.)
There's no way to refer directly to a content control name via the Document object - it must be done over the ContentControls collection. Content controls can be assigned a Title and/or a Tag in the Properties dialog box.
More than one content control can have the same name or title, which makes the code a bit complicated. Querying Document.ContentControls("Title") returns a collection (all the content controls with that title).
If you know which one, then it's possible to pick it up directly (rather than working through a collection) using the Item method, specifying that it's the n content control (the index in the order of content controls). This is usually used when one knows there's only the one.
Note, please, also, that in order to "check" or "uncheck" a content control checkbox the Checked property should be use. So:
Private Sub cbxYes_Click()
Dim oCC As ContentControl
Set oCC = ActiveDocument.SelectContentControlsByTitle("docCbx").Item(1)
If cbxYes.value = True Then
'cbxYes.value = "True" not needed
occ.Checked = True
Else
'cbxYes.value = "False" not needed
oCC.Checked = False
End If
End Sub
Assuming that "docCbx" is the title of the content control you can replace
ActiveDocument.docCbx_Yes.value = True
by
For Each oCC In ActiveDocument.SelectContentControlsByTitle("docCbx")
If (oCC.Type = wdContentControlCheckBox) Then
oCC.Checked = False
End If
Next
and the equivalent, but using False, for the other branch of your code. The above code will update all checkbox type content controls with that name (the names do not have to be unique within a document), except controls that have been marked as "Contents cannot be edited" - they will remain unchanged. It deals with the situation where there aren't any content controls with that name by doing nothing.
If "docCbx" is the value of the Tag, you would need the following instead:
For Each oCC In ActiveDocument.SelectContentControlsByTag("docCbx")
If (oCC.Type = wdContentControlCheckBox) Then
oCC.Checked = False
End If
Next
If docCbx is something else, I would suggest that instead you give Titles and/or Tags to your content controls and use the above approach. Otherwise, you should modify your question to state precisely how you are naming the control "docCbx".
You get the error because adding content controls to a document does not create new members of the document object, whereas adding a form control to a user form does create new members of the Form object. (Documents do in fact have a mechanism that works more like the Form object but it has been deprecated for a long time.)

MS Word ActiveX Textbox Spell Check

I am working on a MS Word form for a client where they want the ability to count the number of words, check spelling, have a character limit, and have the rest of the form locked down so that the end user cannot change anything they are not supposed to. I have attempted to convince them that word count and character limit are redundant if we have proper instructions, however, this is what they want. They also want the form to be able to "work" even if the user does not enable macros, meaning, they want it locked and a character limit first and foremost.
I know that if we just rich text content controls and put the form into a group spell check and word count word while also "locking" the remainder of the form, except user content controls do not allow for character limits and using legacy/activex controls in a grouped form locks those controls as well.
So, for now, I have settled on using the ActiveX Textbox (this is negotiable if I have a reason to use the legacy textbox) and have achieved the minimum "workability" (if that's even a word). The only way I have figured out to check the spelling is below:
Sub chkSpelling()
Activedocument.Tables(1).Rows(26).Cells(1).Range.Text = txtRole.Text
Activedocument.Tables(1).Rows(26).Cells(1).Range.checkSpelling
txtRole.Text = Activedocument.Tables(1).Rows(26).Cells(1).Range.Text
'... so on and so forth throughout each text box
End Sub
The issue is that this is not good enough for my standards. Printing the text of each textbox (up to 1700 characters) at the bottom of the screen each time I need to check the Spelling is unacceptable. Does anyone else have any ideas?
Thank you for your assistance.
Answer with help from #bibadia
Dim doc As Document
Set doc = Documents.Add(, , wdNewBlankDocument, False)
doc.Paragraphs(1).Range.Text = txtRole.Text
doc.Paragraphs(1).Range.CheckSpelling
txtRole.Text = Replace(doc.Paragraphs(1).Range.Text, Chr(13), "")
Use CreateObject to create a new word instance
Ensure .Visible = False (I think that is the default)
Create a new document in that instance.
Copy the text to be checked into that
Spell check.
Remove the document and the Word instance.
If I understand your question correctly then,
I need to check the Spelling is unacceptable. Does anyone else have any ideas?
If text boxes are named with numbers, you might be able to use loop, and save your coding lines with time.
want the form to be able to "work" even if the user does not enable macros
If user did not enable macros, he would not be able to see form (is it User Form, you want to say) and no background macro code would run. (Tested on Ms-Excel 2007), ultimately failing all.
regarding text box control on user form
yes that can be set to character limit from properties menu, and spell check can be done using your method.
Set range2 = Documents("MyDocument.doc").Sections(2).Range
range2.CheckSpelling IgnoreUpperCase:=False, _
CustomDictionary:="MyWork.Dic", _
CustomDictionary2:="MyTechnical.Dic"

Never ending loop while setting focus to control on validating event in cantrol validating event

I am writing below code for validating compulsary field account no. in form.
User's requirement is set focus back on field when error comes :
If txtAccountNo = "" Then
MessageBox.Show("Account no filed can't be left empty")
txtAccountNo.SetFocus
Exit Sub
End If
It's working properlly. But suppose user don't want to fill form and exiting from aaplication.
Message box keep on appearing till user enters account no.
How can I avoid this situation?
Please help.
Set a flag to indicate user has seen messagebox. Check the flag to prevent any future messagebox. Make sure the flag is set before setting focus back to textbox e.g.
dim bMsgBox as boolean=false
If txtAccountNo = "" and bMsgBox = false Then
MessageBox.Show("Account no filed can't be left empty")
bMsgBox=true
txtAccountNo.SetFocus
Exit Sub
End If
You could put all the validation rules in one function / procedure / subrutine (I'm not familiar with VB, mostly C++ / C# user). Then call this function only when user is committing the data filled in, and set focus to first control with mandatory data not filled or invalid data entered.
Say you have a form with 3 controls to be filled in:
a date control not mandatory - dteDate
a text box mandatory - txtAccoutInfo
a text box mandatory - txtAddress
and 2 buttons:
button Save and button Cancel.
When 'Save' button is pressed you first call the function / procedure to validate user input. If date entered is invalid in dteDate, you set focus on it and return / exit the function; if no text is entered in txtAccountInfo then set focus on it and return / exit the function; if no text is entered in txtAddress then set focus on it and return / exit.
When 'Cancel' is pressed you don't call this function, but just quit.