Friday, December 29, 2006

hide-when formula in Richtext fields

Richtext item inherits and keeps it's hide-when formula from the form's design when the document is saved for the first time. So if you set hide-when formula of the paragraph containing richtext field to "status=1" and create a new document, the richtext will also got "status=1" formula. When you later in the design of the form change the hide-when formula of the field's paragraph to "status=2", the richtext will still have the old "status=1" formula. To change the formula in the richtext field, you would need to open each document and manually change the formula to the new one.

You can prevent this problem from happening by putting the richtext field into a subform without any hide-when formula and then include the subform as a Computed Subform into the form. By changing Computed Subform's formula you can deside whether subform containing your richtext is shown or not. The formula for the computed subform will be: @If(status="1"; "MySubform";""). So instead of hiding the paragraph containing the richtext field, you simply do not show the subform containing the richtext field.

In case you already have many documents which must have their old hide-when formulas changed to a new formula and you do not want to do it manually:
a) You can use DXL LotusScript/Java classes to export documents to XML format, then locate and modify the hide-when formula and import the document back to the database. See below for a short example of export result.
b) You can also change hide-when using Midas Rich Text LSX tool (commercial). Check here: http://www.geniisoft.com/MidasHelp.nsf/FIND/559CAE5AF9EFF6CE85256A0900548706?OpenDocument I haven't try the hide-when functionality of the tool yet, but other richtext functionality I earlier used was easy to call in LotusScript.


Here is an example of richtext export to DXL:

<item name='Body'><richtext>
<pardef id='2'><code event='hidewhen'><formula>status="1"</formula></code></pardef>
<par def='2'>text line 1</par>
<par/>
<pardef id='3'><code event='hidewhen'><formula>status="2"</formula></code></pardef>
<par def='3'>text line 2</par>
</richtext></item>


If you have 3 lines of text in richtext field, and all 3 lines are hidden with same hide-when formula, and you then decide to set another hide formula on line 2, the second line of the text will get it's own hide-when tag in XMl as expected, but the third line of the text will not get it's own hide-when formula in DXL code, but will instead inherit the original hide-when formula by using same "pardef" id reference as the original text had:
<item name='Body'><richtext>
<pardef id='2'><code event='hidewhen'><formula>status="1"</formula></code></pardef>
<par def='2'>text line 1</par>
<par/>
<pardef id='3'><code event='hidewhen'><formula>status="2"</formula></code></pardef>
<par def='3'>text line 2</par>
<par def='2'>text line 3</par>
</richtext></item>

I am currently creating a LotusScript library with various DXL features for working with inline images and attachments, and I am considering to include the functionality to remove all hide-when formulas from a richtext field. Should be rather easy to accomplish to locate the node containing the hide-when reference and then simply remove that node.

Monday, December 25, 2006

Sametime bot shows a random Bible quote

To celebrate Christmas holidays, I've re-enabled "biblerandom" command for Sametime bot. This command shows a random verse from the Bible (both Old and New Testaments).

The Notes database which bot uses for finding answers was created from a Microsoft Access database and contains all books from King James's version of the Bible. The search function is implemented using LotusScript agent triggered from the bot.

Click HERE to try the Sametime bot command. After you logged in to chat application using any name, type "biblerandom" or "bible" without quotes and click the "Say" button. You can send this command many times, each time you will get a new Bible verse.

Screenshot:

Bible Bot


Tags:

Funny video about history of Ctrl+Alt+Delete

An old video, but still funny:
http://www.youtube.com/watch?v=WdGQsBDSEpk

Saturday, December 23, 2006

An interesting advice for LotusScript developers to avoid memory leaks

In the technote GetProfileDocument Method Appears to Leak Memory; Error "...LookupHandle: Handle Not Allocated", an interesting solution is given for avoiding memory leaks in certain LotusScript operations.

We all have at some time seen that some objects (usually documents in loops) are not properly removed by Notes after they have been processed and we had to call Delete method on the object to free the memory. Well, I think not many of us tried to free even Database object in each loop iteration. But according to the technote, assigning and deleting database object in each loop iteration can make a big difference. It would be interesting to test how this solution affects performance, as I suppose it would take time to reset database object 6000 times.

Excerpt:
The memory usage can be reduced by deleting the object handle to the profile document, but if you delete the object handle to the NotesDatabase object, then the memory usage is greatly reduced.

For example, based on the agent example above, the code would be altered to the following:

Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim i As Integer
-
For i = 1 To 6000
Print Cstr(i)
Set db = new NotesDatabase("server", "database.nsf")
Set doc = db.GetProfileDocument("ProfileDoc", Cstr(i))
Delete doc
Delete db
Next

Making Internet password changes work faster

IBM has recently published a technote on how to speed up Domino server recognition of a recently changed Internet password.
Technote: New Internet password is not immediately usable
Looks like solutions described in the technote should work with other similar caching problems. Hopefully it can help against problems with cached group members when users who were added to a group still can not access databases containing that group in the ACL.

Merry Christmas from Sametime Bot

Follow this link to see Christmas greeting from our Sametime bot Max: http://www.botstation.com/merrychristmas/index.html
And turn on sound on your computer :)




On the same page you can try out AJAX-based Sametime chat interface to bot.


Tags:

Wednesday, December 06, 2006

Lotus Roadshow 2006 in Stockholm

On the November 30th there was a half-day seminar at IBM about the new release of Domino and features of Sametime 7.5.
A little strange that roadshow in Stockholm was whole 23 days after the seminar in Gothenburg. Stockholm was the last city out of 12.
All seats in the conferance room were taken by more than 200 visitors (customers and business partners).
IBM's presenters showed how the new Lotus Notes 8 client looks like and some of the new features not available in earlier versions.

A funny thing happened when the presenter would show the integration of Notes client with SAP. He asked if there were any people in the audience who used SAP at their company. Noone raised their hand.




Here are presentations from the Road show: http://www-5.ibm.com/se/news/events/lotusroadshow/
And here are presentations available for online reading, converted by Thomas Adrian to Flash format: http://www.notessidan.se/A55B53/blogg.nsf/plink/TADN-6WGVR3

Saturday, November 18, 2006

A quick Sametime tip

If your Sametime server is accessible from the Internet and external users are not able to join the meetings, getting "Sametime server disconnected" message when connecting to Meetings, check that you have specified a valid Internet-resolvable server name (e.g.: sametime.company.com) in the server document: Internet protocols\HTTP\Host name(s) field.

Check also that users ha´ve correct Sametime server in "Sametime server" field in their person documents in NAB.

Information in the web browser's Java console can provide valuable clues to why the web browser failed to connect to the meeting and other client-side sametime problems.



Tags:

Friday, November 17, 2006

Borat from Kazachstan

For Borat's fans, this web site can be interesting. It contains links to several video interviews with Borat Sagdiev. I haven't seen many of them before, but I am not his greatest fan either... Ali G character is way cooler than Borat.
http://www.funkymusic.se/category/borat/




Technorati:

Thursday, November 16, 2006

Skype on mobile phones

From the 1st December will cell phone network operator "3" (Three) begin selling Nokia's N73 and Sony Ericssons W950 equiped with Skype software.

With flat price for mobile Internet access, phone users can make free calls to other Skype-users and cheap international phone calls.

So far the Skype-enabled phones will be available only in UK, but maybe they will work in other countries too as far as there is a mobile broadband connection.

Wednesday, November 08, 2006

Free e-book: Sametime For Dummies



As posted earlier by Ed Brill and Adam Gartenberg, there is a free ebook called "Sametime For Dummies", which you can download from IBM's web site.

The book has 72 pages. I could not find a reference to the number of pages in the paper edition, so I am not really sure if the PDF and paper book are same or not.

You can download the book at http://www-306.ibm.com/software/info/stdummies/index.jsp
It took me about 3 minutes to get the "save file" dialog box after right-clicking the download link and chosing "save target as", so be patient.

Here is the table of contents:

Introduction.......................................................1
Part 1: What Is IBM Lotus Sametime? .................5
Part 2: Instant Messages ..................................15
Part 3: Lotus Sametime Web Conferences ..........31
Part 4: Lotus Sametime Your Way .....................51
Part 5: Ten Lotus Sametime Reminders ..............61
Part 6: Ten Reasons Lotus Sametime Beats
the Competition ...............................................65


Technorati: Sametime

Tuesday, November 07, 2006

Embedding AJAX-based Sametime chat widget on web pages

With STWidget web application it is possible to put chat client on any web page. All you need is to include an IFRAME reference into your page's HTML code. Using STWidget, web users can connect to external or internal Sametime server and chat with other people who use either same STWidget web application or a stand-alone Sametime chat client.

If your internal Sametime server allows anonymous users, you can allow web visitors to directly contact selected people (or any person without restriction) without exposing internal Sametime server to Internet. This works because communication between STWidget app and server goes through a servlet, the web client never accesses the Sametime server directly.

The developer of the web page can choose whether users must with username and password or anonymously. There is also a token login mode, where user is logged in automatically with his current credentials which he used for opening the page, so he doesn't need to login twice (first to Domino web application and then to Sametime).

User's web browser does not need to have support for Java applets, the application works using AJAX-style XMLHTTP technology for communication with the web server.

Flash version of the STWidget application is planned to be released in about 2 months, which will overcome the AJAX limitation of only 2 concurrent connections to the web server.


