createFile() in google Apps Script is not functioning properly - javascript

I am trying to create a file. It works fine when I run the following code segment from the debugger in apps script. However, when I run it real time from the spreadsheet, it says I do not have permission to call createfile. Everything that is logged is identical. The issue is not I do not have authority as I am the only one in the spreadsheet and am the owner. The purpose of the CSV is to move it from my google drive into data for BigQuery
function saveAsCSV(row) { //Doc to Csv
//row = 3; //when this is uncommented and ran from the debugger, it works.
try{
var fileName= Date.now()
fileName = fileName + ".csv";
var csvFile = convertRangeToCsvFile_(fileName,row);
Logger.log(csvFile); //Both times ran on the spreadsheet and from debug equals the same.
DriveApp.createFile(fileName, csvFile);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("New and Open").getRange("J" + row.toString()).setValue("");
loadCsv(fileName);
}
catch(e){Logger.log("B" + e.message);} //No permission to create file
}
function convertRangeToCsvFile_(csvFileName, r) {
var ws = SpreadsheetApp.getActiveSpreadsheet();
try {
//var data = ws.getValues();
var csvFile = undefined;
var csv = "";
var row = r;
var datArray = Create2DArray(1,19);
datArray[0][0] = ws.getRange("A" + row.toString()).getValue().toString().toUpperCase();
datArray[0][1] = ws.getRange("B"+row.toString()).getValue().toString().toUpperCase();
datArray[0][2] = ws.getRange("C"+row.toString()).getValue().toString().toUpperCase();
datArray[0][3] = ws.getRange("D"+row.toString()).getValue().toString().toUpperCase();
datArray[0][4] = ws.getRange("E"+row.toString()).getValue().toString().toUpperCase();
datArray[0][5] = ws.getRange("F"+row.toString()).getValue().toString().toUpperCase();
datArray[0][6] = ws.getRange("G"+row.toString()).getValue().toString().toUpperCase();
datArray[0][7] = ws.getRange("H"+row.toString()).getValue().toString().toUpperCase();
datArray[0][8] = ws.getRange("I"+row.toString()).getValue().toString().toUpperCase();
datArray[0][9] = new Date(ws.getRange("K"+row.toString()).getValue().toString()).getHours();
datArray[0][10] = new Date(ws.getRange("K"+row.toString()).getValue().toString()).getMinutes();
datArray[0][11] = new Date(ws.getRange("L"+row.toString()).getValue().toString()).getHours();
datArray[0][12] = new Date(ws.getRange("L"+row.toString()).getValue().toString()).getMinutes();
datArray[0][13] = new Date(ws.getRange("M"+row.toString()).getValue().toString()).getHours();
datArray[0][14] = new Date(ws.getRange("M"+row.toString()).getValue().toString()).getMinutes();
datArray[0][15] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getTime();
datArray[0][16] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getFullYear();
datArray[0][17] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getMonth();
datArray[0][18] = new Date(ws.getRange("N"+row.toString()).getValue().toString()).getDate();
for(var i = 0; i < 19; i++){
if(datArray[0][i] == ""){if(i > 9){datArray[0][i] = 0;} else{datArray[0][i] = "nil";} }
if(i < 18){csv += '"' + datArray[0][i] + '"' + ",";}
else{ csv += '"' + datArray[0][i] + '"'; }
}
Logger.log("A " + csv);
Logger.log(csv + "\n" + datArray[0].join(","));
csvFile = csv;
return csvFile;
}
catch(err) {
Logger.log("C" + err);
Browser.msgBox(err);
}
}

