Sunday, 12 July 2009

Editing the value of a PDF measurement tool annotation

When you add a distance, perimeter or area measurement to a PDF document, it's possible to choose the units, but impossible (at least via the UI tools) to "fake" the value shown on the label - for example to make it a real-world unit or something Acrobat can't understand like a furlong or bloit.

Luckily, measurements are stored as a PDF comment (annotation) and so we can edit them using Javascript. Below is an example JS script - to use it on the fly, select one or more measurements on the page using the Select Object tool (the big blue arrow), open Acrobat's Javascript console (Ctrl-J or Command-J), paste the code into the console, select it all and press Ctrl-Enter (Command-Enter).

It'll loop through every selected measurement, scrolling to it and temporarily making it a dashed line so you can see which one's being addressed, and ask you for a new label. You can type in anything you want, or press cancel to keep the old value.

If you move the vertices again using the measurement tool, it'll snap back to "real" units - but you can move the labels, offsets, change styles etc. and the custom value will be retained.
var sAnnots = this.selectedAnnots;
if (!sAnnots) app.alert("No measurements are selected")
else {
var dlgQ = "Enter dimension, including units";
var dlgT = "Edit measurement label";
var dlgDA,reply,nProps,aRect;
for (var i=0; i<sAnnots.length; i++) {
dlgDA = sAnnots[i].contents;
this.scroll(sAnnots[i].rect[0],sAnnots[i].rect[3]);
sAnnots[i].setProps({ style: "D", dash: [3,2] });
reply = app.response(dlgQ,dlgT,dlgDA);
nProps = { style: "S", contents: reply };
sAnnots[i].setProps(nProps);
}
}

If you're using the code repeatedly, just copy the following script into a .JS (text) file and save it in Acrobat's Javascript folder - it'll give you a new item under the Edit menu that's enabled whenever you've got a measurement selected:


app.addMenuItem({
cName: "editSelMeas", cUser: "Edit selected measurements",
cParent: "Edit",
cEnable: "event.rc = (event.target.selectedAnnots != null);",
cExec: "editSelMeasurements();"
});

function editSelMeasurements() {
var sAnnots = this.selectedAnnots;
var dlgQ = "Enter dimension, including units";
var dlgT = "Edit measurement label";
var dlgDA,reply,nProps,aRect;
for (var i=0; i<sAnnots.length; i++) {
dlgDA = sAnnots[i].contents;
this.scroll(sAnnots[i].rect[0],sAnnots[i].rect[3]);
sAnnots[i].setProps({ style: "D", dash: [3,2] });
reply = app.response(dlgQ,dlgT,dlgDA);
nProps = { style: "S", contents: reply };
sAnnots[i].setProps(nProps);
}
}