Create multi-line input - vba

We have a custom macro set up in our (health service) CRM which lets us send ad hoc text messages to clients.
It opens as a one line input box, with options for 'OK' and 'Cancel'.
We often send long-ish messages and it's painful not being able to see what you have written all at once.
I've found the code that includes the title of the input box and the prompt next to the field where you type:
set msgEntryDlg = CreateDialog("Adhoc SMS")
set msgTxtCtl = msgEntryDlg.AddControl("SMS Message: ",2, "")
Is there something I can add to this to force it to show a bigger/multi-line input box?

Related

Find Message Number of Popup Dialog Text

I don't find the answer on the internet.
When I open some orders in a transaction, I have sometimes a popup. I want to execute some code if this popup text is 'Consider the subsequent documents'. If it is another text, I will execute some other code.
Problem is, we use SAP in several languages (EN, DE, FR), so I can't just say "if text = 'Consider the subsequent documents'. I know each message has its own ID in SAP. I know how to find this ID manually (see screenshot below), but I can't access it with findById(), even using the Record and Playback tool, because it uses the Performance Assistant window, which is not a children of the SAP session (it's a separate application, see second screenshot).
How could I do?
If session.ActiveWindow.Name = "wnd[1]" Then 'There is a popup
'Find message number (haven't find better way)
session.findById("wnd[1]/tbar[0]/btn[1]").press 'Press "Info"
'Line missing here to click the button in Performance Assistant Window. Record & Playback tool does not catch it.
If session.findById("wnd[2]/usr/txtHELP_INFO-MESSAGENR").Text = "081" Then
'Some code
End If
'close popups
session.findById("wnd[2]").sendVKey 0
session.findById("wnd[1]").sendVKey 0
End If
I found out that it is possible to display the Help in a Modal window (=Popup) rather than in a separate window Performance Assistant. Then it is possible with findById() functions to get the message number Popup raises > F1 > F9 > findByID(...).Text
To set the Help in a Modal window, the user must first (manually or programmatically) check a setting:

Dirty on command?

I have an Access 2010 application that has a form with a text box and a command button on it. Clicking the command button places a default value in the text box.
Question: When a user clicks the command button I can either:
Run an SQL update to save the new text box value in the data source that it is bound to plus set the me.textbox1.value to its new value, or
Run the same SQL update to save the new text box value in the data source that it is bound to plus do a form.requery?
Which is better? Would changing the bound value in the data source initiate a current event and an automatic requery?
Thanks in advance.
If you want to save the entry immediately, I would write the value to the text box, and do
Me.Dirty = False
to save the record in the bound form.
I see no point in doing this via SQL.
Would changing the bound value in the data source initiate a current event and an automatic requery?
No, that would actually be the worst method. The form wouldn't know about the changed data source, and once the user would start editing, he would get the "Write Conflict" message.
Your 1. would have the same problem.

Send HTML Mail from Cocoa with Mail.app

