inDesign 脚本 - 从 "typesetting script" TextFrame 剪切并粘贴到空 TextFrame
inDesign Scripting - Cut from "typesetting script" TextFrame and paste on empty TextFrame
我需要一个 Adobe 脚本来执行此操作:
- Select 带有整个文本脚本的 TextFrame(page1、text、page2、text 等等);
- 截一段(一般用\r或^p分隔);
- 用户 selects 或创建一个新的 TextFrame;
- 将之前剪切的线粘贴到新的空TextFrame上;和
- 转到下一段。
我一直在做这个排版工作,我遇到了这个 Typesetterer for Photoshop, went on a journey to find a similar script/application for inDesign and I found this this solution, tried it and worked, boosting my productivity by at least 2x. Tried this split one 但是调整大小和移动所有生成的 TextFrames 需要更长的时间。但它对我开发最终代码非常有用。
这种方法的主要问题是它要求排版脚本在 .txt 文件中,这破坏了所有 Bold 和 Italic 来自原始脚本。
main();
function main() { // Main() just to keep it organized
try {
var myMeasuringUnit = app.scriptPreferences.measurementUnit;
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
} catch (exception) {
alert(exception.description);
exit();
}
var myTextFrameSelection = app.activeDocument.selection;
cutAndPaste(myTextFrameSelection);
try {
app.scriptPreferences.measurementUnit = myMeasuringUnit;
} catch (exception) {}
}
function cutAndPaste(myTextFrameSelection) {
for (elementsInSelection = 0; elementsInSelection < myTextFrameSelection.length; elementsInSelection++) {
if (myTextFrameSelection[elementsInSelection].constructor.name == "TextFrame") {
var myParagraphs = myTextFrameSelection[elementsInSelection].texts[0].paragraphs;
var isCopied = true;
for (var i = 0; i < myParagraphs.length; i++) {
try {
myParagraphs[i].insertionPoints.itemByRange(0, -2).select();
app.cut();
isCopied = true;
} catch (exception) {
isCopied = false;
}
if (isCopied) {
/*
Attempt at adding a way to select another TextFrame and app.paste() the previously app.cut() line in it
var doc = app.activeDocument.selection[0];
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
if (doc.selection[0] instanceof TextFrame && doc.selection[0].contents == '' && doc.selection[1] == null) {
if (doc.selection[0] instanceof TextFrame) {
doc.selection[0].contents = app.paste();
}
}
*/
app.paste(); // This just pastes it in the same folder
}
}
}
}
} // For now, what it does it "cut paragraph from the TextFrame but also paste in the same TextFrame"
到目前为止,它只是从 TextFrame 中逐段剪切,然后粘贴到同一个 TextFrame 上。它接近于做我需要的事情,但我似乎无法在主循环中找到 select 新框架的方法。我评论了我正在努力工作的可能解决方案。
也许我也使用了错误的 cut/paste 功能?也许修改第二个 link 解决方案以接受 .docx 更容易?
RisingFog's solution and Eugeny Budantsev solition 之间的重要区别在于与用户的交互。以前的脚本显示对话框 window 并保持 运行ning 直到您关闭 window。稍后 运行 仅一次,无法继续跟踪用户操作。
所以如果你想保留你的脚本 运行ning(并做一些对用户操作的反应)你需要显示一些 window 即使 window 将是空的。像这样:
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 200;
dialog.preferredSize.height = 50;
dialog.text = "Select next frame";
dialog.onClose = function() {
doc.removeEventListener('afterSelectionChanged', selectionChanged);
}
dialog.show();
var doc = app.activeDocument;
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
// here is the code that will run wenever you change selection
if (doc.selection[0] instanceof TextFrame
&& doc.selection[0].contents == ''
&& doc.selection[1] == null) {
alert('Next empty text frame is selected!')
}
}
当然你可以用一些文字或按钮填充window。
更新
下面是如何从 selected 非空文本框(假设它是文本脚本)中剪切第一段并将该段落自动粘贴到下一个 selected 空框的示例:
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 300;
dialog.preferredSize.height = 50;
dialog.text = "Please, select next frame";
dialog.onClose = function() {
doc.removeEventListener('afterSelectionChanged', selectionChanged);
}
dialog.add("statictext", undefined, "Last cutted text:");
var msg = dialog.add("edittext");
msg.text = "";
msg.characters = 40
dialog.show();
var doc = app.activeDocument;
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
var sel = doc.selection[0];
if (sel instanceof InsertionPoint) sel = sel.parent.textContainers[0];
if (sel instanceof TextFrame || sel instanceof Story) {
if (sel.contents != '') {
app.select(sel.paragraphs[0], SelectionOptions.REPLACE_WITH);
msg.text = sel.paragraphs[0].contents;
app.cut();
app.selection = null;
}
else {
sel.texts.everyItem().select();
app.paste();
app.selection = null;
// remove '\r' at the very end of text in the frame
app.findGrepPreferences.findWhat ="\r$";
app.changeGrepPreferences.changeTo = "";
sel.changeGrep();
}
}
}
更新 2
这是相同的脚本。唯一不同的是,您不再需要单击文本脚本框架。在 运行 脚本之前,您需要 select 文本框,然后每次单击任何空文本框时,脚本都会自动从该框架中剪切第一段。
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 300;
dialog.preferredSize.height = 50;
dialog.text = "Please, select next frame";
dialog.onClose = function() {doc.removeEventListener('afterSelectionChanged', selectionChanged)}
dialog.add("statictext", undefined, "Last copied text:");
var msg = dialog.add("edittext");
msg.text = "";
msg.characters = 40;
// --- here is the Pause button
var pause = false;
var pause_btn = dialog.add("button", [10,10,300,30], "Pause");
pause_btn.onClick = function() {
pause = !pause;
// if (pause) msg.text = "[PAUSED] " + msg.text; // it can be done better, but it works, too
// if (!pause) msg.text = msg.text.replace(/^\[PAUSED\] /, "");
pause_btn.text = pause ? "Resume" : "Pause"; // this is way better
};
// ---
var doc = app.activeDocument;
var master_frame = app.selection[0]; // <-- the Text Script frame
if (master_frame instanceof TextFrame || master_frame instanceof Story) {
dialog.show();
app.selection = null;
doc.addEventListener('afterSelectionChanged', selectionChanged);
} else {
alert("Please, select a frame with text before run the script!");
exit();
}
function selectionChanged() {
if (pause) return; // <-- here you check the state of the button
var sel = doc.selection[0];
if (sel instanceof InsertionPoint) sel = sel.parent.textContainers[0];
if (sel instanceof TextFrame || sel instanceof Story) {
if (sel.contents == '' && master_frame.contents != '') {
app.select(master_frame.paragraphs[0], SelectionOptions.REPLACE_WITH);
msg.text = master_frame.paragraphs[0].contents;
app.cut();
app.selection = null;
sel.texts.everyItem().select();
app.paste();
app.selection = null;
// remove '\r' at the end
app.findGrepPreferences.findWhat ="\r$";
app.changeGrepPreferences.changeTo = "";
sel.changeGrep();
}
if (master_frame.contents == '') alert ("No text to paste anymore!")
}
}
我已将 'Pause' 按钮添加到 window。
我需要一个 Adobe 脚本来执行此操作:
- Select 带有整个文本脚本的 TextFrame(page1、text、page2、text 等等);
- 截一段(一般用\r或^p分隔);
- 用户 selects 或创建一个新的 TextFrame;
- 将之前剪切的线粘贴到新的空TextFrame上;和
- 转到下一段。
我一直在做这个排版工作,我遇到了这个 Typesetterer for Photoshop, went on a journey to find a similar script/application for inDesign and I found this this solution, tried it and worked, boosting my productivity by at least 2x. Tried this split one 但是调整大小和移动所有生成的 TextFrames 需要更长的时间。但它对我开发最终代码非常有用。
这种方法的主要问题是它要求排版脚本在 .txt 文件中,这破坏了所有 Bold 和 Italic 来自原始脚本。
main();
function main() { // Main() just to keep it organized
try {
var myMeasuringUnit = app.scriptPreferences.measurementUnit;
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
} catch (exception) {
alert(exception.description);
exit();
}
var myTextFrameSelection = app.activeDocument.selection;
cutAndPaste(myTextFrameSelection);
try {
app.scriptPreferences.measurementUnit = myMeasuringUnit;
} catch (exception) {}
}
function cutAndPaste(myTextFrameSelection) {
for (elementsInSelection = 0; elementsInSelection < myTextFrameSelection.length; elementsInSelection++) {
if (myTextFrameSelection[elementsInSelection].constructor.name == "TextFrame") {
var myParagraphs = myTextFrameSelection[elementsInSelection].texts[0].paragraphs;
var isCopied = true;
for (var i = 0; i < myParagraphs.length; i++) {
try {
myParagraphs[i].insertionPoints.itemByRange(0, -2).select();
app.cut();
isCopied = true;
} catch (exception) {
isCopied = false;
}
if (isCopied) {
/*
Attempt at adding a way to select another TextFrame and app.paste() the previously app.cut() line in it
var doc = app.activeDocument.selection[0];
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
if (doc.selection[0] instanceof TextFrame && doc.selection[0].contents == '' && doc.selection[1] == null) {
if (doc.selection[0] instanceof TextFrame) {
doc.selection[0].contents = app.paste();
}
}
*/
app.paste(); // This just pastes it in the same folder
}
}
}
}
} // For now, what it does it "cut paragraph from the TextFrame but also paste in the same TextFrame"
到目前为止,它只是从 TextFrame 中逐段剪切,然后粘贴到同一个 TextFrame 上。它接近于做我需要的事情,但我似乎无法在主循环中找到 select 新框架的方法。我评论了我正在努力工作的可能解决方案。
也许我也使用了错误的 cut/paste 功能?也许修改第二个 link 解决方案以接受 .docx 更容易?
RisingFog's solution and Eugeny Budantsev solition 之间的重要区别在于与用户的交互。以前的脚本显示对话框 window 并保持 运行ning 直到您关闭 window。稍后 运行 仅一次,无法继续跟踪用户操作。
所以如果你想保留你的脚本 运行ning(并做一些对用户操作的反应)你需要显示一些 window 即使 window 将是空的。像这样:
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 200;
dialog.preferredSize.height = 50;
dialog.text = "Select next frame";
dialog.onClose = function() {
doc.removeEventListener('afterSelectionChanged', selectionChanged);
}
dialog.show();
var doc = app.activeDocument;
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
// here is the code that will run wenever you change selection
if (doc.selection[0] instanceof TextFrame
&& doc.selection[0].contents == ''
&& doc.selection[1] == null) {
alert('Next empty text frame is selected!')
}
}
当然你可以用一些文字或按钮填充window。
更新
下面是如何从 selected 非空文本框(假设它是文本脚本)中剪切第一段并将该段落自动粘贴到下一个 selected 空框的示例:
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 300;
dialog.preferredSize.height = 50;
dialog.text = "Please, select next frame";
dialog.onClose = function() {
doc.removeEventListener('afterSelectionChanged', selectionChanged);
}
dialog.add("statictext", undefined, "Last cutted text:");
var msg = dialog.add("edittext");
msg.text = "";
msg.characters = 40
dialog.show();
var doc = app.activeDocument;
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
var sel = doc.selection[0];
if (sel instanceof InsertionPoint) sel = sel.parent.textContainers[0];
if (sel instanceof TextFrame || sel instanceof Story) {
if (sel.contents != '') {
app.select(sel.paragraphs[0], SelectionOptions.REPLACE_WITH);
msg.text = sel.paragraphs[0].contents;
app.cut();
app.selection = null;
}
else {
sel.texts.everyItem().select();
app.paste();
app.selection = null;
// remove '\r' at the very end of text in the frame
app.findGrepPreferences.findWhat ="\r$";
app.changeGrepPreferences.changeTo = "";
sel.changeGrep();
}
}
}
更新 2
这是相同的脚本。唯一不同的是,您不再需要单击文本脚本框架。在 运行 脚本之前,您需要 select 文本框,然后每次单击任何空文本框时,脚本都会自动从该框架中剪切第一段。
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 300;
dialog.preferredSize.height = 50;
dialog.text = "Please, select next frame";
dialog.onClose = function() {doc.removeEventListener('afterSelectionChanged', selectionChanged)}
dialog.add("statictext", undefined, "Last copied text:");
var msg = dialog.add("edittext");
msg.text = "";
msg.characters = 40;
// --- here is the Pause button
var pause = false;
var pause_btn = dialog.add("button", [10,10,300,30], "Pause");
pause_btn.onClick = function() {
pause = !pause;
// if (pause) msg.text = "[PAUSED] " + msg.text; // it can be done better, but it works, too
// if (!pause) msg.text = msg.text.replace(/^\[PAUSED\] /, "");
pause_btn.text = pause ? "Resume" : "Pause"; // this is way better
};
// ---
var doc = app.activeDocument;
var master_frame = app.selection[0]; // <-- the Text Script frame
if (master_frame instanceof TextFrame || master_frame instanceof Story) {
dialog.show();
app.selection = null;
doc.addEventListener('afterSelectionChanged', selectionChanged);
} else {
alert("Please, select a frame with text before run the script!");
exit();
}
function selectionChanged() {
if (pause) return; // <-- here you check the state of the button
var sel = doc.selection[0];
if (sel instanceof InsertionPoint) sel = sel.parent.textContainers[0];
if (sel instanceof TextFrame || sel instanceof Story) {
if (sel.contents == '' && master_frame.contents != '') {
app.select(master_frame.paragraphs[0], SelectionOptions.REPLACE_WITH);
msg.text = master_frame.paragraphs[0].contents;
app.cut();
app.selection = null;
sel.texts.everyItem().select();
app.paste();
app.selection = null;
// remove '\r' at the end
app.findGrepPreferences.findWhat ="\r$";
app.changeGrepPreferences.changeTo = "";
sel.changeGrep();
}
if (master_frame.contents == '') alert ("No text to paste anymore!")
}
}
我已将 'Pause' 按钮添加到 window。