TexasSwede
texasswede@gmail.com
  • About this blog
  • My Website
  • My Resume
  • XML Export Tool
  • Photos

Lotusscript Class for generating PDF files using N2PDF

Posted on November 13, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

To make it easy to implement N2PDF in my applications/agents, I created a simple class, which I put in a script library called Class.PDF. Most of the code for teh actual PDF generation was taken straight from the example provided with the product.

In addition to the actual PDF creation, I also added functions to send the PDF file to a physical printer, and to send the PDF file to our internal document imaging system. I have removed the code for the latter, as it is very specialized code, calling a custom COM object we built, etc.

To send the PDF file to the printer, Acrobat Reader 9.0 is installed on the server (or client, depending on where the code is being executed). Due to limitations in AcroRD32.exe (it is not closing after it finish printing), I am using Acrobat Wrapper (AcroWrap.exe) from bioPDF.
You may also notice that I check two environment variables, this is to detect if the code is running on a 32-bit or 64-bit version of Windows.

I can not take credit for the ShellAndWait() function, I downloaded the code long ago from somewhere. It is used instead of the LotusScript Shell() function, and it will sit and wait until the called program finished executing before it continues.

Option Public
Option Declare
%INCLUDE "N2PDFDEF.SCR"

' *** Used for ShellAndWait()
Type STARTUPINFO
	cb As Long
	lpReserved As String
	lpDesktop As String
	lpTitle As String
	dwX As Long
	dwY As Long
	dwXSize As Long
	dwYSize As Long
	dwXCountChars As Long
	dwYCountChars As Long
	dwFillAttribute As Long
	dwFlags As Long
	wShowWindow As Integer
	cbReserved2 As Integer
	lpReserved2 As Long
	hStdInput As Long
	hStdOutput As Long
	hStdError As Long
End Type

' *** Used for ShellAndWait()
Type PROCESS_INFORMATION
	hProcess As Long
	hThread As Long
	dwProcessID As Long
	dwThreadID As Long
End Type


' *** Used for ShellAndWait()
Declare Function WaitForSingleObject Lib "kernel32" _
(Byval hHandle As Long, Byval dwMilliseconds As Long) As Long
Declare Function CreateProcessA Lib "kernel32" _
(Byval lpApplicationName As Long, Byval lpCommandLine As String, _
Byval lpProcessAttributes As Long, Byval lpThreadAttributes As Long, _
Byval bInheritHandles As Long, Byval dwCreationFlags As Long, _
Byval lpEnvironment As Long, Byval lpCurrentDirectory As Long, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION) As Long
Declare Function CloseHandle Lib "kernel32" _
(Byval hObject As Long) As Long
Const NORMAL_PRIORITY_CLASS = &H20&
Const INFINITE = -1&	
Const tmpPath = "C:\N2PDF\"	' Directory to store files in