<iframe src="http://stwidget.dyndns.org:19760/stwidget.html?login=anonymous" scrolling="no" frameborder="0" style="width:175; height:330;"></iframe>


Below is a working example of embedded Sametime chat (not just a picture). Input any name and you'll be logged in to Sametime server where you can chat with our Sametime Bot. Bot knows a lot of jokes, just type "joke" to him and he'll reply with a funny joke :) If you think the joke was not funny, type "joke" again and again until you are satisfied :)



Note: this embedded chat is for testing purposes only. Do not put it on your web site as it can be removed or modified at any time without prior notice. Contact us if you want to place chat widget on your web site.

Demo for anonymous login and login with password: http://www.botstation.com/products/stweb/demo.php



Technorati:

Tuesday, October 31, 2006

The forgotten art of StampAll .. or the fastest way to update documents

I've been analyzing an agent and found that it uses NotesDocumentCollection.StampAll(fieldname, value) method. I knew about the existence of the method but didn't remember about actually using it, so I decided to test how effective it was compared with other methods. For comparing I used looping through all documents in a document collection and updating them one by one.
The result was that for updating one field StampAll is 80% faster than any other method. To update field called "testfield" in 15000 documents using StampAll("testfield", "test") took 31 seconds, using doc.testfield="test" tool 54 seconds and doc.ReplaceItemValue("testfield", "test") took 50 seconds.

Surprisingly to update the same field using @Formula (Field testfield:="test") took 120 seconds. Using Simple Action it took 65 seconds.

One disadvantage with StampAll method is that it updates only one field at a time. So if you want to update 2 fields in a document, it would take 2 times as long time, while with other methods the difference is about +10% for each additional field.

Here is the source code of the agent and the agent's output.

Sub Initialize
Dim session As New NotesSession
Dim db As NotesDatabase
Dim coll As NotesDocumentCollection
Dim doc As NotesDocument
Dim item As NotesItem
Set db=session.CurrentDatabase

Set coll=db.AllDocuments
timerStart=Timer
Call coll.StampAll("testfield", "test1")
Print "Elapsed in test nr1: "+Cstr(Timer-timerStart)

timerStart=Timer
Set doc=coll.GetFirstDocument
While Not doc Is Nothing
doc.testfield="test2"
Call doc.Save(True, False)
Set doc=coll.GetNextDocument(doc)
Wend
Print "Elapsed in test nr2: "+Cstr(Timer-timerStart)

timerStart=Timer
Set doc=coll.GetFirstDocument
While Not doc Is Nothing
Call doc.ReplaceItemValue("testfield","test3")
Call doc.Save(True, False)
Set doc=coll.GetNextDocument(doc)
Wend
Print "Elapsed in test nr3: "+Cstr(Timer-timerStart)
End Sub

Elapsed in test nr1: 30,89014
Elapsed in test nr2: 54,27002
Elapsed in test nr3: 50,06982

Tuesday, October 24, 2006

Problem with Sametime installation

I hope this post will save some Domino/Sametime administrator time searching for solution.

I had Domino 5 server with Sametime 3.0 installed on my test server. The server was not in autostart mode. I didn't use it much so I decided to upgrade it to Domino 6.5 for making local tests of STWidget application in Anonymous mode. I chose not to update to the latest Sametime 7.0/7.5 because many (50%?) companies still use Domino 6 and Sametime 3.1/6.5.1. Although Sametime 7 Java Toolkit should work fine with Sametime 6, you never know.

I installed the Domino 6.5.5 server to a new folder and tested that it started correctly. Then I tried to install Sametime 6.5.1 server. The installation aborted with following message:
IBM Lotus Sametime 6.5.1 requires that
IBM Lotus Domino 6.0.3 or later
be installed on the same
computer as IBM Lotus Sametime 6.5.1

Install Domino 6.0.3 or later and
then restart this installation.


I checked that PATH environment variable does not point to the old Domino5 installation and even manually registered the nlsxbe.dll file "regsvr32 c:\lotus6\nlsxbe.dll" and un-registered the dll file in R5 folder.
That didn't help. Then I renamed the folder containing the old Domino 5 server files to c:\aaaaaaaLotus5\, hoping that installation will continue after it failed to open non-existant files.
Now when the new Sametime server installation started, it showed "Path not found" error message. This clearly pointed ou that it was just as I suspected that the old R5 server still was somehow found from the new server installation.
With "Path not found" search string I found IBM's technote describing the solution. The solution was simple: delete the HKEY_LOCAL_MACHINE\SOFTWARE\Lotus\Domino\5.0 registry entry.
After deleting the entry, the new Sametime server was installed without problems.


http://www-1.ibm.com/support/docview.wss?rs=0&q1=1158939&uid=swg21158939&loc=sv&cs=utf-8&lang=

Sunday, October 22, 2006

Skype and Lotus Notes

The View journal has recently published my article "How to add Internet telephony to your Lotus Notes and Domino applications"

The article describes how to integrate Skype telephony and chat into Lotus Notes applications using Skype COM API and how to integrate Skype with Domino web applications using javascript and other solutions.

The article includes a downloadable database with example code. Examples show different ways to trigger Skype functionality from Notes client and to monitor Skype status. You can copy buttons from the examples and paste into your own applications to enable one-click phone calls from Address Book.

Prerequisites for the examples to work: installed Skype client and Skype COM API toolkit, both are free to download and use.

Debugging web applications in Firefox

Finding errors in JavaScript on web pages can be a difficult task. In Internet Explorer you can in best case see the line number where the error occured.

I recently began using Firefox Javascript console for debugging web applications. Besides javascript errors, console also shows invalid properties of CSS stylesheets.
The console can be opened using Tools-JavaScript Console menu in Firefox browser. In the console you can see all the errors which occured, not only the last one as in IE. By clicking on error message, it opens a window with the script file where the error occured and marks the error line.




A strange thing I experienced with Firefox console is that it somehow caches XML-document nodes which results in "ghost" nodes. When I changed WIMBO Sametime chat application to use XML-formatted data instead of plain-text data, the Javascript console reported that the web browser still received the old plain-text data. The data was clearly not a part of the information received from the servlet, so I am still wondering why Firefox appended that data to the real data. Similar problem with ghost nodes happened when I replaced an empty "<RESPONSE></RESPONSE>" root node which caused problem in Firefox to "<RESPONSE><NONE>-</NONE></RESPONSE>".

Wednesday, October 18, 2006

A L33T Java agent one-liner

I noticed that most of the Domino developers split object calls into separate (more manageble?) pieces. What a waste of space in the code editor!

Let's create a one line of code which gets days difference between the first and the last document in a view and the total number of documents in a view, all without any declarations of variables.
The code is written in Java (agent), but the same thing can be done in LotusScript.


System.out.println("Time difference in days: "+String.valueOf(getSession().getAgentContext().getCurrentDatabase().getView("all").getLastDocument().getCreated().timeDifference(getSession().getAgentContext().getCurrentDatabase().getView("all").getFirstDocument().getCreated())/60/60/24)+". Number of documents: "+String.valueOf(getSession().getAgentContext().getCurrentDatabase().getView("all").getAllEntries().getCount()));



Post your own one-line code snippets, maybe we can find a practical use for them :)

Sunday, October 08, 2006

USB phone for Skype

Last week I've buyed a Doro 212IPC USB phone for Skype... and tested it as soon as I came home :) It costed 99 SEK (12.5 USD) at Media Markt



The phone quality is pretty good. Both incoming and outgoing sound is clear. But the integration with Skype and Windows could be improved.
Essentially, the USB phone is nothing more than a phone-formed headset with a keypad. I had some more expectations from a device called "phone", but what can you expect for 13 dollars?

