Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

XFA form with button to save file with unique filename

Avatar

Level 4

Is there a way to save a file with a unique filename using some data a user has entered (name, for ex.) that will fire when the user clicks a Print button? Attached is a file for reference.

1 Accepted Solution

Avatar

Correct answer by
Level 10

Hi,

Yes it is working here using your latest form and the amended .js:

Have you created the "HSSSave" folder?

Also make sure the .js file is in the correct application folder and restart Acrobat:

Hope you get it working (and when you do you may want to include a datestamp or timestamp in the filename; as the script automatically overwrites an existing file with the ame name).

N.

View solution in original post

37 Replies

Avatar

Level 10

Hi,

I have seen your other posts on this, but you are running into a security issue with Acrobat. The software is slow to allow for certain scripts (like save as) to run, potentially without the users knowledge or interaction.

There is a way around it, which uses a "trusted function". This is javascript that is written into a .js file, which is then put into the Adobe application/Javascript folder on the C:// drive of EVERY computer that will be using the form. This is one of the potential problems with trusted functions.

I would recommend searching the forums again for "trusted function" as there are several posts dealing with this.

Also Acrobat User Group has a lot of posts dealing with this: http://www.acrobatusers.com/forums/aucbb/viewtopic.php?id=17693  We got a save as button script to work without user interaction, by following this post; however as I said before the .js file has to be installed on each PC.

Lastly some of your script looks like AcroForms Javascript, rather than the LC variety.

Hope that helps,

Niall

Avatar

Level 4

Niall, thank you for your valuable comments. I should have mentioned that this form will be in a kiosk in a hospital waiting room. I have read some material on trusted functions, and that is how I got that javascript to work with an AcroForm. Now I need to do the same thing but with an XFA form. I'll certainly check out the link you suggest. And the javascript is for AcroForm, as you recognized. I've been searching for help in converting that so that it will work in the XFA form, which I've attached for you. I'd be glad to entertain any thoughts you have on this LiveCycle issue.

Avatar

Level 4

I followed your link and tried the code, but it doesn't save. Here's what I have

//This is the trusted file in Acrobat>javascript

mySaveAsName = app.trustPropagatorFunction( function ( myDoc, path )
{
app.beginPriv();
var myDoc = event.target;
return retn = myDoc.saveAs(path);
app.endPriv();
});
myTrustedSpecialTaskFunc100 = app.trustedFunction( function ( myDoc, path )
{
app.beginPriv();


    var a = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].Last_Name[0]");
    var av = a.rawValue;
    var g = "/c/HSSSave/" + av + ".pdf"

    var retn = mySaveAsName(myDoc, g);

  
app.endPriv();
return retn;
});

//Button on click

----- topmostSubform.Page9.PrintButton1::click: - (JavaScript, client) -----------------------------

//this line was already in the XFA form and does work

xfa.host.print(1, "0", (xfa.host.numPages -1).toString(), 0, 1, 0, 0, 0);

//calls trusted function in MySaveAsPO.js folder-level script
event.target.myTrustedSpecialTaskFunc100(event.target);

Avatar

Level 10

Hi,

You could create a save button with the following in the click event:

event.target.myTrustFunct(event.target);

Then in the .js file you will have similar javascript (based on Acrobat User Group thread):

// place this .js file in C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Javascripts

//

// folder level JavaScript to allow access to the identity object properties


trustedIdentity = app.trustedFunction(function (sProperty)

{

     var iProperty = "";

     app.beginPriv(); // explicitly raise privilege

     iProperty = identity[sProperty];

     app.endPriv();

     return iProperty;

})





// folder level JavaScript to allow Save As population of file name


mySaveAs = app.trustPropagatorFunction(function(myForm, path)

{

     app.beginPriv();

     var myForm = event.target;

     return rtn = dmaicForm.saveAs(path);

     app.endPriv();

});


