Looking for some help with Javascript in Adobe Acrobat Pro XI.
Here's what I have so far:
/* Extract pages to file */
// Regular expression used to acquire the base name of file
var re = /\.pdf$/i;
// filename is the base name of the file Acrobat is working on
var filename = this.documentFileName.replace(re,"");
try {for (var i = 0; i < this.numPages; i+=4)
this.extractPages({
nStart: i,
nEnd: i+3,
});
} catch (e) { console.println("Aborted: " + e) }
What happens now is that it extracts the page range and creates a series of open files that I can then rename.
What I'd like to do is add a loop to extract a name from the bill, then use that as the file name to create a new file in a folder.
I found this:
for (var p = 0; p < this.numPages; p++) {
// iterate over all words
for (var n = 0; n < this.getPageNumWords(p); n++) {
if (this.getPageNthWord(p, n) == stringToSearchFor) {
pageArray.push(p);
break;
}
}
}
which I think will get me part of the way there, but I'm not sure how to include that in my loop.
I think I need to search the document a static string (in this case "Student Name") and then return the next two words.
Worked up a file to do this sort of thing using copy-pasted code (and some help from Thom Parker on the Adobe Forums, see: https://community.adobe.com/t5/acrobat/step-by-step-instructions-for-saving-a-pdf-in-acrobat-dc-using-a-javascript/m-p/10893916?page=1#M238905)
// https://community.adobe.com/t5/acrobat/how-to-set-up-a-default-value-in-execdialog/td-p/9343585?page=1
var dialogTitle = "Please specify ";
var defaultAnswer = "";
var stringToSearchFor = app.response("Client ID",
dialogTitle, defaultAnswer);
//https://acrobatusers.com/tutorials/print/how-save-pdf-acrobat-javascript/
/* Put script title here */
// Iterates over all pages and find a given string and extracts all
// pages on which that string is found to a new file.
var pageArray = [];
//var stringToSearchFor = "64718";
for (var p = 0; p < this.numPages; p++) {
// iterate over all words
for (var n = 0; n < this.getPageNumWords(p); n++) {
if (this.getPageNthWord(p, n) == stringToSearchFor) {
pageArray.push(p);
break;
}
}
}
if (pageArray.length > 0) {
// extract all pages that contain the string into a new document
var d = app.newDoc(); // this will add a blank page - we need to remove that once we are done
for (var n = 0; n < pageArray.length; n++) {
d.insertPages( {
nPage: d.numPages-1,
cPath: this.path,
nStart: pageArray[n],
nEnd: pageArray[n],
} );
}
// remove the first page
d.deletePages(0);
// https://community.adobe.com/t5/acrobat/how-to-save-as-pdf-form-using-script/td-p/9848947?page=1
// Split Path into an array so it is easy to work with
var aMyPath = this.path.split("/");
// Remove old file name
aMyPath.pop();
// Add new file name
aMyPath.push(stringToSearchFor);
// Put path back together and save
d.saveAs(aMyPath.join("/")+".pdf");
}
Related
Short term problem: I have three paths on an artboard. The end of one path has a point at the same position as the beginning of another. The other path is separate. They are all grouped. I have some code that loops through the pathsin the group, and if one path ends where another begins it tried to join them together. The group must be highlighted. To start with my artboard look like this (The top line is two paths):
An after the script is run it looks like this:
With a lot of points added to the end of the line underneath. Could someone lend me a hand with this, Ideally, I'd like it to look like this:
The code looks like this:
var doc = activeDocument;//Gets the active document
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var intersections = true
var group = doc.selection[0]
var paths = []
var intersecttions = 0
// Builds an array of all the paths in the grouped object
if (group !== undefined && group.pageItems.length >= 2) {
for (var i = 0; i < group.pageItems.length; i++) {
var item = group.pageItems[i];
if (item instanceof PathItem) {
item.id = 'Path No' + i;
paths.push(item)
}
}
}
//Sets the first path that will be added to
$.write('paths length ', paths.length,'\n')
var chain = paths[0]
var chainPoints = chain.pathPoints
var chainLength = chainPoints.length - 1
var c1 = chainPoints[0]
var c2 = chainPoints[chainLength]
$.write('c ', c1.anchor,':::', c2.anchor,'\n')
//loops through the paths in the group to see if any overlap the first past
for (var i = 1; i < paths.length-1; i++) {
var link = paths[i]
$.write(link, '\n')
var linkPoints = link.pathPoints
var linkLength = linkPoints.length - 1
$.write('l ', l1.anchor, ':::', l2.anchor, '\n')
if (toString(c1.anchor) === toString(l2.anchor)) {
$.write('inttersection', '\n')
$.write('link', link.id, '\n')
for (var j = 0; j < linkLength; ++j) {
chain.pathPoints.add(linkPoints[j])
$.write (linkPoints[j], '\n')
}
}
}
The first problem is that it's not detecting the instance of overlap correctly. The line:
if (toString(c1.anchor) === toString(l2.anchor)) {
is not comparing one string to another but comparing a true response with another true response. It should be:
if (String(c1.anchor) === String(l2.anchor)) {
you also have to pass across the attributes of each point you are adding to the line and remove the old line, so within the j loop you'll need to add the following
for (var j = 0; j < linkLength; ++j) {
var pp1 = chainPoints.add()
var p2i = linkPoints[j];
pp1.anchor = p2i.anchor;
pp1.rightDirection = p2i.rightDirection;
pp1.leftDirection = p2i.leftDirection;
pp1.pointType = p2i.pointType;
pp1.handle = p2i.handle;
}
link.remove();
This seems to work except that it doesn't add the last point of the second line. I'm guessing that the loop length may not be set correctly If I work it out I'll update the post. I found this in Hiroyuki Sato code for his JoinReasonable scripts http://shspage.com/aijs/en/
I try to make a javascript code for ImageJ, wich have to goal to allow me to select a directory, and return me all jpg and jpeg file in the directory and sub-directory.
I have do this code, it's work well for direct children, he call well getJpeg on subdirectories (I have verify it with some IJ.log), but the jpeg Array is not concat with result of recursives call
Have you an idea?
importClass(Packages.ij.IJ);
importClass(Packages.ij.plugin.frame.RoiManager);
importClass(Packages.ij.gui.GenericDialog);
importClass(Packages.ij.io.OpenDialog);
importClass(Packages.java.io.File);
var dirstr = IJ.getDirectory("Choose the stacks folder");
var jpeg = getJpeg(dirstr);
for (var i = 0; i < jpeg.length; i++) {
IJ.log(jpeg[i]);
}
function getJpeg(dirst) {
var dir = new java.io.File(dirst);
var names = dir.listFiles();
var jpeg = new Array();
for (var i = 0 ; i < names.length; i++) {
if(names[i].isDirectory()){
jpeg.concat(getJpeg(names[i].getPath()));
continue;
}
var namest = names[i].getName();
if (namest.match(/.*\.jpg|jpeg/)) {
var path = names[i].getPath();
jpeg.push(path);
}
}
return jpeg;
}
Thank you :)
The problem come from a missread from concat documentation ( w3schools.com/jsreF/jsref_concat_array.asp ). Have to put
jpeg = jpeg.concat(getJpeg(names[i].getPath()));
We have a workbook which contains two dashboards, the first contains one worksheet and the second contains four worksheets.
We're trying to pass filters in via the url (that part is ok) but we cannot get all the worksheets on the second dashboard to update.
The code loops through the dashboards, activating each in turn then calling a filterActiveSheet() method on each.
This method loops through each worksheet in turn, searches for a matching categorical filter with the same FieldName as the provided one and, when found, uses the applyFilterAsync() method to replace it with the provided one.
var options = {
< snip >
onFirstInteractive: function () {
workbook = viz.getWorkbook();
sheets = workbook.getPublishedSheetsInfo();
for(s = 0; s < sheets.length; s++)
{
viz.getWorkbook().activateSheetAsync(s)
.then(filterActiveSheet);
}
}
};
function filterActiveSheet(sheet) {
for (ws = 0; ws < sheet.getWorksheets().length; ws++) {
var worksheet = sheet.getWorksheets()[ws];
worksheet.getFiltersAsync()
.then(function(p) {
var f = filters.split(';');
for(y=0;y<f.length;y++){
var filter = f[y].split(':');
var filterType = $.grep(p, function(e){ return e.getFieldName() == filter[0]; });
if (filterType.length > 0) {
switch(filterType[0].getFilterType()) {
case tableau.FilterType.CATEGORICAL:
return worksheet.applyFilterAsync(filter[0], filter[1], tableau.FilterUpdateType.REPLACE);
break;
< snip >
}
}
}
});
}
}
var viz = new tableauSoftware.Viz(placeholderDiv, url, options);
The problem we're seeing is that only one worksheet on each dashboard is being updated. Stepping through the JS in Chrome I can see the call to applyFilterAsync() the expected number of times which does not seem to cause an error, it simply doesn't seem to want to update all the filters/worksheets, just one on each dashboard.
Thoughts? Suggestions? Syntax errors?
getPublishedSheetsInfo() returns a collection that is returning one worksheet and one dashboard the types of which can be determined by calling getSheetType(). You can't apply getFilterAsync() directly to a dashboard but have to iterate. Try something like:
if (sheet.getSheetType() === 'WORKSHEET') {
sheet.getFiltersAsync().then(function(filters) {
for (var x = 0; x < filters.length; x++) {
// do something
}
})
} else {
// either in a dashboard or story
var workSheetArray = sheet.getWorksheets();
for (var i = 0; i < workSheetArray.length; i++) {
workSheetArray[i].getFiltersAsync().then(function(filters) {
for (var x = 0; x < filters.length; x++) {
// do something
}
}
}
}
I'm attempting to teach myself javascript. I chose something I assumed was simple, but ran into problems relatively quickly.
I'm attempting to search a string for another string given by the user.
My code so far is:
var source = "XREs2qqAQfjr6NZs6H5wkZdOES5mikexRkOPsj6grQiYNZfFoqXI4Nnc1iONKVrA";
var searchString = []; //the users input
searchString = prompt("Enter search string");
var hits = [];
var one = 0;
var two = 0;
var k = 0;
var sourceSearch = function(text) {
for(i = 0; i < source.length; i++) { //for each character in the source
if(source[i] === searchString[0]) { //if a character in source matches the first element in the users input
one = source.indexOf(i); //confused from here on
for(p = searchString.length; p > 0; p--) {
}
}
}
};
sourceSearch(searchString);
My idea was:
check to see if the first loop finds a character that matches the first character in the user input
if it matches, check to see if the next X characters after the first match the next X characters in the source string
if they all match, push them to the hits array
My problem: I have no idea how to iterate along the arrays without nesting quite a few if statements, and even then, that wouldn't be sufficient, considering I want the program to work with any input.
Any ideas would be helpful. Thanks very much in advance.
Note: There are a few un-used variables from ideas I was testing, but I couldn't make them work.
You can try:
if (source.indexOf(searchString) !== -1) {
// Match!
}
else
{
//No Match!
}
As the other answers so far point out, JavaScript strings have an indexOf function that does what you want. If you want to see how it's done "by hand", you can modify your function like this:
var sourceSearch = function(text) {
var i, j, ok; // always declare your local variables. globals are evil!
// for each start position
for(i = 0; i < source.length; i++) {
ok = true;
// check for a match
for (j = searchString.length - 1; ok && j >= 0; --j) {
ok = source[i + j] === searchString[j];
}
if (ok) {
// searchString found starting at index i in source
}
}
};
This function will find all positions in source at which searchString was found. (Of course, you could break out of the loop on the first success.) The logic is to use the outer loop to advance to each candidate start position in source and use the inner loop to test whether that position actually is the position of a match to searchString.
This is not the best algorithm for searching strings. The built-in algorithm is much faster (both because it is a better algorithm and because it is native code).
to follow your approach, you can just play with 2 indexes:
var sourceSearch = function(text) {
j = 0;
for(i = 0; i < source.length; i++) {
if(source[i] === text[j]) {
j++;
} else {
j = 0;
}
if (j == text.length) {
console.log(i - j); //this prints the starting index of the matching substring
}
}
};
These answers are all pretty good, but I'd probably opt for something like this:
var source = "XREs2qqAQfjr6NZs6H5wkZdOES5mikexRkOPsj6grQiYNZfFoqXI4Nnc1iONKVrA";
var searchString = []; //the users input
searchString = prompt("Enter search string");
var hits = source.split(searchString);
var hitsCount = hits.length - 1;
This way you have all of the data you need to figure out where each hit occurred in he source, if that's important to you.
I want to get the file endings from some files in a list.
File 1
File 2
File 3
File 4
Basically, the file endning could be anything, and the string can contain more than just one ".". So I need to fetch the ending only.
I want to get a result that looks like:
mp4
ogg
mp3
jpg
Thanks.
You can get the extensions for all links in a document like this:
var endings = [];
var links = document.getElementsByTagName("a");
var matches;
for (var i = 0; i < links.length; i++) {
if (links[i].href) {
matches = links[i].href.match(/\.([^\.]+)$/);
if (matches) {
endings.push(matches[1]);
}
}
}
// the array endings contains a list of all link extensions
Here's a working version of the code: http://jsfiddle.net/jfriend00/XHKaT/
The regular expression here matches a period followed by one or more non-period characters at the end of the string. The parenthesized grouping allows us to extra just the extension without the period which accomplishes the result you outlined.
This function performs as you need without reporting duplicates and maintaining the order in which the filename extensions are discovered.
function getLinkedFileExtensions() {
var i, len=document.links.length, ext=[], exts={};
for (i=0; i<len; i++) {
var a = document.links[i];
if (a.href && a.href.match(/\.([A-Za-z0-9]{1,4})$/)) {
var x = RegExp.$1;
if (!(x in exts)) {
exts[x] = true;
ext.push(x);
}
}
}
return ext;
}
var ext = [].map.call(document.links, function (a) {
return (a.href.match(this) || [])[1] || "";
}, /\.([a-zA-Z0-9]*)$/).filter(String);
http://jsfiddle.net/hZ9cU/
You can use jQuery to:
Get all of your anchor elements.
For each element you can access the .attr("href") value which will be your address string i.e. "myfile.mp3"
Then you can split the string on "." character and add the value at tokenArray[tokenArray.length-1] to your result list.
Or for vanilla JS try:
function getExtensions(){
var allAnchorTags = document.getElementsByTagName("a");
var extensions = new Array();
for(var i = 0; i < allAnchorTags.length; i++){
var tokenArray = allAnchorTags[i].href.split(".");
extensions[i] = tokenArray[tokenArray.length-1];
}
return extensions;
}
which does the same as described in my algorithm except with vanilla JS syntax. Give it a shot
See Feedle
var ext = a.href.split(".");
ext = ext[ext.length -1];
console.log(ext);
EDIT :
var d = document.getElementsByTagName("a"),
ext, i, j;
for(i = 0, j = d.length; i<j; i++){
ext = d[i].href.split(".");
ext = ext[ext.length -1];
console.log(ext);
}