The phone is setup as a sound device in Windows, and when plugged-in to the USB port, all sound goes through the phone instead of regular speakers. This is not very good as you most probably only want the sound from Skype program go through the phone, not sound from other programs. At the same time, this "feature" makes it possible to use the phone with the most of other softphones because it takes over standard audio input/output devices. It worked fine to speak and hear with X-Lite softphone (I dialed using mouse and softphone's virtual keypad) and after I downloaded a special driver, I could even use phone's number pads to dial the number.
Luckily, it's possible to manually change the settings in Windows after plugging in the phone to use standard sound devices instead of "Doro 212IPC" (you can still keep the Doro settings in Skype).

The first thing I noticed that you must manually open the "dial" tab in the Skype client, otherwise you can not dial a phone number. If any other tab than "dial" is selected in the client, the phone's number pad works for navigation up/down/left/right, which e.g. makes it possible to choose a Skype user in the buddy list. But as it's actually a phone, one would expect that when dialing a number from the key pad, the phone puts the Skype client into dial mode by default. As you must visually verify that the Skype client is on "dial" tab, the number pad on the phone is almost useless, as I can as easily type the number in the Skype software client on the computer when I am there anyway checking that the correct tab is open.

The other thing I expected to find in the phone was that incoming calls would ring in the phone. But the ring signal is possible only from the computer. How hard would it be to put a small speaker in the phone and activate it on incoming calls? Without this feature, the phone feels like an odd headset.


Overall impression of the phone device is positive, specially considering the low price. It's OK for making casual calls, but probably too boring if you are making a lot of calls. As the phone does not have a screen showing the dialed number, you will rather soon happen to dial a wrong number if you do not verify it on the computer screen.


Note: you must purchase SkypeOut credits for making outgoing phone calls; and SkypeIn service for accepting incoming phone calls to Skype client. Skype-to-Skype calls are free.

Sunday, September 17, 2006

Saturday, September 16, 2006

Action icons for Domino applications

Why use stock icons instead of standard Domino images?
Icons deliver the first impression when someone experiences your application or visits your website. Adding stock icons can be the difference between giving an impression of merely functional, or looking professional.

Designing professional-quality icons ranges from time-consuming (if you're artistic) to virtually impossible (if you’re not artistic - witness the shopping cart on the left).

For a fraction of the cost of having a graphics design professional on staff, the solution is to acquire a set of stock icons. A stock icon collection typically contains 100 or more icons that represents the functionality common to most applications and websites (help, copy, paste, shopping carts, flags, locks).


Here is a review and list of many web sites offering free and commercial icons:
http://www.iconsreview.com/

Sunday, September 10, 2006

Mac video ads -VS- HP video ads

Have you seen those fraudulent video ads that Apple produced for the Mac computers?
You can see them here: http://www.apple.com/getamac/ Warning: you must install the latest QuickTime video codec before trying to watch, otherwise the crap won't start. You should not have heavy objects near you as throwing them at the screen can damage the monitor. In short, the ads are about PC computers being boring and infected with viruses; Mac computers on the other hand are cool and are for creative people who don't want to bother about technical details and who use Mac to show their great design skills to other (Mac?) people. Some of the video ads are pretty funny, but the only people they can fool are stay-at-home moms with no technical background wanting to surf the Internet for cookie recepies and school kids who are mistakenly thinking they will somehow instantly raise their creativity level and become able to create cool pics to show their friends. Just look at their ad ("Accident") about a PC which fell down because someone tripped over the cords. What a joke! I woudn't be surprised if they did an ad where a PC user was strike by a lightning because of erhh... hmmm... LED lamp on CD-rom attracting electricity from the air.

But don't be in despair, my PC friends! No need to sue Apple for false advertising, they have enough problems without us, converting to Intel platform so people can finally do something useful with their new Unix-based OS X. We have got something better! HP produced several video ads that kick Apple's butt into the space! The ads are obviously more expensive than Apple's, and web campaign has some additional cool multimedia features. You can include your own picture in a video and send it to your friends. Check out my video here: Link. No comments about how I look in the rock video please :)
Here you can see the professional video ads and create your own video email using your picture: http://www.hp.com/personalagain

I am not sure if HP's computers are really that good as shown in the ads, but the video ads themself are way better than Apple's brain dead dialog between a hippie and an office guy.

Saturday, September 09, 2006

I want to believe

Finally an invention which can change the history of mankind, and you can follow it's course day-by-day!
A claim of this size happens only once in about 10 years, so don't miss it, otherwise who knows when you have a possibility to see something similar next time. It's not every day someone makes a claim to have a WORKING prototype of Perpetuum Mobile.

Here is what the company says:
- We have developed a technology that produces free, clean and constant energy.

- This means never having to recharge your phone, never having to refuel your car. A world with an infinite supply of clean energy for all.

- Our technology has been independently validated by engineers and scientists - always off the record, always proven to work.


"What we have developed is a way to construct magnetic fields so that when you travel round the magnetic fields, starting and stopping at the same position, you have gained energy," Sean McCarthy (Steorn's chief executive officer) said.
"The energy isn't being converted from any other source such as the energy within the magnet. It's literally created. Once the technology operates it provides a constant stream of clean energy," he told Ireland's RTE radio.

Many people think that it's a hoax or some kind of PR trick. As the company does not show it's device publicly, I am somewhat sceptical too.
Their claim to put the energy-producing device in mobile phones to make them work without batteries sounds also somewhat unrealistic, I have hard to see how would they fit the device inside the cell phone and how it would manage to produce that much energy. With all the shakings, falls and hot/moisture/dust environments the cell phone experiences, it would be higly impractical to implement a free energy producing thingy inside a cell phone. Is it their give-away that the device does not exist, or is it just an unfortunate example of usage area?

The main difference of Steorn's invention with other similar claims is that they say that they already have a working machine. 98% of other claimers had only drawings of how such machine would look like. They also say that several independent professionals have verified that the machine works. The fact that ALL of those experts have chosen to remain anonymous raises some suspicion.
Even if the experts couldn't explain why the machine works, according to Steorn they all aknowledged that it does work.
Another difference is that Steorn does not ask for investments. If it was a hoax, they would want to get the investor's money and dissapear before the bluff is exposed. But they challenged 12 scientists to verify the results before any investments are accepted. The fact of not asking for investments does not however exclude it from being a PR trick. As the Steorn itself is too insignificant to gain something from this kind of publicity, maybe some larger company stands behind it as uses Steorn as a marionett. Maybe it's some kind of ad campaign for electricity-driven Toyota Prius? Some people think it's an ad campaign for the next release of HALO video game.

So hold your breath, the new age of human civilization is coming soon! Hmmm.. or maybe the end of the world? Anyway, some kind of result (positive or negative) should be available before the end of the year.


http://www.steorn.net
http://en.wikipedia.org/wiki/Steorn
Ad in "The Economist": http://www.steorn.net/media/downloads/steorn_ad01_screen.pdf

Thursday, September 07, 2006

Export inline Notes pictures to disk as GIF files

Have you tried to export an inline picture from Notes database to hard drive? You can of course select the picture, copy it to clipboard, paste it to Paintbrush and then save the new picture to disk. But what if there are more than thousand pictures to process? The manual procedure would take several hours.
Fortunately you can programmatically export pictures using Notes DXL classes. The code below takes the first picture in a richtext field named PictureRT and saves it to disk as a GIF file.

The code uses a LotusScript library for BASE64 decoding, which you can download from Julian Robichaux's web site: http://www.nsftools.com/tips/NotesTips.htm#lsencryption

Example does not use Notes classes for handling XML (NotesDOMParser), it parses the string using it's own logic. In many cases NotesDOMParser processing is to prefer, and I might later create a version which uses NotesDOMParser.

Option Public
Use "base64encdec"

Sub Initialize
Dim session as New NotesSession
Dim db as NotesDatabase
Dim doc as NotesDocument
Dim picdata As String
Dim decstr As String

set db=session.CurrentDatabase
set doc=db.GetDocumentByUNID("1EC1508B08428D4385256E00004B0D3F")

Set exporter = session.CreateDXLExporter
exporter.ConvertNotesBitmapsToGIF = True
out = exporter.Export(pdoc)

find1="<item name='PersonPicture'"
find2="</item>"
findpic1="<picture"
findpic2="</picture>"
rtstart=Instr(out, find1)
rtstart2=Instr(rtstart, out, findpic1)
rtfinish2=Instr(rtstart2, out, findpic2)
purepic= Mid(out, rtstart2, rtfinish2-rtstart2+Len(findpic2))


finddata1="<gif originalformat="'notesbitmap'">"
finddata2="</gif>"
picdatastart=Instr(purepic, finddata1)
picdatafinish=Instr(picdatastart, purepic, finddata2)
picdata=Mid(purepic, picdatastart+Len(finddata1), picdatafinish-picdatastart-Len(finddata2))

decstr=DecodeBase64(picdata)
fout = Freefile
Open "c:\testgif.gif" For Output As fout
Print #fout, decstr
Close #fout
End Sub

Friday, September 01, 2006

Christmas for OS junkies

With free VMWare player it's possible to test your Java and web applications in almost any OS.

Here you can download different Linux OS distributions pre-configured with different software, such as CRM, firewall, web browsers, free web/email/collaboration servers, SSL VPN, security tools:
http://www.vmware.com/vmtn/appliances/directory/cat/51/


My favorite is Linux OS configured with several web browsers, which makes it possible to see how web (Domino) applications look like in Linux's browsers:
http://www.vmware.com/vmtn/appliances/directory/browserapp.html

I've heard (blink blink ;)) that there is even a way to run Mac OS X in VMWare in Windows. If it was true, that would be a great way to test how web (or Java) applications work in Mac OS.

List of 25 PDF converters

Here is a list of 25 programs which can convert text files to PDF format.
http://www.epublishingdaily.com/25-pdf-converters/

Personally I use OpenOffice to save from Word to PDF, but there might be cases where some extra features are needed not available in OpenOffice. I also have PDF995 and PDFCreator as printer drivers which enable me to save output to PDF file from any program which allows to print out to printer.
A PDF printer driver is the easiest way to save any Notes document to PDF format.

Wednesday, August 23, 2006

Showing user's pictures in Sametime 7.5

Grant Bingham in his blog explains how to show users' pictures in Sametime 7.5 client. His step-by-step instructions with screenshots are much easier to follow than IBM's technote.



Technorati:

Tuesday, August 22, 2006

Avoid caching of web pages

To avoid caching of Domino web pages/documents when re-opening the page, put this code snippet into HTML Head Content property of the form:

"<meta http-equiv=\"Expires\" content=\"0\"> <meta http-equiv=\"Cache-Control\" content=\"must-revalidate\"> <meta http-equiv=\"Cache-Control\" content=\"no-cache\">"

Thursday, August 17, 2006

Programmatically export Lotus Notes contacts to VCard format

Lotus Notes 6 makes it possible to export contacts to VCard format. You can do it using File-Export menu. In the Export dialog box you can choose to export to VCard 2.1/3.0 format. After that you can import the resulting VCF file into Outlook.

But sometimes you would like to modify the format which the automated function uses. For example instead of "FirstName LastName/Company/Country" format in VCard's FN field you want to use simply "FirstName LastName", or you want to make a lookup to fetch the required field value.
"Export to VCard" option is available only in the databases of type "Domino Directory", you can not see that export option in regular Domino databases where you might have people documents.

Here is a LotusScript agent which runs on selected documents in any database and exports them to VCard fromat. The agent expects that the names of the fields in the documents are the same as in Address Book's "Person" form, so if you used other field names you must modify the agent. The agent's "Target" property is "All selected documents". Agent is run by choosing agent's name in the actions menu in a view after you've selected the documents you want to export.


'------------- AGENT START -----------
Sub Initialize
Dim session As New NotesSession
Dim nabdb As NotesDatabase
Dim nabdoc As NotesDocument
Dim nabcoll As NotesDocumentCollection
Dim vcardfile As String
Dim result As String
Dim linebreak As String
Dim fileNum As Integer

linebreak=Chr(13)+Chr(10)
vcardfile="c:\lotus_notes_contacts.vcf"

Set nabdb=session.CurrentDatabase
Set nabcoll=nabdb.UnprocessedDocuments
Print "Exporting"+Cstr(nabcoll.Count)+" documents to VCard "+vcardfile

If nabcoll.Count=0 Then Exit Sub

fileNum% = Freefile()
Open vcardfile For Output As #fileNum%

Set nabdoc=nabcoll.GetFirstDocument
While Not nabdoc Is Nothing

result="BEGIN:VCARD"+linebreak+ "VERSION:2.1"

result=result+linebreak+ "N:"+nabdoc.LastName(0)+";"+nabdoc.FirstName(0)+";"+nabdoc.MiddleName(0)+";"+nabdoc.Title(0)
If nabdoc.MiddleName(0)="" Then
FullName=nabdoc.FirstName(0)+" "+nabdoc.LastName(0)
Else
FullName=nabdoc.FirstName(0)+" "+nabdoc.MiddleName(0)+" "+nabdoc.LastName(0)
End If
result=result+linebreak+"FN:"+FullName
' result=result+linebreak+"NICKNAME:"+FullName
result=result+linebreak+"ORG:"+nabdoc.CompanyName(0)+";"+nabdoc.Department(0)
result=result+linebreak+"TITLE:"+nabdoc.JobTitle(0)
result=result+linebreak+"NOTE:"+nabdoc.Comment(0)
result=result+linebreak+"TEL;WORK;VOICE:"+nabdoc.OfficePhoneNumber(0)
result=result+linebreak+"TEL;HOME;VOICE:"+nabdoc.PhoneNumber(0)
result=result+linebreak+"TEL;CELL;VOICE:"+nabdoc.CellPhoneNumber(0)
result=result+linebreak+"TEL;WORK;FAX:"+nabdoc.OfficeFaxPhoneNumber(0)
result=result+linebreak+"TEL;HOME;FAX:"+nabdoc.HomeFAXPhoneNumber(0)
result=result+linebreak+"ADR;WORK:;"+nabdoc.OfficeCity(0)+";"+replaceLineBreak(nabdoc.OfficeStreetAddress(0))+";"+nabdoc.OfficeCity(0)+";"+nabdoc.OfficeState(0)+";"+nabdoc.OfficeZIP(0)+";"+nabdoc.OfficeCountry(0)
result=result+linebreak+"ADR;HOME:;;"+replaceLineBreak(nabdoc.StreetAddress(0))+";"+nabdoc.City(0)+";"+nabdoc.State(0)+";"+nabdoc.Zip(0)+";"+nabdoc.Country(0)
' result=result+linebreak+"URL;WORK:"+nabdoc.WebSite(0)
result=result+linebreak+"URL;HOME:"+nabdoc.WebSite(0)
result=result+linebreak+"PREF;INTERNET:"+nabdoc.InternetAddress(0)
result=result+linebreak+"EMAIL;INTERNET:"+nabdoc.MailAddress(0)

result=result+linebreak+"END:VCARD"

Print #fileNum%, result

Set nabdoc=nabcoll.GetNextDocument(nabdoc)
Wend

Close #fileNum%

End Sub


Function replaceLineBreak(oldString)
replaceFrom=Chr(13)+Chr(10)
replaceTo=", "
tmpString = Evaluate(|@ReplaceSubstring("| + oldString + |"; "|+replaceFrom+|"; "|+replaceTo+|")|)
replaceLineBreak=tmpString(0)
End Function

'------------- AGENT END -----------


Technorati:

Tuesday, August 15, 2006

Web charts from LotusScript

Thomas Adrian (www.notessidan.se) has now published a LotusScript agent which creates a simple column chart on a Web page by using div-tags . Chart's HTML/CSS code is created dynamically and the agent outputs it directly to the web browser.

Lotus Domino agent uses Apache Axis to consume a web service

Joachim Dagerot published an article on IBM developerWorks about how to use Apache Axis in a Domino Java agent to call a web service: Consuming Web services from a Lotus Domino Java agent. The article provides description and examples of how to call Web Services from your own Domino databases.

Last month I posted about another Java library to consume Web Services: WSIF (Web Services Invocation Framework). I had it as a stand-alone Java program in the Web Services tutorial published on DeveloperWorks, and last month I created a Domino Java agent re-using the same source code as in the stand-alone program. The problem with WSIF framework is that it is 3 years old, but it looks like there are plans for a new release.


What I liked with WSIF the most is the dynamic invocation of Web Services. That means that you do not need to create a stub or proxy or anything, you simply specify the location of the WSDL file, the function name and the parameters to the function:
java DynamicInvoker http://www.server.com/simplesoap/StockquoteSOAP.wsdl getQuote IBM
AXIS also has a DynamicInvoker example which gives absolutely the same result as DynamicInvoker WSIF example, but using different coding. So I guess that in most cases WSIF can be replaced by the newer AXIS. That would be interesting to compare the speed of initialization and processing between these two libraries. Considering that WSIF uses same Java libraries as AXIS, I would guess that they have the same speed... but you never know. So far the fastest (and smallest in size) library I tested was kSOAP, which was initially designed for mobile devices. And of course the good old deprecated MSSOAP (for VB/LotusScript), which is hard(impossible?) to compete with when it comes to dynamic invocation :)



From WSIF FAQ:
1.3 3. What are the differences between WSIF and Axis?
Axis is an implementation of SOAP. It includes on the server-side infrastructure for
deploying web service implementations and then routing SOAP messages between
clients and those implementations. It also implements the JAX-RPC specification for
invoking SOAP services. WSIF is similar to the client piece of Axis, in that it is used
for invoking services. However, WSIF's API is WSDL-driven and protocol
independent; it allows protocol-specific code ("providers") to be plugged in. For
invoking SOAP services, WSIF is in fact packaged with an Axis provider, that uses
Axis APIs (i.e. JAX-RPC) to do the invocation. So WSIF operates at a more abstract
level than Axis.

Saturday, August 12, 2006

Send a screenshot in Skype vs Sametime

Similar to "send a screenshot" feature in Sametime, now it is possible to send a screenshot in Skype too. Maybe Techsmith (the creator of the plugin) were inspired by that new cool feature in Sametime :)
It's not as seamless integrated as in Sametime and the picture is sent as a file instead of as an embedded image, but it's still usefull.
Read more here and see an instructional video.

Here is how it looks in Sametime:


Technorati: Skype Sametime

Wednesday, August 09, 2006

Making simultaneous AJAX requests

During creation of Sametime Web Contact I had to create functionality which process simultaneously 2 web requests: the first request is continiously looping and fetching updates from server-side and the second request is triggered on-demand upon user's actions (send message, change status) and is executed only once. Both are done in asynchronous mode in order to not block the web browser.
Here is an example of how I implemented it:


<script>
var scriptpath="test2.html";
var default_parameters="par1=aaa&par2=bb&par3=ccc";
var stopLooping=false;

function initHTTP(){
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla
http_request = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Your web browser is not compatible');
return false;
}

return http_request;
}


