В этой статье я расскажу, как загружать данные в 1с 8 из простейших текстовых файлов с разделителями. Обычно они имеют расширение csv (Comma-Separated Values). Т. е. название подразумевает, что в каждой строке такого текстового файла значения разделены запятой. Но на самом деле, запятую, в качестве разделителя, использовать не надёжно. Поэтому применяют другие разделители, которые в обычном тексте встречаются редко. Это могут быть символы «^», «~»,«|» и другие. Итак, наша задача состоит в том, чтобы загрузить имеющуюся в csv файле информацию в базу данных 1с. Например, в файле будут содержаться товары интернет - магазина. В качестве образца, я взял выгрузку из магазина на скрипте virtuemart. Посмотрим, как выглядит файл.
Привожу две первых строки из него:
Посмотрим на файл.
Первая строка служебная. В ней описан формат нашего файла. Т. е. в какой ячейке, что находится. Однако, имейте в виду, что такой строки может и не быть.
Ячейки образуются при помощи разделителя «^», а данные в ячейках обрамляются символом «~».
В любой конфигурации 1с есть иерархический справочник товаров. В него и будем загружать информацию.
Создадим внешнюю обработку. Добавим строковый реквизит «путьКФайлуЗагрузки» для хранения имени файла. Добавим на форму поле ввода, связанное с данным реквизитом. Включим в свойствах поля ввода кнопку выбора и создадим обработчик события «НачалоВыбора» и напишем в нём такой код:
Т. о. мы организовали диалог для выбора файла в нашей обработке.
Хорошо. Теперь, для удобства и наглядности я предлагаю создать временную табличку, в которую мы загрузим текстовый файл, а уже после её заполнения - будем осуществлять загрузку в базу 1с. Для этого, на форму добавим табличное поле «табЗагрузки», с типом значения «ТаблицаЗначений» и командной панелью. В панели поместим кнопку «Заполнить» и создадим обработчик её нажатия «КоманднаяПанель1Заполнить». Также для элемента универсальности, добавим в обработку два строковых реквизита «символОграничения» и «разделительПолей». В них мы будем хранить «^», и «~». Можно в теле модуля формы осуществить их начальную инициализацию:
разделительПолей = "^";
символОграничения = "~";
Это позволит пользователю задать свои значения и при желании сохранить настройку, которая впоследствии не затрется нашей инициализацией.
Функцию разложения строки с разделителями в массив можно разместить как в одном из общих модулей, так и непосредственно в обработке.
Отлично. В итоге, после заполнения, получим примерно такую картинку:
Теперь приступим непосредственно к загрузке товаров. Рядом с кнопкой «заполнить» добавим кнопку «загрузить» и добавим обработчик её нажатия «КоманднаяПанель1Загрузить», а также добавим реквизит «ПапкаЗагрузкиВыгрузкиТоваров» с типом вашего справочника товаров для опциональной их загрузки в определенную папку. Текст обработчика будет такой:
В приведенном коде две новые функции «вернутьТовар» и «ЗаписатьЭлементСпр». Вот их текст:
И осталась последняя новая функция для обработки родителя товара вернутьРодителяТовара. Текст её смотрите ниже. Комментарии по тексту.
Обработка "Выгрузка и загрузка данных XML" (ВыгрузкаЗагрузкаДанныхXML)
Данная обработка позволяет производить обмен данными между одинаковыми (идентичными) конфигурациями на платформе 1С 8.х
Режимы работы
Обработка реализует 2 режима работы: Выгрузки (создание файла выгрузки указанных пользователем данных) и Загрузки (чтение файла выгрузки, созданного одноименным режимом, и запись имеющихся в нем данных). Установка режима осуществляется выбором в поле Режим.
Перед запуском того или иного режима (нажатие кнопки Выполнить) нужно указать имя файла выгрузки либо введя его вручную в поле "Имя файла", либо воспользовавшись кнопкой выбора этого поля и стандартным диалогом выбора файла.
В режиме загрузки имеется возможность редактирования использования итогов при записи регистров, что может повлиять на скорость загрузки.
Кнопки "Отключить итоги" и "Включить итоги" доступны при установленном флаге "Включить возможность редактирования использования итогов во время загрузки данных" и используются для ручного управления режимом использования итогов при загрузке данных.
Условия применимости обработки
Обработка может использоваться только в тех случаях, когда информационная база, в которой осуществлялась выгрузка данных, и та, в которой данные загружаются, являются однородными (конфигурации идентичны, данные могут различаться), либо все выгружаемые объекты практически полностью идентичны по составу и типам реквизитов и табличных частей, свойствам "ведущего" объекта метаданных и т.д. Следует отметить, что, в связи с указанными ограничениями, обработка главным образом предназначена для обмена между однородными ИБ.
Формат файла выгрузки отличается от формата файла, создаваемого при выгрузке по плану обмена, заголовочной частью. Для выгрузки данных (элементов справочников, наборов записей регистров и т.д.) обработкой используется тот же механизм XML-сериализации, что и выгрузкой по планам обмена, в этой части форматы файлов идентичны.
Определение состава выгрузки
Обработка позволяет осуществить как полную, так и частичную выгрузку данных информационной базы в файл. Настройка состава выгружаемых данных производится в диалоге путем установки флажков в колонке дерева, отображающего объекты метаданных, данные по которым могут быть выгружены. Дополнительная колонка флажков, "При необходимости", устанавливает необходимость выгрузки объектов данного типа "по ссылке". То есть, если флажок установлен только в колонке "При необходимости", то данные по такому объекту будут выгружаться не полностью, а только в том объеме, который необходим для поддержания ссылочной целостности в информационной базе, которая будет загружать файл выгрузки.
При открытии формы обработка устанавливает признак выгрузки по ссылке всем объектам, что гарантирует ссылочную целостность выгруженного фрагмента информационной базы.
При нажатии на кнопку "Определить объекты, выгружаемые по ссылке" обработка анализирует, ссылки на какие данные могут содержаться в объектах, у которых установлен признак полной выгрузки, и автоматически заполняет колонку флажков, индицирующих необходимость выгрузки по ссылке. Если объект уже имеет установленный флажок полной выгрузки, в таком случае флажок выгрузки по ссылке не устанавливается.
Возможные применения
Использование этой обработки возможно, например, для создания полной или частичной резервной копии данных, осуществления обмена данными между информационными базами, а также как вспомогательный инструмент при восстановлении проблемных информационных баз.
Для того чтобы прочитать файлы из ZIP-архива необходимо выполнить несколько простых действий:
- Открыть необходимый архив
- Распаковать файлы
Создание объекта ЧтениеZIPФайла можно осуществить двумя путями - создать инициализированный объект или создав неинициализированный объект вызвать у него метод Открыть(). В обоих случаях состав параметров является одинаковым. В самом простом случае требуется указать только имя архивного файла, с которым необходимо работать.
Для открытия архива требуется указать:
Имя файла, который требуется открыть. Этот параметр является обязательным.
Пароль доступа к архиву.
После того, как архив успешно открыт, можно получить информацию о файлах, хранящихся внутри него. Для этого у объекта ЧтениеZIPФайла предусмотрено свойство Элементы, которое предоставляет доступ к коллекции элементов ZIP файла.
Для каждого элемента можно получить разнообразную информацию о его имени, времени его модификации, его атрибутах, а также узнать является ли данный элемент зашифрованным.
После получения информации о элементах их можно распаковать на диск. Это возможно сделать двумя методами:
Воспользоваться методом ИзвлечьВсе().
Воспользоваться методом Извлечь().
Метод ИзвлечьВсе() распаковывает все файлы в архиву по указанному пути. Второй параметр данного метода определяет возможность восстановления исходных путей файлов.
Метод Извлечь() распаковывает указанный элемент коллекции из свойства Элементы по указанному пути. Второй параметр данного метода аналогичен тому же параметру метода ИзвлечьВсе(). Наибольший интерес представляет третий параметр данного метода - Пароль. В нем можно указать индивидуальный пароль для элемента архива, в случае если он зашифрован паролем отличным от других файлов.
После того, как архив нам больше не нужен можно завершить работу с ним вызвав метод Закрыть().
Для того чтобы записать файлы в ZIP-архив необходимо выполнить несколько простых действий:
* Создать архив с необходимыми параметрами, в который будут помещаться файлы.
* Поместить в архив необходимые файлы.
* Записать архив.
Создание объекта ЗаписьZIPФайла можно осуществить двумя путями - создать инициализированный объект или создав неинициализированный объект вызвать у него метод Открыть. В обоих случаях состав параметров является одинаковым. В самом простом случае требуется указать только имя файла, куда будет записан архив.
Для создания нового архива требуется указать:
* Имя файла, куда будет записан архив. Этот параметр является обязательным. Если такой файл уже существует на диске, он будет перезаписан!Пароль доступа к архиву. Если этот параметр пропущен или равен пустой строке, то шифрование производится не будет!
* Комментарий к архиву.
* Метод сжатия файлов в архиве. На выбор предоставляется возможность скопировать файлы в архив без сжатия или сжать их. По умолчанию файлы сжимаются.
* Уровень сжатия файлов в архиве. Можно выбирать между минимальным, оптимальным и максимальным сжатием. По умолчанию используется оптимальное сжатие
* Метод шифрования. Можно защитить архив методом шифрования ZIP 2.0, совместимым с большинством программ, или с помощью шифрования на основе новейшего стандарта AES с различной длиной ключа (128, 192 и 256 бит). Однако следует помнить, что данный метод может быть не совместим с некоторыми программами архивирования, например WinRAR.
После создания объекта необходимо добавить в него необходимые файлы, воспользовавшись методом Добавить. Он принимает на вход 3 параметра:
1. Полное имя файла или маску.
2. Режим сохранения путей к файлу. Можно сохранять полные пути, не сохранять пути совсем или сохранять пути относительно каталога. Режим обработки подкаталогов. Можно обрабатывать подкаталоги рекурсивно или не обрабатывать их. Параметр имеет смысл, если в качестве имени указана маска.
После того, как все необходимые файлы добавлены, можно записать архив на диск, воспользовавшись методом Записать().
Важно понимать, что до выполнения этого метода, никаких реальных действий по созданию архива не происходит. После записи архива на диск объект закрывает его и для работы со следующим архивом необходимо выполнить метод Открыть().
Пример:
Особенности упаковки файлов по маске
Остановимся подробнее на особенностях упаковки файлов по маске.
Предположим, что у нас есть следующий файлы, которые нам необходимо поместить в архив:
c:\ZipTest\11.xls
c:\ZipTest\12.xls
c:\ZipTest\13.xls
c:\ZipTest\MoreFiles\14.xls
c:\ZipTest\MoreFiles\15.xls
c:\ZipTest\MoreFiles\16.xls
В результирующий архив будут помещены следующие файлы:
\ZipTest\11.xls
\12.xls
\13.xls
В результирующий архив будут помещены следующие файлы:
\ZipTest\11.xls
\ZipTest\12.xls
\ZipTest\13.xls
В результирующий архив будут помещены следующие файлы:
\ZipTest\11.xls
\ZipTest\12.xls
\ZipTest\13.xls
\ZipTest\MoreFiles\14.xls
\ZipTest\MoreFiles\15.xls
\ZipTest\MoreFiles\16.xls
В современном мире люди используют Интернет не только для поиска информации, но и для приобретения каких либо товаров и услуг. Поэтому организации, например имеющие статус среднего бизнеса, стараются разместить свои прайс-листы в интернете или даже создать Интернет-магазин. Создать его не так-то просто. Если вы имеете «реальный» бизнес и используете определенную систему учета товаров (или услуг), нужно учитывать несколько немаловажных факторов:
* Каждый уважающий себя Интернет-магазин должен показывать остаток товара на складе, а также не показывать тот товар, которого уже нет в наличии. (а может быть что товар есть на разных региональных складах)
* Цены не должны расходиться с ценами в реальном магазине. Не учитывая доставку, хотя и это уже давно стало бесплатным практически везде.
Я привел только 2 факта, в действительности их может быть гораздо больше, всё зависит от того, какую цель вы ставите перед своим Интернет-проектом.
Многие организации для ведения учета товаров или оказанных услуг используют ПО «1С» и как показывает практика, большая часть организаций работает с версией 7.7, и не торопятся перейти на 8.х. так как это влечет за собой накладные расходы.
Для Реализации работы с WEB в 1С7.7 есть прекрасное решение - WEB-расширение, но оно работает только с Microsoft Internet Information Server (IIS). IIS используют не все хостинг – провайдеры, да и те кто использует вряд ли разрешат подключить свой сервер к чужой БД.
А держать «у себя» IIS сервер достаточно накладно для организаций среднего бизнеса (оборудование + интернет канал + лицензии ОС и ПО = увеличение стоимости товара).
Другое дело «свободное» ПО и ОС: Linux, Apache, PHP, MySQL. Эти четыре продукта использует большинство хостинг – провадеров, поэтому их использование как платформы для создания Интернет-проектов наиболее оптимально.
Как связать 1С 7.7 с MySQL? Можно использовать внешнюю компоненту MySQL,dll, но её использование не всегда возможно, особенно если ваш Веб-сервер находиться удаленно или вы покупаете хостинг у сторонней организации, так как не безопасно открывать доступ к БД из Интернета.
Для решения этой задачи я использовал технологию передачи данных через URL.
Возможно, звучит это немного дико, и многие подумают, что это неправильное решение. Однако эта система работает и работает достаточно хорошо и корректно.
И сейчас я бы хотел поделиться с коллегами приобретенным опытом реализации это технологии.
Кратко о принципе:
Выглядит это так: из 1С вызывается url и через него же передаются данные PHP-скрипу, который в свою очередь делает с ними все, что необходимо.
Например, нам нужно передать остаток товара на складе: из 1С должен будет сформироваться url: http://www.server.com/script.php?good=201&count=302&date=2009-06-09, где:
* http://www.server.com – адрес сервера
* script.php – исполняющий скрипт
* good=201 – переменная и код товара
* count=302 – переменная и количество остатка
* date=2009-06-09 – дата на которую передается остаток
причем для работы данной схемы достаточно лишь иметь доступ в Интернет с того компьютера на котором выполняется операция по передачи данных. (сервер БД нет необходимости подключать к Интернету)
Встреча с возможными ошибками:
Для начала хотелось бы рассказать о тех проблемах, с которыми я столкнулся и о том, как можно их наиболее эффективно решить:
1. Проблема передачи дробных чисел, а именно трудности, возникающие при использовании символа «точка» (.)
Если необходимо передать любое дробное число, то в 1С оно будет храниться виде 1.1. При передаче числа через url точка, отделяющая целую часть от дробной, вызывает ошибку, так как символ «точка» служит для разделения доменов. Следовательно, необходимо преобразовать эту самую «точку» в другой символ наиболее подходящий для этого. И этот символ - «запятая» (,). Для того чтобы осуществить это преобразование, я написал функцию, листинг которой приведен ниже:
Эта функция возвращает строку в которой все символы «.» заменены на «,» в строковой переменной Стр. Применимо это не только к числам, но и к текстовым данным.
Теперь при передаче число 1.1 будет иметь формат 1,1. Далее при получении мы должны привести это число обратно в «привычный» вид, это можно сделать на стороне PHP-скрипта функцией strtr() . краткое её описание я привел ниже:
Описание функции string strtr ( string $str , string $from , string $to ):
Эта функция возвращает строку str , в которой каждое вхождение любого символа из перечисленных в from заменено на соответствующий символ из строки to . (www.php.net)
Т.е. в нашем случае функция будет иметь вид strtr("1,1", ",", ".") и результатом её работы будет: 1.1
2. Проблема передачи даты. В 1С дата имеет вид «ДД.ММ.ГГГГ» например, 01.01.2009. При передаче такого вида данных будет вызвана такая же ошибка, как и при передаче числовых данных. Конечно, для решения и этой проблемы можно использовать указанную выше функцию ЧислоURL, но я решил пойти другим путём и конвертировал дату в формат MySQL, то есть «ГГГГ-ММ-ДД». Для этого я написал функцию МуДата, вот ее листинг:
Функция работает следующим образом – опять же выделяет из переменной Стр, Год, Месяц, Число и выстраивает их в формате ГГГГ-ММ-ДД, наиболее привычным при работе с MySQL. Об ошибках все.
Подготовка 1С:
Теперь расскажу о том, как заставить 1С работать с WEB.
Для того, чтобы иметь возможность работать с протоколом HTTP в 1С, я использовал библиотеку V7+, которая поставляется фирмой 1С и служит для расширения возможностей 1С 7.7.
Для начала необходимо подключить внешнюю компоненту (подробнее здесь), используя функцию «ЗагрузитьВнешнююКомпоненту("v7plus.dll")». Далее необходимо создать объект addin.v7httpreader, для этого я использовал переменную НТТР. А для передачи и получения данных используется метод ПолучитьКакСтроку(адрес, СтрокаДляПриёма); который получает данные в переменную СтрокаДляПриёма с адреса указанного в переменной адрес. В целом все это будет выглядеть примерно так:
Выше указанная процедура выведет в окно сообщений HTML-код заглавной страницы сайта http://www.google.ru
Таким образом, теперь мы знаем, как, из 1С, обратиться к нужному сайту, и получить его HTML-код.
Немного о PHP:
Теперь напишем PHP-скрипт, который просто будет выводить данные полученные методом GET. (ознакомиться с тем, как PHP получает данные можно здесь) Листинг такого скрипта:
Назовем его test.php и поместим в корневую папку web-сервера. Далее для проверки работы скрипта введем в адресную строку браузера http://localhost/test.php?text=hello%20wolrd В том случае, если все сделано верно, на экране появиться страница с текстом hello world.
«Соединяем» 1С и PHP:
Далее создаем в 1С внешнюю обработку и вставим в её модуль следующий код:
Отличается она от алгоритма, который мы создавали выше лишь значением в переменной адрес.
И так в случае успешной работы 1С и РНР-скпипта в окне сообщений 1С мы увидим надпись hello world.
Теперь очевидно, что с помощью 1C можно передать данные PHP-скриптам, а они в свою очередь делают с ними все что необходимо, например, записывают их в БД.
Пример записи данных в БД MySQL:
Запись в БД MYSQL будет производиться средствами PHP, об этом сказано уже не мало. Поэтому чтобы не повторяться, опишу пример из собственной практики.
Для начала создадим обработку в 1С:
На форму положим поле ввода и присвоим ему идентификатор текст, далее немного переделаем процедуру описанную в разделом выше:
Теперь необходимо создать БД в MySQL (как это сделать описано здесь). Создадим БД и присвоим ей имя TESTDB. Далее создадим таблицу с именем TEST:
Как видно из запроса, в таблице всего 2 поля:
* id – уникальный номер сроки;
* text – текстовое поле, куда будут помещаться данные из 1С.
Теперь необходимо написать PHP-скрипт, который и будет записывать данные из 1С в MySQL. Листинг данного скрипта приведен ниже:
Все готово! Теперь открываем Внешнюю обработку в 1С и пишем в поле ввода слово Hello! Нажимаем кнопку «Сформировать». Если все сделано правильно, то в созданной нами таблице появится запись со словом Hello! В противном случае, в окне сообщений 1С появится текст ошибки.
Заключение:
Весь тот опыт, которым я поделился в этой статье, можно использовать не только в Интернет-торговли, но и в корпоративных целях, например для того, чтобы:
* Консолидировать данные в единую БД MySQL;
* Предоставлять отчеты компетентным лицам, где бы они не находились.
И это еще далеко не весь перечень, ведь WEB-технологии - очень гибкий инструмент с неограниченным спектром возможностей, при условии умелого их использования.
В общем-то, мной был не только реализован механизм отправки данных, но и приема через HTTP, но вот это уже совсем другая история!
NULL – отсутствующие значения.
Не путать с нулевым значением! NULL – это не число, не равно пробелу, пустой ссылке, Неопределено.
NULL – типообразующее значение, т.е. есть тип NULL и единственное значение этого типа.
NULL значения появляются в запросе в следующих ситуациях:
а) Внешнее соединение, при котором не было найдено соответствующей записи в другой таблице (при левом – во второй, при правом – в первой, при полном – в обоих)
б) Обращение к реквизитам элементов для группы и наоборот.
в) NULL в списке полей выборки (ВЫБРАТЬ)
г) Обращение к реквизитам для битой ссылки
ЕСТЬ NULL используется в операторе ВЫБРАТЬ (как бы проверя, что значение это есть пустое ( Значение ЕСТЬ NULL )):
еще пример:
Функция ЕСТЬNULL (значение, РезультатЕслиNULL) возвращает значение своего первого параметра, в случае если он не равен NULL, и значение второго параметра в противном случае
Является свернутым ВЫБОР…КОНЕЦ, но ЕСТЬNULL предпочтительнее.
еще пример:
В данном примере получаются все элементы справочника номенклатуры, после чего, для каждой номенклатуры из регистра накопления получаются текущие остатки. Т.к. для номенклатуры, по которой отсутствуют остатки, виртуальная таблица остатков не запись вернет, то в результате соединения в поле "УчетНоменклатурыОстатки.КоличествоОстаток" будут значения NULL для номенклатуры, по которой не было остатков. Для того чтобы вместо значения NULL в результате запроса присутствовало значение 0, мы использовали функцию ЕСТЬNULL(), которая осуществит желаемую замену.
ЕСТЬNULL отличается от ВЫБОР по следующим причинам:
а) При ЕСТЬNULL лучше читается запрос (проще)
б) При ЕСТЬNULL, если проверяется сложное выражение, то работает быстрее, поскольку вычисляется один раз
в) При ЕСТЬNULL выражение замены приводится к типу проверяемого выражения, если оно имеет тип Строка (длина) или Число (разрядность).
Нельзя проверять значения на NULL обычным равенством, потому что в SQL действует трехзначная логика – Истина, Ложь, NULL, и результатом такого сравнения будет UNKNOWN, что в 1С 8.0 аналогично ЛОЖЬ.
NULL <> 0, поэтому при левых внешних соединениях спр. Номенклатура с таблицами остатков, цен, Контрагентов со взаиморасчетами при отсутствии таких записей там будет NULL, который не равен 0. Лучшее решение – ЕСТЬNULL