Templa mentis
Работа   Лирика   Склад   Заметки на полях   
На главнуюКарта сайтаОбратная связь







Самый лучший счетчик в РУнете
Работа /
Учим PHP работать с MS Word посредством JScript

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

Задача состояла в том, чтобы создать иллюстрированный печатный каталог плакатов с сайта plakaty.ru. Каталог должен был иметь нестандартное содержание, биографии художников, изображения плакатов с идентификационными номерами, названиями, годами публикации и в завершение — алфавитный указатель всего этого добра. Основной проблемой, мешавшей реализовать эту задачу стандартными методами была реализация «печатной» постраничности. Множество экспериментов с попытками сделать это все на уровне HTML, к сожалению, не увенчались успехом. Ну не умеет HTML работать с печатными документами. На мысль попробовать использовать Word через яваскрипт натолкнул Александр Кроч, за что ему отдельное «БОЛЬШОЕ СПАСИБО».

Как оказалось, Word очень прост и легок в использовании в плане взаимодействия с веб приложениями. И как ни странно имеет довольно простой программный интерфейс, API тобиш.

Итак приступим. Ниже представлена общая схема работы нашей монстрообразной конструкции.

Общая схема работы:

PHP взаимодействует с БД, в данном случае MySQL. Используя шаблоны содержащие в себе необходимые куски кода на JScript'е собирает сценарий, пкоторый в последствии запускается на клиентской машине, создает объект MS Word и выполняет все, что задумано. По сути PHP здесь используется в качестве построителя яваскрипта на базе данных из БД. Все нижеописанное будет работать и без него.

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

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

/*
Для начала, определим несколько констант, чтобы потом не путаться. Дело в том, что в редакторе макросов MS Word есть так называемый Quick Help который умеет показывать все параметры функций, так вот значения в нем обычно показываются в виде констант, частью которых являются описанные ниже. Можно было-бы определить больше, но острой необходимости в этом не было, да и цифру быстрее написать, чем длиннющую константу.
*/

wdSeekMainDocument = 0;
wdSeekCurrentPageHeader = 9;
wdSeekCurrentPageFooter = 10;
wdToggle = 999998;

// Создание объекта MS Word:
word = new ActiveXObject ("Word.Application");

