Прошли те времена, когда в Интернете на уровне элементарных понятий нужно было объяснять, что такое хостинг. Все уже давно знают, что свою страничку вовсе не нужно держать на домашнем компьютере и каким-то образом обеспечивать к ней постоянный доступ, а на порядок проще разместить ее на так называемом хостинге - на компьютере хостинг-провайдера, чьей головной болью и одновременно сферой приложения профессиональных услуг является обеспечение круглосуточного доступа через Интернет к вашей страничке любых желающих.
Что интересно, еще буквально пару-тройку лет назад под хостингом только это и понималось - размещение и обеспечение доступа. В большинстве случаев это так и выглядело - ваша страничка где-то там лежала, периодически откликаясь на попытки ее посмотреть, а нередко и не откликалась, причем когда кто-то из ваших знакомых интересовался, в чем там дело, вы только криво усмехались и отвечали что-то вроде: "Да опять у хостера какие-то проблемы".
Но время шло, и хостинг как интернетовская услуга претерпел значительные изменения. Во-первых, значительно возросла стабильность доступа - если раньше странички "валялись" не менее пары раз в день, то теперь недоступность странички из-за проблем у хостера - явный нонсенс. Во-вторых, значительно изменилось само "железо", на котором размещаются сайты - раньше серверы собирали черт знает из чего на неизвестно чьей коленке, а сейчас любой уважающий себя хостинг-провайдер использует специальные серверы, созданные именно для решения подобных задач.
В-третьих, понятие "техническая поддержка пользователей" из полуабстракции в виде студента на телефоне, который говорил исключительно на фидошном сленге и через минуту общения с клиентом тут же терял человеческое лицо, превратилась во вполне четкую структуру, которая занимается именно поддержкой пользователей, а не их посыланием во все места с их идиотскими вопросами.
В-четвертых, хостинг-провайдеры стали намного более требовательно относиться к вопросам защиты данных клиентов. Если раньше сохранность вашей страницы на сервере хостинга зависела только от вашей предусмотрительности (то есть - догадаетесь ли вы всегда держать актуальную копию сайта на домашнем компьютере), то теперь, независимо от того, что именно вдруг произошло на сервере хостера, вопрос сохранности вашей информации лежит целиком на нем.
Хостинг как интернетовская услуга претерпел значительные изменения
В-пятых, понятие хостинга стало включать в себя большой набор всевозможных дополнительных видов услуг - предоставление почтовых ящиков, баз данных, скриптов, статистики, защиты от спама и вирусов, листов рассылки и так далее.
И при всем этом богатстве услуг вполне серьезный хостинг стал стоить совсем небольших денег - $5, $10, $15 или $20, в зависимости от дисковой квоты и набора предоставляемых сервисов. Причем уровень стоимости похожих пакетов услуг у разных хостинг-провайдеров отличается весьма незначительно. Не бывает такого, чтобы у одного хостинг-провайдера, скажем так, оптимальный хостинговый пакет стоил $10, а у другого - $30. Разница обычно составляет буквально два-три доллара. Но вот как раз эти ничтожные пара долларов в месяц могут означать весьма существенные отличия в уровне и видах предоставляемых услуг.
Мне не раз приходилось слышать разговоры из серии: "Ну, и зачем ты в этой конторе хостишься, когда вон у тех - и оплата ниже на два бакса, и дискового пространства предоставляют больше, и список сервисов - две страницы?". Но потом, когда пользователь, соблазненный экономией двух долларов в месяц и списком сервисов на две страницы, переходил на нового хостинг-провайдера, вдруг выяснялось, что техподдержка там отвечает на звонки с 11 до 17, кроме выходных, причем как они отвечают - так лучше бы вообще не отвечали; что сайт имеет тенденцию вдруг падать и не подниматься, потому что вырубилось электричество, защиты у провайдера нет, так что все серверы полегли, а поднялись после появления электричества далеко не все, но никто и не почесался; что из заявленного длинного списка сервисов реально представлена дай бог половина, причем из них восемьдесят процентов - вещи, которые никогда не понадобятся, зато многое из того, что действительно нужно, работает через пень-колоду, и так далее. И становится не сильно понятно, зачем такие проблемы из-за каких-то двух долларов в месяц? Стоит оно того или нет?
Или наоборот. Бывает так, что вебмастер (или организация) сели к какому-то хостинг-провайдеру, мучаются с его ненавязчивым сервисом, а переходить в другое место - боятся, потому что, дескать, "от добра добра не ищут". От добра - точно, не ищут. Но в данном случае речь идет совсем не о добре, а о некачественном предоставлении услуг.
Понятие хостинга стало включать в себя большой набор всевозможных дополнительных видов услуг
Закончились времена доморощенных хостеров. Точнее, почти закончились, потому что где-то еще остались конторы, предоставляющие хостинг на кошмарном уровне девяностых годов прошлого столетия. Но они очень скоро отомрут, потому что не могут, не умеют и не хотят оказывать эту услугу так, как полагается на современном уровне, а сегодняшнего клиента уже не удовлетворяют фразы "не волнуйтесь, завтра починим" или "пока нет, но скоро будет". Ему нужно сейчас, в полном объеме и качественно.
Однако у неискушенных клиентов тут же возникает вопрос: как выбрать хостинг-провайдера, если они все предлагают примерно одинаковый набор предоставляемых услуг, цены на которые различаются совсем незначительно? Здесь, на мой взгляд, следует обращать внимание на две вещи. Во-первых, сайт провайдера и данные, которые на нем представлены. Если на сайте нет никакой информации о самой компании, используемом оборудовании, защите, сертификатах и так далее - это шарашкина контора. Список предоставляемых услуг - еще далеко не все. Клиенты должны знать, где расположено помещение с серверами, как оно охраняется, что предусмотрено в случае проблем с электричеством, и так далее.
Конечно, тут многое зависит от ваших личных требований к хостингу. Потому что если вам нужно разместить страничку с парой фотографий и текстом "Когда-нибудь здесь будет крутая страница", тогда, конечно, вас мало будет интересовать охрана дата-центра и защита электропитания. Но в этом случае вам и нормальный хостинг не нужен - достаточно просто разместить страничку на одном из бесплатных серверов. А вот в случае размещения серьезного проекта, корпоративного ресурса и так далее все эти вопросы обязательно нужно выяснить, потому что, например, неответ корпоративного ресурса в течение какого-то времени может обернуться серьезными финансовыми потерями.
Ну, и во-вторых, поинтересуйтесь впечатлениями тех людей, которые уже пользуются услугами каких-то хостинг-провайдеров. Пускай они расскажут, что им понравилось, а что нет, с какими проблемами им пришлось столкнуться. Это может быть весьма показательным.
И последнее. Если вам не нравится тот хостинг-провайдер, на котором в настоящий момент размещен ваш проект, - не останавливайтесь перед тем, чтобы подыскать более подходящую фирму. Перенести проект на новый хостинг, как правило, особого труда не составляет, а выигрыш от подобных действий может быть весьма значительным. Потому что на современном этапе хостинг должен отвечать очень высоким требованиям. И есть немало провайдеров, которые этим требованиям действительно отвечают.
Я очень часто встречаю вопрос типа "Как удалить определенную строку из файла?". Народ совсем не хочет шевелиться, ведь так легко зайти на любой крупный форум по PHP, и в сроке поиска написать что-то типа "Удаление строк из файла". Пятерка результатов гарантирована. Итак, в первой части статьи мы как раз рассмотрим способ удаления определенной строки из текстового файла.
Для начала было бы совсем не плохо создать текстовый файл. Назовём его file.txt, который будет состоять из строк, которые мы будем удалять:
Затем создаём что-нибудь типа file.php, занимающий около 11 строк!
Сначала определимся, что для удаления определенной строки нам нужен её номер. Его мы будем передавать с идентификатором id: file.php?id=2 (удалим строку под номером ТРИ, так как исчисления элементов в массиве ведётся с нуля, но позже мы это сгладим).
- функция file() считывает весь файл в массив (каждая строка - это его элемент);
- $id-вычитает один из нашего идентификатора, так что 2 становится 2, а 3 - 3;
- unset($file[$i]) удаляет или обнуляет элемент массива (но только из памяти, т. е. виртуально:);
- implode() объединяет массив в одну строку. Это очень важно, так как если бы это опустили, наш файл бы похудел до бесполезной записи Array
Как вы знаете, большинство скриптов, представленных в Web, ориентированы на работу с пользователем. Но для того, чтобы её начать, нужно, как правило, заполнить форму (в Интернете они встречаются повсеместно). Наивно полагать, что искушенный юзер с первого раза выдаст правильную, а главное корректную, информацию о себе. Конечно, правильность его имени и реальность земного адреса проверить мы не сможем, но вот то, как они введены, пожалуйста.
Представим, нам нужно создать программу, спрашивающую у посетителя его имя, e-mail. А также попросим придумать пароль и ввести по желанию комментарий. Если вы знакомы с HTML, то должны знать, что каждое поле в форме должно иметь имя. Итак, имена: name (Имя), mail (E-mail), password (Пароль), rpassword (Повторный пароль), comment (Комментарий). Для тех, кто ничего не понял, приведу исходный код нашей формы (кстати, его мы будем вставлять прямо в код PHP):
Фрагмент form.php
Непонятная с первого взгляда строка <input type = hidden name = seenform value = yes> поможет нам узнать, заполнялась ли форма данным пользователем или ещё нет. А вот значение $form = "…" объясняется тем, что мы собираемся интегрировать форму напрямую с PHP.
Теперь, когда готова основа, можем начинать её наполнение. Вспомним про поле с именем "seenform". Итак, вот зачем оно было нужно:
Если значение формы не равно ‘yes’, отобразить форму. В обратном случае работает код, следующий за словлм else. Форма заполнена, можно начинать проверку. Но для начала условимся, что
1. Кол-во символов в поле «Имя» и «E-mail» не больше, чем 40;
2. Кол-во символов в поле «Пароль» не меньше, чем 3;
3. Кол-во символов в поле «Комментарий» не больше, чем 450;
4. «Пароль» должен состоять только из латинских букв или цифр;
5. Все поля, кроме «Комментарий» должны быть заполнены!
Проверка на заполнение полей:
Переменная $er = 1 значит, что была ошибка. В конце проверки мы это учтём.
Перед работой через протокол POP3 сервер прослушивает порт 110. Когда клиент хочет использовать этот протокол, он должен создать TCP соединение с сервером. Когда соединение установлено, сервер отправляет приглашение. Затем клиент и POP3 сервер обмениваются информацией пока соединение не будет закрыто или прервано.
Команды POP3 состоят из ключевых слов, за некоторыми следует один или более аргументов. Все команды заканчиваются парой CRLF (в Visual Basic константа vbCrLf). Ключевые слова и аргументы состоят из печатаемых ASCII символов. Ключевое слово и аргументы разделены одиночным пробелом. Ключевое слово состоит от 3-х до 4-х символов, а аргумент может быть длиной до 40-ка символов.
Ответы в POP3 состоят из индикатора состояния и ключевого слова, за которым может следовать дополнительная информация. Ответ заканчивается парой CRLF. Существует только два индикатора состояния: "+OK" - положительный и "-ERR" - отрицательный.
Ответы на некоторые команды могут состоять из нескольких строк. В этих случаях каждая строка разделена парой CRLF, а конец ответа заканчивается ASCII символом 46 (".") и парой CRLF.
POP3 сессия состоит из нескольких режимов. Как только соединение с сервером было установлено и сервер отправил приглашение, то сессия переходит в режим AUTHORIZATION (Авторизация). В этом режиме клиент должен идентифицировать себя на сервере. После успешной идентификации сессия переходит в режим TRANSACTION (Передача). В этом режиме клиент запрашивает сервер выполнить определённые команды. Когда клиент отправляет команду QUIT, сессия переходит в режим UPDATE. В этом режиме POP3 сервер освобождает все занятые ресурсы и завершает работу. После этого TCP соединение закрывается.
У POP3 сервера может быть INACTIVITY AUTOLOGOUT таймер. Этот таймер должен быт, по крайней мере, с интервалом 10 минут. Это значит, что если клиент и сервер не взаимодействуют друг с другом, сервер автоматически прерывает соединение и при этом не переходит в режим UPDATE.
Авторизация в протоколе POP3
Как только будет установлено TCP соединение с POP3 сервером, он отправляет приглашение, заканчивающееся парой CRLF, например:
Теперь POP3 сессия находится в режиме AUTHORIZATION. Клиент должен идентифицировать себя на сервере, используя команды USER и PASS. Сначала надо отправить команду USER, после которой в качестве аргумента следует имя пользователя. Если сервер отвечает положительно, то теперь необходимо отправить команду PASS, за которой следует пароль. Если после отправки команды USER или PASS сервер отвечает негативно, то можно поробовать авторизироваться снова или выйти из сесси с помощью команды QUIT. После успешной авторизации сервер открывает и блокирует maildrop (почтовый ящик). В ответе на команду PASS сервер сообщает сколько сообщений находится в почтовом ящике и передаёт их общий размер. Теперь сессия находится в режиме TRANSACTION. Подведём итоги с командами:
Команда: USER [имя]
Аргументы: [имя] - строка, указывающая имя почтового ящика
Описание: Передаёт серверу имя пользователя.
Возможные ответы:
* +OK name is a valid mailbox
* -ERR never heard of mailbox name
Примеры:
C: USER MonstrVB
S: +OK MonstrVB is a real hoopy frood
...
C: USER MonstrVB
S: -ERR sorry, no mailbox for frated here
* +OK maildrop locked and ready
* -ERR invalid password
* -ERR unable to lock maildrop
Примеры:
C: USER MonstrVB
S: +OK MonstrVB is a real hoopy frood
C: PASS mymail
S: +OK MonstrVB's maildrop has 2 messages (320 octets)
...
C: USER MonstrVB
S: +OK MonstrVB is a real hoopy frood
C: PASS mymail
S: -ERR maildrop already locked
Команда: QUIT
Аргументы: нет
Описание: Сервер завершает POP3 сессию и переходит в режим UPDATE. Возможные ответы:
* +OK
Примеры:
C: QUIT
S: +OK dewey POP3 server signing off
Основные команды (Transaction) протоколе в POP3
После успешной идентификации пользователя на сервере POP3 сессия переходит в режим TRANSACTION, где пользователь может передавать ниже следующие команды. После каждой из таких команд следут ответ сервера. Вот доступные команды в этом режиме:
Команда: STAT
Аргументы: нет
Описание: В ответ на вызов команды сервер выдаёт положительный ответ "+OK", за которым следует количество сообщений в почтовом ящике и их общий размер в символах. Сообщения, которые помечены для удаления не учитываются в ответе сервера.
Возможные ответы:
* +OK n s
Примеры:
C: STAT
S: +OK 2 320
Команда: LIST [сообщение]
Аргументы: [сообщение] - номер сообщения (необязательный аргумент)
Описание: Если был передан аргумент, то сервер выдаёт информацию о указанном сообщении. Если аргумент не был передан, то сервер выдаёт информацию о всех сообщениях, находящихся в почтовом ящике. Сообщения, помеченные для удаления не перечисляются.
Возможные ответы:
* +OK scan listing follows
* -ERR no such message
Примеры:
C: LIST
S: +OK 2 messages (320 octets)
S: 1 120
S: 2 200
S: .
...
C: LIST 2
S: +OK 2 200
...
C: LIST 3
S: -ERR no such message, only 2 messages in maildrop
Команда:RETR [сообщение]
Аргументы: [сообщение] - номер сообщения
Описание: После положительного ответа сервер передаёт содержание сообщения.
Возможные ответы:
* +OK message follows
* -ERR no such message
Примеры:
C: RETR 1
S: +OK 120 octets
S:
S: .
Команда: DELE [ообщение]
Аргументы: [ообщение] - номер сообщения
Описание: POP3 сервер помечает указанное сообщение как удалённое, но не удалет его, пока сессия не перейдёт в редим UPDATE.
Возможные ответы:
* +OK message deleted
* -ERR no such message
Примеры:
C: DELE 1
S: +OK message 1 deleted
...
C: DELE 2
S: -ERR message 2 already deleted
Команда: NOOP
Аргументы: нет
Описание: POP3 сервер ничего не делает и вседа отвечает полжительно.
Возможные ответы:
* +OK
Примеры:
C: NOOP
S: +OK
Команда: RSET
Аргументы: нет
Описание: Если какие - то сообщения были помечены для удаления, то с них снимается эта метка.
Возможные ответы:
* +OK
Примеры:
C: RSET
S: +OK maildrop has 2 messages (320 octets)
Обновление
Когда клиент передаёт команду QUIT в режиме TRANSACTION, то сессия переходит в режим UPDATE. В этом режиме сервер удаляет все сообщения, помеченные для удаления. После этого TCP соединение закрывается.
Дополнительные POP3 команды
Следующие дополнительные команды дают вам большую свободу при работе с сообщениями: Команда: TOP [сообщение] [n] Аргументы: [сообщение] - номер сообщения [n] - положительное число (обязательный аргумент) Описание: Если ответ сервера положительный, то после него он передаёт заголовки сообщения и указанное кол - во строк из тела сообщения. Возможные ответы: +OK top of message follows -ERR no such message Примеры: C: TOP 1 10 S: +OK S: <здесь POP3 сервер передаёт заголовки первого сообщения и первые 10-ть строк из тела сообщения.> S: . ... C: TOP 100 3 S: -ERR no such message Команда: UIDL [сообщение] Аргументы: [сообщение] - номер сообщения (необязательный аргумент). Описание: Если был указан номер сообщения, то сервер выдаёт уникальный идентификатор для этого сообщения. Если аргумент не был передан, то идентификаторы перечисляются для всех сообщений, кроме помеченных для удаления.
Возможные ответы: +OK unique-id listing follows -ERR no such message
Примеры: C: UIDL S: +OK S: 1 whqtswO00WBw418f9t5JxYwZ S: 2 QhdPYR:00WBw1Ph7x7 S: . ... C: UIDL 2 S: +OK 2 QhdPYR:00WBw1Ph7x7 ... C: UIDL 3 S: -ERR no such message, only 2 messages in maildrop
Использование функции file_get_contents() наиболее предпочтительно в случае необходимости получить содержимое файла целиком, поскольку для улучшения производительности функция использует алгоритм 'memory mapping' (если поддерживается операционной системой).
file_get_contents
Функция доступна с PHP 4 >= 4.3.0
file_get_contents -- Получает содержимое файла в виде одной строки
Данная функция идентична функции file() с той только разницей, что содержимое файла возвращается в строке. Замечание: Эта функция безопасна для обработки данных в двоичной форме.
Подсказка: Для этой функции вы можете использовать URL в качестве имени файла, если была включена опция "fopen wrappers". Смотрите более подробную информацию об определении имени файла в описании функции fopen(), а также список поддерживаемых протоколов URL в Прил. J. Замечание: Поддержка контекста была добавлена в PHP 5.0.0.
Пример выборки html контента с помощью PHP и file_get_contents
include_once ("path") - функция включения дополнительного файла включаеться только один раз, те если есть необходимость включения файла в которомидет определение функций, класов или переменных и есть необходимость что бы они не переопределялись, то нужно использовать include_once().
include() - функция не проверяет был ли уже включен файл или нет, а подключает его снова. Т.е если в файле были инициализированны переменные, то они переопределяться.
require() - функция аналогичная include(), но если вызываемогофайла нет(например файла inc.php нет или мы укажем неверный путь) то require() остановит выполнение скрипта, а при include() выполнение продолжиться.
require_once() - функция аналогичная include_once(), но с замечаниями как и для recquire().
Вот вкратце все отличия этих функций, какими из них пользоваться - решать вам.
Итак, что нам понадобится. В первую очередь - Delphi 5-7 (у меня стоит 7-я версия, и весь код тестировался именно в этой версии). Это вызвано тем, что компонент TWebBrowser впервые "прописался" на вкладке Internet именно в 5-й версии (в 4-й его надо было устанавливать как компонент ActiveX).
Сначала нам надо перевести WebBrowser в режим редактирования. Для этого у каждого документа (согласно объектной модели это document) существует свойство DesignMode. Если установить его в 'On', то наша компонента автоматически переключается в режим редактирования, а если установить его в 'Off', то компонент вернется в режим просмотра.
Проверим это! Создадим новую форму, разместим на ней компоненту TWebBrowser и несколько компонент TSpeedButton. Затем напишем такой код:
Код:
Теперь по порядку о том, что мы написали. В событии OnCreate формы мы загружаем в браузер простую страницу (напомню, что протокол About позволяет загружать в браузер HTML строку). Это необходимо для того, чтобы в последующем мы могли обращаться к документу. Сразу после этого будет вызван обработчик события OnDocumentComplete. Но пока еще ничего не произошло. Внимательный читатель мог обратить внимание, что для перевода браузера в режим редактирования надо нажать кнопку 1. Editor - это экземпляр нашего документа (document). Его свойство DesignMode устанавливается в 'On'. Теперь наш редактор практически готов. Он уже умеет править текст, копировать/вырезать/вставлять текст и картинки, делать текст жирным/подчеркнутым/наклонным. Для этого есть соответствующие комбинации клавиш.
Ctrl + C Копировать
Ctrl + X Вырезать
Ctrl + V Вставить
Ctrl + B Жирный текст
Ctrl + I Наклонный текст
Ctrl + U Подчеркнутый текст
Ctrl + Z Отменить
Ctrl + Y Повторить
Ctrl + K Гиперссылка
Ctrl + F Найти
Ctrl + A Выделить всё
Ctrl + Left-Click Выделить блок
"Это, конечно, хорошо, что есть горячие клавиши, но мне не хотелось бы все их запоминать" - можете сказать вы. Хорошо. Тогда давайте разберем, как из Delphi заставить WebBrowser выполнять все эти действия. Для этого есть метод Command интерфейса IHTMLTxtRange (он описан в модуле MSHTML_TLB). Рассмотрим простой пример.
Код:
Сначала в этой процедуре создается объект Range. После этого вызывается метод Command:
Код:
cmdID – это строка идентификатор команды (в нашем примере 'bold' заставляет редактор переключаться между жирным и обычным начертанием текста); полный список команд смотри в приложении.
ShowUI – Show User Interface - показывать интерфейс пользователя (если таковой имеется, как правило это различные диалоговые окна). Если параметр равен False, то команда выполняется без предупреждения.
value – содержит дополнительную информацию в зависимости от команды.
Несколько слов об объекте Range. Помимо уже знакомого нам Command этот объект обладает еще рядом свойств и методов, некоторые из которых сейчас рассмотрим.
Text - Содержит текст выделения (без тегов HTML)
HTMLText - Полный текст выделения
Код:
procedure - Перемещает начальную позицию выделения на count символов вправо (если count<0, то влево), unit_-единицы измерения смещения (чаще всего используется 'character': 1 символ). При этом конечная позиция не смещается.
Код:
То же самое, только для конечной позиции выделения.
Код:
Вставляет HTML-строку
Код:
Отображает помощь по команде, указанной в cmdID
Пожалуй, на сегодня всё. Об остальных объектах (картинки, таблицы, элементы управления) поговорим в другой раз. Будут вопросы - пишите: [email=samum2000@mail15.com?subject=Question about visualhtml part1]samum2000@mail15.com[/email].
Приложение. Доступные команды:
BackColor - Устанавливает или получает цвет фона текущего выделения. Value должно содержать имя цвета или его шеснадцитиричный RGB эквивалент (например, #FFCC00).
Bold - Переключает начертание текста текущего выделения между полужирным и нормальным.
Copy - Копирует выделение в буфер обмена
CreateBookmark - Получает имя якоря или создает его для текущего выделения. Value - строка, содержащая имя якоря.
CreateLink - Получает URL ссылки или создает новую ссылку. Параметр Value должен содержать URL.
Cut - Вырезает текущее выделение в буфер обмена.
Delete - Очищает текущее выделение (удаляет всё его содержимое).
Find - Находит текст, заданный в параметре Value в текущем выделении.
FontName - Устанавливает шрифт для текущего выделения. Value содержит описание этого шрифта (как в теге FONT).
FontSize - Устанавливает размер шрифта. Value - число от 1 до 7 включительно.
ForeColor - Устанавливает цвет текста. Value должно содержать имя цвета или его шеснадцитиричный RGB эквивалент (например, #FFCC00)
FormatBlock - Устанавливает или получает форматирование текущего блока. Value может содержать теги-описатели.
Indent - Увеличивает отступ выделенного текста на одну единицу приращения
InsertButton - Перезаписывает идентификатор кнопки вместо текущего выделения. Value - строка, содержащая идентификатор кнопки.
InsertFieldset - То же для поля ввода.
InsertHorizontalRule - То же для горизонтальной полосы.
InsertIFrame - То же для встроеных фреймов (IFRAME).
InsertImage - То же для изображений.
InsertInputButton - То же для кнопки.
InsertInputCheckbox - То же для чекбоксов (checkBox).
InsertInputFileUpload - То же для элемента выбора файла.
InsertInputHidden - То же для скрытого поля (hidden)
InsertInputImage - То же для изображения.
InsertInputPassword - То же для поля ввода пароля.
InsertInputRadio - То же для радио-кнопок (Radio)
InsertInputReset - То же для кнопки reset.
InsertInputSubmit - То же для кнопки Submit.
InsertInputText - То же для поля ввода текста.
InsertParagraph - Вставляет новый раздел (абзац).
InsertOrderedList - Переключает стиль текущего выделения между списком и простым текстом.
InsertUnorderedList - То же самое.
InsertSelectDropdown - Записывает элемент Drop-down вместо текущего выделения. Value должно содержать идентификатор элемента.
InsertTextArea - То же для элемента TextArea.
Italic - Переключает начертание текста текущего выделения между наклонным и обычным.
JustifyCenter - Устанавливает выравнивание по центру для всего блока, в котором расположено текущее выделение.
JustifyLeft - Устанавливает выравнивание по левому краю для всего блока, в котором расположено текущее выделение.
JustifyRight - Устанавливает выравнивание по правому краю для всего блока, в котором расположено текущее выделение.
Outdent - Уменьшает отступ для всего блока, в котором расположено выделение, на одну единицу.
OverWrite - Переключается между режимами вставки текста и замены текста при вводе. Value: true - замена, false - вставка.
Paste - Вставляет текст из буфера обмена вместо текущего выделения.
Refresh - Обновляет текущий документ.
RemoveFormat - Удаляет из текущего фрагмента все теги форматирования
SelectAll - Выделяет все содержимое документа.
UnBookmark - Удаляет все закладки из текущего выделения.
Underline - Переключает начертание текста текущего выделения между подчеркнутым и обычным.
Unlink - Удаляет все гиперссылки из текущего выделенного фрагмента.
Unselect - Снимает выделение.
Убрать значки с "Рабочего стола" и создать ОЧЕНЬ быструю панель можно нажав на "трэе" (там, где часы) правую кнопку мыши. В меню выбрать "Панели инструментов" - поставить галочку "Рабочий стол" (если там такового нет - нажать "создать" и там выбрать "Рабочий стол"). При этом слева от трэя появится оная перемещаемая панелька со стрелкой, разворачивающей всё содержимое "Стола". После этого зайти в свойства экрана, вкладка "Эффекты" и там установить галку "Прятать содержимое стола, если...".
Всё! Вся фишка в том, что:
1. не захламляются ваши обои и
2. (самое главное!) через эту менюшку можно практически мгновенно добраться до ЛЮБОЙ точки вашего компа НЕ ЗАПУСКАЯ ПРИ ЭТОМ ВСЯКИХ "ПРОВОДНИКОВ", "КОММАНДЕРОВ" и т.д., (заодно и ресурсы экономятся!) Попробуйте, не пожалеете!
З.Ы. Для 98 Выньды. Для остальных - не знаю, есть ли там такое... ;)
Если вам надо постоянно обращаться к какому-то элементу Панели управления, то можно создать ярлык на "Рабочем столе" с такой командной строкой: "CONTROL.EXE desk.cpl,,3". Desk.cpl указывает вызываемую функцию "Панели управления". Например, appwiz.cpl откроет окно "Установка и удаления программ", а цифра следующая после двух запятых - номер нужной вкладки, начиная с нуля.
Отключение Error Reporting - навязчивого желания ХР постоянно отсылать сообщения разработчикам по случаю возникновения каждой ошибки (например, зависания того или иного приложения). Эти желания режутся на корню просто, но со вкусом:
В Контрольной Панели выбирается Система (System).
Закладка Advanced, далее - Error Reporting.
Включается опция Disable Error Reporting. Опцию But Notify me When critical errors occur (уведомлять меня о возникновении критических ошибок) я оставил, чтобы не пребывать в неведении по поводу неожиданных сбоев (пока бог миловал).
Для того, чтобы вставить любое слово рядом с часами нужно сделать следующее:
1. Зайти на "Панель управления", затем "Язык и стандарты"
2. Перейти на вкладку "Время"
3. В поле "Формат времени" измените формат на "ЧЧ:мм:сс оо" (оо набирать русскими), в полях обозначения времени до и после полудня введите ваше слово.
После установки Windows можно переместить системную папку "Мои документы" на рабочий диск, предназначенный для хранения всего содеянного пользователем (я обычно присваиваю ему метку тома Documents). Все необходимые изменения в реестре Windows сделает самостоятельно.
Вы пользуетесь пунктом контекстного (всплывающего) меню файла или папки "Отправить"? Если нет, то вы много теряете! Когда вы кликаете правой кнопкой на файле или папке выбираете пункт "Отправить" и там выбираете, куда хотите отправить, то выбранный вами файл копируется (перемещается) в ту папку, которую вы выбрали. Здорово, правда?
Так вот ярлычки для пунктов назначения (папок) хранятся в X:\%windir%\SendTo, т.е. если у вас Windows установлена на диске C, то путь к папке SendTo будет выглядеть так: C:\windows\SendTo. Очень удобно!
Так вот суть этого совета:
1) Вы создаёте ярлык для папки SendTo.
2) Извращаетесь над ним (меняете иконку, переименовываете).
3) Копируете этот ярлык в папку SendTo.
Теперь, когда вы много всего копируете(перемещаете) в определённую папку, то создаёте для неё ярлык и отправляете в Отправить! Очень удобно! Сам испытал!
По сути не совет, а прикол для тех кому понравился вариант использования функции "Послать".
Если вы работаете в Инете, то слово "Послать" у вас ассоциируется с отправкой письма, а если вы к тому же и гражданин бывшего СССР, то и ещё кое с чем 8). Берём, создаём ярлык ссылающийся на корзину и переименовываем его в "На...*". Потом переносим этот ярлык в папку ..windows/SendTo/
Пользуйтесь на здоровье.
---
Сноска * - зависит только от вашей фантазии :)
Примечание - большая часть написанного здесь текста с примерами взята по памяти (пару лет назад изучал достаточно подробно, поэтому может что-то в алгоритмах не работать - я ведь их не копировал откуда-то, а прямо тут же и писал, так что за синтаксические ошибки не пинайте) - на данный момент я активно OLE не пользуюсь (не из-за каких-то проблем с самим OLE, а из-за отсутствия надобности в его использовании в текущий момент).
Основные преимущества, благодаря которым OLE активно используется:
* Для вызывающей базы "по барабану" - какой тип вызываемой базы (DBF или SQL)
* Объектами вызываемой базы можно управлять всеми известными методами работы с объектами в 1С (т.е. со справочниками работают методы ВыбратьЭлементы(), ИспользоватьДату() и т.п., с документами - ВыбратьДокументы() и т.п.), соответственно, можно напрямую решить - стоит отрабатывать конкретные объекты базы OLE или пропустить их.
Пример 1. Присоединение к базе 1С через OLE.
БазаОле=СоздатьОбъект("V77.Application"); // Получаем доступ к OLE объекту 1С
Локальная версия (на одного пользователя): V77L.Application
Сетевая версия: V77.Application
Версия SQL: V77S.Application
Далее вместо термина "вызываемая база" будет написано просто "база OLE", а вместо термина "вызывающая база" - "местная база"
Теперь, мы должны знать несколько параметров для запуска базы OLE: Каталог базы, имя пользователя и пароль. Ну, наверное, еще и желание запустить 1С в монопольном режиме :)
Комментарий: функции СокрЛП() стоят в примере на случай, если пользователь захочет указанные выше переменные сделать в форме диалога, а проблема при этом состоит в том, что в алгоритм программа передаст полное значение реквизита (т.е. допишет в конце значения то количество пробелов, которое необходимо для получения полной длины строки (указана в свойствах реквизита диалога)).
Пример 2. Доступ к объектам базы OLE.
Запомните на будущее как непреложный факт:
1. Из местной базы в базу OLE (и, соответственно, наоборот) напрямую методом присвоения можно перенести только числовые значения, даты и строки ограниченной длины!!! Т.е. местная база поймет прекрасно без дополнительных алгоритмов преобразования полученного значения только указанные типы значений. Кроме того, под ограничением строк подразумевается проблемы с пониманием в местной базе реквизитов объектов базы OLE типа "Строка неограниченной длины". К этому же еще надо добавить и периодические реквизиты. Естественно, под методом присвоения подразумеваются и попытки сравнить объекты разных баз в одном условии (например, в алгоритмах "Если" или "Пока" и т.п.).
2. Есть проблемы при попытке перенести "пустую" дату - OLE может ее конвертировать, например, в 31.12.1899 года и т.п. Поэтому вам лучше заранее выяснить те значения, которые могут появится в местной базе при переносе "пустых" дат, чтобы предусмотреть условия преобразования их в местной базе.
A) Доступ к константам базы OLE:
Б) Доступ к справочникам и документам базы OLE (через функцию "CreateObject"):
После создания объекта справочника или документа к ним применимы все методы, касающиеся таких объектов в 1С:
Заметьте, что если вместо "Сообщить(Спр.Наименование)" вы укажете "Сообщить(Спр.ТекущийЭлемент())", то вместо строкового/числового представления этого элемента программа выдаст вам в окошке сообщение "OLE". Именно это я и имел в виду, когда говорил, что напрямую мало что можно перенести. Т.е. не будут работать следующие методы (ошибки 1С не будет, но и результат работы будет нулевой). Рассмотрим следующий пример:
Однако, сработает следующий метод:
Отсюда вывод: возможность доступа к объектам базы 1С через OLE требуется, в основном, только для определенной задачи - получить доступ к реквизитам определенного элемента справочника или документа. Однако, не забываем, что объекты базы OLE поддерживают все методы работы с ними, в т.ч. и "Новый()", т.е. приведем пример противоположный предыдущему:
В) Доступ к регистрам базы OLE (Не сложнее справочников и документов):
Г) Доступ к перечислениям базы OLE (аналогичен константе):
ЗначениеПеречисленияOLE = БазаОле.Перечисление.Булево.НеЗнаю; // :)
Заметьте, что пользы для местной базы от переменной "ЗначениеПеречисленияOLE" особо-то и нет, ведь подобно справочнику и документу перечисление также напрямую недоступно для местной базы. Пожалуй, пример работы с ними может быть следующим (в качестве параметра условия):
По аналогии со справочниками и документами работает объект "Периодический", план счетов работает по аналогии с ВидомСубконто, ну и далее в том же духе… Отдельную главу посвятим запросу, а сейчас… стоп. Еще пункт забыл!
Ж) Доступ к функциям и процедурам глобального модуля базы OLE!
Как же я про это забыл-то, а? Поскольку при запуске базы автоматически компилируется глобальный модуль, то нам становятся доступны функции и процедуры глобального модуля (поправлюсь - только те, у которых стоит признак "Экспорт"). Плюс к ним еще и различные системные функции 1С. А доступны они нам через функцию 1С OLE - EvalExpr(). Приведем примеры работы с базой OLE:
На самом деле, в последней строке примера я исхитрился и забежал немного вперед. Дело в том, что как и запрос (см. отдельную главу), так и EvalExpr() выполняются внутри базы OLE, причем команды передавается им обычной строкой, и поэтому надо долго думать, как передать необходимые ссылки на объекты базы OLE в строке текста местной базы. Так что, всегда есть возможность поломать голову над этим…
Алгоритмы преобразования объектов в "удобоваримый вид" между базами.
Ясно, что алгоритмы преобразования нужны не только для переноса объектов между и базами, но и для такой простой задачи, как попытки сравнить их между собой.
И еще раз обращу внимание: ОБЪЕКТЫ ОДНОЙ БАЗЫ ПРЕКРАСНО ПОНИМАЮТ ДРУГ ДРУГА, ПРОБЛЕМЫ ВОЗНИКАЮТ ТОЛЬКО ТОГДА, КОГДА ВЫ НАЧИНАЕТЕ СВЯЗЫВАТЬ МЕЖДУ СОБОЙ ОБЪЕКТЫ РАЗНЫХ БАЗ, т.е. команда
будет прекрасно работать без ошибок. Не забывайте это, чтобы не перемудрить с алгоритмами!
Итак, повторяюсь, что напрямую перенести, да и просто сравнить можно только даты (причем не "пустые"), числа и строки ограниченной длины. Итак, как же нам сравнить объекты разных баз (не числа, не даты, не строки), т.е. как их преобразовать в эту самую строку/число/дату.
А) Преобразование справочников/документов базы OLE (если есть аналогичные справочники/документы в местной базе). В принципе, преобразование их было уже рассмотрено в примерах выше и сводится к поиску их аналогов в местной базе. Могу еще раз привести пример, заодно с использованием регистров:
Б) Преобразование перечислений и видов субконто (подразумевается, что в обоих базах есть аналогичные перечисления и виды субконто). Вся задача сводится к получению строкового или числового представления перечисления или вида субконто.
Не поймите это как прямую команду воспользоваться функцией Строка() или Число() :)) Нет. Для этого у нас есть обращение к уникальному представлению перечисления и вида субконто - метод Идентификатор() или ЗначениеПоНомеру(). Второй вариант не очень подходит, так как зачастую в разных базах даже перечисления бывают расположены в другом порядке, а вот идентификаторы стараются держать одинаковыми в разных базах. Отсюда вывод, пользуйтесь методом Идентификатор(). Кстати, не путайте вид субконто с самим субконто! Привожу пример преобразования:
То же самое относится и к плану счетов - принцип у него тот же, что и у вида субконто…
В) Преобразование счетов:
Во многом объект "Счет" аналогичен объекту "Справочник". Отсюда и пляшем:
Работа с запросами и EvalExpr().
Наконец-то добрались и до запросов. Надо пояснить несколько вещей, касаемых запросов (да и EvalExpr() тоже). Самое главное - компиляция текста OLE-запроса (т.е. разбор всех переменных внутри запроса), как и сами OLE-запросы выполняются внутри базы OLE и поэтому ни одна переменная, ни один реквизит местной базы там недоступны, да и запрос даже не подозревает, что его запускают по OLE из другой базы!!! Поэтому, чтобы правильно составить текст, иногда требуется не только обдумать, как передать параметры запроса в базу OLE, но и обдумать, что нужно добавить в глобальный модуль той самой OLE-базы, чтобы как-то собрать для запросы переменные!
1. Поскольку сам текст запроса и функции EvalExpr() является по сути текстом, а не набором параметров, то напрямую передать ему ссылку на элемент справочника, документ, счет и т.п. нельзя. Исключение может быть составлено для конкретных значений перечислений, видов субконто, констант, планов счетов и т.п.
2. Хоть и многим и так понятно, что я скажу дальше, но я все-таки уточню: при описании переменных в тексте запроса не забывайте, что объекты базы надо указывать напрямую, без всяких префиксов типа "БазаОле".
3. Отрабатывать запрос сложно тем, что ошибки, например, при компиляции напрямую не увидеть. Поэтому начинаем пошагово готовится к отработке запроса в базе OLE.
Вначале допишем в глобальном модуле базы OLE немного строк, которые нам помогут в работе:
Теперь начинаем потихоньку писать сам запрос. Что мы имеем:
В форме диалога местной базы несколько реквизитов диалога (либо местные переменные):
* Даты периода (НачДата и КонДата)
* Элементы справочников для фильтрации (ВыбТовар, ВыбФирма, ВыбКлиент, и т.д.)
* Какие-либо флажки (ТолькоЗамерзающийЗимойТовар , ..)
Мы начинаем писать запрос и сразу попадаем в такую ловушку:
ТекстЗапроса = " Период с НачДата по КонДата; ";
Вроде все в порядке, но такой запрос не выполнится в базе OLE, так как там понятия не имеют, что такое НачДата и КонДата :)) Ведь эти переменные действительны только для местной базы! Переписываем запрос заново:
Казалось бы все очень просто. По аналогии - если уникальность для товаров ведется по наименованию, то простой заменой слова "код" на "наименование" мы решаем вопрос и здесь. Теперь рассмотрим, когда мы выбрали группу, т.е. текст условия должен будет выглядеть так:
И здесь, правда можно проблему решить "двумями путями" :)) Первый пусть - когда мы имеем дело с двухуровне вымсправочником. Тогда проблема группы решается также просто, как и в 1-м варианте:
А если справочник очень даже многоуровневый? Вот для этого мы и используем написанную ранее функцию. Предположим, что список значений запроса с индексом массива " 1 " мы будем использовать для хранения подобных значений (например, хранить в нем группы товаров, клиентов) для хитрых условий. Итак, например, в ВыбТовар у нас указана группа товаров, а в ВыбКлиент - группа клиентов, которым мы товары группы ВыбТовар продавали. Кроме того, мы должны пропустить накладные возвратов поставщикам, и не забыть, что товары надо еще отбирать по флажку ТолькоЗамерзающийЗимойТовар:
Ну, а с реквизитами запроса разбираемся так же, как указано было выше в предыдущих разделах… И не забываем, что кроме хранения конкретных значений, можно использовать другие списки значений запроса. Например, можно заполнить какой-либо список значений запроса списком клиентов и использовать его в запросе:
I. Вступление
II. Таблицы 1С и Excel.
III. Получение данных из Excel.
IV. Вывод данных в Excel.
V. Часто используемые методы для чтения/установки значений в Excel.
Вступление.
Многие знают, что Excel гораздо старше 1С. На мой взгляд, это очень успешный продукт, и нареканий о нем я не слышал. Excel прост и универсален. Он способен выполнять не только простые арифметические операции, но и сложные вычисления, построение графиков и т.п. Знаю примеры, когда организации до перехода на 1С вели часть бухгалтерии в Excel. Многие и сейчас параллельно используют две программы. В этой статье рассмотрим способы обмена данными между 1С и Excel.
Таблицы 1С и Excel.
Многие пользователи для удобства работы сохраняют таблицы 1С (печатные формы) в формате Excel (*.xls). После чего в полученном файле делают различные группировки, сортировки, вычисления и т.п. Связано это с тем, что в таблицах 1С нет такого огромного функционала как в таблицах Excel. Но в версии 1С 8.0 есть нововведения, делающих работу с таблицами более комфортной.
На сайте 1С (www.1C.ru) есть полезная программка, которая дает возможность открывать таблицы 1С в Excel и сохранять лист Excel как таблицу 1С. Это пригодится в том случае, если таблицу 1С не сохранили в формате Excel, а на том компьютере, где нужно открыть эту таблицу не установлена 1С. Да и постоянно помнить о том, что сохранить таблицу 1С нужно в формате Excel, не будет необходимости.
Полная информация о программе находится здесь.
Скачать программу можно здесь (архив zip 682 739 байт).
Замечание: В Excel разделителем дробной части считается символ ",". Поэтому перед сохранением таблицы 1С в формате Excel замените в ней другой разделитель (например ".") на ",". Иначе в Excel с этими числами не удастся произвести вычисления, или они вообще не будут отображаться как числа. Например, в таблице 1С "15.2" отобразится в Excel как "15.фев".
Получение данных из Excel.
Доступ из 1С к Excel производится посредством OLE. Например, код
позволит нам получить доступ через переменную "Эксель" к запущенному приложению Excel. А далее уже можно получить доступ к книге (файлу), листу и ячейке с данными. Далее примеры кода.
Открытие книги (файла):
ПутьКФайлу - полный путь к файлу книги Excel.
Выбор листа книги для работы с ним:
НомерЛиста - номер листа в книге, ИмяЛиста - имя листа в книге.
Получение значения ячейки листа:
НомерСтроки, НомерКолонки - номер строки и номер колонки, на пересечении которых находится ячейка.
Важно: не забывайте поле выполнения нужных действий добавлять код Эксель.Quit(); , иначе запущенный процесс останется незавершенным и будет занимать память и процессор компьютера.
Вывод данных в Excel.
Для вывода (выгрузки) данных в Excel необходимо либо открыть существующую книгу, либо создать новую, и выбрать рабочий лист для вывода данных. Открытие существующей книги описано выше, а для создания новой книги нужно использовать следующий код:
Так как при создании книги в Excel автоматически создаются листы (Сервис->Параметры->Общие->Листов в новой книге), то нужно лишь произвести выбор листа, с которым будет вестись работа:
либо добавить в книгу новый лист, если необходимо:
Следующим шагом будет установка значения ячейки:
НомерСтроки, НомерКолонки - номер строки и номер колонки, на пересечении которых находится ячейка.
И в конце нужно произвести запись созданной книги:
П
ПутьКФайлу - полный путь к файлу книги Excel (включая имя).
Важно: не забывайте, что в имени файлов не должно содержаться символов \ / : * ? " > < |.
Часто используемые методы для чтения/установки значений в Excel.
Эксель = СоздатьОбъект("Excel.Application");
Получение доступа к приложению Excel.
Мне приходится часто менять клиентов, потому что работаю удаленно. Сделал одному – иди к другому. А еще я продаю свои программы через Интернет. При имеющейся специфике работы, заметил одну странность: примерно в двадцати пяти процентов случаев, предприятие, оплатившее работу программиста и принявшее его работу, не пользуется ею.
Начну с примеров
Фирма, продающая компьютеры, купили внушительный комплект программного обеспечения, все своевременно оплатили, купили необходимое торговое оборудование... Мы, соответственно, все им установили и приготовились запускать. Остановились на этапе, когда сотрудники фирмы, ответственные за ввод в эксплуатацию нового программного комплекса, должны внести в информацию по имеющимся в отделах остаткам. Для справки – это примерно пара сотен наименований. Но на этом все работы по проекту остановились, потому что остатки не были внесены к намеченному сроку, ни через неделю после срока, ни через месяц. Не внесены они и до сих пор, хотя прошло уже пол года. Официально мы договорились, что клиент нам позвонит, когда сотрудники освободятся и найдут время внести остатки. Сами понимаете, на небольших фирмах менеджеры – по совместительству еще и продавцы, еще и грузчики, и кассиры…
Еще пример
Достаточно крупный комбинат решил автоматизировать учет обедов собственным сотрудникам в счет зарплаты. Систему подготовили, протестировали, поставили. Обучили их специалиста. Все как обычно. Недавно узнал, что конечный пользователь нашу систему не использует. Оказывается, по весьма банальной причине: на приобретение нового компьютера руководство не выделяет средств, а на имеющемся оказалось недостаточно мощности. В свое время мы указывали им на необходимость более мощного компьютера, но в силу не совсем понятных мне внутренних интриг, этот вопрос был замят на уровне IT-отдела. В результате, автоматизация стала не эффективной, и от использования новой программы решено было отказаться.
Третий пример
Производственная фирма заказала автоматизацию учета. От фирмы был назначен специалист – постановщик ТЗ и в будущем - внедренец. Работу сделали, сдали, провели обучение внедренца (на углубленное внедрение и обучение нами всех сотрудников не выделили бюджет). Я перезвонил клиенту через пол года, чтобы узнать, не было ли замечено каких-либо багов в работе системы. С удивлением услышал, что учет по-прежнему ведется в Excel-е, потому что на глубокое, самостоятельное освоение новой системы у сотрудников нет времени, а специалист, которого мы обучали, уволился…
Хотелось бы обобщить имеющийся, скромный опыт по таким случаям, и порассуждать на тему, когда автоматизация учета становится не эффективной по вине заказчика.
Уже из приведенных примеров можно сделать одно важное заключение: во всех трех случаях явно, что администрация не была заинтересована в результате. В первом – директор не захотел останавливать продажи даже не день, чтобы довести начатое до конца, во втором и третьем был урезан бюджет, и решили сэкономить там, где этого делать было нельзя.
1. Незаинтересованность руководства в результатах
Для меня всегда было загадкой, зачем руководство той или иной фирмы вообще тратится на автоматизацию, если отчетов в excel-е достаточно, и нет желания доводить начатое до конца? Чего дирекция хочет добиться? Дань моде? Надоел ноющий главбух? Решили, что что-то пора менять, но что менять – не выяснили? Стоит напомнить, что грамотно поставленная автоматизация учета в торгово-производственных фирмах способна увеличить прибыль и уменьшить затраты. Хорошая автоматизация окупается достаточно быстро, и уже скоро начинает приносить прибыль и экономию. Но если руководство не оценило перспектив автоматизации или, что еще хуже, считает, что новый стол из красного дерева топ-менеджеру важнее нового сервера сисадмину, то вряд ли на такой фирме автоматизация будет успешной.
2. Ограниченный бюджет
Как правило, из первого следует второе. Когда руководство не совсем отдает себе отчет в том, чего они ждут от автоматизации, тогда возникают идеи, наподобие: «а давайте пригласим студента, и он все сделает, как надо», или «давайте посадим главбуха на сервер»... Я, конечно, не против подработки студентов и не сомневаюсь в потенциале российского студенчества, но хочу лишь сказать о том, что для внедрения серьезной системы учета простого умения программировать очень мало. Хороший внедренец должен уметь просчитать возможные последствия выбора той или иной стратегии автоматизации. Это достаточно кропотливая работа, требующая, прежде всего, большого практического опыта, понимание не только специфики учета предприятия, но и его неочевидных нюансов. В конце концов, такая работа требует настойчивости, потому что часто решения внедренцев могут встретить сопротивление со стороны заказчика, и нужно уметь отстоять свои предложения, основываясь, опять же, на собственном опыте, защищая интересы сопротивляющегося клиента. Вряд ли какой-либо студент, понимающий, что занимается временным, не свойственным ему делом, способен на такое. Поэтому, считаю, что экономия на уровне исполнителя – это почти гарантия неудавшейся автоматизации.
Это же относится и к неоправданной экономии на оборудовании. Как правило, сбой системы происходит в самом слабом ее звене и в самый неподходящий момент… Помню, как у одного моего клиента, смотрящего «сквозь пальцы» на предложение обновить сервер, этот сервер вдруг однажды сгорел, когда бухгалтерия делала годовой отчет. Печально было то, что архивирование данных не велось должным образом, опять же, не смотря на рекомендации: директор считал покупку пишущего cd-room (в то время) – не особенно необходимыми затратами. Систему, конечно, восстановили. Но я помню, как бухгалтерии пришлось две недели работать чуть ли не по ночам, чтобы восстановить потерянные за год данные по первичным документам. Кстати, после этого случая руководство все-таки купило в то время жутко дорогой сервер с райд-массивом…
3. Тендер на откатах
Где-то встречал в сети примерную статистику, какой процент тендеров на IT услуги в России выигрывается за счет откатов ответственному лицу. Статистика – не утешительна. Печально, что на откаты попадают в основном крупные заказчики, где сумма договора внушительна, и руководство напрямую не занимается подбором исполнителя, а поручает это собственному специалисту, который не всегда бывает доволен уровнем своей заработной платы. Практика показывает, что при таком раскладе, все работы бывают выполнены в срок, все документы подписаны, но сотрудники фирмы остаются недовольны результатами и не могут использовать внедренную систему в планируемом объеме по разным причинам. Соответственно, руководство не имеет требуемой аналитической базы и начинает выяснять, в чем причина. Такие разбирательства затягиваются надолго, часто сопровождаются кадровыми движениями и, в конечном итоге, поисками того, кто бы систему довел до ума…
4. К вопросу о лидерах отрасли
Хотел бы привести еще один пример, достаточно типичный. Фирма готова тратить деньги на автоматизацию, но не сориентировалась на рынке IT-услуг и обратилась к кому-то очень известному. В результате затраты превысили все разумные пределы, а итог оказался не совсем ожидаемым, хотя, возможно, приемлемым с натяжкой.
К сожалению, это только при покупке автомобиля можно руководствоваться рекламными буклетами, и, если позволяют средства, выбирать самое последнее из модельного ряда. В сфере IT-услуг, как показывает практика, все далеко не так, особенно в сфере автоматизации на базе продуктов фирмы «1С» фирмами-франчайзи. Если исполнитель – не на уровне масштабов компании «Intel Corporation», то его раскрученность совсем может не соответствовать качеству предлагаемых им услуг, а объемы клиентской сети, требующей постоянного сопровождения, могут не позволить заниматься новым клиентом на должном уровне. На фоне этого, стоило бы вспомнить о небольших фирмах, менее раскрученных, а потому не выигравших тендер, которые были бы просто счастливы получить крупного заказчика IT-услуг, даже с меньшей суммой договора, и были готовы отдать все силы на то, чтобы клиент остался доволен. Амбиции небольших коллективов, уровень их специалистов и заинтересованность в результатах работы часто оказываются выше, чем у раскрученных, больших компаний. Небольшие фирмы не могут допустить в работе того, что позволят себе монополии, потому что любая неудача может грозить такой фирме банкротством.
Я назвал лишь четыре, пожалуй, основных фактора, когда автоматизация не достигает результатов, и присходит это, отчасти, по вине заказчика. Наверняка, имеются и другие причины, но корень проблем, на мой взгляд, следует искать, прежде всего, в неправильной позиции руководства компании, которая выражается или в непонимании, зачем нужна автоматизация, или в неправильно выбранной стратегии решения этого вопроса. Там, где решения принимаются трезво и взвешенно, где оценивается уровень специалиста, а не его раскрученность на рынке, где руководство четко понимает, чего оно ждет от автоматизации в итоге – там все будет нормально, чего всем и желаю…
В этой статье мы рассмотрим технику создания инифайлов их назначение и применение. Начнем с ответа на вопрос зачем же нужны эти инифайлы?! Предположим, что вы создали приложение, в котором пользователь может настраивать цвет фона, шрифт надписей и так далее. Когда он повторно включит вашу программу он очень сильно разочаруется, так как всего его старания по настройке интерфейса вашей программы пропали даром - программа будет иметь такой вид, который сделали вы при проектировании программы. Так вот чтобы эти настройки сохранять, лучше всего пользоваться инифайлами.
Одно из главных преимуществ инифайлов заключается в том, что эти файлы подерживают переменные разных типов (String, Integer, Boolean). В этих файлах очень удобно хранить различные настройки, например параметры шрифта, цвет фона, какие checkbox'ы выбрал пользователь и многое другое.
Теперь начнем разбираться с этими инифайлами. Для начала создайте новое приложение. Добавьте в секцию uses слово inifiles. Сохраните и откомпилируйте ваше приложение. Теперь сделаем, чтобы при каждом открытии программы форма имела такие размеры, какие установил пользователь последний раз. Для начала нам надо создать объект типа Inifile. Создается он методом Create(Filename:string); причем если в переменной Filename не указан путь к фалу, то он создаться в директории Windows, что не очень-то удобно. Поэтому мы создадим этот файл в директории нашей программы. Напишем это в обработчик события OnDestroy для формы:
Если файл с таким именем существует, то он откроется для чтения, а если нет - то он будет создан. Это очень удобно, так как не надо обрабатывать возможные исключительные ситуации, которые могут возникнуть при обращении к файлу.
Вот файл MyIni.ini после завершения работы программы (у вас естественно значения будут другими):
Теперь подробно разберемся как записывать информацию в инифайлы:
После того, как вы создали инифайл, в него можно записывать три вида переменных: Integer, String, Boolean, это осуществляется соответствующими процедурами: WriteInteger, WriteString, WriteBool. У всех этих процедур одинаковые параметры. В общем объявление этих процедур выглядит так:
Здесь Section -это имя секции, куда будут помещены параметры и значения. В файле имена секций заключены в квадратные скобки. Обычно в секции объединяют схожие параметры.
Ident - это название параметра, которому будет присваиваться какое-нибудь значение.
Value - это собственно значение, которое будет присвоено параметру. В файле оно стоит после знака равно.
Теперь напишем обработчик события OnCreate для формы, в котором будем считывать значения из файла и изменять размеры формы в соответствии с полученными значениями. Код должен иметь такой вид:
В этом коде все просто: открыли файл, прочитали из соответствующих секций необходимые параметры и присвоили их форме. Чтение значений из инифайла по сути ничем не отличается от записи в них. Указываете секцию, где хранится необходимый параметр, указываете параметр и читаете его значение. Как вы видите все просто!
Теперь я отвечу еще на один вопрос, который может появиться - почему не обычные текстовые файлы и не реестр? Отвечаю: из текстового файла очень сложно получить и обработать необходимую информацию. Многие рекомендуют для Win95/98/2000/Me, короче для всех 32-разрядных ОС использовать именно реестр, но лично я считаю, что инифайлы удобнее, так как при при переносе программы на другой компьютер, нужно перенести только один инифайл, а во-вторых, если вы что-нибудь в реестре случайно удалите, то может случиться каюк.
В данной статье рассмотрены принципы, помогающие компилятору Delphi генерировать более оптимальный с точки зрения скорости код. Если Вы не хотите вникать в подробности, в конце статьи есть «свод правил», которые рекомендуется соблюдать при написании программ.
Компилятор Delphi относится к разряду оптимизирующих. Но насколько качественно проводится оптимизация? Как «помочь» компилятору создать более быстрый код? Давайте разберемся с этим на экспериментах.
Оптимизация константных выражений
Пример 1:
С точки зрения оптимизации код можно упростить еще на этапе компиляции до
Но написанный выше листинг преобразуется в
С одной стороны компилятор не «сообразил», что значение переменной «a» можно преобразовать в константу и сложить с другой константой (которая, заметим, подставлена именно как константа) на этапе компиляции, с другой стороны был применен весьма хитрый трюк с LEA (об этом ниже). Тем не менее, код
в любом случае быстрее и короче.
Пример 2:
Скомпилированный код будет выглядеть
А ведь значение, присвоенной переменной «а» являлось константой и наш пример можно было бы переписать как:
Пример 3:
После компиляции получаем:
Т.е. компилятор преобразовал код так, как он был написан, а ведь можно было бы просто записать:
Оптимизация алгебраических выражений
Пример 4:
После компиляции эти переменные будут удалены, причем с предупреждением
Пример 5:
Код скомпилируется как есть! Таким образом мы обманули компилятор псевдо использованием переменных. Delphi не исправляет нашей «кривости», поэтому эта задача ложится исключительно на плечи программиста.
Пример 6:
Данный код можно оптимизировать до
И этого Delphi за нас не сделает.
Пример 7:
В данном примере первую строчку можно безболезненно удалить, что Delphi делать умеет.
Пример 8:
В данном случае можно избавится от одной операции умножения, присвоив значение выражения a*b временной переменной. Анализ ассемблерного листинга показывает, что компилятор именно так и поступает. Тем не менее, поменяв второе подвыражение на ((b*a)>0), компилятор принимает выражения за разные и генерирует умножение для обоих случаев, не смотря на то, что результат одинаков.
Оптимизация арифметических операций
Сложение и вычитание
Применение инструкции LEA вместо ADD позволяет производить сумму 3х операндов (двух переменных и одной константы) за один такт. Трюк заключается в том представление ближних указателей эквивалентно их фактическому значению, поэтому результат, возвращенный LEA равен сумме ее операндов. При возможности Delphi производит такую замену.
Деление
Операция деления требует гораздо больше тактов процессора, нежели умножение, поэтому замена деления на умножение может значительно ускорить работу. Существуют формулы, позволяющие выполнять такое преобразование. Тем не менее, Delphi не использует такую оптимизацию. Деление на степень двойки можно заменять сдвигом вправо на n бит, но даже в этом случае получаем следующий код:
Здесь учитывается особенность самой операции div – округление в большую сторону. Поэтому, если можно пренебрегать округлением, используйте c:=a shr 1 вместо с:=a div 2.
Умножение
Умножение на степень двойки можно заменять сдвигами битов. Delphi заменяет умножение сдвигами при умножении на 4,8,16 итд. При умножении на 2 производится суммированием переменной с собой.
Умножать на 3,5,6,7,8,10 и т. д. можно и без операции умножения – расписав выражение по формуле (a shl n)+a, где n – показатель степени двойки. Например, при умножении на 3 n=1. Delphi при возможности прибегает к этому трюку. Заметим, операнд LEA умеет умножать регистр на 2,4,8, что также при возможности используется компилятором. Например, умножение на 3 преобразуется в инструкцию
Оптимизация case of
Анализ скомпилированного кода показывает, что Delphi проводит утрамбовку дерева. Т.е. значения case сортируются и выбор нужного элемента производится при помощи двоичного поиска.
В случае, если элементы case of выстраиваются в арифметической прогрессии, компилятор формирует таблицу переходов. Т.е. создается массив указателей с индексами элементов, поэтому выбор нужно элемента выполняется за одну итерацию независимо от количества элементов.
Оптимизация циклов
Разворачивание циклов – не производится. Разворачивание циклов весьма спорный момент в оптимизации, поэтому принять грамотное решение может только человек. Delphi не производит разворачивания ни больших, ни маленьких циклов.
Слияние циклов – не производится. Если два цикла, следующие друг за другом имеют одинаковые границы итерационной переменной, разумно оба цикла объединить в один.
Вынесение инвариантного кода за пределы цикла – не выносится. Наиболее распространенный недочет – условие цикла записывается как:
Delphi будет при каждой итерации вызывать метод count, вычитать из результата 1 и потом уже сверять. Настоятельно рекомендуется переписывать подобный код как
Весь код VCL написан с нарушением этого правила. Очевидно, что проще подобного рода оптимизацию встроить в компилятор, нежели переписывать VCL :)
Замена циклов с предусловием на циклы с постусловием – производится. Циклы с постусловием имеют главное преимущество над другими видами циклов (с предусловием и с условием в середине) – они содержат всего одно ветвление. Delphi производит такую замену.
Замена инкремента на декремент – не производится. Более того, даже декрементный цикл компилируется в неоптимальный код, т.к. не используется флаг ZF. Вместо этого происходит сравнивание значения регистра с 0.
Удаление ветвлений – не производится.
Вывод:
1. Не используйте переменные для временного хранения констант или обязательно объявляйте «магические» числа как const, либо подставляйте в код непосредственные значения
2. Неиспользуемыми объявлениями и присвоениями можно безболезненно пренебрегать – Delphi умеет их вычищать.
3. Внимательно следите за использованием переменных, в частности лишним присвоениям их значений друг другу. Такого рода оптимизации Delphi делать не умеет.
4. Используйте свернутые математические выражения. (например, (3*a - a) /2 упрощается до a). Delphi не умеет упрощать математические выражения. (Да и что говорить, даже MathCAD не всегда грамотно умеет делать такие преобразования).
5. Не используйте конструкции типа a:=10*sin(45*pi/180); Delphi не вычислит эту константу на этапе компиляции, напротив, будет послушно вызывать sin и pi по ходу выполнения программы! В случае, если угол является переменной, по крайней мере pi можно заменить константой 3,1415...
6. Delphi прекрасно справляется с выражениями, полностью составленных из констант – они вычисляются на этапе компиляции.
7. Внимательно следите за условиями и их границами. Компилятор Delphi не умеет обнаруживать заведомо ложных условий. Также он не умеет удалять заведомо лишние условия. Например, (a>0) and (a<15616) and (a<>0)
8. Если в условии несколько раз проверяется одно и тоже выражение, следите, чтобы оно было выражено во всех конструкциях одинаково. В противном случае скомпилированный код будет не оптимален. Например, if ((a*b)>0) and ((a*b)<1024) then... При перестановке во втором случае b*a смысл выражения не изменится, но код будет иметь уже на одну операцию умножения, а две. Можно временно присвоить проверяемое выражение временной переменной, а затем уже проверять полученное значение.
9. Сообщение «Combining signed and unsigned types – widened both operands» сообщает не только о потенциальной ошибке – также вследствие преобразования мы теряем производительность. Например, z – объявлена как ineteger. условие if z>$abcd6123 then z:= $abcd6123; несмотря на его правильность вызовет данное предупреждение. Сгенерированный код будет, выполнять преобразования величин до 64-х бит, и дальнейшее уже сравнение 64-х битных операндов. Если изменить тип z на cardinal, мы избавимся от предупреждения и получим 3 строки кода, вместо 8 !
10. Delphi умеет оптимизировать сложение, умножение и частично деление. При делении на степень двойки, если не важно округление до большего, рекомендуется пользоваться shr 1 вместо div 2.
11. В case of при возможности используйте элементы, расположенные в арифметической прогрессии. Тем не менее, даже при невыполнении данного условия мы получим качественный код после утрамбовки дерева.
12. Выносите инвариантный код за тело цикла. Наиболее частая ошибка – for i:=1 to length(str) do... Дело в том, что при каждой итерации будет вызываться функция length, что пагубно скажется на производительности. Рекомендуется длину строки заранее присвоить переменной. Также не включайте в тело цикла код, заведомо не зависящий от изменения итерационной переменной.
Сравнивая Delphi с компиляторами Visual C++, WATCOM, Borland C++ (тестирование данных компиляторов приведено в [1]) приходим к выводу, что Delphi по своим оптимизирующим свойствам аналогичен Borland C++ (а кто сомневался? ;) ). Учитывая, что Borland C++ по итогам сравнения оказался последним, делаем несложный вывод. Весьма печален и тот факт, что большинство кода VCL написано с точки зрения «красоты» кода, а не его оптимальности с точки зрения скорости. Например, не соблюдается правило 12.
Создать гиперссылку в Delphi довольно просто. На простом примере разберемся с созданием ссылки в Delphi, а затем оформим все в виде компонента.
Алгоритм создания такой: ставим на форму метку (TLabel), приводим ее внешний вид к привычному нам виду гиперссылки в нашем браузере и пишем обработчик события OnClick.
А чтобы можно было постоянно использовать гиперссылку в программах, мы создадим компонент. Начнем с того, что поставим на форму нашего проекта метку (TLabel), пусть ее имя останется Label1. Теперь мы напишем обработчик события OnClick, для нее:
Теперь поясню что мы здесь написали. Функция ShellExecute предназначена для открытия или печати файла, как исполняемого, так и документа. Первый параметр - это handle родительского окна, второй параметр - строка, указывает, что надо сделать с файлом, третий параметр содержит имя открываемого файла, четвертый параметр указывает дополнительные параметры запуска исполняемого файла, пятый параметр определяет директорию по умолчанию, последний параметр определяет где будет отображен файл после октрытия.
Если Вы уже попробовали запустить приведенный код, то скорее всего у Вас ничего не вышло, потому что функция ShellExecute, находится в модуле ShellAPI, который конечно же надо добавить в секцию uses, кода нашего приложения.
Теперь разберем параметры относительно нашего случая:
handle - это дескриптор главной формы (аналогично Form1.handle)
open - тип действия с файлом. Нам надо его открыть.
http://delphiworld.narod.ru/ - имя файла, который надо открыть. У нас это может быть гиперссылка, содержащая абсолютный URI.
nil - здесь никаких дополнительных параметров открытия файла не должно быть, поэтому nil.
nil - директория по умолчанию нас так же не интересует.
SW_SHOW - активирует окно и отображает его с текущими размерами и положением. Об остальных режимах можно узнать в хелпе (о функции ShellExecute).
Второй и третий параметры функции являются нуль терминированными строками, т.е. строками типа PChar, поэтому для использования в функции имени файла, полученного из OpenDialog1, нужно использовать PChar(OpenDialog1.Filename).
В браузере (при настройках по умолчанию) ссылка меняет цвет в зависимости от своего состояния и действий пользователя, мы тоже сделаем так. Для этого создадим три константы (в них будут определяться цвета), которые надо поместить в раздел Implementation:
Теперь в обработчике события формы OnCreate нужно написать:
В обработчике события метки OnMouseDown мы напишем:
А в обработчике события OnMouseUp нашей метки напишем:
Для придания полной реалистичности нашей ссылке, нужно установить свойство метки Cursor в crHandPoint. При наведении на ссылку указатель будет иметь вид привычной нам кисти руки с вытянутым указательным пальцем и ссылка будет подчеркнутой.
Ну вот и разобрались, а теперь напишем компонент. Там все предельно просто и понятно, поэтому объяснения напишу только в виде комментариев в коде.
В качестве родительского класса (Ancestor Type) мы конечно же должны выбрать TLabel. Привожу полный код модуля компонента Link класса Tlink (текст модуля надо сохранить в файле Link.pas):
Вот мы и разобрались с созданием гиперссылок в Delphi, как оказалось все очень просто.
Часто работая в Фотошоп, приходится выполнять целый ряд постоянно повторяющихся операций. Такие операции выстраиваясь определенным образом, образуют цепочку команд - макропоследовательностей. Чтобы не повторять последовательность одних и тех же команд снова и снова, можно задействовать инструменты автоматизации. Одним из таких инструментов является Actions.
Автоматизация работы в Photoshop.
Часто работая в Фотошоп, приходится выполнять целый ряд постоянно повторяющихся операций. Такие операции выстраиваясь определенным образом, образуют цепочку команд - макропоследовательностей. Чтобы не повторять последовательность одних и тех же команд снова и снова, можно задействовать инструменты автоматизации. Одним из таких инструментов является Actions. Action - это записанный набор команд, которые можно быстро повторить. За такими макропоследовательностями также можно закреплять клавиатурные сокращения, то есть для их выполнения достаточно нажать клавишу или сочетание клавиш.
Для работы с Actions используется одноименная палитра. Чтобы увидеть эту палитру, следует выполнить команду Window>Actions или нажать клавишу F9.
Стандартные Actions
По умолчанию в Photoshop уже есть стандартный набор записанных команд, поэтому списки последовательно выполняющихся команд можно создавать самостоятельно, а можно воспользоваться уже готовыми. Например, используя стандартный макрос для создания виньетки (Vignette), достаточно выделить область на изображении и нажать кнопку его запуска.
Таким образом, все макропоследовательности состоят из команд, которые являются последними ступеньками в раскрывающемся списке.
Для удобства работы, макропоследовательности объединяются в наборы - Sets. Например, можно создать набор, в котором будут собраны макросы для работы с текстом, для создания различных текстур и т.д. По умолчанию в Photoshop есть набор Default Actions.
Палитра Actions содержит наборы различных последовательностей. Чтобы их увидеть, необходимо щелкнуть на треугольнике, расположенном слева от названия набора. После этого перед вами появится список действий, любое из которых может быть выполнено. Если вы хотите увидеть, из каких операций состоят действия, то следует щелкнуть на треугольнике, расположенном слева от них.
Внизу палитры расположены кнопки, позволяющие управлять действиями - создавать новые, запускать и останавливать запись и т.д.
Просмотрите все предлагаемые Actions на изображении с небольшим разрешением (на нем макрокоманды будут выполняться быстрее). После такого просмотра можно сформировать свою палитру, оставив понравившиеся элементы и удалив те, которые вам никогда не пригодятся. Можно также изменить названия, чтобы стало понятнее, где какая возможность скрывается.
Если какое-нибудь действие вам очень понравилось, то посмотрите, как оно было сделано. Для этого следует обратиться к палитре Actions и, раскрыв все списки, просмотреть последовательность выполняемых операций.
Лучше всего не только просмотреть, как выполнялись операции, но и попытаться добиться такого же эффекта, проделав самостоятельно все действия, особенно если вы неопытный пользователь. Это поможет лучше узнать программу, а также ознакомиться с возможностями, которые она предоставляет. Кроме того, в процессе работы можно будет изменить некоторые параметры, подобрав их для конкретного изображения.
Создание собственных макрокоманд
Можно не только пользоваться готовыми макрокомандами, но и создавать свои собственные.
Приведем пример ситуации, в которой они могу оказаться полезными. Предположим, вы хотите выложить фотографии в интернете. Прежде чем публиковать их в сети, нужно выполнить цветокоррекцию и уменьшить размер. Допустим, вы решили делать цветокоррекцию в режиме Lab Color.
Рассмотрим список действий, которые необходимо выполнить с каждым изображением:
1) Выполнить команду Image>Mode>Lab Color, чтобы перевести снимок в цветовое пространство Lab Color.
2) Повысить четкость изображения, для чего нужно перейти на палитру Channels, выделить канал Lightness и применить к нему фильтр Sharpen>Unsharp Mask. Благодаря тому, что фильтр применяется в канале освещенности, можно повысить резкость изображения, не затрагивая цветовую составляющую.
3) Улучшить цвета на изображении, для чего нужно выделить цветовой канал b, вызвать окно редактирования кривых, выполнив команду Image>Adjustments>Curves или же используя сочетание клавиш CTRL+M, и изменить форму кривой. Чем круче график кривой, тем более контрастным становится изображение в канале, и тем более насыщенными становятся цвета на снимке.
4) Выделить цветовой канал a и проделать те же действия с изменением формы кривой.
5) Наконец, нужно изменить размер изображения, используя команду Image>Image Size.
Если после этого отобразить палитру History, можно увидеть, что пришлось выполнить целый ряд команд и действий, чтобы обработать фотографию. Эти действия нужно было бы повторять с каждой следующей фотографией, которую вы хотите выложить в интернете.
Задачу можно существенно упростить, используя Actions. Вернемся к исходному изображению, используя палитру History, и создадим собственный макрос. Сначала создадим новую группу для хранения макросов. Для этого нужно нажать кнопку Create New Set в нижней части палитры Actions.
В окне New Set введим название набора команд. Создадим в новой группе первый макрос, нажав кнопку Create New Action. В появившемся окне New Action выберем название макроса и клавишу, при нажатии которой он будет запускаться, например, F11. Для вызова макропоследовательностей можно использовать клавиши F2-F12, а также их сочетания с клавишами CTRL и Shift.
Для начала записи необходимо нажать кнопку Record в нижней части палитры Actions. Теперь любая команда, выполненная в Photoshop, будет запоминаться до тех пор, пока вы не остановите запись макроса.
Скроем палитру Actions, чтобы она не мешала, и повторим выполненные ранее действия: переведем изображение в Lab Color, увеличим резкость, изменим цветопередачу и уменьшим размер изображения при помощи команды Image Size.
После этого вернемся на палитру Actions и остановим запись, нажав кнопку Stop Playing/Recording. В списке нашего макроса можно увидеть записанную последовательность команд. Также рядом с названием макроса отображается горячая клавиша, которая выбрана для его запуска.
Чтобы проверить действие макроса, вернемся к исходному изображению, используя палитру History, и нажмем горячую клавишу, которую вы выбрали для выполнения макроса. Можно убедиться, что все действия выполняются автоматически и довольно быстро. Макрос также можно запускать, нажимая кнопку Play Selecтion в нижней части палитры Actions, если предварительно выделить его в списке макрокоманд.
Записав макрос, посмотрите, как макрокоманда сработает на другой фотографии. Откройте изображение в Photoshop и снова запустите макрос горячей клавишей. Как вы можете убедиться, макрос работает.
Таким образом, благодаря макросам на подготовку фотографий для публикации в интернете может уходить гораздо меньше времени. Достаточно нажать горячую клавишу - и можно сохранять изображение.
Сохранение макрокоманд
В ряде случаев, например, при переустановке системы или при необходимости использовать созданные ранее макросы на другом компьютере, возникает необходимость сохранить Actions. Такая возможность предусмотрена в Photoshop.
Actions нельзя сохранять по отдельности, только в наборах. Поэтому для сохранения макропоследовательностей выделите на палитре Actions тот набор, в который они входят, после чего нажмите миниатюрную кнопку, расположенную в верхней правой части палитры (под кнопкой для сворачивания палитры) и выберите команду Save Actions. Если при этом будет выделен не набор, а отдельный макрос, эта команда будет неактивна.
Наборы макросов сохраняются в файлы с расширением ATN. Для загрузки сохраненного ранее набора в Photoshop необходимо щелкнуть по той же кнопке на палитре Actions и выбрать команду Load Actions.
Инструмент Batch
В Photoshop есть еще одно средство для автоматизации, которое удобно использовать вместе с Actions. Это - инструмент пакетной обработки Batch. С его помощью можно применить макропоследовательность к группе файлов, даже не открывая их в Photoshop.
Приведем простой пример использования этого инструмента. Предположим, необходимо перед публикацией фотографий в интернете защитить свое авторское право. Для этого можно добавить на фотографии какой-нибудь текст, например, адрес сайта.
Для начала запишем в макрос все действия, которые необходимо выполнить. Создадим новый Action и начнем запись. Макрос будет состоять из трех действий: добавление на изображение текста, сохранение изображения в формате JPEG и закрытие исходного файла. После выполнения этих операций остановим запись макроса.
Выполним команду File>Automate>Batch. В окне Batch необходимо установить настройки пакетной обработки файлов. В разделе Play выбирается группа, в которую сохранен макрос и его название.
В разделе Source необходимо указать путь к папке, содержащей исходные файлы. Если установить флажок Include All Subfolders, то будут обработаны и файлы, которые находятся во вложенных папках.
В разделе Destination устанавливаются параметры сохранения файлов. Если выбрать в этом списке вариант None, то файлы не будут сохраняться автоматически. Вместо этого Photoshop будет выдавать запрос на сохранение каждого файла. При выборе варианта Save and close файлы будут сохранены в ту же папку, где хранятся исходные изображения.
Для того чтобы файлы были автоматически сохранены, нужно выбрать в списке Destination вариант Save and close. При выборе варианта Folder появляется возможность указать папку для сохранения обработанных файлов. Кроме этого, можно переименовать их, используя маску. Название файла может включать исходное имя, представленное строчными или заглавными буквами, дату выполнения операции в разных форматах, порядковый номер, букву алфавита, расширение.
Флажок Override Action Save As Commands нужно использовать осторожно. Если он установлен, то файлы будут сохранены только в том случае, если операция сохранения является одним из шагов макроса.
Для запуска пакетной обработки необходимо закрыть окно Batch, нажав кнопку OK. После этого файлы будут один за другим открываться в Photoshop, к ним будут применяться заданные операции, после чего они будут закрываться и сохраняться.
Batch и Actions - это очень полезные инструменты Photoshop, которые могут сэкономить не один час времени. Кроме этого, Actions могут стать хорошим пособием для изучения программы - загрузите в Photoshop наборы макропоследовательностей, созданные опытными пользователями, и пошагово разберите, как они работают.
Разместил: Игорь
Всего 303 на 21 страницах по 15 на каждой странице