Copy link to clipboard
Copied
Hello fellows,
I wonder what is the best way to find the 5th book component from the end of the book (so the 1st book component to count is basically the last one).
I can loop through all components and get a list of all of them. Then, I guess, I need to somehow put them into an array and find the 5th one from the bottom?
Any ideas will be appreciated!
Copy link to clipboard
Copied
I cannot see any alternative to iterating through all the book components, storing the component ids as you go..
I'd use a buffer big enough to hold only 5 component ids. Store each successive component id you find in location (counter modulo 5) - so it's effectively a circular buffer. When you reach the last component in the book, the component you want will be the next entry in the circular buffer. This method saves memory, and handles a book of any size.
Whether or not you use the above method, ensure you gracefully handle a book with fewer than 5 components. In the above case, I'd intiialize the buffer to nulls, and check for a non-null value at the end.
Copy link to clipboard
Copied
Mike, Rom, all this sounds good so far, but why bother with buffers at all? I would just go to the end with FP_NextComponentInBook, then step backwards 5 times with FP_PrevComponentInBook. Given the speed of this type of operation, I don't think that you would see any performance issues even with a very large book.
Russ
Copy link to clipboard
Copied
Hi Russ,
I wonder why there is no LastComponentInBook. It would be easier to start counting from it.
Copy link to clipboard
Copied
Hi Mike,
Thank you for your response!
How would you create and manage this buffer?
Copy link to clipboard
Copied
This is how I would do it:
#target framemaker
var comps = [];
var book = app.ActiveBook;
var bookComp = book.FirstComponentInBook;
while (bookComp.ObjectValid ()) {
// put the components into the array in reverse order.
comps.unshift (bookComp);
bookComp = bookComp.NextBookComponentInDFSOrder;
}
alert (comps[4].Name);
Copy link to clipboard
Copied
Hi Rick,
Thank you for your response and for the suggested code! What does the unshift method do? I couldn't find it in the scripting guide.
Thank you!
Copy link to clipboard
Copied
unshift is an array method that puts an item into the front of the array instead of the back. So if you had an array of numbers:
var array = [1, 2, 3, 4, 5];
and did this:
array.unshift (6);
you would have this:
[6, 1, 2, 3, 4, 5]
Normally, you use push to put items on an array:
array.push (6);
would give you:
[1, 2, 3, 4, 5, 6]
Copy link to clipboard
Copied
Hi Rick,
Thank you for the explanations!
Now I see that unshift is a standard JS method. I need to learn more about arrays.
Thank you for your help!
Copy link to clipboard
Copied
Hello fellows,
Let's say I have a book open and also a standalone FM file that is not part of that book.
I previously opened this standalone FM file as follows:
var openFM = Open(dname, openParams, openReturnParams), where dname is the full name of that FM file, openFileParams and openFileReturnParams are defined in a function that lists all relevant open params.
var openParams = getOpenPrefs();
var openReturnParams = new PropVals();
function getOpenPrefs() {
var params, i;
params = GetOpenDefaultParams();
i = GetPropIndex(params, Constants.FS_RefFileNotFound);
params.propVal.ival = Constants.FV_AllowAllRefFilesUnFindable;
i = GetPropIndex(params, Constants.FS_FileIsOldVersion);
params.propVal.ival = Constants.FV_DoOK;
i = GetPropIndex(params, Constants.FS_FontChangedMetric);
params.propVal.ival = Constants.FV_DoOK;
i = GetPropIndex(params, Constants.FS_FontNotFoundInCatalog);
params.propVal.ival = Constants.FV_DoOK;
i = GetPropIndex(params, Constants.FS_FontNotFoundInDoc);
params.propVal.ival = Constants.FV_DoOK;
i = GetPropIndex(params, Constants.FS_LockCantBeReset);
params.propVal.ival = Constants.FV_DoOK;
i = GetPropIndex(params, Constants.FS_FileIsInUse);
params.propVal.ival = Constants.FV_OpenViewOnly;
return (params);
}
After getting the 5th book component, I open it as follows:
var T_FM = comps[4].Name;
var openT_FMParams = getOpenPrefs();
var openT_FMReturnParams = new PropVals();
var openT_FM = Open(T_FM, openT_FMParams , openT_FMReturnParams ).
So now, I have 2 FM files open in addition to the book. The active FM file is the 5th book component that I just opened.
Now, I'd like to import formats from the 5th book component to the standalone FM file (dname) and then close the 5th book component.
I tried doing that as follows:
openFM.SimpleImportFormats(openT_FM, Constants.FF_UFF_COND|Constants.FF_UFF_FONT|Constants.FF_UFF_PAGE |Constants.FF_UFF_PGF|Constants.FF_UFF_REFPAGE|Constants.FF_UFF_TABLE|Constants.FF_UFF_VAR|Constants.FF_UFF_XREF);
openT_FM.Close(Constants.FF_CLOSE_MODIFIED, true);
This part does not work for a reason that is unclear to me. What could be the cause of this problem?
Thank you for your input in advance!
Copy link to clipboard
Copied
After the Open method, you should confirm that the template did open correctly.
if (openT_FM.ObjectValid () === 1) {
// opened correctly.
}
Also, there is a special constant for importing all formats:
openFM.SimpleImportFormats(openT_FM, Constants.FF_ALL);
As far as closing the template without saving changes, all you need is this:
openT_FM.Close(true);
Copy link to clipboard
Copied
Hi Rick,
Thank you for your response. It works only if all the operations described above are defined within the same function. But what if I'd like to split that into 2 functions?
How, for example, do I pass the openFM variable defined and opened in Function A to Function B that will open openT_FM and import the formats to openFM? How do I make local function var's visible to other functions?
Thank you for your explanations in advance!
Copy link to clipboard
Copied
Hi Rick,
Let's say I would like not to count excluded book components that appear at the end of the book. So I tried changing the while statement as follows:
However, in this case, the comps[4] element is one of the first components of the book. Any idea why comps[4] is now counted from the top?
Thank you!
Copy link to clipboard
Copied
Try using && on line 2.
Copy link to clipboard
Copied
Hi Rick,
I appreciate your response.
I tried that previously. As a result, comps[4] is an LOT file (which is the fourth component from the top of the book ).