You are viewing limited content. For full access, please sign in.

Question

Question

Workflow Apply Stamp Limitations

asked on March 6, 2018 Show version history

We are wondering with the Apply Stamp activity in LF Workflow 10.2. It seems it can only choose a public stamp. Another concern is that we made a public stamp with a Date as token. When we ran the workflow, the stamp only produced the text but the token prints %(Date) instead of the actual date. When we did it manually in the LF client, it prints the current date.

We made another public stamp without a Date token. We added the token on the workflow design and when we ran it, the stamp could not be found.

 

We are also wondering if there's a way for the Apply Stamp activity to stamp every page of the image file instead of only one specific page.

 

1 0

Replies

replied on March 6, 2018 Show version history

You can use the below code to create a SDK script activity to apply a dynamic stamp.  Make sure to add the 3 needed Import statements at the top of the activity code.  Then set your default values for the stamp in the first 7 lines of code of the Execute() function (line number 24 - 30).  You could use tokens to pass in the defaults if you wanted.

 

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.SqlClient
Imports System.Text
Imports System.Drawing ' Add
Imports System.Drawing.Imaging ' Add
Imports System.Runtime.InteropServices ' Add
Imports Laserfiche.RepositoryAccess

Namespace WorkflowActivity.Scripting.SDKScript
    '''<summary>
    '''Provides one or more methods that can be run when the workflow scripting activity is performed.
    '''</summary>
    Public Class Script1
        Inherits RAScriptClass102
        Private sErrorMsg as String = Nothing
        '''<summary>
        '''This method is run when the activity is performed.
        '''</summary>
        Protected Overrides Sub Execute()
            'Write your code here. The BoundEntryInfo property will access the entry, RASession will get the Repository Access session
            Dim sStampName As String = "ApprovedDateStamp" ' Name of stamp to apply to document.
            Dim iMaxW As Integer = 2000 ' Maximum width of stamp
            Dim iPageNumber As Integer = 1 ' Page number where stamp is applied
            Dim iStampLeft As Integer = 600 ' How far from the left edge to place the stamp
            Dim iStampTop As Integer = 50 ' How far from the top edge to place the stamp
            Dim fScale As Single = 0.3 ' Stamp scale factor
            Dim StampColor As Laserfiche.RepositoryAccess.Common.LfColor = Laserfiche.RepositoryAccess.Common.LfColor.BLUE ' Sets stamp fill color
            If BoundEntryInfo.EntryType = EntryType.Document Then
                Try
                    Dim StampImage As Bitmap = CreateStampImage(sStampName, iMaxW)
                    Dim iW As Integer = StampImage.Width
                    Dim iH As Integer = StampImage.Height
                    Using docinfo As DocumentInfo = DirectCast(BoundEntryInfo, DocumentInfo)
                        docinfo.Lock(LockType.Exclusive)
                        Dim DynamicStamp As StampInfo = New StampInfo(RASession)
                        DynamicStamp.Name = sStampName & "_temp"
                        Dim SourceByteArray() As Byte = BmpToByte(StampImage)
                        Dim StampBytes(SourceByteArray.Length - 15) As Byte
                        Array.Copy(SourceByteArray, 14, StampBytes, 0, StampBytes.Length - 1)
                        DynamicStamp.ImageData = StampBytes
                        DynamicStamp.UpdateImageData()
                        Dim BCStampAnnotation As New StampAnnotation(docinfo, iPageNumber, DynamicStamp)
                        BCStampAnnotation.Position = New Laserfiche.RepositoryAccess.Common.LfPoint(iStampLeft, iStampTop)
                        BCStampAnnotation.Color = StampColor
                        Dim StampRect As Laserfiche.RepositoryAccess.Common.LfRectangle = BCStampAnnotation.Coordinates
                        StampRect.Width = iW * fScale
                        StampRect.Height = iH * fScale
                        StampRect.Location = New Laserfiche.RepositoryAccess.Common.LfPoint(iStampLeft, iStampTop)
                        BCStampAnnotation.Coordinates = StampRect
                        docinfo.GetPageInfo(iPageNumber).AddAnnotation(BCStampAnnotation)
                        docinfo.Save()
                        docinfo.Unlock()
                    End Using
                    StampImage.Dispose()
                Catch ex As Exception
                    sErrorMsg = ex.Message
                    WorkflowApi.TrackError(ex.Message)
                End Try
            End If
            If Not String.IsNullOrEmpty(sErrorMsg) Then
                SetTokenValue("Error", sErrorMsg)
            End If
        End Sub

    Private Function BmpToByte(ByVal bmp As Bitmap) As Byte()
        Dim byteReturn() As Byte
        Using memStream As System.IO.MemoryStream = New System.IO.MemoryStream
            bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Bmp)
            byteReturn = memStream.ToArray()
        End Using
        bmp.Dispose()
        Return byteReturn
    End Function

    Private Function PublicStampList() As List(Of String)
        Dim lstReturn As New List(Of String)
        Try
            Using PublicStampInfoReader As StampInfoReader = Stamp.EnumPublicStamps(RASession)
                While PublicStampInfoReader.Read()
                    Dim CurStamp As StampInfo = PublicStampInfoReader.Item()
                    lstReturn.Add(CurStamp.Name)
                End While
            End Using
        Catch ex As Exception
            sErrorMsg = ex.Message
        End Try
        Return lstReturn
    End Function

    Private Function PersonalStampList() As List(Of String)
        Dim lstReturn As New List(Of String)
        Try
            Using PersonalStampInfoReader As StampInfoReader = Stamp.EnumPersonalStamps(RASession)
                While PersonalStampInfoReader.Read()
                    Dim CurStamp As StampInfo = PersonalStampInfoReader.Item()
                    lstReturn.Add(CurStamp.Name)
                End While
            End Using
        Catch ex As Exception
            sErrorMsg = ex.Message
        End Try
        Return lstReturn
    End Function

    Private Function StampIDbyName(ByVal sName As String) As Integer
        Dim iReturn As Integer = -1
        Try
            Using PersonalStampInfoReader As StampInfoReader = Stamp.EnumPersonalStamps(RASession)
                While PersonalStampInfoReader.Read()
                    Dim CurStamp As StampInfo = PersonalStampInfoReader.Item()
                    If CurStamp.Name = sName Then
                        iReturn = CurStamp.Id
                        Exit While
                    End If
                End While
            End Using
            If iReturn = -1 Then
                Using PublicStampInfoReader As StampInfoReader = Stamp.EnumPublicStamps(RASession)
                    While PublicStampInfoReader.Read()
                        Dim CurStamp As StampInfo = PublicStampInfoReader.Item()
                        If CurStamp.Name = sName Then
                            iReturn = CurStamp.Id
                            Exit While
                        End If
                    End While
                End Using
            End If
        Catch ex As Exception
            sErrorMsg = ex.Message
            iReturn = -1
        End Try
        Return iReturn
    End Function

    Private Function ReplaceStampTokens(ByVal StampText As String) As String
        Dim sReturn As String = StampText
        Try
            If sReturn.Contains("%(Date)") Then
                sReturn = sReturn.Replace("%(Date)", DateTime.Now.ToShortDateString)
            End If
            'If sReturn.Contains("%(Count)") Then
            '    sReturn = sReturn.Replace("%(Count)", "Count To Do")
            'End If
            'If sReturn.Contains("%(GCount)") Then
            '    sReturn = sReturn.Replace("%(GCount)", "GCount To Do")
            'End If
            If sReturn.Contains("%(UserName)") Then
                sReturn = sReturn.Replace("%(UserName)", GetTokenValue("Initiator").ToString())
            End If
            If sReturn.Contains("%(ParentName)") Then
                Dim sParentName As String
                Using Parent As FolderInfo = Folder.GetFolderInfo(BoundEntryInfo.ParentId, RASession)
                    sParentName = Parent.Name
                End Using
                sReturn = sReturn.Replace("%(ParentName)", sParentName)
            End If
            If sReturn.Contains("%(Id)") Then
                sReturn = sReturn.Replace("%(Id)", BoundEntryId.ToString())
            End If
            If sReturn.Contains("%(ParentId)") Then
                sReturn = sReturn.Replace("%(ParentId)", BoundEntryInfo.ParentId.ToString())
            End If
        Catch ex As Exception
            sErrorMsg = ex.Message
            sReturn = StampText
        End Try
        Return sReturn
    End Function

    Private Function Convert_Text_to_Image(ByVal txt As String, ByVal fontname As String, ByVal fStyle As FontStyle, ByVal ifontsize As Integer, ByVal iMaxWidth As Integer) As Bitmap
        If String.IsNullOrEmpty(txt) Then
            txt = " "
        End If
        'creating bitmap image
        Dim bmp As New Bitmap(100, 100)
        'bmp.SetResolution(300, 300)
        'FromImage method creates a new Graphics from the specified Image.
        Dim grfx As Graphics = Graphics.FromImage(bmp)
        ' Create the Font object for the image text drawing.
        Using fnt As Font = New Font(fontname, ifontsize, fStyle)
            ' Instantiating object of Bitmap image again with the correct size for the text and font.
            Dim stringSize As SizeF = grfx.MeasureString(txt, fnt)
            Dim iProjWidth As Integer = Convert.ToInt32(stringSize.Width)
            If iProjWidth > iMaxWidth Then
                iProjWidth = iMaxWidth
            End If
            bmp = New Bitmap(bmp, iProjWidth, Convert.ToInt32(stringSize.Height))
            'bmp.SetResolution(300, 300)
            grfx = Graphics.FromImage(bmp)

            'Draw Specified text with specified format
            grfx.DrawString(txt, fnt, Brushes.Black, 0, 0)
        End Using
        'font.Dispose()
        grfx.Flush()
        grfx.Dispose()
        'return Bitmap Image
        Return bmp
    End Function

    Private Function Superimpose(ByVal largeBmp As Bitmap, ByVal smallBmp As Bitmap, ByVal TopOffset As Integer, ByVal iLeftMargin As Integer) As Bitmap
        Dim g As Graphics = Graphics.FromImage(largeBmp)
        g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver
        smallBmp.MakeTransparent()
        Dim x As Integer = iLeftMargin
        Dim y As Integer = TopOffset
        g.DrawImage(smallBmp, New Point(iLeftMargin, TopOffset))
        Return largeBmp
    End Function

    Private Function ConvertToBitonal(ByVal original As Bitmap) As Bitmap
        Dim source As Bitmap = Nothing

        ' If original bitmap is not already in 32 BPP, ARGB format, then convert
        If original.PixelFormat <> PixelFormat.Format32bppArgb Then
            source = New Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb)
            source.SetResolution(original.HorizontalResolution, original.VerticalResolution)
            Using g As Graphics = Graphics.FromImage(source)
                g.DrawImageUnscaled(original, 0, 0)
            End Using
        Else
            source = original
        End If

        ' Lock source bitmap in memory
        Dim sourceData As BitmapData = source.LockBits(New Rectangle(0, 0, source.Width, source.Height), ImageLockMode.[ReadOnly], PixelFormat.Format32bppArgb)

        ' Copy image data to binary array
        Dim imageSize As Integer = sourceData.Stride * sourceData.Height
        Dim sourceBuffer As Byte() = New Byte(imageSize - 1) {}
        Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize)

        ' Unlock source bitmap
        source.UnlockBits(sourceData)

        ' Create destination bitmap
        Dim destination As New Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed)
        destination.SetResolution(original.HorizontalResolution, original.VerticalResolution)

        ' Lock destination bitmap in memory
        Dim destinationData As BitmapData = destination.LockBits(New Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.[WriteOnly], PixelFormat.Format1bppIndexed)

        ' Create destination buffer
        imageSize = destinationData.Stride * destinationData.Height
        Dim destinationBuffer As Byte() = New Byte(imageSize - 1) {}

        Dim sourceIndex As Integer = 0
        Dim destinationIndex As Integer = 0
        Dim pixelTotal As Integer = 0
        Dim destinationValue As Byte = 0
        Dim pixelValue As Integer = 128
        Dim height As Integer = source.Height
        Dim width As Integer = source.Width
        Dim threshold As Integer = 500

        ' Iterate lines
        For y As Integer = 0 To height - 1
            sourceIndex = y * sourceData.Stride
            destinationIndex = y * destinationData.Stride
            destinationValue = 0
            pixelValue = 128

            ' Iterate pixels
            For x As Integer = 0 To width - 1
                ' Compute pixel brightness (i.e. total of Red, Green, and Blue values) - Thanks murx
                '                           B                             G                              R
                pixelTotal = Convert.ToInt32(sourceBuffer(sourceIndex)) + Convert.ToInt32(sourceBuffer(sourceIndex + 1)) + Convert.ToInt32(sourceBuffer(sourceIndex + 2))
                If pixelTotal > threshold Then
                    destinationValue += CByte(pixelValue)
                End If
                If pixelValue = 1 Then
                    destinationBuffer(destinationIndex) = destinationValue
                    destinationIndex += 1
                    destinationValue = 0
                    pixelValue = 128
                Else
                    pixelValue >>= 1
                End If
                sourceIndex += 4
            Next
            If pixelValue <> 128 Then
                destinationBuffer(destinationIndex) = destinationValue
            End If
        Next

        ' Copy binary image data to destination bitmap
        Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize)

        ' Unlock destination bitmap
        destination.UnlockBits(destinationData)

        ' Dispose of source if not originally supplied bitmap
        If Not source.Equals(original) Then
            source.Dispose()
        End If
        'destination.SetResolution(300, 300)
        ' Return
        Return destination
    End Function

    Private Function CreateStampImage(ByVal sMyStampName As String, ByVal iMaxWidth As Integer) As Bitmap
        Dim MyImage As Bitmap = Nothing
        Dim sN As String = Nothing
        Dim sT As String = Nothing
        Dim iFS As Integer = 0
        Dim sF As String = Nothing
        Dim bB As Boolean = False
        Dim bI As Boolean = False
        Dim bU As Boolean = False
        Dim bS As Boolean = False
        Dim iBW As Integer = 0
        Dim iHP As Integer = 0
        Dim iVP As Integer = 0
        ' Get stamp
        Dim DynamicStamp As StampInfo = Stamp.GetInfo(StampIDbyName(sMyStampName), RASession)
        ' Add stamp properties to XML Document for parsing
        Dim xd As New Xml.XmlDocument
        If Not String.IsNullOrEmpty(DynamicStamp.CustomData) Then
            xd.LoadXml(DynamicStamp.CustomData)
            ' Get XML Element with stamp properties
            Dim xe As Xml.XmlElement = xd.DocumentElement
            ' Get xml Atributes from xml element
            Dim Attribs As Xml.XmlAttributeCollection = xe.Attributes
            ' Process xml attributes
            For Each Attrib As Xml.XmlAttribute In Attribs
                Select Case Attrib.Name
                    Case "N" ' Get Stamp Name
                        sN = Attrib.Value
                    Case "T" ' Get Stamp text
                        sT = Attrib.Value
                    Case "FS" ' Get Font Size
                        iFS = Integer.Parse(Attrib.Value)
                    Case "F" ' Get Font Name
                        sF = Attrib.Value
                        If String.IsNullOrEmpty(sF) Then sF = "Arial"
                    Case "B" ' Get Bold
                        bB = Boolean.Parse(Attrib.Value)
                    Case "I" ' Get Italic
                        bI = Boolean.Parse(Attrib.Value)
                    Case "U" ' Get Underline
                        bU = Boolean.Parse(Attrib.Value)
                    Case "S" ' Get Strikethrough
                        bS = Boolean.Parse(Attrib.Value)
                    Case "BW" ' Get Boarder Width
                        iBW = Integer.Parse(Attrib.Value)
                    Case "HP" ' Get Horizontal Padding
                        iHP = Integer.Parse(Attrib.Value)
                    Case "VP" ' Get Vertical Padding
                        iVP = Integer.Parse(Attrib.Value)
                End Select
            Next

            Dim myStyle As New FontStyle
            If bB Then myStyle = myStyle Or FontStyle.Bold
            If bI Then myStyle = myStyle Or FontStyle.Italic
            If bU Then myStyle = myStyle Or FontStyle.Underline
            If bS Then myStyle = myStyle Or FontStyle.Strikeout
            Dim ImageList As New List(Of Bitmap)()
            Dim iMaxW As Integer = iMaxWidth - (iHP + iHP) - (iBW + iBW)
            Dim txtStamp As New List(Of String)
            Dim sStampT As String = ReplaceStampTokens(sT)
            ' Replace new line syntax for splitting
            sStampT = sStampT.Replace("\n", "�")
            ' Split Stamp text into individual lines
            txtStamp.AddRange(sStampT.Split("�"))
            For Each LineText As String In txtStamp
                ImageList.Add(Convert_Text_to_Image(LineText, sF, myStyle, iFS, iMaxW))
            Next
            Dim iStampH As Integer = 0
            Dim iStampW As Integer = 0
            For Each bmp As Bitmap In ImageList
                iStampH = iStampH + bmp.Height
                If bmp.Width > iStampW Then
                    iStampW = bmp.Width
                End If
            Next
            iStampH = iStampH + (iHP * 2) + (iBW * 2)
            iStampW = iStampW + (iVP * 2) + (iBW * 2)
            Dim iWritableHeight As Integer = iStampH - (iHP * 2) - (iBW * 2)
            Dim iOffset As Integer = 0
            MyImage = New Bitmap(iStampW, iStampH)
            'MyImage.SetResolution(300, 300)
            Dim MyGraphics As Graphics = Graphics.FromImage(MyImage)
            If iBW > 0 Then
                'draw a Black rectangle for boarder
                MyGraphics.FillRectangle(New SolidBrush(Color.Black), 0, 0, MyImage.Width, MyImage.Height)
                'draw a white rectangle inside the boarder
                MyGraphics.FillRectangle(New SolidBrush(Color.White), iBW, iBW, MyImage.Width - (iBW * 2), MyImage.Height - (iBW * 2))
                iOffset = iBW
            Else
                'draw a white rectangle
                MyGraphics.FillRectangle(New SolidBrush(Color.White), 0, 0, MyImage.Width, MyImage.Height)
            End If
            For Each textImage As Bitmap In ImageList
                If iWritableHeight >= ((iOffset + textImage.Height) - iBW) Then
                    MyImage = Superimpose(MyImage, textImage, iOffset, (iVP + iBW))
                    iOffset = iOffset + textImage.Height
                End If
            Next
            MyImage = ConvertToBitonal(MyImage)
        End If
        Return MyImage
    End Function

    End Class