function makeAsyncRequestLoop(parameters) {
if(stopLooping==false){
if (parameters=="") parameters=default_parameters;
var http_request1=initHTTP();
http_request1.onreadystatechange = function() { readyhandler(http_request1, true); };
http_request1.open('POST', scriptpath, true);
http_request1.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request1.setRequestHeader("Content-length", parameters.length);
http_request1.setRequestHeader("Connection", "Keep-Alive");
http_request1.send(parameters);
}

}
function makeAsyncRequestOnce(parameters){
var http_request2=initHTTP();
http_request2.onreadystatechange = function() { readyhandler(http_request2, false); };
http_request2.open('POST', scriptpath, true);
http_request2.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request2.setRequestHeader("Content-length", parameters.length);
http_request2.setRequestHeader("Connection", "Keep-Alive");
http_request2.send(parameters);
}

function readyhandler(http_requestobj, fetchloop) {
if (http_requestobj.readyState == 4){
if (http_requestobj.status == 200) {
document.getElementById("test").innerHTML=(new Date().getTime())+" "+http_requestobj.responseText;
if(fetchloop==false) alert((new Date().getTime())+" "+http_requestobj.responseText)
}
if(fetchloop==true) {
makeAsyncRequestLoop(default_parameters); //request same web page again
}
}
}

