Copy link to clipboard
Copied
Background: We use red font to indicate changes in the draft document. Then we change the red text back to black before issuing the final version of the document. We sometimes have master page borders and artwork that we use red text with that we do NOT want to change.
Four questions:
Thanks in advance!
-
var doc, textRange;
doc = app.ActiveDoc;
textRange = doc.TextSelection;
applyTextColor (textRange, "Black", doc);
function applyTextColor (textRange, colorName, doc) {
var color, prop;
// Get the color object.
color = doc.GetNamedColor (colorName);
// Make sure the color exists in the document.
if (color.ObjectValid () === 1) {
// Make a property list containing the color.
prop = new PropVal ();
prop.propIdent.num = Constants.FP_Color;
...
@frameexpert - THANK YOU!!!!
I got the script working. Seems to do fine. Here is the full find and replace script in case anyone searches this thread:
main();
function main(){
var doc = app.ActiveDoc;
if(!doc.ObjectValid())
{
alert("No active document. Cannot continue.");
return;
}
FindAndReplaceColor(doc, doc.MainFlowInDoc, 'Red', 'Black') ;
}
function FindAndReplaceColor(doc, flow, findString, replaceString) {
// https://community.adobe.com/t5/framemaker-discussions/find-
...
Copy link to clipboard
Copied
Hopefully last issue for a while ...
The script is working. In the grand scheme, what I want to do is click a button and the script will turn the red text to black, bring up the print dialog, allow to save as a PDF, and then revert to Saved, which will bring back the red text.
I didn't see anything in FrameMaker Scripting.pdf about revert, other than:
Fcodes ([FCodes.KBD_REVERT]);
That should work, however, it brings up a pop-up "Are you sure?" and the default is no. About the time that the pop-up appears, the PDF is created and opens and somehow FM interprets that as "No", so the reversion never happens.
Edit: It's actually somewhat worse than I said. The script doesn't accidentally click "No". When the PDF file opens, the "Do you want to revert" pop-up gets moved behind the other open windows, so when you try to close FM, you get a "Cannot Quit" message and you have to hope you see it when you do a show desktop or similar.
Copy link to clipboard
Copied
The issue with the "Revert To Saved" pop-up seems to be a timing issue and not consistent. Often the pop-up goes in back of the FM window when the PDF opens, but sometimes it stays on top.
I've worked around it by adding a 7-second delay:
$.sleep(7000);
between the print menu and the revert to save command. That seems to work for most documents - although for longer documents, I might cause the issue b/c I inserted the delay.
Also, the option to open the PDF on creation is a function of the Adobe PDF and Power PDF "printers". Microsoft Print to PDF doesn't have the option and if it is turned off, the issue shouldn't occur (but it's a nice feature).
Copy link to clipboard
Copied
Revert to saved could be done programmatically by simply closing the document without saving and then opening it again. You should make this a new post if you want to pursue it.
Copy link to clipboard
Copied
@frameexpert - I hadn't thought of that. Great suggestion. Right now, with the delay, I'm okay with the pop-up message, but I'll consider your idea and start a new thread if I run into issues (which unfortunately is likely).
Copy link to clipboard
Copied
I got it working properly now. I created my own pop-up message which asks if they want to save or revert and explains what changed (Revert brings back the red font, Save leaves the text black). If they select Revert, the script closes and re-opens the file as you suggested.)
Copy link to clipboard
Copied
@frameexpert - New question and helping the community. Your previous script works whether any text is selected or not. I would like the script to display a message if no text is selected.
I found a solution from here: https://community.adobe.com/t5/framemaker-discussions/find-in-selection-with-extendscript/td-p/11866...
But I'm wondering if there is a simpler way, but this does work:
var doc, textRange
doc = app.ActiveDoc;
textRange = doc.TextSelection;
if (getText(textRange,doc)===""){
alert("No Selected Text");
}
else{
applyTextColor (textRange, "Black", doc);
}
function getText (textObj, doc) {
// Gets the text from the text object or text range.
var text = "", textItems, i;
// Get a list of the strings in the text object or text range.
if (textObj.constructor.name !== "TextRange") {
textItems = textObj.GetText (Constants.FTI_String);
}
else {
textItems = doc.GetTextForRange(textObj, Constants.FTI_String);
}
// Concatenate the strings.
for (i = 0; i < textItems.len; i += 1) {
text += (textItems[i].sdata);
}
return text; // Return the text
}
Thanks again!!!
Copy link to clipboard
Copied
@frameexpert I'm running into a new issue now (I think) with resetting variables.
My find and replace script is supposed to show how many times it made a change to the document. I want it to only show the popup to revert the document to saved if it actually found and changed red text to black.
I'm using a test like this:
var doc = app.ActiveDoc;
var FoundRed
FoundRed = FindAndReplaceColor(doc, doc.MainFlowInDoc, 'Red', 'Black');
alert (FoundRed);
Usually, that works - i.e. I run the script on a document with two instances of red text, and it returns "2". I run it again and it returns "0".
Sometimes it won't work correctly - i.e. I run it once and it returns 109. I run it again and it returns 57, even through the document was just cleaned and does not have any red text.
I tried initializing FoundRed to "0" or "-1' (although I shouldn't have to), and that didn't work either.
For reference, the main script looks like this:
// Remove red font - Find and Replace Color didn't always run without the sleep statements.
$.sleep(500);
doc.SimpleSave(doc.Name, false);
$.sleep(500);
var FoundRed = -1;
FoundRed = FindAndReplaceColor(doc, doc.MainFlowInDoc, 'Red', 'Black');
$.sleep(500);
// Print
#include "Print_To_PDF.jsx"
$.sleep(500);
alert(FoundRed);
alert(FoundRed);
if (FoundRed!==0)
{
switch (CustomConfirm("Revert will close and re-open the document (preserving the red font text, if there was any)." +
"\r\rSave will save the document as it is (red font text converted to black)." +
"\r\rIf multiple customers are being processed, click revert after completion of PDF generation.", "Revert or Save?", 1, "Revert", "Save", "Don't Save")) {
case "Save":
doc.SimpleSave(doc.Name, false);
break;
case "Revert":
// Close without saving and re-open is used instead of KBD_REVERT to avoid the confirmation pop-up.
var docpath = doc.Name;
doc.Close(Constants.FF_CLOSE_MODIFIED);
openDocOrBook(docpath, true);
win.close();
Win_Reopen();
Ckbx_CondInd_TCTO.value = RainbowState;
Ckbx_RedText_TCTO.value = RedTextState;
doc = app.ActiveDoc;
// Fcodes ([FCodes.KBD_REVERT]);
}
}
Any idea what is going on or how to fix it?
Thanks in advance!
Copy link to clipboard
Copied
I am not sure how you are incrementing the counter in your FindAndReplaceColor function, so here is a contrived example where I am counting the total number of table paragraphs in the main flow of the document. If you initialize a counter in each function, you have to return the value to the calling function.
var doc, tblPgfs;
doc = app.ActiveDoc;
// Initialize the counter outside of the count function.
tblPgfs = 0;
// Run the main count function.
tblPgfs = countTableParagraphs (doc);
alert (tblPgfs);
function countTableParagraphs (doc) {
var textList, count, i, tblPgfs;
tblPgfs = 0;
// Get all of the tables in the main text flow.
textList = doc.MainFlowInDoc.GetText (Constants.FTI_TblAnchor);
count = textList.length;
// Process each table.
for (i = 0; i < count; i += 1) {
tblPgfs += processTable (textList[i].obj);
}
// Return the paragraph count for all main flow tables.
return tblPgfs;
}
function processTable (tbl) {
var pgfCount, pgf, cell;
pgfCount = 0;
if (tbl.TblTitlePosition !== Constants.FV_TBL_NO_TITLE) {
pgf = tbl.FirstPgf;
while (pgf.ObjectValid () === 1) {
pgfCount += 1;
pgf = pgf.NextPgfInFlow;
}
}
cell = tbl.FirstRowInTbl.FirstCellInRow;
while (cell.ObjectValid () === 1) {
if (cell.CellIsStraddled === 0) {
pgf = cell.FirstPgf;
while (pgf.ObjectValid () === 1) {
pgfCount += 1;
pgf = pgf.NextPgfInFlow;
}
}
cell = cell.NextCellInTbl;
}
return pgfCount;
}
Copy link to clipboard
Copied
Here is the same type of script, but I use a single counter variable that I pass along (and return) to each function.
var doc, tblPgfs;
doc = app.ActiveDoc;
// Initialize the counter outside of the count function.
tblPgfs = 0;
// Run the main count function, passing in the counter.
tblPgfs = countTableParagraphs (doc, tblPgfs);
alert (tblPgfs);
function countTableParagraphs (doc, tblPgfs) {
var textList, count, i;
// Get all of the tables in the main text flow.
textList = doc.MainFlowInDoc.GetText (Constants.FTI_TblAnchor);
count = textList.length;
// Process each table.
for (i = 0; i < count; i += 1) {
tblPgfs += processTable (textList[i].obj, tblPgfs);
}
// Return the paragraph count for all main flow tables.
return tblPgfs;
}
function processTable (tbl, tblPgfs) {
var pgf, cell;
if (tbl.TblTitlePosition !== Constants.FV_TBL_NO_TITLE) {
pgf = tbl.FirstPgf;
while (pgf.ObjectValid () === 1) {
tblPgfs += 1;
pgf = pgf.NextPgfInFlow;
}
}
cell = tbl.FirstRowInTbl.FirstCellInRow;
while (cell.ObjectValid () === 1) {
if (cell.CellIsStraddled === 0) {
pgf = cell.FirstPgf;
while (pgf.ObjectValid () === 1) {
tblPgfs += 1;
pgf = pgf.NextPgfInFlow;
}
}
cell = cell.NextCellInTbl;
}
return tblPgfs;
}
Copy link to clipboard
Copied
I am not sure how you are incrementing the counter in your FindAndReplaceColor function,By @frameexpert
Script was earlier in this thread, but:
function FindAndReplaceColor(doc, flow, findString, replaceString) {
// https://community.adobe.com/t5/framemaker-discussions/find-replace/td-p/3581679#4032650
// https://community.adobe.com/t5/framemaker-discussions/find-and-replace-text/td-p/14438481#M82917
// https://community.adobe.com/t5/framemaker-discussions/script-to-change-red-text-to-black/m-p/1529323...
var tr = new TextRange();
var restoreTR,
frame = 0;
var loopCounter = 0,
replacementCounter = 0;
var findParams = new PropVals();
//if the flow object is not valid, assume the main flow
if (doc.ObjectValid() && !flow.ObjectValid()) {
flow = doc.MainFlowInDoc;
}
//get the first text frame in the flow, a starting point to
//find the first paragraph
if (flow.ObjectValid()) {
frame = flow.FirstTextFrameInFlow;
}
//At this point, if we don't have a frame object, might as well abort.
if (!frame.ObjectValid()) {
AutocloseAlert("Could not find a starting point for the search. Cannot continue.");
return replacementCounter;
}
//Turn off document display to speed the script and prevent flicker.
if (app.Displaying === 1) {
app.Displaying = 0;
}
//store the original text selection as an amenity to restore after the action.
restoreTR = doc.TextSelection;
//now, set up the starting text range as the very beginning
//of the flow. We'll move straight from beginning to end.
// Hide the saftety heading, if shown to prevent it changing to black. We will restore it later.
var CondFmt = doc.GetNamedObject(Constants.FO_CondFmt, "Safety heading");
if (CondFmt.ObjectValid) {
var IsSafety = CondFmt.CondFmtIsShown;
if (IsSafety) {
CondFmt.CondFmtIsShown = 0;
}
}
tr.beg.obj = tr.end.obj = frame.FirstPgf;
tr.beg.offset = tr.end.offset = 0;
//set up our find parameters. We want to configure it to look
//for the color format. We don't need
//the find to wrap because we are controlling the flow from
//beginning to end. (But the find wraps anyway, even if you tell it not to do so.)
findParams = AllocatePropVals(1);
var color = doc.GetNamedColor(findString);
findParams[0].propIdent.num = Constants.FP_Color;
findParams[0].propVal.valType = Constants.FT_Id;
findParams[0].propVal.obj = color;
//findParams[1].propIdent.num = Constants.FS_FindWrap ;
//findParams[1].propVal.valType = Constants.FT_Integer;
//findParams[1].propVal.ival = 0 ; // no wrap
//findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;
//findParams[1].propVal.valType = Constants.FT_Integer;
//initialize the errno global, which will be used to
//track the progress of the find and replace
FA_errno = Constants.FE_Success;
//and do an initial find to get started.
tr = doc.Find(tr.beg, findParams);
//now, run the find and replace loop as long as we keep finding things.
//The loop counter is just an emergency back door in case something
//goes critically wrong and causes an endless loop.
while (FA_errno === Constants.FE_Success && loopCounter++ < 1000) {
//set up the text range to change the color
doc.TextSelection = tr;
//clear it - Uncomment this line to test if the search is finding the correct items.
//activeDoc.Clear(0);
// Change the color:
applyTextColor(tr, replaceString, doc);
replacementCounter++;
//increment our return counter
// if (FA_errno === Constants.FE_Success) {
// replacementCounter++;
// }
//...and find the next instance. We'll reset FA_errno again just in case
//something screwy happened while we were replacing text.
// FA_errno = Constants.FE_Success;
tr = doc.Find(tr.beg, findParams);
}
if (CondFmt.ObjectValid) {
CondFmt.CondFmtIsShown = IsSafety;
}
// Restore the document display and refresh the screen.
if (app.Displaying === 0) {
app.Displaying = 1;
doc.Redisplay();
}
doc.TextSelection = restoreTR;
doc.ScrollToText(restoreTR);
return replacementCounter;
} // End FindAndReplaceString
Commented bold lines above were in the original script. I moved the replacement counter outside of the If block so it incremented whenever the applyTextColor function was called, but it didn't help.
When I first run the script on my template, it returns 109, which is probably correct. When I run it again without saving the document, it returns 57 when the document should not have any red text and it should return 0.
In your examples, I'm not seeing why you have to initialize the counter outside of the count function. I don't see that it hurts, but the count function is going to start with a value of zero, and then increment and return that which will be saved as tblpgf's - seems like it would give the correct result whether or not it was initialized.
Copy link to clipboard
Copied
Tried something else and didn't get it to work, but maybe it will give you some insights:
I renamed my Find and ReplaceColor Script to "CountColor" and didn't have it replace anything. It returned 1000 if there was red text and 0 if there was not. (It is just looping through the document, I need to change it to init as false and return true if any instance was found.
I changed my main script to run CountColor and if CountColor returned >0 to run FindandReplaceColor.
It worked, but when I ran the main script again after it changed the colors to black, it still shows 1000 for the Count Color result.
So somehow that doesn't seem to be working in the main function, although it seems to work fine if I run it independently of the main function (???).
Copy link to clipboard
Copied
More testing and odd results. Let's name what I referred to as the main script as "MakeFinalPDF".
It checks for quite a number of things, but toward the end, it replaces red text with black text, displays the print dialog, and then asks if you want to revert to saved.
The first time I run the script, it reports 109 changes, which is probably correct. The next time I run the script and every time after, it reports 57 changes, even though there shouldn't be any red text left in the document.
However, I have another button on the window that the script is run from that only runs "FindandReplaceColor." If I run that and then run the "MakeFinalPDF" script (without saving in between), "MakeFinalPDF" correctly reports "0" instances of red text.
I thought I could maybe do something with running the script twice, so I tried this in "MakeFInalPDF":
...
var FoundRed = -1;
var FoundRed2 = -1;
FoundRed = FindAndReplaceColor(doc, doc.MainFlowInDoc, 'Red', 'Black');
alert(FoundRed);
if (FoundRed>0)
{
FoundRed2 = FindAndReplaceColor(doc, doc.MainFlowInDoc, 'Red', 'Black');
alert(FoundRed2)
}
...
The first time I ran the script, it reported 127 for FoundRed, and 0 for FoundRed2. Any additional time I ran it, it reported 57 for FoundRed and 0 for FoundRed2.
Note the 57 seems to be consistent for the second time I run the script, but I don't know what it might represent ...
Also - I'm not crazy about running find and replace twice on the entire document just to get a correct value of the replacement count ...
Copy link to clipboard
Copied
Hi,
I do not know, how you count your Track Text Edits. However, when I accept my Track Text Edits, there are usually a number of them left. Possibly these are your 57 edits.
I have an old FrameScript script to save as MIF, and this script finds all those remaining edits which had not been accepted. When I select such edits, I can accept them individually.
Sometimes some edits are accepted, when I select all in the main flow and then accept.
Best regards, Winfried
Copy link to clipboard
Copied
I don't think it is related to track edits. If I save the file, it still reports 57 if I run the MakeFinalPDF button. But it reports 0 if I run the ClearRedFont button first.
I was trying to think of a way to have it trigger a flag variable if ApplyTextColor was run, but for all I can tell, it might be running that 57 times, even though there doesn't seem to be a reason for it to do so, so I'm stuck right now.
Copy link to clipboard
Copied
@frameexpert I figured out what it happening, but not really why.
The document has a condiditonal Format - let's call it Format A - which contains red font text.
This format is not hidden when we make a Final PDF, so the red text is NOT removed from it.
However, if I manually hide the conditional format and search for Character Format Red Text manually, it finds each occurrence of the hidden text - although I don't think it should.
I think this is where the 57 instances are coming from. Other possibility is that these are some zero-length non-printing characters that use red font and are not being changed by the initial find command.
Now I need to figure out how to get the script working as I intended for it to work.
Copy link to clipboard
Copied
I can probably change the step order - i.e. get rid of ALL the red text (including the Condition A text) and the hide Condition A and that SHOULD work ...
Update - that seems to have fixed the issue. It's not quite ideal b/c the script is replacing red text even though the author didn't add any red text themself, but it is close to what I intended.
Copy link to clipboard
Copied
@frameexpert Thinking about it overnight, something still is not working correctly, but I'm not sure why.
If I start with a clean template and run MakeFinalPDF button repeatedly, FoundRed consistently reports 100-ish, and then 57, and continues reporting 57 no matter how many times I run it. Now:
I might need to update the way FindandRepaceColor reports the number of changes, but it should work.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now