Link to home
Create AccountLog in
Avatar of tommyfs
tommyfs

asked on

Need VB6 program code for an attachment to expose its email subject line.

I've written a VB6 program that will process a Word document named, for example, xxxx.doc. The program also contains the ability to open Lotus Notes on the user's PC. The executable program is sent automatically as an attachment to the user; the subject of the email contains the Word documents filename, the "xxxx". I need a code statement that will expose the subject line of the email having this program as the attachment.

Within the NotesDocumentCollection Class, we have GetFirstDocument, GetLastDocument, GetNextDocument, GetNthDocument, and GetPrevDocument. What I need is "GetTHISDocument", which appears not to exist. If it did, I could grab the subject filename ("xxxx"), upon which the VB6 program would execute. I can't use GetLastDocument, since the user is not always going to open the subject email the instant it arrives, therefore putting the email somewhat "down the line".

My Notes-related code follows:

Public Sub Main()
    Dim Maildb As Object 'The mail database
    Dim UserName As String 'The current users notes name
    Dim MailDbName As String 'THe current users notes mail database name
    Dim MailDoc As Object 'The mail document itself
    Dim Session As Object 'The notes session
    'Dim collection As NotesDocumentCollection
    Dim collection
    'Dim item As NotesItem
    Dim item
   
    'Start a session to notes
    Set Session = CreateObject("Notes.NotesSession")
    'Get the sessions username and then calculate the mail file name
    UserName = Session.UserName
    MailDbName = Left$(UserName, 1) & Right$(UserName, (Len(UserName) - InStr(1, UserName, " "))) & ".nsf"
    'Open the mail database in notes
    Set Maildb = Session.GetDatabase("", MailDbName)
    If Maildb.IsOpen = True Then
        'Already open for mail
    Else
        Maildb.OPENMAIL
    End If

    Set collection = Maildb.AllDocuments
   
    '***************************************
    'Here's where my program, as an email attachment, needs to expose the current email's ID
    'or something that will enable me to grab the subject line, below.

    Set MailDoc = collection.GetTHISDocument      'if only!!!
    '***************************************    

    Set item = MailDoc.GetFirstItem("Subject")  'to reveal the Word filename
    MsgBox item.Text

End Sub

Any ideas gratefully welcomed.
Tom
ASKER CERTIFIED SOLUTION
Avatar of Bill-Hanson
Bill-Hanson
Flag of United States of America image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Avatar of tommyfs
tommyfs

ASKER

Thanks, Bill. Yes, I'm trying to get a handle on the currently opened email that contains both the attachment VB6 program as well as the subject line that contains the filename of the document that I want the VB6 program to process. BTW, the rationale for this approach is to limit the email recipient to one specific document, the one stated in the subject line. Looks like the UI Classes are the answer, but won't have a chance to try it until Monday. I'll let you know.
Avatar of tommyfs

ASKER

Bill, I've modified my code, as follows, to take advantage of your UI Classes idea:
******************
Public Sub Main()
    Dim Maildb As Object 'The mail database
    Dim UserName As String 'The current users notes name
    Dim MailDbName As String 'THe current users notes mail database name
    Dim MailDoc As Object 'The mail document itself
    Dim Session As Object 'The notes session
    Dim ws As Object
    Dim uidoc As Object
    Dim doc As Object

    'Start a session to notes
    Set Session = CreateObject("Notes.NotesSession")
    Set ws = CreateObject("Notes.NotesUIWorkspace")
    Set uidoc = CreateObject("ws.CurrentDocument")
    Set doc = CreateObject("uidoc.Document")
    'Get the sessions username and then calculate the mail file name
    UserName = Session.UserName
    MailDbName = Left$(UserName, 1) & Right$(UserName, (Len(UserName) - InStr(1, UserName, " ")))& ".nsf"
    'Open the mail database in notes
    Set Maildb = Session.GetDatabase("", MailDbName)
    If Maildb.IsOpen = True Then
        'Already open for mail
    Else
        Maildb.OPENMAIL
    End If
   
    MsgBox doc.GetItemValue("Subject")(0)
End Sub
******************
Instead of stepping thru the code interactively, I figured it's going to actually have to be part of an open email document; so I compiled and included the executable as an attachment in an email. Runtime error 429 "ActiveX component can't create object" is the result of running the .exe file. Next, I did in fact step thru the code in the VB6 interface and got this error at the code line " Set uidoc = CreateObject("ws.CurrentDocument"). As project references, Notes Domino Objects and Lotus Notes Automation Classes are checked.