myTrustFunct = app.trustedFunction(function(myForm, path)

{

     app.beginPriv();

     var proNr = event.target.xfa.resolveNode("#pageSet.Page1.patientName").rawValue;

     //console.println("proNr: " + proNr);

     var vProNr = proNr.toString();

     var vPath = "/c/Folder/HSS Foot & Ankle for Patient " + vProNr + ".pdf";

     //console.println("vPath: " + vPath);

     var retn = mySaveAs(myForm, vPath);

     app.endPriv();

     return retn;

});

Then place the .js file in the following application folder (or similar):

“C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Javascripts”

I was putting the above together when you posted, so I am hoping this will get you out of the blocks!!

Hope that helps.

Niall

ps Don't worry about the trustedIdenity javascript at the top; that is for a different purpose, but I have it in the same .js for convenience. Also the above works for us, so I am hoping it will work for you as well.

Avatar

Level 4

Niall, if the script works for you, we must be really close to a solution. It doesn't work here, but I've attached the files I used.

In LC on the Print Form button I have

----- topmostSubform.Page9.PrintButton1::click: - (JavaScript, client) -----------------------------

xfa.host.print(1, "0", (xfa.host.numPages -1).toString(), 0, 1, 0, 0, 0);

//calls trusted function in MySaveAsPO.js folder-level script
event.target.myTrustFunct(event.target);;

and in the folder .js file I have

// folder level JavaScript to allow access to the identity object properties
trustedIdentity = app.trustedFunction( function (sProperty)
{
var iProperty = "";
app.beginPriv();
iProperty = identity[sProperty];
app.endPriv();
return iProperty;
});

// folder level JavaScript to allow Save As population of file name
mySaveAs = app.trustPropagatorFunction(function(myForm, path)
{
     app.beginPriv();
     var myForm = event.target;
     return rtn = dmaicForm.saveAs(path);
     app.endPriv();
});

myTrustFunct = app.trustedFunction(function(myForm, path)
{
     app.beginPriv();
     var proNr = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].Last_Name[0]").rawValue;
     //console.println("proNr: " + proNr);
     var vProNr = proNr.toString();
     var vPath = "/c/HSSSave/HSS Foot & Ankle for Patient " + vProNr + ".pdf";
     //console.println("vPath: " + vPath);

     var retn = mySaveAs(myForm, vPath);

     app.endPriv();

     return retn;
});

Can you see what's missing? I created a folder HSSSave at the root of C:\ and shared it. I also copied into /c/Documents and Settings/All Users/Documents/HSSSave and still no PDF copy was saved in that location.

Avatar

Level 10

Bingo!!

My mistake; I was adapting my script to suit your application and missed one of the references:

// folder level JavaScript to allow Save As population of file name

mySaveAs = app.trustPropagatorFunction(function(myForm, path)

{

     app.beginPriv();

     var myForm = event.target;

     return rtn = myForm.saveAs(path);

     app.endPriv();

});

myTrustFunct = app.trustedFunction(function(myForm, path)

{

     app.beginPriv();

     var proNr = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].Last_Name[0]").rawValue;

     //console.println("proNr: " + proNr);

     var vProNr = proNr.toString();

     var vPath = "/c/HSSSave/HSS Foot & Ankle for Patient " + vProNr + ".pdf";

     //console.println("vPath: " + vPath);

     var retn = mySaveAs(myForm, vPath);

     app.endPriv();

     return retn;

});

Also I would remove the click script at the end of the .js file (copy attached).

Also note that if the "last name" field is blank, it won't save the form, so an if statement might help. Once the last name is provided, the form saves in the folder with the specific name.

Good luck,

Niall

Avatar

Level 4

Even with the new folder .js, the Print Form button fires Print but not the Save. I noticed a couple of errors that I made. One was in LC on the button where I had ;; at the end here

----- topmostSubform.Page9.PrintButton1::click: - (JavaScript, client) -----------------------------

xfa.host.print(1, "0", (xfa.host.numPages -1).toString(), 0, 1, 0, 0, 0);

//calls trusted function in MySaveAsPO.js folder-level script
event.target.myTrustFunct(event.target);;

So I changed that, but it didn't make any difference. Then I looked at the XML Source at the Last Name box:

         <field h="9.0001mm" name="Last_Name" w="76.732mm" x="120.8678mm" y="35.6042mm">

I had been using topmostSubform[0].Page1[0].Last_Name[0] from an earlier AcroForm version of the form, but in the XML, the field is just named "Last_Name." So I changed that in the .js file, too. That didn't make any difference, either. Does the form save for you? I wonder what the difference could be?

Avatar

Correct answer by
Level 10

Hi,

Yes it is working here using your latest form and the amended .js:

Have you created the "HSSSave" folder?

Also make sure the .js file is in the correct application folder and restart Acrobat:

Hope you get it working (and when you do you may want to include a datestamp or timestamp in the filename; as the script automatically overwrites an existing file with the ame name).

N.

Avatar

Level 4

All I needed to do was restart Acrobat! Thank you very much for all your guidance here. I'll definitely look into adding a dat/time stamp, and I'll probably want to add the patient's first name and middle initial. This resolution is really so exciting! Until you came along, I was starting to think that this sort of saving wasn't possible with LC. Fantastic work!

Avatar

Level 4

What I wanted to do was to add the First_Name and MI fields to the new filename (see attachment), but my code doesn't work. I guess that it has to do with the var vProNr = proNr.toString(); line. I should probably have a line that concatenates all three vars, but I don't know the syntax.

At the same time, I'd like to add a DateTimeStamp to prevent overwriting files. Can you get me over the hump again?

Avatar

Level 10

Hi,

I would recommend an if statement in the form before calling the trusted function to check the value of the fields for null values.

Also I have given examples for the other fields in the .js file and the date stamp in the form.

You may want to amend the button caption to highlight that the form is saved, or create a new button.

Good luck,

Niall

Avatar

Level 4

These files are a tremendous help! Thank you very much again! I just tested, and everything works. I corrected what looked like a couple of typos in the folder .js:

     var vDataStamp = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].dateStamp[0]").rawValue.toString();
     var vFirstName = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].First_Name[0]").rawValue.toString();
     var vInitial = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].MI[0]").rawValue.toString();
     var vLastName = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].Last_Name[0]").rawValue.toString();

     var vPath = "/c/HSSSave/" + vDataStamp + " HSS Foot & Ankle for Patient " + vFirstName  + " " + vInitial + " " + vLastName + ".pdf";

changing DataStamp to DateStamp wherever that occurred.

How does your DateStamp field work? Does it grab the date which the user enters? Or the system date? And can I go ahead and change the format to

Date and Time?

And about your suggestion of giving the user some feedback about the saving, with a button highlight. In the button object properties, I see that there are Highlighting and Rollover Caption and Down Caption. These seem to fire on click. But how do we first determine that the file has actually been saved, and then show the user some message that the file has been saved? You mention creating another button. How would that work?

The only other thing that remains to be done is to create a "hidden" button next to MRN# that a staff member can click to email the form after assigning it a research number. I'll use the script at the bottom of the form in that email button for this purpose. And I think I know how to make the button "hidden" by using a white border and white fill.

I experimented with the Save path, too. "/c/inetpub/wwwroot/HSS/" works, but would a path with spaces work also (like "/c/Documents and Settings/All Users/HSS/")?

Niall, I can't thank you enough. I'm sure everyone at the hospital will breathe a deep sigh of relief that the form finally works. Someone told me this has been languishing for about a year now. I got involved about two weeks ago, at the tail end. But without your help, the form would still be incomplete.

If there's anything I can do in return, please let me know.

Avatar

Level 10

Hi,

Glad you have got it to work!!

Yes, DataStamp was a typo on my part.

In addition, in the version I posted I had commented out (//) the print script, to save paper when testing. You might delete the //.

In LC the dateStamp field is hidden and looks at the user entered date field. If that is null it sets its own value to the system date. When the user inputs a date the dateStamp field gets that value. I set the pattern to YYYY-MM-DD so that all of the files would be in chronological order. I would nearly be inclined to leave it at a date stamp and not bother with the time stamp. The issue will be if you expect the same patient to complete the form multiple times in one day.

At the moment the caption that saves the file is "print". The button does more than that, so I was just suggesting changing the caption to reflect that the file would be saved.

At the moment when the file is saved, the new file name will appear in the blue (application) bar at the top of the window (if this is visible in the kiosk). Within LC you could set up an app.alert to confirm the file is saved after the trusted function script in the button.

With the MRN# you could change the presence of the button to visible once the MRN# is not null. Otherwise you will have to "train" the staff member to hit a particular white section of the form. Also consider tooltips, which you can script for. If MRN# is null; then button tooltip is "". When MRN# is not null; then button tooltip is "Click here to email form..."

Lastly I would expect the file path to work where folder names have spaces (it already works for file names with spaces).

Your are welcome. Good luck with the rest of the form,

Niall

Avatar

Level 4

About the Show/Hide of the email button. I've done some searching and tried out about six different scripts, none of which work. The last one looks like this

----- topmostSubform.Page1.MRN::change: - (JavaScript, client) -------------------------------------

var email_button = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].Button1[0]").presence;
var boxes_MRN = event.target.xfa.resolveNode("topmostSubform[0].Page1[0].MRN[0]").rawValue;

if (boxes_MRN == null){
email_button = "Invisible";
}else {email_button = "Visible";
}

I must be close. Can you spot the trouble?

Also, since I've done a lot of searching, can you mention a few resources that helped you learn XFA javascript? I used just the Adobe forums.

Thank you again!

Avatar

Former Community Member

Invisible and Visible should be in lower case ... and it is the presence property that you want to set. So your command should look like this:

Email_button.presence = "invisible";

also the form must be dynamic.

Paul

Avatar

Level 4

Just after I sent the last reply, I tried another solution from a forum

----- topmostSubform.Page1.MRN::change: - (JavaScript, client) -------------------------------------

if

(this.rawValue == null

)

xfa.resolveNode("Button1").presence

=

"hidden";

else

xfa.resolveNode("Button1").presence

=

"visible";

And that worked! I'm all set. Now I'm going to look into your suggestion for "set up an app.alert to confirm the file is saved after the trusted function script in the button."

Avatar

Level 10

Heads up,

You could access and test the file name using:

var vCurrentName = event.target.documentFileName.toString();

Then concat the objects in the form that make up the file name: First name; initial; surname; and date stamp. If both are the same, then a simple app.alert.

N.

Avatar

Level 4

Well, the show/hide DID work. But now it DOESN'T. Here's the code on the MRN field

----- topmostSubform.Page1.MRN::change: - (JavaScript, client) -------------------------------------

if

(this.rawValue == null

)

xfa.resolveNode("Button1").presence

=

"hidden";

else

xfa.resolveNode("Button1").presence

=

"visible";

When I added app.alert('--------'); after the trusted function, this seemed to cause a problem. The file wanted to print, but it didn't save. When I took out this alert, then the button worked as it should. Still, Button1 doesn't become visible when I type into the MRN box. And it did work just a short time ago. What could have happened? Do files become corrupt in LC?

Avatar

Level 4

I successfully added the app.alert

event.target.myTrustFunct(event.target);;

{

app.alert("Thank you. Your form has been saved.");

}

Now the only remaining problem is that show/hide behavior on Button1.

Avatar

Level 10

Hi,

I would move the script out to the exit event of the MRN# object. Also you don't need to always resolve an object, espically when it is on the same page, so script could become:

if (this.rawValue == null)

Button1.presence="hidden";

else

Button1.presence="visible";

Works here...

I don't think the form is corrupt.

In relation to the app.alert it might be worth putting in some console.println("variable....." + variable) scripts to debug.

N.