End Namespace

Use the fScale variable to scale the size of the stamp image on the page. fScale of 1.0 is no scaling, less than 1.0 shrinks the stamp on the page and greater than 1.0 grows the stamp on the page.

2 0
replied on March 11, 2018

What programming language are you using? Is it VB?

0 0
replied on March 11, 2018 Show version history

Yes, the code above is VB.NET.  The Laserfiche Workflow script activities allow you to select either the VB.NET or C#.NET scripting language when you add it to the Designer Canvas.  

Often times when I am collaborating with another developer that is more comfortable with one language over another I will run the code through a converter like Telerik to make it easier for them to follow along...

0 0
replied on May 19, 2020

Hey Bert!  Awesome code.  After a bit of trial and error, I got it working in my application.  One issue I'm running into, though, is that my workflow has the possibility of running multiple times on a document.  I want to save the stamps from each run.  In the "Apply Stamp" activity, there is the option to cascade or replace the stamps if there is already a stamp there.  With this code, they just apply on top of each other.  Is there a way to make the stamp apply right under the previous one if there's already one there?

replied on March 14, 2018

Why not just use a text box annotation? You can put dynamic text in that, give it a border and make it  nearly identical to a stamp in presentation and functionality.

1 0
replied on March 28, 2018

Text box in Workflow will allow you to use tokens, but it limiting as far as customizing font style and font color.  Other than visual limitations the text box works great!