What am I missing?

Tom
Avatar of tommyfs

ASKER

Bill, Further progress. If I move the statements:

Set ws = CreateObject("Notes.NotesUIWorkspace")
Set uidoc = CreateObject("ws.CurrentDocument")

to AFTER the MailDB.Open statement (and End If); and use:

MsgBox uidoc.FIELDGETTEXT("Subject")

error 429 is gone, and replaced by "Error 7412, Notes Error - cannot locate field"

"Subject" surely is the field I want, and running the executable as an attachment to the email should definitely "see" the Subject. Right?

Tom
Did you look at the code I posted in comment #21073955?  It shows exactly how to get a handle to the current UI document.

In a nutshell, the only objects that you need to instantiate using CreateObject are NotesSession and NotesUIWorkspace.  The rest of the handles are obtained by calling the methods or properties of these two classes.

For example, to get the current UI document, use...

    Dim uidoc As Object = ws.CurrentDocument

From your comments about project references, it sounds like you could use a bit of help understanding the difference between early-binding vs. late-binding and the differences between the various Notes references that are available.

Here's a very basic primer...

-------------------------------------
Early-Binding vs. Late-Binding
-------------------------------------

There are two ways to access and use external objects.  You can add a reference to your project and use the classes just like you would use any other data type (early-binding), or you can leave the references out of your project and handle everything at run-time by using CreateObject (late-binding).

We call the first way early-binding because the compiler knows everything about the classes (ie: parameter type, return value type, etc) at compile-time.  When you use CreateObject, however, the compiler does not know anything about the methods or properties that you will be using, so everything is handled at run-time.

In general, early-binding is faster than late-binding because the compiler can make optimizations based on the knowledge of parameter and return value data types.  Late-binding is slower because everything is handled as an object which is evaluated at run-time.

Your code uses late-binding (which is your only option for this app), so you don't need to include either reference in your project.  Including a reference and not using it just wastes space in your app.

----------------------
Lotus References
----------------------

This has always been a source of confusion, so don't feel too bad.
There are three ways to access Lotus Notes objects from VB.
Note: a plus sign (+) indicates an advantage and a minus sign (-) indicates a disadvantage.

1) Lotus Notes Automation Classes (Lotus.NoteSession)
    + COM based.
    - Access back-end classes only.
    + Can be early-bound or late-bound.
    + Notes does not need to be running.

2) Lotus Domino Objects (Domino.NoteSession)
    + COM based.
    - Access back-end classes only.
    + Can be early-bound or late-bound.
    + Notes does not need to be running.

3) Notes OLE Objects (Notes.NoteSession)
    - OLE based.
    + Access front-end and back-end classes.
    - Late-bound only.
    + Notes must be running.  If it is not, the application will launch automatically.

OK, here's the skinny:  #1 and #2 are basically the same thing.  Use "Lotus Domino Objects" for early-bound code and "Lotus Notes Automation Classes" for late-bound code.  #3 is used anytime you need to access front-end objects.

Here are some case scenarios:

1) A .Net application that uses back-end classes only:
    > Use early-binding by including a reference to the "Lotus Domino Objects" COM library.
    > Example:
            Dim sess As New Domino.NotesSession()
            Call sess.Initialize(pwd)

2) A .Net application that uses font-end classes:
    > Use late-binding by declaring your variables as type Object and instantiating them using CreateObject with "Notes OLE" objects.
    > Example:
            Dim sess As Object = CreateObject("Notes.NotesSession")

3) A VBA or vbScript application that uses back-end classes only:
    > Use late-binding by declaring your variables as type Object and instantiating them using CreateObject with "Lotus Notes Automation Classes" objects.
    > Example:
            Dim sess As Object
            Set sess = CreateObject("Lotus.NotesSession")
            Call sess.Initialize(pwd)

4) A VBA or vbScript application that uses font-end classes:
    > Use late-binding by declaring your variables as type Object and instantiating them using CreateObject with "Notes OLE" objects.
    > Example:
            Dim sess As Object
            Set sess = CreateObject("Notes.NotesSession")

Notice that for the front-end classes, you only have one option -- late-bound code using CreateObject("Notes.NotesSession").

For more info, check out this document from IBM:

http://www.ibm.com/developerworks/lotus/library/ls-COM_Access/
It looks like we cross-posted.

