Copy link to clipboard
Copied
Hi All,
I am working on creating a planner on indesign. I have a page with has a calendar of February 2023 like below, I would like to hyperlink the numbers in the corner to all the daily pages I have created for February, is there an easy way to do this please using a script? I have 12 months I would need to do this for.
1 Correct answer
Hi @wahid28246070iu4o, here's a quick script that does what you want, I think. It works on your sample file. To use it, select one or more table cells and run script. You don't need to tell it what month, because I noticed you have set the script labels for the text frames on first page to "calendarDatesN" so the script gets the month from that. Now you just need to set up the pages so that the 1st of each month is a section start with the section prefix "FEB-" and "MAR-" etc. See attached sampl
...Copy link to clipboard
Copied
Hi @wahid28246070iu4o, do you have any scripting experience? It is possible, but we'd need much more specific information about your document. Here's a workflow: you could select cells of a table and run a script. The script could ask you for the month prefix and you enter, for example, "FEB". Then the script makes new hyperlinks and destinations that go to Page named [month prefix]-[content of cell], so for the cell on day 1, the contents is "1" and it links to the page FEB-1.
Just an idea.
- Mark
Copy link to clipboard
Copied
I was thinking something along this line, I can code in Java but haven't done it in a while unfortunately
Copy link to clipboard
Copied
Can I send an example of the document for you to have a look please by any chance?
Copy link to clipboard
Copied
Java and JavaScript are two different things. Unless you meant JavaScript 😉
If you have a basic knowledge of the JavaScript - you just need to learn / explore DOM structure of the InDesign and you should be good to go - I'm not JS guy so can't help you.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hi @wahid28246070iu4o, here's a quick script that does what you want, I think. It works on your sample file. To use it, select one or more table cells and run script. You don't need to tell it what month, because I noticed you have set the script labels for the text frames on first page to "calendarDatesN" so the script gets the month from that. Now you just need to set up the pages so that the 1st of each month is a section start with the section prefix "FEB-" and "MAR-" etc. See attached sample doc. If you want to use a different scheme, just alter the script to match. I've put all the relevent settings in a "settings" object at the start. Let me know how it goes.
- Mark
/**
* Create hyperlinks to document pages, based on selected table cell contents.
* @author m1b
* @version 2023-02-04
* @discussion https://community.adobe.com/t5/indesign-discussions/hyperlinking-script/m-p/13552525
*/
var settings = {
pageNameTemplate: '#MONTHCODE#-#DAYNUMBER#',
hyperlinkNameTemplate: 'Goto-#MONTHCODE#-#DAYNUMBER#',
textFrameLabelMatcher: /calendarDates(\d+)/,
monthCodes: ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
};
function main() {
var doc = app.activeDocument,
counter = 0
if (
doc.selection.length == 0
|| !doc.selection[0].hasOwnProperty('cells')
|| doc.selection[0].cells == undefined
|| doc.selection[0].cells.length == 0
) {
alert('Please select one or more table cells and try again.');
return;
}
var cells = doc.selection[0].cells,
table = cells[0].parent;
// make sure we have a table object
while (
table.constructor.name != 'Table'
&& table.constructor.name != 'Document'
)
table = table.parent;
if (
table.constructor.name != 'Table'
|| !table.isValid
)
throw Error('Could not get valid table.');
cellsLoop:
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
if (!cell.isValid)
continue;
// get the day number
var dayNumber = Number(cell.contents);
if (
isNaN(dayNumber)
|| dayNumber == 0
)
continue;
// get the month code from the text frame label
var labelParts = table.parent.label.match(settings.textFrameLabelMatcher);
if (labelParts.length < 2)
// no match
continue;
var monthNumber = Number(labelParts[1]);
if (
monthNumber < 1
&& monthNumber > 12
)
// not a month number
continue;
var monthCode = settings.monthCodes[monthNumber - 1];
var destinationPageName = settings.pageNameTemplate
.replace('#MONTHCODE#', monthCode)
.replace('#DAYNUMBER#', dayNumber);
var hyperlinkName = settings.hyperlinkNameTemplate
.replace('#MONTHCODE#', monthCode)
.replace('#DAYNUMBER#', dayNumber);
// get the page
var destinationPage = doc.pages.itemByName(destinationPageName);
if (!destinationPage.isValid) {
alert('There is no page named "' + destinationPageName + '". Script will abort.');
return;
}
// remove hyperlink if already exists
if (doc.hyperlinks.itemByName(hyperlinkName).isValid)
doc.hyperlinks.itemByName(hyperlinkName).remove();
// remove hyperlinkSources from cell
var existingHyperlinkSources = cell.texts[0].findHyperlinks();
for (var j = existingHyperlinkSources.length - 1; j >= 0; j--)
existingHyperlinkSources[j].remove();
// set up new hyperlink
var hyperlinkSource = doc.hyperlinkTextSources.add(cell.texts[0]),
hyperlinkDestination = doc.hyperlinkPageDestinations.add(destinationPage, { hidden: false }),
hyperlink = doc.hyperlinks.add(hyperlinkSource, hyperlinkDestination);
hyperlink.name = hyperlinkName;
counter++;
}
alert('Added ' + counter + ' hyperlinks.');
}; // end main
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Add Calendar Hyperlinks');
Copy link to clipboard
Copied
Hello, thank you for writing a script! I saved the script as a .js file and tried to run it in InDesign, however i get this error?
Copy link to clipboard
Copied
The error was because you saved the text as "rich text". I needs to be "plain text". - Mark
Copy link to clipboard
Copied
Edited as was using a Mac, works now!! Thank you soo much!!!
Copy link to clipboard
Copied
👍
Copy link to clipboard
Copied
run .js file in InDesign, however i get this error? Pls help sir
Copy link to clipboard
Copied
Hi @Mac29594311qpi5, that error occurs when the script is causing the creation of a hyperlink in a document that already has a hyperlink with the same name property. You will either need to put a check in to make sure there is no hyperlink with that name before trying it, or you must remove() the hyperlink before creating a new one with that name.
- Mark
Copy link to clipboard
Copied
Thank you for replying, the script works very well as you said, thanks sir
Copy link to clipboard
Copied
Daily pages script works very well. So I thank you very much.
Now my new planner has more than one page. It did not work well. In it the first page takes the first date and the second page takes the second one, but I see the link 1 of the first and the second page. If you want to do this, it can be done. Thank you very much for helping
Copy link to clipboard
Copied
May I ask how you edited it to work on a mac? I´m totally new to using a mac and can´t spot where the code needs to be changed yet.
Copy link to clipboard
Copied
This would be soo awsome for me as I´m doing the same process. I have just gotten a MAC though and when I try the script it doesn´t work. Would it be a a terrible inconvenience if I asked you to modify it to work for a MAC? I mean, I would be soo grateful, but I sure understand if you do not have the time. All the best!
Copy link to clipboard
Copied
Hi @Jonatan296132974ogj, it works on MacOS already (I wrote it using a Mac). However, it written very specifically for a particular document. It is very unlikely to work in your case unless you set up the document the same. You need to follow what the script is doing and have a look at Wahid's sample document (test.indd) to see how the document is set up. - Mark
Copy link to clipboard
Copied
Oh it does? Then I must be doing anything wrong then. I´ve saved it as a .js and also tried .jsx and I´ve both tried it on my own documents and on your sample document which is set up exacly as the script is built for. I can´t get it to work though. (I have one or more cells in the calendar selected and have reinstalled my cc and it is the latest version.) Nothing happens when I run the script, no error and no "action" so to speak. Do you have any thoughts on what I´m doing wrong? Could it be that i get the file format wrong somehow? I dont have any fancy coding program, so on my past PC computer I saved it in notepad and changed the file type to .jsx or .js, and now since getting the mac I´ve tried saving it in "script editor" and changing the filetype afterwards to .js. You think that may be the issue? If you do, can you guide me further you think? Also, thanks a LOT for being so helpful and for replying so fast!! -Jonatan
Copy link to clipboard
Copied
Hi @Jonatan296132974ogj sorry for late reply. Paste the script into TextEdit and choose menu Format > Make Plain Text, and then save as .js.
- Mark
Copy link to clipboard
Copied
I am attemping the same thing, but with text frames instead of cells. I've tried amending the code, but get thrown errors. ChatGPT says that Adobe Id's scripting API doesn't allow you to hyperlink text frames (I used to hyperlink them manually but want to run a script). If I have my file set up the same as the test file, how can I select the text frames, it reads the number contained within, and then link out to respective page. For example, separate text frames of 1, 2, and 3 are selected. These link out to JUL-1, JUL-2, and JUL-3 respectively.
Copy link to clipboard
Copied
You need to change how hyperlinkSource is created:
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Hyperlink.html
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#HyperlinkPageItemSource.html#d1e115261
Copy link to clipboard
Copied
This is probably my 15th time trying to get the code to work.
var settings = {
pageNameTemplate: '#MONTHCODE#-#DAYNUMBER#',
hyperlinkNameTemplate: 'Goto-#MONTHCODE#-#DAYNUMBER#',
monthCodes: ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
};
function main() {
var doc = app.activeDocument;
var selectedItems = app.selection;
var counter = 0;
if (selectedItems.length == 0) {
alert('Please select one or more text frames and try again.');
return;
}
// Get the current page name from the first selected item
var currentPage = selectedItems[0].parentPage;
if (!currentPage || !currentPage.isValid) {
alert('Cannot determine the current page.');
return;
}
var currentPageName = currentPage.name;
var pageParts = currentPageName.split('-');
if (pageParts.length < 3) {
alert('Invalid page name format. It should be something like W-JUL-1. Current page name is: ' + currentPageName);
return;
}
var monthCode = pageParts[1];
if (settings.monthCodes.indexOf(monthCode) == -1) {
alert('Invalid month code in page name: ' + monthCode);
return;
}
for (var i = 0; i < selectedItems.length; i++) {
var textFrame = selectedItems[i];
if (textFrame.constructor.name != 'TextFrame') {
continue;
}
var dayNumber = parseInt(textFrame.contents.trim(), 10);
if (isNaN(dayNumber) || dayNumber <= 0) {
continue;
}
var destinationPageName = settings.pageNameTemplate
.replace('#MONTHCODE#', monthCode)
.replace('#DAYNUMBER#', dayNumber);
var hyperlinkName = settings.hyperlinkNameTemplate
.replace('#MONTHCODE#', monthCode)
.replace('#DAYNUMBER#', dayNumber);
var destinationPage = doc.pages.itemByName(destinationPageName);
if (!destinationPage.isValid) {
alert('There is no page named "' + destinationPageName + '". Script will skip this hyperlink.');
continue;
}
// Remove existing hyperlink if already exists
var existingHyperlink = doc.hyperlinks.itemByName(hyperlinkName);
if (existingHyperlink.isValid) {
existingHyperlink.remove();
}
// Set up new hyperlink
var hyperlinkSource = doc.hyperlinkPageItemSources.add(textFrame);
var hyperlinkDestination = doc.hyperlinkPageDestinations.add(destinationPage, { hidden: false });
var hyperlink = doc.hyperlinks.add(hyperlinkSource, hyperlinkDestination);
hyperlink.name = hyperlinkName;
counter++;
}
alert('Added ' + counter + ' hyperlinks.');
}
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Add Calendar Hyperlinks');
Copy link to clipboard
Copied
Is it working now?
What is your end goal?
Work on a selection - and do each page separately - or process whole document?
Because, you could go through activeDocument.stories collection - or TextFrames if you have breaks set up correctly - and then "simulate" selection so you can easier integrate it with your current code.
So, you would've to rename your main() function to ProcessSelection() or something, then create new main() that will go through Stories or TextFrames collection of the Document, select TextFrame - as long as it meets your naming convention - and then call ProcessSelection().
Minimal change to your current code.
Copy link to clipboard
Copied
Not working. My end goal is for the script to read the number entered in the text frame, say "21" and then looks at what the page is named, say "W-JUL-1" and hyperlinks that text-frame to page "JUL-21" because it registers that JUL is part of the page name structure. I'd like it to look through all the text frames in the document, but I realize that is super complicated since not all text frames will have just an integer. I am happy to have it run just with text frames I select. I'm not sure where to amend that in the code to get it to work.


-
- 1
- 2