Copy link to clipboard
Copied
You know, my favorite errors ar typos... but I have not found any in my codet. So I hope You see my error.
// var tr is defined in a subroutine
var replaceString = "";
for (j = 0; j < gasUserVariables.length; j++) {
replaceString = replaceString + "\n" + gasUserVariables; // \n gives new paragraphs
}
alert (replaceString);
targetDoc.TextSelection = tr; // some ¶s excluding last ¶-mark
targetDoc.Clear(0); // delete selected content
targetDoc.AddText(tr.beg, replaceString); // insert the text from the array
Where is my mistake?
BTW: in the function where I set up the selection I need to reduce FV_OBJ_END_OFFSET by 2 to exclude the final ¶ mark from the selection (snippet only):
var tr = new TextRange();
tr.beg.obj = oPara; // text range starts at the first found para
tr.beg.offset = 0;
while (oPara.ObjectValid ()) {
pgfFmt = oPara.Name;
if (pgfFmt == type) { // must not be interspearsed with other pgf formats
tr.end = new TextLoc (oPara, Constants.FV_OBJ_END_OFFSET - 2);
oPara = oPara.NextPgfInFlow;
continue;
}
break;
}
return tr;
I'm working in FM-13.
Dear friends,
I have found the culprit! It is not the problem with the textrange, but what I insert: The empty paragraph at the beginning of the inserted sequece is the result of a wrong preparation of the inserted string. This starts with an \n ...
The relevant portion of the script must read
...replaceString = "";
if (gasUserVariables.length > 0) {
replaceString = gasUserVariables[0];
for (j = 1; j < gasUserVariables.length; j++) {
replaceString = replaceString + "\n" + gasUserVariables; // \
Copy link to clipboard
Copied
Hec, I can not edit my post ...
All said starting with "BTW: in the function ..." should be deleted. In the the screenshot you see wha I need a value of 2: there is an empty paragraph of the relevant type, which must not be there...
Copy link to clipboard
Copied
Hi Klaus,
In line 09 you use a textrange, but to insert text, you don't need a textrange, but a textlocation.
Copy link to clipboard
Copied
OK, Klaus, but why then does this work in the famous script from Russ Ward in https://forums.adobe.com/message/3888653#3888653 which I have used in my last project?
while(FA_errno === Constants.FE_Success && loopCounter++ < 2*loopMax) { //find and replace loop as long as we keep finding
activeDoc.TextSelection = tr; // set up the text range to clear the original text
activeDoc.Clear(0); // clear it
activeDoc.AddText(tr.beg, replaceString); // insert the new text at the original beginning of the text range
tr.beg.offset += replaceString.length; // lets jimmy the text range in memory to place it directly after
There are plenty of mysteries.
Copy link to clipboard
Copied
Sorry.
Of course this is right.
tr.beg is a textloc
shame on me.
EDIT:
EDIT:
But in this case you are deleting the whole pgf and so the tr-object is deleted, too
Copy link to clipboard
Copied
Hi Klaus D.,
Thanks for the fame. I didn't know what a sensation that script really is.
While Klaus G. is normally the resident genius, I think the advice this time is incorrect. The "beg" and "end" members of a textrange are indeed textlocs, so it is proper to use either with AddText(). I don't know exactly what is wrong with your script, but I am sure that the problem is with your definition of "tr". Here are some notes/observations:
1 - Are you absolutely sure that oPara is valid? If it is not, the whole operation will fail from the start.
2 - While it may be OK to use new TextLoc() to define tr.end, it seems possibly risky to me. I don't know that for sure, but what I do know is that the previous methodology you use to define tr.beg works reliably. You already have a TextLoc array in the structure, so you can just do tr.end.obj = oPara, etc.
3 - It seems like the code can enter an endless loop if the paragraph format varies. Your code to step to the next paragraph (line 8) is inside the "if (pgfFmt == type)" conditional. But then looking again, I see the "break" statement, which means that the while loop will never loop? I think this whole area is problematic.
4 - While the following phrase seems logical, it is actually non-functional and may be another source of the problem:
Constants.FV_OBJ_END_OFFSET - 2
This constant is just some huge integer that FM uses as a flag, not as an explicit offset length. It basically tells FM that you want to select to the end of the object for future operations, but it does not dynamically become the actual length of the object. So, when you subtract 2 from it, you are changing the constant and thus eliminating any meaning it might have had. With your code, you are actually setting some huge explicit offset that FM might be choking on.
The only way I know to accomplish your goal is to actually set the text selection, retrieve it again, then adjust the offset. For example:
var tr = new TextRange();
tr.beg.obj = oPara; // text range starts at the first found para
tr.beg.offset = 0;
while (oPara != null && oPara.ObjectValid ()) {
pgfFmt = oPara.Name;
if (pgfFmt == type) { // must not be interspearsed with other pgf formats
tr.end.obj = oPara;
tr.end.offset = Constants.FV_OBJ_END_OFFSET;
oPara = oPara.NextPgfInFlow;
}
else oPara = null;
}
//Select the text in the doc
doc.TextSelection = tr;
//Reset tr
tr = doc.TextSelection;
tr.end.offset -= 2;
//Since you are replacing the text, maybe just delete it now?
//The AddText() method will not replace it!
doc.TextSelection = tr;
doc.Clear(0);
tr = doc.TextSelection;
return tr;
PLEASE NOTE I just scratched this out, I did not test anything. There are likely some typos, errors, etc. I hope it helps.
Russ
Copy link to clipboard
Copied
Hi Russ,
the problem in this case is, that the object of the textrange is deleted.
One way could be to remember the my PrevPgf = pgf.PrevPgfInFlow, then delete the text.
Rebuild it:
pgf = PrevPgf.NextPgfinFlow
and use this pgf for a new textlocation.
The problem in doing this is, if you delete the first PGF in flow. This you have to handle it separately. And take care of the LastPgf
Copy link to clipboard
Copied
Hi Russ, One comment on number 4 above: According to the FDK docs, it is OK to add or subtract numbers from the special Constants.FV_OBJ_END_OFFSET variable. From the "FDK Programmers Guide":
To specify offsets near the end of an object, you can add or subtract integers from FV_OBJ_END_OFFSET.
If have done this successfully in all three environments: the FDK, ExtendScript, and FrameScript. -Rick
Copy link to clipboard
Copied
@Russ: In my original post everything after "BTW: in the function ..." should be ignored. I could not edit my post after discovering that I had an empty ¶ which needed the -2 rather than a -1 to leave out the final ¶-mark from the selection.
@Klaus: no, I'm not deleting the whole selection, because the selection does not include the alst ¶-mark. But nevertheless the tr object may be invalid after the deletion of the selection. I can not use the " PrevPgf = pgf.PrevPgfInFlow, then delete the text." construction, because the ¶s around the selection have other formats. The ¶-format-name is the "selection criterion". The paragraphs within the selection of coarse are
Actually I'm very close to the solution (snippet A):
targetDoc.TextSelection = tr; // set up the text range to clear the original text
targetDoc.Clear(0); // clear it
targetDoc.AddText(tr.end, replaceString);
Using tr.end rather than tr.beg in line 3 of this snippet A results in 'appended' paragraphs:
; ... document, they are also listed here
#cats
#dogs
#HORSE
#DUCKUMENT; comment line
Line 2 is what exists after deleting the selection (line 2 in the snippet). ¶s 1 and 7 have format Ref-Comment, ¶s 2 … 6 have ¶ format Ref-Variables.
But manipulating the offset seems not to be a good idea. With (snippet B):
targetDoc.TextSelection = tr; // set up the text range to clear the original text
targetDoc.Clear(0); // clear it
tr.end.offset = -1;
targetDoc.AddText(tr.end, replaceString);
The inserted ¶s get the format of ¶ 1 (that is format Ref-Comment)
I will try to build a script with just the relevant lines....
Copy link to clipboard
Copied
Friends, I have now cleaned out everything which is not needed to demonstrate...
However, use this test file
// ReplaceParagraphs.jsx
// use test file ReplaceParagraphs.fm
#target framemakervar gasUserVariables = ["#cats", "#dogs", "#HORSE", "#DUCKUMENT"];
var goCurrentDoc = app.ActiveDoc; // the current documentPutRefPageItems ("Ref-Variables", "");
function PutRefPageItems (category, itemName) { // ================================================
var flowName = "FM-calc";
var oFlow, oPara, tr, targetDoc = goCurrentDoc;
var j, replaceString;oFlow = targetDoc.FirstFlowInDoc; // go to the relevant flow in (ref) page
var notFound = true;
while (oFlow.ObjectValid()) {
if (oFlow.Name == flowName) {
notFound = false;
break; }
oFlow = oFlow.NextFlowInDoc;
}
if (notFound) {
alert ("PutRefPageItems:\nFlow «" + flowName + "» does not exist in document\n"+ targetDoc);
return false;
}
oPara = oFlow.FirstTextFrameInFlow.FirstPgf;tr = GetParagraphs (oPara, "Ref-Variables"); // paragraphs to be replaced
//? $.bp(true);
replaceString = "";
for (j = 0; j < gasUserVariables.length; j++) {
replaceString = replaceString + "\n" + gasUserVariables; // \n gives new paragraphs
}
targetDoc.TextSelection = tr; // set up the text range to clear the original text
targetDoc.Clear(0); // clear it
tr.end.offset = 0; // 0, 1 create 'appended' paragraphs;
// -1 inserts in previous ¶ with wrong format
targetDoc.AddText(tr.end, replaceString); // insert the new text
} // --- end PutRefPageItemsfunction GetParagraphs (oPara, type) { // =========================================================
var pgfFmt;
while (oPara.ObjectValid ()) {
pgfFmt = oPara.Name;
if (pgfFmt == type) { // skip this
break;
}
oPara = oPara.NextPgfInFlow;
continue;
} // we are now on the first of the relevant ¶
//? $.bp(true);
var tr = new TextRange();
tr.beg.obj = oPara; // set up the starting text range as the very beginning
tr.beg.offset = 0;
while (oPara.ObjectValid ()) {
pgfFmt = oPara.Name;
if (pgfFmt == type) { // must not be interspearsed with other
tr.end = new TextLoc (oPara, Constants.FV_OBJ_END_OFFSET - 1);
oPara = oPara.NextPgfInFlow;
continue;
}
break;
}
return tr;
}
Lines 37 ... 39 are the 'crucial' ones.
Copy link to clipboard
Copied
Dear friends,
I have found the culprit! It is not the problem with the textrange, but what I insert: The empty paragraph at the beginning of the inserted sequece is the result of a wrong preparation of the inserted string. This starts with an \n ...
The relevant portion of the script must read
replaceString = "";
if (gasUserVariables.length > 0) {
replaceString = gasUserVariables[0];
for (j = 1; j < gasUserVariables.length; j++) {
replaceString = replaceString + "\n" + gasUserVariables; // \n gives new paragraphs
}
}
targetDoc.TextSelection = tr; // set up the text range to clear the original text
targetDoc.Clear(0); // clear it
targetDoc.AddText(tr.end, replaceString); // insert the new text
Thank You all very much for Your assistance!
... and lines 1 to 7 can be replaced by
replaceString = gasUserVariables.join("\n");
Copy link to clipboard
Copied
I guess I stand corrected about FF_OBJ_END_OFFSET. Somehow I was sure that this did not work. My apologies for the misinformation. It is good to be educated, because I always did believe that this would be very useful.
Russ