I'm surprised that you don't get an error on this line:
Set uidoc = CreateObject("ws.CurrentDocument")

There is no COM object named "ws.CurrentDocument".  Instead, you should use:
Set uidoc = ws.CurrentDocument

Take a look at my last comment.  If you still have questions, consider this:

Since you're using the UI classes, you don't need to open the mail database at all.  This is the minimum code you will need to get a handle to the currently open document:

        Dim sess As Object = CreateObject("Notes.NotesSession")
        Dim ws As Object = CreateObject("Notes.NotesUIWorkspace")
        Dim uidoc As Object = ws.CurrentDocument
        Dim doc As Object = uidoc.Document
        MessageBox.Show(doc.GetItemValue("Subject")(0))

Also note that there is only one "currently open document" at a time.  There is no way to search through all open documents in Notes. Are you sure that this is what you are trying to accomplish.  Maybe you should explain the entire process.
Avatar of tommyfs

ASKER

Hi Bill,

Thank you for the refresher info on Binding and References. I understand that the CreateObject code is a front-end class using late binding. For the record, I'm stuck with VB6 with no access to .net, so my code will be a little different from yours.

Using your example (transposed to VB6), running this:

Private Sub Main()
    Dim sess As Object
    Dim ws As Object
    Dim uidoc As Object
    Dim doc As NotesDocument
    Set sess = CreateObject("Notes.notesSession")
    Set ws = CreateObject("Notes.NotesUIWorkspace")
    Set uidoc = ws.CurrentDocument
    Set doc = uidoc.Document
    'MessageBox.Show (doc.getitemvalue("Subject")(0))
    MsgBox (doc.GetItemValue("Subject")(0))
End Sub

results in runtime error 91: Object variable or With block variable not set. The error is raised at the "Set doc = uidoc.Document" statement. Looking again at your primer, it appears I would need to set a reference to Notes OLE Objects in order to use Notes.NoteSession. I am unable to locate this dll file in my available VB6 references, unless it's got a really arcane filename.

In addition, your reference to the IBM developerworks document site is unavailable to me, and IBM sincerely apologizes for their Site Under Construction. Arrgghhh!

Your last request was to have me explain the entire process, which I will summarize here:

There is a folder in an ifs partition on our iSeries (AS400) system, which contains hundreds of files each identified by a unique 5 digit number. Most of our users do not have permissions to access this partition, so my VB6 program temporarily maps a drive on their PC to that partition which, unless I limit their access to one specific document, gives them access to every document in that partition/folder. I can do limiting by having my program open MS Word and load the document whose filename is given in the subject line of an email to the user. To accomplish that an email is sent to the user with 2 pertinent things: 1) my VB6 program as an attachment; and 2) the required Word document's filename at the end of the Subject line.

The user will double-click on the attachment, launching my executable program, opening an instance of Word, loading the document mentioned in the Subject line, allowing the user to process and save the modified document, and quit the program (which removes the temporary drive mapping aforementioned). All the above works perfectly, other than it's inability to recognize the Subject line text.

We are using Lotus Notes V6.5 and WINXP Pro. Hopes this helps.
Thanks for the detailed explanation, I'll comment on that in a minute, but I want to address the issue in your Main sub first.

The only thing I see wrong is the mixture of OLE and COM objects in the same script.  This is a big no no.  Here's the problem: we need to use OLE because we need the Notes GUI, but on line 4 you set doc = NotesDocument.  NotesDocument is a COM object.  Since you don't get an error on this line, that means that you still have a COM reference in your project.  Remove it if it's not being used in another part of your application.  The line should read: Dim doc As Object.

Another condition that would cause that error is when no document is open in the Notes client.

The code below should solve both problems.  The doc variable is declared as Object, and there are error traps setup to detect invalid objects.  The only thing left is to remove the reference to the COM object from your project.

Now, about the application design.  I might handle this a bit differently depending on how the emails are created.  If you're sending them manually, or from outside of Notes, then you don't have much choice, but if you use Notes to create and send the email, you have another option that you might not have considered:  stored forms.

Normally in Notes, forms and documents are separate.  If you create a document and mail it to a user, the user would need to have that specific form design element in their mail database's design in order to use it.  But if you store the form inside the document, you can email it to any Notes user and they will be able to use it.

