Copy link to clipboard
Copied
ABCD Name
AD Name
ABD Name
I need to align the three above.
Some people may use grids, but that feature is difficult to use and I usually don't use it. It's better to use font spacing.
However, it is troublesome to adjust the font spacing. For example, when the font size becomes larger, I have to try every Letter spacing value.
Just want to ask: What is the relationship between font size and spacing, can we calculate it?
Hi @dublove5CFE, the issue here is converting tracking units (which I assume you are using to space out the A in the second line) into ruler units. Tracking is measured in em units which relate to the font size. The conversion factor is, 1000 / font size. Some fonts have differing sized em squares but Indesign seems to calibrate them all to 1000 units in terms of the UI and scripting API. You can see how it works in this script, that attempts to solve your problem.
/**
* Letterspace Chars T
...
Hi @dublove5CFE, I have written a modified version that also sets the tab stop so that the tab character width is 5mm (you can adjust this in the script). I've also put the letterspacing into a function so it can be used for other purposes.
Try this version and see what you think.
- Mark
/**
* Letterspace Chars Before Tab
* Script expects to have a text selection that includes
* paragraphs that share a tab stop, and will and will
* adjust tracking of characters before the tab character
*
...
Hi @dublove5CFE, it sounds like it might be better in your case just to replace the tab with another character of your choice. Here is a re-write of the script that replaces tab with em space u+2003. You could choose another unicode space character.
- Mark
/**
* Letterspace Chars Before Tab
* Script expects to have a text selection that includes
* paragraphs that share a tab stop, and will adjust
* tracking of characters before the tab character
* so that the last characters before each
...
Thank you Robert.
Copy link to clipboard
Copied
Letter spacing (kerning values) are set by the type designer and generally vary withthe combination of glyphs. For consistent spacing no matter waht the text might be you would need to use a mono-spaced font like Courier, or create your own.
I suspect this might work better if set up as a table. You could then use full justification in your paragraph styles to completely fill the width of each cell regardless of the number of characters.
Copy link to clipboard
Copied
The table is too cumbersome. Not a good idea
Copy link to clipboard
Copied
The table is too cumbersome. Not a good idea
By @dublove5CFE
Here is initial comment from the latest code created by m1b:
* Notes and assumptions:
* - Script assumes each paragraph is a single line.
This condition = "convert to table and forget" - earlier idea from @Peter Spier to use table... And would also automatically work for multiline paragraphs.
Copy link to clipboard
Copied
A,B,C,D,N,a,m,e - each one has a DIFFERENT width chosen by the font designer. But they scale reasonably exactly with the font size - if you go from 12 point to 24 point the letter spacing (for each letter, for that specific font and weight and style) is exactly double.
Copy link to clipboard
Copied
I have been searching for many years
Copy link to clipboard
Copied
You can type (or place) your tabbed text normally, then select it and Table > Convert text to table...
Copy link to clipboard
Copied
I'm not sure what you've been searching for. It doesn't seem to relate to my point about each font being different. But you don't have to guess, you can get the font metrics (or a programmer could...)
Copy link to clipboard
Copied
What EXACTLY are you trying to achieve?
Copy link to clipboard
Copied
Hi @dublove5CFE, the issue here is converting tracking units (which I assume you are using to space out the A in the second line) into ruler units. Tracking is measured in em units which relate to the font size. The conversion factor is, 1000 / font size. Some fonts have differing sized em squares but Indesign seems to calibrate them all to 1000 units in terms of the UI and scripting API. You can see how it works in this script, that attempts to solve your problem.
/**
* Letterspace Chars To Align Tab.
* Script expects to have a text selection that includes paragraphs share a tab stop,
* and will adjust tracking of characters before the tab character so that the last
* characters in each paragraph align.
* So that the script can be run multiple times, it resets tracking to 0 each time.
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/is-there-any-specific-algorithm-relationship-between-letter-spacing-and-font-size-in-indesign/m-p/13861581
*/
function main() {
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
const emSquare = 1000;
var doc = app.activeDocument,
text = doc.selection[0];
if (
text == undefined
|| typeof text.findGrep !== 'function'
) {
alert('Please select some text and run script again.');
return;
}
// find paragraphs with tabs
app.findGrepPreferences = NothingEnum.NOTHING;
app.findGrepPreferences.findWhat = '^[^\\t]+\\t';
var found = text.findGrep();
// store the horizontal position
// of the right-most tab
var positions = [],
maxPosition = -Infinity;
for (var i = 0; i < found.length; i++) {
found[i].tracking = 0;
positions[i] = found[i].insertionPoints[found[i].insertionPoints.length - 2].horizontalOffset;
if (positions[i] > maxPosition)
maxPosition = positions[i];
}
// track out the initial characters
for (var i = 0; i < found.length; i++) {
if (positions[i] == maxPosition)
continue;
var chars = found[i].characters.itemByRange(0, found[i].characters.length - 3).characters;
for (var j = 0; j < chars.length; j++)
chars[j].tracking = ((maxPosition - positions[i]) / chars.length) * (emSquare / chars[j].pointSize);
}
}; // end main
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Space Chars Before Tab");
Edit 2023-06-15: reset tracking to zero time.
Edit 2023-06-16: now correctly handles no characters before tab.
In the script you can see the conversion into em units here: <ruler distance> * (emSquare / chars[j].pointSize). Where emSquare is 1000.
Note that for convenience I altered your example so that every paragraph has a tab character to tell the script where to align. The script will only work if there is a tab in every selected paragraph—it will try to align the text before the tab. Here is what it does when I run it:
Let me know if that helps.
- Mark
Copy link to clipboard
Copied
That's great.
Very effective, thank you very much.
I can quickly get different Letter spacing and add these values to the character style.
Use grep to call these character styles in paragraph styles
Copy link to clipboard
Copied
Found a small problem.
If you later add or delete content, the script will become invalid
You need to manually set the Letter spacing to 0, and then run the script.
Copy link to clipboard
Copied
I try to modify the script. Clear the Letter spacing before running the script.
I failed.
Copy link to clipboard
Copied
No problem. I have updated the script above.
- Mark
Copy link to clipboard
Copied
Can you control the value of the Tab key?
It would be great if it could be added to the script.
Using the longest character before the tab as a reference, set the value of the tab?
Copy link to clipboard
Copied
Starting with the Tab key will prompt for an error.
And there is also no alignment
Copy link to clipboard
Copied
Hi @dublove5CFE, I have written a modified version that also sets the tab stop so that the tab character width is 5mm (you can adjust this in the script). I've also put the letterspacing into a function so it can be used for other purposes.
Try this version and see what you think.
- Mark
/**
* Letterspace Chars Before Tab
* Script expects to have a text selection that includes
* paragraphs that share a tab stop, and will and will
* adjust tracking of characters before the tab character
* so that the last characters in each paragraph align.
* It will set a tab stop so that the width of the tab
* character equals `tabWidth`.
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/is-there-any-specific-algorithm-relationship-between-letter-spacing-and-font-size-in-indesign/m-p/13861581
*/
function main() {
var tabWidth = '5mm';
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var doc = app.activeDocument,
text = doc.selection[0];
if (
text == undefined
|| typeof text.findGrep !== 'function'
|| text.contents == ''
) {
alert('Please select some text and run script again.');
return;
}
// find paragraphs with tabs
app.findGrepPreferences = NothingEnum.NOTHING;
app.findGrepPreferences.findWhat = '^[^\\t]*\\t';
var found = text.findGrep();
// store the horizontal position
// of the right-most tab
var positions = [],
maxPosition = -Infinity,
tabPosition = 0,
tabWidthPts = new UnitValue(tabWidth).as('pt');
for (var i = 0; i < found.length; i++) {
found[i].tracking = 0;
positions[i] = found[i].insertionPoints[found[i].insertionPoints.length - 2].horizontalOffset;
if (positions[i] > maxPosition) {
maxPosition = positions[i];
left = found[i].insertionPoints[0].horizontalOffset;
tabPosition = found[i].insertionPoints[found[i].insertionPoints.length - 1].horizontalOffset;
}
}
for (var i = 0; i < found.length; i++) {
var tabStops = found[i].tabStops;
// remove all tab stops in alignment area
for (var j = tabStops.length - 1; j >= 0; j--)
if (tabStops[j].position <= Math.max(maxPosition + tabWidthPts, tabPosition))
tabStops[j].remove();
// set a tab stop to match the tabWidth
tabStops.add({ position: maxPosition - left + tabWidthPts });
if (
positions[i] !== maxPosition
&& found[i].characters.length > 1
)
// letterspace the characters before tab
letterspaceToWidth(found[i].characters.itemByRange(0, found[i].characters.length - 2), maxPosition - found[i].insertionPoints[0].horizontalOffset);
}
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Space Chars Before Tab");
/**
* Applies tracking to text so that
* the width of the text will match
* with `width` parameter supplied.
* Assumptions:
* - text is justified left
* - text is uniform point size
* - text doesn't span multiple lines
* @author m1b
* @version 2023-06-16
* @param {Text} text - an Indesign text object.
* @param {Number} width - the desired width in pts.
*/
function letterspaceToWidth(text, width) {
if (!text.hasOwnProperty('insertionPoints'))
return;
const emSquare = 1000;
var left = text.insertionPoints[0].horizontalOffset,
right = text.insertionPoints[text.insertionPoints.length - 1].horizontalOffset,
chars = text.characters.itemByRange(0, text.characters.length - 2).characters,
delta = width - (right - left);
for (var i = 0; i < chars.length; i++)
chars[i].tracking = (delta / chars.length) * (emSquare / chars[i].pointSize);
};
Copy link to clipboard
Copied
Yes, that's it. You're amazing.
Thank you.
Your script may be included by Adobe in the future and comes with it
Copy link to clipboard
Copied
var tabWidth = '4mm';
Another question
How to write this sentence with one character width?
Full width or half width characters.
thanks.
Copy link to clipboard
Copied
Hi @dublove5CFE, it sounds like it might be better in your case just to replace the tab with another character of your choice. Here is a re-write of the script that replaces tab with em space u+2003. You could choose another unicode space character.
- Mark
/**
* Letterspace Chars Before Tab
* Script expects to have a text selection that includes
* paragraphs that share a tab stop, and will adjust
* tracking of characters before the tab character
* so that the last characters before each tab align
* vertically. Script will replace tab with a character
* of your choice.
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/is-there-any-specific-algorithm-relationship-between-letter-spacing-and-font-size-in-indesign/m-p/13861581
*/
function main() {
// replace tab with em space
var dividerChar = '\u2003';
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
var doc = app.activeDocument,
text = doc.selection[0];
if (
text == undefined
|| typeof text.findGrep !== 'function'
|| text.contents == ''
) {
alert('Please select some text and run script again.');
return;
}
// add space when no characters before tab
app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.NOTHING;
app.findGrepPreferences.findWhat = '^([\\t]?)\\t';
app.changeGrepPreferences.changeTo = ' $0';
text.changeGrep();
// find paragraphs with tabs
app.findGrepPreferences.findWhat = '^[^\\t]*\\t';
var found = text.findGrep();
// store the horizontal position
// of the right-most tab
var positions = [],
maxPosition = -Infinity;
for (var i = 0; i < found.length; i++) {
// start with no letterspacing
found[i].tracking = 0;
positions[i] = found[i].insertionPoints[found[i].insertionPoints.length - 2].horizontalOffset;
if (positions[i] > maxPosition) {
maxPosition = positions[i];
left = found[i].insertionPoints[0].horizontalOffset;
}
}
for (var i = 0; i < found.length; i++) {
if (
positions[i] !== maxPosition
// && found[i].characters.length > 1
)
// letterspace the characters before tab
letterspaceToWidth(found[i].characters.itemByRange(0, found[i].characters.length - 2), maxPosition - found[i].insertionPoints[0].horizontalOffset);
// replace tab with a divider character
found[i].characters.lastItem().contents = dividerChar;
}
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Letterspace Chars Before Tab");
/**
* Applies tracking to text so that
* the width of the text will match
* with `width` parameter supplied.
* Assumptions:
* - text is justified left
* - text is uniform point size
* - text doesn't span multiple lines
* @author m1b
* @version 2023-06-16
* @param {Text} text - an Indesign text object.
* @param {Number} width - the desired width in pts.
*/
function letterspaceToWidth(text, width) {
if (!text.hasOwnProperty('insertionPoints'))
return;
const emSquare = 1000;
var left = text.insertionPoints[0].horizontalOffset,
right = text.insertionPoints[text.insertionPoints.length - 1].horizontalOffset,
chars = text.characters.itemByRange(0, text.characters.length - 2).characters,
delta = width - (right - left);
for (var i = 0; i < chars.length; i++)
chars[i].tracking = (delta / chars.length) * (emSquare / chars[i].pointSize);
};
Copy link to clipboard
Copied
Thank you~
Forget it, I'll manually modify the tab value.
This space looks so strange.
I want to keep the tab, just make sure that the spacing between the tabs is exactly one word wide
Copy link to clipboard
Copied
Okay, no worries. I'm sure I can make the script do what you want, but I don't understand what you mean. Sorry.
- Mark
Copy link to clipboard
Copied
I'm sorry to trouble you too much.
I want to keep using tab, just make the value of tab exactly one character wide.
(Full width character width)
This way, I don't need to try adjusting this value multiple times.
Copy link to clipboard
Copied
I'll repeat myself - what are you trying to achieve OVERALL?
What kind of publication are you preparing?
How do you get your data? How is it originally formatted?
Can you show us more real life example screenshot?
Copy link to clipboard
Copied
sorry
Find more inspiration, events, and resources on the new Adobe Community
Explore Now