Adobe Javascript in Action Wizard vs a form button - javascript

I've been writing some javascript to fill in fields of a PDF form. I initially wrote the code in the "Action Wizard" in Adobe. I did not realize at the time that I was adding it to my local application, not the form itself. So I then copied it to a button on the from and now it is not working.
The code:
/* Test to read in a file and update the fields*/
var dataFrom = null;
//Grab the current path and update it to indicate the TempInfo location
var strPath = this.path;
strPath = strPath.slice(0,-12);
strPath = strPath + "TempInfo.txt"
//Get data from TempFile into array, display message if no file found
try{
var dataStream = util.readFileIntoStream(strPath);
var dataFrom = util.stringFromStream(dataStream);
}catch(e){
app.alert("Temp file not found");
}
//Put the data into an array and update the fields
var strTest = new Array();
strTest = dataFrom.split(/\n/);
getField("Username").value = strTest[0];
getField("UID").value = strTest[1];
//Clear the data
dataStream = null;
dataFrom = null;
strTest = null;
I am getting the app.alert "Temp file not found" so the "var dataStream = readFileInfoStream(strPath);" isn't reading in the file. I did app.alerts to verify the strPath variable has the right path and one to verify that dataStream is coming up null. Being that I copied it from the Action Wizard, I am unsure why its not working.
Just to make this a little odder (at least to me), if I open the JavaScript editor and highlight the code, it works fine.

For the util.readFileIntoStream method, when the cDIPath parameter is specified, the method can only be executed in a privileged context meaning during a batch, console event, or Action. It won't work when executed within the document context unless you create a Trusted Function.
Read this to understand how to executing privileged methods in a non-privileged context...
http://help.adobe.com/en_US/acrobat/acrobat_dc_sdk/2015/HTMLHelp/index.html#t=Acro12_MasterBook%2FJS_Dev_Contexts%2FExecuting_privileged_methods_in_a_non-privileged_context.htm&rhsearch=trusted%20function&rhsyns=%20

Related

NEWBIE: Impossible to get my attached pdf in a mail with google script and form

I'm new to google script and I'm going crazy trying to do a simple tool.
I created a simple google form with just an email and a file uploader and I need just to insert an email and a pdf, and this should go to the recipient well HTML formatted and whit the pdf attached.
I'm new to this and I tried litterally every syntax using mailApp and Gmail app and the mail comes smooth but the pdf wont.
I know it's just a newbie stupid thing but I can't figure it out at my 74th attempt.
here's the code, I will be grateful forever with someone who can help me!
function sendPDF (e) {
var html = HtmlService.createTemplateFromFile("emailbolladireso.html");
var htmlText = html.evaluate().getContent();
var emailTo = e.response.getRespondentEmail();
var Subject = "---."
var textbody = "---."
var attach = e.response.getItemResponses();
var options = { htmlBody: htmlText};
if(emailTo !== undefined){
GmailApp.sendEmail(emailTo, Subject, textbody, options, )
attachments: attach[1];
}
}
First you have to get the id of your file wich is uploaded by your form to google drive.
You tried with:
var attach = e.response.getItemResponses();
But this will return you an array of objects with all your answers of your form.
From this object you have to extract the id of the uploaded PDF.
If you know the position, for example the first question in your form is for the pdf you can access it with attach[0] if it is e.g. in second position with attach[1], cause arrays index start with 0.
(You could look it also up with a for loop check for the name of the object.
attach[0].getItem().getTitle()
)
With attach[0] you get the next object and from this you get with attach[0].getResponse() finaly the id of your PDF.
attach[0].getResponse()
Now you "load" the file with the given id from google Drive (Make sure you have the permissions for access GoogleDrive)
var file = DriveApp.getFileById(attach[0].getResponse())
You can now attach your file (blob) to your attachments with the right MimeType
attachments: [file.getAs(MimeType.PDF)]
You should also place the attachments in the options of your email.
function sendPDF (e) {
var html = HtmlService.createTemplateFromFile("emailbolladireso.html");
var htmlText = html.evaluate().getContent();
var emailTo = e.response.getRespondentEmail();
var Subject = "Form with PDF"
var textbody = "Your PDF is attached."
var attach = e.response.getItemResponses();
var file = DriveApp.getFileById(attach[0].getResponse())
var options = { htmlBody: htmlText, attachments: [file.getAs(MimeType.PDF)]};
if(emailTo !== undefined){
GmailApp.sendEmail(emailTo, Subject, textbody, options);
}
}
Finaly it should work...
I tested it like this and it works for me.
DON'T PANIC!
Read also the docs -> https://developers.google.com/apps-script/reference/forms/item-response