You mention in your comment on my answer that you are using onEdit to trigger the script. Since this is a Simple Trigger, your current approach will not work. When you use simple triggers to run an Apps Script, it runs in a sandbox with reduced permissions.
See: https://developers.google.com/apps-script/guides/triggers/#restrictions
The best I can recommend is create a custom menu option with a UI popup asking for the row number to export. If the code is triggered from a menu by the user, it runs with full permission to access that users account.
Depending on your use-case, a scheduled trigger might work too. It could run every 10 minutes or every Hour and export any changes to the spreadsheet. In this case the Apps Script runs as you, with permission to access your account, and the resulting CSV would be created on your drive.
Details on how to create a custom menu: https://developers.google.com/apps-script/guides/triggers/#onopen
Details on how to create a form for the user: https://developers.google.com/apps-script/guides/ui-service
Details on time driven triggers: https://developers.google.com/apps-script/guides/triggers/installable#time-driven_triggers

Related

How do I pause/resume in Photoshop with a JS code script?

I'm currently trying to automate a certain task in Photoshop (the latest version) with a JS code script. The each process is that 1. load an image -> 2. do something -> 3. implement an action -> 4. save the image -> 5. repeat this. Pretty simple, right? Cut to the chase, it's my code snippet below.
var opts;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
opts.PNG8 = false;
for(var i = 1; i < 6; i ++){
var filename = '/Users/abcde/Desktop/ap/' + i.toString() + '.PNG';
var file = File(filename);
var document = app.open(file);
// do something in Photoshop manually !!
app.doAction('bbbb', 'aaaa');
var savename = '/Users/abcde/Desktop/ap_save/' + i.toString() + '.PNG';
var savefile = new File(savename)
app.activeDocument.exportDocument(savefile, ExportType.SAVEFORWEB, opts);
}
So, my question is how do I pause the program when it loaded an image and do something, and get an input key like 'w' and resume the entire process again?
With my question, the code snippet is going to be like below
var opts;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
opts.PNG8 = false;
for(var i = 1; i < 6; i ++){
var filename = '/Users/abcde/Desktop/ap/' + i.toString() + '.PNG';
var file = File(filename);
var document = app.open(file);
// pause this code script (which type of code can I put in here?)
// do something(I'm going to do something manually in the Photoshpp when this script's been paused, this part doesn't has to be written in code)
// resume when it gets a key input(I want to type 'w' when that something task has been done, again.. which type of code function can I put?)
app.doAction('bbbb', 'aaaa');
var savename = '/Users/abcde/Desktop/ap_save/' + i.toString() + '.PNG';
var savefile = new File(savename)
app.activeDocument.exportDocument(savefile, ExportType.SAVEFORWEB, opts);
}
Please help me.
If either it's impossible to build or I need to clarify this question more let me know too.
Thanks.
I would restructure the script to run the export first (in case there is already a file open and then open the next document. Then, when the script is finished, the user can do something with the open document in Photoshop. Once they are done with that, they run the script again.
This needs a bit of extra checking if there is a document already open and also if there are any files left to handle. But it would basically look like this:
// set export options
var opts;
opts = new ExportOptionsSaveForWeb();
opts.format = SaveDocumentType.PNG;
opts.PNG8 = false;
// find out, which destination files already exists, to know which new one to open
// increase i until it finds an index that does not exist yet
var i = 1;
while( File('/Users/abcde/Desktop/ap_save/' + i.toString() + '.PNG').exists ) {
i++;
}
// if a document is already open, run the action on it and export it
if(app.documents.length) {
app.doAction('bbbb', 'aaaa');
var savename = '/Users/abcde/Desktop/ap_save/' + i.toString() + '.PNG';
var savefile = new File(savename)
app.activeDocument.exportDocument(savefile, ExportType.SAVEFORWEB, opts);
app.activeDocument.close();
// increase i once more to jump to the next file
i++;
}
// try to open a new source file, if there is one left
var srcFile = File('/Users/abcde/Desktop/ap/' + i.toString() + '.PNG)'
if(!srcFile.exists) {
// no further source file does exist, exit the script
exit();
}
var document = app.open(file);
// script ends here and the user can do stuff
// and then use a hot key to run the script again

Fail to Send an email with attachment using Google Apps Script

function SendEmails() {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Name List").activate();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email Template").getRange(1, 1).getValue();
var quotaLeft = MailApp.getRemainingDailyQuota();
//Logger.log(quotaLeft);
if ((lr-1) > quotaLeft){
Browser.msgBox("You have " + quotaLeft + " left and you're trying to send " + (lr-1) + "emails. Emails were not sent.");
} else {
for (var i = 2;i<=lr;i++){
var currentName = ss.getRange(i, 1).getValue();
var currentAppNo = ss.getRange(i, 2).getValue();
var currentEmail = ss.getRange(i, 3).getValue();
var messageBody = templateText.replace("{First Name}",currentName).replace("{App No}",currentAppNo);
var subjectLine = "CONGRATULATION ON YOUR VAL APPROVAL " + currentName
var attachmentBody = DriveApp.getFilesByName("THE ROOM SCRIPT.pdf");
MailApp.sendEmail(currentEmail, subjectLine, messageBody)
} //close for loop
} //close else statement
}
I have a Google Spreadsheet with a list of emails. I want to build a routine that sends email automatically to those email addresses. I also want to attach a PDF to this email. The PDF file is located on my Google Drive.
This does not seem to work
Here are two things that you may want to change in your script.
getFilesByName() gets a collection of files (as a FileIterator object) with that name. If there is just one such file, you'll need to change that line to
var attachmentBody = DriveApp.getFilesByName("THE ROOM SCRIPT.pdf").next; // To get the first such file
Ref doc here.
As #ross said, the sendMail() function needs to include the attachment like so:
MailApp.sendEmail(currentEmail, subjectLine, messageBody, {
attachments: [attachmentBody.getAs(MimeType.PDF)]
});
Ref doc here.

Check if user exists in Active Directory from client side JavaScript

I am creating a ASP.NET page for creating AD user objects. I am using JQuery for client side validation (to check if user name already exists).
I found some script on Google which returns user properties if user is found in active directory (I will convert this to return bool).
However, if you run this script (below) outside of Visual Studio by directly double clicking ScriptFile.js it works perfectly but when you try the same through visual studio it gives object undefined error at var objRootDSE = GetObject('LDAP://RootDSE');
Here is the JavaScript function code:
function Search(search) {
var arrSearchResult = [];
var objRootDSE = GetObject('LDAP://RootDSE');
var strDomain = objRootDSE.Get("DefaultNamingContext");
strAttrib = "samaccountname";
objConnection = new ActiveXObject("ADODB.Connection");
objConnection.Provider = "ADsDSOObject";
objConnection.Open("ADs Provider");
objCommand = new ActiveXObject("ADODB.Command");
objCommand.ActiveConnection = objConnection;
var Dom = "LDAP://" + strDomain;
var arrAttrib = strAttrib.split(",");
objCommand.CommandText = "Select '" + strAttrib + "' From '" + Dom + "' WHERE objectCategory = 'user' AND objectClass='user' AND samaccountname='" + search + "' ORDER BY samaccountname ASC";
try {
objRecordSet = objCommand.Execute();
objRecordSet.Movefirst;
while (!(objRecordSet.EoF)) {
var locarray = new Array();
for (var y = 0; y < arrAttrib.length; y++) {
locarray.push(objRecordSet.Fields(y).value);
}
arrSearchResult.push(locarray); objRecordSet.MoveNext;
}
return arrSearchResult;
}
catch (e)
{ alert(e.message); }
}
Please suggest how to make this work in visual studio or some other way to check if user exists in AD from client side.

Is there a way of Creating lnk file using javascript

I would like to give the users in my website the ability to download a "lnk" file.
My idea is to generate this file with to contain an address that can be used only once.
Is there a way to generate this file in javascript?
The flow is something like -
the user presses a button
the javascript generates this file and downloads it to the user's machine
the user sends this file to another user to use this one-time-address from his machine
Is something like this is doable in javascript from the client side? or would i need to generate this file using java server side?
This is a faithful translation of mslink.sh.
I only tested my answer in Windows 8.1, but I would think that it works in older versions of Windows, too.
function create_lnk_blob(lnk_target) {
function hex_to_arr(s) {
var result = Array(s.length / 2);
for (var i = 0; i < result.length; ++i) {
result[i] = +('0x' + s.substr(2*i, 2));
}
return result;
}
function str_to_arr(s) {
var result = Array(s.length);
for (var i = 0; i < s.length; ++i) {
var c = s.charCodeAt(i);
if (c >= 128) {
throw Error("Only ASCII paths are suppored :-(");
}
result[i] = c;
}
return result;
}
function convert_CLSID_to_DATA(s) {
var idx = [[6,2], [4,2], [2,2], [0,2],
[11,2], [9,2], [16,2], [14,2],
[19,4], [24,12]];
var s = idx.map(function (ii) {
return s.substr(ii[0], ii[1]);
});
return hex_to_arr(s.join(''));
}
function gen_IDLIST(s) {
var item_size = (0x10000 + s.length + 2).toString(16).substr(1);
return hex_to_arr(item_size.replace(/(..)(..)/, '$2$1')).concat(s);
}
var HeaderSize = [0x4c, 0x00,0x00,0x00],
LinkCLSID = convert_CLSID_to_DATA("00021401-0000-0000-c000-000000000046"),
LinkFlags = [0x01,0x01,0x00,0x00], // HasLinkTargetIDList ForceNoLinkInfo
FileAttributes_Directory = [0x10,0x00,0x00,0x00],
FileAttributes_File = [0x20,0x00,0x00,0x00],
CreationTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
AccessTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
WriteTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
FileSize = [0x00,0x00,0x00,0x00],
IconIndex = [0x00,0x00,0x00,0x00],
ShowCommand = [0x01,0x00,0x00,0x00], //SW_SHOWNORMAL
Hotkey = [0x00,0x00], // No Hotkey
Reserved = [0x00,0x00],
Reserved2 = [0x00,0x00,0x00,0x00],
Reserved3 = [0x00,0x00,0x00,0x00],
TerminalID = [0x00,0x00],
CLSID_Computer = convert_CLSID_to_DATA("20d04fe0-3aea-1069-a2d8-08002b30309d"),
CLSID_Network = convert_CLSID_to_DATA("208d2c60-3aea-1069-a2d7-08002b30309d"),
PREFIX_LOCAL_ROOT = [0x2f],
PREFIX_FOLDER = [0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
PREFIX_FILE = [0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
PREFIX_NETWORK_ROOT = [0xc3,0x01,0x81],
PREFIX_NETWORK_PRINTER = [0xc3,0x02,0xc1],
END_OF_STRING = [0x00];
if (/.*\\+$/.test(lnk_target)) {
lnk_target = lnk_target.replace(/\\+$/g, '');
var target_is_folder = true;
}
var prefix_root, item_data, target_root, target_leaf;
if (lnk_target.substr(0, 2) === '\\\\') {
prefix_root = PREFIX_NETWORK_ROOT;
item_data = [0x1f, 0x58].concat(CLSID_Network);
target_root = lnk_target.subtr(lnk_target.lastIndexOf('\\'));
if (/\\\\.*\\.*/.test(lnk_target)) {
target_leaf = lnk_target.substr(lnk_target.lastIndexOf('\\') + 1);
}
if (target_root === '\\') {
target_root = lnk_target;
}
} else {
prefix_root = PREFIX_LOCAL_ROOT;
item_data = [0x1f, 0x50].concat(CLSID_Computer);
target_root = lnk_target.replace(/\\.*$/, '\\');
if (/.*\\.*/.test(lnk_target)) {
target_leaf = lnk_target.replace(/^.*?\\/, '');
}
}
var prefix_of_target, file_attributes;
if (!target_is_folder) {
prefix_of_target = PREFIX_FILE;
file_attributes = FileAttributes_File;
} else {
prefix_of_target = PREFIX_FOLDER;
file_attributes = FileAttributes_Directory;
}
target_root = str_to_arr(target_root);
for (var i = 1; i <= 21; ++i) {
target_root.push(0);
}
var id_list_items = gen_IDLIST(item_data);
id_list_items = id_list_items.concat(
gen_IDLIST(prefix_root.concat(target_root, END_OF_STRING)));
if (target_leaf) {
target_leaf = str_to_arr(target_leaf);
id_list_items = id_list_items.concat(
gen_IDLIST(prefix_of_target.concat(target_leaf, END_OF_STRING)));
}
var id_list = gen_IDLIST(id_list_items);
var data = [].concat(HeaderSize,
LinkCLSID,
LinkFlags,
file_attributes,
CreationTime,
AccessTime,
WriteTime,
FileSize,
IconIndex,
ShowCommand,
Hotkey,
Reserved,
Reserved2,
Reserved3,
id_list,
TerminalID);
return new Blob([new Uint8Array(data)], { type: 'application/x-ms-shortcut' });
}
var blob = create_lnk_blob('C:\\Windows\\System32\\Calc.exe');
Use it like:
var blob_to_file = create_lnk_blob('C:\\Windows\\System32\\Calc.exe');
var blob_to_folder = create_lnk_blob('C:\\Users\\Myself\\Desktop\\'); // with a trailing slash
Demo: http://jsfiddle.net/5cjgLyan/2/
This would be simple if your website allows php.
If your script is part of an html file, just write the the javascript as if you were writing it to send a static lnk file. Then, at the lnk address part, break apart the javascript into two parts, breaking into html. Then at that point, put in
<?php /*PHP code set a variable *? /* PHP code to generate proper string*/ PRINT /*PHP variable*/
?>
I think make it pure client is impossible.
Even the web rtc protocol need at least one iceServer to signal other client.
And I think the easiest way to do that is use http://peerjs.com/
you could first create a clinet token of the room owner
//room owner side
peer.on('open', function(my_peer_id) {
console.log('My peer ID is: ' + my_peer_id);
});
And send the token to any other you want (by text file, web chat ...etc)
Then other connect it use the token above
//the other one
var conn = peer.connect(other_peer_id);
After the room owner detected someone entered the room.
Disconnect from signal server, so the token will become unusable
//room owner side
peer.disconnect()
About generate and read file by client side, I recommend you read article below.
http://www.html5rocks.com/en/tutorials/file/dndfiles/ read from file
How to use filesaver.js save as file
I believe the compatibility of fileReader api and blob doesn't matter.
Since there will never be a browser which support webrtc but not support fileReader api

InDesign ExtendScript script sometimes creates a corrupted PDF during export

I've had this problem for a while, now. Close to the end of my "Proofing" script, the currently opened document in InDesign is to be exported to two different .pdf files. The first is password-protected while the second is not. I don't seem to have any problems with the latter, but the former often becomes corrupted somehow and cannot be opened by any PDF reader, including Acrobat itself. Here's the code block that does the exporting (it is not runnable by itself, btw):
/********** BEGIN PDF EXPORTING **********/
// First, let's create and set PDF export preferences.
// This begins with creating a temporary preset if it doesn't already exist.
// This preset will be used for both the Proof page and the Cover sheet.
var tempPreset = app.pdfExportPresets.item("tempPreset");
try
{
tempPreset.name;
}
catch (eNoSuchPreset)
{
tempPreset = app.pdfExportPresets.add({name:"tempPreset"});
}
with (tempPreset)
{
acrobatCompatibility = AcrobatCompatibility.ACROBAT_5;
bleedMarks = false;
colorBars = false;
colorBitmapCompression = BitmapCompression.AUTO_COMPRESSION;
colorBitmapQuality = CompressionQuality.MAXIMUM;
colorBitmapSampling = Sampling.BICUBIC_DOWNSAMPLE;
colorBitmapSamplingDPI = 300;
compressTextAndLineArt = true;
cropImagesToFrames = true;
cropMarks = false;
exportGuidesAndGrids = false;
exportNonprintingObjects = false;
exportReaderSpreads = false;
exportWhichLayers = ExportLayerOptions.EXPORT_VISIBLE_PRINTABLE_LAYERS;
generateThumbnails = false;
grayscaleBitmapCompression = BitmapCompression.AUTO_COMPRESSION;
grayscaleBitmapQuality = CompressionQuality.MAXIMUM;
grayscaleBitmapSampling = Sampling.BICUBIC_DOWNSAMPLE;
grayscaleBitmapSamplingDPI = 300;
includeBookmarks = false;
includeHyperlinks = false;
includeSlugArea = false;
includeStructure = true;
monochromeBitmapCompression = MonoBitmapCompression.CCIT4;
monochromeBitmapSampling = Sampling.BICUBIC_DOWNSAMPLE;
monochromeBitmapSamplingDPI = 1200;
omitBitmaps = false;
omitEPS = false;
omitPDF = false;
optimizePDF = true;
pageInformationMarks = false;
pageMarksOffset = 0.0833;
pdfMarkType = MarkTypes.DEFAULT_VALUE;
printerMarkWeight = PDFMarkWeight.P25PT;
registrationMarks = false;
standardsCompliance = PDFXStandards.NONE;
subsetFontsBelow = 100;
thresholdToCompressColor = 450;
thresholdToCompressGray = 450;
thresholdToCompressMonochrome = 1800;
useDocumentBleedWithPDF = false;
}
currentProcess.text = "PDF export preferences"; progressWin.show();
progressIndividual.value++; if (aProducts.length > 1) {progressOverall.value++;}
// Now let's actually set the export preferences. These are for the proof page.
with (app.pdfExportPreferences)
{
pageRange = proofRange;
useSecurity = true;
disallowChanging = true;
disallowCopying = false;
disallowDocumentAssembly = true;
disallowExtractionForAccessibility = false;
disallowFormFillIn = true;
disallowHiResPrinting = true;
disallowNotes = true;
disallowPlaintextMetadata = true;
disallowPrinting = false;
changeSecurityPassword = "sky";
if (multiColor)
{
pageRange = colorTable.toString();
}
if (currentProduct.pLabel != "")
{
pageRange += "," + labelPage.name;
}
}
currentProcess.text = "Exporting PDF proof page"; progressWin.show();
progressIndividual.value++; if (aProducts.length > 1) {progressOverall.value++;}
// Before exporting the Proof page(s), hide the color bar on multicolor products.
if (multiColor) {document.layers.item("COLOR BAR").visible = false;}
// Then we save the proof page.
document.exportFile(ExportFormat.PDF_TYPE, File(jobFolder.toString() + "/" + saveName + ".pdf"), false, tempPreset);
When that produced corrupted PDFs once in a while, I thought that perhaps it was our less-than-ideal network structure causing the problem, so I instead tried exporting the PDF file to the local hard drive rather than directly to the network, then having the file be moved to the network afterward. So, the last line in the above code block was replaced with:
// First, to the local HDD.
document.exportFile(ExportFormat.PDF_TYPE, File("~/Documents/" + saveName + ".pdf"), false, tempPreset);
$.sleep(1000);
File("~/Documents/" + saveName + ".pdf").copy(File(jobFolder.toString() + "/" + saveName + ".pdf"));
$.sleep(1000);
File("~/Documents/" + saveName + ".pdf").remove();
I even added in those 1-second delays, just in case. Sadly, this hasn't helped. I am still getting a corrupted PDF every now and then. If there is any pattern to the corrupted files, I haven't been able to discern it. Does anyone have any thoughts?
It finally hit me that, if the corrupted files are not able to be opened in Acrobat, then why not just test for that after the file is created? So I created a loop that exports the PDF file and tries to open it in Acrobat. If it opens fine, then it prints and closes the file, returning a "true" message. If it is unable to do so, then it returns a "false" message to the script. Then the loop repeats so long as that message is "false". While not a great fix for the underlying cause (whatever it may be), it at least is a workaround that will do just fine for our needs. The trick is that, because we work with Macs, we have to route the message through an AppleScript instead of using BridgeTalk to communicate directly with Acrobat.
Here's the code snippet from the main InDesign script which goes through the PDF-checking loop:
// Then we save the proof page.
// The loop is to make sure that the file was saved properly.
var validFile = false; // Flag that states whether or not the file is corrupted after saving.
var rString; // String returned from Acrobat that should be either "true" or "false".
var testAndPrintFile = File("~/Documents/testAndPrint.applescript"); // The applescript file that calls Acrobat and runs a folder-level script.
var pdfFile; // A String of the filename & path that will be passed to through the applescript file to Acrobat.
var pdfArray = new Array(4); // An array to send to Acrobat. [0] is the PDF filename as a String,
// [1] is duplex if true, [2] is the printer name, and [3] is to enable printing.
if (multiTwoSided || twoPages) pdfArray[1] = "true";
else pdfArray[1] = "false";
pdfArray[2] = localPrinter;
pdfArray[3] = "true";
while (!validFile)
{
$.writeln("If this message is seen more than once, then the Proof PDF was corrupted.");
try
{
document.exportFile(ExportFormat.PDF_TYPE, File(jobFolder.toString() + "/" + saveName + ".pdf"), false, tempPreset);
}
catch (e)
{
alert("Could not save the Proof PDF. Please close any open copies of the Proof PDF, then save and print it manually.");
}
pdfFile = jobFolder.toString() + "/" + saveName + ".pdf";
pdfArray[0] = pdfFile;
$.writeln("pdfArray contains: " + pdfArray);
try
{
rString = app.doScript(testAndPrintFile, ScriptLanguage.APPLESCRIPT_LANGUAGE, pdfArray);
validFile = rString == "true";
// validFile = true;
$.writeln("validFile is " + validFile);
if (!validFile)
{
alert("It seems that the file " + unescape(pdfArray[0]) + " is corrupted. Will try to export it again.");
}
}
catch (e)
{
$.writeln("ERROR at line number " + e.line);
$.writeln(e.description);
throw new Error("ERROR at line number " + e.line + "\n" + e.description);
}
}
The testAndPrint.applescript file that this loop calls:
set pdfFile to item 1 of arguments
set duplexed to item 2 of arguments
set printerName to item 3 of arguments
set printEnabled to item 4 of arguments
tell application "Adobe Acrobat Pro"
set result to do script ("testAndPrint(\"" & pdfFile & "\", \"" & duplexed & "\", \"" & printerName & "\", \"" & printEnabled & "\");")
end tell
return result
And, finally, the folder-level Javascript file that is loaded into memory when Acrobat starts, ready to have its function called by the above Applescript file:
var testAndPrint = app.trustedFunction(function (fName, duplexed, sPrinterName, bEnablePrinting)
{
var success = true;
app.beginPriv();
console.println("fName is " + unescape(fName));
console.println("sPrinterName is " + sPrinterName);
try
{
var printDoc = app.openDoc(unescape(fName));
var pp = printDoc.getPrintParams();
if (duplexed == "true") pp.DuplexType = pp.constants.duplexTypes.DuplexFlipLongEdge;
else pp.DuplexType = pp.constants.duplexTypes.Simplex;
pp.printerName = sPrinterName;
pp.interactive = pp.constants.interactionLevel.silent;
pp.pageHandling = pp.constants.handling.none;
if (bEnablePrinting == "true") printDoc.print({bUI: false, bSilent: true, bShrinkToFit: false, printParams: pp});
printDoc.closeDoc(true);
}
catch (e)
{
console.println("ERROR at line number " + e.lineNumber);
console.println(e.message);
success = false;
}
app.endPriv();
console.println("success is " + success);
return success;
});
I hope that, perhaps, this information might be useful to anyone else running into a similar problem. It's not pretty, of course, but it certainly gets the job done.

Categories

Resources