Link to home
Start Free TrialLog in
Avatar of Richie_Simonetti
Richie_SimonettiFlag for Argentina

asked on

VB and picture in document

Hi,
i know we could draw tables in notes document:
What i need is insert a picture FROM an image file stored in my hard disk in a cell and put a little description in other cell.
how do ALL of with VB and COM?
I am not interested in LS.
Hope i was clear.
Cheers
Richie
Avatar of zvonko
zvonko

Is this for web or for Notes native client?
Which Domino server release? Which platform?
Does embeding happen interactively as in an agent in backend?

There is no way to draw a table programmatically (there are tricks to let it look like table and creating row by row but you can not draw tables).

If you place anywhere on your form a table and locate into one cell a RichText field and into another cell a field for the description then this would work as requested.

But this would work only for web.

For Notes clients it is not possible to embed an image anywhere in backend. In fronted (on workstation in a Notes client) it is again possible, but not trivial.

For your distinguish between LS and VB: LotusScript is absolutely Visual Basic with additional Lotus specific objects. And there is no EXE compiler like the VB IDE offers. You can not make standalone executables. You can call all Notes object also in a VB environment trough COM but why should you do this? And this is not the way of choice for such complex action like image embedding into a Notes document. That makes no sense for me. Please explain a bit your needs.

So long,
zvonko

Avatar of Richie_Simonetti

ASKER

I need to create a new mail, insert a picture (maybe a logo), put some text, attach a file and send the message.
I have the code already, only need picture matter.
All with VB-COM or VB/OLE.
is it so hard?
Yes, it is.

Now I can start programming and testing.
The only info I miss is your Notes version.

It would be easier if I could extend your code.
Would you mind pasting your code here or sending it to: zp@arcore.de

There is no problem, you can download it from www.angelfire.com/realm/vb-shared/index.html under "Say OLE to COM..." topic.
Cheers
I have no problems sending mail with VB. I only asked for your code to use same variable names for less confusion. When you say this is your starting point, than ok. I will extend it for you :-)

Stay tuned...

<|:-)


Aiming for a  300 Zvo ?  

Did you see i just got a "A" for 20 pts ?  I am happy that i too can get some pts nowadays...

:-)
Let us see how big spender Mr. AngelFire is :-)

Hello Richie,

here my first evaluations.

You can only place an image into Body to be visible with UI function Paste.
Here the code:
Set Doc = OLEDB.CreateDocument
Call Doc.AppendItemValue("Form", "Memo")
Set OLEWorkspace = CreateObject("Notes.NotesUIWorkspace")
Set OLEUIDoc = OLEWorkspace.EDITDOCUMENT(True, Doc)
Call OLEUIDoc.FIELDSETTEXT("EnterSendTo", "Zvonko Paunoski")
Call OLEUIDoc.FIELDSETTEXT("Subject", "Mail Subject")
Call OLEUIDoc.GOTOFIELD("Body")
Call OLEUIDoc.Paste
Call OLEUIDoc.Send
Call OLEUIDoc.Close
End Sub

Does this say anything to you?

I mean, you have to feed the clipboard with VB Image Copy call...

Good luck,
zvonko

This should do exactly what you want except for the table part, let me know if this is what you were looking for and we'll look at the RT dynamic table part.


#include <iostream.h>
#include <windows.h> //FOR THE MESSAGEBOX
#define W32

#include <lncppapi.h>

#define ERR_BUF_SIZE 512


extern "C" {
     extern __declspec (dllexport) int InsertPicture(
                    char *DocUNID,
                    char *RTFieldName,
                    char *FileName,
                    char *Text);
}
LNNotesSession   Session;

BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved){
     switch (fdwReason) {
     case DLL_PROCESS_ATTACH:
          if ( Session.Init()){
               return (FALSE);
          }
          break;
     case DLL_PROCESS_DETACH:
          Session.Term();
          break;
     }
     return (TRUE);
}


int InsertPicture(
                    char *DocUNID,
                    char *RTFieldName,
                    char *FileName,
                    char *Text){

     LNDatabase              Db;
     LNDocument                    Memo;
     LNString                    LNStrUNID;
     LNUniversalID               UNID;
     LNRichText                    RTF;
     LNRTCursor                    Cursor;    

     LNSetThrowAllErrors(TRUE);
     try{
          LNStrUNID=DocUNID;
          UNID=LNUniversalID(LNStrUNID);
          Session.GetMailDatabase(&Db);
          Db.Open();
          Db.GetDocument(UNID,&Memo);
          Memo.Open();
          Memo.CreateItem(RTFieldName, &RTF);
          Memo.GetItem(RTFieldName, &RTF);
          RTF << Text;
          RTF.GetCursor(&Cursor);
          RT.Import(FileName, &Cursor);
          Memo.Save();
          Memo.Close();
     }

     catch (LNSTATUS lnerror){
          char ErrorBuf[ERR_BUF_SIZE];
          LNGetErrorMessage(lnerror, ErrorBuf, ERR_BUF_SIZE);
          MessageBox(NULL,ErrorBuf,"BIG ERRORRRRRRRRR",MB_OK);
          return (1);
     }

     Db.Close();
     return (0);
}

