Skip navigation
All Places > Getting Started > Blog > Authors mlauer

Getting Started

6 Posts authored by: mlauer Champion

A sandwich PDF is a scanned document that contains an invisible text layer exactly over the image text. Text layer is produced by OCR (optical character recognition) using open source software tesseract. So PDF ist searchable for text and text can copied and pasted in another document.

 

prerequisites

 

sharepoint lists

  • document library named e.g. tesseract for uploading (scanned) images in tiff format
  • list named tesseract-lang to select text language in list lookup control on start form

list workflow tif2pdf

  • startform

  • workflow

load up an image in tiff format and start item workflow for it. By powershell script text is recognized by tesseract from image and converted to a searchable PDF with image and text layer a so called sandwich pdf. It is also possible to select und copy text from new pdf.

 

Here is powershell script for PowerActivity action:

$VerbosePreference = "Continue"   # keine Ausgabe: "SilentlyContinue"

##############################################################################

Add-PsSnapin Microsoft.SharePoint.PowerShell

##############################################################################

$SiteURL  =  "{Common:WebUrl}"

$ItemURL =  "{Common:ItemUrl}"

 

$FromDoc = ($ItemURL).Replace($SiteURL + "/", "")

$DocLib = [System.IO.Path]::GetDirectoryName($FromDoc)  # tesseract

$PathName = "c:\temp\"

 

$ToPDF   = [System.IO.Path]::GetFileNameWithoutExtension($ItemURL)

$ToPDFFile = $PathName + $ToPDF                                                   

$PDFFile = $ToPDFFile  + '.pdf'

$TiffFile = $PathName + [System.IO.Path]::GetFileName($ItemURL)   

 

$web = Get-SPWeb $SiteURL

$file = $web.GetFile($FromDoc)

$filebytes = $file.OpenBinary()

$filestream = New-Object System.IO.FileStream($TiffFile, "Create")

$binarywriter = New-Object System.IO.BinaryWriter($filestream)

$binarywriter.write($filebytes)

$binarywriter.Close()

##############################################################################

$ErrorActionPreference="Continue"

tesseract -l {WorkflowVariable:Sprachkuerzel} "$TiffFile" "$ToPDFFile" pdf

##############################################################################

$FilePath = $ToPDFFile + '.pdf'                    

$overWriteExisting = $True #or add new version if versioning enabled

 

$Web = Get-SPWeb $SiteURL

$List = $Web.GetFolder($DocLib)

$Files = $List.Files

 

$File= Get-ChildItem $FilePath

$metadata = @{}

$Files.Add($DocLib +"/" + $ToPDF + ".pdf",$File.OpenRead(), $metadata, $overWriteExisting)

 

$web.Dispose()

 

del $PDFFile

del $TiffFile

Repeating section as html table in mail describes how to transform a repeating section to html. It was done by template rules. Problem was it outputs all the Text Data that is present in the XML file even if no template rule is defined for a repeating section control since then applies the default rule for text.

 

To avoid that here for-each is used in stylesheet. Only these fields that have to appear in the output must be specified.

 

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" />

   <!-- transform repeating section from xml to html -->

   <xsl:template match="/">

      <table border="1" width="100%" style="border-collapse:collapse;background-color:#eee;border:1px solid;color:black;font-size:100%;font-family:arial,helvetica,sans-serif;">

         <thead>

            <tr>

               <td>first name</td>

               <td>name</td>

               <td>company</td>

            </tr>

         </thead>

         <tbody>

            <xsl:for-each select="//Items/Item">

               <tr>

                  <td>

                     <xsl:value-of select="first_name" disable-output-escaping="yes" />

                  </td>

                  <td>

                     <xsl:value-of select="last_name" disable-output-escaping="yes" />

                  </td>

                  <td>

                     <xsl:value-of select="company" disable-output-escaping="yes" />

                  </td>

               </tr>

            </xsl:for-each>

         </tbody>

      </table>

   </xsl:template>

</xsl:stylesheet>

 

Except for the stylesheet, everything remains as in Repeating section as html table in mail .

To show a guide to fill in complex forms, a tool tip is often not enough. Formatted instructions may be displayed in a separate dialog by clicking on an info button:

 

