Как автоматизировать Keynote через Javascript

Ирина Чернова avatar | 19
FavoriteLoading В закладки
Как автоматизировать Keynote через Javascript

Переходим на новый уровень взаимодействия с OS X.

Эта статья об автоматизации решения следующих задач:

  • Пакетный экспорт презентаций в PDF/HTML/Power Point;
  • Извлечение данных из презентаций;
  • Создание презентации из электронной таблицы;
  • Создание презентации из группы картинок;
  • Изменение оформления нескольких презентаций одновременно.

Есть два способа извлечь пользу из этого материала:

  • Скопировать готовый код, прочитать краткую инструкцию и пользоваться им;
  • Дочитать статью до конца, узнать как устроено приложение и изучить множество полезных приемов создания автоматизаций под Mac на JavaScript. Эти знания помогут переделать «под себя» код из статьи или создавать свои собственные скрипты.

Краткая инструкция

1. Берем Mac с операционной системой OS X Yosemite или OS X El Capitain;
2. Запускаем Keynote;
3. Открываем Программы -> Утилиты -> Редактор скриптов;
4. Копируем туда код c этой страницы:
start_with_code
5. Нажимаем на черный треугольник, чтобы выполнить его:
start_automation

Дальнейшие действия зависят от поставленной задачи.

Экспорт презентаций

Когда бывает нужно: если надо по-быстрому выложить несколько презентаций на сайт в виде html-страничек, послать их по почте приятелям с Windows (во избежании вопросов: «А это что еще за key-файлы?») или сохранить в PDF, чтобы смотреть в iBooks.

1. Выбираем пункт меню Экспортировать презентации и нажимаем ОК:
choose_export_keynote
2. Выбираем один или несколько файлов для экспорта:
choose_file_for_export
3. Выбираем один или несколько форматов экспорта:
choose_format
4. Если появилось такое окно, значит все готово (надо нажать ОК):
export_is_ready
5. Смотрим результаты экспорта на iCloud Drive в папке Keynote:

exported_files

Извлечение данных

Когда бывает нужно: когда какая-то какая то полезная информация в интернете существует только в виде презентации или когда коллега сделал презентацию в таком жутком виде, что ее надо полностью переделать, а текстовое содержимое сочинялось по ходу создания и переписывать его/копировать руками времени нет.

1. Выбираем пункт меню Экспортировать презентации и нажимаем ОК:
start_extract_data
2. Выбираем один или несколько файлов, из которых будем извлекать данные:
choose_presentation
3. Дожидаемся появления индикатора готовности:
export_is_ready
4. На iCloud Drive в папке TextEdit находим файл с данными:
extracted_data

Создание презентации из электронной таблицы

Когда бывает нужно: когда есть необходимость или желание сократить на треть время создании презентации.

Программы для создания презентации, включая Keynote, очень неудобны для ввода текста. Много времени тратиться впустую на переходы между слайдами и переключение активных зон. Чтобы ускорить процесс создания слайдов, можно набрать их содержимое в текстовом редакторе, скопировать в Numbers и скриптом сгенерировать презентацию.

1. Перед запуском скрипта следует создать электронную таблицу. В ячейки первого столбца поместить заголовки слайдов, а в ячейки второго основной текст:

numbers_for_keynote

Сохранить таблицу следует в папку Numbers на iCloud Drive.

2. Запускаем скрипт, выбираем пункт меню Создать презентацию из файла и нажимаем ОК:
create_from_file

3. Выбираем электронную таблицу с данными для создания презентации:
choose_numbers_for_keynote

4. Выбираем файл-шаблон для презентации:
choose_file_template

5. Указываем, сколько строк файла надо использовать для создания слайдов презентации:

numbers_of_rows

6. Указываем имя для сохранения новой презентации:

name_of_keynote

7. Дожидаемся появления индикатора готовности:
export_is_ready

8. Ищем новую презентацию на iCloud Drive и смотрим, что получилось:

from_file_result

Создание презентации из картинок

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

1. Запускаем скрипт, выбираем пункт меню Создать презентацию из картинок и нажимаем ОК:

from_file_result

2. Выбираем картинки:

select_images