Here's the basic idea:  Create a Notes database and a form that contains everything you need to run your application (including fields, attachments, images, buttons, etc).  Since everything is in the form, you don't have to rely on the subject to contain the info you need anymore, you could just store the data that you need in a hidden field. What's more is that you may be able to eliminate the application attachment altogether by coding your entire process in LotusScript.  At the very least, you could hide the attachment and provide a nice button that will detach and run your application.  The main benefit of doing things this way is that you may be able to eliminate the Notes specific code in your app.  For example, in your button code, you could pass the subject of the email as a command-line parameter to your app.  Then you wouldn't have to use the Notes API to get the subject.
Private Sub Main()
    Dim sess As Object
    Dim ws As Object
    Dim uidoc As Object
    Dim doc As Object
    Set sess = CreateObject("Notes.NotesSession")
    Set ws = CreateObject("Notes.NotesUIWorkspace")
    Set uidoc = ws.CurrentDocument
    If (uidoc Is Nothing) Then Error 2000
    Set doc = uidoc.Document
    If (doc Is Nothing) Then Error 2001
    MsgBox (doc.GetItemValue("Subject")(0))
    Exit Sub
CATCH:
    Select Case Err
        Case 2000: MsgBox "There is no open document!"
        Case 2001: MsgBox "Unable to get back-end document."
        Case Else: MsgBox Error$
    End Select
End Sub

Open in new window

Avatar of tommyfs

ASKER

Interesting! But first, let's handle the application design -- the email is created outside of Notes by the VB6 program which retrieves info from a HelpDesk database, and creates a Word document with formfield checkboxes for the user to fill in and then "signoff" with name and date; then sends an email to him/her using a Notes object. The stored forms idea, while interesting, is, I believe, unusable.

Back to the code, I compiled your revisions and sent the executable as an attachment in an email, with a specific subject line, and the body containing the word "test". When retrieved by the user, who then ran the attached program, Error 2000 is raised, revealing the "there is no open document" message. At the time, there was no other open Notes document, other than the one containing the VB6 program, and of course this Notes document is most certainly open. It almost seems that the program, being launched from the attachment position is disassociated from the main document (does it require the program being in the body of the email? Nah, that makes no sense).
You got me there.  I'm not sure why it doesn't see the open document.  Are you sure it's still open when the app is run?
Avatar of tommyfs

ASKER

Bill,
Once again you have provided the clue. My testing has consisted of sending the test email message to another box to which I have access, then opening the received message and executing the program. Without closing the first iteration of Notes, it's entirely possible that my program was unable to distinguish between "which open document" do you want, and thru up the error.

In addition, much to my surprise, my usual email client is not Lotus Notes, but rather iNotes (a subset of Lotus Notes, as I understand). If I truly do use Lotus Notes to open the received email and run the .exe, the subject is readily captured. If I use iNotes, it's not! I'm left with the impression that there must be totally different classes/objects for each email client.

Further, it appears that only the programmers and management here have the full Lotus Notes client, whereas "most" only have the iNotes version. My next goal, then, is to figure out the code to expose the Subject using either email client, assuming that's even possible. Any experience with that?
Oh, boy!  This could get hairy!  I strongly recommend taking a step back and coming up with a more elegant solution.  So far, we have automated Notes.  Since iNotes runs in a web browser, what you are planning is to:

1) Detect which browser version is being used.
2) Write custom code for each web browser (IE, Firefox, Mozilla, etc...) than can locate the subject field, etc.

I have no experience or desire to attempt this level of integration.

My first thought is to host a web service that can accomplish the same thing as your app, then just add a link to the email that calls the service, passing any required data from the subject.  That way, the link in the email will work in any client.

Even if you have to use a local program, you may be able to do something similar by passing command-line arguments.  It may be a bit tricky getting this to work via a browser due to security restrictions, though.
Avatar of tommyfs

ASKER

Bill,

I agree -- no interest in opening that can of worms. The Web-based service would cause us problems due to authority issues on the network. Since my project involves signoffs by users requesting coding changes to our iSeries software, we will modify the policy as to the level of employee that can sign off on the implemented change; in our case, that's management-level, most of whom have Lotus Notes. Thus, the project will require the use of Lotus Notes. The bonus here is that it gives us tighter controls re requested software changes, since a director, a manager, or a supervisor will always be involved.

As such, I'm approving comment #21073955 as the Accepted Solution. Thank you for your patience and tenacity with my problem. I feel much more confident regarding Bindings, Classes and References when related to email.