Deal with InDesign® books
Here you will find examples to use book.
Deal with InDesign® books
static int create(char* fullpath)
Create a new empty book. The book is NOT opened automatically.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
fullpath | String or char* | - | Complete path to the resulting book. The file name must should end with an extender (.indb). The path will be created if nesseccary. |
static int open(char* fullpath, ItemRef bookRef = 0)
Open a book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
fullpath | String or char* | - | Complete path to the book. |
bookRef | ItemRef | 0 | On success a valid reference to the opened booked. You should create this ref before the call using item::alloc. |
static int count()
Determine the number of currently open books.
Name | Type | Default | Description |
Return | int | Number of currently open books 0 : no books open or errors |
int main () { int B = book::count (); int b; ItemRef bref= item::alloc (); for (b = 0; b < B; b++) { book::get_nth (b, bref); wlog ("", "# %d. book : '%s'\n", b, book::get_path (bref)); } book::get_current (bref); wlog ("", "Current book : '%s'\n", book::get_path (bref)); book::get_by_path ("$DESKTOP/Buch 3.indb", bref); wlog ("", "Thrd book : '%s'\n", book::get_path (bref)); book::set_current (bref); book::get_current (bref); wlog ("", "Current book (2): '%s'\n", book::get_path (bref)); return 0; }
static int get_nth(int nth, ItemRef out_bookRef)
Get the nth open book. The result is a reference to an open book. The path of the book can be determined with get_path.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
nth | int | - | 0-based index of book |
out_bookRef | ItemRef | 0 | After successful execution, the variable contains a reference to the nth book. The path of the book can be determined with get_path. |
You can find an example under count.
see count
static char* get_path(ItemRef bookRef)
Determine the complete path of a book.
Name | Type | Default | Description |
Return | char* | Complete path of the book incl. its name or "" in case of some errors. The return value is read only, do NOT CHANGE. The result will be overridden on following calls to the function. See here to learn more about functions returning r/o char* values. |
|
bookRef | ItemRef | - | Valid reference to an open book. |
You can find an example under count.
siehe count
static int get_by_path(char* path, ItemRef out_bookRef)
Determine from the file path of an InDesign® book the current reference in the program. To obtain a valid reference, the book file exist and the book must be opened in InDesign®!
Name | Type | Default | Description |
Return | int | 0 or ErrorCode To obtain a valid reference, the book file exist and the book must be opened in InDesign®! |
|
path | String oder char* | - | Full path of an InDesign® book file |
bookRef | ItemRef | - | After successful execution, the variable contains a reference to given book. |
Ein Beispiel finden Sie unter count.
siehe count
static int get_current(ItemRef out_bookRef)
Get the currently 'active' book.
Please note: The active book is the book you last worked on. The active book may change by script calls for other books!
Here is an article from InDesign Secrets:
A note on "activeBook"
One more note, in case you’re going to be scripting book panels: Before you add your own custom options to the Book panel,
you have to make sure it works as intended in a standalone script. Now there is something weird going on when using 'activeBook'.
Other than, say, 'activeDocument', 'activeBook' does not always get right what book document is the active one!
The reason for this is that you can have several book panels open at a time, scattered about your workspace.
Which one is then "active"? So when experimenting with this, you’d better make sure you only have one single book open.
I was kind of weary of this issue when testing my open/close script, but it seems that if you call a script from within the book panel
itself, 'the' active book is indeed the one you called the menu from, so the problem resolved itself.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
out_bookRef | ItemRef | 0 | After successful execution, the variable contains a reference to 'acive' book. The path of the book can be determined with get_path. |
You can find an example under count.
see count
static int set_current(ItemRef bookRef)
Set the currently 'active' book.
Please note: The active book is the book you last worked on. The active book may change by script calls for other books!
Here is an article from InDesign Secrets:
A note on "activeBook"
One more note, in case you’re going to be scripting book panels: Before you add your own custom options to the Book panel,
you have to make sure it works as intended in a standalone script. Now there is something weird going on when using 'activeBook'.
Other than, say, 'activeDocument', 'activeBook' does not always get right what book document is the active one!
The reason for this is that you can have several book panels open at a time, scattered about your workspace.
Which one is then "active"? So when experimenting with this, you’d better make sure you only have one single book open.
I was kind of weary of this issue when testing my open/close script, but it seems that if you call a script from within the book panel
itself, 'the' active book is indeed the one you called the menu from, so the problem resolved itself.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | 0 | New 'active' book |
You can find an example under count.
see count
static int is_valid(ItemRef bookRef)
Does a given reference point to an open book?
Name | Type | Default | Description |
Return | int | 1 : Yes 0 : Empty reference or reference does not point to an opened book |
|
bookRef | ItemRef | - | Any reference |
static int save(ItemRef bookRef)
Save a book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Valid reference to a book opened before |
static int close(ItemRef bookRef, int doSave = 1)
Close a book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Valid reference to a book opened before |
doSave | int | 1 | Save book before closing 0 : Do not save changes otherwise : save changes |
static int insert(
ItemRef bookRef,
char* docPath,
int location = -1,
int updateCrossrefs = 0,
int showProgress = 0,
int repaginate = 1)
Insert a document to a opened book. If the document is already part of the book, the call does nothing. Optionally you can update all Cross Reference Placeholders of the given book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Valid reference to a book opened before |
docPath | String or char* | - | Complete path to an existing InDesign® document |
location | int | -1 | 0-based insertion point -1 : append |
updateCrossrefs | int | 0 | Update Cross Reference Placeholders?
The parameter is only evaluated if repaginate is 1. 0 : No 1 : Yes. Updating cross-references can change the length of the document and cross-references that have just been updated become incorrect. In the hope that a directly repeated update of the cross-references will not change their length again, we always make two passes of the updates. 2 : Lazy. If the total number of pages in the book remains unchanged after the first run, no second run is made (since v4.3 R35900). |
updateCrossrefs | int | 0 | Update Cross Reference Placeholders? 0 : No 1 : Yes |
showProgress | int | 0 | Show progress while updating Cross Reference Placeholders? 0 : No 1 : Yes |
repaginate | int | 1 | Repaginate pages (since 4.1 R22155) 0 : No 1 : Yes |
static int moveto(
ItemRef bookRef,
char* docPath,
int pos,
int updateCrossrefs = 0,
int showProgress = 0)
Move a document to an new position inside the book. Optionally you can update all Cross Reference Placeholders of the given book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Valid reference to a book opened before |
docPath | String or char* | - | Complete path to an InDesign® document |
pos | int | - | New position inside the book (0-based) -1 : to the end of the book |
updateCrossrefs | int | 0 | Update Cross Reference Placeholders?
The parameter is only evaluated if repaginate is 1. 0 : No 1 : Yes. Updating cross-references can change the length of the document and cross-references that have just been updated become incorrect. In the hope that a directly repeated update of the cross-references will not change their length again, we always make two passes of the updates. 2 : Lazy. If the total number of pages in the book remains unchanged after the first run, no second run is made (since v4.3 R35900). |
showProgress | int | 0 | Show progress while updating Cross Reference Placeholders? 0 : No 1 : Yes |
static int remove(
ItemRef bookRef,
char* docPath,
int updateCrossrefs = 0,
int showProgress = 0)
Removes a document from an opened book. if the document isn't a part of the book, the call does nothing. Optionally you can update all Cross Reference Placeholders of the given book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Valid reference to a book opened before |
docPath | String or char* | - | Complete path to an InDesign® document |
updateCrossrefs | int | 0 | Update Cross Reference Placeholders?
The parameter is only evaluated if repaginate is 1. 0 : No 1 : Yes. Updating cross-references can change the length of the document and cross-references that have just been updated become incorrect. In the hope that a directly repeated update of the cross-references will not change their length again, we always make two passes of the updates. 2 : Lazy. If the total number of pages in the book remains unchanged after the first run, no second run is made (since v4.3 R35900). |
showProgress | int | 0 | Show progress while updating Cross Reference Placeholders? 0 : No 1 : Yes |
static int repaginate(
ItemRef bookRef,
int updateCrossrefs = 0,
int showProgress = 0)
Repaginate an open book. Optionally you can update all Cross Reference Placeholders of the given book.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Reference to an opened book |
updateCrossrefs | int | 0 | Update Cross Reference Placeholders?
The parameter is only evaluated if repaginate is 1. 0 : No 1 : Yes. Updating cross-references can change the length of the document and cross-references that have just been updated become incorrect. In the hope that a directly repeated update of the cross-references will not change their length again, we always make two passes of the updates. 2 : Lazy. If the total number of pages in the book remains unchanged after the first run, no second run is made (since v4.3 R35900). |
showProgress | int | 0 | Show progress while updating Cross Reference Placeholders? 0 : No 1 : Yes |
static int position(ItemRef bookRef, char* docPath)
Find the location of a document inside a book.
Name | Type | Default | Description |
Return | int | -1 : Document not found inside the book otherwise : 0-based doc position |
|
bookRef | ItemRef | - | Valid reference to a book opened before |
docPath | String or char* | - | Complete path to an InDesign® document |
static int set_master(ItemRef bookRef, char* docPath)
Set the Style Source of the book.
Name | Type | Default | Description |
Return | int | -1 : Document not found inside the book otherwise : 0-based doc position |
|
bookRef | ItemRef | - | Valid reference to a book opened before |
docPath | String or char* | - | Complete path to an InDesign® document inside the book |
static char* get_master(ItemRef bookRef)
Get the Style Source of the book.
Name | Type | Default | Description |
Return | char* | Complete path to the document use to be the books style source document. "" : In case of an error The return value is read only, do NOT CHANGE. The result will be overridden on following calls to the function. See here to learn more about functions returning r/o char* values. |
|
bookRef | ItemRef | - | Valid reference to a book opened before |
static int count_docs(ItemRef bookRef)
Count the documents of an opened book.
Name | Type | Default | Description |
Return | int | Number of documents inside the book. | |
bookRef | ItemRef | - | Valid reference to a book opened before |
static char* nth_doc(ItemRef bookRef, int n)
Name | Type | Default | Description |
Return | char* | Complete path to the n-th document in the book. The result will be overridden
on following calls to the function. "" : In case of an error |
|
bookRef | ItemRef | - | Valid reference to a book opened before |
n | i | - | 0-based index in the book |
static int create_toc(
ItemRef frameRef,
char* selector,
int sortType,
int functionPtr,
...)
Create a table of contents of all text anchors of all documents of a book. The call collects all desired text anchors that are found in the documents of the book that also contains the document with the table of contents. The book must be open for this and InDesign® must be able to open all documents in the book at the same time. A function defined in the calling script is then executed for each text anchor found. In this function you calculate the text content of the respective entry for the table of contents then. In addition you determine whether the new content entry should have an active link to the text anchor. For active links, the complete book must be exported as an interactive PDF.
The function for evaluating the text anchors has strictly defined data types for the parameter and Errors in the data types of the parameters will cause InDesign® to crash. The names of the parameters are of course freely selectable. The names given in the following list are therefore only suggestions:
Type | Name | Description | |||||||||||||||||||||||||||
ItemRef | fr | Target framework for the table of contents. The varibale contains the value gFrame of the containing script. | |||||||||||||||||||||||||||
Link | lk | Current text anchor. The properties of the anchor (position, length, name, ...) can be queried using the functions link::crossref::. | |||||||||||||||||||||||||||
int | situation | Call situation, reserved for later extensions and currently always 0 | |||||||||||||||||||||||||||
String | txt |
Return variable : Text for the table of contents.
The content of this variable is inserted at the current text position in the target frame
(first parameter of the function) at the current text position. The current text position is calculated by book::create_toc.
The text may be TaggedText-formatted.
This call determines the document text of a named text anchor. frame::gettext ( link::crossref::frame (lk), str, link::crossref::src_textpos (lk)+1, link::crossref::src_textlen (lk)-1); |
|||||||||||||||||||||||||||
int* | entryType | Return variable : Type of target. In the variable you specify whether the text in the table of contents
should be a clickable link and where this link points to.
Links are always placed over the entire inserted text of the entry.
To activate links, the book must be exported to an interactive PDF. -1 : [Default] Do not create a link (only insert the text) 0 : Use the text anchor of the transferred link as target 1 : Use the page of the transferred link as target Please note that the variable is a pointer to an int. With this specification, book::create_toc produces a link to the page of the text anchor: *entryType = 1 |
|||||||||||||||||||||||||||
... | ... |
Although the handling function is defined in the same script, it is executed independently of this script and does not have access to the global variables of the surrounding script. To have access to global variables and other values that may be required, the call to book::create_toc may have up to a maximum of 20 additional parameters after its functionPtr parameter. The variables of these additional parameters must also be defined with its correct datat types 1:1 in the editing function.
|
You can create target text anchors for the table of contents using the textmodel::insert_crossref function, for example.
The example requires InDesign® 2025!
To create a clickable PDF from the book, select the fly-out Export Book to PDF... of the open book. Please pay attention to the following two things:
The script for creating the table of contents can be found in the load action 40 of the placeholder List of Contents.
To see this script, open the panel Placeholder Options. Then place the text cursor in the placeholder.
By clicking the edit button of the Load action you can open the script.
A developer licence for the priint:comet plug-ins is required to open the script from InDesign®.
Alternatively, you can also directly open the script file in any plain text editor.
You can find the script in the file CreateTOC/xmldata-flowers/actions/40.crpt
Similarly, you will find the placeholders for creating the text anchors in actions 20 and 21. These placeholders are contained in documents 100-400 of the book.
Name | Type | Default | Description |
Return | int | 0 or Error Code | |
frameRef | ItemRef | - | Target frame for the table of contents. The document of the target frame must be in a currently open book! |
selector | String oder char* | - | Specification for collecting the text anchors, see crossRefName of the hyperlink::find function 0 or "" : No restrictions |
sortType | int | - | Sort order of the text anchors found -1 : Page by page 0 : By page and column (x-coordinate) per page 1 : By page and row (y-coordinate) per page |
functionPtr | int | - | Function for calculating the texts of the individual entries in the table of contents. The function is called for each text anchor found and must have the parameters described here. |
... | Additional parameters | Empty | Additional parameters, \URL [see here]{#toc_adds} |
To create an invisible text anchor for a text placeholder that contains the entire text placeholder:
textmodel::insert_crossref (
0, textmodel::length(),
txt,
3, gRecordID, gRecordID2, gRecordID3, gRecordStringID,
0); // Invisible anchor
Here is a complete example of how to create a table of contents. The source code and instructions for use can be found here. The example uses the additional parameter lastDocument for the content function functionPtr. This variable contains the name of the document of the last text anchor handled. If the document changes, an additional reference to the first page of the new document is inserted by the function.
#pragma plain
int create_entry (ItemRef fr, Link lk, int situation, String txt, int * entryType, String lastDocument) { String str = string::alloc (); int isHead = 0;
// The new entry should of course be on a new line. // But the new line should not become part of the link. // if (textmodel::length () > 1) textmodel::append ("%!TT<ParaStyle:TOC-Entry><ParaStyle:TOC-Entry>", 0);
// If the document changes, an additional blank line is inserted // if (string::compare (lastDocument, link::crossref::document (lk))) { if (textmodel::length () > 1) textmodel::append ("%!TT<ParaStyle:TOC-Entry><ParaStyle:TOC-Entry>", 0); string::set (lastDocument, link::crossref::document (lk)); isHead = 1; }
// Get the placeholders text content // frame::gettext ( link::crossref::frame (lk), str, link::crossref::pos (lk)+1, link::crossref::src_textlen (lk)-1);
// Build the TOC entry text // if (isHead) { entryType = 1; // Make it a page-link string::set (txt, "%%!TT<ParaStyle:TOC-Entry><CharStyle:Bold>%s\t%d<CharStyle:>", str, link::crossref::page (lk, 0)); } else { entryType = 0; // Make it a text-link string::set (txt, "%%!TT<ParaStyle:TOC-Entry>%s\t%d", str, link::crossref::page (lk, 0)); }
string::release (str); return 0; }
int main() { String lastDocument = string::alloc ();
// Ignore normal LOAD calls // if (!gRepagination) { placeholder::set_sync (-1); gSyncChanged = 1; return 0; }
string::set (lastDocument, ""); textmodel::replace ("");
book::create_toc (gFrame, "", 0, create_entry, lastDocument);
string::release (lastDocument); return 0; }
static int all_documents_do(
char* bookPath,
int actionID,
int saveOnClose = 0)
Editing of all documents in a book. The documents are opened, edited and closed again in the order specified in the book. Previously opened documents remain open.
The function solves the problem that InDesign® does not really close documents until the next idle time. This behaviour means that books with many documents can quickly lead to memory overflow and InDesign® crashing when they are processed in a single script. all_documents_do solves the problem by processing the individual documents in separate idle time sequences. Between these steps, InDesign® is given enough time to 'really' close closed documents.
Name | Type | Default | Description |
Return | int | 0 or Error Code | |
bookPath | String oder char* | - | Complete path of the book to be edited |
actionID | int | - | ID from actions of the script for editing the individual documents.
The documents are open at execution time and are always in the foreground. Global variables (read only!) char* gMyBook : Path (parameter bookPath) of book int gMyChapter : 0-based index of the document in the book Return values 0 : Okay Otherwise : Error and cancellation of the processing of further documents |
saveOnClose | int | 0 | Should the individual documents be saved after processing? 0 : No, close documents without saving 1 : Yes, save changes to the documents |
Use the following line to edit all documents of a book. The documents themselves are edited by action 170.
book::all_documents_do ("/Users/paul/Desktop/ID_19.0/Book 1.indb", 170, 1);
Action 170 creates an orange frame in the first document. For demo purposes, after the third document you are asked whether editing should be continued.
#include "internal/types.h"
int main () { ItemList frames; ItemRef fr = item::alloc (); char pp [5000]; int res = 0;
wlog ("", "BOOK %s, CHAPTER %d\n", gMyBook, gMyChapter);
if (gMyChapter == 0) { frame::create (fr, kRectangle, 0.0, 0.0, 300.0, 50.0, 1); frame::color_rgb (fr, 255, 128, 0); }
frames = itemlist::allframes (); wlog("", "### %d frame(s) found in doc '%s'\n", itemlist::length (frames), document::path (pp));
itemlist::release (frames); item::release (fr);
// For demonstration purposes only // if (gMyChapter == 2) { res = alert ("Proceed", "Cancel", 0, 1, 2, "%d documents proceeded. Should I proceed with the next documents?", gMyChapter+1); if (res == 1) res = 0; // Proceed }
return res; }
static int export_(
ItemRef bookRef,
char* pdfPath = 0,
char* styleName = 0)
Export a book as a PDF document.
Name | Type | Default | Description |
Return | int | 0 or ErrorCode | |
bookRef | ItemRef | - | Valid reference to an open book |
pdfPath | String or char* | 0 | Path for the export file 0 : Use path and name of book file with the extension pdf. otherwise : Complete path and file name. The path is created automatically. |
styleName | String or char* | 0 | Export style name : 0 : Current default style otherwise : Name of an existing PDF export style Style names must be case seinsitive. |
Demostrating some book function calls and logs the result to the global logfile. You must have the three documents book.indd, book2.indd and book3.indd on your desktop.
int main () { ItemRef bookRef = item::alloc (); int rt; char bookPath[256]; char doc1[256]; char doc2[256]; char doc3[256]; char* masterDoc;
strcpy (bookPath, "$DESKTOP/book.indb"); strcpy (doc1, "$DESKTOP/book.indd"); strcpy (doc2, "$DESKTOP/book2.indd"); strcpy (doc3, "$DESKTOP/book3.indd");
rt = book::create (bookPath); wlog ("", "Create book returned %d.\n", rt);
rt = book::open (bookPath, bookRef); wlog ("", "Open book returned %d.\n", rt);
rt = book::is_valid (bookRef); wlog ("", "bookRef valid? %d\n", rt); if (!rt) return 0;
rt = book::insert (bookRef, doc1, 0); wlog ("", "Insert doc1 in book returned %d.\n", rt);
rt = book::insert (bookRef, doc2, 1); wlog ("", "Insert doc2 in book returned %d.\n", rt);
rt = book::insert (bookRef, doc3, 1); wlog ("", "Insert doc3 in book returned %d.\n", rt);
rt = book::position (bookRef, doc1); wlog ("", "Position of '%s' in book : %d\n", doc1, rt);
rt = book::position (bookRef, doc3); wlog ("", "Position of '%s' in book : %d\n", doc3, rt);
wlog ("", "Style source is '%s'\n", book::get_master (bookRef)); rt = book::set_master (bookRef, doc2); wlog ("", "Set style source returned : %d\n", rt); wlog ("", "Style source is now '%s'\n", book::get_master (bookRef));
rt = book::save (bookRef); wlog ("", "Saving book returned : %d\n", rt); return 0; }
Open an existing book and write all documents of the book to the global logfile.
int main () { ItemRef bookRef = item::alloc (); int rt, i; char doc1[256]; char bookPath[256];
strcpy (bookPath, "$DESKTOP/book.indb"); rt = book::open (bookPath, bookRef); wlog ("", "Open book returned %d.\n", rt); if (rt) return 0;
wlog ("", "Book contains %d doc(s)\n", book::count_docs (bookRef)); for (i = 0; i < book::count_docs (bookRef); i++) { wlog ("", "Doc %d : '%s'\n", i+1, book::nth_doc (bookRef, i)); }
return 0; }
Remove a document from an existing book.
int main () { ItemRef bookRef = item::alloc (); int rt; char bookPath[256]; char doc3[256]; char* masterDoc;
strcpy (bookPath, "$DESKTOP/book.indb"); strcpy (doc3, "$DESKTOP/book3.indd"); rt = book::open (bookPath, bookRef); wlog ("", "Open book returned %d.\n", rt); if (rt) return 0;
rt = book::remove (bookRef, doc3); wlog ("", "Removing doc3 in book returned %d.\n", rt);
rt = book::save (bookRef);
return 0; }
Export a book to a PDF file using the defined export style 'Vorschau'.
int main () { ItemRef bookRef = item::alloc (); int rt; char bookPath[256];
strcpy (bookPath, "$DESKTOP/book.indb"); rt = book::open (bookPath, bookRef); if (rt) return 0; rt = book::export_ (bookRef, "", "Vorschau"); wlog ("", "Export book returned %d.\n", rt);
book::save (bookRef); return 0; }
Alphabetic index HTML hierarchy of classes or Java