3. Указываем имя новой презентации:
keynote_pictures_name

4. Дожидаемся появления индикатора готовности:
export_is_ready

5. Ищем результат на iCloud Drive:

images_keynote

Изменение оформления презентации

Когда бывает нужно: когда перед конференцией неожиданно обнаружилось, что у слайдов ко всем докладам мелкий шрифт.

1. Запускаем скрипт, выбираем пункт меню Изменить оформление презентации и нажимаем ОК:
edit_keynote_start

2. Выбираем одну или несколько презентаций для редактирования:

choose_presentation_for_editing

3. Выбираем часть презентации, которую будем редактировать:

choose_slide_part

4. Выбираем цвет текста:
choose_color_editing

5. Указываем размер шрифта:

ask_font_size

6. Указываем угол поворота текста:

insert_rotation

7. Дожидаемся появления индикатора готовности:
export_is_ready

8. Смотрим обработанный файл:

keynote_edit_is_ready

Кстати, отличная первоапрельская шутка: пока коллега вышла на чай, взять все ее презентации и перевернуть в них вверх дном текст заголовков.

А теперь перейдем к подробному разбору кода.

Меню с выбором функции

[jscript]
// Сокращаем обращение к приложению, чтобы дальнейший код было легче читать
Keynote = Application("Keynote");
// Включаем возможность использования UI-элементов
Keynote.includeStandardAdditions = true;
// Отображаем listbox с выбором действия
currentAction=Keynote.chooseFromList(["Экспортировать презентации","Извлечь данные из презентаций", "Создать презентацию из файла", "Создать презентацию из картинок","Изменить оформление презентаций"],{withPrompt:"Что надо сделать?"});
// В зависимости от выбранного действия запускаем нужную функцию
if(currentAction=="Экспортировать презентации")
{
exportKeynote();
}
if(currentAction=="Извлечь данные из презентаций")
{
extractKeynote();
}
if(currentAction=="Создать презентацию из файла")
{
createKeynote();
}
if(currentAction=="Создать презентацию из картинок")
{
createKeynoteFromImages()
}
if(currentAction=="Изменить оформление презентаций")
{
editKeynote()
}
[/jscript]

Начинается выполнение скрипта с выпадающего списка для выбора нужного действия, которые создается с помощью метода chooseFromList. Иногда, при использовании этого метода возникает такая ошибка:

user_interaction_error

Чтобы ее не возникало, необходимо перед запуском скрипта запускать Keynote, как это сказано в краткой инструкции.

Обратите внимание также на эту строчку:

[jscript]
Keynote.includeStandardAdditions = true;
[/jscript]

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

Экспорт презентаций

[jscript]
function exportKeynote()
{
// Отображаем панель Finder для выбора файлов с презентациями
pathKeynote=Keynote.chooseFile({withPrompt:"Какие презетации нужно конвертировать?", multipleSelectionsAllowed:true});
// Отображаем listbox с выбором форматов для экспорта
listFormats=new Array();
listFormats=Keynote.chooseFromList(["PDF","Microsoft PowerPoint","HTML"],{withPrompt:"В какие форматы нужно конвертировать?", multipleSelectionsAllowed:true});
// Объявляем служебный массив с расширениями, соответствующими каждому формату
var extensions=new Array();
extensions[‘PDF’]=".pdf";
extensions[‘HTML’]=".html";
extensions[‘Microsoft PowerPoint’]=".pptx";
// Открываем выбранные файлы с презентациями
var sourceKeynote =Keynote.open(pathKeynote);
// Перебираем все файлы
for(i=0;i<=sourceKeynote.length-1;i++)
{
// Текущий файл экспортируем во все выбранные форматы поочередно
for(j=0;j<=listFormats.length-1;j++)
{
sourceKeynote[i].export({to:"/Users/irina/Library/Mobile Documents/com~apple~Keynote/Documents/"+sourceKeynote[i].name().replace(".key","")+extensions[listFormats[j]],as:listFormats[j]});
}
// Закрываем текущий файл
sourceKeynote[i].close();
}
}
[/jscript]

Выбор презентации производится с помощью метода chooseFile. Мы указали параметр multipleSelectionsAllowed равный true и можем выбирать несколько файлов для обработки. Если бы мы его не указывали, то могли бы выбрать только один файл.

