Think.JS №17

  • Для начинающих: Параметры страницы документа
  • Полевые испытания: Печать документов. Общие сведения
  • Начальное ускорение: Быстрый и универсальный
  • Полезный скрипт: Излишество вредит

Содержание

Для начинающих: Параметры страницы документа

Полевые испытания: Печать документов. Общие сведения

Начальное ускорение: Быстрый и универсальный

Полезный скрипт: Излишество вредит

Для начинающих

Параметры страницы документа

Создавать новые документы из скрипта приходится довольно часто. Изменять параметры страниц ранее созданного документа – значительно реже, но тоже приходится. Разберем основные объекты и их свойства, которые относятся к управлению видом страниц.

Базовым объектом, который влияет на внешний вид всех страниц документа, является свойство documentPreferences объекта типа document. Это свойство в свою очередь имеет достаточно широкий набор свойств, которые регулируют как свойства страниц, так и их поведение в составе разворотов. Например, размеры страниц документа определяются изменяемым свойством documentPreferences.pageHeight и documentPreferences.pageWidth.

pageInfo.jsx
Скрипт информирует о размерах страницы активного документа
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Получаем и выводим информацию о размерах страницы документа
  with (myDoc.documentPreferences) {
    alert("Высота страницы: " + pageHeight + "\nШирина страницы: " + pageWidth);
  }
}

При выполнении указанного скрипта в документе со стандартным форматом А4 или А3 полученное значение будет на стотысячные доли миллиметра меньше реального размера. Казалось бы, парадокс? На самом деле ничего удивительного. Как уже неоднократно говорилось, базовой единицей измерения в InDesign является пункт, поэтому при приведении к миллиметрам возможны некоторые потери в точности, особенно в малых долях. Однако даже такие потери способны вызвать неправильную работу скрипта. Один из написанных мной скриптов должен был автоматически размещать в документе некие группы объектов с изменяемыми полями, при этом в нем была реализовано вычисление количества рядов и строк, основанная на размерах страницы и объекта. При всех внешне правильных расчетах, не получалось поместить впритык два объекта, размеры которых были точно равны половине ширины страницы. Все дело оказалось в тех десятитысячных миллиметра, которые терялись при пересчете из пунктов в миллиметры. Решением этой проблемы стало округление значения до целого числа. Такое решение нельзя рекомендовать для повсеместного употребления, но для форматов А оно подойдет.

pageInfo.jsx
Скрипт информирует о размерах страницы активного документа
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Получаем и выводим информацию о размерах страницы документа (с округлением до целого)
  with (myDoc.documentPreferences) {
    alert("Высота страницы: " + Math.round(pageHeight) + "\nШирина страницы: " + Math.round(pageWidth));
  }
}

Поскольку свойства pageHeight и pageWidth являются изменяемыми, то с их помощью можно не только получать размеры страницы, но и задавать их.

pageSetup.jsx
Скрипт устанавливает размеры страниц активного документа
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Задаем размеры страниц документа
  with (myDoc.documentPreferences) {
    pageHeight = "100mm";
    pageWidth = "100mm";
  }
}

С помощью свойства documentPreferences.pagesPerDocument можно также управлять количеством страниц в документе. Такая возможность полезна в том случае, если в документ нужно добавить определенное количество страниц, не прибегая к методу pages.add(). В том случае, если количество страниц документа больше, чем указывается, то страницы, находящиеся за пределами указанного диапазона будут удалены.

Свойство documentPreferences.PageOrientation определяет ориентацию страницы. Значением этого свойства могут быть значения нумератора PageOrientation, которых всего два: PageOrientation.portrait (1751738216) и PageOrientation.landscape (2003395685).

Свойство documentPreferences.facingPages отвечает за группировку страниц в развороты. При значении true страницы группируются, при false – отображаются по отдельности. Отключать это свойство рекомендуется в том случае, если скрипт должен работать с каждой страницей документа по отдельности. При этом нужно учитывать, что отключение свойства ведет к тому, что каждая страница будет считаться первой в развороте, соответственно и объекты мастер-страницы будут применены в соответствии.

facingPage.jsx
Скрипт демонстрирует использование свойства facingPage
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
  with (myDoc.documentPreferences) {
// Задаем количество страниц в документе
    pagesPerDocument = 20;
// Задаем ориентацию страниц в документе
    pageOrientation = PageOrientation.landscape;
// Отключаем группировку в разворот
    facingPages = false;
  }
}

Отступы и настройки колонок могут быть заданы для каждой страницы персонально. Как правило, общие настройки задаются при помощи мастер-страниц (как с ними обращаться, рассмотрим позже), но настройки каждой страницы могут быть изменены независимо от настроек остальных страниц. Для управления этими настройками используется свойство marginPreferences. Для установки отступов используются соответственно свойства top, bottom, left, right (сверху, снизу, справа, слева).

pageMarginSet.jsx
Скрипт устанавливает отступы страницы
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Устанавливаем отступы первой страницы
  with (myDoc.pages[0].marginPreferences) {
    top = "20mm";
    bottom = "20mm";
    left = "10mm";
    right = "10mm";
  }
}

Кроме значения отступов можно установить количество колонок на странице и значение средника между ними. Количество колонок – columnCount – может находиться в диапазоне от 1 до 216, средник – columnGutter – в пределах от 0 до 1440 пунктов.

columnSet.jsx
Скрипт устанавливает настройки колонок
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Устанавливаем количество колонок и средник
  with (myDoc.pages[0].marginPreferences) {
    columnCount = 3;
    columnGutter = "3mm";
  }
}

Ширина колонок может быть не одинаковой. Для задания произвольной ширины колонок используется columnsPositions, значением которого является массив с указанием начальной и конечной координаты каждой колонки.

columnArraySet.jsx
Скрипт устанавливает произвольные размеры колонок при помощи массива
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
//Устанавливаем произвольные размеры колонок
  with (myDoc.pages[0].marginPreferences) {
    columnsPositions = [0,45,50,95,100,145,150,195];
  }
}

Основным неудобством этого метода является то, что параметры должны передаваться опять-таки в пунктах, что при работе с другими единицами измерения требует пересчета. Однако использование этого свойства бывает полезно в том случае, если нужно разместить текст по колонкам – в этом случае нужно точно знать координаты колонок, которые можно определить исходя из отступов и свойства columnsPositions.

Определить, используются ли произвольные размеры колонок (такое бывает в случае, если пользователь случайно сдвинул одну из колонок даже на небольшое расстояние) можно при помощи свойства customColumns. При значении true колонки расположены в произвольном порядке, при значении false – рассчитаны автоматически. Для того, чтобы восстановить автоматическое расположение, достаточно заново указать количество колонок и интервал.

Полевые испытания

Печать документов. Общие сведения

Печатать документы при помощи скриптов приходится нечасто, в основном по запросу пользователя. Но такие скрипты, написанные для собственного пользования, могут сэкономить немало времени, например, во время печати в файл указанного диапазона страниц сразу в «горячую папку» Adobe Distiller для автоматической обработки.

Для того чтобы напечатать документ, нужно вызвать для него метод print(), который имеет два параметра: showDialog – логическое значение, определяющее, будет показан диалог печати (true – будет, false – нет), и printPreset – заранее сохраненный набор установок печати.

documentPrint.jsx
Скрипт демонстрирует использование метода print
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
  myDoc.print(true);
}

Как видно, в методе нет параметров, которые определяли бы хотя бы диапазон печатаемых страниц. При использовании диалога печати это не доставляет пользователю неудобств, но если нужно печатать без диалога, нужно сначала настроить специальный набор свойств печати – printPreferences.

Свойство printPreferences относится к конкретному документу и редактируется до вызова метода print(). В свою очередь printPreferences имеет большое количество свойств. Рассмотрим наиболее важные из них.

Диапазон печатаемых страниц определяется при помощи свойства printPreferences.pageRange, который может быть как строкой с описанием диапазона, так и свойством нумератора PageRange.allPages (для печати всех страниц).

printRange.jsx
Скрипт демонстрирует использование диапазона страниц при печати
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Настраиваем свойства печати
  with (myDoc.printPreferences) {
    pageRange = "1-3";
  }
// Выполняем печать  
  myDoc.print(true);
}