Google Script - Adding images in document & removing copied files

I'm passing information from Google Sheets to a Document via Google Apps Script. All the information transfers with two exceptions...
The link of the picture shows rather than the image. How can I insert the image rather than the link?
In the folder it saves to, I get 2 versions of the document. One with the name I want, and another named 'Copy of Template'. I don't want the copy of the template, how can I either not create it, or delete it in the script?
Any help would be greatly appreciated.
function myFunction(e) {
var timestamp = e.values[0];
var studentName = e.values[1];
var firstName = e.values[2];
var studentNumber = e.values[3];
var dateOfBirth = e.values[4];
var studentImage = e.values[5];
var file = DriveApp.getFileById('fileId');
var folder = DriveApp.getFolderById('folderId')
var copy = file.makeCopy(studentName, folder);
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
body.replaceText('{{Time}}', timestamp);
body.replaceText('{{Name}}', studentName);
body.replaceText('{{Preferred Name}}', firstName);
body.replaceText('{{Student Number}}', studentNumber);
body.replaceText('{{DOB}}', dateOfBirth);
body.replaceText('{{Image}}', studentImage);
doc.saveAndClose();
}
The expected output is a document with relevant information, an image of the student, and only 1 version of the document in the folder.
I am unsure of why your code creates an extra copy of your file. This might be due to something else.
However, to change "{{image}}" to an image from an URL you can do this:
body.findText('{{Image}}').getElement().asParagraph()
.setText("") //Clears text
.appendInlineImage(UrlFetchApp.fetch(studentImage).getBlob()); //Adds image element from URL

Export a Birt report at run time to a PDF file

How do you export a birt report using javascript at runtime?
The code that I have tried is in the After Render event:
importPackage(Packages.org.eclipse.birt.report.engine.api);
rptdoc = reportContext.getReportRunnable().getReportName();
// Open the rptDocument
reportDocument = getReportEngine().openReportDocument(rptdoc);
// Create the render task, configured for the wanted export format
IRenderTask renderTask = getReportEngine().createRenderTask(reportDocument);
IRenderOption options = new RenderOption();
options.setOutputFormat("pdf");
options.setOutputFileName("C:/test/myfile.pdf");
renderTask.setRenderOption(options);
// Launch the render task and close it
renderTask.render();
renderTask.close();
// Close the rptDocument
reportDocument.close();
It runs and there are no errors but no pdf gets generated...
My requirement is to run the birt report using an URL and the report should generate itself in a folder as a pdf.
The report should only execute once. I don't want to execute the URL and then in the report it does another runAndRender in after factory, the report should export itself. Hope this makes sense.
I am using Birt 4.5.
UPDATED CODE.
I can get it working using the following code in the afterRender event of the report.
//Import Lib for birt this is standard, Import our custom birt report java lib
importPackage(Packages.org.eclipse.birt.report.engine.api);
importPackage(Packages.company.reports.data);
//Creates an instance of our custom class
st = new Packages.company.reports.data.MyStandardFunctions();
//Get Global vaiables
fileDir = reportContext.getGlobalVariable("fileDir");
sTcNumber = reportContext.getGlobalVariable("sTcNumber");
sTcRevNum = reportContext.getGlobalVariable("sTcRevNum");
sTcType = reportContext.getGlobalVariable("sTcType");
sPdfPath = reportContext.getGlobalVariable("sPdfPath");
bHasErrors = reportContext.getGlobalVariable("bHasErrors");
testCertError = reportContext.getGlobalVariable("testCertError");
var re = reportContext.getReportRunnable().getReportEngine();
//Get current dreport
var pathOfReport = reportContext.getReportRunnable().getReportName().replace("file:", "");
//Create a directory for temp export reports TempExport is my dir name.
fileDir = st.createOrGetDir(fileDir);
//Only export to pdf if there were no errors.
if(bHasErrors == false)
{
var des = re.openReportDesign(pathOfReport);
var ntask = re.createRunAndRenderTask(des);
//Set parameters ie. ntask.setParameterValue("sOpiid", params["sOpiid"].value);
ntask.setParameterValue("createPDF", false);
ntask.setParameterValue("TCNumber", sTcNumber);
ntask.setParameterValue("TCRevNum", sTcRevNum);
ntask.setParameterValue("TCType", sTcType);
//The ReportPath were you want to store the file on server(linux) test17.pdf is the name of your file. You can change this.
var outputfile = fileDir + "temp.pdf"; //***** test17.pdf you can change to your file name.
//This is the export options.. this will change when exporting to another format.
var options = new PDFRenderOption();
options.setOutputFileName(outputfile);
options.setOutputFormat("pdf");
ntask.setRenderOption(options);
ntask.run();
ntask.close();
The problem is that it generates the report two times when calling the report as a post call from withing a system. Now I know why it does this because it does the runandrender again. I just want it to run once and export to a pdf.
The Java wrapper service is what I would recommend. You can use the RunAndRenderTask then instead of separate RunTask and RenderTask.
Or you can use the Web Viewer Servlet and retrieve the PDF output as the HTTP response.
Anyway, it is the wrong approach if you try to call any of these tasks from Javascript inside the report itself.
See https://wiki.eclipse.org/Integration_Examples_(BIRT) for an examples of the Java API and https://www.eclipse.org/birt/documentation/integrating/viewer-usage.php for the viewer (you'll want to use /run in your URL).

How can I modify a javascript event in a PDF file programmatically?

My PDF file has an event attached to a button. I need to be able to modify that event programmatically. I tried this way using iTextSharp, but it didn't change the javascript in the new file:
var pdfReader = new PdfReader(originalPdfDocumentPath);
pdfReader.RemoveUsageRights();
var pdfStamper = new PdfStamper(pdfReader, new FileStream(
newPdfDocumentPath, FileMode.Create, FileAccess.Write, FileShare.None),
'\0', true);
var originalXml = pdfReader.AcroFields.Xfa.DomDocument.InnerXml;
var newXml = originalXml.Replace(
"Table2.Row1.instanceManager.removeInstance(1)",
"Table2._Row1.removeInstance(this.parent.parent.index)");
// Unfortunately, this line does nothing.
pdfStamper.AcroFields.Xfa.DomDocument.InnerXml = newXml;
pdfStamper.Close();
pdfReader.Close();
Any help would be greatly appreciated.
I found that it works if, instead of changing the XML directly, I change the DomDocument and mark the XFA as changed. Below is the corrected code:
var pdfReader = new PdfReader(originalPdfDocumentPath);
pdfReader.RemoveUsageRights();
var pdfStamper = new PdfStamper(pdfReader, new FileStream(newPdfDocumentPath, FileMode.Create, FileAccess.Write, FileShare.None), '\0', true);
var originalXml = pdfReader.AcroFields.Xfa.DomDocument.InnerXml;
var newXml = originalXml.Replace("Table2.Row1.instanceManager.removeInstance(1)", "Table2._Row1.removeInstance(this.parent.parent.index)");
/* New Code */
var doc = new XmlDocument();
doc.LoadXml(newXml);
pdfStamper.AcroFields.Xfa.DomDocument = doc;
pdfStamper.AcroFields.Xfa.Changed = true;
/* End of New Code */
pdfStamper.Close();
pdfReader.Close();
I should note that, even though this code changes the javascript in the PDF file, it also disables the extended features in Adobe Acrobat Reader. You can find more information regarding this here:
http://developers.itextpdf.com/question/why-do-i-get-error-saying-use-extended-features-no-longer-available
"The problem is related to whether or not your document is Reader Enabled. Reader-enabling can only be done using Adobe software. It is a process that requires a digital signature using a private key from Adobe. When a valid signature is present, specific functionality (as defined in the usage rights when signing) is unlocked in Adobe Reader.
You change the content of such a PDF, hence you break the signature."

Trouble accessing javascript property

I have an object called users inside a global object called streams. Each property of users is a username with the value of an array that stores other objects with info about each user. The project is supposed to be a small version of twitter. E.g:
var users = {};
users.bill = []
users.keith = [];
var someInfo = {};
someInfo.tweet = "Hello, I am a message";
someInfo.dateCreated = new Date();
users.keith.push(someInfo);
The above is in a separate .js file that is included in my index.html file. My index.html file also has a script section and that is where my problem lies. What I am attempting to do is retrieve the string from the tweet property, when a username is clicked on, using jQuery. Here is what I am trying.
var showTimeline = function (){
var tweeter = $(this).text(); // get username from whichever name is clicked on
console.log(tweeter); // log name to console. e.g tweeter holds "keith"
console.log(streams.users["keith"][0].message); // this works fine and extracts string as expected
console.log(streams.users[tweeter][0].message); // program breaks here and says "tweeter is undefined", right after i logged it to the console and showed it holds the string "keith"
};
jsfiddle
There are some invisible character(s) causing problems:
console.log(tweeter == 'douglascalhoun'); //false
This solves it:
var tweeter = $.trim($(this).text());
http://jsfiddle.net/26gwz/

Categories