Для выбора целой папки для обработки следовало бы использовать метод chooseFolder.

В нашем скрипте используется только три формата для экспорта. Но еще существует возможность сохранить презентацию в виде видео, папки с картинками или файла с расширением .ppt (для неистребимых любителей MS Office 2003 и Windows XP).

Извлечение данных

[jscript]
function extractKeynote()
{
TextEdit = Application("TextEdit");
// Отображаем панель Finder для выбора презентаций, из которых будем извлекать данные
pathKeynote=Keynote.chooseFile({withPrompt:"Из каких презентаций нужно извлечь данные?", multipleSelectionsAllowed:true});
// Открываем выбранные файлы
var sourceKeynote = Keynote.open(pathKeynote);
// Перебираем файлы с презентациями
for(i=0;i<=sourceKeynote.length-1;i++)
{
// Создаем пустой текстовый файл
var extractData=TextEdit.Document().make();
content="";
// Перебираем слайды презентации
for (j=0;j<=sourceKeynote[i].slides().length-1;j++)
{
// Добавляем текст заголовка и тела слайда к переменной "content"
titleText=sourceKeynote[i].slides()[j].defaultTitleItem().objectText()
bodyText=sourceKeynote[i].slides()[j].defaultBodyItem().objectText();
var content = content +titleText+": "+bodyText+"\n";
}
// Вставляем заголовки и тексты всех слайдов в текстовый файл
extractData.text = content;
// Сохраняем текстовый файл с извлеченными данными (на iCloud!)
extractData.save({in:"/Users/irina/Library/Mobile Documents/com~apple~TextEdit/Documents/"+sourceKeynote[i].name().replace(".key","")+".txt"});
// Закрываем все файлы
extractData.close({saving:"no"});
sourceKeynote[i].close({saving:"no"});
}
}
[/jscript]

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

Создание презентации из таблицы

[jscript]
function createKeynote()
{
Numbers = Application("Numbers");
// Отображаем панели Finder для выбора файла с данными и шаблона для презентации
pathNumbers=Keynote.chooseFile({withPrompt:"Выберите файл с данными"});
pathKeynote=Keynote.chooseFile({withPrompt:"Выберите шаблон для презентации"});
// Создаем презентацию
var newKeynote = Keynote.open(pathKeynote);
// Открываем файл с данными
var sourceTable = Numbers.open(pathNumbers);
// Кладем в переменную таблицу из которой будем брать данные (самая верхняя таблица на первом листе)
var name = sourceTable.name();
var sheet = sourceTable.sheets[0];
var table = sheet.tables[0];
// Отображаем окно с вопросом о количестве используемых строк
countRows=Keynote.displayDialog("Из скольких строк с данными будем делать слайды?",{defaultAnswer:"5"}).textReturned;
// Перебираем первые пять строк
for (i=1;i<=countRows;i++)
{
// Создаем пустой слайд (на основе самого первого)
newKeynote.slides[0].duplicate();
// Кладем последний слайд в переменную
slide = newKeynote.slides[i];
// Значение из первого столбца пишем в заголовок слайда
slide.defaultTitleItem().objectText=table.cells["A"+i].value();
// Значение из второго столбца пишем в тело слайда
slide.defaultBodyItem().objectText=table.cells["B"+i].value();
}
// Спрашиваем у пользователя имя под которым будем сохранять презентацию
keynoteName=Keynote.displayDialog("Как назовем презентацию?",{defaultAnswer:"Презентация из таблицы"}).textReturned;
// Сохраняем готовую презентацию
newKeynote.save({in:"/Users/irina/Library/Mobile Documents/com~apple~Keynote/Documents/"+keynoteName+".key"},{as:"Keynote"});
// Закрываем презентацию и электронную таблицу
newKeynote.close({saving:"no"});
sourceTable.close({saving:"no"});
}
[/jscript]

В качестве источника данных мы могли бы использовать текстовый файл, документ Pages, письмо или веб-страницу.

Создание презентации из картинок