' *** Main class to create and print PDF files
Class PDF
	Private JobID As Long
	Private IsOnServer As Integer
	Public PrinterName As String
	Public testmode As Integer
	
	Public Sub New()
		Dim session As New NotesSession
		Dim txtrow As String
		Dim cmd As String
		Dim res As Integer
		' *** Fix registry settings for Acrobat 9.0 to not shrink/fit page
		Open tmpPath & "AcrobatSettings.reg" For Output As #1
		Print #1, "Windows Registry Editor Version 5.00"
		Print #1, ""
		Print #1, "[HKEY_CURRENT_USER\Software\Adobe\Acrobat Reader\9.0\AVGeneral]"
		Print #1, |"bprintExpandToFit"=dword:00000000|
		Print #1, |"iprintScaling"=dword:00000001|
		Close #1
		cmd = |regedit /s | & tmpPath & |AcrobatSettings.reg|
		res =  ShellAndWaitFunc(cmd)
		Kill tmpPath & "AcrobatSettings.reg"
		Me.IsOnServer = session.IsOnServer()	' True if code is running on server
		If InitN2PDF() = False Then
			Call printmsg( "Failed to initialize N2PDF. Exiting.")			
			Exit Sub
		End If
		testmode = False
	End Sub

	
	Sub Delete
		' *** Destructor
	End Sub

	
	' *** This function print to console on server but display message box if running in client
	Private Sub PrintMsg(text As String)
		If Me.IsOnServer Then
			Print text
		Else 
			Msgbox text,,"Class.PDF:" & Getthreadinfo(LSI_THREAD_CALLPROC)
		End If
	End Sub

	
	Private Function InitN2PDF() As Integer
		Me.JobID = N2PDFInit (0)
		If ( Me.JobID < 0 ) Then	' Make sure N2PDF was initialized successfully
			InitN2PDF = False
			Exit Function
		End If
		' *** Set N2PDF options
		Call N2PDFSetGlobalOption( N2PDFGLOBALOPTION_SHOW_MESSAGES, _
		N2PDFVALUE_False,"" )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_SYSTEM_LAUNCH_VIEWER, N2PDFVALUE_FALSE, "" )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_NOTES_LINK_DOC_MODE, N2PDFVALUE_NOTES_LINK_MODE_IMAGE_LINK, "" )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_PDF_COMPRESSION_MODE, N2PDFVALUE_COMPRESSION_DEFLATE, "" )
		Call N2PDFSetOption ( Me.JobID, _ 
		N2PDFOPTION_PARAGRAPH_FONT_NAME, "Arial", N2PDFVALUE_DEFAULT_PARAGRAPH_NAME )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_PARAGRAPH_FONT_SIZE, "8", N2PDFVALUE_DEFAULT_PARAGRAPH_NAME )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_PARAGRAPH_FONT_COLOR, N2PDFVALUE_COLOR_BLACK, _
		N2PDFVALUE_DEFAULT_PARAGRAPH_NAME )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_FORMAT_DELETE_TRAILING_SPACE, N2PDFVALUE_True, "" )
		Call N2PDFSetOption ( Me.JobID, _
		N2PDFOPTION_PAGE_FORMAT_STANDARD,N2PDFVALUE_PAGEFORMAT_LETTER, "" )		
		Call N2PDFSetOption ( Me.JobID, N2PDFOPTION_EXPORT_TABLE_GAP, "1", "" )
		InitN2PDF = True
	End Function

	
	Public Function AddDocToPDF(doc As NotesDocument)
		' *** Add doc to the PDF we are processing. 
		' *** Use trailing CRLF to avoid blank page at the end
		Call N2PDFAddRTContent ( JobID, N2PDFVALUE_CONTENT_BODY, _
		N2PDFVALUE_CRLF_AFTER, doc.ParentDatabase.Server, _
		doc.ParentDatabase.FilePath, doc.UniversalID, "")
	End Function

	
	Public Sub AddPageBreak()
		Call N2PDFAddContent( Me.JobID, N2PDFVALUE_CONTENT_BODY, _
		N2PDFVALUE_PAGEBREAK_AFTER," " )
	End Sub

	
	Public Sub AddLineBreak()
		Call N2PDFAddContent( Me.JobID, N2PDFVALUE_CONTENT_BODY, _
		N2PDFVALUE_CRLF_AFTER," " )
	End Sub

	
	Public Function CreatePDF(outfile As String)
		If Fulltrim(outfile) = "" Then
			Call PrintMsg("No filename provided provided for [outfile].")
			Exit Function
		End If
		Call N2PDFProcess ( Me.JobID, outfile, 0 )
	End Function
	
	
	Public Sub SetPrinter(printername As String)
		Me.PrinterName = printername
	End Sub
	

	Public Function PrintPDF(Byval filename As String) As Integer
		Dim printer As String
		Dim prg As String
		Dim cmd As String
		Dim success As Long
		Dim dirtemp As String
		Dim path As String 
		
		If Environ$("ProgramFiles(x86)") <> "" Then
			path = Environ$("ProgramFiles(x86)")
		Elseif Environ$("ProgramFiles") <> "" Then
			path = Environ$("ProgramFiles")
		Else
			path = "c:\Program Files"
		End If	
		dirtemp = path & "\bioPDF\Acrobat Wrapper\"
		prg = dirtemp & "acrowrap.exe"
		If Dir$(prg) = "" Then
			' *** File was  not found, we can't print to printer without it.
			Print "Failed to locate acrowrap.exe (bioPDF Acrobat Wrapper)."
			PrintPDF = -1
			Exit Function
		End If		
		prg = |"| & prg & |"|	' Add double quotes around file name
		If Me.PrinterName<>"" Then
			printer = " " & Me.PrinterName
		Else
			printer = ""	' This will use default printer
		End If
		filename = |"| & filename & |"|
		cmd = prg & | /t | & filename & printer
		success = ShellAndWaitFunc(cmd)
		PrintPDF = Cint(success)
	End Function
	

	Private Function ShellAndWaitFunc(Byval RunProg As String) As Long
		Dim RetVal As Long
		Dim RetvalClose As Long
		Dim proc As PROCESS_INFORMATION
		Dim StartInf As STARTUPINFO
		StartInf.cb = Len(StartInf)
	     ' Execute the given path
		RetVal = CreateProcessA(0&, RunProg, 0&, 0&, 1&, _
		NORMAL_PRIORITY_CLASS, 0&, 0&, StartInf, proc)
	     ' Disable this app until the shelled one is done
		RetVal = WaitForSingleObject(proc.hProcess, INFINITE)
		RetValClose = CloseHandle(proc.hProcess)
		ShellAndWaitFunc = RetValClose
	End Function
End Class

Here is a small code snippet showing how to call the class. Enjoy!

Option Public
Option Declare
Use "Class.PDF"

Dim pdf As PDF
Dim success As Integer
dim PDFfile As String

...set doc here
PDFfile = doc.UniversalID & ".pdf"	' Create file name based on document UNID

Set pdf = New PDF()		' Initialize PDF object
pdf.TestMode = False	' Set PDF object to test mode if desired
pdf.PrinterName ="CRP_Accounting_Color"	' Set the printer name for printouts
Call pdf.AddDocToPDF( doc )
Call pdf.CreatePDF( PDFfile )
success= pdf.PrintPDF( PDFfile )
If success = 1 Then
	MsgBox "Successfully printed " & PDFfile & "."
End If

 

I am not Amish…

Posted on November 12, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

Earlier this week, Peter Presnell compared Notes/Domino developers who are not embracing Xpages as being Amish.

I don´t agree. Sure, Xpages have been around for about 2 years, but it was not until recently (8.5.2 released back in September) that they were supported in the client and actually useful. I think that most enterprise customers who are using Notes/Domino actually use the Notes client to a large extent. At least my network admin and CIO want to wait about 4-6 months from a release until even thinking about putting it in production. Especially now with the 8.0 and 8.5 code streams, where we seen all kinds of strange bugs. Code that used to work is suddenly not returning the expected information, etc.

 

My company is currently migrating the last few users off Notes 5.0.12 and onto 7.0.2. Yes, you read it right. It was not until about a year ago I was allowed to install Domino Designer 7.0 and start using any new functionality from that version. All our servers are on 7.0.2 now, and we have one 8.5 server, and that only because of Traveller.
I think the plan is to move the servers to 8.5 sometime during the first half of next year, and the users perhaps towards the end of 2011.

So why not install 8.5.2 everywhere? Because the standard machine only got 512 MB memory. Two memory slots, with now two 256 MB memory sticks. And they are not going to upgrade the memory on 400 computers. So what we do is migrating all users to Citrix, and then it will be easy to upgrade and run 8.5. But it won’t happen overnight.
 

All our applications are for the Notes client, so until Notes 8.5.2 is installed everywhere, Xpages is not useful to me (at work). I have enough other things to do at work, I don´t have the time to play with Xpages there. I don´t even have Domino Designer 8.5 installed there.
At home I have the latest version installed, but I have had limited time to play around and learn Xpages. That does not make me "Domish", as Peter calls it. I focus on technologies I currently can use. I will look at Xpages if I have the spare time, but it is not high priority.

 

"Circus Acts of a Dying Operating System"

Posted on November 11, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

Back when I was a journalist for Computer Sweden, I got to interview some very interesting people from the IT industry. One time, I think it was in 1996 around the time Windows NT 4.0 was released, Microsoft had a press meeting at their Stockholm office. We were perhaps 8-10 journalists total who got to meet Jim Allchin, then in charge of the development of NT.

After the regular PR fluff, slides and presentations, there was time for questions. I eventually asked about a feature in the the then newly released OS/2 Warp 4.0, namely that you could run virtual DOS sessions in OS/2. I think you could even set different sessions to emulate different versions of DOS (I am old enough to remember when certain programs needed particular DOS versions to work). You could even run Windows 3.0 in a virtual session in OS/2.

Today we are all doing this, using tools like Parallels and VMware. But Jim Allchin was not impressed: "Circus acts of a dying operating system" was his comment. For the rest of the interview he glared at me every time he mentioned Windows NT in comparison with OS/2…

 

Did They Make Better Programs In The Past?

Posted on November 11, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

This morningimageI blogged about processing a photo to look like a painting, and I mentioned Picture Publisher, a graphics program from Micrografx (later purchased by Corel).

I started using Picture Publisher sometime around 1993-94, and I was using it until a little over a year ago, when I finally switched from Picture Publisher 10 (released in 2001, if I recall correctly) to Photoshop CS2.

So why did I use such an old product? Perhaps because Picture Publisher did it´s job, and it did it well. It had all the functions I could ask for at that time, and I could do pretty much anything The program also did use few resources and very little memory, it was fast and also was easy to use.
What it was lacking was layers and other features that the competing programs eventually got. In the lat 90´s, Micrografx stopped developing the product, and it was not until 2000/2001 the two final versions (9.0 and 10) came out. If Picture Publisher would have had layers and a couple of other features, I would probably still been using it. I wonder what it would have looked like if Corel had not stopped developing it”…”

 

Cam2PC_screen The second "old" program I am using is Cam2PC from NaboCorp. Version 4.6.1 came out in October 2007. It is a very competent program, and as the name indicates, it is used to transfer pictures from a digital camera to the PC. This it is doing better than any other program I found. The pictures are organized by date, and during download you can enter a description to be included in the folder name. Simple editing is built in, like cropping, sharpening, red-eye removal and levels/color. In the paid version (there is a limited shareware/trial version) you can burn pictures to CD/DVD, provided you have Nero Burning ROM installed, and you can mail pictures directly from the program. Well worth the $20 it cost.
I have not found any program to replace it, including Picasa, F-Spotor Shotwell.

 

So did they simply make better programs a few years ago? Perhaps. Or am I just in my comfort zone and don´t want to learn new things? I don´t think so. I love getting new software, but they have to add something. If they have less functionality than an older program, why should I switch? It´s a little bit like the switch from Notes to Exchange. If it is working and doing the job, why switch to a product that have less functionality, just because it is newer? It is not until the current program is lacking functionality that you need you start thinking about switching.

 

My Favorite Free Icon Set

Posted on November 11, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

In my Notes and Domino applications I have standardized on one icon set. That one is the FamFamFam Silk web icons. They have a muted and nice look that match the Notes client (especially Notes 8.x), and they are free.

Here are some sample icons:

FamFamFam_iconsample 

Go take a look if you haven’t done so already!

 

Agent Logging – Budget Style

Posted on November 10, 2010 by Karl-Henry Martinsson Posted in IBM/Lotus, Lotusscript, Notes/Domino, Programming Leave a comment

At my work, we had several issues/needs related to agents in different Domino databases. I tried to come up with a quick and lean solution, that gave us the functionality we needed, nothing more and nothing less. Yes, I am aware of Julian Robichaux’s excellent OpenLog. But we had some needs that I did not feel were addressed in that project.

What I wanted was a database where the agents could be documented, and also where the log data was stored. So I created a Agent Log database where one document is stored per agent. The form let me document the actions of the agent, as well as what server it is running on, in what database, when it is triggered, etc. When the document is opened, I also read the last time the agent was run and if the agent is enabled or not.

This is a sample document for an agent. It is scheduled to run at 11am every day:

AgentLog_Doc

 

This is what the actual database looks like.

AgentLog

I plan to release the database on OpenNTF.org when I get the time.

 

Nothing complicated this far. The next step was to create a small script library, doing the actual logging. I created a script library called Class.AgentLog with the following code:

Public Const THREAD_TICKS=6
Public Const THREAD_TICKS_PER_SEC=7

Class AgentLog
	Private session As NotesSession
	Private logdb As NotesDatabase
	Private agentdoc As NotesDocument   ' Main doc in Agent Log db
	Private logdoc As NotesDocument
	Private running As Integer
	Private tstart As Long              ' Ticks at start
	Private tend As Long                ' Ticks at end
	Private tps As Long                 ' Ticks per second (system dependant)
	
	Public Sub New( agentname As String )
		Dim view As NotesView
		Dim key As String
		running = True
		tstart = GetThreadInfo( THREAD_TICKS )
		tps = GetThreadInfo( THREAD_TICKS_PER_SEC )
		Set session = New NotesSession
		Set logdb = New NotesDatabase( session.CurrentDatabase.Server, "IT/AgentLog.nsf" )
		Set view = logdb.GetView( "(LookupAgent)" )
		If agentname = "" Then
			agentname = session.CurrentAgent.Name
		End If
		key = session.CurrentDatabase.FilePath & "~" & agentname
		Set agentdoc = view.GetDocumentByKey( key )
		If agentdoc Is Nothing Then
			Print "AgentLog: Failed to locate agent document for " & agentname & "."
			Exit Sub
		End If
		Set logdoc = New NotesDocument( logdb )
		logdoc.Form = "LogItem"
		Call logdoc.MakeResponse( agentdoc )
		Call logdoc.ReplaceItemValue("AgentName", agentname )
		Call logdoc.ReplaceItemValue("StartTime", Now() )
		If session.IsOnServer = True Then
			Call logdoc.ReplaceItemValue("RunBy", session.CurrentDatabase.Server )
		Else
			Call logdoc.ReplaceItemValue("RunBy", session.CommonUserName )
		End If
	End Sub
	
	Public Sub Finish()
		running = False
	End Sub
	
	Public Sub Terminate()
		Dim seconds As Integer
		If logdoc Is Nothing Then
			Exit Sub
		End If
		tend = GetThreadInfo( THREAD_TICKS )
		seconds = (tend - tstart) / tps
		Call logdoc.ReplaceItemValue("EndTime", Now() )
		Call logdoc.ReplaceItemValue("Seconds", seconds )
		If running = True Then ' Check if not terminated gracefully
			Call logdoc.ReplaceItemValue("Terminated", "Yes" )
		End If
		Call logdoc.Save(True,True)
	End Sub

