Jump to content
View in the app

A better way to browse. Learn more.

FMForums.com

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Howdy from Texas!

I am trying to change a little bit of Groovy that stamps a given phrase at a specified location on an existing PDF.

The original code operates on files however I want to simply specify container fields as input and output.   

I did successfully change the input (src) to come FROM a container field.   I can't seem to figure out how to return the resulting object to a container (dest) directly.   

I am passing the container parameters as:  "myTable::inputContainer" and "myTable::outputContainer".

Can someone please point me in the right direction here?

Thanks in advance!

Bob Minteer

 

This is the code:

RegisterGroovy( "stampPdf( src ; dest ; xPosition ; yPosition ; phrase )" ; "import com.itextpdf.text.Rectangle;¶
import com.itextpdf.text.Element;¶
import com.itextpdf.text.pdf.PdfReader;¶
import com.itextpdf.text.pdf.PdfStamper;¶
import com.itextpdf.text.pdf.ColumnText;¶
import com.itextpdf.text.pdf.PdfContentByte;¶
import com.itextpdf.text.Phrase;¶
import com.itextpdf.canvas.*;¶
import com.itextpdf.text.pdf.PdfWriter;¶
¶
InputStream container¶
try{¶
	container = fmpro.getContainerStream(src)¶
}catch(e){¶
	throw new Exception('Could not get data from container (make sure container field name is passed as text)')¶
}¶
¶
// test if container field is empty¶
if( container == null ) {¶
	throw new Exception('Container field is empty')¶
}¶
¶
reader = new PdfReader(container)¶
¶
float xP = Float.parseFloat(xPosition)¶
float yP = Float.parseFloat(yPosition)¶
¶
stamper = new PdfStamper(reader, new FileOutputStream(dest), PdfWriter.VERSION_1_7)¶
¶
PdfContentByte canvas = stamper.getOverContent(1);¶
¶
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(phrase),xP,yP,0)¶
¶
return stamper¶" )

 

Bob

Which version of iText??

Once that is clear, I certainly have the code you are looking for..

If you want to explore first, you need to send the output to a ByteArrayOutputStream rather than a FileOutputStream, then convert it to ByteArrayInputStream and use fmpro.getAsContainer() on that

 

You don't set a variable to the script result, but SetField to this output. Which CAN NOT be the same field as the original PDF.

In that code you also need to explicitly call stamper.close() before you return as it runs the risk the file is still locked by the Java process

 

Edited by john renfrew

  • Author

Hi John!  Thanks for giving me some direction on this.

I went ahead and changed to using a ByteArrayOutputStream for PdfStamper and then, after updating the canvas (and before closing stamper), converted the byteArrayOutputStream to an input stream using byteArrayOutputStream.toByteArray().

Then after closing stamper, I try returning the fmpro.getAsContainer(byteArrayInputStream; fileName).  

I feel like I am closer, as I am actually returning a file to the target container (not the same as the input container).  But... the file is empty.

I am using itextpdf-5.5.5.    As I have been kicking this mule for quite awhile, and reading quite a bit of JavaDocs at itextpdf.com , my brain is now oatmeal. 

I'd be grateful for an explanation as to what I am missing here.  As I said, I am pretty sure I am REAL close and that it is probably a matter of me giving FileMaker back what it expects.

Have an awesome day!

--Bob Minteer

 

RegisterGroovy(
"stampPdf( src ; xPosition ; yPosition ; phrase )" ;
"import com.itextpdf.text.Rectangle;¶
import com.itextpdf.text.Element;¶
import com.itextpdf.text.pdf.PdfReader;¶
import com.itextpdf.text.pdf.PdfStamper;¶
import com.itextpdf.text.pdf.ColumnText;¶
import com.itextpdf.text.pdf.PdfContentByte;¶
import com.itextpdf.text.Phrase;¶
import com.itextpdf.canvas.*;¶
import com.itextpdf.text.pdf.PdfWriter;¶
¶
InputStream container¶
String fileName¶
¶
try{¶
	container = fmpro.getContainerStream(src)¶
}catch(e){¶
	throw new Exception('Could not get data from container (make sure container field name is passed as text)')¶
}¶
¶
// test if container field is empty¶
if( container == null ) {¶
	throw new Exception('Container field is empty')¶
}¶
fileName = fmpro.evaluate(src)¶
¶
reader = new PdfReader(container)¶
¶
float xP = Float.parseFloat(xPosition)¶
float yP = Float.parseFloat(yPosition)¶
¶
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()¶
¶
stamper = new PdfStamper(reader, byteArrayOutputStream)¶
¶
PdfContentByte canvas = stamper.getOverContent(1)¶
¶
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(phrase),xP,yP,0)¶
¶
byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray())¶
¶
stamper.close()¶
reader.close()¶
¶
return fmpro.getAsContainer(byteArrayInputStream,fileName)"
)

 

Thats a really good attempt (not trying to sound patronising btw) but you are exactly on the right lines

the BAIS line comes AFTER the close, it is the action of closing that writes the file to the BAOS, otherwise we don't know you have completed your actions on it

 

  • Author

Thanks John!  

I appreciate your patience and giving me nudges in the right direction!

No wonder the BAIS was empty...   I guess you have to close streams before they can flush their buffers and populate the array.

You really helped me learn some excellent info today!   

If I see you at DevCon here in Texas this year, I'll buy ya a drink!

That does exactly what I need for some stuff I am working on.

regards...

Bob Minteer

 

Create an account or sign in to comment

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.