function startLoop(){
stopLooping=false;
makeAsyncRequestLoop(default_parameters);
}
function stopLoop(){
stopLooping=true;
}
function customRequest(param){
makeAsyncRequestOnce(param);
}
</script>

<input type="Button" name="Start" value="Start" onClick="startLoop()">
<input type="Button" name="Stop" value="Stop" onClick="stopLoop()"><br><br>
<input type="Button" name="Custom" value="Custom" onClick="customRequest('p1=abc&p2=cde')">
<br><br><br>
<div id="test"></div>


If you test the code, you will see that the fetch loop continues getting new data even when the alert box is being shown.

Warning: IE and Firefox can handle only 2 concurrent connections to the same server. The third connection will get queued until one of the previous connections are released. So if you send 2 requests which take 2 minutes to accomplish, the third request will be queued for 2 minutes until processed. This little "feature" took me 2 days to realize.


Technorati:

Tuesday, August 08, 2006

Address Book on server? Nah, not for l33t D0m1n0 developerz!

I have found a rather old but still interesting article in The View written by Page Nix. The article shows how Domino applications can have it's own "Address Book" for validating user's login. The main usage area of the application is in web databases where database responsible person wants to quickly add new users and there is no possibility to add these new users to server's (secondary) Address Book. The responsible person can simply create a new user directly in the database.LotusScript agent is used to verify if the login credentials provided by user match the credentials saved in the user document, and if they match the agent sets a cookie to user's browser containing a "session id".
So far I could not find any obvious security risks with this approach. Groups and ACL Roles will not work without additional programming, but in many cases it's not needed.

Demo application is included in the article.

Tuesday, August 01, 2006

White nights in Stockholm

In the middle of June you can experience white nights in Stockholm. It's dark for only 2.5 hours: from 00 to 02:30 o'clock. Even when it's gets dark, it never gets compeletely dark, you can without problems see everything as if it was 23 o'clock and not kl 01. I think that 21th June is the longest daylight day of the year, so I was 1 day late.

I have a LotusScript application which interacts with webcamera using Windows API and can take pictures and movies at scheduled times. So I put the webcam on the balcony for the whole night 22 June-23 June and recorded the process of getting dark outside and then getting light again.
As the webcam does not work well when it's dark, I made also a reference shot at 01 o'clock (the darkest time) with an ordinary digital camera.

Here is a Flash movie I composed from the taken images. Click the image to open the movie.


Here is a reference shot at 01 o'clock (click to view full size):




P.S. I will later publish the Lotus Notes application I used for taking webcam pictures. It can be used to spy on your Lotus Notes users if they have a webcam :)

Wednesday, July 26, 2006

AJAX-based Sametime client. Beta release soon.

Finally an alternative to STLinks. No Java, ActiveX or other plug-ins required.

Botstation Technologies will soon release a web-based client for Sametime messaging.
In difference to STLinks, this client does not require Java or ActiveX components installed on the user's computer.

With STAJAX users can pick online people from their buddy list and start interacting with them through text chat. Users can also change their own online status. More features might be included in the final release.

The client-side of the solution consists of a single HTML file which contains JavaScript and CSS. The background logic is done in a servlet. The servlet can be run in Tomcat, Domino, Websphere and other servlet engines. Client uses AJAX technology for data exchange with servlet and generates very little network traffic. Updates of messages sent to web client from other web clients and stand-alone Sametime clients are almost instanteneous. As the client is HTML-based, it is easy to change it's GUI and add/remove functionality. Same JavaScript functions can be called from Flash applications.

Here comes a screenshot of beta release taken in Firefox:
Sametime AJAX
Click image to view full size

Saturday, July 22, 2006

Free 10-week AJAX Programming Course

In this online course, learn the basic concepts of AJAX and how to use the various AJAX frameworks and toolkits like Dojo, jMaki, Google Web, and AJAX-enabled JavaServer Faces components.
The 1st session will start from August 4th, 2006.
http://www.javapassion.com/ajaxcodecamp/

Thursday, July 20, 2006

Mobile client for Sametime

Lotus Sametime 7.5 is expected to be available in the third quarter of 2006. Mobile support for Lotus Sametime is expected to support RIM BlackBerry, Nokia and Windows Mobile devices with expected availability in the fourth quarter of 2006. Integration with Microsoft SharePoint, Outlook 2000 and above and Office XP and above is expected at the beginning of 2007.

http://www-03.ibm.com/press/us/en/pressrelease/19882.wss

Wednesday, July 19, 2006

One of the differences in Java features between Notes R7 and Notes R6

After testing one of my Java applications in Notes/Domino R7 I discovered that it handled some of the Java operations differently than in Notes R6. The difference caused an error and could potentially lead to crash.

The old code was something similar to this:

MyClass MyObjects = new MyClass();
Document doc = MyObjects.db.getDocumentByUNID(unid32)


db is a public variable declared in MyClass. "MyObjects.db" is a valid object and is accessible from the code. The only thing that doesn't work is getDocumentByUNID function. This have however worked without problems in Notes R5 and R6.

The solution is to declare the database object in the same scope where you call the getDocumentByUNID function.

Database db = session.getDatabase(servername, dbpath);
Document doc = db.getDocumentByUNID(unid32)

Tuesday, July 18, 2006

Sametime 7.5 client released again

Sametime 7.5 client can now be downloaded again. Here is a link (thanks to vowe.net): http://stdemo75.dfw.ibm.com/stcenter.nsf/WebDownloads?OpenView
The download size is 52 MB, but the installation went surprisinglty fast. To use the demo server and download the client, you can register here: http://stdemo75.dfw.ibm.com/

Problems I encountered during the first 10 minutes:
1)During the installation, the default Sametime server(stdemo3.dfw.ibm.com) is suggested automatically, but when the program is started I had to enter it manually again (stdemo75.dfw.ibm.com) because the server field was empty.
2)When the client is started for the first time, it asks to enter the name of my Sametime community... errrhhh.. Sametime what?? Community? Give me a break, you are lucky if I know my login name! I left that field empty and it worked fine.
3)The client uses Swedish language (OS language) for all menues and configurations, though I chose English in the settings (File-Settings-Language ..or whatever it is in English) and restarted the client.
4) I could not find how to switch to another username. Took me 5 minutes to figure out that this can be done by hmmm... removing current password (username can not be removed), thus causing client to ask again for a password, where I have a chance to reset user. It asked if I want to remove the current buddylist, I sensed that it would not dare to remove it from the server and called the bluff.
5) When I tried to add a new contact and typed "andrei k", it did not presented the list of matching contacts, I had to input the full name "Andrei Kouvchinnikov"

Other than these 5 things, I have nothing to complain at yet.

Some useful features in 7.5 client:
* You can change fonts and colors of the text parts of the message.
* You can use smiley pictures.
* You can insert screen captures directly into chat window.
* Time stamps for messages in chat window is rather usefull.
* Spell check of the message.
* Connect to several sametime servers at once.

I tried to test voice chat functionality, but it lloks like demo server does not support it, as the option to start a voice chat is missing. Will try later on another server. Here is a link to one post which has more info about voice chats: http://www-03.ibm.com/developerworks/blogs/page/InsideLotus?entry=sametime_sunday_s_click_to

Friday, July 07, 2006

Lotus Notes Java agent for consuming a Web Service

Here comes a little addition to the tutorial I wrote for IBM developerWorks. Tutorial has several example of using MSSOAP from LotusScript, but no examples of service consumer as Java agent. So here comes a Java consumer created from code in the WSIF stand-alone example.
There are several other frameworks to call Web Services from Java, some of them are loading much faster than WSIF and Apache SOAP, but WSIF is very easy to use. Take a look at kSOAP if you want a faster initial loading.

Here is the database with the example agent: http://www.botstation.com/download/WebservicesR7.zip

How to setup the example:
1) Download WSIF framework and unzip it
2) Copy all JAR files from the WSIF's \lib directory into Notes's \jvm\lib\ext directory.
3) Copy the example database into data\ws\ catalog.
4) Open the database, do "Preview in web browser" . Then choose Actions menu and run "javaconsumer" agent.
You will see the output of the agent in the Java debug console window.

Start Notes client without typing password

In some situations it is required to start Notes automatically without entering the password. Such situation can be locally running agents on a Notes client. Changing password to empty string is often not a good solution for different reasons.

But there is a solution for this problem. Using extpwd example from Domino C API toolkit it is possible to accomplish this task.

I've compiled the example and you can try it on your Notes client.
http://www.botstation.com/download/notesnopass.zip

Steps to setup the solution:

1) Copy nextpwd.dll to the Notes program directory.
2) Create a file called password.txt in the notes\data directory and type the Notes password there.
3) Add line EXTMGR_ADDINS=extpwd to notes.ini

Now when you start Notes client, it will not ask you for password.

Tuesday, June 20, 2006

Solution for Java error "native library c:\test.dll already loaded in another classloader while loading driver MyDriver"