This should do exactly what you want except for the table part, let me know if this is what you were looking for and we'll look at the RT dynamic table part.


#include <iostream.h>
#include <windows.h> //FOR THE MESSAGEBOX
#define W32

#include <lncppapi.h>

#define ERR_BUF_SIZE 512


extern "C" {
     extern __declspec (dllexport) int InsertPicture(
                    char *DocUNID,
                    char *RTFieldName,
                    char *FileName,
                    char *Text);
}
LNNotesSession   Session;

BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved){
     switch (fdwReason) {
     case DLL_PROCESS_ATTACH:
          if ( Session.Init()){
               return (FALSE);
          }
          break;
     case DLL_PROCESS_DETACH:
          Session.Term();
          break;
     }
     return (TRUE);
}


int InsertPicture(
                    char *DocUNID,
                    char *RTFieldName,
                    char *FileName,
                    char *Text){

     LNDatabase              Db;
     LNDocument                    Memo;
     LNString                    LNStrUNID;
     LNUniversalID               UNID;
     LNRichText                    RTF;
     LNRTCursor                    Cursor;    

     LNSetThrowAllErrors(TRUE);
     try{
          LNStrUNID=DocUNID;
          UNID=LNUniversalID(LNStrUNID);
          Session.GetMailDatabase(&Db);
          Db.Open();
          Db.GetDocument(UNID,&Memo);
          Memo.Open();
          Memo.CreateItem(RTFieldName, &RTF);
          Memo.GetItem(RTFieldName, &RTF);
          RTF << Text;
          RTF.GetCursor(&Cursor);
          RT.Import(FileName, &Cursor);
          Memo.Save();
          Memo.Close();
     }

     catch (LNSTATUS lnerror){
          char ErrorBuf[ERR_BUF_SIZE];
          LNGetErrorMessage(lnerror, ErrorBuf, ERR_BUF_SIZE);
          MessageBox(NULL,ErrorBuf,"BIG ERRORRRRRRRRR",MB_OK);
          return (1);
     }

     Db.Close();
     return (0);
}

This should do exactly what you want except for the table part, let me know if this is what you were looking for and we'll look at the RT dynamic table part.


#include <iostream.h>
#include <windows.h> //FOR THE MESSAGEBOX
#define W32

#include <lncppapi.h>

#define ERR_BUF_SIZE 512


extern "C" {
     extern __declspec (dllexport) int InsertPicture(
                    char *DocUNID,
                    char *RTFieldName,
                    char *FileName,
                    char *Text);
}
LNNotesSession   Session;

BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved){
     switch (fdwReason) {
     case DLL_PROCESS_ATTACH:
          if ( Session.Init()){
               return (FALSE);
          }
          break;
     case DLL_PROCESS_DETACH:
          Session.Term();
          break;
     }
     return (TRUE);
}


int InsertPicture(
                    char *DocUNID,
                    char *RTFieldName,
                    char *FileName,
                    char *Text){

     LNDatabase              Db;
     LNDocument                    Memo;
     LNString                    LNStrUNID;
     LNUniversalID               UNID;
     LNRichText                    RTF;
     LNRTCursor                    Cursor;    

     LNSetThrowAllErrors(TRUE);
     try{
          LNStrUNID=DocUNID;
          UNID=LNUniversalID(LNStrUNID);
          Session.GetMailDatabase(&Db);
          Db.Open();
          Db.GetDocument(UNID,&Memo);
          Memo.Open();
          Memo.CreateItem(RTFieldName, &RTF);
          Memo.GetItem(RTFieldName, &RTF);
          RTF << Text;
          RTF.GetCursor(&Cursor);
          RT.Import(FileName, &Cursor);
          Memo.Save();
          Memo.Close();
     }

     catch (LNSTATUS lnerror){
          char ErrorBuf[ERR_BUF_SIZE];
          LNGetErrorMessage(lnerror, ErrorBuf, ERR_BUF_SIZE);
          MessageBox(NULL,ErrorBuf,"BIG ERRORRRRRRRRR",MB_OK);
          return (1);
     }

     Db.Close();
     return (0);
}

Sorry for the tripple post, something must have gotten screwed up.
Welcome to EE Buddy!

I dont know the short form of KrzysztofOblucki !!!
Could you let us know ?

Thanks
Arun.
Hey guys,
Chris will do fine.

Thanks for the warm welcome =).
Oh that was not bad at all Chris!

Could you explain what your identity stand for ?

:-)
Arun.
(This is a Fun Forum as you could see already right ?)
Hello Chris,

I have a question to you. Have you tested your code?
Because there is a typo:
 RT.Import(FileName, &Cursor);

Variable RT is not defined in your source.

Anyway is your idea a good one ;-)

<|:-)
zvonko
zvonko, i was thinking in that UI part but i was too lazy to try it since i could have to rewrite db connection stuff.
I will do a try on your code and hope could be back soon.
what do you mean saying rewrite?

I have not posted the connection stuff because I tested with your code from OLE form. It worked well when testing with image from other program in clipboard.
So the bigger rewrite part I see in the placement of an image on your form. This is to be used as Copy source programmatically by the button Send code.

I am also interested in Chris path. The code looks like copied from C++API documentation and never tested for pitfalls. I am at home on a new computer without VisaulC so I can not test his good idea. If you succeed tell us please how it works.

So long,
zvonko


Well, i think if you don't open db with UI stuff, that code doesn't works (indeed, it doesn't, i got an automation error at line Set OLEUIDoc = OLEWorkspace.EDITDOCUMENT(True, Doc))
ASKER CERTIFIED SOLUTION
Avatar of zvonko
zvonko

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Actually I haven't tested the code but I wanted to
get a feel for what Richie wants, considering that my solution requires compilation and distribution of the dll together with the program, which may or may not be ok.  
Now, how does your solution work with back-end zvanko?
I would say that it is a considerable *pitfall* that this only works through the clunky OLE.
Also, could you point me to the portion of the documentation where the code was copied from, I seem to have forgotten =).

OT
My first name, Krzysztof which translates to Christopher and the last name Oblucki.  

Yes, the forum is fun but a little too competitive at times.  I personally don't care about the points, I come here to provide help to those who need it.

Unfortunatelly, i couldn't try it to monday.
Cheers and happy weekend.
OK, following is the code for inserting interpretetions for different files in the RT filed.
Requirements:
-document needs to contain a field with RT attributes set
properly, otherwise errors such as "Item not found" or "Invalid item type" will occur.
-lcppn21.dll needs to be in the Notes directory

Also the previous version of this code had two typos,
one -> RT should have been RTF
two -> GetCursor should have been GetEndCursor

If you give me your email address I'll send you the compiled version of this.

VB Declaration:
Path should be in notes directory for dependency reasons.

Private Declare Function InsertPicture Lib "C:\Lotus\Notes\InsertPicture.dll" ( _
            ByVal DocUNID As String, _
            ByVal FieldName As String, _
            ByVal FileName As String, _
            ByVal Text As String) As Long

C++ Code:


#include <iostream.h>
#include <windows.h> //FOR THE MESSAGEBOX
#define W32

#include <lncppapi.h>

#define ERR_BUF_SIZE 512


extern "C" {
    extern __declspec (dllexport) int InsertPicture(
                   char *DocUNID,
                   char *RTFieldName,
                   char *FileName,
                   char *Text);
}
LNNotesSession   Session;

BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved){
    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
         if ( Session.Init()){
              return (FALSE);
         }
         break;
    case DLL_PROCESS_DETACH:
         Session.Term();
         break;
    }
    return (TRUE);
}


int InsertPicture(
                   char *DocUNID,
                   char *RTFieldName,
                   char *FileName,
                   char *Text){

    LNDatabase                         Db;
    LNDocument                  Memo;
    LNString                    LNStrUNID;
    LNUniversalID               UNID;
    LNRichText                  RTF;
    LNRTCursor                  Cursor;    

    LNSetThrowAllErrors(TRUE);
    try{
         LNStrUNID=DocUNID;
         UNID=LNUniversalID(LNStrUNID);
         Session.GetMailDatabase(&Db);
         Db.Open();
         Db.GetDocument(UNID,&Memo);
         Memo.Open();
         Memo.GetItem(RTFieldName, &RTF);
          RTF << Text;
         RTF.GetEndCursor(&Cursor);
         RTF.Import(FileName, &Cursor);
         Memo.Save();
         Memo.Close();
    }

    catch (LNSTATUS lnerror){
         char ErrorBuf[ERR_BUF_SIZE];
         LNGetErrorMessage(lnerror, ErrorBuf, ERR_BUF_SIZE);
         MessageBox(NULL,ErrorBuf,"BIG ERRORRRRRRRRR",MB_OK);
         return (1);
    }

    Db.Close();
    return (0);
}



Actually following is the whole deal in VB that I used to test this:


'extern "C" {
'    extern __declspec (dllexport) int InsertPicture(
'                   char *DocUNID,
'                   char *RTFieldName,
'                   char *FileName,
'                   char *Text);
'}
Private Declare Function InsertPicture Lib "C:\Lotus\Notes\InsertPicture.dll" ( _
            ByVal DocUNID As String, _
            ByVal FieldName As String, _
            ByVal FileName As String, _
            ByVal Text As String) As Long
           
Private Sub button_Click()
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim i As Long
Call session.Initialize("You password goes here")
Set db = session.GetDatabase("Your mail server path", "Your mail file path", False)
Set doc = db.CreateDocument
With doc
    .ReplaceItemValue "FORM", "Memo"
    .ReplaceItemValue "Subject", "DLL TEST"
    .CreateRichTextItem "Body"
    .ComputeWithForm True, False
    .Save True, False
    i = InsertPicture(CStr(.UniversalID), "Body", "C:\test.xls", "HELLO")
End With
End Sub
Another note, the test code above was for several different files.  I tested bmp, jpg and txt files and they do work as expected, unfortunately xls files produce an error(above test).
Great job Chris! :-)

Do not be disturbed by the competition here: The only hunter here is me :_)

Please send me your complied solution to: zp@arcor.de

And please excuse moa for this first unpleasant impression. It can only get better :-)

Cheers,
zvonko

Zvo!

Guess Chris is another Simon Henry !!! What do you say ?
And i think he will go top very soon without begging like me (or you) hee hee hee !!! (OfCourse no offense meant buddies !)

Congratulations Chris!

So Very Nice of You Zvo !

;-)
Well, after minus modifications it works.
I don't like to see the open session window but we cannot avoid it, isn't it?
So, let's go to second part:
How about tables?
Cheers
Can this be done with COM?
What do you want to do with tables?

Basically does COM offer less than native LotusScript.


Please, re-read my primary question.
Lotusscript is not what i need. I need to do with VB and OLE AND COM if possible.
Thanks
And my answer is: what is not possible in LS is more not possible in VB, OLE, COM or any other subset :-)

What do you want to do whit tables?

There are always workarounds for nearly all problems...

But it is not possible to create tables programmatically in Notes. No way. The only way is doing it in Designer by hand.
OK, did you mean zvonko's solution or mine (I mean the one with the modifications you made).  You actually haven't given me any indication whether you are interested in this or not so I'll assume this is a conversation between you and zvonko.

As for the tables, I would give you the same type of solution (a straight windows dll) or an lsx module that you could call with OLE via ws.USELSX("blah"), the cool thing about lsxs is is that you deal with objects rather than basic types so you get a table object a tablecell object and so on and deal with that, the problem is that it goes through OLE(in VB at least since you need to load the LS host).  As for the session window, again, what do you mean, which session window OLE or COM, both of which can be made disappear with another C module.
Another thing, all of this can be done using COM, well not the notes library, but that certainly goes beyond a 100 point question, we're talking signing contracts and POs =).  Anyway, let us know.

I guess what I'm trying to say is that *you can* create tables dynamically either in an rt field or directly on a form(since a form is just a big'ol static rt field without the brackets in edit mode)  In fact you can even make it look as if they were created with the menu item create table (but you have to be a little clever with your rt field refresh code which you would have to do with OLE)

If you want to check out the lsx then let me know and I'll send it to you since I already have it.
KrzysztofOblucki, i am very sorry. The problem is you are talking C which is not what i want. Could you implement that in VB (Maybe vb-API?)?
I am not able to distribute any file/dll that not belongs to VB.
Cheers
I apologize again.
;)
In that case zvonko is absolutly correct, *no dynamic tables* in the client.  You will only be able to load an actual picture with OLE.

Sorry I couldn't be of any more assistance
Hello Richie,

thank you for the points and for the feedback :-)

I missed to note here that Chris solution worked on my machine; sorry Chris.
But I think this would not help to Richie (AngelFire) because I assume he is going to publish this solution on his web page :-)
And in such publishing methods is always bad to say: install my small (and evil >:) DLL and be happy :)

Cheers,
zvonko


zvonko,
thanks for comming back!.
"....
But I think this would not help to Richie (AngelFire) because I assume he is going to publish this solution
on his web page :-)
..."
Not at all!. As you surely saw, there are little examples there, do you know why?. Because i posted only code that i figured out by myself. What is the idea of doing what you suggest which is stole code from other people and publish it as mine?
I used code from the site in a regular basis at office, so in this case, i need to send a message to about 100 people showing Company Logo and a table with some values (a little one indeed). I need to automate this since is a very repetitive task and values on cells could be easily get from a database.
It's amazing why we cannot use a simple method like appenditemvalue or embedobject to put an image in the body of a document with COM.
To me, DOM from Lotus is a mess. I think they did it in a rush and they never have the way to go back.
Cheers