// Создание документа и установка параметров страницы:
with (word) {
  Documents.Add (); // Создаем документ
// Альтернативой может служить
// Documents.Open ("d:\\ИмяФайла.doc"); // открытие существующего документа

// Selection я так понял основная рабочая область ворда, хотя в объектной модели MS черт ногу сломит.
  with (Selection) {
    ParagraphFormat.TabStops.Add (word.CentimetersToPoints (1.69), 0, 1); // Позиции табов
    PageSetup.LeftMargin = word.CentimetersToPoints (1.59); // Настройки страницы, левый отступ
    PageSetup.TopMargin = word.CentimetersToPoints (2.54); // Настройки страницы, правый отступ
  }

// Двигаемся
// В ворде предусмотрены передвижения по тексту, и каждая описанная ниже операция, будет применяться
// к текущей позиции курсора. Передвижения по тексту производятся программным нажатием кнопок клавиатуры.
Selection.EndKey (6); // жмем End, 6 — Ctrl+End конец документа.
Selection.HomeKey (5); // 5 — строка
// первый параметр юнит, 1-символ, второй параметр — количество, третий — выделять текст или нет
Selection.MoveRight (1, 3, 1);
Selection.MoveLeft (1, 3, 0);
Selection.MoveUp (1, 5);
Selection.MoveDown (1, 5);

// Добавляем нижний колонтитул:
  ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter; // переключаемся на колонтитул
  Selection.Fields.Add (Selection.Range, 33); // 33 — есть номер поля "текущая страница"
  Selection.ParagraphFormat.Alignment = 2; // По правому краю
  ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument; // возвращаемся в документ из области колонтитула

/*
Колонтитулы в ворде не поддаются логике, особенно если у вас несколько разделов и на каждый раздел необходим свой колонтитул, насколько мне удалось их понять, они почму-то строятся в обратном порядке.
Для того чтобы создать разрыв и новый раздел, а на нем колонтитул не наследуемый от предыдущего используется следующая конструкция:
Selection.InsertBreak (2); // Разрыв страницы, 2-новый раздел с текущей страницы

// Не забываем выставить параметры страницы для нового раздела
Selection.PageSetup.LeftMargin = CentimetersToPoints (1.59);
Selection.PageSetup.TopMargin = CentimetersToPoints (2.54);

// Переключаемся на верхний колонтитул
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader;
// Отключаем привязку. Дальше делаем с колонтитулом что хотим.
Selection.HeaderFooter.LinkToPrevious = false;

*/

// Устанавливаем параметры шрифта:
  Selection.Font.Name = 'Arial';
  Selection.Font.Size = '24';
  Selection.Font.Bold = wdToggle; // Переключаем жирность, можно использовать 0 и 1 для вкл/выкл
// У Selection.Font есть еще другие параметры которые описаны в QuickHelp

// Пишем текст:
  Selection.TypeText („Ворд, матерая хреновина!“);

// Жмем Enter (создаем параграф и переводим каретку):
  TypeParagraph ();

// Вставка файла в текст документа выглядит следующим образом
// В качестве источника можно использовать урлы как в этом примере
// Параметры идущие за именем источника я уже не помню, загляните в QuickHelp редактора макросов
  Selection.InsertFile („http://plakaty.ru/index.php“, "", 0, 0, 1);

/*
Учтите то, что при вставке HTMLя с картинками, эти самые картинки будут "подтягиваться"
из источника, Ворд не будет их сохранять в документе, как это обойти выяснить не удалось,
поэтому пришлось пойти на хитрость. Сразу в документ можно поставить метку, потом её найти
и заменить на так называемый InlineShape (внутреннюю картинку) которая сохранится вместе с документом.
Пример:

// Страшный объект поиска по документу
// имеющий кучу бесполезных параметров:)
with (Selection.Find) {
ClearFormatting (); // Очищаем параметры поиска
Text = "#P1#"; // Что ищем
Replacement.Text = ""; // На что заменяем
Forward = true; // В какую сторону ищем
Wrap = 1;
Format = false;
MatchCase = false; // Регистр
MatchWholeWord = false; // Целое слово
MatchWildcards = false;
MatchSoundsLike = false;
MatchAllWordForms = false;
Execute (); // ФАС!
}

// Таки нашли или нет?
if (Selection.Find.Found) {
  // Вставка внутренней картинки на место метки
  Selection.InlineShapes.AddPicture ("d:\\posters\\Картинка.jpg", false, true);
}

*/

// Создаем Оглавление
// Для того, чтобы оглавление у нас не было пустым,
// необходимо задать уровни нужным элементам оглавления
  Selection.Range.Paragraphs.OutlineLevel = 1; // цифра определяет уровень

// Вставляем автооглавление
  ActiveDocument.TablesOfContents.Add (Selection.Range, true, 3, 0);


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

*/

  with (ActiveDocument) {
    // Собственно файлик списка помечаемых слов
    ActiveDocument.Indexes.AutoMarkEntries ("d:\\concord.txt");

    // Добавляем алфавитный указатель
    Indexes.Add (Selection.Range, 0, 0, false, 1, 2, 0,1049);

    // Назначаем ему кучу всяких бесполезных параметров:)
    Indexes (1). HeadingSeparator = 2;
    Indexes (1). Type = 0;
    Indexes (1). RightAlignPageNumbers = true;
    Indexes (1). NumberOfColumns = 2;
    Indexes (1). TabLeader = 1;
  }

// Запись документа
  ActiveDocument.SaveAs ("d:\\MyDoc.doc");
  Quit (); // завершает работу MS Word
}

На этом в принципе и закончим, тема раскрыта, все остальное увлеченному человеку не составит труда изучить самостоятельно. Будут вопросы — пишите, постараюсь ответить.

P.S.
650 страниц каталога плакатов, сделанного по вышеописанной технологии лопатились на P4, 2.8GHz, 512 RAM около получаса, в принципе терпимо, если учесть общее количество непростых операций по сборке нестандартного содержания и вставки картинок. В результате получился нескромный файлик в 42Мегабайта.




Комментарии:
  1234 5 678910
Предыдущая страница Следующая страница
[21.06.2016 00:55] Lanette
That's a creative answer to a diilfcuft question
[21.06.2016 00:53] Hetty
Help, I've been informed and I can't become igornant.
[21.06.2016 00:52] Jady
Phmoeennal breakdown of the topic, you should write for me too!
[21.06.2016 00:50] Magda
Walking in the prsenece of giants here. Cool thinking all around!
[21.06.2016 00:47] Darence
Keep these aricelts coming as they've opened many new doors for me.
[21.06.2016 00:44] Patch
Shiver me timbers, them's some great inatomfrion.
[21.06.2016 00:44] Darvin
That's the smart thkining we could all benefit from.
[21.06.2016 00:42] Adelaide
This weitsbe makes things hella easy.
[21.06.2016 00:42] Melvina
Wow, that's a really clever way of thnkiing about it!
[21.06.2016 00:42] Lotta
Just cause it's simple doesn't mean it's not super heupfll.
[21.06.2016 00:41] Caro
Awesome you should think of sohmeting like that
[21.06.2016 00:38] Conyers
Learning a ton from these neat arilstec.
[21.06.2016 00:38] Jaylyn
There's a secret about your post. ICITTYBHTKY
[21.06.2016 00:38] Marlie
Noitnhg I could say would give you undue credit for this story.
[21.06.2016 00:38] Suevonne
This is a neat suryamm. Thanks for sharing!
  1234 5 678910
Предыдущая страница Следующая страница

Добавить

Ваше имя: 
 
Ваш e-mail: 
:-)  =)  :-(  ;-)  :-P  :'-(  :+)  :-/  :-}  :-{}  :*)  8-)  
:-D  :-@  :-X  :-|  :-!  :-O  ]:-]  @}=--  @=  (#)  }-|  I-)  


© 2002—2005 Sharky
Сделано в подполье студии «Вито»