I'm trying to send html email from Cocoa app, through Mail.app. I want to open new message in Mail.app, include subject, recipient and add HTML Body with links and other content. But can't find the way to do this.
I already tried Scripting Bridge, but MailOutgoingMessage class doesn't have content type i can add content in plaintext.
tried AppleScript, something like this:
set htmlContent to read "/Path/index.html"
set recipientList to {"mail#mail.com"}
tell application "Mail"
set newMessage to make new outgoing message with properties {subject:"qwerty", visible:true}
tell newMessage
make new to recipient at end of to recipients with properties {address:"mail#s.com"}
set html content to htmlContent
--send
end tell
end tell
this code send email with html, only if I'm changing --send to send. But i need to send letter later, after user made some changes.
To recap the problem: Using AppleScript to create a message with HTML content for interactive editing does not work (as of OS X 10.9.2): the new-message form comes up with an empty body.
This should be considered a bug and I encourage everyone to let Apple know at http://bugreport.apple.com - caveat: the html content message class property is not defined in Mail.sdef, Mail.app's AppleScript dictionary, so assigning HTML may not be officially supported.
There is a workaround, but it ain't pretty:
Create the message invisibly.
Save it as a draft.
Open the draft message, at which point the HTML content will appear.
Implementing this robustly is challenging, because several workarounds are required. The following code tries its hardest, though:
Note: Since the code uses GUI scripting, Access for Assistive Devices must be enabled (via System Preferences > Security & Privacy > Accessibility) for the application running this code (e.g., AppleScript Editor or, if run via osascript, Terminal.app).
# Example values; use `read someFile` to read HTML from a file.
set htmlContent to "<html><body><h1>Hello,</h1><p>world.</p></body></html>"
set recipientList to {"person1#example.com", "person2#example.com"}
set msgSubject to "qwerty"
tell application "Mail"
# Create the message *invisibly*, and assign subject text
# as well as the HTML content.
set newMessage to make new outgoing message with properties ¬
{visible:false, subject:msgSubject, html content:htmlContent}
# Add recipients.
# !! Given the workaround below, this is currently pointless.
tell newMessage
repeat with toRcpt in recipientList
make new to recipient at end of to recipients with properties {address:toRcpt}
end repeat
end tell
# Save the current number of drafts messages.
set draftCountBefore to count messages of drafts mailbox
# !! Save the new message as a *draft* - this is necessary
# for the HTML content to actually appear in the message
# body when we open the message interactively later.
save newMessage
# !! Sadly, it takes a little while for the new message
# !! to appear in the drafts mailbox, so we must WAIT.
set newMessageAsDraft to missing value
repeat with i from 1 to 30 # give up after n * 0.1 secs.
set draftCountNow to (count messages of drafts mailbox)
if draftCountNow > draftCountBefore then
set newMessageAsDraft to message 1 of drafts mailbox
exit repeat
end if
delay 0.1 # sleep a little
end repeat
# Abort, if the draft never appeared.
if newMessageAsDraft is missing value then error "New message failed to appear in the drafts mailbox within the timeout period."
# Open the new message as a *draft* message - this ensures that
# the HTML content is displayed and editable in the message body.
# !! The ONLY solution I found is to use `redirect`, which, unfortunately,
# !! *wipes out the recipients*.
# !! It does, however, ensure that the draft is deleted once the message is sent.
redirect newMessageAsDraft with opening window
# Activate Mail.app and thus the draft message's window.
activate
# !! Since the recipients have been wiped out, we need to
# !! add them again - unfortunately, the only way we can do that is to
# !! *GUI scripting* - simulating invocation of a menu command or
# !! sending keystrokes.
tell application "System Events"
# We must make sure that the target window is active before
# we can perform GUI scripting on it.
set newMessageWindow to missing value
repeat with i from 1 to 30 # give up after n * 0.1 secs.
tell (first window of (first process whose frontmost is true) whose subrole is not "AXFloatingWindow")
if name is msgSubject then
set newMessageWindow to it
exit repeat
end if
end tell
delay 0.1 # sleep a little
end repeat
if newMessageWindow is missing value then error "New message failed to become the active window within the timeout period."
# Turn the list of recipients into comma-delimited *string* for pasting into the To field.
set {orgTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {","}}
set recipientListString to (recipientList as text)
set AppleScript's text item delimiters to orgTIDs
# Save the current clipboard content.
set prevClipboardContents to the clipboard
# Cursor is in the "To:" field, so use GUI scripting to send the Edit > Paste command now.
# NOTE: Access for assistive devices must be enabled via System Preferences > Security & Privacy > Accessibility.
set the clipboard to recipientListString
my pasteFromClipboard("")
# Restore the previous clipboard content.
# !! We mustn't do this instantly, as our temporary content may not have
# !! finished pasting yet. It would be non-trivial to determine
# !! when pasting has finished (examining `count of to recipients` doesn't work),
# !! so we take our chances with a fixed, small delay.
delay 0.1
set the clipboard to prevClipboardContents
# Place the cursor in the message *body*.
# !! This works as of Mail.app on OS X 10.9.2, but may break in the future.
try
tell newMessageWindow
tell UI element 1 of scroll area 1
set value of attribute "AXFocused" to true
end tell
end tell
end try
end tell
end tell
(*
Pastes form the clipboard into the active window of the specified application (process) using GUI scripting
rather than keyboard shortcuts so as to avoid conflicts with keyboard shortcuts used to invoke this handler.
Specify "" or `missing value` to paste into the currently active (frontmost) application.
The target process may be specified by either name or as a process object.
CAVEAT: While this subroutine IS portable across *UI languages*, it does make an assumption that will hopefully hold for
all applications: that the "Edit" menu is the *4th* menu from the left (Apple menu, app menu, File, Edit).
Examples:
my pasteFromClipboard("") # paste into frontmost app
my pasteFromClipboard("TextEdit")
*)
on pasteFromClipboard(targetProcess)
tell application "System Events"
if targetProcess is missing value or targetProcess = "" then
set targetProcess to first process whose frontmost is true
else
if class of targetProcess is text then
set targetProcess to process targetProcess
end if
-- Activate the application (make it frontmost), otherwise pasting will not work.
set frontmost of targetProcess to true
end if
tell menu 1 of menu bar item 4 of menu bar 1 of targetProcess
-- Find the menu item whose keyboard shortcut is Cmd-V
set miPaste to first menu item whose value of attribute "AXMenuItemCmdChar" is "V" and value of attribute "AXMenuItemCmdModifiers" is 0
click miPaste
end tell
end tell
end pasteFromClipboard
It isn't clear what your are looking for, but I'll do my best to offer some help.
If you leave send commented, then the message should already be open in Mail.app, waiting for further editing and sending.
By adding the line save newMessage, it will be saved to the drafts folder. The user can open it and continue editing whenever they please. If you want to actually send the draft from your application, use:
set sendMessage to first message of drafts mailbox
send sendMessage
Good luck!
I didn't see that you needed to edit the message before sending, so my previous answer was wrong. This time it should be correct.
It basically
takes a preformatted RTF file,
renders it & puts it into the clipboard,
creates a new message,
fills in the fields,
moves the focus to the message body,
pastes the formatted clipboard
Here is the code:
set textSubject to "HTML Test"
set toAddress to "john.doe#gmail.com"
set toName to "John Doe"
tell application "Mail"
do shell script "cat ~/Documents/RTF\\ File.rtf | textutil -stdin -stdout -convert rtf | pbcopy"
set refMessage to make new outgoing message with properties {name:toName, address:toAddress, subject:textSubject, visible:true}
tell refMessage
make new to recipient at end of to recipients with properties {name:toName, address:toAddress}
end tell
end tell
tell application "System Events"
tell application process "Mail"
set frontmost to true
set value of attribute "AXFocused" of scroll area 4 of window textSubject to true
end tell
keystroke "v" using {command down}
end tell
Again, this worked fine on Snow Leopard
Hope that helped.

How to change the Contents of a msg box

I have a form for creating a record, I also have a button on the top of the form for to return to a form called home. When the form is being viewed and half the information is put in and the home button is clicked an error pops up saying " you cannot add or change a record beacasue a related record is required in a table "Elements"." How do I Change what the content of the error message is ?
You can put checks in your button_click sub to circumvent -- check to make sure all fields are filled in, and if not, display your own message box followed by
Exit Sub
That will short circuit the rest of the method so you should not get the standard message.
Here is a resource on error-handling in VBA: http://allenbrowne.com/ser-23a.html
I'm not sure, however, if you can create a handler in VBA for standard program error messages.

Validating Attachment in Richtext field

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).