Если указанный диапазон не согласуется с количеством страниц в документе, скрипт завершится с ошибкой. О том, как обрабатывать диапазоны, введенные пользователем вручную, читайте в рассылке № 15.

Еще одним полезным свойством является printPreferences.printer, позволяющее установить текущий принтер. Но в каждой системе обычно свой персональный набор принтеров, состав которого заранее узнать нельзя (даже если скрипт пишется для собственного употребления, желательно делать проверку существования целевого принтера). В крайнем случае можно распечатать документ на специальный принтер-нумератор Printer.postscriptFile, который доступен из InDesign при любом наборе принтеров в системе. Но можно получить весь набор доступных принтеров и выбрать из него нужный. Делается это при помощи свойства printerList, содержащего массив строк – имен принтеров. Этот массив очень удобно использовать в диалогах без всякой предварительной обработки

setPrinter.jsx
Скрипт демонстрирует возможность выбора активного принтера
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Создаем диалог
  var myDialog = dialogs.add();
  with (myDialog.dialogColumns.add().borderPanels.add().dialogColumns.add()) {
    dialogRows.add().staticTexts.add({staticLabel: "Выберите принтер"});
// Создаем выпадающий список при помощи списка принтеров
    var userPrinter = dialogRows.add().dropdowns.add({stringList: myDoc.printPreferences.printerList, selectedIndex: 0});
  }
// Отображаем диалог
  var myResult = myDialog.show();
  if (!myResult) {
    exit();
  }
// Настраиваем принтер и диапазон страниц  
  with (myDoc.printPreferences) {
   printer = printerList[userPrinter.selectedIndex];
   pageRange = PageRange.allPages;
  }
// Печатаем документ
  myDoc.print(true);
}

В следующий раз мы подробно разберем, как при помощи скрипта печатать каждую краску документа по отдельности.

Начальное ускорение

Быстрый и универсальный

В этот раз речь снова пойдет о быстрой обработке текстовых объектов InDesign при помощи методов обработки срок JavaScript. В прошлый раз мы рассмотрели, как обрабатывать текст от начала абзаца до специального символа или от специального символа до конца абзаца. В этот раз мы напишем универсальную функцию для обработки текста по парам специальных символов, которых в тексте может быть любое количество.

Определим основную задачу функции. Функция должна искать в указанном тексте все вхождения спецсимвола (или группы спецсимволов) и возвращать соответствующие индексы в виде массива. В качестве дополнительного параметра функция должна принимать логическое значение, указывающее, нужно ли при определении индекса учитывать длину искомого символа (для того, чтобы можно было включать спецсимволы в обрабатываемый текст). При этом нужно учитывать, является ли спецсимвол открывающим тегом либо закрывающим, поскольку от этого зависит подсчет индекса.

Для реализации поиска используется тот же самый метод indexOf(), который мы использовали ранее, но с одним отличием. В качестве второго параметра функции передается индекс символа, с которого следует начать поиск, что позволяет найти все вхождения спецсимвола в тексте.

