March 14, 20187 yr 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¶" )
March 14, 20187 yr 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 March 14, 20187 yr by john renfrew
March 14, 20187 yr 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)" )
March 14, 20187 yr 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
March 14, 20187 yr 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