"java.lang.UnsatisfiedLinkError: Native Library C:\test.dll already loaded in another classloader" can happen in Lotus Notes/Domino when Java agents or libraries use native calls to Windows DLL files.
What was strange about this error is that the same Java scriptlibrary worked fine in Java agent, but not in LS2J LotusScript agent.

I guess the error happens because the JAR file (the one which calls the DLL) is automatically detached at run-time and gets a new filename each time, which confuses JVM. With pure Java agents this behaviour might be different and the error does not occur.

Anyway, here is the solution:
Instead of including JAR files directly into the Java agent/scriptlibrary, put them into Notes's classpath.

Monday, June 19, 2006

Jumping with a parachute

I was watching "Rocky & Drago" documentary today on TV6. One of the missions the 2 actors got was a tandem jump with a parachute from 4000 meters height.

I did a tandem jump for 1 year ago so I want to share my experience of skydiving :)
Many people think that they are going to be afraid of the height, specially in the moment when they jump out. This is partially true, but shouldn't bother 97% of the people. Here is what happens: When you jumped out of the plane, you can see that the ground is very far away and it's going to get a loooong while to get there. This is rather calming. And actually you do not notice that you move towards the ground because the height is too high to be able to estimate the distance to the ground and speed of the fall. So you will not see a big difference if you are at 4000 meters or at 1000 meters. At 800-1000 meters you can begin suspecting that you are getting closer to the ground. At this moment the parachute opens. You understand that you are still falling, but now you can estimate the speed of the fall and you see that the speed is not dangerous.

The only thing I worried about was that I totally depended on the instructor who was strapped with me on my back. I mean maybe he was very upset over something today and decided to take his last jump. The other thing I worried about was that when the parachute opens, the sudden pull upwards can cause the strapping between me and instructor to burst. But nothing of this happened, otherwise you won't read this post :)

BUT.. I have a warning to you: if your ears hurt when you fly airplane (because of air pressure changes), consult with the instructor before deciding to jump, and get ear-plugs. I got a terrible ear-ache during the jump, which ruined this fantastic experience. I guess in some cases it can lead to serious injuries.
You can also get a slight head ache because of the turbulence.

Wednesday, June 14, 2006

Can you crack Da Andrei code?

Test your logic skills by solving this puzzle! If you solve it you will see a message which can change your life!



Click the image to come to the secret page!

Monday, June 12, 2006

Make incorrectly populated fields blink on web

This tip shows how to make fields with incorrect values to blink with blue and red colors. The correctness of a field is verified against field's expected value.

blinking fields



click image to view in full size

Formula for the first computed field: @If(Field1="This field has correct value";"color:black";"color:blue; font-weight: bold")

Formula for the second computed field: @If(Field2="This field has correct value";"color:black";"color:blue; font-weight: bold")


Code on Form (remove space in tags):

< div id="field1" style="< Computed Value >">FIELD1< /div >
< div id="field2" style="< Computed Value >">FIELD2< /div >
< div id="field3" style="< Computed Value >">FIELD3< /div >

< script >
checkfield('field1');
checkfield('field2');
checkfield('field3');
< /script >



Code in JSHeader:

function blinkme(fldid) {
var fld=document.all[fldid];
if (fld.style.color=="red"){
fld.style.color="blue";
}else{
fld.style.color="red";
}
mytime=setTimeout("blinkme('"+fldid+"')",800);
}
function checkfield(fldid){
var fld=document.all[fldid];
if(fld.style.color=="blue"){
mytime=setTimeout("blinkme('"+fldid+"')",800);
}
}

Sunday, June 11, 2006

Validating numeric fields in Javascript

Unless you use "Punctuated at thousands" field property of number fields, you can use following:
isnumeric=parseFloat(tmp)==(tmp*1)

But if you must have "Punctuated at thousands" property, the above code will not work properly.
For example, 20 000,00 is not the same as 20000,00.
The "space" character in the number is not a regular space, but a special separator. It's ASCII code is 160. This special character makes the validation code above work incorrectly.

Here is how you can validate such field without changing it's properties:

Code to put in onBlur event of the field:
isNumber(this, "Product Price"); // pass field handle and field title

Code to put on Form or in JSHeader:
< script >
function isNumber(obj, title){
if(typeof obj=="undefined" || obj.value.length==0){
return true;
}
tmp="";i=0;
sText=obj.value.replace(".", ","); //replace dot to comma, which is decimal separator
for(i=0; i <= sText.length; i++){
if(sText.charAt(i).length!=0){
if(sText.charCodeAt(i)!=160 && sText.charCodeAt(i)!=32){ // remove thousands space and regular space
tmp=tmp+sText.substring(i,i+1);
}
}
}
obj.value=tmp;
tmp=tmp.replace(",", ".").replace(" ", ""); //replace dot to comma and remove space
res=(parseFloat(tmp)==(tmp*1));
if(res==false){
alert(title+" field must be numeric!");
obj.focus();
};
return res;
}
< /script >

Friday, June 09, 2006

Blogging by phone

When you absolutely MUST create a blog post but has NO access to Internet, there is a solution! You can make a phone call and leave a message which gets posted to your blog!

Blogger.com is a partner with Audioblogger.com. Audioblogger.com allows to save voice messages as blog posts in Blogger.com. They are saved as MP3 files. To access audioblogger, login to your Blogger account and on the "Edit Profile" page click "audio clips" link. You will get a phone number in USA which you can call and leave a voice message. This message will be posted to your ordinary Blogger blog.
Not sure if this audio blog post is compatible with podcasting software.
Next time I will test bloggin from email and from a mobile device. Looks like text and photos can be posted from cell phones to Blogger.

Steps to post a voice message to Blogger:

1. Call the number
(Listen very carefully to the Voice Prompts)
2. Enter your Primary Number
3. Enter your PIN, press #
4. Record your post, Press #
5. Press 1 to post, 2 to review, 3 to re-record.

Thursday, June 08, 2006

Create web charts from LotusScript agents. An easy way. And cool.

Thomas Adrian in his blog shows how to create a web-based chart without using any image files, by simply printing out DHTML from the agent.

Creating charts has never been easier before!



http://notessidan.se/A55B53/blogg.nsf/plink/TADN-6QET46

Old pictures from Lotus Evolution seminar

Just found a webpage I've created for 4-6 months ago with pictures from Lotus Evolution seminar in Stockholm.

YOu can see the pictures and 2 videos here:
http://www.dominokonsult.se/lotusevolution.html

Wednesday, June 07, 2006

Run two instances of Skype

Originally posted here.

Same tip can be used to start multiple instances of other programs.


The only way to run 2 instances of Skype presently is:

On a Windows OS you can run another Skype instance at the same time if you start the second with another Windows user account. Example
1. Make sure you have another user account (login) for your Windows.
2. Right click the Skype icon and select "Run as..."
3. On the next screen click "The following user:" and select one different from the one you are currently logged in as on your computer.
4. Voila - another Skype opening which can be used independently from your first Skype instance. You can even make calls between them on the same computer



Additional tip from JP White.

To help automate the 'run as' trick you can create a second desktop icon for Skype and modify its properties. Click the advanced button and check the box 'run with different credentials'. After clicking on the modified icon it will ask you to sign in as another user. Changing the icon graphic also helps ensures you click on the correct icon.

Tuesday, June 06, 2006

Scan papers directly from Lotus Notes code

Dmitrij Vojtushin in his blog shares LotusScript code to scan papers and attach the scanned picture to a Notes document. Looks like it works in both UI and background code.

Here is a short example:
Sub Initialize
' Scan paper page to clipboard and then paste to Body
Call TWAIN_AcquireToClipboard(0,0)
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = workspace.CurrentDocument
Call uidoc.GotoField( "Body" )
Call uidoc.Paste
End Sub

http://my.opera.com/LotusDomiNotes/blog/show.dml/144710

IBM DeveloperWorks article about AJAX

In "Using AJAX to manipulate Lotus Notes documents" article written by Joachim Dagerot you can see how to use AJAX in Domino databases. Included example shows how to update To-Do list in a Domino database using an agent. The agent receives data through a HTTP request and performs the requested action on a document. The document is found in the database by it's ID.

http://www-128.ibm.com/developerworks/lotus/library/domino-ajax/

Sunday, June 04, 2006

Sleep function in LotusScript

If you want to pause script execution in LotusScript, yuo can use Sleep function. You might want to do it if you need to wait until external operation completes.

Syntax:
Sleep n

Where n is a number of seconds.

If you want to pause for less than 1 second, use following:
Sleep 0.2 ' pause for 200ms

Another good function to use in conjunction with Sleep is DoEvents. Using DoEvents in code allows you to stop looping code with Ctrl+Break keyboard command. Without it Notes client is often not responsible to break command.
Documentation says that Doevents and Yield functions are same, but in my experience DoEvents works much better... at least in older versions of Notes.

Call MyObject.SendExternalMessageDLL("message")
While Not MyObject.Status=2
sleep 0.1
DoEvents
Wend

POST data to Domino agent using AJAX

Many people on Domino forums ask about getting data from LotusScript agent without refreshing the page, as if it was a pure javascript function call. It is possible with AJAX, here is an example and a live demo.

This example sends text located in a DIV tag on a web page to a LotusScript agent and updates the DIV element with response data received back from the agent.


Live example


Sub Initialize