End Class

All code goes in the (Declarations) section of the script library.
There are a few things to notice. I actually make each log item a child (response) document to the main document. By doing this, I can easily later create reports for each agent about all the times it was executed, etc.
When the object is instantiated, a blank string is normally passed. This will set the agent name variable to the actual agent name. The agent name is listed in the agent log document. If for some reason you want to use a different agent name in the document (e.g. the agent is a manually triggered agent called AdminUpdateSelectedDocuments and you want it listed just as UpdateSelectedDocuments).

 

The only thing left now is to update every agent you want to log as follows:

In the (Options) section:

Use "Class.AgentLog"

In the (Declarations) section:

Dim agent As AgentLog

In the Initialize event, I put one line at the beginning and one right at the end. The first line instantiate the agent log object and. set a flag indicating that the agent is running. The second line will clear that flag, so the final function knows that the agent ended gracefully.

Sub Initialize
 Set agent = New AgentLog("")
 ' *** Do stuff here
 Call agent.Finish()
End Sub

The last thing is to add one line to the Terminate event. This line is where the logging is actually done. If the flag running is set, we know the agent was terminated before it actually reached the end.

Sub Terminate
 Call agent.Terminate()
End Sub

Happy logging!

Paintings from Photos

Posted on November 10, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

A few months ago, I talked to someone about printing photos in large format on canvas. When I got home, I located a packet of "canvas inkjet paper" I purchased many years ago, but never used up. It is a pretty cool paper, it is thick and has a structure like a painting but is of course blank.

At first I though about just printing a photo, but then I remembered something. Back in my pre-Photoshop days when I used Picture Publisher from Micrografx, the software had filters that emulated a few different drawing styles, including charcoal, water color and oil painting. However, there is nothing native in Photoshop giving the same capability.

I did some searching, looking for oil painting actions, plugins or filters. Finally if found Dynamic Auto Painter (DAP), a $49.95 program that sounded promising. I downloaded the demo version and tested it. I was amazed, this was a really neat program. Perhaps a narrow niche, but worth the money. What the program does is to analyze the picture and then redraw it from scratch, using different brushes and tools, in many layers. Just like I imagine a real painter would do it. There are about a dozen or so different filters, and the user can change parameters like color palette, detail level, how fine brushes to use, etc.

I picked a few photos and ran them through Dynamic Auto Painter, and below is the result. The photo of the Waxholm ferry is not the same as the one I processed (I don’t have access to it at the moment), but they were taken just a few seconds apart.

BigBen_original BigBen_illustrator 

 

Waxholm_original Waxholm_benson 

 

I printed the picture of the ferry on the 11" x 8.5" canvas paper, and it turned out really good. My biggest issue now is to find more paper like that, as the manufacturer seems to have closed business.

More examples of pictures I processed using Dynamic Auto Painter can be found here.

 

Ubuntu 10.10 nuked my boot loader

Posted on October 17, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

ubuntu-splash-transparent Last Sunday I downloaded the latest version of Ubunu, 10.10 (Maverick Meerkat). I then decided to use the Update Manager in Ubuntu to upgrade the version I was running (10.04) in-place. The download was nice and fast, I was asked a few questions, and then it was time to restart the computer. Instead of the GRUB menu, I was met by a message that some file was missing and I ended up at a rescue prompt. Nice. The boot loaded had been nuked/damaged. Seems like I am not the only one”…”

Finally, after some Google searches and some other tricks (including using a bootable CD with Clonezilla and Gparted I happened to have laying around), I was able to boot on my Windows XP partition. I got the Ubuntu CD burned, as I had been foolish enough to just download the ISO file but not burn it, as I assumed the install would work.

Eventually I got GRUB restored on my computer. Then I proceeded with copying the few files I had on my Ubuntu partition to one of my other drives, and reinstalled Ubuntu from scratch, so I had a nice new install. I actually first installed on top of the existing version, juts to try that out. That worked, but none of the new software in 10.10 were installed, so I opted to start all over.

I had less problems with this version compared with previous version. Perhaps it is that i am getting used to Ubuntu, or perhaps the distribution is becoming easier to use, My network card, a Netgear WG311, is still not supported natively in Ubuntu, but by installing ndiswrapper (which comes on the CD but is not installed by default) I would use the Windows XP drivers for the card. Very slick, took just a few minutes.

I had to install the Nvidia graphics drivers separately, but again, that was easy. The tricky part was to get my left monitor (I have two older CRT monitors connected to my system) to run in a higher resolution than 640×480. After some searching through Google and editing the file /etc/X11/xorg.conf file I was able to get 1200×1024 on that screen as well.

What about Notes 8.5.2 then? I am happy to report that it was extremely simple. I downloaded the compressed .tar file from the IBM Passport Advantage site, unpacked the contents (half a dozen .deb files) to the desktop and simply right-clicked on one file at a time and opened them in the Ubuntu Software Manager, Answered a question or two, and after just a few minutes I was all set. Actually much faster than installing it on a Windows XP PC at work, which I did today. Well, a small disclaimer, my system at home got a faster processor, 3 GB memory (vs. 768 MB at work) and probably faster hard disks”…”

Over the last year, I estimate that I have been in Ubuntu about 80% of the time, and in Windows just 20%. Perhaps even less. And after I installed some additional programs this week, for example to transfer digital video from my old camcorder, I might work even more in Ubuntu. I am not ready to fully let go of Winodws, I need a particular remote control program to connect to work. Of course. Vmware or VirualBox would solve that as well.

So if you haven´t looked at Ubuntu or some other Linux distribution lately, try it out.

 

Offshoring Development — My Thoughts

Posted on October 11, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

The other day I noticed a posting on LinkedIn, in the Lotus Notes/Domino Technology group by a Joseph Roblee asking "Does anyone know of a talented offshore Domino 8.5 development group you can put me in contact with?"

I find it interesting that Mr. Roblee, who happens to live in Austin, TX, is looking at India when there are so many US developers looking for jobs”…” I wonder what his neighbors (a simple google search for his name reveals an address in Cedar Park, a suburb of Austin) would say if they were told that their nice neighbor is exporting jobs away from the US, while the country has record high unemployment.

Perhaps I will see him at Lotusphere, because surely "one of the leading Lotus Notes developers in the United States" will be there”…”

I notice that Mr. Roblee proudly tells that he got an MBA (as well as MCSE). I know a CEO who went back to school to get his MBA, and he came back with the "knowledge" that one can hire brilliant developers in India, with MBA and higher degrees, for $5/hr or similar. Is that is what is being taught in MBA trainings across the US?

There are a number of responses/comments to his posting from people who either have Indian sounding names or identify themselves as from India (as well as a few from Latvia, South Africa and some other countries). What I heard from people who actually been involved in offshore development is that the culture is very different in India. You have to be aware of that. Not oly is the actual development process different, other cultural differences also comes into play. If you are not aware of those, and have a very strong project leader, the project can easily get larger/longer/more expensive that projected.

Also, from judging at what I been reading in the past in the (now pretty dead) usenet newsgroup comp.groupware.lotus-notes.programmer (and to some lesser extent in the DeveloperWorks forums), it seems like many of the most basic questions came from people with Indian sounding names, or identifying themselves as from India. Often the question is extremely basic, or showing that the person has no clue about what Notes is or how it works. There is often a comments saying "I never programmed Notes before, but I was put in this project for a client”…”" or similar, the proceeding how to do relational lookups or similar. To me that sounds like they took on a project, and now want the very same people they just put out of a job to do the training or actual work for them”…”

I also found it very interesting that Kirankumar Nellore from Bengalure [sic!] is commenting and trying to get the business from Mr Roblee. In another Lotus-related group on LinkedIn, he asks What is difference between lotus notes normal application and composite application??. Shouldn´t a certified Notes developer and administartor (as he claim he is) know that? Or am I just setting the bar too high for what the certification indicates?

I can understand the lure for business owners to save a few dollars by developing a project in say India. But the loss for the US is greater. Americans lose their jobs, and this will eventually force the taxes to be increased for everyone to cover unemployment. The interest rates to borrow at the bank will be higher du to the increased number of foreclosures when people lose their jobs. And of course the loss of knowledge. We all know that if you don´t work with something, you get behind and lose knowledge.

So the companies makes a profit while the tax payers foot the bill. Why not add a "offshoring tax" for companies to cover the additional cost for the country? Any US-based company, or company with a major US presence (say more than 10,000 employees or more than 25% of the workforce in the US), who employs a call center or development department/company outside the US will pay an additional tax. I will leave it to the bean counters to decide the actual amount, perhaps 5% of the profit before taxes and deductions? Perhaps 10%? Since money is the only thing CEOs seem to understand, hit them where it hurts since they can´t do The Right Thing without being forced”…”

For the record, I have nothing against people from India or any other countries. But I think it is wrong to export jobs from any country when there is high unemployment.

 

Being a soccer dad

Posted on October 10, 2010 by Karl-Henry Martinsson Posted in Old Blog Post Leave a comment

My son, Erik, has taken up soccer (or football as it is known in the world outside the United States) this year. After 5 years of playing baseball, I am happy that he choose a sport where he get to move more. At first he wanted to try football (the American version, where they hold the oval shaped "ball" and run, wearing heavy padding), but his mom was not too thrilled about that. Erik quickly changed his mind and wanted to do soccer instead, as heliked watching the 2010 FIFA World Cup tournament.He loves playing soccer, andalso likesto go to the home games of FC Dallas.

His team lost the first 3 games, but won the fourth one last Sunday and tied the fifth one this past Thursday. As he and his mom lives over an hour away, I was not able to attend the first couple of games, but I went last weekend and brought my camera. I ended up taking quite a few pictures and here are a couple, mostly of Erik (number 10), I wanted to share.

 

Stack Exchange

profile for Karl-Henry Martinsson on Stack Exchange, a network of free, community-driven Q&A sites

Recent Posts

  • Domino 14 is now available
  • Domino 14 Early Access Program
  • Announced: Engage 2024
  • Integrate Node-RED with Notes and Domino
  • Notes and Domino v12 is here!

Recent Comments

  • Theo Heselmans on Announced: Engage 2024
  • Lotus Script Multi-thread Message Box [SOLVED] – Wanted Solution on ProgressBar class for Lotusscript
  • Viet Nguyen on Keep up with COVID-19 though Domino!
  • Viet Nguyen on Keep up with COVID-19 though Domino!
  • Mark Sullivan on Looking for a HP calculator? Look no further!

My Pages

  • How to write better code in Notes