[jscript]
function createKeynoteFromImages()
{
// Отображаем панель Finder для выбора картинок
var pathImages=new Array();
pathImages=Keynote.chooseFile({withPrompt:"Выберите картинки для вставки в презентацию", multipleSelectionsAllowed:true});
// Создаем пустую презентацию
var newKeynote = Keynote.Document().make();
// Добавляем в презентацию слайды с выбранными картинками
newKeynote.makeImageSlides({files:pathImages});
// Спрашиваем у пользователя имя под которым сохраним презентацию
keynoteName=Keynote.displayDialog("Как назовем презентацию?",{defaultAnswer:"Презентация из картинок"}).textReturned;
// Сохраняем готовую презентацию
newKeynote.save({in:"/Users/irina/Library/Mobile Documents/com~apple~Keynote/Documents/"+keynoteName+".key"},{as:"Keynote"});
// Закрываем презентацию
newKeynote.close({saving:"no"});
}
[/jscript]

Редактирование презентаций

[jscript]
function editKeynote()
{
// Отображаем панель Finder с выбором презентаций для редактирования
pathKeynote=Keynote.chooseFile({withPrompt:"У каких презентаций нужно изменить оформление?", multipleSelectionsAllowed:true});
// Отображаем listbox с выбором части презентации, оформление которой будем менять
editPart=Keynote.chooseFromList(["Заголовок","Основной текст"],{withPrompt:"Какую часть слайда будем менять?"});
// Отображаем панель для выбора цвета текста
choosedColor=Keynote.chooseColor();
// Преобразуем полученный цвет в нужный формат
choosedColor[0]=Math.round(choosedColor[0]*65255);
choosedColor[1]=Math.round(choosedColor[1]*65255);
choosedColor[2]=Math.round(choosedColor[2]*65255);
// Спрашиваем у пользователя размер шрифта
fontSize=Keynote.displayDialog("Какого размера будем делать шрифт?",{defaultAnswer:"35"}).textReturned;
// И угол поворота надписи
textRotaion=Keynote.displayDialog("На какой угол повернем текст?",{defaultAnswer:"180"}).textReturned;
// Открываем выбранные файлы
var sourceKeynote = Keynote.open(pathKeynote);
// Перебираем их
for(i=0;i<=sourceKeynote.length-1;i++)
{ // Перебираем все слайды
for (j=0;j<=sourceKeynote[i].slides().length-1;j++)
{ // Кладем в переменную нужную часть для редактирования
if(editPart=="Заголовок")
{
editText = sourceKeynote[i].slides[j].defaultTitleItem();
}
if(editPart=="Основной текст")
{
editText = sourceKeynote[i].slides[j].defaultBodyItem();
}
// Красим текст нужным цветом
editText.objectText.color=choosedColor;
// Меняем размер
editText.objectText.size=fontSize;
// И угол поворота
editText.rotation=textRotaion;
}
}
}

[/jscript]

Если какое-то свойство текста вам редактировать не нужно, то просто закомментируйте участок кода, где оно изменяется.

Уведомление о завершении скрипта

[jscript]
// Отображаем текст с уведомлением для пользователя
Keynote.displayAlert(‘Подробнее об этом скрипте и найти другие полезные автоматизации можно на iPhones.ru’);
[/jscript]

Мы закончили разбирать код нашего примера. Немного дополнительной информации напоследок.

Автоматизируем показ презентаций

Вот набор команд, который поможет вам написать проограмму для реализации собственного алгоритма показа презентации. Подобный скрипт + несколько репетиций позволят отказаться от необходимости держать в руках пульт/смартфон во время доклада:

[jscript]
Keynote = Application("Keynote");
// Открываем файл для показа
var newKeynote = Keynote.open("/Users/irina/Library/Mobile Documents/com~apple~Keynote/Documents/example.key");
// Переходим на 6-ой слайд
newKeynote.slides[6].show();
// Ждем 20 секунд
delay(20);
// Идем на пятый слайд
newKeynote.slides[5].show();
// Ждем десять секунд
delay(10);
// Делаем так, чтобы пятый слайд больше не учавствовал в слайд-шоу
newKeynote.slides[5].skipped="true";
// Начинаем слайд-шоу с третьего слайда
newKeynote.start({from: doc.slides[3]});
// Включаем автоповтор
newKeynote.autoLoop = true;
[/jscript]

Закрытие приложений

Во всех вышеприведенных скриптах, Keynote остается открытым после выполнения всех команд. Но читателю следует знать, что выход из приложения тоже можно автоматизировать:

[jscript]
// Закрываем приложение без сохранения
Keynote.quit({saving:"no"});
// Закрываем приложение с вопросом о сохранении
Keynote.quit({saving:"ask"});
// Закрываем приложение с сохранением открытых файлов
Keynote.quit({saving:"yes"});
[/jscript]

На основе этих простых примеров можно создавать сложные автоматизации, которые принесут реальную пользу конкретно вам. Естественно, понадобится необходима дополнительная информация.

Справка по всем методам и классам, которые можно использовать в скриптах доступна из пункта меню Окно -> Библиотека:

javascript_library

Подробнее об основных принципах создания автоматизаций на JavaScript можно прочитать на сайте Applе в статье OS X 10.10 Release Notes.

P.S. В комментариях к моим прошлым статьям на тему автоматизаций для OS X некоторые читатели просили сделать статьи, посвященные AppleScript. Но вместо них будут статьи про JavaScript. Почему?

На этом языке можно делать все тоже самое, что и на Apple Script, но у создания автоматизаций для OS X на JavaScript есть ряд преимуществ:

  • JavaScript – это новшество, которое приходит на смену Apple Script (начиная с OS X Yosemite). Зачем нам тратить время на вчерашний день?
  • На AppleScript можно писать автоматизации только для OS X, а на JavaScript пользовательские скрипты для браузеров, макросы с использованием Java Script API для Microsoft Office, скрипты для LibreOffice и т.д. Не говоря уже о веб-разработке. Вкладываясь в изучение этого языка, вы открываете себе дверь в мир автоматизаций под самые разные платформы;
  • JavaScript, в отличие от Apple Script прекрасно умеет работать с регулярными выражениями! А в деле автоматизации рутины без них некуда!

По моему мнению, самое весомое преимущество Apple Script перед JavaScript — это огромная база готовых скриптов на этом языке, накопленная за десяток с лишним лет его активного применения пользователями OS X.

В обозримом будущем выпустим статью о самых полезных готовых скриптах на Apple Script. Но детально рассматривать применение этого языка не будем, чтобы не тратить зря время читателя. А учиться писать автоматизации будем на JavaScript.

P.S.S. Совсем недавно у нас вышло несколько статей про Automator:

Читателю следует знать, что автоматизации на JavaScript (Apple Script/Shell Script) отлично комбинируется с этим инструментом. Надо просто перетащить на основное поле действие Запустить JavaScript и вставить в него нужный код:

java_script_in_automator

1 Звезд2 Звезды3 Звезды4 Звезды5 Звезд (Проголосуйте первым за статью!)
undefined
iPhones.ru
Переходим на новый уровень взаимодействия с OS X. Эта статья об автоматизации решения следующих задач: Пакетный экспорт презентаций в PDF/HTML/Power Point; Извлечение данных из презентаций; Создание презентации из электронной таблицы; Создание презентации из группы картинок; Изменение оформления нескольких презентаций одновременно. Есть два способа извлечь пользу из этого материала: Скопировать готовый код, прочитать краткую инструкцию и...
Прокомментировать