< script >
var http_request = false;
function makePOSTRequest(url, parameters) {
http_request = false;
if (window.XMLHttpRequest) { // Mozilla
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}

http_request.onreadystatechange = GetResponse;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}

function GetResponse() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
result = http_request.responseText;
document.getElementById('test').innerHTML = result;
} else {
alert('There was a problem with the request.');
}
}
}

function GetAgentData(txtdata) {
var poststr = txtdata; //encodeURI(txtdata);
makePOSTRequest('/test.nsf/postagent?openagent', poststr);
}
< /script >



-------------- LOTUSSCRIPT AGENT ---------------------
Sub Initialize
Dim session As New NotesSession
Dim doc As NotesDocument
Set doc=session.DocumentContext
req=doc.Request_Content(0)
For x=Len(req) To 1 Step -1
tmp=tmp+Mid(req,x,1)
Next
Print tmp
End Sub

Funny story

The local bar was so sure that its bartender was the strongest man around that they offered a standing $1,000 bet. The bartender would squeeze a lemon until all the juice ran into a glass, and hand the lemon to a patron. Anyone who could squeeze one more drop of juice out would win the money.
Many people had tried over time (weightlifters, longshoremen, etc.) but nobody could do it. One day this scrawny little man came into the bar, wearing thick glasses and a polyester suit, and said in a tiny squeaky voice “I’d like to try the bet.”

After the laughter had died down, the bartender said OK, grabbed a lemon, and squeezed away. Then he handed the wrinkled remains of the rind to the little man. But the crowd’s laughter turned to total silence as the man clenched his fist around the lemon and six drops fell into the glass.

As the crowd cheered, the bartender paid the $1,000 and asked the little man, “What do you do for a living? Are you a lumberjack, a weightlifter, what?”

The man replied, "I work for the IRS."

Saturday, May 27, 2006

Microsoft.XMLHTTP and cached data

Once I had a problem with Microsoft.XMLHTTP object. It used cached results from previous fetch.
I solved the problem by appending a unique parameter to the URL, which caused the object to fetch the new result each time.
Something like this:
strUrl="http://server.com/servlet/GetData?docid=25C6&unique="+cstr(timer())


----------------------------

Sub Initialize
Dim oHTTP As Variant
Dim strUrl As String
Dim strReturn As String

strUrl = "http://server.com/servlet/GetData?docid=25C6&unique="+cstr(timer())

Set oHTTP = CreateObject("Microsoft.XMLHTTP")
oHTTP.open "GET", strUrl, False, "", ""
oHTTP.send("")
strReturn = oHTTP.responseText
Set oHTTP = Nothing
msgbox strReturn
End Sub

NotesDXLExporter export fails on document with attachment

This is from an my answer to a post on Notes.net.
The problem was that NotesDXLExporter failed to export document in UI to XML if there was an attachment in the document, even if the document was manually saved in UI.


I could reproduce this error.
It happens under following conditions:
a)create a new mail document, add attachment to it, save the document but do not close it. Run the code (agent action or form button).
b)open an existing mail document, add attachment to it, save the document without closing it. Run the code.

It happens only with attachments, adding an inline picture does not generate the error. Triggering a LS agent to perform export results in same error.

Once you closed and re-opened the document, everything works fine until you add a new attachment.

Maybe some antivirus attachment control operations can make Notes think that attachment is new even on "old" documents, but I could not test this.

I could however make the DXLExporter work by programmatically re-opening the document, I guess it's the only solution:


Sub Click(Source As Button)
Dim session As New notessession
Dim doc As notesdocument
Set ws=New NotesUIWorkspace
Set uidoc = ws.CurrentDocument
Set doc = uidoc.Document
Call uidoc.save
Call uidoc.close

Set ws=New NotesUIWorkspace
Set uidoc=ws.editdocument(False, doc)
Set doc = uidoc.Document
Set dxle = session.CreateDXLExporter
Msgbox dxle.Export(doc)
Msgbox dxle.Log
End Sub

Thursday, May 18, 2006

Skype pricing for calls in USA

Skype announced that until December 31, all calls from SkypeOut users living in USA and Canada users to landline AND mobile phones in the USA/Canada are totally free. Unfortunately calls from other countries are priced according to standard rates.
I wonder how soon US Skype accounts will be available for sale on the Ebay. I would guess that many European and Asian companies and private persons would be happy to get those free unlimited calls. As Skype uses IP-number verification for location of the caller, this can be difficult.

Netgear has created a special Skype Wi-Fi phone. It looks like a regular cell phone, but only can make calls using Skype protocoll from Wi-Fi places which does not require logging in. As I understood "looging in" in this case means providing username and password to Wi-Fi net provider using web browser interface. As phone supports WEP, it should be possible to use at home and at most other places. Looks like the price is about 60 USD.
http://tools.netgear.com/skype/

Wednesday, May 17, 2006

Using Media Player object in Lotus Notes mail documents

Watch Flash movie describing how to
use Media Player object in Lotus Notes documents

Lotus Domino and PHP

Read my latest article on IBM DeveloperWorks about PHP interface to data stored in Domino.
There is also a live demo of reading Domino email from PHP. Same demo is available as download.
I also compiled php_notes.dll file which is needed for native API calls from PHP to Notes. For some reason I could not find the compiled version anbywhere on the Internet.

Article: http://www-128.ibm.com/developerworks/lotus/library/domino-php/

Live demo: http://www.botstation.com/phpdomino/main.php

Stylesheets for web tables

Just today found a web site with a lot of tabel stylesheets.
Looks interesting, will try later to apply them to Domino tables.
http://icant.co.uk/csstablegallery/index.php

Tuesday, April 25, 2006

Gasoline prises in US vs Sweden

Today I found a video on MSN which shows prises of gasoline (bensin) in the USA. The current price is 3$ for a gallon.

1 gallon is 3.8 liters.
1$ is 7.6 SEK (Swedish crowns).
So the price of 1 liter gasoline counted in SEK is: (3 / 3.8) * 7.6 = 6

The current price of gasoline in Sweden is 12 SEK/liter, which makes the gasoline price in the US twice as cheap as in Sweden.

Historical price rise is about the same for both coutries: about 50% up during last 3 years, maybe slightly higher rise in the US.


http://video.msn.com/v/us/v.htm?g=942c87fb-acd7-4150-acf2-d3573072c9ff&t=s2&f=06/64&p=hotvideo_energy

Monday, April 24, 2006

Very fast import from MS Excel to Lotus Notes using LotusScript

Original location: Fast import from Excel to Notes

This LotusScript agent has very high performance. It can read 10000 cells in just 1 second, compared to reading cell-by-cell which would take several minutes.



Sub Initialize
'This agent imports records from excel to Notes. It uses Range method which makes it very fast.
'Copyright Botstation (www.botstation.com)

Dim session As New NotesSession
Dim db As NotesDatabase
Dim xlApp As Variant, xlsheet As Variant, xlwb As Variant, xlrange As Variant
Dim x As Integer
Dim y As Integer

Dim filename As String, currentvalue As String
Dim rowsatonce As Integer, cnt As Integer
Dim DataArray

Set db=session.CurrentDatabase
Set xlApp = CreateObject("Excel.Application")

xlApp.Visible = True 'Excel program is visible to see what is happening

Set xlwb=xlApp.Workbooks.Open("C:\test.xls")
Set xlsheet =xlwb.Worksheets(1)

actRows=1000 'process 1000 rows
actColumns=5 'process 5 columns

Redim DataArray(actRows, actColumns) As String
DataArray=xlsheet.Range("A1").Resize(actRows, actColumns).Value 'get sheet area of 5*1000 size

For x=1 To actRows
For y=1 To actColumns
currentvalue=Cstr(DataArray(x,y))
tmp=tmp+" "+currentvalue
Next
tmp=tmp+" "+Chr(10)
Next

Msgbox tmp

End Sub



Implementation of putting array values into notes documents is left as an exercise to the reader :)

Sametime for iSeries How to Install Sametime and Add It to a Domino Server

Just found a technote on how to install Sametime on iSeries(AS400). Actually it's more like an article than a regular technote. I had the link as icon on my Windows Desktop for about a year, so today was it's lucky day.
The technote has some black-green screenshots for AS400 lovers :)

Here is the link:
http://www-1.ibm.com/support/docview.wss?rs=0&uid=swg21085821

Take also a look at common problems for Sametime on iSeries, the same problems apply to other OS:
http://www-1.ibm.com/support/docview.wss?rs=477&context=SSKTXQ&q=1108423&uid=swg21108423&loc=en_US&cs=utf-8&lang=en

And one more useful technote:
Changing IP Address or Hostname After Adding Sametime
http://www-1.ibm.com/support/docview.wss?rs=0&uid=swg21099966

Saturday, April 22, 2006

Sametime Bot instructional video and configuration program

I've created a VB program which helps to configure Botstation Sametime Bot. The problem with current configuration is that person installing the Bot must change in BAT-file and in INI-file some customer-specific values, such as server name and login info. It is not very difficult, but several people evaluating the Bot expressed their desire to make the configuration easier. With this new configuration program they do not need to care about what file to open and which variales to change. They don't even need to read the instructions. This will hopefully make many users happy.

I am also planning to create an instructional screen capture video in Flash. To be more precise, several videos: one for each topic. The topics will be:
-Installing Bot
-Configuring Bot
-Creating new Pattern Answer "from scratch"
-Creating new Agent Answer "from scratch"
Each video will be about 2 minutes long, hopefully even with speaker voice, if I find some native English speaker.

Friday, April 14, 2006

Sametime Bot

Lean, mean Sametime machine is ready to serve you!
New version of Botstation Sametime Bot is released today and the most important improvement is better support for running agents on local Notes client.
You can now also spcify another ID file and password to login with, instead of using the last user's ID.

Sametime Bot http://www.botstation.com/products/stbot/about.php

Free 30-day trial version is available for download

Technorati:

Notes Error "Can't run a private agent belonging to someone else"

If you get "Can't run a private agent belonging to someone else" error when you trigger a Lotus Notes agent from your Java application, make sure that the agent is initiated in the same thread as it's parent Database. Looks like you can't simply get agent object from another thread without getting it through it's parent database object. Well, you actually get the valid object but the agent can not start. This applies only to local calls, not to DIIOP. And it looks that sometimes it can work anyway.
You might ask why would you have separate sessions/threads in the first place? There are many reasons for that, especially in large applications where Domino objects might have been initiated in different classes.

Incorrect:
class ClassA{
Session s = null;
Database db = null;
Agent agent = null;
NotesThread.sinitThread();
s = NotesFactory.createSession();
db=s.getDatabase(null, "mydb.nsf");
agent = db.getAgent("agent123");
// NotesThread.stermThread(); //Notes thread is still running!
}

class ClassB{
NotesThread.sinitThread();
Agent agent=classA.agent; //this is valid call and we do get valid agent object!
agent.run(); //here we get error "Can't run a private agent belonging to someone else"
NotesThread.stermThread();
}


Correct:
class ClassA{
Session s = null;
Database mydb = null;
NotesThread.sinitThread();
s = NotesFactory.createSession();
db=s.getDatabase(null, "mydb.nsf");
// NotesThread.stermThread(); //Notes thread is still running!
}

class ClassB{
NotesThread.sinitThread();
Agent agent=classA.mydb.getAgent("agent123");
agent.run(); //agent gets triggered without error
NotesThread.stermThread();
}

Wednesday, April 12, 2006

A minimum WinXP Install

Found an article about what files can be deleted from Windows XP without considerably affecting the functionality. Not sure if it applies in all cases, and haven't tested it by myself yet, but it sounds interesting.

Here is a list of directories which according to the article can be deleted:

C:\windows\apppatch C:\windows\inf C:\windows\system\ (surprise!!!)
C:\windows\msagent C:\windows\help C:\windows\ime\ (depending on the language)
C:\windows\srchasst C:\windows\mui C:\windows\temp C:\windows\debug C:\windows\tasks C:\windows\registration C:\windows\pchealth C:\windows\installer C:\Windows\system32\catroot C:\Windows\system32\catroot2 C:\Windows\system32\wbem C:\Windows\system32\dllclache C:\Windows\system32\setup C:\Windows\system32\npp C:\Windows\system32\spool C:\Windows\system32\inetsrv C:\Windows\system32\ime C:\Windows\system32\com C:\Windows\system32\1033 C:\Windows\system32\usmt C:\Windows\system32\mui C:\Windows\system32\oobe C:\Windows\system32\xircom C:\Windows\system32\restore C:\Windows\system32\macromed
Source: http://www.xxcopy.com/xxcopy80.htm

Here is another related WinXP article: http://www.sapiensbryan.com/index.php/winxp-minimum-system-requirements/

Monday, April 10, 2006

Running servlets in Lotus Domino 6

To run servlets in R6 you must do following:
1)In Domino Directory (NAB) open the server's document and in the "Internet Protocols\Domino Web Engine" tab there is "Java Servlets" section. There you choose "Domino Servlet Manager" as Java servlet support.
2)Put servlet's class file into servlets directory (domino\servlet) on your Domino server.
3)Put Java libraries used by servlet (if any needed) to jvm\lib\ext directory in Domino, e.g. C:\Lotus6Server\Domino\jvm\lib\ext

Now your servlet should be able to start. You can test it by calling it by it's file name, e.g.: http://myserver.com/servlet/helloworld
Note that you do not specify ".class" file extension when you call the servlet.

If it does not work, restart the Domino server and even better restart the whole computer just to be sure :)

Saturday, April 08, 2006

Lotus Domino is Exchange, SQL Server, Access, Visual Basic, and IIS all wrapped together

Read the whole article

What Is Lotus Notes?
by Julian Robichaux
revision 1.1

For as long as I've been working with Lotus Notes, people have asked me, "Just what the heck is Lotus Notes anyway?" That has always been a difficult question to answer, because there are no equivalent products to compare it to. A typical conversation will go something like this:


"Does it do e-mail?"
"Yes."
"So it's like Exchange, right?"
"Only in the sense that it's an e-mail system. It's actually primarily a database system that happens to have built-in e-mail functionality."
"Okay, so it's like SQL or Oracle or something."
"No, it's not a relational database system like those are. It's more of a flattened data structure."
"What's that?"
"Probably nothing you should worry about. It's a database."
"Okay, so how do I manipulate the data? Write an Access front-end or something?"
"No, that's all built-in to the client. It's also got support for several programming languages, and a web server component that allows you to access the data from a web browser."
"Then it's like Exchange, SQL Server, Access, Visual Basic, and IIS all wrapped together?"
"Sort of. But it's packaged so that you don't see all those separate components individually. That's what makes it such a powerful workflow application."
"I don't think I understand..."
"I know. I think I'll have to show you some sample applications."

Read the whole article

Friday, March 24, 2006

overture/yahoo ads network has serious cancer and will not survive the operation

Today I opened the MSN Adcenter account.
Currently MSN is showing 40% of all ads from it's own Adcenter and 60% from the Yahoo/Overture ad network.
The problem with Yahoo ads is that they are pretty much useless if you live outside of the USA. Yahoo simply can not deliver the amount of traffic you need unless you open a SEPARATE account for each country. And you must wait for a week to get your ads approved. And believe me, 70% of your ads gets disapproved, if the page you point your ad link does not directly relate to the words in the ad. Does Yahoo think that they know better than me where I want to send visitor who click on my ads?
Sure Yahoo might have higher conversion rate, but who cares about it when they can not deliver the traffic? 100% conversion from 0 visitors is still 0.
Yahoo's ad center interface is very confusing and non-intuitive.

So far I found 1 downside on MSN Adcenter: keywords must be approved before showing them in search. Not sure yet how long it takes to get them approved.

Friday, March 17, 2006

Mess with the best...

I was watching the movie "Hackers" today on TV and noticed an interesting Swedish subtitle translation of expression "Mess with the best, die like the rest". It was "Ge dig på eliten och dö i skiten", which translated word by word is "Attack the elite and die in shit" .. or more rhyming "Fight with elite and die like shite".

For those who don't know, in Sweden all foreign movies are shown in original language and at the bottom of the screen you can read Swedish subtitles.
On children cartoons voice is usually replaced to Swedish language though. Stupid kids.. learn to read!

Excel is a virus?

According to this article McAfee antivirus counts Excel as a virus. Personally I think Excel is a pretty good program :)

An error in McAfee's virus definition file released Friday morning caused the company's consumer and enterprise antivirus products to flag Microsoft's Excel, as well as other applications on users' PCs, as a virus called W95/CTX....

Thursday, March 16, 2006

Login to Sametime without using username and password

I am working at 3 new features to Sametime Agent (STAgent):
1) Login to Sametime server from LotusScript run Notes client using Token instead of username/password
2) Login to Sametime server from LotusScript run in web browser using Token instead of username/password
3) Login to Sametime server from LotusScript as Anonymous user

The first feature is the most interesting as it allows to run STAgent without having to provide username and password, which can have numereous advantages when SAmetime actions are trigger manually by user.

A new quote from the great Homer Simpson

I can't take HIS money. I can't print my OWN money. I've to work for money. Why don't I just lie down and die?
(from the episode where Homer allows Marge to date Artie for one weekend)

Thursday, March 09, 2006

Lean,mean DB2 synchronizing machine!

What is faster than LEI and cheaper than DECS? It's Botstation's SQL123 application which was released as alpha version today.
Synchronisation speed: 1000 records per second.

Here is a short Flash presentation of how it works:
http://www.botstation.com/downloads/other/sql123_flashdemo.zip


/Andrei
http://www.botstation.com/domino_products.php

Wednesday, March 08, 2006

Sametime awareness without Java applet

Sametime awareness without Java applet can be of course done with Sametime Agent STAgent using servlet interface.

STAgent can be easily adjusted to return an icon showing user's status when you call it with URL like this: http://stserver.company.com/servlet/stagent_servlet?type=status&user=John+Doe

Lotusphere comes to you

I was attending "Lotusphere comes to you" conferance in Stockholm today. Ed Brill was the first speaker. Then there were sessions about Sametime, Workplace and Portlets.
I forgot my digital camera at home so I di no pictures. There were too dark to make pictures with camera in the mobile phone.

I really liked the Sametime session. Interesting feature I haven't seen before is that with Sametime 7.5 client you can take a screenshot of selected part of the screen and automatically send it to the chat partner. Very useful for sharing information.

Would need to test if my Sametime applications (Sametime Bot and Sametime Agents) still work in Sametime 7.5.