А.Я. Архангельский: 100 компонентов общего назначения библиотеки Delphi 5. Эта книга — вторая в серии, посвященной Delphi — популярной среди разработчиков системе визуального объектно-ориентированного проектирования прикладных программ для Windows. Delphi — превосходный инструмент, с помощью которого и начинающий пользователь, и программист-профессионал могут создавать одинаково профессионально выглядящий интерфейс пользователя к прикладным программам самых различных классов.
В данной книге описаны компоненты библиотеки Delphi 5. Описание скомпоновано не по страницам библиотеки, а по назначению компонентов и по выполняемым ими функциям. Это позволяет параллельно рассматривать сходные компоненты, сравнивать их возможности и давать рекомендации по их применению.
Описаны также некоторые классы и типы Delphi 5, которые формально не являются компонентами, поскольку не включены в палитру библиотеки, но без которых изложение было бы неполным. Например, невозможно описывать компоненты отображения графической информации, не рассмотрев канву Canvas, перо Pen, кисть Brush. А такие объекты, как принтер Printer, приложение Application или экран Screen, фактически являются невизуальными компонентами и не включены в страницы библиотеки только потому, что в каждой прикладной программе они имеются всего в одном экземпляре.
К сожалению, в небольшой книге невозможно описать все компоненты библиотеки. Поэтому пришлось пойти на самоограничение — отказаться от описания компонентов, предназначенных для работы с базами данных и с Интернет. Применение этих компонентов связано со спецификой соответствующих прикладных программ, которая требует отдельного и детального рассмотрения. Эти компоненты будут описаны в будущих книгах серии «Все о Delphi».
Данная книга предназначена для пользователей различной квалификации – от начинающих до опытных специалистов. Начинающий найдет в ней простое изложение методики работы с различными компонентами. Специально для этой категории читателей введена небольшая первая глава и отдельные разделы второй главы, поясняющие общие принципы работы с Delphi 5. А опытному пользователю она также будет полезна как справочное пособие. Во-первых, он найдет в ней сведения по последней версии Delphi — Delphi 5, в которой появилось много нового. А во-вторых, жизнь показывает, что обычно даже опытный разработчик предпочитает работать с очень ограниченным набором когда-то освоенных им компонентов и не использует в полной мере всего богатства библиотеки Delphi.
Книга написана так, что ее отдельные главы и разделы можно читать в произвольном порядке. Вероятно, наиболее разумно сначала проглядеть ее всю, не вникая в детали, посмотреть краткие характеристики отдельных групп компонентов и иллюстрирующие их рисунки, возможно, построить некоторые описанные в книге тестовые приложения, чтобы воочию увидеть функционирование компонентов. А потом по мере работы с Delphi 5, когда возникают те или иные задачи и проблемы, обращаться к соответствующим главам и разделам как к справочному пособию за более детальной информацией.
От Автора:
У читателя, знакомого с моими большими (и, увы, дорогими) книгами по аналогичной тематике, например, с книгой «Программирование в Delphi 4», может возникнуть законный вопрос: «Как соотносится материал той книги и этой, не является ли данная книга просто фрагментом большой?». Смею заверить, что не является. Конечно, часть материала повторяется. Но, прежде всего, книга посвящена Delphi 5 и в нее введен соответствующий материал по этой новой версии Delphi. Да и по традиционным компонентам материал заметно расширен по сравнению с соответствующими разделами книги «Программирование в Delphi 4». В книгу добавлено описание ряда компонентов (компонентов ActiveX, фреймов, Application, ApplicationEvents), многие компоненты (например, списки) рассмотрены существенно более детально, введено много новых примеров. Так что данную книгу можно рассматривать как значительно расширенное и переработанное издание соответствующих разделов прежней книги.
Целью данной статьи является попытка на конкретных примерах показать некоторые из возможностей XML, ответить на ряд часто возникающих при знакомстве с новым языком вопросов. Что же такое XML? В чем заключаются его преимущества перед привычным уже нам языком HTML? Можно ли использовать XML на своих Web-страничках уже сегодня? А если можно, то как?
Познакомившись с STL, я был в восторге от ее возможностей.
Учился я именно по этой книге, и несмотря на то, что она 1999 года выпуска, до сих пор ни чего лучше по данной тематике я не нашел. Обязательно надо прочесть и использовать.
В данной статье приведены общие сведения об организации работы системы 1С:Предприятие с распределенной информационной базой (ИБ). Также описаны внутренние особенности организации механизма работы с распределенными данными для того, чтобы специалисты, осуществляющие конфигурирование и администрирование распределенных систем могли лучшее понимать выполняемые системой действия. Данная информация может также быть использована для оценки дополнительных затрат ресурсов системы, расходуемых на поддержание распределенной информационной базы.
Так как средства системы 1С:Предприятие для работы с распределенными информационными базами поставляются отдельно, сначала кратко остановимся на назначении и основных принципах организации работы системы 1С:Предприятие с территориально удаленными подразделениями.
Назначение и основные принципы
В тех случаях, когда предприятие представляет собой территориально распределенную структуру, зачастую сохраняется потребность в ведении единой системы учета. То есть необходимо иметь возможность работать в едином пространстве документов, получать отчеты, отражающие состояние дел как в территориально удаленных подразделениях предприятия, так и на предприятии в целом и т.п. При этом не всегда имеется возможность организовать работу всех подразделений с единой информационной базой в режиме он-лайн.
Для решения подобных задач предназначена компонента "Управление распределенными ИБ". С помощью указанной компоненты можно организовать двухуровневую структуру информационных баз (ИБ) системы 1С:Предприятие, состоящую из одной центральной и нескольких периферийных информационных баз, работающих с единой конфигурацией. При этом система будет стремиться поддерживать одинаковое состояние объектов данных во всех узлах распределенной ИБ.
Содержимое информационных баз синхронизируется путем переноса измененных объектов данных между каждой из периферийных и центральной ИБ. Для переноса данных используются так называемые файлы переноса данных. Перенос изменений выполняется только между центральной и периферийными ИБ. Перенос данных непосредственно между периферийными ИБ невозможен. Поэтому изменения данных, произведенные в одном из периферийных узлов распределенной ИБ попадают в другие периферийные узлы только через центральную ИБ.
В простейшем случае (по умолчанию) областью распространения изменений для всех объектов является вся распределенная ИБ. Таким образом, в случае если в течение какого-то времени изменения данных системы не будут производиться, и, в то же время, будут произведены все необходимые действия по обмену изменениями между узлами распределенной ИБ, то все узлы будут содержать абсолютно одинаковые данные.
В некоторых случаях может возникнуть необходимость в том, чтобы объекты того или иного типа никогда не попадали в те или иные узлы распределенной ИБ или никогда не покидали места своего создания. Для обеспечения такой возможности предназначен механизм настройки параметров миграции объектов. С его помощью можно ограничить распространение изменений объектов того или иного вида. Кроме того, в версии 7.7 системы 1С:Предприятие можно создавать периферийные ИБ, которые будут принимать информацию о измененных объектах из центральной ИБ, но не будут передавать изменения, сделанные в них самих.
Механизмы распространения изменений объектов работают полностью автоматически. Разработчик конфигурации лишен возможности вмешиваться в функционирование этих механизмов. Для того, чтобы механизмы распределенной ИБ начали работать, не нужно производить никаких специальных действий по конфигурированию системы.
Однако, для того, чтобы документы, элементы справочников и другие объекты, созданные в разных узлах распределенной ИБ, имели заведомо непересекающиеся пространства номеров, кодов и т. п., может потребоваться внести в конфигурацию некоторые изменения. Также изменения в конфигурации должны вноситься при необходимости обеспечить специальные ограничения работы пользователей на периферийных информационных базах.
Для переноса измененных объектов в распределенной ИБ и для первичного создания периферийной ИБ используется файл переноса данных. Он представляет собой упакованный (сжатый) файл, содержащий объекты информационной базы (все при создании периферийной ИБ или измененные при передаче изменений) в специальном формате. Формат данного файла не предназначен для использования его способами отличными от тех, которые предусмотрены механизмами выгрузки/загрузки и передачи изменений. Файл переноса фактически отражает содержимое объектов информационной базы в формате, не зависящем от формата базы данных. Это позволяет использовать в распределенной информационной системе в различных узлах различные форматы хранения данных, поддерживаемые системой 1С:Предприятие (DBF/CDX и MS SQL Server).
Регистрация изменений
Перенос измененных данных производится "пообъектно". То есть единицей переноса данных является так называемый ведущий объект. С точки зрения работы в распределенной информационной базе в 1С:Предприятии существуют следующие типы ведущих объектов:
константа,
элемент справочника,
документ,
календарь,
счет бухгалтерского учета,
типовая операция.
Вместе с документами переносятся все действия, выполняемые ими в процессе проведения: движения регистров, акты расчета, бухгалтерская операция, проводки. В случае, если при проведении документа производятся изменения периодических реквизитов элемента справочника, то производится перенос всего элемента справочника.
Регистрация изменений объектов производится автоматически при любом изменении объекта, независимо от того каким способом это изменение производилось (интерактивно или из встроенного языка). Кроме того в версии 7.7 системы 1С:Предприятие для таких объектов как элементы справочников и документы появилась возможность управления регистрацией изменений. Для этого у соответствующих объектов метаданных введен признак "Автоматическая регистрация изменений". Если этот признак установлен (значение по умолчанию), то автоматическая регистрация производится, а если признак сброшен, то регистрация не производится и изменения объектов в распределенной ИБ не распространяются. Но и в данном случае, при выполнении записи изменений объектов из встроенного языка можно управлять регистрацией изменений с помощью метода встроенного языка РегистрацияИзменений().
Регистрация изменений ведущих объектов производится в специальной служебной таблице. При этом фиксируются следующие данные об изменении объекта:
Сам ведущий объект;
Идентификатор той ИБ, в которую должно быть передано изменение;
Идентификатор ИБ, в которую должно быть передано изменение, служит для отслеживания переноса данных в каждую из ИБ, с которой данная ИБ обменивается данными. Таким образом, при изменении какого-либо объекта в центральной ИБ в таблицу будет помещено по одной записи для каждой из зарегистрированных периферийных информационных баз. Если же изменение объекта происходит в периферийной ИБ, то в таблицу будет занесена только одна запись, соответствующая центральной ИБ, так как каждая из периферийных ИБ непосредственно взаимодействует только с центральной.
Заметим, что удаление объекта является частным случаем изменения. Оно также помечается в таблице регистрации изменений и передается при выгрузке.
Выгрузка и загрузка изменений
Каждая выгрузка изменений осуществляется в адрес конкретной ИБ. В файл переноса, создаваемый при выгрузке попадают все объекты, записи об изменениях которых содержатся в таблице регистрации изменений для данной ИБ.
Заметим, что выгружаются не изменения объектов, а сами измененные объекты. То есть, если в документе изменилось значение одного реквизита, то будет передаваться весь документ и он будет полностью перезаписан на той ИБ, в которую переносится. Как уже отмечалось, вместе с документом будут перенесены и сделанные им движения регистров, операция и проводки. Если изменяется любой реквизит справочника, то передается полностью весь элемент. При этом история периодических реквизитов передается целиком. Последнее означает, что изменения сделанные в истории периодического реквизита элемента на в двух ИБ не будут сливаться вместе.
В процессе выгрузки в таблице регистрации изменений отмечается выгрузка изменений объектов.
При загрузке файла переноса данных помимо загрузки измененных данных выполняется так называемый прием подтверждений.
В случае, когда пришло подтверждение на получение выгрузки, содержащей последнее изменение объекта, запись об изменении удаляется из таблицы регистрации. То есть записи об изменении объектов данных хранятся в таблице регистрации до тех пор, пока не будет получено подтверждение о доставке измененного объекта по назначению.
Причем выгрузка измененного объекта будет производиться до тех пор, пока не будет получено подтверждение, о доставке изменения. Это значит, что если выполнять перенос все время в одном направлении и не выполнять обратного переноса то объем файла переноса данных будет все время расти, так как каждый раз будут передаваться все объекты, измененные после последнего полученного подтверждения.
При загрузке изменений объектов из периферийной ИБ в центральную, в таблицу регистрации изменений (если, конечно, параметры миграции настроены соответствующим образом) заносятся записи, указывающие, что загруженные из периферийной ИБ изменения объектов должны быть переданы в другие периферийные ИБ.
Изменения конфигурации
Как уже отмечалось, при работе с распределенной ИБ, конфигурация системы может быть изменена только в центральном узле.
Для регистрации изменений конфигурации и передачи ее на периферийные ИБ используется тот же механизм, что и для объектов данных. При записи измененной конфигурации, в таблицу регистрации изменений объектов по числу известных периферийных ИБ заносятся записи, фиксирующие факт изменения конфигурации.
После записи измененной конфигурации в распределенной ИБ складывается такая ситуация, что центральная и периферийные ИБ работают фактически с разными конфигурациями. В таком состоянии созданные на периферийной ИБ файлы переноса данных не могут быть загружены на центральной ИБ по той причине, что в условиях различных конфигураций содержащаяся в файле информация не может быть правильно интерпретирована. Обмен будет восстановлен только после того, как в периферийную ИБ будет загружена измененная конфигурация с центральной ИБ. То есть после изменения конфигурации требуется выполнить перенос из центральной ИБ в каждую из периферийных, а уже затем выполнять перенос из периферийных ИБ в центр.
Перенос измененной конфигурации в периферийные ИБ осуществляется тем же способом, что и перенос измененных объектов данных. В процессе очередной выгрузки из центральной ИБ, в файл переноса данных целиком включается измененная конфигурация, если, конечно, в таблице регистрации изменений содержится запись о том, что измененную конфигурацию следует передать в соответствующую периферийную ИБ. Выгрузка конфигурации также будет производиться до получения извещения о приеме измененной конфигурации.
Заметим, что конфигурация считается измененной при любых изменениях метаданных, форм, модулей, таблиц конфигурации, наборов прав, пользовательских интерфейсов, описаний. В состав конфигурации не входит список пользователей, а также внешние по отношению к файлу конфигурации (1CV7.MD) файлы (внешние отчеты, отдельно записанные таблицы и тексты). И эти внешние файлы не переносятся механизмом управления распределенной ИБ. Поэтому при конфигурировании распределенной системы не рекомендуется использовать в конфигурации находящиеся в отдельных файлах модули, таблицы и отчеты.
Для изменения уже работающей конфигурации можно рекомендовать использовать механизм загрузки измененной конфигурации. Он позволяет специалисту скопировать конфигурацию, выполнить в ней все необходимые изменения, отладить внесенные изменения (этот процесс может занять и несколько дней), а затем загрузить измененную конфигурацию в центральную ИБ, после чего изменения будут распространены на все периферийные ИБ с очередной передачей изменений. Такая последовательность позволит избежать многократной передачи измененной конфигурации в периферийные ИБ в процессе ее модернизации.
При загрузке файла переноса данных на периферийной ИБ, этап загрузки измененной конфигурации (если, конечно, она содержится в файле переноса данных) предшествует этапу загрузки измененных объектов данных. В случае неудачного завершения загрузки конфигурации, загрузка объектов данных производиться не будет и информационная база останется в том же состоянии, что и была до начала загрузки.
Загрузка измененной конфигурации может завершиться неудачей, если измененная конфигурация не соответствует существующим данным. Например, было уменьшено число уровней справочника, а новое число уровней оказывается меньшим, чем фактически содержащееся в справочнике или в других подобных случаях. Если такое произошло, то следует привести данные в соответствие с новой конфигурацией или изменить конфигурацию в центральной ИБ и заново произвести выгрузку, чтобы ликвидировать возникшее противоречие.
Коллизии
При работе в реальных распределенных ИБ один и тот же объект может изменяться одновременно в различных узлах распределенной ИБ. И при переносе измененных объектов из одной ИБ в другую может случиться так, что в какую-либо ИБ будет загружаться объект, зарегистрированный в самой этой ИБ как измененный. Такая ситуация носит название коллизии. Приведем описание действий системы в наиболее типовых вариантах коллизий.
Один и тот же объект изменен более чем в одной ИБ.
Общий принцип здесь состоит в том, что "главным" считается изменение, произведенное в центральной ИБ. Отработка ситуации различается в зависимости от того, на какой ИБ - центральной или периферийной коллизия обнаружена. Если коллизия обнаружена на центральной ИБ, то есть при загрузке файла переноса из периферийной ИБ обнаружено, что один из измененных объектов также изменен и в центральной ИБ, то изменения объекта в центральную ИБ не загружаются. При этом гарантируется, что при очередной выгрузке в адрес периферийной ИБ будет передано состояние объекта как оно есть в центральной ИБ. Если же коллизия обнаружена на периферийной ИБ, то изменения объекта, прибывшие из центральной ИБ загружаются.
Объект, измененный в одной ИБ, удален в другой.
В данном случае принцип заключается в том, что изменение всегда "главнее" удаления. В случае, если на центральную ИБ прибывает файл переноса, в котором содержится информация, что некоторый объект удален на периферийной ИБ, то в центральной ИБ объект не удаляется, а в записи таблицы регистрации изменений данный объект помечается как измененный. То есть при очередном обмене объект будет восстановлен в той ИБ, в которой он был удален, причем само содержание объекта будет соответствовать той ИБ, которая "отвергла" удаление.
Аналогичные действия производятся, если коллизия обнаружена на периферийной ИБ.
Объект, удаленный в одной ИБ, не может быть удален в другой по причине наличия ссылок на него.
При загрузке изменений, если загружается информация об удалении объектов, автоматически включается механизм контроля ссылочной целостности и выполняется проверка наличия ссылок в данной ИБ на объекты, которые переданы как удаленные.
В случае обнаружения коллизии такого рода, вне зависимости от того на какой из ИБ она была обнаружена, выполняется следующее: удаление не выполняется, а в таблицу регистрации изменений заносится запись о том, что объект должен быть перенесен в адрес той ИБ, из которой была прислана информация о его удалении.
При очередном обмене объект восстанавливается в той ИБ, в которой он был удален, однако само содержание объекта будет соответствовать той ИБ, которая "отвергла" удаление.
Таким образом, управление распределенной информационной базой имеет определенную стратегию автоматического разрешения любых коллизий с описанными приоритетами. Однако, в реальных условиях рекомендуется средствами конфигурации определить возможные действия пользователей на различных узлах таким образом, чтобы исключить или минимизировать вероятность возникновения коллизий. Основным путем является определения средствами конфигурации "ответственного" узла за каждый ведущий объект в распределенной ИБ и ограничение всем остальным возможности его редактирования и удаления. Определение "ответственных" должно происходить исходя из логики работы предприятия. Очевидно, что многие виды объектов можно разрешить изменять только в центральной ИБ (например, список складов). Для многих объектов можно рекомендовать средствами встроенного языка установить возможность изменения только на той ИБ, на которой они созданы, например для документов.
Параметры миграции
С помощью настройки параметров миграции можно ограничивать области распространения изменений объектов. Настройка параметров миграции происходит по видам "ведущих" объектов. То есть для каждого вида "ведущих" объектов можно определить конкретную настройку параметров миграции. В настройке параметров миграции объектов ведущую роль играет выбор того или иного варианта области распространения изменений объектов данного вида. Существуют три варианта настройки области распространения:
Все информационные базы. Данный вариант настройки используется по умолчанию для всех объектов. В этом случае любые изменения объектов данного типа будут распространяться по всем узлам распределенной ИБ. Этот вариант обеспечивает полную синхронизацию объектов данного вида во всей распределенной ИБ. Очевидно, что этот вариант наиболее прост для конфигурирования.
Место создания. Данный вариант настройки также является довольно простым. В этом случае изменения объекта не передаются в другие ИБ. При такой настройке параметров миграции, объект данного вида никогда не "покидает" места своего создания и не появляется в других ИБ. Однако при выборе данного варианта следует учитывать возможные ссылки на объекты данного вида из объектов других видов, имеющих другие параметры миграции. Например, если установить такой вариант для справочника, и в документах, которые участвуют в обмене, будет содержаться реквизит типа справочник данного вида, то при переносе документа получится неразрешенная ссылка.
Место создания и центр. При таком варианте настройки области распространения объектов существенную роль играет понятие места создания объекта. Местом создания объекта считается ИБ, в которой был создан конкретный объект. Естественно, что различные объекты одного вида могут быть созданы в различных ИБ. Однако место создания объекта может быть определено не для всех видов "ведущих" объектов. Для таких объектов как константы, календари или корректные проводки место создания не определено. Поэтому для этих видов объектов вариант настройки "Место создания и центр" не может быть установлен.
В случае выбора такого варианта области распространения, объекты данного вида помимо места их создания попадают еще и на центральную ИБ. То есть, в случае, если для некоторого вида объектов установлена область распространения "Место создания и центр", то для объектов этого вида, созданных на периферийной ИБ, их изменения будут передаваться между местом их создания и центральной ИБ. Для объектов того же вида, созданных на центральной ИБ, изменения не будут передаваться никуда. С помощью такого варианта области распространения можно добиться такого эффекта, что все объекты того или иного вида будут "собираться" на центральной ИБ, а на любой из периферийных ИБ будут находиться только те объекты, для которых она является местом создания.
В случае выбора области распространения "Место создания и центр", для вида объекта можно задать перечень периферийных узлов распределенной ИБ, которые дополнительно включаются в область распространения всех объектов данного вида. Этот перечень задается как список кодов периферийных ИБ, разделенный запятыми. При задании кодов ИБ допускается использование символов-заменителей '*'. Символ-заменитель должен завершать последовательность символов, образующих код одной или нескольких периферийных ИБ. Таким образом, "A*" представляет собой обозначение всех периферийных ИБ, коды которых начинаются символом 'А'. Последовательность "A*B" является ошибочной, так как символ '*' не завершает последовательность символов, представляющих код периферийной ИБ.
Кроме того, как отмечалось выше, дополнительной возможностью управлять распространением изменений объектов в версии 7.7 системы 1С:Предприятие является особый вид периферийных ИБ, которые получают изменения из центральной ИБ, а сами информацию о сделанных в них изменениях не передают. Для создания периферийной ИБ такого рода, надо при ее инициализации указать признак "Только получатель".
Отдельно стоит рассмотреть случай, когда параметры миграции объектов изменяются в процессе изменения конфигурации уже работающей системы. Изменения параметров миграции для каждого из объектов производится независимо от других. То есть, Конфигуратор не отслеживает ссылки между объектами при настройке параметров миграции. Таким образом, при определенных вариантах настройки параметров миграции у некоторых объектов могут появиться ссылки, указывающие "никуда". Ответственность за сохранение ссылочной целостности в распределенных ИБ возлагается на лицо, занимающееся конфигурированием системы. Общим правилом настройки параметров миграции является определение области миграции для конкретного вида объектов равной более широкой, чем область миграции ссылающихся на него объектов. Например, для справочника область миграции должна быть определена не уже, чем области миграции документов и справочников, в которых есть реквизиты типа "справочник" данного вида. Если, например, измерение регистра имеет тип "справочник" данного вида, то область миграции справочника должна покрывать области миграции всех документов, которые могут записать движения данного регистра.
При изменении параметров миграции того или иного объекта система старается привести имеющиеся данные в соответствие с новыми параметрами. Общим принципом здесь является то, что при изменении параметров миграции объекты никогда ни в каком узле распределенной ИБ не удаляются. Даже в том случае, если в соответствии с вновь установленными параметрами миграции их там быть не должно. Изменения производятся лишь в таблице регистрации изменений. Рассмотрим случаи изменения параметров миграции объектов подробнее.
Наиболее простой случай - это смена любого из вариантов области распространения на вариант "Место создания". В этом случае из таблицы регистрации изменений удаляются все записи по данному виду объектов. То есть все изменения объектов, еще не переданные в другие ИБ, не будут переданы. При этом, все объекты для которых данная ИБ не является местом создания, не будут удалены. Просто их изменения (как и изменения других объектов данного вида) не будут больше передаваться в другие ИБ.
Следующий случай - это смена области распространения "Место создания" на варианты "Все информационные базы" или "Место создания и центр". В этом случае в таблицу регистрации изменений заносятся записи для передачи всех объектов, для которых текущая ИБ является местом создания во все ИБ, в которые должны передаваться изменения в соответствии с вновь заданной настройкой. В случае, если такая смена производится для объектов, для которых место создания не определено (константы, календари, корректные проводки), то записи в таблицу регистрации изменений будут произведены только в центральной ИБ. Этими двумя вариантами и ограничиваются возможные случаи изменения параметров миграции для такого рода объектов. Все остальные случаи возможны только для тех объектов, для которых место создания можно определить.
При изменении области распространения объектов с "Место создания и центр" на "Все информационные базы", какие-либо действия предпринимаются только в центральной ИБ. В этом случае определяется список периферийных ИБ, попавших в список дополнительно включаемых в область распространения, но ранее в него не входивших. После этого производится обход всех объектов данного вида и для каждого из объектов в таблицу регистрации изменений вносятся записи для передачи состояния объекта в каждую из попавших в список периферийных ИБ, за исключением ИБ места создания объекта.
Последний и самый сложный случай - это изменение области распространения объектов с "Все информационные базы" на "Место создания и центр" или изменение списка дополнительных ИБ в варианте "Место создания и центр". Действия, производимые в данном случае различаются в зависимости от того, производятся они в центральной ИБ или в периферийной. В центральной ИБ для каждой из периферийных ИБ, не попавших в новый перечень дополнительно включаемых в область распространения, выполняется удаление из таблицы регистрации изменений записей соответствующих данному виду объектов, но только для тех объектов, для которых эта периферийная ИБ не является местом создания. Затем определяется список периферийных ИБ, попавших в список дополнительно включаемых в область распространения, но ранее в него не входивших. Естественно, что в случае, если предыдущим вариантом настройки области распространения было "Все информационные базы", то этот список окажется пустым. Затем, как и в предыдущем случае, производится обход всех объектов данного вида и для каждого из объектов в таблицу регистрации изменений вносятся записи для передачи объекта в каждую из попавших в список периферийных ИБ, за исключением ИБ места создания объекта.
Проблемы конфигурирования и администрирования
При разработке конфигурации для распределенной ИБ проявляется ряд объективно существующих проблем, которые решаются как средствами конфигурации, так и административными решениями.
Очевидной проблемой, которая уже упоминалась выше, является уникальная и последовательная нумерация документов и элементов справочников. Для организации уникальной нумерации используется механизм префиксов. Для его включения в конфигурацию, прежде всего, следует выработать некоторую дисциплину, зависимости префикса от ИБ, в которой создается объект. В простейшем случае это может быть собственно код ИБ. Однако часто префикс может автоматически определяться на каждой ИБ, но не являться ее кодом, так как он может участвовать в печатных формах документов и должен быть понятным для пользователей системы. Более сложной задачей является обеспечение сквозной нумерации объектов без префиксов в случае, когда такая нумерация регламентируется нормативными документами. Особенно сложным является обеспечение строго последовательной нумерации. Очевидно, что полного решения данной проблемы не может быть в принципе, так как объекты создаваемые динамически в независимых системах не могут иметь строгой сквозной нумерации. Отчасти данная проблема решается с помощью введения диапазонов номеров, выделяемых для каждой ИБ. Следует заметить, что номера документов и коды справочников не являются внутренними идентификаторами и их уникальность для системы не обязательна. Это значит, что поддержку уникальность номеров и кодов можно отключить для тех видов, объектов, для которых она не нужна. Кроме того, средствами конфигурации можно организовать перенумерацию объектов, например в центральной ИБ. Однако следует иметь ввиду, что эти изменения будут передаваться как и любые другие изменения, что может вызвать достаточно большой объем передаваемых между узлами данных.
Более сложной проблемой является ситуация, когда возникает необходимость использования некоторого нового объекта в двух и более узлах одновременно, до осуществления передачи данных. Например, новый товар должен быть введен и на центральной ИБ и на периферийной. Важно понимать, что созданный ведущий объект системы 1С:Предприятие обладает некоторой сущностью - внутренним идентификатором, который уникален во всей распределенной системе. То есть один и тот же объект не может быть введен в двух узлах. Даже при полном соответствии кодов, номеров и всех данных это будут два разных объекта. Такой принцип необходим для четкой работы системы со всех точек зрения.
Заметим, что возможные варианты ввода двух объектов и затем автоматической замены на центральной ИБ всех ссылок на один из объектов, достаточно сложны в реализации и весьма ненадежны.
Поэтому, на наш взгляд, решение проблемы должно лежать в области администрирования системы. Технология работы пользователей должна быть построена таким образом, чтобы ввод объекта производился на одном узле.
В отдельных случаях может использоваться следующее решение. В справочник заранее вносится некоторое количество новых элементов со специальными кодами или в специальную группу. При появлении необходимости ввода нового товара реально не вводится новый элемент, а изменяется один этих элементов. При этом административными силами должно быть обеспечено идентичное изменение одного и того же "зарезервированного" объекта в тех узлах распределенной ИБ, в которой он должен быть использован до обмена данными. При обмене данными сами реквизиты элемента будут системой синхронизированы, а ссылки в других объектах, разумеется будут идентичными, так как использовался один и тот же объект.
В любых случаях следует учитывать, что раздельный ввод и использование объектов потребует от пользователей правильного ввода данных. Так, например, при вводе нового товара в двух узлах с разными ценами могут иметь место серьезные ошибки в оформлении документов.
Еще одна проблема, с которой приходится сталкиваться при конфигурировании распределенной ИБ, это правильное поддержание механизмов учета компонент при неполной миграции объектов. Следует учитывать, что итоги оперативного и бухгалтерского учета не являются самостоятельными объектами. Они не переносятся, а рассчитываются на основании перенесенных движений регистров и проводок. Движения регистров и проводки переносятся соответственно только вместе с документами. Таким образом, для правильного состояния итогов на некоторой ИБ, на нее должны переноситься все документы, осуществляющие движения регистров или записывающие проводки влияющие на эти итоги. С другой стороны, это не означает, что переноситься должны все документы, записывающие движения конкретного регистра и проводки. Например, если на периферийной ИБ вводятся документы, выполняющие движения по одному складу, и итоги регистра учета товарного запаса в данной ИБ нужны только по данному складу, то, разумеется, в данном узле будет достаточно наличия всех документов выполняющих движения регистров по данному складу. Это достигается установкой параметра миграции "Место создания и центр".
В Windows основной элемент пользовательского интерфейса - форма. В Delphi каждый проект имеет по крайней мере одно окно - главное окно приложения. Все окна в Delphi основаны на объекте TForm. В данной статье мы рассмотрим основные события учавствующие в "жизни формы".
Форма
Формы имеют свои свойства, события и методы, при помощи которых Вы можете управлять видом и поведением формы. Форма, это обычный компонент Delphi, но в отличие от других, её нет на панели компонентов. Обычно форма создаётся при создании нового проекта (File -> New Application). Вновь созданная форма будет главной формой приложения.
Дополнительные формы в проекте создаются через File -> New Form. Так же существуют и другие способы создания форм, но здесь мы не будем рассматривать их...
Как и любой другой компонент (объект) форма имеет свои методы и реагирует на события. Давайте рассмотрим некоторые из этих событий...
Событие OnCreate возникает при создании TForm и только один раз. При создании формы (у каторой свойство Visible установлено в True), события произойдут в следующем порядке: OnCreate, OnShow, OnActivate, OnPaint.
В обработчике события OnCreate можно сделать какие-либо инициализационные действия, однако, любые объекты созданные в OnCreate будут уничтожены в событии OnDestroy.
OnShow
Это событие генерируется, когда форма станет видимой. OnShow вызывается сразу перед тем, как форма станет видимой. Это событие случается, если установить свойство формы Visible в True, либо при вызове методов Show или ShowModal.
OnActivate
Это событие генерируется, когда форма становится активной, тоесть когда форма получает фокус ввода. Это событие можно использовать для того, чтобы сменить элемент формы который должен получить фокус.
OnPaint, OnResize
Эти события вызываются каждый раз, когда форма изначально создаётся. При этом OnPaint вызывается каждый раз, когда какому-нибудь элементу формы необходимо перерисоваться (это событие можно использовать, если необходимо при этом рисовать на форме что-то особенное).
Уничтожение
При уничтожении формы, события генерируются в следующем порядке:
Если мы попытаемся закрыть форму при помощи метода Close либо другим доступным способом (Alt+F4 либо через системное меню), то сгенерируется событие OnCloseQuery. Таким образом, это событие можно использовать, чтобы предотвратить закрытие формы. Обычно, событие OnCloseQuery используется для того, чтобы спросить пользователя - уверен ли он (возможно в приложении остались несохранённые данные).
Обработчик события OnCloseQuery содержит переменную CanClose, которая определяет, можно ли форме закрыться. Изначальное значение этой переменной True. Однако в обработчике OnCloseQuery можно установить возвращаемое значение CloseQuery в False, чтобы прервать выполнение метода Close.
OnClose
Если OnCloseQuery вернул CanClose=True (что указывает на то, что форма должна быть закрыта), то будет будет сгенерировано событие OnClose.
Событие OnClose даёт последний шанс, чтобы предотвратить закрытие формы. Обработчик OnClose имеет параметр Action со следующими четырьмя возможными значениями:
caNone. Форме не разрешено закрыться. Всё равно, что мы установим CanClose в False в OnCloseQuery.
caHide. Вместо закрытия, форма будет скрыта.
caFree. Форма будет закрыта, и занятые ей ресурсы будут освобождены.
caMinimize. Вместо закрытия, форма будет минимизирована. Это значение устанавливается поумолчанию у дочерних форм MDI.
Замечание: Когда пользователь шутдаунит Windows, то будет вызвано OnCloseQuery, а не OnClose. Если Вы не хотите, чтобы Windows завершила свою работу, то поместите свой код в обработчик события OnCloseQuery, хотя CanClose=False не сделает, того, что сделано здесь.
OnDestroy
После того, как метод OnClose будет обработан и форма будет закрыта, то будет вызвано событие OnDestroy. В OnDestroy обычно делаются действия, противоположные тем, которые проделывались в OnCreate, то есть уничтожение созданных объектов и освобождение выделенной памяти.
Естевственно, что когда главная форма проекта будет закрыто, то приложение будет завершено.
Лазерные диски – не слишком-то надежные носители информации. Даже при бережном обращении с ними вы не застрахованы от появления царапин и загрязнения поверхности (порой диск фрезерует непосредственно сам привод и вы бессильны этому противостоять). Но даже вполне нормальный на вид диск может содержать внутренние дефекты, приводящие к его полной или частичной нечитаемости на штатных приводах.
Особенно это актуально для CD-R/CD-RW дисков, качество изготовления которых все еще оставляет желать лучшего, а процесс записи сопряжен с появлением различного рода ошибок. Однако даже при наличии физических разрушений поверхности лазерный диск может вполне нормально читаться за счет огромной избыточности хранящихся на нем данных, но затем, по мере разрастания дефектов, корректирующей способности кодов Рида-Соломона неожиданно перестает хватать, и диск безо всяких видимых причин отказывается читаться, а то и вовсе не опознается приводом.
К счастью, в подавляющем большинстве случаев хранимую на диске информацию все еще можно спасти, и эта статья рассказывает как.
Общие рекомендации по восстановлению
Не всякий не читающийся (нестабильно читающийся) диск – дефектный. Зачастую в этом виновен отнюдь не сам диск, а операционная система или привод. Прежде чем делать какие-либо заключения, попробуйте прочесть диск на всех доступных вам приводах, установленных на компьютерах девственно-чистой операционной системой. Многие приводы, даже вполне фирменные и дорогие (например, мой PHILIPS CD-RW 2400), после непродолжительной эксплуатации становятся крайне капризными и раздражительными, отказывая в чтении тем дискам, которые все остальные приводы читают безо всяких проблем. А операционная система по мере обрастания свежим софтом склонна подхватывать различные глюки подчас проявляющиеся самым загадочным образом (в частности, привод TEAC, установленный в систему с драйвером CDR4_2K.SYS, доставшемся ему в наследство от PHILIPS'a, конфликтует с CD Player'ом, не соглашаясь отображать содержимое дисков с данными, если тот активен, после удаления же CDR4_2K.SYS все идет как по маслу).
Также не стоит забывать и о том, что корректирующая способность различных моделей приводов очень и очень неодинакова. Как пишет инженер-исследователь фирмы ЕПОС Павел Хлызов в своей статье "Проблема: неисправный CD-ROM": "…в зависимости от выбранной для конкретной модели CD-ROM стратегии коррекции ошибок и, соответственно, сложности процессора и устройства в целом, на практике тот или иной CD-ROM может либо исправлять одну-две мелкие ошибки в кадре информации (что соответствует дешевым моделям), либо в несколько этапов восстанавливать, с вероятностью 99,99%, серьезные и длинные разрушения информации. Как правило, такими корректорами ошибок оснащены дорогостоящие модели CD-ROM. Это и есть ответ на часто задаваемый вопрос: "Почему вот этот диск читается на машине товарища, а мой ПК его даже не видит?".
Вообще-то, не совсем понятно, что конкретно господином инженером-исследователем имелось ввиду: корректирующие коды C1, C2, Q- и P- уровней корректно восстанавливают все известные мне приводы, и их корректирующая способность равна: до двух 2 ошибок на каждый из C1 и C2 уровней и до 86- и 52-ошибок на Q- и P- уровни соответственно. Правда, количество обнаруживаемых, но уже математически неисправимых ошибок составляет до 4 ошибок на C1 и C2 уровней и до 172/104 ошибок на Q/P, но… гарантированно определяется лишь позиция сбойных байт во фрейме/секторе, а не их значение. Впрочем, зная позицию сбойных байт и имея в своем распоряжении исходный HF-сигнал (т. е. аналоговый сигнал, снятый непосредственно со считывающей головки), кое-какие крохи информации можно и вытянуть, по крайней мере теоретически… так что приведенная выше цитата в принципе может быть и верна, однако, по наблюдениям автора данной статьи, цена привода очень слабо коррелирует с его "читабельной" способностью. Так, относительно дешевые ASUS читают практически все, а дорогие PHILIPS'ы даже свои родные диски с драйверами опознают через раз.
Другая немаловажная характеристика – доступный диапазон скоростей чтения. В общем случае – чем ниже скорость вращения диска, тем мягче требования, предъявляемые к его качеству. Правда, зависимость эта не всегда линейна. Большинство приводов имеют одну или несколько наиболее предпочтительных скоростей вращения, на которых их читабельная способность максимальна. Например, на скорости 8x дефектный диск читается на ура, а на всех остальных скоростях (скажем, 2x, 4x, 16x, 32x) – не читается вообще. Предпочтительная скорость легко определяется экспериментально, необходимо лишь перебрать полный диапазон доступных скоростей.
При покупке CD-ROM'a выбирайте тот привод, у которого скоростной диапазон максимален. Например, уже упомянутый выше PHILIPS CDRW 2400 умеет работать лишь на: 16x, 24x, 38x и 42x. Отсутствие скоростей порядка 4x – 8x ограничивает "рацион" привода только высококачественными дисками.
По непонятным причинам, штатные средства операционной системы Windows не позволяют управлять скоростью диска и потому приходится прибегать к помощи сторонних утилит, на недостаток которых, впрочем, жаловаться не приходится. Вы можете использовать Slow CD, Ahead Nero Drive Speed и т. д. Вообще-то, большинство приводов самостоятельно снижают скорость, натолкнувшись на не читающиеся сектора, однако качество заложенных в них алгоритмов все еще оставляет желать лучшего, поэтому "ручное" управление скоростью дает значительно лучший результат.
Если же ни на одном из доступных вам приводов диск все равно не читается, можно попробовать отшлифовать его какой-нибудь полировальной пастой. Технике полирования оптических поверхностей (и лазерных дисков в частности) посвящено огромное количество статей, опубликованных как в печатных изданиях, так и в Интернете (особенно полезны в этом смысле астрономические книги по телескопостроению), поэтому здесь этот вопрос будет рассмотрен лишь кратко. Да, действительно, поцарапанный диск в большинстве случав можно отполировать, и если все сделать правильно, диск с высокой степенью вероятности возвратится из небытия, но… Во-первых, полировка восстанавливает лишь царапины нижней поверхности диска и бессильна противостоять разрушениям отражающего слоя. Во-вторых, устраняя одни царапины, вы неизбежно вносите другие - после иной полировки лазерному диску может очень сильно поплохеть. В-третьих, полировке дисков невозможно научиться за раз, – вам понадобиться уйма времени и куча "подопытных" дисков. Нет уж, благодарю покорно! Лучше мы пойдем другим путем!
А вот что вашему диску действительно не помешает – так это протирка обычными салфетками, пропитанными антистатиком (ищите их в компьютерных магазинах). Прежде чем вытирать диск, сдуйте все частицы пыли, осевшие на него (иначе вы его только больше поцарапаете) и ни в коем случае не двигайтесь концентрическими мазками! Вытирать поверхность диска следует радиальными движениями от центра к краям, заменяя салфетку на каждом проходе.
Вторая часть серии статей "Использование регулярных выражений в PHP" посвящена решению ряда проблем обработки сложных текстов с помощью "продвинутых" операторов регулярных выражений.
Несмотря на то, что термины данные и информация используются взаимозаменяемо, между ними есть существенная разница. Данные существуют реально. Данные — - это список температур, перечень недавних продаж или опись товара, имеющегося в наличии. Информация — это прогнозы. Информация — это предсказание погоды, прогноз прибылей и убытков и тенденции сбыта. Данные записываются в виде нулей и единиц, в то время как информация обрабатывается мозгом.
Между данными и информацией располагается приложение: механизм, который преобразует одно в другое и наоборот. Например, при покупке книги в Интернете это приложение преобразует вашу информацию — название книги, идентификатор, информацию о банковском счете — в данные: номер заказа, цену со скидкой, характеристики транзакции с использованием кредитной карточки и количество оставшихся в наличии экземпляров книги. Аналогичным образом, приложение преобразует данные в запрос на выборку со склада, отметку об отгрузке и номер отслеживания — информацию, необходимую для реализации продажи.
В действительности сложность создания приложения прямо пропорциональна преобразованиям, которые оно выполняет. Гостевая книга Web-сайта, передающая имя и адрес в поля базы данных, устроена элементарно. С другой стороны, онлайновый магазин, который передает большое количество видов информации в модель данных коммерческой сделки и преобразует данные в информацию для реализации процесса принятия решений, достаточно сложен с точки зрения разработки. Искусство программирования заключается в умелом манипулировании данными и информацией — мастерство, схожее с фиксацией света в живописи.
Как было сказано в первой части, регулярные выражения являются одним из самых мощных средств манипулирования данными. Регулярные выражения лаконично описывают форму данных и раскладывают их на составляющие. Например, следующее регулярное выражение можно использовать для обработки температуры, заданной в градусах по Цельсию или по Фаренгейту: /^([+-]?[0-9]+)([CF])$/.
Регулярное выражение сравнивает начало строки (отображается знаком "крышка" (^), за которым идет знак "+", знак "-", или ничего ([+-]?), за которым следует целое число ([0-9]+), обозначение шкалы — Цельсия или Фаренгейта ([CF]) — и заканчивается концом строки (обозначается знаком доллара $).
В данном регулярном выражении операторы начала строки и конца строки представляют собой примеры операторов нулевой ширины или совпадений по положению, а не по символам. Круглые скобки также не указывают на символы. Зато, если заключить шаблон в круглые скобки, то будет извлечен текст, соответствующий шаблону. Следовательно, если текст полностью сопоставим с шаблоном, то первая пара круглых скобок выдаст строку, представляющую собой положительное или отрицательное целое число, например, +49, а вторая пара круглых скобок - или букву C, или F.
В первой части серии представлено понятие регулярного выражения и были описаны PHP-функции для сравнения текста с шаблонами, а также для извлечения совпадений. А теперь давайте углубимся в изучение регулярных выражений и посмотрим на некоторые "продвинутые" операторы и средства.
Круглые скобки опять приходят на помощь
В большинстве случаев пара круглых скобок используется для описания части шаблона и получения текста, соответствующего этой части. Однако от круглых скобок не всегда требуется получение части шаблона. Как и в сложной арифметической формуле, круглые скобки можно использовать для группировки условий.
Приведу пример. Догадаетесь, какому типу данных соответствует данное выражение?
/[-a-z0-9]+(?:\.[-a-z0-9]+)*\.(?:com|edu|info)/i
Как можно догадаться, это регулярное выражение определяет имена Интернет-сайтов (только для доменов .com, .edu, и .info). Отличием является использование дополнительного оператора ?:. Квалификатор части шаблона ?: отключает функцию извлечения данных, и тем самым дает круглым скобкам возможность обозначать последовательность действий. Например, в данном случае фраза (?:\.[-a-z0-9]+)* соответствует нулю или более элементам строки, например, ".ibm." Аналогично, фраза \.(?:com|edu|info) обозначает последовательность символов, за которой идет одна из строк com, edu, или info.
Отключение функции извлечения информации может показаться бессмысленным, если не подумать о том, что извлечение информации требует дополнительной обработки. Если программа обрабатывает большое количество данных, то отказ от извлечения может быть целесообразным. Кроме того, если вы имеете дело со сложным регулярным выражением, то отключение функции извлечения информации в некоторых частях шаблона может упростить извлечение тех частей шаблона, которые реально нужны.
Примечание: Модификатор i в конце регулярного выражения делает все сопоставления с шаблоном нечувствительными к регистру. Следовательно, подмножество a-z будет сопоставимо со всеми буквами, независимо от регистра.
В PHP есть и другие модификаторы частей шаблона (subpattern). Используя отладчик регулярных выражений, показанный в первой части данной серии (повторно показан в листинге 1), попробуйте сопоставить регулярное выражение ((?i)edu) со строками "EDU," "edu," и "Edu." Если в начале части шаблона задать модификатор (?i), то сопоставление с шаблоном не будет зависеть от регистра. Чувствительность к регистру восстанавливается, как только заканчивается данная часть шаблона. (Сравните с модификатором / ... /i, который применяется ко всему шаблону.)
Листинг 1. Простой отладчик регулярных выражений
Еще один полезный модификатор части шаблона - это (?x). Он позволяет добавлять в шаблон пробелы, что упрощает чтение регулярных выражений. Таким образом, часть шаблона ((?x) edu | com | info) (обратите внимание на пробелы между операторами дизъюнкции, которые добавлены для удобочитаемости) аналогична (edu|com|info). Для того, чтобы добавлять пробелы и комментарии в регулярное выражение, можно использовать глобальный модификатор / ... /x, см. листинг ниже.
Листинг 2. Добавление пробелов и комментариев
Как видно из листинга, при необходимости модификаторы можно объединять. Если необходимо включить в регулярное выражение символ пробела при использовании модификатора (?x), используйте метасимвол \s для поиска любого пробельного символа и \ (обратный слеш с пробелом) для поиска одного пробела, например, ((?x) hello \ there).
Оглядываемся вокруг
В подавляющем большинстве случаев регулярные выражения используются для проверки или декомпозиции входной информации на отдельные "лакомые кусочки", которые записываются в архив данных или сразу же обрабатываются приложением. Общепринятыми сферами применения являются: обработка полей форм, парсинг XML-кода и анализ протоколов.
Еще одна область применения регулярных выражений - форматирование, нормализация или улучшение читаемости данных. Вместо того чтобы использовать регулярные выражения для поиска и извлечения текста, при форматировании они применяются для поиска и вставки текста в надлежащее местоположение.
Вот пример полезного применения форматирования. Предположим, что Web-форма передает приложению значение зарплаты с округлением до целого доллара. Так как зарплата хранится в виде числа целого типа, то перед сохранением переданных данных приложение должно удалять из них знаки пунктуации. Однако при извлечении данных из хранилища, возможно, понадобится изменить их формат и сделать удобочитаемыми с помощью разделителей. В листинге 3 показано, как простой PHP-запрос преобразует сумму в долларах в число.
Листинг 3. Преобразование суммы в долларах в число
Вызов функции preg_replace() заменяет знак доллара, любой пробельный символ и все запятые -- на пустую строку, возвращая то, что предположительно является целым числом. Если проверка функцией is_numeric() подтверждает правильность входных данных, их можно сохранить.
А теперь давайте выполним обратную операцию - добавим к числу знак денежной единицы и запятые-разделители сотен, тысяч и миллионов. Для добавления запятых в определенных позициях можно написать программу для поиска этих компонентов, а можно воспользоваться операторами посмотри вперед и посмотри назад. Модификатор части шаблона ?<= обозначает посмотри назад (то есть влево) от текущей позиции. Модификатор ?= означает "посмотри вперед" (то есть вправо) от текущей позиции.
[pagebreak]
Итак, какие позиции нам нужны? Любое место в строке, при условии, что есть как минимум один символ слева и одна или более групп по три символа справа, не считая десятичной точки и количества центов. Соблюдая это правило и используя два модификатора, анализирующих символы справа и слева от определенной позиции и являющихся операторами нулевой ширины, мы можем достичь цели с помощью следующей инструкции:
Как работает это регулярное выражение? Начиная с первого символа строки и обрабатывая каждый символ, регулярное выражение отвечает на вопрос: "Есть ли хотя бы один символ слева и одна или несколько групп из трех символов справа?" Если да, то наш оператор нулевой ширины заменяется запятой.
Большинство сложных сопоставлений можно реализовать, используя стратегию, аналогичную приведенной выше. Например, вот еще один вариант использования оператора "посмотри вперед", который решает широко распространенную дилемму.
Листинг 4. Пример использования оператора "посмотри вперед" ("предвидение")
Оператор preg_replace() преобразует строку данных, разделенных запятыми, в строку данных, разделенных знаком табуляции. Предусмотрительным образом, он не заменяет запятые в строке, заключенной в кавычки.
Это регулярное выражение при каждом обнаружении запятой (на это указывает запятая в самом начале регулярного выражения) проверяет утверждение: "Впереди не было кавычек или было четное количество кавычек". Если утверждение верно, то запятую можно заменить знаком табуляции (the \t).
Если Вам не нравятся операторы «посмотри вперед» и «посмотри назад» или вы работаете с таким языком, в котором их нет, можно добавить запятые в число и с помощью обычного регулярного выражения. Однако для реализации такого решения потребуется много итераций.
Листинг 5. Добавление запятых
Давайте пройдем по коду. Сначала параметр зарплаты очищается от знаков пунктуации для моделирования ситуации чтения целого числа из базы данных. Затем выполняется цикл в поисках позиций, где за одним числовым символом ((\d) идут три числовых символа ((\d\d\d\): если обнаруживается граница слова, заданная как \b, цикл прекращается. Граница слова -- это еще один оператор нулевой ширины, который соответствует следующим позициям:
* Перед первым символом строки, если это буква слова.
* За последним символом строки, если это буква слова.
* Между буквой слова и небуквенным символом, непосредственно за буквой слова.
* Между небуквенным символом и буквой слова, непосредственно за небуквенным символом.
Таким образом, примерами правильных границ слова являются пробел, точка и запятая.
Благодаря внешнему циклу регулярное выражение перемещается слева направо в поисках цифры, за которой идут три цифры и граница слова. При обнаружении совпадения между двумя частями шаблона добавляется запятая. Цикл должен продолжаться до тех пор, пока оператор preg_replace() находит совпадения, что задано в условии $old != $pretty_print.
Жадность и лень
Регулярные выражения обладают большими возможностями, иногда даже слишком большими. Например, давайте рассмотрим, что произойдет, если регулярное выражение ".*" будет обрабатывать строку "The author of 'Wicked' also wrote 'Mirror, Mirror.'" Вероятно, вы предполагаете, что preg_match() вернет два совпадения, и с удивлением обнаружите, что результат всего один: 'Wicked' also wrote 'Mirror, Mirror.'
Почему? Если не задать иное, то такие операторы как * (ноль или более) и + (один или более) -- "жадные". Если сопоставление с образцом может продолжаться, то они и будут его продолжать до тех пор, пока не будет возвращен максимальный результат из возможных. Для сохранения минимальных совпадений необходимо принудительно заставлять определенные операторы быть "ленивыми". "Ленивые" операторы находят самое короткое совпадение и на этом останавливаются. Чтобы сделать оператор более "ленивым", добавьте суффикс в виде знака вопроса. Пример показан в листинге 6.
Листинг 6. Добавление суффикса в виде знака вопроса
Регулярное выражение ".*?" расшифровывается следующим образом: "найти кавычку, за которой идет ровно столько символов с последующей кавычкой.
Однако иногда оператор * может быть слишком "ленивым". Например, посмотрите на следующий фрагмент кода. Что он делает?
Листинг 7. Простой отладчик регулярных выражений
Что вы загадали? "123"? "1"? Нет результата? На самом деле результатом будет Array ( [0] => [1] => ), означающий, что совпадение было найдено, но никаких данных извлечено не было. Почему? Вспомните, что оператор * ищет совпадения с нулем или более символов. В данном случае, выражение [0-9]* находит совпадение с нулем символов от начала строки, и обработка заканчиваетс.
Для решения данной проблемы добавьте оператор нулевой ширины для привязки совпадения, который заставляет регулярное выражение продолжать сопоставления; /([0-9]*\b/.
Советы и рекомендации
С помощью регулярных выражений можно решать как простые, так и сложные задачи при обработке текста. Начните с небольшой группы операторов и по мере того, как вы будете набираться опыта, расширяйте свой словарь. В качестве вознаграждения за ваши старания -- некоторые советы и рекомендации.
Создание переносимых регулярных выражений с помощью классов символов
Вам уже знакомы метасимволы, например, \s - соответствует любому пробельному символу. Кроме того, большинство реализаций регулярных выражений поддерживает предопределенные классы символов, которые более просты в использовании и переносимы с одного письменного языка на другой. Например, класс символов [:punct:] замещает все символы пунктуации в данном языке. Вместо [0-9] можно использовать [:digit:] и более переносимое замещение [:alpha:] вместо [-a-zA-Z0-9_]. Например, можно убрать все знаки пунктуации, используя:
Класс символов представляет собой более сжатую форму по сравнению с подробным описанием всех символов пунктуации. Полный перечень классов символов можно найти в документации по версии языка PHP.
Как исключить то, что вы не ищете
Как показано в примере с данными, разделенными символом табуляции, в качестве значений, разделенных запятыми (CSV), иногда проще и точнее задать список тех вариантов, которые не нужно находить (сопоставлять). Последовательность, начинающаяся со знака "крышка" (^) будет соответствовать любому символу, не принадлежащему данной последовательности. Например, для проверки правильности телефонных номеров для США можно использовать регулярное выражение /[2-9][0-9]{2}[2-9][0-9]{2}[0-9]{4}/. Используя набор ограничений можно написать регулярное выражение в более явном виде /[^01][0-9]{2}[^01][0-9]{2}[0-9]{4}/. Оба регулярных выражения работают, хотя смысл последнего, вероятно, более понятен.
Пропуск новой строки
Если во входных данных несколько строк, стандартного регулярного выражения будет недостаточно, так как сканирование прекращается на начале новой строки, которая обозначается $. Однако, если воспользоваться модификаторами s или m, то регулярное выражение будет обрабатывать входные данные по-другому. Первый модификатор рассматривает строковую последовательность как одну строку, где точка указывает на начало новой строки (обычно она этого не делает). Второй рассматривает строковую последовательность как несколько строк, где ^ и $ соответствуют началу и концу любой строки, соответственно. Приведем пример. Если задать $string = "Hello,\nthere";, то оператор preg_match( "/.*/s", $string, $matches) параметру $matches[0] присвоит значение Hello,\nthere. (При удалении s будет выдано Hello.)
Поиск по шаблону является настолько обычным занятием в разработке программного обеспечения, что для облегчения этой задачи была создана специальная технология — регулярные выражения. Узнайте, как можно использовать ее при написании кода, прочитав эту статью.
Все устройства получают входную информацию, выполняют какие-либо операции и выдают результат. Например, телефон во время разговора преобразует звуковую энергию в электрический сигнал и обратно. Двигатель потребляет топливо (пар, расщепление атомных ядер, бензин, мышечные усилия) и преобразует его в энергию. Блендер поглощает ром, лед, лайм и кюрасао и взбалтывает их в коктейль Mai Tai. (Или, если вам хочется чего-то изысканного, сделайте Bellini из шампанского и грушевого сока. Блендер – замечательное универсальное устройство.)
Так как программное обеспечение преобразует данные, то каждое приложение фактически является устройством (хоть и виртуальным, так как у него нет физических составляющих). Например, компилятор в качестве входной информации получает исходную программу и преобразует ее в двоичный исполняемый код. Программа прогнозирования погоды генерирует предсказания на основе результатов прошлых (исторических) замеров, а графический редактор обрабатывает пикселы, применяя правила к отдельным пикселам или их группам, чтобы, например, сделать изображение более четким или изменить его стиль.
Так же, как и любое другое устройство, программное обеспечение предназначено для работы с определенным исходным материалом, например, набором чисел, данными XML-схемы или протоколом. Если программе задать некорректную входную информацию — неподходящую по форме или типу, то существует большая вероятность того, что результат будет непредсказуемым и, возможно, даже катастрофическим. Как говорится: "Мусор заложишь - мусор получишь".
На самом деле для решения всех нетривиальных задач необходимо отделять правильные данные от некорректных и отклонять некорректные данные во избежание ошибок в результатах. Это, конечно же, актуально и для Web-приложений, написанных на языке PHP. Неважно, получены ли входные данные из формы для ввода с клавиатуры или в результате выполнения программного запроса Asynchronous JavaScript + XML (Ajax), прежде чем начать какие-либо вычисления, программа должна проверить входную информацию. Возможно, что числовые значения должны находиться в пределах определенного диапазона чисел или представлять собой только целые числа. Возможно, значение должно соответствовать определенному формату, например, почтового индекса. Например, почтовый индекс в США представляет собой пять цифр плюс дополнительный префикс "Plus 4", состоящий из дефиса и 4 дополнительных цифр. Возможно, другие строки также должны состоять из определенного количества символов, например, две буквы для указания аббревиатуры штата США. Строковые данные доставляют особенно много проблем: PHP-приложение должно быть начеку по отношению к злонамеренным программам-агентам, вложенным в SQL-запросы, код JavaScript или любой другой код, которые способны изменить поведение приложения или обойти защиту.
Однако каким образом программа может определить, являются ли входные данные числом или соответствуют ли определенным требованиям, например, к почтовому индексу? На самом деле для реализации проверки путем сопоставления с шаблоном необходим небольшой парсер, создающий конечный автомат, считывающий входные данные, обрабатывающий маркеры, отслеживающий состояние и выдающий результаты. Однако создание и обслуживание даже самого простого парсера может оказаться непростым делом.
К счастью, анализ на основе сопоставления с шаблоном настолько широко распространен в компьютерных технологиях, что с течением времени (примерно с момента появления UNIX®) были разработаны специальные технологии и, конечно же, механизмы обработки, чтобы облегчить рутинную работу. Регулярное выражение (regex) описывает шаблоны посредством лаконичных и удобочитаемых обозначений. Получив регулярное выражение и данные, механизм regex сообщает, совпадают ли эти данные с шаблоном, и если совпадение было обнаружено, что именно совпало.
Вот небольшой пример использования регулярного выражения, взятый из UNIX-утилиты, работающей в режиме командной строки, которая ищет заданный шаблон в содержимом одного или нескольких текстовых файлов UNIX. Команда grep -i -E '^Bat' ищет последовательность символов beginning-of-line (начало строки), обозначаемое "крышкой", [^]), за которым следуют буквы b, a, и t верхнего или нижнего регистра (ключ -i указывает на то, что при сопоставлении с шаблоном регистр не учитывается, таким образом, например, B и b - тождественны). Следовательно, для файла heroes.txt:
Листинг 1. heroes.txt
Вышеупомянутая команда grep выдаст два совпадения:
Batman
Batgirl
Регулярные выражения
PHP предлагает два программных интерфейса регулярных выражений: один -- для интерфейса переносимых операционных систем (POSIX), а второй - для регулярных выражений, совместимых с языком Perl (PCRE). В общем и целом второй интерфейс является более предпочтительным, так как PCRE сам по себе мощнее, чем POSIX, и предоставляет все операторы, используемые в языке Perl. Более подробная информация по обращению к regex-функциям POSIX представлена в документации по языку PHP (см. раздел Ресурсы). В данной статье мы сосредоточим свое внимание на свойствах PCRE.
Регулярные выражения PHP PCRE содержат операторы, позволяющие путем сопоставления находить конкретные символы или другие операторы, определенные местоположения, например, начало и конец строки, начало или конец слова. Регулярные выражения также позволяют описывать альтернативы, которые можно задать альтернативы типа "или"-"или"; повторения фиксированной, изменяемой или неопределенной длины; наборы символов (например, "любая буква от a до m"); и классы, или типы символов (печатаемые символы, знаки препинания). Специальные операторы также разрешают использовать группировку — возможность применить оператор к целой группе других операторов.
В таблице 1 показаны некоторые типичные операторы регулярных выражений. Для создания сложных выражений можно последовательно объединять элементарные операторы из таблицы 1 (и другие).
Таблица 1. Типичные операторы регулярных выражений
Оператор Значение
. (точка) Любой одиночный символ
^ (крышка) Пустая последовательность в начале строки или цепочки
$ (знак доллара) Пустая последовательность в конце строки
A Буква A верхнего регистра
a Буква a нижнего регистра
\d Любая цифра
\D Любой нецифровой символ
\w Любая буква или цифра; синоним - [:alnum:]
[A-E] Любая заглавная буква из A, B, C, D или E
[^A-E] Любой символ, за исключением заглавных букв A, B, C, D или E
X? Найти совпадение по отсутствию или наличию одной заглавной буквы X
X* Ни одной или любое количество заглавных букв X
X+ Одна или несколько заглавных букв X
X{n} Ровно n заглавных букв X
X{n,m} Не менее n и не более m заглавных букв X; если опустить m, то выражение будет искать не менее n заглавных букв X
(abc|def)+ По меньшей мере одно вхождение последовательности abc и def
В следующем примере показано типичное использование регулярного выражения. Например, для web-сайта необходимо, чтобы каждый пользователь регистрировался. Имя пользователя должно начинаться с буквы и содержать от 3 до 10 буквенно-цифровых символов. Для проверки имени пользователя на соответствие ограничениям при отправке данных в приложение можно использовать следующее регулярное выражение: ^[A-Za-z][A-Za-z0-9_]{2,9}$.
Знак "крышка" соответствует началу строки. Первый набор [A-Za-z] соответствует любой букве. Второй набор [A-Za-z0-9_]{2,9} соответствует последовательности, содержащей от 2 до 9 букв, цифр или символов подчеркивания. Знак доллара ($) соответствует концу строки.
На первый взгляд, знак доллара может показаться лишним, однако его использование важно. Если его пропустить, то условиям данного регулярного выражения будет отвечать любая строка, которая начинается с буквы, содержит от 2 до 9 буквенно-цифровых символов и любое количество других символов. Иными словами, если бы не было знака доллара как привязки к концу строки, то подошла бы недопустимо длинная строка с подходящим началом, например, "martin1234-cruft" .
Программирование на языке PHP и регулярные выражения
В PHP есть функции для поиска совпадений в тексте, замены каждого совпадения на другой текст (похоже на операцию "найти и заменить") и поиска совпадений среди элементов списка. Вот эти функции:
Чтобы показать, как работают эти функции, давайте создадим небольшое PHP-приложение, которое будет просматривать список слов на соответствие определенному шаблону. Слова и регулярные выражения будут вводиться из обычной web-формы, а результаты отображаться в браузере посредством функции simple print_r(). Эта программка пригодится, если возникнет желание проверить или отладить регулярное выражение.
PHP-код показан в листинге 2. Все входные данные берутся из обычной HTML-формы. (Для краткости эту форму и PHP-код, отслеживающий ошибки, опустим.)
Листинг 2. Сравнение текста с шаблоном
Вначале с помощью функции preg_split() строка из слов, разделенных запятыми, преобразуется в отдельные элементы. Данная функция разбивает строку в тех местах, которые соответствуют условиям регулярного выражения. В данном случае регулярное выражение представляет собой просто "," , (запятая - разделитель списка слов, указанных через запятую). Слэш в начале и в конце просто показывает начало и конец regex.
Третий и четвертый аргументы функции preg_split() необязательны, но полезны. Добавьте в третий аргумент число n целого типа, если необходимо вернуть только первые n совпадений, или -1, если необходимо вернуть все совпадения. Если в качестве четвертого аргумента задать идентификатор PREG_SPLIT_NO_EMPTY, то функция preg_split() не будет возвращать пустые результаты.
Затем каждый элемент списка слов, разделенных запятыми, корректируется (убираются начальные и конечные пробелы) с помощью функции trim() и сравнивается с заданным регулярным выражением. Функция preg_grep() существенно упрощает процесс обработки списка: просто укажите в качестве первого аргумента шаблон, а в качестве второго - массив слов для сравнения. Функция возвращает массив совпадений.
Например, если в качестве шаблона задать регулярное выражение ^[A-Za-z][A-Za-z0-9_]{2,9}$ и список слов разной длины, то можно получить результат, показанный в листинге 3.
Листинг 3. Результат работы простого регулярного выражения
Кстати, с помощью дополнительного маркера PREG_GREP_INVERT можно инвертировать операцию preg_grep() и найти элементы, которые не совпадают с шаблоном (аналогично оператору grep -v в командной строке). Заменяя 22 строку на $matches = preg_grep( "/${_REQUEST[ 'regex' ]}/", $words, PREG_GREP_INVERT ) и используя входные данные из листинга 3, мы получим Array ( [1] => 1happy [2] => hermanmunster ).
Разбор строк
Функции preg_split() и preg_grep() очень удобны. Первая из них может разбирать строку на подстроки, если подстроки разделяются определенным шаблоном. Функция preg_grep() позволяет быстро отфильтровать список.
Но что произойдет, если строку нужно разобрать на составные части, используя одно или несколько сложных правил? Например, в США номера телефонов обычно выглядят следующим образом: "(305) 555-1212," "305-555-1212," или "305.555.1212." Если убрать пунктуацию, то количество символов сократится до 10 цифр, что легко можно определить с помощью регулярного выражения \d{10}. Однако код и префикс (каждый из которых состоит из трех цифр) телефонного номера США не могут начинаться с нуля или единицы (так как нуль и единица используются как префиксы для междугородных звонков). Вместо того чтобы разбивать числовую последовательность на отдельные цифры и создавать сложный код, для верификации можно использовать регулярное выражение.
Фрагмент кода позволяющий решить эту задачу, показан в листинге 4.
Листинг 4. Проверка американского телефонного номера
Давайте пройдем по этому коду:
* Как показано в таблице 1, в регулярных выражениях используется ограниченный набор специальных символов, например, квадратные скобки ([ ]) для наименования последовательности. Если надо найти такой символ в тексте, необходимо "выделить" специальный символ в регулярном выражении, поставив перед ним обратный слэш (\). Когда символ выделен, можно задать его посик, как и любого другого символа. Если нужно найти символ точки, например, в полном составном имени хоста, то напишите \.. При желании строку можно подать в функцию preg_quote() которая выполняет автоматическую изоляцию всех специальных символов регулярных выражений, как показано в строке 1. Если поставить echo() $punctuation после первой строки, то вы должны увидеть \(\)\.-.
* В строке 2 из телефонного номера убираются все знаки пунктуации. Функция preg_replace() заменяет все символы из $punctuation — операторы из набора [ ] - пустой строкой, эффективно устраняя такие символы. Возвращаемая новая строка присваивается переменной $number.
* В строке 4 определен шаблон верифицируемого телефонного номера США.
* Строка 5 реализует сопоставление, сравнивая телефонный номер, который теперь состоит только из цифр, с шаблоном. Функция preg_match() возвращает 1, если есть совпадение. Если совпадения нет, функция preg_match() возвращает нулевое значение. Если во время обработки возникла ошибка, то функция возвращает значение False (ложно). Таким образом, чтобы проверить удачное завершение, необходимо посмотреть, было ли возвращено значение 1. В противном случае проверьте итоговое значение функции preg_last_error() (если используется PHP версии 5.2.0 или выше). Если оно не равно нулю, то, возможно, был превышен лимит вычислений, например, разрешенная глубина рекурсии регулярного выражения. Обсуждение констант и ограничений, применяемых в регулярных выражениях PHP, представлено на странице, посвященной функциям регулярных выражений PCRE (см. раздел Ресурсы).
Извлечение данных
Во многих случаях необходимо только получить ответ на вопрос: "Соответствуют ли данные шаблону?" – например, при проверке данных. Однако чаще регулярные выражения используются для подтверждения соответствия и получения информации о совпадении.
Вернемся к примеру с телефонным номером. Пусть при соответствии шаблону нам необходимо сохранить код, префикс и номер линии в отдельных полях базы данных. Регулярные выражения могут запоминать совпадающие с шаблоном данные с помощью оператора capture. Оператор capture обозначается круглыми скобками и может использоваться в любой части регулярного выражения. Операции capture можно делать вложенными для поиска подсегментов в извлеченных сегментах данных. Например, чтобы из 10-значного номера телефона извлечь код города, префикс и номер линии, можно использовать следующую строку:
/([2-9][0-9]{2})([2-9][0-9]{2})([0-9]{4})/
Если входные данные соответствуют шаблону, первые три цифры захватываются первой парой круглых скобок, следующие три цифры - второй парой, а последние 4 цифры - последним оператором. Модификация вызова функции preg_match() возвращает извлеченные данные.
Листинг 5. Возврат извлеченных данных функцией preg_match()
Если в качестве третьего аргумента функции preg_match() указать переменную, например, в нашем коде, $matches, то в качестве ее значения будет выступать список извлеченных результатов. Нулевой элемент списка (с индексом 0) - это все совпадение целиком; первый элемент - совпадение, относящееся к первой паре круглых скобок, и так далее.
Вложенные операторы capture извлекают сегменты и подсегменты фактически любой глубины. Сложность с вложенными операторами capture состоит в том, чтобы определить, в какой части массива соответствий находится каждое соответствие, например, $matches. Действует следующее правило: подсчитайте порядковый номер открывающей скобки в регулярном выражении — этот номер и будет индексом нужного совпадения в массиве соответствий.
В листинге 6 показан пример (немного надуманный) извлечения частей городского адреса.
Листинг 6. Код для извлечения городского адреса
Опять все совпадение целиком хранится по индексу 0. А где хранится номер улицы? Если считать слева направо, номер улицы проверяется \d+. Это вторая открывающая круглая скобка слева, следовательно, значением $matches[2] будет 123. В $matches[4] оказывается название города, а в $matches[6] - почтовый индекс.
Продвинутые технологии
Обработка текста – широко распространенная задача, и PHP предоставляет ряд функций, упрощающих выполнение большого числа операций. Обратите внимание на следующее:
* Функция preg_replace() может работать как с одной строкой, так и с массивом строк. Если вызвать preg_replace() для массива строк, замена будет выполнена во всех элементах массива. В этом случае код preg_replace() возвращает массив измененных строк.
* Как и во всех остальных реализациях PCRE, здесь для осуществления замены можно прибегать к сравнению с вложенным шаблоном. Для наглядности давайте рассмотрим проблему стандартизации формата телефонного номера. Заменим все знаки пунктуации точками. Наше решение показано в листинге 7.
Листинг 7. Замена знаков пунктуации точками
Сопоставление с шаблоном и, в случае совпадения, перевод в стандартный телефонный номер выполняется за один шаг.
Извлечение изображения из BLOB-поля таблицы dBASE или Paradox -- без первой записи изображения в файл -- простейший процесс использования метода Assign для сохранения содержимого BLOB-поля в объекте, имеющим тип TBitmap. Отдельный объект TBitmap или свойство Bitmap объекта Picture, в свою очередь являющегося свойством компонента TIMage, могут служить примером совместимой цели для данной операции.
Вот пример кода, демонстрирующего использование метода Assign для копирования изображения из BLOB-поля в компонент TImage.
В данном примере, объект Table1Bitmap типа TBLOBField - BLOB-поле таблицы dBASE. Данный TBLOBField-объекты был создан с помощью редактора полей (Fields Editor). Если редактор полей для создания TFields для полей таблицы не используется, получить доступ к полям можно с помощью метода FieldByName или свойства Fields, оба они являются членами компонентов TTable или TQuery. В случае ссылки на BLOB-поле таблицы с помощью одного из приведенных членов, перед использованием метода Assign указатель на поле должен быть прежде приведен к типу объекта TBLOBField. Для примера:
Изображение, хранящееся в BLOB-поле, может быть скопировано непосредственно в отдельный TBitmap объект. Ниже приведен пример, демонстрирующий создание объекта TBitmap и сохранения в нем изображения из BLOB-поля.
Из приложений Delphi вы можете получить доступ к .MDB-файлам Microsoft Access, используя драйверы ODBC. Delphi действительно может дать все необходимое, но некоторые вещи не столь очевидные. Вот шаги для достижения вашей цели.
Что вам нужно: Первое: проверьте, установлен ли ODBC Administrator (файл ODBCADM.EXE в WINDOWS\SYSTEM, вам также необходим файл DBCINST.DLL для установки новых драйверов и ODBC.DLL). Администратор ODBC должен присутствовать в Панели Управления в виде иконки ODBC. Если у вас его не было, то после установки Delphi он должен появиться. Если вы получаете сообщение типа "Your ODBC is not up-to-date IDAPI needs ODBC greater then 2.0", у вас имеется старая версия администратора и вы должны обновить ее до версии, включенной в поставку Delphi. Проверьте, имеете ли вы доступ к драйверу Access ODBC, установленному в Windows. Вы можете сделать это, щелкнув на "Drivers" в диалоговом окне "Data Sources", появляющемся при запуске ODBC Administrator. Delphi должна в диалоге добавить пункты Access Files (*.mdb) и Access Data (*.mdb), работающие с файлами Access 1.10 и использующие драйвер SIMBA.DLL (имейте в виду, что для данного DLL необходимы также файлы RED110.DLL и SIMADMIN.DLL, устанавливаемые для вас Delphi). Данные файлы должны поставляться с дистрибутивом вашей программы как часть ReportSmith Runtime библиотеки. Если вы хотите работать с файлами Access 2.0 или 2.5, вам необходимо иметь другой набор драйверов от Microsoft. Ключевой файл - MSAJT200.DLL, также необходимы файлы MSJETERR.DLL и MSJETINT.DLL. В США набор ODBC Desktop Drivers, Version 2.0. стоит $10.25. Он также доступен в январском выпуске MSDN, Level 2 (Development Platform) CD4 \ODBC\X86 как часть ODBC 2.1 SDK. Очевидно есть обновление этих драйверов для файлов Access 2.5 на форуме MSACCESS CompuServe. Имейте в виду, что драйвер Access ODBC, поставляемый с некоторыми приложениями Microsoft (например, MS Office) могут использоваться только другими MS-приложениями. К сожалению, они могут сыграть с вами злую шутку: сначала заработать, а потом отказать в совершенно неподходящий момент! Поэтому не обращайте внимания (запретите себе обращать внимание!) на строчку "Access 2.0 for MS Office (*.mdb)" в списке драйверов ODBC Administrator. Вы можете установить новые ODBC драйверы с помощью ODBC Administrator в Панели Управления.
Добавление источника данных ODBC (Data Source): если у вас имеются все необходимые файлы, можете начинать. Представленный здесь пример использует драйвер Access 1.10, обеспечиваемый Delphi. Используя ODBC Administrator, установите источник данных для ваших файлов Access: щелчок на кнопке "Add" в окне "data sources" выведет диалог "Add Data Source", выберите Access Files (*.mdb) (или что-либо подходящее, в зависимости от установленных драйверов). В диалоге "ODBC Microsoft Access Setup" необходимо ввести имя в поле "Data Source Name". В данном примере мы используем "My Test". Введите описание "Data Source" в поле Description. Щелкните на "Select Database" для открытия диалога "Select Database". Перейдите в директорию, где хранятся ваши Access .MDB-файлы и выберите один. Мы выберем файл TEST.MDB в директории C:\DELPROJ\ACCESS. Нажмите OK в диалоге "Setup". Теперь в списке источников данных (Data Sources) должен появиться "My Test" (Access Files *.mdb). Нажмите Close для выхода из ODBC Administrator. Используя этот метод, вы можете установить и другие, необходимые вам, источники данных.
Настройка Borland Database Engine: загрузите теперь Borland Database Engine (BDE) Configuration Utility. На странице "Drivers" щелкните на кнопке New ODBC Driver. Имейте в виду, что это добавит драйвер Access в BDE и полностью отдельное управление дополнительно к драйверам Access в Windows, устанавливаемым при помощи ODBC Administrator. В открывшемся диалоге Add ODBC Driver в верхнем поле редактировании введите ACCESS (или что-то типа этого). BDE автоматически добавит на первое место ODBC_. В combobox, расположенном немного ниже, выберите Access Files (*.mdb). Выберите Data Source в следующем combobox (Default Data Source Name), это должен быть источник данных, который вы установили с помощью ODBC Administration Utility. Здесь можно не беспокоиться о вашем выборе, поскольку позднее это можно изменить (позже вы узнаете как это можно сделать). Нажмите OK. После установки драйвера BDE, вы можете использовать его более чем с одним источником данных ODBC, применяя различные псевдонимы (Alias) для каждого ODBC Data Source. Для установки псевдонима переключитесь на страницу "Aliases" и нажмите на кнопку "New Alias". В диалоговом окне "Add New Alias" введите необходимое имя псевдонима в поле "Alias Name". В нашем примере мы используем MY_TEST (не забывайте, что пробелы в псевдониме недопустимы). В combobox Alias Type выберите имя ODBC-драйвера, который вы только что создали (в нашем случае ODBC_ACCESS). Нажмите OK. Если вы имеете более одного ODBC Data Source, измените параметр ODBC DSN ("DSN" = "Data Source Name") в списке "Parameters" псевдонима на подходящий источник данных ODBC Data Source, как установлено в ODBC Administrator. Имейте в виду, что вы не должны ничего добавлять в параметр Path (путь), так как ODBC Data Source уже имеет эту информацию. Если вы добавляете параметр Path, убедитесь, что путь правильный, в противном случае ничего работать не будет! Теперь сохраните конфигурацию BDE, выбирая пункты меню File|Save, и выходите из Database Engine Configuration Utility.
В Delphi: Создайте новый проект и расположите на форме компоненты Table и DataSource из вкладки Data Access палитры компонентов. Затем из вкладки Data Controls выберите компонент DBGrid и также расположите его на форме. В Table, в Инспекторе Объектов, назначьте свойству DatabaseName псевдоним MY_TEST, установленный нами в BDE Configuration Utility. Теперь спуститесь ниже и раскройте список TableName. Вас попросят зарегистрироваться в базе данных Access MY_TEST. Обратите внимание, что если бюджет не установлен, то User Name и Password можно не заполнять, просто нажмите на кнопку OK. После некоторой паузы раскроется список, содержащий доступные таблицы для ODBC Data Source указанного псевдонима BDE. Выберите TEST. В DataSource, в Инспекторе Объектов, назначьте свойству DataSet таблицу Table1. В DBGrid, также в Инспекторе Объектов, назначьте свойству DataSource значение DataSource1. Возвратитесь к таблице, и в том же Инспекторе Объектов установите свойство Active в True. Данные из таблицы TEST отобразятся в табличной сетке. Это все! Одну вещь все-таки стоит упомянуть: если вы создаете приложение, использующее таблицы Access и запускаете его из-под Delphi IDE, то при попытке изменения данных в таблице(ах) вы получите ошибку. Если же вы запустите скомпилированный .EXE-файл вне Delphi (предварительно Delphi закрыв), то все будет ОК. Сообщения об ошибках ODBC, к несчастью, очень туманные и бывает достаточно трудно понять его источник в вашем приложении, в этом случае проверьте установку ODBC Administrator и BDE Configuration Utility, они также могут помочь понять источник ошибки. Для получения дополнительной информации обратитесь к ODBC 2.0 Programmer's Reference или SDK Guide от Microsoft Press (ISBN 1-55615-658-8, цена в США составляет $24.95). В этом документе вы получите исчерпывающую информацию о возможных ошибках при использовании Access-файлов посредством ODBC. Также здесь вы можете найти рапорты пользователей о найденных ошибках, в том числе и при использовании Delphi. Более того, я выяснил, что большинство описанных проблем возникает при неправильных настройках ODBC, т.е. те шаги, которые я описал выше. Надеюсь, что с развитием технологии доступа к базам данных такие сложности уйдут в прошлое. Кроме того, имейте в виду, что если вам необходимо создать новую таблицу Access 1.10, вы можете воспользоваться Database Desktop, включаемый в поставку Delphi.
Авторы данной технологии Ralph Friedman (CompuServe 100064,3102), Bob Swart и Chris Frizelle.
Взято из Советов по Delphi от Валентина Озерова
--------------------------------------------------------------------------------
Может кто-нибудь, предпочтительно из персонала Borland, ПОЖАЛУЙСТА, дать мне ПОЛНЫЙ рассказ о том, как с помощью Delphi и сопутствующего программного обеспечения получить доступ и работать с базами данных MS Access. Среди прочего, мне необходимо узнать...
Нижеследующая инструкция в точности повторяет ту технологию, с которой я работаю на данный момент, надеюсь, что это поможет.
Драйвер ODBC, предусмотренный для доступа к Access 2.0, разработан только для работы в пределах среды Microsoft Office. Для работы со связкой ODBC/Access в Delphi, вам необходим Microsoft ODBC Desktop Driver kit, part# 273-054-030, доступный через Microsoft Direct за $10.25US (если вы живете не в США, воспользуйтесь службой WINEXT). Он также доступен в январском выпуске MSDN, Level 2 (Development Platform) CD4 \ODBC\X86 как часть ODBC 2.1 SDK. Имейте в виду, что смена драйверов (в частности Desktop Drivers) может негативно сказаться на работе других приложений Microsoft. Для информации (и замечаний) обращайтесь в форум WINEXT.
Также вам необходимы следующие файлы ODBC:
Минимум:
ODBC.DLL 03.10.1994, Версия 2.00.1510
ODBCINST.DLL 03.10.1994, Версия 2.00.1510
ODBCINST.HLP 11.08.1993
ODBCADM.EXE 11.08.1993, Версия 1.02.3129
Рекомендуется:
ODBC.DLL 12.07.1994, Версия 2.10.2401
ODBCINST.DLL 12.07.1994, Версия 2.10.2401
ODBCINST.HLP 12.07.1994
ODBCADM.EXE 12.07.1994, Версия 2.10.2309
Нижеследующие шаги приведут вас к искомой цели:
1. Используя администратора ODBC, установите источник данных (datasource) для вашей базы данных. Не забудьте задать путь к вашему mdb-файлу. Для нашего примера создайте источник с именем MYDSN.
2. Загрузите утилиту BDE Configuration.
3. Выберите пункт "New Driver".
4. Назначьте драйверу имя (в нашем случае ODBC_MYDSN).
5. В выпадающем списке драйверов выберите "Microsoft Access Driver (*.mdb)
6. В выпадающем списке имен выберите MYDSN
7. Перейдите на страницу "Alias" (псевдонимы).
8. Выберите "New Alias" (новый псевдоним).
9. Введите MYDSN в поле имени.
10. Для Alias Type (тип псевдонима) выберите ODBC_MYDSN.
11. На форме Delphi разместите компоненты DataSource, Table, и DBGrid.
12. Установите DBGrid1.DataSource на DataSource1.
13. Установите DataSource1.DataSet на Table1.
14. Установите Table1.DatabaseName на MYDSN.
15. В свойстве TableName компонента Table1 щелкните на стрелочку "вниз" и вы увидите диалог "Login". Нажмите OK и после короткой паузы вы увидите список всех имен ваших таблиц. Выберите одно.
16. Установите свойство Active Table1 в True и данные вашей таблицы появятся в табличной сетке.
С появлением и продвижением микрософтом OLE DB и реализацией в Дельфи ADO (начиная с версии 5.0) работа с MS Access через ODBC перестала быть актуальной. За исключением особых случаев рекомендуется пользоваться именно ADO линейкой компонентов для связи с MS Access
Многие мои друзья и знакомые часто спрашивают меня о том, как устроен мой сайт, сколько у меня таблиц в базе данных, как я храню данные и по каким полям веду поиск. Я, конечно, не выдаю все свои государственные тайны, но всегда понимаю причину таких вопросов и пытаюсь помочь людям построить быструю и надежную базу данных - т.е. тщательно продумать структуру БД таким образом, чтобы при увеличении нагрузки или объема таблиц динамический веб-сайт не превратился в тормозное усмертие.
А ведь многие новички (веб-строители) даже не догадываются о том, что крупные динамические сайты тормозят вовсе не из-за нагрузки скриптов на процессор, а в основном из-за неоптимизированного или дохленького MySQL-сервера. При этом во многом все зависит от того, как устроена ваша база данных.
Итак, начнем ликбез. Сразу всем вопрос: что делает MySQL во время записи в таблицы типа INSERT или UPDATE? Правильно - БЛОКИРУЕТ ТАБЛИЦЫ и пишет в них данные. Скорость записи и поиска может быть достаточно низкой, поэтому статус таблиц запрещает другим процессам считывать из них данные до окончания операции записи или обновления и снятия блокировки. При этом может получиться так, что во время записи единственного поля в длинные таблицы, ваш MySQL-сервер надолго заблокирует доступ к таблице остальным скриптам.
Например, вы создали таблицу новостей такого типа:
ID - номер, первичный ключ TEMA - тема новости MESS - сообщение, сама новость VIEWS - количество просмотров
При каждом обращении к новостям, скрипт будет выводить саму новость, а потом увеличивать поле VIEWS запросом UPDATE table 'NEWS' set VIEWS=VIEWS+1 where id=ID. При этом количество апдейтов будет довольно высоким. При высокой посещаемости веб-ресурса или при "нападении" на сайт поискового робота (эти ребята страдают многопоточностью и могут запросто повесить ваш сайт своими запросами) несколько одновременных процессов станут пытаться сделать UPDATE и SELECT. При каждом UPDATE таблица будет блокироваться (на это уходит время) и все остальные процессы будут ждать завершения операции. А если таблица достаточно большая? Например, несколько тысяч записей. Ежу понятно, что построится очередь из нескольких десятков скриптов, ожидающих ответа MySQL-сервера. Каждый будет жрать память и держать остальные процессы. В итоге все у вас зависнет и переглючит. Выход: делать вместо одной таблицы несколько. Советую разделять поля по типу их использования. Одну таблицу - только для вывода и редких обновлений или вставок. Другую - для частых обновлений, но редкого вывода. Например, значения счетчика обращений держать отдельно в таблицу вида:
ID - номер, первичный ключ VIEWS - количество просмотров
Сами новости лучше держать в другой таблице, где нет поля VIEWS. При этом таблица с новостями будет тяжелой (много текста, полей, индексов), а таблица COUNT (счетчик) будет очень легкой и быстрой. Таблица NEWS будет кешироваться и выводиться очень быстро при любых объемах, а таблица COUNT будет быстро обновляться из-за того, что она очень легкая (всего два целочисленных поля). Разделение данных по нескольким таблицам существенно ускоряет работу MySQL-сервера. Гораздо быстрее работают несколько мелких запросов по каждой таблице, чем один длинный запрос по одной или нескольким таблицам. Имейте это в виду, чтобы спать спокойно.
Дальше - круче. Чтобы не блокировать лишний раз свои таблицы используйте при вставках директиву DELAYED. Пример: INSERT DELAYED into STAT (ID,IP,UTIME) values (null,$ip,NOW()). Он позволяет серверу ответвлять поток в режиме ожидания, а саму вставку производить тогда, когда сервер освободится от других запросов или поступит следующий аналогичный INSERT DELAYED. Обычно отложенный метод подходит для любых операций с кумулятивными таблицами (когда в основном идут INSERTы, а данные копятся, а не модифицируются), при которых не особо важно когда именно подействуют изменения - мгновенно или через несколько секунд, минут. Например, если хотите собирать IPадреса своих посетителей, УРЛы, по которым они ходят или страницы, откуда пришли, время. При добавлении с задержкой скрипт отработает почти мгновенно, еще до выполнения операции.
Операция UPDATE идет в три этапа: поиск того, что будете менять, затем запись данных, обновление индексов. При этом, чем больше таблица, тем дольше поиск. Если есть индексы, то операция кешируется и выполняется достаточно быстро. Но сам процесс очень емкий. И только дурак не догонит, что большая таблица со множеством индексов и записей, будет тормозить при UPDATE. INSERT же выполняется одним залпом, очень быстро. Поэтому обычно используют аддитивные записи (вставками INSERT) во временные таблицы, потом блокируют основные талицы, суммируют обновления, и плюют их в основную таблицу. Получается, что в основном, главные таблицы работают только в режиме вывода, а обновления идут гораздо реже и быстрее. Например, можно копить данные о загрузках новостей во временной таблице, а по крону или иным образом обновлять счетчик каждые 10 минут (или реже). Это ускорит работу сервера.
При запросах SELECT * FROM таблица скрипт получит все поля данной таблицы. А нужно ли это? Использование * ведет к лишнему расходу ресурсов. Гораздо эффективнее использовать точные названия полей, которые нужны скрипту. Например: SELECT id,name FROM таблица. При таком запросе передача займет меньше времени и понадобится меньше ресурсов. Старайтесь ограничивать вывод при помощи директивы LIMIT. Это также ускоряет вывод.
Поиск по БД идет быстрее если вместо LIKE '%слово%', ставить 'слово%'. Операции с шаблонами регулярных выражений кешируются только в том случае, если в начале отсутствует символ %. Поэтому при построении поисковых запросов с LIKE избегайте начинающих символов %.
При построении таблиц для наиболее используемых полей (при поиске, сортировке и т.д.) обязательно создавайте индексы. Без индексов таблицы будут сильно тормозить. Индексы служат для кеширования и позволяют существенно ускорить вывод данных из таблиц. При этом таблицы будут занимать больше места на диске и в памяти. Но это в наше время не проблема.
Используйте надлежащий тип полей для своих записей. Тип TINYINT занимает 1 байт - самый быстрый. Таблицы с MEDIUMINT быстрее таблиц с INT. Если ставить полям свойство NOT NULL, то в целом их работа будет быстрее. VARCHAR медленее CHAR, поэтому таблицы переменной длины (где есть тип VARCHAR или TEXT) занимают меньше дискового пространства, но работают медленнее.
По своему опыту скажу, что для большинства сайтов подходят изложенные советы по работе с MySQL. Чтобы еще больше ускорить свой сервер, советую частоиспользуемые операции проводить по крону выделенными процессами и писать данные в различные файлы. Например, раз в 20 минут запускать скрипт, который будет создавать файл с новостями. Или например, генерить файл с новостями при их добавлениях или обновлениях. Таким образом, вы экономите на каждом обращении к БД. Интерактивность при этом не теряется, а производительность увеличивается во много раз. Особенно, повторяю, при высокой посещаемости ресурса. Старайтесь отделить интерактивные операции от фоновых. Например, на ПротоПлексе работает один интерактивный движок, но в фоне по заданиям трудятся с десяток различных роботов, которые генерируют часто вызываемые страницы, рассылают письма и т.д. Крупный сайт - это не только то, что вы видите, но и бек-енд (обратная сторона). В фоновом режиме можно быстро и эффективно готовить контент, освобождая основной движок от лишней работы.
В общем, основы должны быть всем понятны. Дробите все на мелочи, будь то запросы, таблицы или операции. Структура БД должна быть такой, чтобы не выполнялось ничего лишнего. Регулярно проводите OPTIMIZE на таблицах с переменной длиной, особенно, если в них идут удаления записей. Тестируйте свои запросы на скорость, упрощайте их.
Часто программисту приходится сталкиваться с задачей написания приложения, работающего в фоновом режиме и не нуждающегося в месте на Панели задач. Если вы посмотрите на правый нижний угол рабочего стола windows, то наверняка найдете там приложения, для которых эта проблема решена: часы, переключатель раскладок клавиатуры, регулятор громкости и т. п. Ясно, что, как бы вы не увеличивали и не уменьшали формы своего приложения, попасть туда обычным путем не удастся. Способ для этого предоставляет shell api.
Те картинки, которые находятся на system tray — это действительно просто картинки, а не свернутые окна. Они управляются и располагаются панелью system tray. Она же берет на себя еще две функции: показ подсказки для каждого из значков и оповещение приложения, создавшего значок, обо всех перемещениях мыши над ним.
Весь api system tray состоит из 1 (одной) функции:
Код:
Параметр dwmessage определяет одну из операций: nim_add означает добавление значка в область, nim_delete — удаление, nim_modify — изменение.
Ход операции зависит от того, какие поля структуры tnotifyicondata будут заполнены.
Обязательным для заполнения является поле cbsize — там содержится размер структуры. Поле wnd должно содержать дескриптор окна, которое будет оповещаться о событиях, связанных со значком.
Идентификатор сообщения windows, которое вы хотите получать от системы о перемещениях мыши над значком, запишите в поле ucallbackmessage. Если вы хотите, чтобы при этих перемещениях над вашим значком показывалась подсказка, то задайте ее текст в поле sztip. В поле uid задается номер значка — каждое приложение может поместить на system tray сколько угодно значков. Дальнейшие операции вы будете производить, задавая этот номер. Дескриптор помещаемого значка должен быть задан в поле hicon. Здесь вы можете задать значок, связанный с вашим приложением, или загрузить свой — из ресурсов.
Примечание
Изменить главный значок приложения можно в диалоговом окне project/ options на странице application. Он будет доступен через свойство application.icon. Тут же можно отредактировать и строку для подсказки — свойство application.title.
Наконец, в поле uflags вы должны сообщить системе, что именно вы от нее хотите, или, другими словами, какие из полей hicon, ucallbackmessage и sztip вы на самом деле заполнили. В этом поле предусмотрена комбинация трех флагов: nif_icon, nif_message и nif_tip. Вы можете заполнить, скажем, поле sztip, но если вы при этом не установили флаг nif_tip, созданный вами значок не будет иметь строки с подсказкой.
Два приведенных ниже метода иллюстрируют сказанное. Первый из них создает значок на system tray, а второй — уничтожает его.
Код:
Примечание
he забывайте уничтожать созданные вами значки на system tray. Это не делается автоматически даже при закрытии приложения. Значок будет удален только после перезагрузки системы.
Сообщение, задаваемое в поле ucallbackmessage, по сути дела является единственной ниточкой, связывающей вас со значком после его создания. Оно объединяет в себе несколько сообщений. Когда к вам пришло такое сообщение (в примере, рассмотренном выше, оно имеет идентификатор wm_mytraynotify), поля в переданной в обработчик структуре типа tmessage распределены так. Параметр wparam содержит номер значка (тот самый, что задавался в поле uid при его создании), а параметр lparam — идентификатор сообщения от мыши, вроде wm_mousemove, wm_lbuttondown и т. п. К сожалению, остальная информация из этих сообщений теряется.
Координаты мыши в момент события придется узнать, вызвав функцию api getcursorpos:
Код:
Обратите внимание, что при показе всплывающего меню недостаточно просто вызвать метод popup. При этом нужно вынести главную форму приложения на передний план, в противном случае она не получит сообщений от меню.
Теперь решим еще две задачи. Во-первых, как сделать, чтобы приложение минимизировалось не на Панель задач (taskbar), а на system tray? И более того — как сразу запустить его в минимизированном виде, а показывать главную форму только по наступлении определенного события (приходу почты, наступлению определенного времени и т. п.).
Ответ на первый вопрос очевиден. Если минимизировать не только окно главной формы приложения (application.mainform.handle), но и окно приложения (application.handle), то приложение полностью исчезнет "с экранов радаров". В этот самый момент нужно создать значок на панели system tray. В его всплывающем меню должен быть пункт, при выборе которого оба окна восстанавливаются, а значок удаляется.
Чтобы приложение запустилось сразу в минимизированном виде и без главной формы, следует к вышесказанному добавить установку свойства application.showmainform в значение false. Здесь возникает одна сложность — если главная форма создавалась в невидимом состоянии, ее компоненты будут также созданы невидимыми. Поэтому при первом ее показе установим их свойство visible в значение true. Чтобы не повторять это дважды, установим флаг — глобальную переменную shownonce:
Код:
Теперь у вас в руках полноценный набор средств для работы с панелью system tray.
В заключение необходимо добавить, что все описанное реализуется не в операционной системе, а в оболочке ОС — Проводнике (explorer). В принципе, и windows nt 4/2000, и windows 95/98 допускают замену оболочки ОС на другие, например dashboard или lightstep. Там функции панели system tray могут быть не реализованы или реализованы через другие api. Впрочем, случаи замены оболочки достаточно редки.
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.
В этой статье описываются полезные функции и процедуры, помогающие эффективно работать с различными типами данных в системе "1С:Предприятие 7.7".
* Обработка значений
* Форматирование
* Список значений
* Таблица значений
* Таблица
* Период и дата
* Календари и праздники
* Справочники
* Документы
* Предопределённые функции
* Налоговый учёт
Обработка значений в 1С
Форматирование данных в 1С
Список значений в 1С
Таблица значений в 1С
Таблица или печатная форма в 1С
Периоды и даты в 1С
Календари и праздники в 1С
Справочники в 1С
Документы в 1С
Предопределённые функции и процедуры в 1С
Налоговый учёт и первое событие в 1С
Резюме
В статье описаны функции и процедуры, используемые в программе "1С:Предприятие 7.7" для работы со справочниками, документами, списками значений, таблицами значений и с прочими агрегатными типами данных. Образцы практического применения описанных средств Вы сможете найти в статьях "Отчёты для 1С" и "Обработки для 1С".
Мне приходится часто менять клиентов, потому что работаю удаленно. Сделал одному – иди к другому. А еще я продаю свои программы через Интернет. При имеющейся специфике работы, заметил одну странность: примерно в двадцати пяти процентов случаев, предприятие, оплатившее работу программиста и принявшее его работу, не пользуется ею.
Начну с примеров
Фирма, продающая компьютеры, купили внушительный комплект программного обеспечения, все своевременно оплатили, купили необходимое торговое оборудование... Мы, соответственно, все им установили и приготовились запускать. Остановились на этапе, когда сотрудники фирмы, ответственные за ввод в эксплуатацию нового программного комплекса, должны внести в информацию по имеющимся в отделах остаткам. Для справки – это примерно пара сотен наименований. Но на этом все работы по проекту остановились, потому что остатки не были внесены к намеченному сроку, ни через неделю после срока, ни через месяц. Не внесены они и до сих пор, хотя прошло уже пол года. Официально мы договорились, что клиент нам позвонит, когда сотрудники освободятся и найдут время внести остатки. Сами понимаете, на небольших фирмах менеджеры – по совместительству еще и продавцы, еще и грузчики, и кассиры…
Еще пример
Достаточно крупный комбинат решил автоматизировать учет обедов собственным сотрудникам в счет зарплаты. Систему подготовили, протестировали, поставили. Обучили их специалиста. Все как обычно. Недавно узнал, что конечный пользователь нашу систему не использует. Оказывается, по весьма банальной причине: на приобретение нового компьютера руководство не выделяет средств, а на имеющемся оказалось недостаточно мощности. В свое время мы указывали им на необходимость более мощного компьютера, но в силу не совсем понятных мне внутренних интриг, этот вопрос был замят на уровне IT-отдела. В результате, автоматизация стала не эффективной, и от использования новой программы решено было отказаться.
Третий пример
Производственная фирма заказала автоматизацию учета. От фирмы был назначен специалист – постановщик ТЗ и в будущем - внедренец. Работу сделали, сдали, провели обучение внедренца (на углубленное внедрение и обучение нами всех сотрудников не выделили бюджет). Я перезвонил клиенту через пол года, чтобы узнать, не было ли замечено каких-либо багов в работе системы. С удивлением услышал, что учет по-прежнему ведется в Excel-е, потому что на глубокое, самостоятельное освоение новой системы у сотрудников нет времени, а специалист, которого мы обучали, уволился…
Хотелось бы обобщить имеющийся, скромный опыт по таким случаям, и порассуждать на тему, когда автоматизация учета становится не эффективной по вине заказчика.
Уже из приведенных примеров можно сделать одно важное заключение: во всех трех случаях явно, что администрация не была заинтересована в результате. В первом – директор не захотел останавливать продажи даже не день, чтобы довести начатое до конца, во втором и третьем был урезан бюджет, и решили сэкономить там, где этого делать было нельзя.
1. Незаинтересованность руководства в результатах
Для меня всегда было загадкой, зачем руководство той или иной фирмы вообще тратится на автоматизацию, если отчетов в excel-е достаточно, и нет желания доводить начатое до конца? Чего дирекция хочет добиться? Дань моде? Надоел ноющий главбух? Решили, что что-то пора менять, но что менять – не выяснили? Стоит напомнить, что грамотно поставленная автоматизация учета в торгово-производственных фирмах способна увеличить прибыль и уменьшить затраты. Хорошая автоматизация окупается достаточно быстро, и уже скоро начинает приносить прибыль и экономию. Но если руководство не оценило перспектив автоматизации или, что еще хуже, считает, что новый стол из красного дерева топ-менеджеру важнее нового сервера сисадмину, то вряд ли на такой фирме автоматизация будет успешной.
2. Ограниченный бюджет
Как правило, из первого следует второе. Когда руководство не совсем отдает себе отчет в том, чего они ждут от автоматизации, тогда возникают идеи, наподобие: «а давайте пригласим студента, и он все сделает, как надо», или «давайте посадим главбуха на сервер»... Я, конечно, не против подработки студентов и не сомневаюсь в потенциале российского студенчества, но хочу лишь сказать о том, что для внедрения серьезной системы учета простого умения программировать очень мало. Хороший внедренец должен уметь просчитать возможные последствия выбора той или иной стратегии автоматизации. Это достаточно кропотливая работа, требующая, прежде всего, большого практического опыта, понимание не только специфики учета предприятия, но и его неочевидных нюансов. В конце концов, такая работа требует настойчивости, потому что часто решения внедренцев могут встретить сопротивление со стороны заказчика, и нужно уметь отстоять свои предложения, основываясь, опять же, на собственном опыте, защищая интересы сопротивляющегося клиента. Вряд ли какой-либо студент, понимающий, что занимается временным, не свойственным ему делом, способен на такое. Поэтому, считаю, что экономия на уровне исполнителя – это почти гарантия неудавшейся автоматизации.
Это же относится и к неоправданной экономии на оборудовании. Как правило, сбой системы происходит в самом слабом ее звене и в самый неподходящий момент… Помню, как у одного моего клиента, смотрящего «сквозь пальцы» на предложение обновить сервер, этот сервер вдруг однажды сгорел, когда бухгалтерия делала годовой отчет. Печально было то, что архивирование данных не велось должным образом, опять же, не смотря на рекомендации: директор считал покупку пишущего cd-room (в то время) – не особенно необходимыми затратами. Систему, конечно, восстановили. Но я помню, как бухгалтерии пришлось две недели работать чуть ли не по ночам, чтобы восстановить потерянные за год данные по первичным документам. Кстати, после этого случая руководство все-таки купило в то время жутко дорогой сервер с райд-массивом…
3. Тендер на откатах
Где-то встречал в сети примерную статистику, какой процент тендеров на IT услуги в России выигрывается за счет откатов ответственному лицу. Статистика – не утешительна. Печально, что на откаты попадают в основном крупные заказчики, где сумма договора внушительна, и руководство напрямую не занимается подбором исполнителя, а поручает это собственному специалисту, который не всегда бывает доволен уровнем своей заработной платы. Практика показывает, что при таком раскладе, все работы бывают выполнены в срок, все документы подписаны, но сотрудники фирмы остаются недовольны результатами и не могут использовать внедренную систему в планируемом объеме по разным причинам. Соответственно, руководство не имеет требуемой аналитической базы и начинает выяснять, в чем причина. Такие разбирательства затягиваются надолго, часто сопровождаются кадровыми движениями и, в конечном итоге, поисками того, кто бы систему довел до ума…
4. К вопросу о лидерах отрасли
Хотел бы привести еще один пример, достаточно типичный. Фирма готова тратить деньги на автоматизацию, но не сориентировалась на рынке IT-услуг и обратилась к кому-то очень известному. В результате затраты превысили все разумные пределы, а итог оказался не совсем ожидаемым, хотя, возможно, приемлемым с натяжкой.
К сожалению, это только при покупке автомобиля можно руководствоваться рекламными буклетами, и, если позволяют средства, выбирать самое последнее из модельного ряда. В сфере IT-услуг, как показывает практика, все далеко не так, особенно в сфере автоматизации на базе продуктов фирмы «1С» фирмами-франчайзи. Если исполнитель – не на уровне масштабов компании «Intel Corporation», то его раскрученность совсем может не соответствовать качеству предлагаемых им услуг, а объемы клиентской сети, требующей постоянного сопровождения, могут не позволить заниматься новым клиентом на должном уровне. На фоне этого, стоило бы вспомнить о небольших фирмах, менее раскрученных, а потому не выигравших тендер, которые были бы просто счастливы получить крупного заказчика IT-услуг, даже с меньшей суммой договора, и были готовы отдать все силы на то, чтобы клиент остался доволен. Амбиции небольших коллективов, уровень их специалистов и заинтересованность в результатах работы часто оказываются выше, чем у раскрученных, больших компаний. Небольшие фирмы не могут допустить в работе того, что позволят себе монополии, потому что любая неудача может грозить такой фирме банкротством.
Я назвал лишь четыре, пожалуй, основных фактора, когда автоматизация не достигает результатов, и присходит это, отчасти, по вине заказчика. Наверняка, имеются и другие причины, но корень проблем, на мой взгляд, следует искать, прежде всего, в неправильной позиции руководства компании, которая выражается или в непонимании, зачем нужна автоматизация, или в неправильно выбранной стратегии решения этого вопроса. Там, где решения принимаются трезво и взвешенно, где оценивается уровень специалиста, а не его раскрученность на рынке, где руководство четко понимает, чего оно ждет от автоматизации в итоге – там все будет нормально, чего всем и желаю…