Archives

  • December 2023 (1)
  • October 2023 (2)
  • September 2023 (1)
  • June 2021 (1)
  • April 2021 (2)
  • March 2021 (1)
  • August 2020 (3)
  • July 2020 (2)
  • April 2020 (2)
  • March 2020 (1)
  • December 2019 (2)
  • September 2019 (1)
  • August 2019 (2)
  • July 2019 (2)
  • June 2019 (3)
  • April 2019 (2)
  • December 2018 (1)
  • November 2018 (1)
  • October 2018 (5)
  • August 2018 (2)
  • July 2018 (3)
  • June 2018 (2)
  • May 2018 (1)
  • April 2018 (2)
  • March 2018 (1)
  • February 2018 (2)
  • January 2018 (4)
  • December 2017 (3)
  • November 2017 (2)
  • October 2017 (2)
  • September 2017 (1)
  • August 2017 (2)
  • July 2017 (6)
  • May 2017 (4)
  • February 2017 (1)
  • January 2017 (2)
  • December 2016 (2)
  • October 2016 (3)
  • September 2016 (4)
  • August 2016 (1)
  • July 2016 (2)
  • June 2016 (2)
  • May 2016 (3)
  • April 2016 (1)
  • March 2016 (4)
  • February 2016 (2)
  • January 2016 (4)
  • December 2015 (3)
  • November 2015 (2)
  • October 2015 (1)
  • September 2015 (2)
  • August 2015 (1)
  • July 2015 (5)
  • June 2015 (2)
  • April 2015 (2)
  • March 2015 (3)
  • February 2015 (2)
  • January 2015 (10)
  • December 2014 (1)
  • November 2014 (3)
  • October 2014 (3)
  • September 2014 (13)
  • August 2014 (6)
  • July 2014 (5)
  • May 2014 (3)
  • March 2014 (2)
  • January 2014 (10)
  • December 2013 (5)
  • November 2013 (2)
  • October 2013 (5)
  • September 2013 (4)
  • August 2013 (7)
  • July 2013 (3)
  • June 2013 (1)
  • May 2013 (4)
  • April 2013 (7)
  • March 2013 (8)
  • February 2013 (9)
  • January 2013 (5)
  • December 2012 (7)
  • November 2012 (13)
  • October 2012 (10)
  • September 2012 (2)
  • August 2012 (1)
  • July 2012 (1)
  • June 2012 (3)
  • May 2012 (11)
  • April 2012 (3)
  • March 2012 (2)
  • February 2012 (5)
  • January 2012 (14)
  • December 2011 (4)
  • November 2011 (7)
  • October 2011 (8)
  • August 2011 (4)
  • July 2011 (1)
  • June 2011 (2)
  • May 2011 (4)
  • April 2011 (4)
  • March 2011 (7)
  • February 2011 (5)
  • January 2011 (17)
  • December 2010 (9)
  • November 2010 (21)
  • October 2010 (4)
  • September 2010 (2)
  • July 2010 (3)
  • June 2010 (2)
  • May 2010 (3)
  • April 2010 (8)
  • March 2010 (3)
  • January 2010 (5)
  • November 2009 (4)
  • October 2009 (7)
  • September 2009 (1)
  • August 2009 (7)
  • July 2009 (1)
  • June 2009 (4)
  • May 2009 (1)
  • April 2009 (1)
  • February 2009 (1)
  • January 2009 (3)
  • December 2008 (1)
  • November 2008 (1)
  • October 2008 (7)
  • September 2008 (7)
  • August 2008 (6)
  • July 2008 (5)
  • June 2008 (2)
  • May 2008 (5)
  • April 2008 (4)
  • March 2008 (11)
  • February 2008 (10)
  • January 2008 (8)

Categories

  • AppDev (10)
  • Blogging (11)
    • WordPress (5)
  • Design (5)
    • Graphics (1)
    • UI/UX (2)
  • Featured (5)
  • Financial (2)
  • Food (5)
    • Baking (3)
    • Cooking (3)
  • Generic (11)
  • History (5)
  • Hobbies (10)
    • LEGO (4)
    • Photography (4)
  • Humor (1)
  • IBM/Lotus (178)
    • #Domino2025 (14)
    • #DominoForever (8)
    • #IBMChampion (46)
    • Administration (7)
    • Cloud (7)
    • CollabSphere (9)
    • Community (49)
    • Connect (33)
    • ConnectED (12)
    • Connections (3)
    • HCL (15)
    • HCL Master (1)
    • IBM Think (1)
    • Lotusphere (46)
    • MWLUG (25)
    • Notes/Domino (99)
      • Domino 11 (7)
    • Sametime (8)
    • Verse (14)
    • Volt (3)
    • Watson (6)
  • Life (8)
  • Microsoft (7)
    • .NET (2)
    • C# (1)
    • Visual Studio (1)
  • Movies (3)
  • Old Blog Post (259)
  • Personal (23)
  • Programming (84)
    • App Modernization (11)
    • Formula (4)
    • Lotusscript (47)
    • NetSuite (4)
      • SuiteScript (3)
    • node.js (4)
    • XPages (4)
  • Reviews (9)
  • Sci-Fi (4)
  • Software (24)
    • Flight Simulator (2)
    • Games (4)
    • Open Source (2)
    • Utilities (6)
  • Technology (37)
    • Aviation (3)
    • Calculators (2)
    • Computers (6)
    • Gadgets (7)
    • Mobile Phones (7)
    • Science (3)
    • Tablets (2)
  • Travel (7)
    • Europe (1)
    • Texas (2)
    • United States (1)
  • Uncategorized (16)
  • Web Development (50)
    • Frameworks (23)
      • Bootstrap (14)
    • HTML/CSS (12)
    • Javascript (32)
      • jQuery (23)
  • Prev
  • 1
  • …
  • 39
  • 40
  • 41
  • 42
  • 43
  • …
  • 54
  • Next

Administration

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Tracking

Creeper
MediaCreeper
  • Family Pictures
© TexasSwede 2008-2014