🙈 Комментарии 19

  1. Мурад Газибеков avatar
    2

    ну и говнокод

    Ирина Чернова avatar
    Ирина Чернова6 марта 2016
    0

    @Мурад Газибеков, укажите на конкретные проблемы, пожалуйста)

    Мурад Газибеков avatar
    0

    @Ирина Чернова,
    >Меню с выбором функции:
    “запускаем функцию” лучше заменить на вызываем функцию, потому что их именно вызывают.
    Зачем 6 раз писать if, если JS предоставляет switch по строкам? Так и понятнее будет, что происходит и лучше выглядеть. После вызова функций нет ;

    >Экспорт презентаций:
    21 строчка просто колбаса, я не представляю, как её заменить потому что на JS не пишу, но подумать над этим стоит, так что вызываю JS программистов.
    Зачем писать цикл (i = 0; i <= data.length – 1; i++), если можно написать (i = 0; i Редактирование презентаций
    В преобразовании в полученный формат лучше использовать цикл от нуля до трех, чем писать три раза одно и то же.

    И много где напропущены точки с запятыми.

    Dexfir avatar
    Dexfir6 марта 2016
    2

    @Мурад Газибеков, если начинать править этот код, то нужно сам принцип алгоритма менять. весь подход. так что, уж лучше пусть останется так. работает – не трогай. :)

    Ирина Чернова avatar
    Ирина Чернова6 марта 2016
    0

    @Dexfir, а расскажите вкратце, пожалуйста, как бы Вы изменили подход?

    Innerspace avatar
    Innerspace6 марта 2016
    0

    @Ирина Чернова, ты ведь не думаешь, что можно в двух словах объяснить, как писать код? Если в кратце, то почитай SICP.

    Ирина Чернова avatar
    Ирина Чернова6 марта 2016
    0

    @Innerspace, я думаю что подход к решению конкретной задачи вполне можно объяснить в двух словах)

    Innerspace avatar
    Innerspace6 марта 2016
    0

    @Ирина Чернова, но все же не воспринимай серьезно советы вышеотписавшихся сенсеев – для домашних скриптов качество кода имеет второстепенное значение (пока не начнутся проблемы с их сопровождением, что вряд ли).

    Артём Баусов avatar
    Артём Баусов6 марта 2016
    0

    @Мурад Газибеков, относительно switch согласен, он к более божескому виду приведёт код, но алгоритм нужно весь переработать, если уж совсем откровенно. Проще оставить так, как есть)

    Innerspace avatar
    Innerspace6 марта 2016
    0

    @Артём Баусов, switch это зло императивное как бы. Уж если вы тут взялись оверинжинирить скрипты для домохозяек, соблюдайте все принципы SOLID (в т.ч. малоизвестные), учите логику Хоара, используйте иммутабельность и функции высшего порядка.

    Ирина Чернова avatar
    Ирина Чернова6 марта 2016
    0

    @Innerspace, :-D

    Ирина Чернова avatar
    Ирина Чернова6 марта 2016
    0

    @Мурад Газибеков, большое Вам спасибо)

    Innerspace avatar
    Innerspace6 марта 2016
    0

    @Мурад Газибеков,
    sourceKeynote.forEach(function(keynote)
    {
    listFormats.forEach(function(format)
    {
    var fileName = keynote.name().replace(“.key”,””);
    var extension = extensions[format];
    var exportTarget = targetFolder + fileName + ‘.’ + extension;
    keynote.export({to: exportTarget, as:format});
    });
    keynote.close();
    });

    Я тоже на JS не пишу, но это вроде очевидно.
    Ничего не проверял, но возможно этот код имеет светлое будущее, если его поправить.
    Более полное понимание проблемы (я ничего кроме JS не читал в статье xD) позволит еще больше приблизиться к очевидному коду – я просто заюзал синтаксический сахар и элементарные улучшения.

    Innerspace avatar
    Innerspace6 марта 2016
    0

    @Innerspace, потерял в начале строку:
    var targetFolder = “/Users/irina/Library/Mobile Documents/com~apple~Keynote/Documents/”;

  2. dennis1 avatar
    dennis16 марта 2016
    0

    Очень рад Вашему возвращению Ирина, а то читать не чего было…

  3. Artemitto avatar
    Artemitto6 марта 2016
    0

    Спасибо за статью

    Ирина Чернова avatar
    Ирина Чернова6 марта 2016
    0

    @Artemitto, :-)

  4. metalhead avatar
    metalhead6 марта 2016
    0

    отличная статья, уважили старика :)

  5. migmit avatar
    migmit6 марта 2016
    0

    Может, когда-нибудь я и дойду до того, чтобы делать слайды в Keynote. В следующей жизни, возможно. А то как-то Beamer проще.

Вы должны авторизоваться или зарегистрироваться для комментирования.

Нашли орфографическую ошибку в новости?

Выделите ее мышью и нажмите Ctrl+Enter.

Как установить аватар в комментариях?

Ответ вот здесь