0 0
replied on March 6, 2018

On stamps, the text replacement of tokens is handled by the LF client.  The workflow activity has never had this functionality built into it.  To create stamps with dynamic text in workflow, you must use a SDK script activity and build it yourself.

Here is a good search to give you some history and information on this topic

0 0
replied on May 19, 2020

Hey Bert!  Awesome code.  After a bit of trial and error, I got it working in my application.  One issue I'm running into, though, is that my workflow has the possibility of running multiple times on a document.  I want to save the stamps from each run.  In the "Apply Stamp" activity, there is the option to cascade or replace the stamps if there is already a stamp there.  With this code, they just apply on top of each other.  Is there a way to make the stamp apply right under the previous one if there's already one there?

1 0
replied on May 19, 2020

It is possible, but it would require using an offset value and code to cycle through the existing stamps on the page and increasing the offset to account for each previous stamp.

0 0
replied on May 19, 2020

So after thinking about this a bit, it really does make a good addition/enhancement to the script.

To calculate the top offset (shift the stamp down), add this function to the code:

    Private Function GetTopOffset(ByRef Doc As DocumentInfo, ByVal iPage As Integer, ByVal iTop As Integer) As Integer
        Dim iResult As Integer = iTop
        Try
            Dim Page As PageInfo = Doc.GetPageInfo(iPage)
            Dim AllAnno As ICollection(Of AnnotationBase) = Page.GetAnnotations()
            For Each Anno As AnnotationBase In AllAnno
                If Anno.AnnotationType = AnnotationType.Stamp Then
                    Dim s As StampAnnotation = TryCast(Anno, StampAnnotation)
                    If s.Coordinates.Top = iResult Then
                        iResult = iResult + s.Coordinates.Height + 2
                    End If
                End If
            Next
            Dim iCount As Integer = AllAnno.Count
        Catch ex As Exception
            WorkflowApi.TrackError(ex.Message)
            iResult = iTop
        End Try
        Return iResult
    End Function

