Specific Selection to Merge Text
Copy link to clipboard
Copied
Hello all, beginner-ish javascripter here. I've been looking into creating a script for my job to automate the merging of text elements on my floorplans, and have thus far been successful. The main() function in my script takes a single text group and merges the elements inside the group together, to form one block of text, then groups it again.
The issue I am having is with the next step, which is running a loop to perform the main function on each appropriate text item in the plan at once. I believe the issue I'm running into doesn't have to do with the main function, as it works just fine if the user goes in and selects each text piece they want to merge. But that's just a theory, and after banging my head against this for the past 6 hours, I'm running out of ideas.
I'll omit the main() function for now, as it's pretty long. This is my latest attempt:
Explore related tutorials & articles
Copy link to clipboard
Copied
1. Your goals, both general and specific to the shared code, are unclear to me. If the below doesn't fix your problem, can you elaborate on this a little more?
2. The purpose of cull() seems to be to push items with 2+ children items (i.e. groupItems and/or compoundPathItems) into the array mergeItems. As it is, "select.pageItems" will throw an error if "select" doesn't have any "pageItems". You can delete this line and change the test to
if (select.typename == "GroupItem") {
3. You then iterate the array mergeItems, calling cull() for each element. Is this intentional?
Copy link to clipboard
Copied
Appreciate the help, unfortunately the script still throws up errors. Let me explain the goal of this script in greater detail. Firstly, my main function. What this essentially does is take the user's selection whether it's grouped or ungrouped, and merges the text together. The base code is found here: http://www.ajarproductions.com/adobe_extensions/ai/MergeText_AI_CS1.js
I built on and modified it by adding functionality for rotated text, sorting options, and centering the paragraph style. As far as I know, this part of the code works flawlessly, assuming the user makes a valid selection.
Secondly, the automation portion. All I really need this function to do is parse through each text item in the document, and merge it if it needs to be merged. So, for example, see the attached image. I need the script to be able to find each of the circled items, and individually merge them, while skipping over the other text items. Assuming the main function works as intended, all I need to do here is select each element that needs to be merged and run the main function on it.
In the original code above, I call cull() for each element because the main() function does some ungrouping and regrouping, so I wasn't sure if this would mess up the mergeItems array or not, so I figured redefining the array for each element would solve for this. Sorry if the original posting was vague, hopefully this helps a bit.
Copy link to clipboard
Copied
I can't run Ajar's script as it is. There is at least one undefined non-native function (newOminoDialog). I can run Wundes' script, so I think I understand what you mean by merging textFrames. So the next question is: How are you deciding which two (or more) textFrames to merge at a time?
Copy link to clipboard
Copied
At my job the floorplans come in as PDFs with all of the text elements grouped. So I want to merge text groups that have multiple elements inside the grouping, and ignore the others, if that makes sense. And that is the bit that's giving me issue, automating the selecting of each group that needs to be merged one by one, then running the merge script on it.
Copy link to clipboard
Copied
I would iterate the groups, then iterate the textFrames within these groups, selecting these textFrames, running the main function and then deselecting all. E.g. (this worked for me on a first attempt)
var groups = app.activeDocument.groupItems;
for (var i = 0; i < groups.length; i++) {
for (var j = 0; j < groups[i].textFrames.length; j++) {
groups[i].textFrames[j].selected = true;
}
main();
app.executeMenuCommand("deselectall");
}
function main() {
// Wundes' script, minus the alerts
}
Copy link to clipboard
Copied
Ok so that successfully selected all the text that needed to be merged, but it still threw up an error when I tested it with the main function. In the main function, "app.activeDocument.selection" is called quite a bit, is this where my issue lies? Does that selection have to be user defined? Either way, appreciate you taking the time to help, thanks a ton.
Copy link to clipboard
Copied
Adobe won't let me upload a .jsx file, so here's a link to the code if you'd like to take a look at the whole thing.
https://www.dropbox.com/s/s26p2qmdzq434g7/MergeText_AI.jsx?dl=0
Copy link to clipboard
Copied
I'll have a look and get back if can make it work.
Copy link to clipboard
Copied
Calling main() when a group possesses no fextFrames seemed to through an error. Skipping these groups and deselecting all just before selecting the target fextFrames and calling main() seems to work. I've not changed main() itself. I'm a bit wary, because it was all too easy.
app.selection = null;
var aDoc = app.activeDocument;
var groups = aDoc.groupItems;
for (var i = 0; i < groups.length; i++) {
if (groups[i].textFrames.length > 0) {
app.selection = null;
for (var j = 0; j < groups[i].textFrames.length; j++) {
if (groups[i].textFrames.length > 1) {
groups[i].textFrames[j].selected = true;
}
}
main();
}
}
function main(){
var aDoc = app.activeDocument;
var x = 0;
var y = 0;
var largestWidth = 0;
var sLength = aDoc.selection.length;
var sel = aDoc.selection[0];
function ungroupJ(){
app.executeMenuCommand("ungroup");
}
function groupJ(){
app.executeMenuCommand("group");
}
function orientate(){
ungroupJ();
sel = aDoc.selection[0];
var anchorY = Number((sel.anchor[1]).toFixed(1));
var topLeftY = Number((sel.position[1]).toFixed(1));
var anchorX = Number((sel.anchor[0]).toFixed(1));
var topLeftX = Number((sel.position[0]).toFixed(1));
if (anchorX == topLeftX) {
var orient = "straight";
}
else if (anchorY == topLeftY) {
var orient = "left";
}
else if (anchorY < topLeftY) {
var orient = "right";
}
return orient;
}
var orient = orientate();
if (orient != "straight"){
groupJ();
sel = aDoc.selection[0];
if (orient == "left"){
sel.rotate(90);
}
else if (orient == "right"){
sel.rotate(270);
}
ungroupJ();
}
while (x < sLength) {
testWidth = aDoc.selection[x].width;
if (testWidth > largestWidth) largestWidth = testWidth;
x++;
}
x = 0
while (x < sLength) {
if (aDoc.selection[x].width == largestWidth) var coreObj = aDoc.selection[x];
x++;
}
var objLoc1 = coreObj.left;
/*******************************************
* begin code for Merging Text
********************************************/
if(app.documents.length >= 1) {
var sortProp = "top";
var doc = app.activeDocument;
var sel = doc.selection;
var tfs = new Array();
var separator = "\r";
var appversion = app.version;
var minimumversion = 13;
var aiversion = parseInt(appversion.split(".")[0]);
init();
} else {
alert("No documents open");
}
function init(){
collectFields();
if(tfs.length> 1) {
if(aiversion >= minimumversion) run();
else run();
} else if (tfs.length == 1) {
alert("You must select more than one textfield.");
} else {
alert("No textfields selected.");
}
}
function collectFields() {
for(var i=0; i < sel.length; i++){
var t = sel[i];
if (t == undefined) continue;
if(t.typename == "TextFrame"){
//t.position //for text boxes
//$.writeln(t.position);
tfs.push(t);
}
}
}
function run () {
//position for sorting---------
if(sortProp == "right") flipFields(tfs, -100, 100);
else if(sortProp == "bottom") flipFields(tfs, 100, -100);
//-------------------------------
tfs.sort(sortFields);
//reset----------
if(sortProp == "right") flipFields(tfs, -100, 100);
else if(sortProp == "bottom") flipFields(tfs, 100, -100);
//----------------
doc.selection = tfs;
assemble(tfs);
}
function flipFields(arr, scaleX, scaleY) {
var g = group(arr);
g.resize(scaleX, scaleY);
var items = ungroup(g);
}
function assemble(arr){
var targField = arr.shift();
for (var i=0; i<arr.length; i++){
arr[i].textRange.contents = separator + arr[i].textRange.contents;
arr[i].textRange.move(targField, ElementPlacement.PLACEATEND);
arr[i].remove();
}
}
function sortFields(a,b) {
var tProp = sortProp;
if(tProp == "bottom") tProp = "top"; //use flipped values
else if(tProp == "right") tProp = "left"; //use flipped values
var aN = parseFloat(a[tProp]);
var bN = parseFloat(b[tProp]);
var returnVal = aN - bN;
if(returnVal == 0) {
//second level sorting
if(tProp == "top") tProp = "left";
else if(tProp == "left") tProp = "top";
aN = parseFloat(a[tProp]);
bN = parseFloat(b[tProp]);
returnVal = aN - bN;
}
if(tProp == "top") returnVal *= -1; //y is reverse
return returnVal;
}
function group(arr){
var g = doc.groupItems.add();
for(var i=0; i < arr.length; i++){
arr[i].move(g, ElementPlacement.INSIDE);
}
return g;
}
function ungroup(group){
var items = new Array();
var numItems = group.pageItems.length;
for(var i=numItems-1; i >=0; i--){
var item = group.pageItems[i].move(group.parent, ElementPlacement.INSIDE);
items.push(item);
}
group.remove();
return(items);
}
function replace(searchStr, findStr, replaceStr){
//fl.trace('replacing...' + findStr + '...with...' + replaceStr + '...in: ' + searchStr);
var tArr = searchStr.split(findStr);
var returnStr = tArr.join(replaceStr);
return returnStr;
}
// //for testing only
// function traceFields(arr){
// $.writeln("----------------");
// for(var i=0; i<arr.length; i++){
// $.writeln(arr[i].contents + "// 1: " + Math.round(arr[i].left) + ", 2: " + Math.round(arr[i].top) );
// }
// $.writeln("----------------");
// }
var obj = aDoc.selection[0];
//Center and shift text - Josh
obj.textRange.justification = Justification.CENTER;
var objLoc2 = obj.left;
var textLoc = objLoc1 - objLoc2;
aDoc.selection[0].translate(textLoc);
groupJ();
sel = aDoc.selection[0];
if (orient != "straight"){
if (orient == "left"){
sel.rotate(270);
}
else if (orient == "right"){
sel.rotate(90);
}
}
}
Copy link to clipboard
Copied
Alright at this point I have no clue what I'm doing wrong. Still won't work for my floorplans, or even for a random document I set up to test, with only various groups of text. Which is becoming increasingly strange, because it looks like it worked flawlessly for you. Can I ask what version of illustrator you're on? I have the most up to date one downloaded, but I just don't see how it could work on your end and not mine...
Copy link to clipboard
Copied
I'm using CS6, but I doubt that the version of Illustrator is a factor. What error message did you get?
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I believe this mean's it's not finding the next object, it's the error I've been getting all along. See attached
Copy link to clipboard
Copied
I am not sure about your code's objectives too, but the one script example that comes to mind is the John Wundes tie-text script. Here is a Graphics stackexchange answer that explains everything: https://graphicdesign.stackexchange.com/questions/57730/merge-point-text-objects-into-one-text-area-...
If you'd like to merge broken text while preserving as much of the formatting, placement, paragraphs and other typography of the existing text as you can, rather than pasting into a newly created text area as plain text, you can try John Wundes' amazing Join Text Frames script.
Copy link to clipboard
Copied
Appreciate the help, but after testing it, Wundes' script essentially does the same thing as my main() function. My goal is to automate this process, so that rather than the user going through and selecting each text element and running the script, they can hit one button and the script will go through and select each text element, merge it, and move on to the next.