textFormatter.jsx
Скрипт демонстрирует использование метода indexOf() при быстром форматировании текста
// Функция быстрого поиска вхождений
function seek (myText, mySymbol, myOpen, myIncSym) {
// Создаем массив для хранения результата
  var myResult = [];
// Создам переменную для хранения текущей позиции (также используется для проверки условия цикла)
  var myPosition = 0;
// Пока текущая позиция меньше чем длина текста
  while (myPosition < myText.length) {
// Получаем индек вхождения спецсимвола от текущей позиции
    var myIndex = myText.indexOf(mySymbol, myPosition);
// Если индекс равен -1, выходим, поскольку ничего не найдено
    if (myIndex == -1) {
      break;
    }
// Если текущий спецсимвол указан как открывающий тег
    if (myOpen) {
// Если указано включение спецсимвола в обрабатываемый текст      
      if (myIncSym) {
// Заносим в массив результата значение индекса
        myResult.push(myIndex);
// Если не указано включение спецсимвола в обрабатываемый текст
      } else {
// Заносим в массив результата значение с учетом длины спецсимвола        
        myResult.push(myIndex + mySymbol.length);
      }
// Если текущий спецсимвол указан как закрывающий тег      
    } else {
// Если указано включение спецсимвола в обрабатываемый текст      
      if (myIncSym) {
// Заносим в массив результата значение с учетом длины спецсимвола
        myResult.push(myIndex + mySymbol.length -1);
// Если не указано включение спецсимвола в обрабатываемый текст
      } else {
// Заносим в массив результата значение индекса (-1 потому, что тег закрывающий)        
        myResult.push(myIndex - 1);
      }      
    }
// Смещаем позицию поиска на первый символ после найденного    
    myPosition = myIndex + mySymbol.length;
  }
  return myResult;
}
with (app) {
// Получаем активный документ
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Получаем текст  
  try {
    var myStory = selection[0]
  } catch (error) {
    exit ();
  }
// Ищем левую скобку как открывающий тег без включения
  var myStart = seek(myStory.contents, "(", true, false);
// Ищем правую скобку как закрывающий тег без включения  
  var myEnd = seek(myStory.contents, ")", false, false);
// Если длина найденных массивов не совпадает (непарные теги), выходим
  if (myStart.length != myEnd.length) {
    exit();
  }
// В цикле обрабатываем найденные индексы
  for (var counter = 0; counter < myStart.length; counter++) {
// На всякий случай проверяем, какое из значений больше
    if (myStart[counter] < myEnd[counter]) {
      var myText = myStory.characters.itemByRange(myStart[counter], myEnd[counter]);
    } else {
      var myText = myStory.characters.itemByRange(myEnd[counter], myStart[counter]);
    }
// Форматируем текст
    myText.fontStyle = "Bold";
  }
}

Полезный скрипт

Излишество вредит

Плохо, когда связанные файлы в документе имеют слишком маленькое эффективное разрешение. Также ничего хорошего, если они имеют более высокое разрешение, чем требуется. Совсем плохо искать такие файлы вручную.

По просьбе одного из пользователей рассылки был написан скрипт, который создает отчет с информацией о связанных файлах, в которых разрешение либо недостает до нужного, либо наличествует в излишнем количестве. Информация выдается постранично, что достаточно удобно. Думаю, пригодится многим.

linkInfo.jsx
Скрипт создает отчет о связанных файлах с несоответствующим разрешением
// Определяем допустимый интервал разрешений
var iniMinResolution = 250;
var iniMaxResolution = 300;
with (app) {
// Получаем активный документ  
  try {
    var myDoc = activeDocument;
  } catch (error) {
    exit();
  }
// Создаем массив для хранения отчета
  var myReport = [];
// Обрабатываем каждую страницу документа  
  for (var pcounter = 0; pcounter < myDoc.pages.length; pcounter++) {
    var myPage = myDoc.pages[pcounter];
// Обрабатываем каждый графический элемент на странице
    for (var counter = 0; counter < myPage.allGraphics.length; counter++) {
// Пробуем получить картинку и ее эффективное разрешение (у векторных нет такого, потому используем try)
      try {
        var myImage = myPage.allGraphics[counter];
        var myPPI = myImage.effectivePpi;
      } catch (error) {
        continue;
      }
// Проверяем оба значения разрешения (по x и y)
      if (myPPI[0] > iniMaxResolution || myPPI[1] > iniMaxResolution || myPPI[0] < iniMinResolution || myPPI[1] < iniMinResolution) {
// Получаем имя связанного файла
        var myFile = File(myImage.itemLink.filePath);
// Преобразуем значение эффективного разрешения в строку
        var myResolution = myImage.effectivePpi.join("x");
// Добавляем данные в отчет
        myReport.push("Страница " + myPage.name + ", файл: " + decodeURI(myFile.name) + ", разрешение: " + myResolution);
      }
    }
  }
// Объединяем отчет в строку  
  var myResult = (myReport.join("\n"));
// Задаем имя файла для сохранения
  var myFile = new File (activeScript.path + "imageReport.txt");
// Записываем результат в файл и выполняем его
  myFile.open("w");
  myFile.write(myResult);
  myFile.close;
  myFile.execute();  
}

Олег Бутрин
THINK.JS выпуск № 17 от 2007-02-26

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s