Jump to content
Claris Engage 2025 - March 25-26 Austin Texas ×

This topic is 2437 days old. Please don't post here. Open a new topic instead.

Recommended Posts

Posted

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¶" )

 

Posted (edited)

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
Posted

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)"
)

 

Posted

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

 

Posted

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

 

This topic is 2437 days old. Please don't post here. Open a new topic instead.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

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