Then modify the "Execute" to account for and use the top offset like this:

        Protected Overrides Sub Execute()
            'Write your code here. The BoundEntryInfo property will access the entry, RASession will get the Repository Access session
            Dim sStampName As String = "ApprovedDateStamp" ' Name of stamp to apply to document.
            Dim iMaxW As Integer = 2000 ' Maximum width of stamp
            Dim iPageNumber As Integer = 1 ' Page number where stamp is applied
            Dim iStampLeft As Integer = 600 ' How far from the left edge to place the stamp
            Dim iStampTop As Integer = 50 ' How far from the top edge to place the stamp
            Dim fScale As Single = 0.3 ' Stamp scale factor
            Dim StampColor As Laserfiche.RepositoryAccess.Common.LfColor = Laserfiche.RepositoryAccess.Common.LfColor.BLUE ' Sets stamp fill color
            ' iTopOffset lets us shift stamp down for each one applied
            Dim iTopOffset As Integer = 0
            If BoundEntryInfo.EntryType = EntryType.Document Then
                Try
                    Dim StampImage As Bitmap = CreateStampImage(sStampName, iMaxW)
                    Dim iW As Integer = StampImage.Width
                    Dim iH As Integer = StampImage.Height
                    Using docinfo As DocumentInfo = DirectCast(BoundEntryInfo, DocumentInfo)
                        'Get the Top Offset
                        iTopOffset = GetTopOffset(docinfo, iPageNumber, iStampTop)
                        docinfo.Lock(LockType.Exclusive)
                        Dim DynamicStamp As StampInfo = New StampInfo(RASession)
                        DynamicStamp.Name = sStampName & "_temp"
                        Dim SourceByteArray() As Byte = BmpToByte(StampImage)
                        Dim StampBytes(SourceByteArray.Length - 15) As Byte
                        Array.Copy(SourceByteArray, 14, StampBytes, 0, StampBytes.Length - 1)
                        DynamicStamp.ImageData = StampBytes
                        DynamicStamp.UpdateImageData()
                        Dim BCStampAnnotation As New StampAnnotation(docinfo, iPageNumber, DynamicStamp)
                        'BCStampAnnotation.Position = New Laserfiche.RepositoryAccess.Common.LfPoint(iStampLeft, iStampTop)
                        'Create Stamp Possition using Top Offset
                        BCStampAnnotation.Position = New Laserfiche.RepositoryAccess.Common.LfPoint(iStampLeft, iTopOffset)
                        BCStampAnnotation.Color = StampColor
                        Dim StampRect As Laserfiche.RepositoryAccess.Common.LfRectangle = BCStampAnnotation.Coordinates
                        StampRect.Width = iW * fScale
                        StampRect.Height = iH * fScale
                        'StampRect.Location = New Laserfiche.RepositoryAccess.Common.LfPoint(iStampLeft, iStampTop)
                        'Set Stamp on image using Top Offset
                        StampRect.Location = New Laserfiche.RepositoryAccess.Common.LfPoint(iStampLeft, iTopOffset)
                        BCStampAnnotation.Coordinates = StampRect
                        docinfo.GetPageInfo(iPageNumber).AddAnnotation(BCStampAnnotation)
                        docinfo.Save()
                        docinfo.Unlock()
                    End Using
                    StampImage.Dispose()
                Catch ex As Exception
                    sErrorMsg = ex.Message
                    WorkflowApi.TrackError(ex.Message)
                End Try
            End If
            If Not String.IsNullOrEmpty(sErrorMsg) Then
                SetTokenValue("Error", sErrorMsg)
            End If
        End Sub

 

1 0
replied on May 20, 2020

You are the man.  Thanks so much!

0 0
replied on May 20, 2020

Hey Bert, one last question on this.  Is there a way to specify in the function to look for a specific stamp name to trigger the offset instead of all annotations?  As it is currently, it will bump the stamp down even if there's another stamp somewhere else on the document.

For instance, my stamp that workflow is applying is called "Built By".  We would only want the offset if there's already a "Built By" stamp there, not some other annotation elsewhere.  Sorry to bother you with this.  I sure appreciate the help.

0 0
replied on May 20, 2020 Show version history

It will only bump the stamp down if the top offset value matches another stamp top value.  So it does not bump down for each stamp applied.

If s.Coordinates.Top = iResult Then

The above line compares the stamp top with the offset value.  It only runs the code inside if the 2 values are equal.

Dynamic Stamps, even those added through the client, are temporary (single use) and do not have a stamp name and have a StampID of 0 (zero), so you cannot easily tell one dynamic stamp from another

1 0
replied on May 20, 2020

Ok, so the reason mine was bumping down was because I've got two different stamps applying using this script, and they have the same top offset, but different Left offsets.  I'll change the top offset slightly on one and that should avoid the issue.  Thanks!

0 0
replied on May 20, 2020

Tried that and it worked perfectly.  Thanks again!

0 0
replied on September 11, 2020

Hey Bert, I have one more question on this.  In the code, we use:

Dim iPageNumber As Integer = "1" ' Page number where stamp is applied

to place the stamp on the first page of the document.  The customer is worried about how often this process is going to take place, so the stamps may end up covering the full page.

Each time this process takes place, though, at least one page will be added to the end.  As such, we've decided it would be best to just always apply the stamps to the last page.  I created a token called "FindEntry2_OutputEntry_PageCount", which should contain the page count, and therefore the number of the last page.  I don't know the syntax to add it into the code, though, in place of the "1".  Could you help me out with that?

0 0
replied on September 11, 2020

Try

Dim iPageNumber As Integer = GetTokenValue("FindEntry2_OutputEntry_PageCount")

 

1 0
replied on September 11, 2020

That worked perfectly!  Thanks again!

0 0
replied on March 14, 2018

Pretty crazy to me that you have to know VB or .NET just to apply a dynamic stamp using workflow. Not sure how this isn't' standard.. But great information none the less.

0 0
replied on March 14, 2018

I believe that is one of the great strengths of Laserfiche.  Functionality that is not immediately available from the native workflow activities can usually be implemented as a script or a custom workflow activity.  As a Laserfiche PDP the development of custom workflow activities to provide functionality not natively available in workflow is a core part of our business.  Perhaps Bert can be convinced to distill the above script into a custom workflow activity that can be  plugged directly into the Workflow Designer canvas just like any other workflow activity so that users don't have to script!  ;-)

 

0 0
replied on March 14, 2018

Yes, using scripts is very nice. But, also available in every other ECM I have ever used along with dynamic stamps using date/time..  Odd that such an easy task would need a developer on staff to complete...not saying it isn't nice to have the SDK. 

1 0
replied on March 14, 2018 Show version history

I agree. I'm a System/Network Admin, not a programmer and we are hoping that this type of function will be available in the future version of LF Workflow.

2 0
You are not allowed to follow up in this post.

Sign in to reply to this post.