It's a floating window that contains a title bar and a content area. The dialog window can be moved, resized and closed with the 'x' icon by default or by pressing escape key.

 

How can that be done in Nintex Forms?

 

First of all create an info button:

I used File:Information green.svg - Wikimedia Commons as button image.

 

Here is the client click coding:

 

NWF$("#Topic_1_help").dialog({

    title: "Topic 1",

    hide: {

        effect: "fade",

        duration: 1000

    },

    maxHeight: 400,

    minWidth: 500,

    modal: false

});

 

Here the jquery-ui dialog widget is used to display help text. Modal behavior here is non modal, but can be changed to modal setting option modal to true.

 

Now create a Rich Text Control in your form and enter help text:

 

In control settings Visible has to be set to Yes. To hide the Control use css class, e.g. info-hidden and css in form settings: .info-hidden {visibility: hidden;}

 

Next step is to define the ID #Topic_1_help used in button client click coding. For that edit source of help text:

Enclose full source text with <div id="Topic_1_help">.... your help text.... </div>

 

That's it!

Have You ever had the situation in Forms Designer that the minimal width of a list lookup control is too big for your form?

 

In this example I wanted to insert a list lookup for 'unit of measure' to the right of the 'quantity' field.

But the width of the inserted control is too big and I could not shrink it in Forms Designer. What to do?

CSS is your friend. Assign a class name to the control, e.g. 'measure'

 

and enter a little piece of CSS in the form settings:

Now the form looks as exspected:

You have to play with the number of pixels for width und position. For the width its important to use '!important' in CSS!

I think you can use this also for other controls.

 

Hope that helps someone

 

Manfred

To limit the maximum length of input field during typing you have to assign a Control CCS Class to an text box. The class name is a concatenation of string 'kob-maxtextlen-' and a number giving the maximum text length.

After assigning the Control CCS Class and activating the javascript you will find below, a little box is shown during field input on top and on left of the input control counting down the yet available input characters:

 

Javascript code:

NWF$(document).ready(function () {

   NWF$("body").append('<div id="charCounter";></div>');  // create div for counter

   var zaehlerFeld = NWF$('#charCounter');   // save as jquery object

   zaehlerFeld.hide(); // hide the div

   NWF$("[class*=kob-maxtextlen-]").each(function () { // for all html elemts with class name beginning with kob-maxtext-len

      var classes = this.className.split(" ");  // splitt class names

      for (var i = 0; i < classes.length; i++) {  // for all class names of the actual html

         if (classes[i].substr(0, 15) == "kob-maxtextlen-") {   // check if class name begins with kob-maxtext-len

            var maxlen = parseInt(classes[i].split('kob-maxtextlen-')[1]); // extract the number at the end of the class name

            NWF$(this).on('focus input blur', function () { // define an event function

               zaehlerFeld.show();   // show counter

               zaehlerFeld.css({   // format counter

                                 "text-align":"center",

                                 "display":"inline-block",

                                  "background-color":"#FFF",

                                  "border":"1px solid",

                                  "box-shadow":"3px 3px 3px #888",

                                  "height":"16px",

                                  "width":"22px"

                              });

               MaxTextLaenge(NWF$(this), maxlen, zaehlerFeld);  / call check function

            });

            NWF$(this).blur(function () {

               zaehlerFeld.text(' ');

               zaehlerFeld.hide();

            });

         }

      }

   });

 

});

 

function MaxTextLaenge(textFeld, maxAnzahl, zaehlerFeld) {

   zaehlerFeld.position({  // positioning the counter

      my: "left top-16",

      at: "left top",

      of: textFeld,

      collision: "fit"

   });

   if (textFeld.val().length > maxAnzahl) { // more then max characters enterd

      textFeld.val(textFeld.val().substr(0, maxAnzahl)); // limit to max text length

      textFeld.css('border-color', 'red');  // show control border in red

      zaehlerFeld.text(0);   // no more input allowed

   } else {

      zaehlerFeld.text(maxAnzahl - textFeld.val().length); // count down counter

      textFeld.css('border-color', "");   // normal border

   }

}

 

Minimized:

NWF$(document).ready(function(){NWF$("body").append('<div id="charCounter";></div>');var zaehlerFeld=NWF$('#charCounter');zaehlerFeld.hide();NWF$("[class*=kob-maxtextlen-]").each(function(){var classes=this.className.split(" ");for(var i=0;i<classes.length;i++){if(classes[i].substr(0,15)=="kob-maxtextlen-"){var maxlen=parseInt(classes[i].split('kob-maxtextlen-')[1]);NWF$(this).on('focus input blur',function(){zaehlerFeld.show();zaehlerFeld.css({"text-align":"center","display":"inline-block","background-color":"#FFF","border":"1px solid","box-shadow":"3px 3px 3px #888","height":"16px","width":"22px"});MaxTextLaenge(NWF$(this),maxlen,zaehlerFeld)});NWF$(this).blur(function(){zaehlerFeld.text(' ');zaehlerFeld.hide()})}}})});function MaxTextLaenge(textFeld,maxAnzahl,zaehlerFeld){zaehlerFeld.position({my:"left top-16",at:"left top",of:textFeld,collision:"fit"});if(textFeld.val().length>maxAnzahl){textFeld.val(textFeld.val().substr(0,maxAnzahl));textFeld.css('border-color','red');zaehlerFeld.text(0)}else{zaehlerFeld.text(maxAnzahl-textFeld.val().length);textFeld.css('border-color',"")}}

The first time I worked with attachments in a workflow, I ask where are the attachments stored and how can I show all attachments in the following workflow tasks to give an approver the possibility to read the attachments.

 

I have attached an NINTEX 2013 example site workflow using NINTEX Forms 2013.

 

A prerequisite is the installation of the Get List Item Attachment in Base64 Custom Action from Vadim Tabakman (see http://www.vadimtabakman.com/nintex-workflow-get-list-item-attachment-in-base64-custom-action-happy-thanksgiving.aspx).

 

In the first Flexi Task you can add multiple attachments. The task IDs are stored in the workflow variable task_ids This attachments are stored in the task items of the Flexi Task.

If the Flexi Task is approved an item is created in a data list.

 

To copy the attachments from the task item(s) to the list item the following steps have to be executed in a loop for each task ID:

  1. Call web service Lists.asmx with method GetAttachmentCollection to get the URLs of all task item attachments. The resulting XML is stored in workflow variable attachments_xml
  2. Extract the URLs from XML and store them in a workflow collection variable attachment_coll by Query XML action.
  3. For each attachment URL the following steps are executed:
    1. Get the attachment from task item in base64 format an store it in workflow variable attachment_base64
    2. Get the filename from attachment URL by Regular Expression action
    3. Call web service Lists.asmx with method AddAttachmentCollection to add the attachment to the list item

 

 

Now all task attachment are stored in the list item.

 

To show the attachments formatted  as HTML links in the next Flexi task form the following steps have to be executed:

  1. Call web service Lists.asmx with method GetAttachmentCollection to get the URLs of all list item attachments. The resulting XML is stored in workflow variable attachments_xml
  2. Extract the URLs from XML and store them in a workflow collection variable attachment_coll by Query XML action.
  3. For each attachment URL the following steps are executed:
    1. Get the filename from attachment URL by Regular Expression action
    2. Build the html coding for the links and store it in the workflow variable attachment_html_links

 

Now the html coding for the attachment links is ready to be rendered in the form of the next flexi task.

 

To show the links in the form I used a Rich Text control. My first attempt to enter the worklfow variable by Insert Referenz to the control was unsuccesful - the html coding was shown, not the rendered link. So a little JavaScript was neccessary. First I assigned a unique CCS Class name Anlagen to the control. Second I created a Single Line Textbox control where I inserted by Insert Referenz my workflow variable containing the html coding. The control itself was made invisible on the form by css. By JQuery the html content of the control will be replaced by the content of my workflow variable:

NWF$(document).ready(function () {

    try {

          NWF$('.Anlagen').html(NWF$('#'+ anlagen_html).val());

    } catch (err) {

 

    }});

Now the attachment links will be rendered:

 

I hope it is helpfull for someone!

 

Manfred

Filter Blog

By date: By tag: