Stamp a barcode over a fax page received with RightFax in a Lotus Notes workflow

A company receives orders via a RightFax server and a Lotus Notes gateway put the received faxes in a mail-in database Lotus Workflow enabled.

First, we need to stamp a unique barcode (the order identifier) in each fax page, then the order is loaded in the company ERP (IBM iSeries). The data entry operator loads the order data and, with a barcode scanner, associates the order identifier to the order.

So, after the order arrives in the mail-in database the Lotus Workflow PostInitByMail_ event is triggered.

This event reads (GetHistory function) the Fax identifier from the history file attached in the mail containing the pdf fax also and save the Fax id in a notes document field.

Then it calls the BarCode java agent that stamps in each page of the attached fax the Fax ID using a barcode char. The same agent detach and remove the original pdf and attaches the bar coded one.

The received fax order workflow

The received fax order workflow

The customized PostInitByMail_ function.

You can find this function in the Script Library ‘Os Application Events‘ part of a Lotus Workflow application.

Private Function PostInitByMail_(CoverDocument As NotesDocument, MainDocument As NotesDocument, Memo As NotesDocument)

    Dim sess As New NotesSession
    Dim db As NotesDatabase
    Dim agent As NotesAgent
    Dim doc As NotesDocument
    Dim item As NotesItem
    Dim paramid As String

    Call GetHistory(MainDocument)

    Set db = sess.CurrentDatabase
    Set agent = db.GetAgent("(BarCoder)")

    paramid = MainDocument.Noteid

    Call Agent.Run(paramid)

End Function

The GetHistory function.

This function, reading the attached history.txt file,  checks also if the received fax is good (no tranmission errors).

Sub GetHistory(doc As NotesDocument)
	Dim newdocs As NotesDocumentCollection
	Dim vPath As String

	Dim txt As String
	Dim risultato As String
	Dim uniqueID As String
	Dim fileNum As Integer
	Dim positionOfChar As Long
	Dim positionOfCharUnique As Long

	Dim object As NotesEmbeddedObject
	Dim inbox As NotesView
	Dim resultItem As NotesItem

	Dim bodyItem As NotesItem
	Dim textBody As String

	If Not doc Is Nothing Then
		Set bodyItem = doc.GetFirstItem( "Body" )
		If Not( bodyItem Is Nothing ) Then
			textBody=bodyItem.Abstract(300,False, False)
			positionOfChar& = Instr(textBody, "Routing Code:")
			If positionOfChar& > 0 Then
				risultato$ =Trim(Mid(textBody, positionOfChar& + 13,4))
				doc.LineaFax = risultato$
				Call doc.Save(True,True)
			End If
		End If
		Set resultItem = doc.GetFirstItem( "RISULTATO" )
		If ( resultItem Is Nothing ) Then
			Set object = doc.GetAttachment( "history.txt" )
			If Not(Isnull(object)) Then
				vPath = SetAttachmentName(object, "")
				Call object.ExtractFile( vPath)
				fileNum% = Freefile
				Open vPath For Input As fileNum%
				Do While Not Eof(fileNum%)
					Line Input #fileNum%, txt
					positionOfChar& = Instr(txt, "Result:")
					positionOfCharUnique& = Instr(txt, "Unique ID:")
					If positionOfChar& > 0 Then
						risultato$=Trim(Mid(txt, positionOfChar + 7))
						doc.Risultato=risultato
						Call doc.Save(True,True)
					Elseif positionOfCharUnique& > 0 Then
						uniqueID$=Trim(Mid(txt, positionOfCharUnique + 10))
						uniqueID$ =Strright(uniqueID, "[FAX")
						uniqueID$ = Strleftback(uniqueID,"]")
						doc.RFUniqueID=uniqueID
						Call doc.Save(True,True)
					End If

				Loop
				Print "Parsed file " & Cstr(fileNum)
				Close fileNum%
				Kill vPath
			End If ' fine Not(Isnull(object))
		End If ' fine resultItem Is Nothing
	End If
End Sub

Some LotusScript support functions.

You can find also the useful RandomFileName function. Thanks to Breaking Par Consulting, Inc.

Function SetAttachmentName(o As Variant, dbName As String) As String
	Dim sAttachmentName As String
	Dim strSuffix As String
	Dim vTempPath As String

	vTempPath = GetSystemTempFolder()

	strSuffix = "." & Strrightback(o.Source, ".")

	sAttachmentName=RandomFileNAme(vTempPath,strSuffix)

	Print "Creating name " & sAttachmentName
	SetAttachmentName=sAttachmentName

End Function

Function RandomFileName(inpDir As String, ext As Variant) As String
   ' Pass in the name of a directory, build a random file name, make sure the file does not exist
   ' in the directory.   Note that ext can be a single string or an array of strings. If it's an array,
   ' the random file name will not match with any of the extensions and the value returned will
   ' be MISSING THE EXTENSION. If it's a single string, the random file name will not match
   ' with that extension and the FULL PATH INFORMATION will be returned.
	Dim directory As String
	Dim slash As String
	Dim checkFileName As String
	Dim fileName As String
	Dim i As Integer
	Dim num As Integer
	Dim ch As String

   ' The "ext" parameter can either be a single value or an array. Make sure the first character
   ' is a period - makes things easier later on
	If Isarray(ext) Then
		For i = Lbound(ext) To Ubound(ext)
			If ext(i) <> "" Then ' Could be looking for a blank extension, so check for that
				If Left(ext(i), 1) <> "." Then ext(i) = "." & ext(i)
			End If
		Next
	Else ' Not an array. Is a single value
		If ext <> "" Then ' Could be looking for a blank extension
			If Left(ext, 1) <> "." Then ext = "." & ext
		End If
	End If
	directory = inpDir ' We don't want to change the passed-in parm, so make a local copy of the value
	If Instr(directory, "/") = 0 And Instr(directory, "\") = 0 Then
		RandomFileName = "" ' No slashes. Unknown file system setup - return empty string
		Exit Function ' ======== EXIT ============
	End If
	If Instr(directory, "/") <> 0 And Instr(directory, "\") <> 0 Then
		RandomFileName = "" ' Both slashes. Unknown file system setup - return empty string
		Exit Function ' ======== EXIT ============
	End If
	If Instr(directory, "/") <> 0 Then slash = "/" Else slash = "\"
   ' Make sure the directory exists first
	If Right(directory, 1) <> slash Then directory = directory & slash ' Format dir so it ends in a slash
	On Error Resume Next
	checkFileName = Dir$(directory & "*.*") ' Look for something in the directory
	On Error Goto 0
	If Err <> 0 Then ' Will give a "path not found" error if the path doesn't exist
		Err = 0
		RandomFileName = ""
		Exit Function ' ======== EXIT ============
	End If
	Randomize
	fileName = "" ' Get us into the while loop
	While fileName = ""
		For i = 1 To 8 ' Random file name will have 8 characters
			If i = 1 Then num = Rnd * 52 Else num = Rnd * 62 ' starts w/ a letter, but other chars can be nums
			Select Case num
			Case 0 To 25 : fileName = fileName & Chr$(Asc("A")+num) ' 0...25 = upper case letter
			Case 26 To 51 : fileName = fileName & Chr$(Asc("a")+num-26) ' 26...52 = lower case letter
			Case 52 To 61 : fileName = fileName & Cstr(num-52) ' 52...61 = number
			End Select
		Next
		If Isarray(ext) Then
			For i = Lbound(ext) To Ubound(ext)
				checkFileName = Dir$(directory & fileName & ext(i)) ' See if the file exists
				If checkFileName <> "" Then ' If found, continue the while loop
					i = Ubound(ext) + 1 ' Get out of the inner For loop
					fileName = "" ' Continue the outer While loop
				End If
			Next
		Else ' Not an array - a single string was passed in
			checkFileName = Dir$(directory & fileName & ext) ' See if the file exists
			If checkFileName <> "" Then fileName = "" ' If found, continue the while loop
		End If
	Wend
   ' At this point, the random file name doesn't exist in the directory. To make this compatible
   ' with the old version of the function, return the full path if only one extension was passed
   ' in. If multiple extensions were passed in, return the directory plus file name (w/ no extension)
	If Isarray(ext) Then
		RandomFileName = directory & fileName
	Else
		RandomFileName = directory & fileName & ext
	End If
End Function

Function GetSystemTempFolder As String
	Dim session As New NotesSession
	Select Case session.Platform
	Case "Macintosh", "Linux", "UNIX"
		GetSystemTempFolder = "/tmp"
	Case "Windows/32", "Windows/64"
		GetSystemTempFolder = Environ("TEMP")
	Case Else
		Print "GetSystemTempFolder: Unsupported platform '" & session.Platform & "'."
	End Select
End Function

The BarCoder Lotus Notes java agent

It uses the PDFclown java library by Stefano Chizzolini.

import lotus.domino.*;
import it.stefanochizzolini.clown.documents.Page;
import it.stefanochizzolini.clown.documents.contents.colorSpaces.DeviceRGBColor;
import it.stefanochizzolini.clown.documents.contents.composition.AlignmentXEnum;
import it.stefanochizzolini.clown.documents.contents.composition.AlignmentYEnum;
import it.stefanochizzolini.clown.documents.contents.composition.PrimitiveFilter;
import it.stefanochizzolini.clown.documents.contents.fonts.Font;

import it.stefanochizzolini.clown.files.File;
import it.stefanochizzolini.clown.files.SerializationModeEnum;
import it.stefanochizzolini.clown.tools.PageStamper;

import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.io.FileNotFoundException;

import java.util.Date;

public class JavaAgent extends AgentBase {

	public void NotesMain() {

		try {
		    Session session = getSession();
		    AgentContext agentContext = session.getAgentContext();
		    Log log = session.createLog("BarCoder");
		    log.openNotesLog("<nomeserver>", "<AgentLogDatabase>.nsf");
		    Date startdate = new Date ();

		    log.logAction("BarCoder (" + System.getProperty("java.version") + ") started at " + startdate.toString ());

		    String npDir = session.getEnvironmentString("Directory", true);
		    if (npDir == null)
		    	log.logError(0,"No Directory entry in notes.ini");

			Agent ag1 = agentContext.getCurrentAgent();
	                String paramid =  ag1.getParameterDocID();

			Database db = agentContext.getCurrentDatabase();
			lotus.domino.Document doc = db.getDocumentByID(paramid);
			EmbeddedObject obj = doc.getAttachment("Images.PDF");
			if (obj != null) {
				log.logAction("   Found " + obj.getName() +
		                " in \"" + doc.getItemValueString(
		                "RFUNIQUEID") + "\"");
				System.out.println("Found " + obj.getName() +
                " in \"" + doc.getItemValueString(
                "RFUNIQUEID") + "\"" );
				if (obj.getType() == EmbeddedObject.EMBED_ATTACHMENT) {
						String basePath = System.getProperty ("java.io.tmpdir");
						String rfuniqueid = doc.getItemValueString("RFUNIQUEID");
						String tmp_file = "T_" + rfuniqueid + ".pdf";
						obj.extractFile(basePath + tmp_file);

						log.logAction("   File extracted to " + basePath  + tmp_file);
						File file = new File(basePath  + tmp_file);
				              it.stefanochizzolini.clown.documents.Document document = file.getDocument();

						// 2. Stamp the document!
						stamp(document, rfuniqueid, npDir);
						System.out.println("Stamped " + rfuniqueid );
						log.logAction("    Stamped " + rfuniqueid);

						System.out.println("try to serialize to file name " + basePath + rfuniqueid + ".pdf" );
						SerializationModeEnum serializationMode = SerializationModeEnum.Incremental;
						file.writeTo(basePath + rfuniqueid + ".pdf", serializationMode);
						System.out.println("Serialized " + rfuniqueid );
						log.logAction("    Serialized " + rfuniqueid);

						obj.remove();
						System.out.println("Removed " + rfuniqueid );
						log.logAction("    Removed " + rfuniqueid);
						RichTextItem body = (RichTextItem)doc.getFirstItem("Body");
						if (body == null) {
							 body = doc.createRichTextItem("Body");

						}

						body.embedObject(EmbeddedObject.EMBED_ATTACHMENT, "", basePath + rfuniqueid + ".pdf", rfuniqueid + ".pdf");
						System.out.println("Embedded " + rfuniqueid );
						log.logAction("    Embedded " + rfuniqueid);

						doc.save(true, true);
						System.out.println("Doc saved " + rfuniqueid );
						log.logAction("    Doc saved " + rfuniqueid);

						file.close();

						java.io.File barcodedFile = new java.io.File(basePath + rfuniqueid + ".pdf");
						java.io.File tbarcodedFile = new java.io.File(basePath + tmp_file);
						if (barcodedFile.delete()) {
							System.out.println("deleted the file with barcode " +barcodedFile.getAbsolutePath() );
							log.logAction("    deleted the file with barcode " + rfuniqueid + ".pdf");
						}else {
							System.out.println("not deleted the file with barcode " +barcodedFile.getAbsolutePath() );
							log.logAction("    not deleted the file with barcode " + rfuniqueid + ".pdf");
						}
						if (tbarcodedFile.delete()) {
							System.out.println("deleted the orginal file " +tbarcodedFile.getAbsolutePath() );
							log.logAction("    deleted the original file " + basePath + tmp_file);
						}else {
							System.out.println("not deleted the original file " +tbarcodedFile.getAbsolutePath() );
							log.logAction("    not deleted the original file " + basePath + tmp_file);
						}
					}
			}
			log.logAction("BarCoder ended at " + startdate.toString ());
			log.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	private void stamp(it.stefanochizzolini.clown.documents.Document document, String stampID, String dominoDir ) throws FileNotFoundException  	  {
		// 1. Instantiate the stamper!
		/* NOTE: The PageStamper is optimized for dealing with pages. */
		PageStamper stamper = new PageStamper();

		// 2. ...
		Font Font3of9 = Font.get(
				document,
				dominoDir + java.io.File.separator + "IDAutomationHC39M.ttf"
		);

		DeviceRGBColor redColor = new DeviceRGBColor(1, 0, 0);
		//DeviceRGBColor whiteColor = new DeviceRGBColor(1, 1, 1);
		int margin = 20;
		for(Page page : document.getPages())
		{
			// 2.1. Associate the page to the stamper!
			stamper.setPage(page);

			// 2.2. Stamping the page number on the foreground...
			{
				PrimitiveFilter foreground = stamper.getForeground();

				foreground.setFont(Font3of9,8);
				foreground.setFillColor(redColor);

				Dimension2D pageSize = page.getSize();

				foreground.showText(
						"*" + stampID + "*",
						new Point2D.Double( pageSize.getWidth() - margin, pageSize.getHeight() - 2),
						AlignmentXEnum.Right,
						AlignmentYEnum.Bottom,
						0
				);
				foreground.showText(
						"*" + stampID + "*",
						new Point2D.Double( 32, 32),
						AlignmentXEnum.Right,
						AlignmentYEnum.Bottom,
						90
				);
			}

			// 2.3. End the stamping!
			stamper.flush();
		}
	}
}

A sample fax page with bar code

Below a fax page with the bar code inside.

We have choose to print the same barcode in two different positions in order to avoid overlaying with some fax text.

A fax page with bar code

A fax page with bar code

4 pensieri su “Stamp a barcode over a fax page received with RightFax in a Lotus Notes workflow

  1. Pingback: Stamp a barcode over a fax page received with RightFax in a Lotus … | Latest Technology News

  2. After I originally left a comment I appear to have clicked the -Notify me when new comments are
    added- checkbox and now every time a comment is
    added I get 4 emails with the exact same comment.
    Is there an easy method you are able to remove me
    from that service? Kudos!

  3. Hi there just wanted to give you a quick heads up and
    let you know a few of the images aren’t loading correctly.
    I’m not sure why but I think its a linking issue. I’ve tried it in two different browsers
    and both show the same outcome.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *