Библиотека кода: Сравнить две таблицы значений Код 1C v 8.х
//Сравнивает две таблицы значений
//
Функция ТаблицыЗначенийРавны(ТаблицаЗначений1, ТаблицаЗначений2) Экспорт
Если ТипЗнч(ТаблицаЗначений1) <> Тип("ТаблицаЗначений") ИЛИ ТипЗнч(ТаблицаЗначений2) <> Тип("ТаблицаЗначений") Тогда
Возврат Ложь;
КонецЕсли;
Если ТаблицаЗначений1.Количество() <> ТаблицаЗначений2.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Если ТаблицаЗначений1.Колонки.Количество() <> ТаблицаЗначений2.Колонки.Количество() Тогда
Возврат Ложь;
КонецЕсли;
// Проверим поля
Для каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
Если ТаблицаЗначений2.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Для каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
Если ТаблицаЗначений1.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
// сформируем строку индекса для оптимизации поиска по таблице значений
СтрокаИндекса = "";
Для каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
Если СтрокаИндекса = "" Тогда
СтрокаИндекса = Колонка.Имя;
Иначе
СтрокаИндекса = СтрокаИндекса+","+Колонка.Имя;
КонецЕсли;
КонецЦикла;
// добавим индекс
ТаблицаЗначений2.Индексы.Добавить(СтрокаИндекса);
// Проверим записи
Для каждого СтрокаТаблицы Из ТаблицаЗначений1 Цикл
СтруктураПоиска = Новый Структура;
Для каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
СтруктураПоиска.Вставить(Колонка.Имя, СтрокаТаблицы[Колонка.Имя]);
КонецЦикла;
СтрокиТаблицы2 = ТаблицаЗначений2.НайтиСтроки(СтруктураПоиска);
Если СтрокиТаблицы2.Количество() <> 1 Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
// сформируем строку индекса для оптимизации поиска по таблице значений
СтрокаИндекса = "";
Для каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
Если СтрокаИндекса = "" Тогда
СтрокаИндекса = Колонка.Имя;
Иначе
СтрокаИндекса = СтрокаИндекса+","+Колонка.Имя;
КонецЕсли;
КонецЦикла;
// добавим индекс
ТаблицаЗначений1.Индексы.Добавить(СтрокаИндекса);
Для каждого СтрокаТаблицы Из ТаблицаЗначений2 Цикл
СтруктураПоиска = Новый Структура;
Для каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
СтруктураПоиска.Вставить(Колонка.Имя, СтрокаТаблицы[Колонка.Имя]);
КонецЦикла;
СтрокиТаблицы1 = ТаблицаЗначений1.НайтиСтроки(СтруктураПоиска);
Если СтрокиТаблицы1.Количество() <> 1 Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции// СравнитьТаблицыЗначений()
Категория:
Полезные, Универсальные Функции 17 правил для составления оптимального ЗАПРОСа к данным базы 1С Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос . Создается этот объект вызовом конструкции Новый Запрос . Запрос удобно использовать, когда требуется получить сложную выборку данных, сгруппированную и отсортированную необходимым образом. Классический пример применения запроса - получение сводки по состоянию регистра накопления на определенный момент времени. Так же, механизм запросов позволяет легко получать информацию в различных временных разрезах.
Текст запроса – это инструкция, в соответствии с которой должен быть выполнен запрос. В тексте запроса описывается:
таблицы информационной базы, используемые в качестве источников данных запроса; поля таблиц, которые требуется обрабатывать в запросе; правила группировки; сортировки результатов; и т. д. Инструкция составляется на специальном языке – языке запросов и состоит из отдельных частей – секций, предложений, ключевых слов, функций, арифметических и логических операторов, комментариев, констант и параметров.
Язык запросов платформы 1С очень похож на синтаксис других SQL-языков, но имеются отличия. Основными преимуществами встроенного языка запросов являются: разыменование полей, наличие виртуальных таблиц, удобная работа с итогами, нетипизированные поля в запросах.
Рекомендации по написанию запросов к базе данных на языке запросов платформы 1С: 1) Текст запроса может содержать предопределенные данные конфигурации, такие как:
значения перечислений; предопределенные данные: справочников; планов видов характеристик; планов счетов; планов видов расчетов; пустые ссылки; значения точек маршрута бизнес-процессов. Также текст запроса может содержать значения системных перечислений, которые могут быть присвоены полям в таблицах базы данных: ВидДвиженияНакопления, ВидСчета и ВидДвиженияБухгалтерии. Обращение в запросах к предопределенным данным конфигурации и значениям системных перечислений осуществляется с помощью литерала функционального типа ЗНАЧЕНИЕ. Данный литерал позволяет повысить удобочитаемость запроса и уменьшить количество параметров запроса.
Пример использования литерала ЗНАЧЕНИЕ :
ГДЕ Город = ЗНАЧЕНИЕ(Справочник.Города.Москва) ГДЕ Город = ЗНАЧЕНИЕ(Справочник.Города.ПустаяСсылка) ГДЕ ТипТовара = ЗНАЧЕНИЕ(Перечисление.ВидыТоваров.Услуга) ГДЕ ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) ГДЕ ТочкаМаршрута = ЗНАЧЕНИЕ(БизнесПроцесс.БизнесПроцесс1.ТочкаМаршрута.Действие1 2) Использование инструкции АВТОУПОРЯДОЧИВАНИЕ в запросе может сильно время выполнения запроса, поэтому, если сортировка не требуется, то лучше вообще ее не использовать. Во большинстве случаях лучше всего применять сортировку с помощью инструкции УПОРЯДОЧИТЬ ПО .
Автоупорядочивание работает по следующим принципам:
Если в запросе было указано предложение УПОРЯДОЧИТЬ ПО, то каждая ссылка на таблицу, находящаяся в этом предложении, будет заменена полями, по которым по умолчанию сортируется таблица (для справочников это код или наименование, для документов – дата документа). Если поле для упорядочивания ссылается на иерархический справочник, то будет применена иерархическая сортировка по этому справочнику. Если в запросе отсутствует предложение УПОРЯДОЧИТЬ ПО, но есть предложение ИТОГИ, тогда результат запроса будет упорядочен по полям, присутствующим в предложении ИТОГИ после ключевого слова ПО, в той же последовательности и, в случае если итоги рассчитывались по полям – ссылкам, то по полям сортировки по умолчанию таблиц, на которые были ссылки. Если в запросе отсутствуют предложения УПОРЯДОЧИТЬ ПО и ИТОГИ, но есть предложение СГРУППИРОВАТЬ ПО, тогда результат запроса будет упорядочен по полям, присутствующим в предложении, в той же последовательности и, в случае если группировка велась по полям – ссылкам, то по полям сортировки по умолчанию таблиц, на которые были ссылки. В случае же, если в запросе отсутствуют предложения и УПОРЯДОЧИТЬ ПО, ИТОГИ и СГРУППИРОВАТЬ ПО, результат будет упорядочен по полям сортировки по умолчанию для таблиц, из которых выбираются данные, в порядке их появления в запросе. В случае, если запрос содержит предложение ИТОГИ, каждый уровень итогов упорядочивается отдельно. 3) Что бы избежать повторного запроса к базе данных при выводе результата запроса пользователю (например, построение запроса или отображение результата запроса с помощью табличного документа) полезно использовать инструкцию ПРЕДСТАВЛЕНИЕССЫЛКИ , которая позволяет получать представление ссылочного значения. Пример:
Код 1C v 8.х ВЫБРАТЬ
ПРЕДСТАВЛЕНИЕССЫЛКИ(РасходнаяНакладнаяСостав.Номенклатура) КАК НоменклатураПредставление<br>
Так же возможно использование инструкции ПРЕДСТАВЛЕНИЕ - предназначена для получения строкового представления значения произвольного типа. Отличие этих инструкций в том, что в первом случае, если инструкции передать ссылку, результатом будет строка, В остальных случаях результатом будет значение переданного параметра. Во втором случае, результатом инструкции всегда будет строка!
4) Если в запросе имеется поле с составным типом, то для таких полей возникает необходимость привести значения поля к какому-либо определенному типу с помощью инструкции ВЫРАЗИТЬ , что позволит убрать лишние таблицы из левого соединения с полем составного типа данных и ускорить выполнение запроса. Пример:
Имеется регистра накопления ОстаткиТоваров, у которого поле Регистратор имеет составной тип. В запросе выбираются Дата и Номер документов ПоступлениеТоваров, при этом при обращении к реквизитам документа через поле Регистратор не происходит множество левых соединений таблицы регистра накопления с таблицами документов-регистраторов.
Код 1C v 8.х ВЫБРАТЬ
ВЫРАЗИТЬ(ОстаткиТоваров.Регистратор КАК Документ.ПоступлениеТоваров).Номер КАК НомерПоступления,
ВЫРАЗИТЬ(ОстаткиТоваров.Регистратор КАК Документ.ПоступлениеТоваров).Дата КАК ДатаПоступления
ИЗ
РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров<br>
Если приведение типа считается не осуществимым, то результатом приведения типа будет значение NULL .
5) Не стоит забывать про инструкцию РАЗРЕШЕННЫЕ , которая означает, что запрос выберет только те записи, на которые у текущего пользователя есть права. Если данное слово не указать, то в случае, когда запрос выберет записи, на которые у пользователя нет прав, запрос отработает с ошибкой.
6) В случае, если в запросе используется объединение, и в некоторых частях объединения присутствуют вложенные таблицы (документ с табличной частью), а в некоторых нет, возникает необходимость дополнения списка выборки полями – пустыми вложенными таблицами. Делается это при помощи ключевого слова ПУСТАЯТАБЛИЦА , после которого в скобках указываются псевдонимы полей, из которых будет состоять вложенная таблица. Пример:
Код 1C v 8.х // Выбрать поля Номер и Состав
// из виртуальной таблицы Документ.РасхНакл
ВЫБРАТЬ Ссылка.Номер, ПУСТАЯТАБЛИЦА.(Ном, Тов, Кол) КАК Состав
ИЗ Документ.РасхНакл
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Ссылка.Номер, Состав.(НомерСтроки, Товар, Количество)
ИЗ Документ.РасхНакл Документ.РасходнаяНакладная.Состав.*<br>
7) Что бы в результат запроса не попали повторяющиеся строки, следует использовать инструкцию РАЗЛИЧНЫЕ , потому что так нагляднее и понятнее, а инструкция СГРУППИРОВАТЬ ПО применяется для группировки с помощью агрегатных функций. Ксати, при использовании агрегатных функций предложение СГРУППИРОВАТЬ ПО может быть и не указано совсем, при этом все результаты запроса будут сгруппированы в одну единственную строку. Пример:
Код 1C v 8.х // Необходимо узнать, каким вообще контрагентам
// отгружался товар за период.
Выбрать Различные
Документ.РасходнаяНакладная.Контрагент<br>
8) Инструкция СГРУППИРОВАТЬ ПО позволяет обращаться к полям верхнего уровня, без группировки результатов по этим полям, если агрегатные функции применены к полям вложенной таблицы. Хотя в справке 1С написано, при группировке результатов запроса в списке полей выборки обязательно должны быть указаны агрегатные функции, а помимо агрегатных функций в списке полей выборки допускается указывать только поля, по которым осуществляется группировка. Пример:
Код 1C v 8.х ВЫБРАТЬ
ПоступлениеТоваровИУслуг.Товары.(СУММА(Количество),Номенклатура),
ПоступлениеТоваровИУслуг.Ссылка,
ПоступлениеТоваровИУслуг.Контрагент
ИЗ
Документ.ПоступлениеТоваровИУслуг КАК ПоступлениеТоваровИУслуг
СГРУППИРОВАТЬ ПО
ПоступлениеТоваровИУслуг.Товары.(Номенклатура)<br>
9) Инструкция ЕСТЬNULL предназначена для замены значения NULL на другое значение, но не забываем, что второй параметр будет преобразован к типу первого в случае, если тип первого параметра является строкой или числом.
10) При обращении к главной таблице можно в условии обратиться к данным подчиненной таблицы. Такая возможность называется разыменование полей подчиненной таблицы.
Пример (поиск документов, содержащих в табличной части определенный товар):
Код 1C v 8.х ВЫБРАТЬ
Приходная.Ссылка
ИЗ
Документ.Приходная Где Приходная.Товары.Номенклатура =Номенклатура.<br>
Преимущество этого запроса перед запросом к подчиненной таблице Приходная.Товары в том, что если есть дубли в документах, результат запроса вернет только уникальные документы без использования ключевого слова РАЗЛИЧНЫЕ.
11) Интересный вариант оператора В - это проверка вхождения упорядоченного набора в множество таких наборов (Поле1, Поле2, ... , ПолеN) В (Поле1, Поле2, ... , ПолеN).
Пример:
Код 1C v 8.х ВЫБРАТЬ
Контрагенты.Ссылка
ГДЕ
(Контрагенты.Ссылка, Товары.Ссылка) В
(ВЫБРАТЬ Продажи.Покупатель, Продажи.Товар
ИЗ РегистрНакопления.Продажи КАК Продажи)
ИЗ
Справочник.Контрагенты,
Справочник.Товары<br>
12) При любой возможности используйте виртуальные таблицы запросов. При создании запроса система предоставляет в качестве источников данных некоторое количество виртуальных таблиц - это таблицы, которые так же являются результатом запроса, который система формирует в момент выполнения соответствующего участка кода.
Разработчик может самостоятельно получить те же самые данные, которые система предоставляет ему в качестве виртуальных таблиц, однако алгоритм получения этих данных не будет оптимизирован, так как:
Все виртуальные таблицы параметризованы, т. е. разработчику предоставляется возможность задать некоторые параметры, которые система будет использовать при формировании запроса создания виртуальной таблицы. В зависимости от того, какие параметры виртуальной таблицы указаны разработчиком, система может формировать РАЗЛИЧНЫЕ запросы для получения одной и той же виртуальной таблицы, причем они будут оптимизированы с точки зрения переданных параметров.
Не всегда разработчик имеет возможность получить доступ к тем данным, к которым имеет доступ система.
13) В клиент-серверном варианте работы функция ПОДСТРОКА() реализуется при помощи функции SUBSTRING() соответствующего оператора SQL, передаваемого серверу баз данных SQL Server, который вычисляет тип результата функции SUBSTRING() по сложным правилам в зависимости от типа и значений ее параметров, а так же в зависимости от контекста, в котором она используется. В большинстве случаев эти правила не оказывают влияния на выполнение запроса, но бывают случаи, когда для выполнения запроса существенна максимальная длина строки результата, вычисленная SQL Server. Важно иметь в виду, что в некоторых контекстах использования функции ПОДСТРОКА() максимальная длина ее результата может оказаться равной максимальной длине строки ограниченной длины, которая в SQL Server равна 4000 символам. Это может привести к неожиданному аварийному завершению выполнения запроса:
Microsoft OLE DB Provider for SQL Server: Warning: The query processor could not produce a query plan from the optimizer because the total length of all the columns in the GROUP BY or ORDER BY clause exceeds 8000 bytes.
HRESULT=80040E14, SQLSTATE=42000, native=8618
Чтобы избежать такой ошибки, не рекомендуют использовать функцию ПОДСТРОКА() с целью приведения строк неограниченной длины к строкам ограниченной длины. Вместо нее лучше использовать операцию приведения типа ВЫРАЗИТЬ().
14) С осторожностью используйте ИЛИ в конструкции ГДЕ , так как использование условия с ИЛИ может значительно "утяжелить" запрос. Решить проблему можно конструкцией ОБЪЕДИНИТЬ ВСЕ . Пример:
Код 1C v 8.х ВЫБРАТЬ
_ДемоКонтрагенты.НаименованиеПолное
ИЗ
Справочник._ДемоКонтрагенты КАК _ДемоКонтрагенты
ГДЕ
_ДемоКонтрагенты.Ссылка =Ссылка1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
_ДемоКонтрагенты.НаименованиеПолное
ИЗ
Справочник._ДемоКонтрагенты КАК _ДемоКонтрагенты
ГДЕ
_ДемоКонтрагенты.Ссылка =Ссылка2<br>
15) Условие НЕ В в конструкции ГДЕ увеличивает время исполнения запроса, так как это своего рода НЕ (ИЛИ1 ИЛИ2 ... ИЛИn) , поэтому для больших таблиц старайтесь использовать ЛЕВОЕ СОЕДИНЕНИЕ с условием ЕСТЬ NULL . Пример:
Код 1C v 8.х ВЫБРАТЬ
_ДемоКонтрагенты.Ссылка
ИЗ
Справочник._ДемоКонтрагенты КАК _ДемоКонтрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Документ._ДемоЗаказПокупателя КАК _ДемоЗаказПокупателя
ПО _ДемоКонтрагенты.Ссылка = _ДемоЗаказПокупателя.Контрагент
ГДЕ
_ДемоЗаказПокупателя.Контрагент ЕСТЬ NULL<br>
16) При использовании Временных таблиц нужно индексировать поля условий и соединений в этих таблицах, НО, при использовании индексов запрос может выполняться еще медленнее. Поэтому необходимо анализировать каждый запрос с применением индекса и без, замерять скорость выполнения запроса и принимать окончательное решение.
Если вы помещаете во временную таблицу данные, которые изначально индексированы по некоторым полям, то во временной таблице индекса по этим полям уже не будет.
17) Если вы не используете Менеджер временных таблиц , то явно удалять временную таблицу не требуется, она будет удалена после завершения выполнения пакетного запроса, иначе следует удалить временную таблицу одним из способов: командой УНИЧТОЖИТЬ в запросе, вызвать метод МенеджерВременныхТаблиц.Закрыть() .
Источник
И в дополнении видео от Евгения Гилева : Типовые ошибки при написании запросов на 1С:
VIDEO Категория:
Запросы Как удалить строку или очистить дерево значений Помните, что при при удалении/очистке строки, все подчиненные строки удаляются.
Очистить дерево значений: Дерево.Строки.Очистить();
Код 1C v 8.2 УП &НаСервере
Процедура ОчиститьНаСервере()
тДерево = РеквизитФормыВЗначение("Дерево");
тДерево.Строки.Очистить();
ЗначениеВРеквизитФормы(тДерево, "Дерево");
КонецПроцедуры
Точно также можно очистить от подчиненных элементов другую другую строку.
Удалить строку дерева значений не сложнее & нужно только знать ее индекс:
Код 1C v 8.2 УП &НаКлиенте
Процедура Удалить(Команда)
УдалитьНаСервере();
КонецПроцедуры
&НаСервере
Процедура УдалитьНаСервере()
тДерево = РеквизитФормыВЗначение("Дерево");
тДерево.Строки.Удалить(0);
ЗначениеВРеквизитФормы(тДерево, "Дерево");
КонецПроцедуры
Категория:
Работа с Деревом Значений Функции сохранения таблицы значений в файл и чтения из файла В данном примере хочу привести несколько универсальных функций по выгрузке таблицы значений в файл и дальнейшего чтения из файла:
П орядок программных действий при выгрузке в файл выглядит так:
Подготавливаем таблицу значений (выгружаем из табличной части, выбираем колонки); Конвертируем таблицу значений в табличный документ; Сохраняем табличный документ в MXL. При загрузке таблицы порядок действий такой:
Читаем из файла табличный документ; Конвертируем табличный документ в таблицу значений; Используем эту таблицу значений в своих целях (загружаем в табличную часть). Соответственно файл для хранения данных таблицы имеет расширение *.mxl.
Основные функции для реализации поставленной задачи следующие:
ПреобразоватьТДвТЗ – Функция преобразования табличного документа в таблицу значений.
ПреобразоватьТЗвТД – Функция обратного преобразования таблицы значений в табличный документ.
ПрочитатьТЗИзMXL – Читает из файла данные, определяет колонки таблицы и преобразует эти данные в таблицу значений.
ЗаписатьТЗВMXL – Преобразует таблицу значений в табличный документ и записывает его в файл.
Код 1C v 8.3 // Преобразовать табличный документ в таблицу значений.
//
// Параметры:
// ТабДок - <ТабличныйДокумент> - Исходный табличный документ;
// СтруктураКолонок - <Структура>, <ТаблицаЗначений> - Структура колонок;
// НачалоСтрока - <Число> - Строка начала области;
// НачалоСтолбец - <Число> - Столбец начала области;
// КонецСтрока - <Число> - Строка конца области;
// КонецСтолбец - <Число> - Столбец конца области.
//
// Возвращаемое значение:
// <ТаблицаЗначений> - Полученная таблица значений.
//
Функция ПреобразоватьТДвТЗ(ТабДок, СтруктураКолонок, Знач НачалоСтрока = Неопределено, Знач НачалоСтолбец = Неопределено, Знач КонецСтрока = Неопределено, Знач КонецСтолбец = Неопределено) Экспорт
// Определение габаритов таблицы
Если НачалоСтрока = Неопределено И НачалоСтолбец = Неопределено Тогда
НачалоСтрока = 1;
НачалоСтолбец = 1;
КонецЕсли;
Если НачалоСтрока = Неопределено Тогда
НачалоСтрока = 1;
Пока НЕ ТабДок.Область(НачалоСтрока, НачалоСтолбец).СодержитЗначение
И НачалоСтрока < ТабДок.ВысотаТаблицы
Цикл
НачалоСтрока = НачалоСтрока + 1;
КонецЦикла;
ИначеЕсли НачалоСтолбец = Неопределено Тогда
НачалоСтолбец = 1;
Пока НЕ ТабДок.Область(НачалоСтрока, НачалоСтолбец).СодержитЗначение
И НачалоСтолбец < ТабДок.ШиринаТаблицы
Цикл
НачалоСтолбец = НачалоСтолбец + 1;
КонецЦикла;
КонецЕсли;
КонецСтрока = ?(КонецСтрока = Неопределено, ТабДок.ВысотаТаблицы, КонецСтрока);
КонецСтолбец = ?(КонецСтолбец = Неопределено, ТабДок.ШиринаТаблицы, КонецСтолбец);
// Преобразование
ЭтоТаблица = (ТипЗнч(СтруктураКолонок) = Тип("ТаблицаЗначений"));
ТабЗначений = ПолучитьТаблицуВывода(СтруктураКолонок);
Для ИндексСтроки = НачалоСтрока По КонецСтрока Цикл
СтрокаТЗ = ТабЗначений.Добавить();
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из СтруктураКолонок Цикл
НаименованиеКолонки = ?(ЭтоТаблица, Колонка.Наименование, Колонка.Ключ);
пИндексКолонки = ?(ЭтоТаблица, Колонка.СтолбецОтчёт, ИндексКолонки);
Если ТабДок.Область(ИндексСтроки, пИндексКолонки).СодержитЗначение Тогда
СтрокаТЗ[НаименованиеКолонки] = ТабДок.Область(ИндексСтроки, пИндексКолонки).Значение;
Иначе
СтрокаТЗ[НаименованиеКолонки] = ТабДок.Область(ИндексСтроки, пИндексКолонки).Текст;
КонецЕсли;
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
КонецЦикла;
Возврат ТабЗначений;
КонецФункции;
// Преобразовать таблицу значений в табличный документ.
//
// Параметры:
// ТабЗначений - <ТаблицаЗначений> - Исходная таблица значений;
// ТабДок - <ТабличныйДокумент> - Полученный табличный документ. Если параметр не задан,
// то документ создаётся заново и возвращается функцией;
// НачалоСтрока - <Число> - Строка начала области;
// НачалоСтолбец - <Число> - Столбец начала области;
// ВыводитьЗаголовки - <Булево> - Определяет выводить ли имена колонок или нет.
//
// Возвращаемое значение:
// <ТабличныйДокумент> - Полученный табличный документ (возвращает параметр "ТабДок").
//
Функция ПреобразоватьТЗвТД(ТабЗначений, ТабДок = Неопределено, Знач НачалоСтрока = Неопределено, Знач НачалоСтолбец = Неопределено, ВыводитьЗаголовки = Ложь) Экспорт
Если ТабДок = Неопределено Тогда
ТабДок = Новый ТабличныйДокумент;
КонецЕсли;
// Определение габаритов таблицы
НачалоСтрока = ?(НачалоСтрока = Неопределено, 1, НачалоСтрока);
НачалоСтолбец = ?(НачалоСтолбец = Неопределено, 1, НачалоСтолбец);
// Преобразование
ИндексСтроки = НачалоСтрока;
Если ВыводитьЗаголовки Тогда
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из ТабЗначений.Колонки Цикл
ТабДок.Область(ИндексСтроки, ИндексКолонки).Текст = ?(ПустаяСтрока(Колонка.Заголовок), Колонка.Имя, Колонка.Заголовок);
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
ИндексСтроки = ИндексСтроки + 1;
КонецЕсли;
Для Каждого Элемент Из ТабЗначений Цикл
ИндексКолонки = НачалоСтолбец;
Для Каждого Колонка Из ТабЗначений.Колонки Цикл
ТабДок.Область(ИндексСтроки, ИндексКолонки).СодержитЗначение = Истина;
ТабДок.Область(ИндексСтроки, ИндексКолонки).ТипЗначения = Новый ОписаниеТипов(Колонка.ТипЗначения);
ТабДок.Область(ИндексСтроки, ИндексКолонки).Значение = Элемент[Колонка.Имя];
ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;
ИндексСтроки = ИндексСтроки + 1;
КонецЦикла;
Возврат ТабДок;
КонецФункции;
// Читает табличный документ из файла MXL и преобразует его в таблицу значений.
//
// Параметры:
// ИмяФайла - <Строка> - Путь к файлу MXL;
// СтруктураКолонок - <Структура>, <ТаблицаЗначений> - Структура колонок. Если этот параметр
// не задан, то структура колонок формируется из самого табличного документа;
// ЕстьЗаголовок - <Булево> - Есть ли первая строка с заголовками или нет.
//
// Возвращаемое значение:
// <ТаблицаЗначений> - Полученная таблица значений.
//
Функция ПрочитатьТЗИзMXL(ИмяФайла, СтруктураКолонок = Неопределено, ЕстьЗаголовок = Истина) Экспорт
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);
Если СтруктураКолонок = Неопределено И ЕстьЗаголовок Тогда
СтруктураКолонок = Новый Структура;
Для ИндексКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Обл1 = ТабДок.Область(1, ИндексКолонки);
Обл2 = ТабДок.Область(2, ИндексКолонки);
ИмяКолонки = СокрЛП(Обл1.Текст);
ИмяКолонки = ?(Найти(ИмяКолонки, " ") > 0, СтрЗаменить(ТРег(ИмяКолонки), " ", ""), ИмяКолонки);
СтруктураКолонок.Вставить(ИмяКолонки, ?(Обл2.СодержитЗначение, Обл2.ТипЗначения, Новый ОписаниеТипов));
КонецЦикла;
ИначеЕсли СтруктураКолонок = Неопределено И НЕ ЕстьЗаголовок Тогда
СтруктураКолонок = Новый Структура;
Для ИндексКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Обл2 = ТабДок.Область(1, ИндексКолонки);
ИмяКолонки = "К" + Формат(ИндексКолонки, "ЧДЦ=0; ЧН=0; ЧГ=0");
СтруктураКолонок.Вставить(ИмяКолонки, ?(Обл2.СодержитЗначение, Обл2.ТипЗначения, Новый ОписаниеТипов));
КонецЦикла;
КонецЕсли;
Таблица = ПреобразоватьТДвТЗ(ТабДок, СтруктураКолонок, ?(ЕстьЗаголовок, 2, 1), 1);
Возврат Таблица;
КонецФункции;
// Сохраняет таблицу значений в файле в виде табличного документа.
//
// Параметры:
// ИмяФайла - <Строка> - Путь к файлу MXL;
// ТабЗначений - <ТаблицаЗначений> - Сохраняемая таблица значений;
// ЕстьЗаголовок - <Булево> - Есть ли первая строка с заголовками или нет.
//
Процедура ЗаписатьТЗВMXL(ИмяФайла, ТабЗначений, ЕстьЗаголовок = Истина) Экспорт
ТабДок = ПреобразоватьТЗвТД(ТабЗначений, Неопределено, 1, 1, ЕстьЗаголовок);
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.MXL);
КонецПроцедуры;
Еще небольшой набор функций для вывода таблицы значений в табличный документ. После формирования табличного документа, - сохраняем его в файл mxl.
Табличный документ можно сохранить a файлы следующих типов:
ANSITXT - Текстовый документ DOCX - документ MS Word HTML HTML3 HTML4 HTML5 MXL MXL7 ODS - Файл Open Office PDF - файл Acrobat Readr TXT - Текстовый документ XLS - файл Excel XLS95 - файл Excel95 XLS97 - файл Excel97 XLSX - файл Excel2010 Код 1C v 8.3 // Получаем таблицу значения из файла.
Функция ЗагрузитьТЗизФайла(ИмяФайла)
Путь = КаталогВременныхФайлов() + ИмяФайла;
Текст = Новый ЧтениеТекста(Путь, КодировкаТекста.UTF8);
стрТЗ = Текст.Прочитать();
Текст.Закрыть();
// получим таблицу значений из строки
ТЗ = ЗначениеИзСтрокиВнутр(стрТЗ);
Возврат ТЗ;
КонецФункции
// Заполнить ячейки в строке значениями
//
Функция ЗаписьТЗ2ТабДок(записьТЗ,НомерСтроки,ТабличныйДокумент)
НомерКолонки = 1;
Символ160 = Символ(160);
// цикл по колонкам таблицы
// РезультатЗапроса.Колонки.Количество() // - количество колонок
Для каждого полеТЗ из ЗаписьТЗ цикл
// значения ячейки в Excel
типПоляТЗ = ТипЗнч(полеТЗ);
если типПоляТЗ = Тип("Число") тогда
полеТЗ=Строка(полеТЗ);
полеТЗ=СтрЗаменить(полеТЗ,Символ160,"");
полеТЗ=СтрЗаменить(полеТЗ,",",".");
иначеесли типПоляТЗ = Тип("Строка") тогда
иначе
полеТЗ = строка(полеТЗ);
КонецЕсли;
имяОбласти = "R" + номерСтроки + "C" + НомерКолонки;
имяОбласти = СтрЗаменить(имяОбласти,Символ(160),"");
Ячейка = ТабличныйДокумент.Область(имяОбласти);
Ячейка.Текст = полеТЗ;
НомерКолонки = НомерКолонки + 1;
КонецЦикла;
КонецФункции
// Заполнить наименованиями колонок таблицу
Функция НаимКолонок2Mxl(ТаблицаЗначений,ТабличныйДокумент)
// массКолонки = новый массив();
номерСтроки=1;
номКолонки=1;
ТабличныйДокумент = новый ТабличныйДокумент;
// цикл по коллекции колонок
Для НомКол=0 по ТаблицаЗначений.Колонки.Количество() - 1 Цикл
//Сообщить(Колонка.Имя + "(" + Колонка.ТипЗначения + ")" );
имяКолонки=ТаблицаЗначений.Колонки[НомКол].Имя;
//ТабличныйДокумент.Область(
имяОбласти = "R" + номерСтроки + "C" + номКолонки;
имяОбласти = СтрЗаменить(имяОбласти,Символ(160),"");
Ячейка = ТабличныйДокумент.Область(имяОбласти);
//значениеЯчейки = СтрЗаменить(имяОбласти,Символ(160),"");
Ячейка.Текст = имяКолонки;
// на основе текущего шрифта сделаем Жирный
ЖирныйШрифт = ?(ЖирныйШрифт = Неопределено,Новый Шрифт(Ячейка.Шрифт,,,Истина),ЖирныйШрифт);
Ячейка.Шрифт = ЖирныйШрифт;
номКолонки = номКолонки + 1;
КонецЦикла;
КонецФункции
// Заполнить построчно табличный документ
Функция Таблица2Mxl(ТаблицаЗначений,ТабличныйДокумент)
//Выборка = РезультатЗапроса.Выбрать();
НомСтр=1; // заполняем данными начиная со 2-й строки
// цикл по строкам таблицы
Для каждого записьТЗ из ТаблицаЗначений Цикл
НомСтр = НомСтр + 1;
// цикл по колонкам таблицы
ЗаписьТЗ2ТабДок(записьТЗ,НомСтр,ТабличныйДокумент);
КонецЦикла;
КонецФункции
// Таблица значений в табличный документ
Функция ТаблицаЗначений2Mxl(ТаблицаЗначений,ФайлMxl)
ТабличныйДокумент = новый ТабличныйДокумент;
// вывести колонки
НаимКолонок2Mxl(ТаблицаЗначений,ТабличныйДокумент);
// вывести содержимое таблицы
Таблица2Mxl(ТаблицаЗначений,ТабличныйДокумент);
ТабличныйДокумент.Записать(ФайлMxl,ТипФайлаТабличногоДокумента.MXL);
ТабличныйДокумент.Показать(ФайлMxl,ФайлMxl);
Возврат 0;
КонецФункции
Функция Тест_ВыгрузитьТЗвMxl();
файл_мТЗИсходныеДанные = "мТЗИсходныеДанные.dat";
ТЗ = ЗагрузитьТЗизФайла(файл_мТЗИсходныеДанные);
ФайлMxl = КаталогВременныхФайлов() + СтрЗаменить(файл_мТЗИсходныеДанные,".dat",".mxl");
ТаблицаЗначений2Mxl(ТЗ,ФайлMxl);
КонецФункции
Тест_ВыгрузитьТЗвMxl();
Пример выгруженной таблицы значений в файл:
Категория:
Работа с Таблицей Значений Google maps : вывод точек на карту и режим панорамы В отличие от яндекс карт в GMaps можно использовать панорамы - за что им большой плюс! Надеюсь в яндексе прочитают этот пост и тоже когда-нибудь это сделают!
Для клиента нужно было сделать вывод объектов на карту
С возможностью просмотра панорамы:
Основной HTML код карты хранится в макете:
Код VBS <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map { height: 100% }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.9&sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://www.sitedev.by/lab/markerclusterer/markerclusterer.js"></script>
<script type="text/javascript">
var latlng;
var markers = [];
var myMap;
var index = 1;
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var infoWindow = new google.maps.InfoWindow;
var clusterer, mcOptions;
var trafficLayer = new google.maps.TrafficLayer();
var trafficOn = false;
var noclick = false;
var PointArray = [];
var polygons = [];
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
latlng = new google.maps.LatLng(55.75, 37.62);
var myOptions = {
zoom: 12,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDoubleClickZoom: true,
panControl: true,
zoomControl: true,
mapTypeControl: true,
scaleControl: true,
streetViewControl: true,
overviewMapControl: true
};
myMap = new google.maps.Map(document.getElementById("map"),
myOptions);
google.maps.event.addListener(myMap, 'dragend', function() {
noclick = true;
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
});
google.maps.event.addListener(myMap, 'click', function(event) {
infoWindow.close();
if (!noclick) {
addMarker(event.latLng);
}else{
noclick = false;
}
});
mcOptions = {gridSize: 3, maxZoom: 15};
clusterer = new MarkerClusterer(myMap, markers, mcOptions);
//отображение кнопки управления трафиком - все спер с примера, только подцепил свою функцию
var trafficControlDiv = document.createElement('div');
trafficControlDiv.style.padding = '5px';
// Set CSS for the control border
var controlUI = document.createElement('div');
controlUI.style.backgroundColor = 'white';
controlUI.style.borderStyle = 'solid';
controlUI.style.borderWidth = '2px';
controlUI.style.cursor = 'pointer';
controlUI.style.textAlign = 'center';
controlUI.title = 'нажмите для вкл/выкл трафика';
trafficControlDiv.appendChild(controlUI);
// Set CSS for the control interior
var controlText = document.createElement('div');
controlText.style.fontFamily = 'Arial,sans-serif';
controlText.style.fontSize = '12px';
controlText.style.paddingLeft = '4px';
controlText.style.paddingRight = '4px';
controlText.innerHTML = '<b>Трафик</b>';
controlUI.appendChild(controlText);
google.maps.event.addDomListener(controlUI, 'click', function (){
if (!trafficOn){
trafficOn = true;
trafficLayer.setMap(myMap);
}else{
trafficOn = false;
trafficLayer.setMap(null);
}
});
trafficControlDiv.index = 1;
myMap.controls[google.maps.ControlPosition.TOP_RIGHT].push(trafficControlDiv);
};
//добавляем маркер и отправляем в массив
function addMarker(location) {
marker = new google.maps.Marker({
position: location,
map: myMap,
title: 'Точка'+index
});
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
google.maps.event.addListener(marker, 'click', function(){
var mark = this;
var latLng = mark.getPosition();
infoWindow.setContent(mark.title);
infoWindow.open(myMap, mark);});
markers.push(marker);
index++;
document.getElementById('CoordX').value = location.lat();
document.getElementById('CoordY').value = location.lng();
}
function calcRoute(options) {
//вытягиваем из массива переданных параметров значения
//и преобразуем их в формат LatLng
var option1 = options[0];//начальная точка
var option2 = options[1];//промежуточные точки
var option3 = options[2];//конечная точка
var start = new google.maps.LatLng(option1[0], option1[1]); //первый
var end = new google.maps.LatLng(option3[0], option3[1]); //последний
//получаем транзитные точки
var waypts = [];
if(option2.length > 0) {
for(var i = 0, l = option2.length; i < l; i++) {
temp = option2[i];
Qcoord = new google.maps.LatLng(temp[0], temp[1])
waypts.push({
location:Qcoord,
stopover:true
});
}
}
//return;
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setMap(myMap);
directionsDisplay.setDirections(response);
var total = 0;
var myroute = response.routes[0];
for (i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById('RouteInfo').value = "Длина маршрута - " + total + "км.";
//генерация события для перехвата в 1С
var evt = document.createEventObject();
document.body.fireEvent('ondatasetcomplete', evt);
}else{
alert(status);
}
});
}
function Reset(){
directionsDisplay.setMap(null);
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers = [];
index = 1;
//обнуляем кластер маркеров
clusterer.clearMarkers();
for (var i = 0; i < polygons.length; i++) {
polygons[i].setMap(null);
}
polygons = [];
PointArray = [];
}
function FindAdres(Adres){
Reset();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': Adres}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latlng = results[0].geometry.location;
myMap.panTo(latlng);
marker = new google.maps.Marker({
map: myMap,
position: latlng,
animation: google.maps.Animation.BOUNCE,
title:Adres
});
markers.push(marker);
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
} else {
alert("Ничего не найдено: " + status);
}
});
}
function ReverseSearchAdres(CoordX, CoordY, Adres){
Reset();
latlng = new google.maps.LatLng(CoordX, CoordY);
myMap.panTo(latlng);
var marker = new google.maps.Marker({
map: myMap,
position: latlng,
animation: google.maps.Animation.BOUNCE,
title:Adres
});
markers.push(marker);
infoWindow.setContent(marker.title);
infoWindow.open(myMap, marker);
}
function addToPointArray(CoordX, CoordY, ID, IconT, Text){
var latLng = new google.maps.LatLng(CoordX, CoordY);
var point = new google.maps.Marker({'position': latLng, title: Text, icon: IconT});
PointArray.push(point);
}
function drawCluster(){
clusterer.addMarkers(PointArray);
//myMap.geoObjects.add(clusterer);
}
function createPolygon(ArrayPoint, Name, color) {
//создаем массив координат вершин многоугольника
var paths = [];
for(var i = 0, l = ArrayPoint.length; i < l; i++) {
var temp = ArrayPoint[i];
Qcoord = new google.maps.LatLng(temp[0], temp[1])
paths.push(Qcoord);
};
// Создаем многоугольник
myPolygon = new google.maps.Polygon({
paths: paths,
strokeColor: color,
strokeOpacity: 0.6,
strokeWeight: 5,
fillColor: "#0000FF"
});
myPolygon.setMap(myMap);
polygons.push(myPolygon);
}
function WebClientClick() {
//очистка перед кликом координат, иначе после клика в упр. формах идет считывание координат
document.getElementById('CoordX').value = "0";
document.getElementById('CoordY').value = "0";
var WebClientOperation = document.getElementById("WebClientOperation").value;
//alert(WebClientOperation);
switch (WebClientOperation) {
case "0": // ничего не делаем
var a = 1;
default: // запускаем функцию
eval(WebClientOperation);
}
document.getElementById('WebClientOperation').value = "0";
}
</script>
</head>
<body onload="initialize()">
<div id="map" style="width:100%; height:100%"></div>
<input type="hidden" id="CoordX" name="CoordX" value="0"></input>
<input type="hidden" id="CoordY" name="CoordY" value="0"></input>
<input type="hidden" id="RouteInfo" name="RouteInfo" value=""></input>
<input type="hidden" id="WebClientOperation" name="WebClientOperation" value="0"></input>
<input type="hidden" id="WebClient" name="WebClient" onclick="WebClientClick();"></input>
</body>
</html>
Код вывода карты:
Код 1C v 8.х Процедура ИнициализироватьКарту()
ПутьКФайлу = КаталогВременныхФайлов()+"Карта.html";
Ф = новый Файл(ПутьКФайлу);
Если Ф.Существует() Тогда
УдалитьФайлы(ПутьКФайлу);
КонецЕсли;
Т = новый ТекстовыйДокумент;
ТД = ЭтотОбъект.ПолучитьМакет("МакетГугл");
Т.УстановитьТекст(ТД.ПолучитьТекст());
Т.Записать(ПутьКФайлу);
ЭлементыФормы.Эксплорер.Перейти(ПутьКФайлу);
КонецПроцедуры
Процедура ОчиститьКарту()
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("Reset()");
КонецПроцедуры
//к сожалению, другого спососба получить "внутрь 1С" информацию о действии пользователя на карте я не сумел
//действие пользователя на карте изменяет поле HTML-документа, но не вызывает никакого события в 1с-ке
// поэтому через обработчикОжидания делаю непрерывный опрос карты
Процедура ПриОткрытии()
ИнициализироватьКарту();
КонецПроцедуры
// вывод точек на карту
Процедура ОсновныеДействияФормыОсновныеДействияФормыВыполнить(Кнопка)
ОчиститьКарту();
СписокВидов = Новый СписокЗначений;
Для Каждого стр из ВыборВывода Цикл
если стр.пометка тогда СписокВидов.Добавить(стр.наименование); КонецЕсли;
КонецЦикла;
табАдресов.Очистить();
табАдресов = получитьтабАдресов(СписокВидов);
табУникальныхАдресов = табАдресов.скопировать();
табУникальныхАдресов.свернуть("Уник");
тзДанных = табАдресов.скопировать();
табАдресов.очистить();
Для Каждого стр из табУникальныхАдресов Цикл
Отбор = Новый Структура();
Отбор.Вставить("Уник",стр.Уник);
Строки = тзДанных.НайтиСтроки(Отбор);
НовСтр = табАдресов.добавить();
НовСтр.уник = стр.уник;
Если Строки.Количество() > 0 Тогда
для Каждого тздстр из Строки Цикл
НовСтр.Адрес = тздстр.Адрес;
НовСтр.КД = тздстр.КД;
НовСтр.КШ = тздстр.КШ;
НовСтр.ВидОбъекта = тздстр.ВидОбъекта;
НовСтр.Наименование=Строка(НовСтр.Наименование)+Строка(тздстр.Наименование)+"; ";
КонецЦикла;
КонецЕсли;
КонецЦикла;
ЭлементыФормы.табАдресов.СоздатьКолонки();
ВыборМасштаба = "50%";
ВыборРегиона = "Москва";
ЭлементыФормы.Надпись24.Заголовок = "Точек: "+Строка(табАдресов.количество());
Кол = табАдресов.Количество();
Индекс = 0;
Для Каждого ТекСтрока Из табАдресов Цикл Индекс = Индекс + 1; Если НЕ ЗначениеЗаполнено(ТекСтрока.КД) тогда Продолжить; КонецЕсли;
Широта = формат(ТекСтрока.КШ, "ЧРД=.");
Долгота = формат(ТекСтрока.КД, "ЧРД=.");
СодержимоеТочки = СокрЛП(ТекСтрока.ВидОбъекта)+": "+ СокрЛП(ТекСтрока.адрес); //опять же можно вставить свое название
Попытка
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("addToPointArray(" + Широта + "," + Долгота + ", '" + Строка(Индекс) + "', '" + СокрЛП(ТекСтрока.ВидОбъекта.ПутьКИконке)+ "', """ + СодержимоеТочки + """);");
Исключение
Сообщить("addToPointArray(" + Широта + "," + Долгота + ", '" + Строка(Индекс) + "', '" + СокрЛП(ТекСтрока.ВидОбъекта.ПутьКИконке)+ "', """ + СодержимоеТочки + """);",СтатусСообщения.Внимание);
КонецПопытки;
Состояние("Вывожу на карту " + Индекс + " из " + кол);
КонецЦикла;
ЭлементыФормы.Эксплорер.Документ.parentWindow.eval("drawCluster();");
КонецПроцедуры
Вырванная из конфигурации обработка GMaps.rar
Можно ее использовать как макет для создания обработки под свои требования.
Пример автоматизации в котором это использовалось.
Категория:
Географическая схема Как удалить дубли в списке значений Если Вам необходимо почистить список значений от повторяющихся записей, используйте следующий код:
Код 1C v 8.х структошибок = Новый СписокЗначений;
//....
// заполнение списка значений
//....
//список значений в массив
Массив=структошибок.ВыгрузитьЗначения();
//Удаляем дубли из массива
ТекущийИндекс = 0;
ВсегоЭлементов = Массив.Количество();
Пока ТекущийИндекс < ВсегоЭлементов Цикл
Индекс2 = ТекущийИндекс + 1;
Пока Индекс2 < ВсегоЭлементов Цикл
Если Массив[Индекс2] = Массив[ТекущийИндекс] Тогда
Массив.Удалить(Индекс2);
ВсегоЭлементов = ВсегоЭлементов - 1;
Иначе
Индекс2 = Индекс2 + 1;
КонецЕсли;
КонецЦикла;
ТекущийИндекс = ТекущийИндекс + 1;
КонецЦикла;
//Выведем результат
Для Каждого спстр из Массив цикл
Сообщить(спстр);
КонецЦикла;
Категория:
Работа с Списком Значений Синтаксический анализ JSON - выражения средствами 1С 7.7 Код 1C v 7.x
Перем Л_Лев_Фиг_Скобка, Л_Прав_Фиг_Скобка, Л_Лев_Кв_Скобка, Л_Прав_Кв_Скобка, Л_Кавычка, Л_Экран, Л_Двоеточие, Л_Запятая, Л_Число, Л_Строка, Л_Константа, Л_Финиш;
Перем Цифры1_9, Цифры0_9, ПервыеСимволыКонстант, ОдносимвольныеЛексемы;
Перем НомЛексемы, ТекЛексема;
Перем JSON_Error;
Перем В_Массив, В_Объект, В_Значение;
//*****
Перем НомерСимвола;
Перем ФлагОшибки;
Перем СписокСтроковыхКонстант;
Перем СтекЛексем;
Перем АнализируемаяСтрока;
//*****
Перем ТекКаталог, ТекФайл;
//*****
Функция ПолучитьОбъект_ТЗ() Далее
Функция ПолучитьМассив_ТЗ() Далее
//*****
Функция ТекущиеСимволы(Сколько)
Возврат Сред(АнализируемаяСтрока, НомерСимвола, Сколько);
КонецФункции
//*****
Функция ПрошлыйСимвол(Сдвиг)
Возврат Сред(АнализируемаяСтрока, НомерСимвола - Сдвиг, 1);
КонецФункции
//*****
Процедура ДобавитьЛексему(Лексема, Значение, Сдвиг)
СтекЛексем.НоваяСтрока();
СтекЛексем.Лексема = Лексема;
СтекЛексем.Значение = Значение;
НомерСимвола = НомерСимвола + Сдвиг;
КонецПроцедуры
//*****
Процедура ОбвестиОбласть(Обл)
Обл.РамкаСнизу(1);
Обл.РамкаСверху(1);
Обл.РамкаСлева(1);
Обл.РамкаСправа(1);
КонецПроцедуры
//*****
Процедура НапечататьТЗ(Таб, ТЗ, НомС, НомК)
Перем Тип, Обл1, НС, КС, Ключ, Зн, Обл2;
Тип = ТЗ.ПолучитьЗначение(1, 1);
НомС = НомС + 1;
Обл1 = Таб.Область(НомС, НомК);
ОбвестиОбласть(Обл1);
Если Тип = В_Значение Тогда
ТипЗн = ТЗ.ПолучитьЗначение(2, 1);
Обл1.Текст = ТЗ.ПолучитьЗначение(2, 2);
Обл1.ГоризонтальноеПоложение(1);
Если ТипЗн = Л_Число Тогда
Обл1.ГоризонтальноеПоложение(2);
ИначеЕсли ТипЗн = Л_Константа Тогда
Обл1.Полужирный(1);
ИначеЕсли ТипЗн = Л_Строка Тогда
Обл1.Контроль(4);
КонецЕсли;
Возврат;
ИначеЕсли (Тип = В_Объект) Или (Тип = В_Массив) Тогда
Обл1.Текст = Тип;
Обл1.Полужирный(1);
Обл1.ЦветФона(12648447);
Обл1.РамкаСнизу(5);
КС = ТЗ.КоличествоСтрок();
Для НС = 2 По КС Цикл
НомС = НомС + 1;
Обл2 = Таб.Область(НомС, НомК);
Обл2.Текст = ТЗ.ПолучитьЗначение(НС, 1);
Если Тип = В_Массив Тогда
Обл2.ГоризонтальноеПоложение(2);
КонецЕсли;
ОбвестиОбласть(Обл2);
НомС = НомС - 1;
НапечататьТЗ(Таб, ТЗ.ПолучитьЗначение(НС, 2), НомС, НомК + 1);
КонецЦикла;
Иначе
Сообщить("Фигня " + Тип, "!");
КонецЕсли;
КонецПроцедуры
//*****
Процедура ВыравнятьТЗ(Таб, ОграничениеШирины)
Перем НомерКол, НомерСтр, МаксШирина, Обл, ТекШирина, ТекДлина;
Для НомерКол = 1 По Таб.ШиринаТаблицы() Цикл
МаксШирина = 0;
Для НомерСтр = 1 По Таб.ВысотаТаблицы() Цикл
Обл = Таб.Область(НомерСтр, НомерКол);
ТекШирина = Обл.ШиринаСтолбца();
ТекДлина = СтрДлина(СокрЛП(Обл.Текст));
МаксШирина = Макс(МаксШирина, ТекШирина, ТекДлина);
КонецЦикла;
Таб.Область(, НомерКол).ШиринаСтолбца(Мин(МаксШирина, ОграничениеШирины));
КонецЦикла;
КонецПроцедуры
//*****
Процедура Напечатать_ТЗ(ТЗ)
Перем Таб, НС, НК, МаксШирина, ТекДлина, Обл;
Таб = СоздатьОбъект("Таблица");
МаксНК = 1;
НС = 0;
НК = 1;
НапечататьТЗ(Таб, ТЗ, НС, НК);
ВыравнятьТЗ(Таб, 30);
Таб.Область(1, 1, Таб.ВысотаТаблицы(), Таб.ШиринаТаблицы()).ВертикальноеПоложение(2);
Таб.Опции(0, 0);
Таб.Показать("JSON");
КонецПроцедуры
//*****
Функция Ошибка()
ФлагОшибки = 1;
Возврат 0;
КонецФункции
//*****
Функция ЧитатьКонстанту(ПервСимвол)
Перем КонстантаСтр, ДлинаКонстанты;
КонстантаСтр = СписокСтроковыхКонстант.Получить(ПервСимвол);
ДлинаКонстанты = СтрДлина(КонстантаСтр);
Если ТекущиеСимволы(ДлинаКонстанты) = КонстантаСтр Тогда
ДобавитьЛексему(Л_Константа, КонстантаСтр, ДлинаКонстанты);
Возврат 1;
Иначе
Возврат Ошибка();
КонецЕсли;
КонецФункции
//*****
Процедура ДописатьСимвол(Стр)
Стр = Стр + ТекущиеСимволы(1);
НомерСимвола = НомерСимвола + 1;
КонецПроцедуры
//*****
Функция ЧитатьЧисло()
Перем ЧислоСтр;
ЧислоСтр = "";
Если ТекущиеСимволы(1) = "-" Тогда
ДописатьСимвол(ЧислоСтр);
КонецЕсли;
Если Найти(Цифры1_9, ТекущиеСимволы(1)) > 0 Тогда // не с нуля
ДописатьСимвол(ЧислоСтр);
Пока Найти(Цифры0_9, ТекущиеСимволы(1)) > 0 Цикл // любые цыфры
ДописатьСимвол(ЧислоСтр);
КонецЦикла;
ИначеЕсли ТекущиеСимволы(1) = "0" Тогда //с нуля - ничего дальше
ДописатьСимвол(ЧислоСтр);
Иначе
Возврат Ошибка();
КонецЕсли;
Если ТекущиеСимволы(1) = "." Тогда // десятичная точка
ДописатьСимвол(ЧислоСтр);
Пока Найти(Цифры0_9, ТекущиеСимволы(1)) > 0 Цикл // любые цыфры
ДописатьСимвол(ЧислоСтр);
КонецЦикла;
КонецЕсли;
Если ВРег(ТекущиеСимволы(1)) = "E" Тогда // значок e больное или маленькое
ДописатьСимвол(ЧислоСтр);
Если Найти("+-", ТекущиеСимволы(1)) > 0 Тогда // унарный знак для порядка
ДописатьСимвол(ЧислоСтр);
КонецЕсли;
Пока Найти(Цифры0_9, ТекущиеСимволы(1)) > 0 Цикл // любые цыфры
ДописатьСимвол(ЧислоСтр);
КонецЦикла;
КонецЕсли;
ДобавитьЛексему(Л_Число, ЧислоСтр, 0);
Возврат 1;
КонецФункции
//*****
Функция ЧитатьСтроку()
Перем СтрокаСтр;
СтрокаСтр = "";
НомерСимвола = НомерСимвола + 1;
Пока (ТекущиеСимволы(1) <> Л_Кавычка) Или ((ТекущиеСимволы(1) = Л_Кавычка) И (ПрошлыйСимвол(1) = Л_Экран) И (ПрошлыйСимвол(2) <> Л_Экран)) Цикл
ДописатьСимвол(СтрокаСтр);
КонецЦикла;
ДобавитьЛексему(Л_Строка, СтрокаСтр, 1);
Возврат 1;
КонецФункции
//*****
Функция ПрочитатьФайл(ИмяФайла)
Перем Т, НомерСтрокиФайла, СтрокаРез;
Т = СоздатьОбъект("Текст");
Т.Открыть(ИмяФайла);
СтрокаРез = "";
Для НомерСтрокиФайла = 1 По Т.КоличествоСтрок() Цикл
СтрокаРез = СтрокаРез + Т.ПолучитьСтроку(НомерСтрокиФайла);
КонецЦикла;
Возврат СтрокаРез;
КонецФункции
//*****
Функция СледующаяЛексема()
НомЛексемы = НомЛексемы + 1;
СтекЛексем.ПолучитьСтрокуПоНомеру(НомЛексемы);
ТекЛексема = СтекЛексем.Лексема;
Возврат 1;
КонецФункции
//*****
Функция ОшибкаЛексемы()
Перем РезСтр, НомСтр, ТЛ, ТС;
Сообщить("Ошибочная лексема № " + НомЛексемы + " : <" + ТекЛексема + ">", "!");
РезСтр = "";
Для НомСтр = НомЛексемы + 1 По СтекЛексем.КоличествоСтрок() Цикл
СтекЛексем.ПолучитьСтрокуПоНомеру(НомСтр);
ТЛ = СтекЛексем.Лексема;
Если ТЛ = Л_Строка Тогда
ТС = "<" + ТЛ + "(" + СтекЛексем.Значение + ")>";
ИначеЕсли ТЛ = Л_Константа Тогда
ТС = "<" + ТЛ + "(" + СтекЛексем.Значение + ")>";
Иначе
ТС = "<" + ТЛ + ">";
КонецЕсли;
РезСтр = РезСтр + ТС + ",";
КонецЦикла;
Сообщить(Лев(РезСтр, 400), "!");
Возврат 0;
КонецФункции
//*****
Процедура ДобавитьПару(ТЗ, Ключ, Значение)
ТЗ.НоваяСтрока();
ТЗ.Ключ = Ключ;
ТЗ.Значение = Значение;
КонецПроцедуры
//*****
Функция НоваяТЗ(Тип)
Перем _ТЗ;
_ТЗ = СоздатьОбъект("ТаблицаЗначений");
_ТЗ.НоваяКолонка("Ключ");
_ТЗ.НоваяКолонка("Значение");
ДобавитьПару(_ТЗ, Тип, "");
Возврат _ТЗ;
КонецФункции
//*****
Функция ПолучитьПроизвольноеЗначение_ТЗ()
Перем ТЗ;
Если (ТекЛексема = Л_Строка) Или (ТекЛексема = Л_Число) Или (ТекЛексема = Л_Константа) Тогда
ТЗ = НоваяТЗ(В_Значение);
ДобавитьПару(ТЗ, ТекЛексема, СтекЛексем.Значение);
СледующаяЛексема();
Возврат ТЗ;
ИначеЕсли ТекЛексема = Л_Лев_Фиг_Скобка Тогда
Возврат ПолучитьОбъект_ТЗ();
ИначеЕсли ТекЛексема = Л_Лев_Кв_Скобка Тогда
Возврат ПолучитьМассив_ТЗ();
КонецЕсли;
Возврат ОшибкаЛексемы();
КонецФункции
//*****
Функция ДобавитьКлючЗначение(ТЗ)
Перем НовКлюч, НовЗначение;
Если ТекЛексема <> Л_Строка Тогда
Возврат 0;
КонецЕсли;
НовКлюч = СтекЛексем.Значение;
СледующаяЛексема();
Если ТекЛексема <> Л_Двоеточие Тогда
Возврат ОшибкаЛексемы();
КонецЕсли;
СледующаяЛексема();
НовЗначение = ПолучитьПроизвольноеЗначение_ТЗ();
Если НовЗначение = 0 Тогда
Возврат 0;
КонецЕсли;
ДобавитьПару(ТЗ, НовКлюч, НовЗначение);
Возврат 1;
КонецФункции
//*****
Функция ПолучитьОбъект_ТЗ()
Перем ТЗ;
ТЗ = НоваяТЗ(В_Объект);
СледующаяЛексема();
Если ТекЛексема = Л_Прав_Фиг_Скобка Тогда // пустой объект
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
Если ДобавитьКлючЗначение(ТЗ) = 0 Тогда // первая пара ключ-значение
Возврат 0;
КонецЕсли;
Пока ТекЛексема = Л_Запятая Цикл // пока запятые
СледующаяЛексема();
Если ДобавитьКлючЗначение(ТЗ) = 0 Тогда // пара ключ-значение
Возврат 0;
КонецЕсли;
КонецЦикла;
Если ТекЛексема = Л_Прав_Фиг_Скобка Тогда
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
Возврат 0;
КонецФункции
//*****
Функция ПолучитьМассив_ТЗ()
Перем ТЗ, _Ключ, _Значение;
ТЗ = НоваяТЗ(В_Массив);
СледующаяЛексема();
Если ТекЛексема = Л_Прав_Кв_Скобка Тогда
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
_Значение = ПолучитьПроизвольноеЗначение_ТЗ();
Если _Значение = 0 Тогда
Возврат 0;
КонецЕсли;
_Ключ = 0; // JS - индексы массиворв с нуля
ДобавитьПару(ТЗ, _Ключ, _Значение);
Пока ТекЛексема = Л_Запятая Цикл
СледующаяЛексема();
_Значение = ПолучитьПроизвольноеЗначение_ТЗ();
Если _Значение = 0 Тогда
Возврат 0;
КонецЕсли;
_Ключ = _Ключ + 1;
ДобавитьПару(ТЗ, _Ключ, _Значение);
КонецЦикла;
Если ТекЛексема = Л_Прав_Кв_Скобка Тогда
СледующаяЛексема();
Возврат ТЗ;
КонецЕсли;
Возврат 0;
КонецФункции
//*****
Функция ПрочитатьОбъект_ТЗ()
Перем Рез;
НомЛексемы = 0;
СледующаяЛексема();
Если ТекЛексема = Л_Лев_Фиг_Скобка Тогда
Рез = ПолучитьОбъект_ТЗ();
ИначеЕсли ТекЛексема = Л_Лев_Кв_Скобка Тогда
Рез = ПолучитьМассив_ТЗ();
Иначе
Рез = ПолучитьПроизвольноеЗначение_ТЗ();
КонецЕсли;
Если (Рез = 0) Или (ТекЛексема <> Л_Финиш) Тогда
ОшибкаЛексемы();
Возврат 0;
КонецЕсли;
Возврат Рез;
КонецФункции
//*****
Функция СгенерироватьТЗ(НачАнализируемаяСтрока)
Перем НачальныйСимвол, Рез;
АнализируемаяСтрока = НачАнализируемаяСтрока;
СтекЛексем = СоздатьОбъект("ТаблицаЗначений");
СтекЛексем.НоваяКолонка("Лексема" , "Строка");
СтекЛексем.НоваяКолонка("Значение", "Строка");
ФлагОшибки = 0;
НомерСимвола = 1;
Пока НомерСимвола <= СтрДлина(АнализируемаяСтрока) Цикл
НачальныйСимвол = ТекущиеСимволы(1);
Если Найти(" " + Симв(9), НачальныйСимвол) > 0 Тогда // пробелы и разделители строк пропускаем
НомерСимвола = НомерСимвола + 1;
ИначеЕсли НачальныйСимвол = Л_Кавычка Тогда // кавычка - читаем строку
ЧитатьСтроку();
ИначеЕсли Найти(ОдносимвольныеЛексемы, НачальныйСимвол) > 0 Тогда
ДобавитьЛексему(НачальныйСимвол, "", 1);
ИначеЕсли Найти(ПервыеСимволыКонстант, НачальныйСимвол) > 0 Тогда // первая буква из начала константы - константа null, true, false
Если ЧитатьКонстанту(НачальныйСимвол) = 0 Тогда
Прервать;
КонецЕсли;
ИначеЕсли Найти("-" + Цифры0_9, НачальныйСимвол) > 0 Тогда // число
Если ЧитатьЧисло() = 0 Тогда
Прервать;
КонецЕсли;
Иначе // иных вариантов нет
Сообщить("========= " + НомерСимвола, "!");
Сообщить(НачальныйСимвол, "!");
Сообщить("<" + НачальныйСимвол + "> " + КодСимв(НачальныйСимвол), "!");
Сообщить(ТекущиеСимволы(100), "!");
Возврат 0;
КонецЕсли;
КонецЦикла;
Если ФлагОшибки <> 0 Тогда
Сообщить("Ошибка парсинга JSON - выражения", "!");
Возврат 0;
ИначеЕсли СтекЛексем.КоличествоСтрок() = 0 Тогда
Сообщить("Пустой стек", "!");
Возврат 0;
КонецЕсли;
ДобавитьЛексему(Л_Финиш, "", 0);
Возврат ПрочитатьОбъект_ТЗ();
КонецФункции
//*****
Функция JSON_Error(Стр = "")
Если Стр <> "" Тогда
Сообщить("JSON-ОШИБКА: " + Стр, "!");
КонецЕсли;
Возврат JSON_Error;
КонецФункции
//*****
Функция JSON_Type(Парам)
Если ТипЗначенияСтр(Парам) <> "ТаблицаЗначений" Тогда
Возврат JSON_Error();
ИначеЕсли Парам.КоличествоКолонок() <> 2 Тогда
Возврат JSON_Error();
ИначеЕсли Парам.КоличествоСтрок() < 2 Тогда
Возврат JSON_Error();
КонецЕсли;
Возврат Парам.ПолучитьЗначение(1, 1);
КонецФункции
//*****
Функция JSON_GetValue(Парам, Keys)
Перем Тип, До, После, ПозЗакр, Л1, П2, Инд, ИндСтр, НС, КвоСтрок;
Тип = JSON_Type(Парам);
ПозЗакр = Найти(Keys, "]");
Если ПозЗакр = 0 Тогда
ПозЗакр = СтрДлина(Keys) + 1;
КонецЕсли;
До = Лев(Keys, ПозЗакр);
После = Сред(Keys, ПозЗакр + 1);
Л1 = Лев(До, 1);
П2 = Найти(До, "]");
Если Тип = JSON_Error Тогда
Возврат JSON_Error("Параметра");
КонецЕсли;
КвоСтрок = Парам.КоличествоСтрок();
Если До = "" Тогда // сам объект
Если (Тип = В_Массив) Или (Тип = В_Объект) Тогда
Возврат JSON_Error();
ИначеЕсли Тип = В_Значение Тогда
Возврат Парам.ПолучитьЗначение(2, 2);
Иначе
Возврат JSON_Error("№ 1");
КонецЕсли;
ИначеЕсли До = ".length" Тогда // размер массива или объекта. Для значения - ошибка
Если (Тип = В_Массив) Или (Тип = В_Объект) Тогда
Возврат Парам.КоличествоСтрок() - 1;
Иначе
Возврат JSON_Error("Длина скаляра");
КонецЕсли;
ИначеЕсли Л1 = "[" Тогда // размер массива или объекта. Для значения - ошибка
Если П2 = 0 Тогда
Возврат JSON_Error("Индексация: <" + До + ">");
КонецЕсли;
Инд = Сред(До, 2, П2 - 2);
Если (Найти("'""", Лев(Инд, 1)) > 0) И (Найти("'""", Прав(Инд, 1)) > 0) Тогда // строковый только объект
ИндСтр = Сред(Инд, 2, СтрДлина(Инд) - 2);
Если Тип <> В_Объект Тогда
Возврат JSON_Error("Строковый индекс <" + ИндСтр + "> только для Объекта");
КонецЕсли;
НС = 0;
Если Парам.НайтиЗначение(ИндСтр, НС, 1) = 1 Тогда
Возврат JSON_GetValue(Парам.ПолучитьЗначение(НС, 2), После);
КонецЕсли;
Возврат JSON_Error("Нет индекса <" + ИндСтр + ">");
КонецЕсли;
ИндЧис = 0 + Инд;
Если "" + ИндЧис <> Инд Тогда // защита от <5D>
Возврат JSON_Error("Ошибка 1 числового индекса <" + Инд + ">");
ИначеЕсли Цел(ИндЧис) <> ИндЧис Тогда // защита от неЦелого индекса
Возврат JSON_Error("Ошибка 2 числового индекса <" + Инд + "> (нецелый)");
ИначеЕсли ИндЧис < 0 Тогда
Возврат JSON_Error("Ошибка 3 числового индекса <" + Инд + "> (отрицательный)");
ИначеЕсли ИндЧис > (КвоСтрок - 2) Тогда
Возврат JSON_Error("Ошибка 4 числового индекса <" + Инд + "> (" + ИндЧис + ">" + (КвоСтрок - 2) + ")");
КонецЕсли;
Возврат JSON_GetValue(Парам.ПолучитьЗначение(ИндЧис + 1, 2), После);
Иначе
Возврат JSON_Error("Ошибка 5 <" + До + ">");
КонецЕсли;
КонецФункции
//*****
Процедура ПриОткрытии()
Перем Рез1, ТипУзла1, Зн1, Значение;
ОчиститьОкноСообщений();
СтатусВозврата(0);
Рез1 = СгенерироватьТЗ(ПрочитатьФайл(ТекКаталог + "j1.json"));
Напечатать_ТЗ(Рез1);
ТипУзла1 = JSON_Type(Рез1);
Сообщить("Тип узла: " + ТипУзла1);
Зн1 = JSON_GetValue(Рез1, ".length"); Сообщить("1) Размер: " + Зн1);
Зн3 = JSON_GetValue(Рез1, "['1']"); Сообщить("3) ['1']: <" + Зн3 + ">");
Зн4 = JSON_GetValue(Рез1, "[1]"); Сообщить("4) [1]: <" + Зн4 + ">");
Зн5 = JSON_GetValue(Рез1, "['Массив'][6]"); Сообщить("5) [*]: <" + Зн5 + ">");
Зн6 = JSON_GetValue(Рез1, "['Соответствие']['ДопустимоеИмяСвойства']"); Сообщить("6) [*]: <" + Зн6 + ">");
КонецПроцедуры
//*****
Процедура ДобавитьСтроковуюКонстанту(КонстантаСтр)
Перем ПервыйСимвол;
ПервыйСимвол = Лев(КонстантаСтр, 1);
ПервыеСимволыКонстант = ПервыеСимволыКонстант + ПервыйСимвол;
СписокСтроковыхКонстант.Установить(ПервыйСимвол, КонстантаСтр);
КонецПроцедуры
//*****
РасположениеФайла(ТекКаталог, ТекФайл);
//*****
Л_Лев_Фиг_Скобка = "{";
Л_Прав_Фиг_Скобка = "}";
Л_Лев_Кв_Скобка = "[";
Л_Прав_Кв_Скобка = "]";
Л_Двоеточие = ":";
Л_Запятая = ",";
Л_Экран = "\";
Л_Кавычка = """";
Л_Финиш = "";
Л_Число = "number";
Л_Строка = "string";
Л_Константа = "const";
ОдносимвольныеЛексемы = Л_Лев_Фиг_Скобка + Л_Прав_Фиг_Скобка + Л_Лев_Кв_Скобка + Л_Прав_Кв_Скобка + Л_Двоеточие + Л_Запятая;
//*****
Цифры1_9 = "123456789";
Цифры0_9 = "0" + Цифры1_9;
//*****
В_Массив = "###array";
В_Объект = "###object";
В_Значение = "###value";
//*****
СписокСтроковыхКонстант = СоздатьОбъект("СписокЗначений");
ПервыеСимволыКонстант = "";
ДобавитьСтроковуюКонстанту("null");
ДобавитьСтроковуюКонстанту("false");
ДобавитьСтроковуюКонстанту("true");
JSON_Error = "ERROR";
В качестве примера взят файл j1.json :
{
"999": 88,
"Null": null,
"Сэкраном": "\"",
"Ложь": false,
"ОдинСимв": "1",
"1": "11111",
"Пустышка": "",
"Истина": true,
"Число (плавающая точка)": 1.001e-2,
"Число (плавающая)": -1.001e-2,
"Число (фиксированная точка)": -1000.001,
"Дата": "2011-01-01T12:00:00Z",
"Строка (двойная кавычка)": "Двойная кавычка",
"Строка (одинарная кавычка)": "Одинарная кавычка",
"Маскируемые символы": " \\ \/ \b \t \n \f \r \" ",
"Заковыристая строка": "\\n\\",
"Проблемные символы": "Спец. символы: \u0000, \u0001, \u0002, ... , \u001e, \u001f; Юникод символы: \u0421\u0430\u0448\u0430\u0020\u003a\u0029",
"Кириллические символы": "’АБВГҐДЂЃЕ?ЁЄЖЗЅИ?ІЇЙЈКЛЉМНЊОПРСТЋЌУЎФХЦЧЏШЩЪЫЬЭЮЯ",
"Идентификатор": "a763cfbb-f94f-4c67-8e13-0e96a3a7f353",
"Пустой массив": [],
"Пустой объект": {},
"Массив": [
null,
false,
true,
1.001e-2,
-1000.001,
"2011-01-01T12:00:00Z",
"Двойная кавычка",
"Одинарная кавычка",
"a763cfbb-f94f-4c67-8e13-0e96a3a7f353",
[
"Первый элемент",
"Второй элемент"
],
{
"Имя": "Александр",
"Отчество": "Владимирович",
"Фамилия": "Переверзев"
},
{
"ДопустимоеИмяСвойства": true,
"Недопустимое Имя Свойства": false
}
],
"Структура":
{
"Имя": "Александр",
"Отчество": "Владимирович",
"Фамилия": "Переверзев"
},
"Соответствие":
{
"ДопустимоеИмяСвойства": true,
"Недопустимое Имя Свойства": false
},
"Ссылка":
{
"Ссылка": "00000000-0000-0000-0000-000000000000",
"Представление": "Неизвестная ссылка"
},
"COMSafeArray": [
0,
1,
2,
3,
4,
5
]
}
Категория:
HTML, JS, VML Блокировка записей, невозможно изменить или удалить из регистра. Конфликт блокировок MS SQL + 1C При попытке удалить запись из регистра сведений - получаю ошибку: она заблокирована, ошибка блокировок и т.д.
Отключил всех пользователей, перезапустил сервер, пробую удалить - опять ошибка блокировки
Путем тестов было вяснено, что проблема не в коде, а происходит это на этапе обращения платформы к SQL серверу... после долгих поисков решений, в интернете была найдена статья, которая помогла в решении данной проблемы:
Кто что блокирует, MS SQL + 1C
В повседневной работе достаточно задействовать только первый блок "/*кто кого*/". Открываем MS SQL Server Management Studio, правой на корень - "new query" - вставляем код запроса (только верхнюю часть до "Кто что блокирует", остальное - для детального анализа), выполняем запрос (вверху есть кнопочка выполнения запроса).
Выполнив запрос, запоминаем "ID виновника", быстренько идем в консоль сервера 1С, заходим в ветку "Сеансы" нашей базы. Видим все соединения с 1С-сервером, ищем там колонку "Соединение с СУБД", чтобы увидеть соединения 1С-сервера с MSSQL-сервером. В колонке будет всего несколько заполненных значений, среди них и будет "ID виновника".
Что делать если его там нет, тут 3 варианта:
1. Вернитесь в MSSQL и сделайте запрос еще несколько раз подряд, если значения меняются или таблица вообще пуста - постоянной блокировки нет, у вас (уже) все в порядке.
2. Сеанс который блокирует MSSQL находится в другой базе т.е. блокировка не в той базе (можно попробовать задействовать ветку всех сеансов в консоли 1С-сервера) - вернитесь в MSSQL и внимательно посмотрите в колонку DB в ней находится название базы.
3. Бывает что ID процесса в 1С-консоли вообще отсутствует, такое тоже бывает если у вас есть какие-то внешние программы подключенные напрямую в базу 1С, если пускаете кого-то в MSSQL напрямую, то вариант не исключен.
Код SQL-запроса:
Код SQL SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
DECLARE @dbid AS smallint;
use [ВАШАБАЗА];
SET @dbid=DB_ID();
/*кто кого*/
SELECT DB_NAME(pr1.dbid) AS 'DB'
,pr1.spid AS 'ID жертвы'
,RTRIM(pr1.loginame) AS 'Login жертвы'
,pr2.spid AS 'ID виновника'
,RTRIM(pr2.loginame) AS 'Login виновника'
,pr1.program_name AS 'программа жертвы'
,pr2.program_name AS 'программа виновника'
,txt.[text] AS 'Запрос виновника'
FROM MASTER.dbo.sysprocesses pr1(NOLOCK)
JOIN MASTER.dbo.sysprocesses pr2(NOLOCK)
ON (pr2.spid = pr1.blocked)
OUTER APPLY sys.[dm_exec_sql_text](pr2.[sql_handle]) AS txt
WHERE pr1.blocked <> 0
/* Кто что блокирует */
SELECT s.[nt_username]
,request_session_id
,tran_locks.[request_status]
,rd.[Description] + ' (' + tran_locks.resource_type + ' ' + tran_locks.request_mode + ')' [Object]
,txt_blocked.[text]
,COUNT(*) [COUNT]
FROM sys.dm_tran_locks AS tran_locks WITH (NOLOCK)
JOIN sys.sysprocesses AS s WITH (NOLOCK)
ON tran_locks.request_session_id = s.[spid]
JOIN (
SELECT 'KEY' AS sResource_type
,p.[hobt_id] AS [id]
,QUOTENAME(o.name) + '.' + QUOTENAME(i.name) AS [Description]
FROM sys.partitions p
JOIN sys.objects o
ON p.object_id = o.object_id
JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
UNION ALL
SELECT 'RID' AS sResource_type
,p.[hobt_id] AS [id]
,QUOTENAME(o.name) + '.' + QUOTENAME(i.name) AS [Description]
FROM sys.partitions p
JOIN sys.objects o
ON p.object_id = o.object_id
JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
UNION ALL
SELECT 'PAGE'
,p.[hobt_id]
,QUOTENAME(o.name) + '.' + QUOTENAME(i.name)
FROM sys.partitions p
JOIN sys.objects o
ON p.object_id = o.object_id
JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
UNION ALL
SELECT 'OBJECT'
,o.[object_id]
,QUOTENAME(o.name)
FROM sys.objects o
) AS RD
ON RD.[sResource_type] = tran_locks.resource_type
AND RD.[id] = tran_locks.resource_associated_entity_id
OUTER APPLY sys.[dm_exec_sql_text](s.[sql_handle]) AS txt_Blocked
WHERE (
tran_locks.request_mode = 'X'
AND tran_locks.resource_type = 'OBJECT'
)
OR tran_locks.[request_status] = 'WAIT'
GROUP BY
s.[nt_username]
,request_session_id
,tran_locks.[request_status]
,rd.[Description] + ' (' + tran_locks.resource_type + ' ' + tran_locks.request_mode + ')'
,txt_blocked.[text]
ORDER BY
6 DESC
IF EXISTS ( SELECT Name
FROM tempdb..sysobjects
WHERE name LIKE '#LOCK_01_01%' )
DROP TABLE #LOCK_01_01
CREATE TABLE #LOCK_01_01
(
spid INT,
dbid INT,
ObjId INT,
IndId SMALLINT,
Type VARCHAR(20),
Resource VARCHAR(50),
Mode VARCHAR(20),
Status VARCHAR(20)
)
INSERT INTO #LOCK_01_01
EXEC sp_lock
select OBJECT_NAME(ObjId) as [Имя объекта], Mode [Тип блокировки (код)],
CASE
WHEN Mode='Sch-S' THEN 'Блокировка стабильности схемы. Гарантирует, что элемент схемы, такой как таблица или индекс, не будет удален до тех пор, пока сеанс связи удерживает блокировку стабильности схемы на данный элемент схемы;'
WHEN Mode='Sch-М' THEN '= Блокировка изменения схемы. Должен поддерживаться любым сеансом связи, во время которого предполагается изменить схему данного ресурса. Гарантирует, что другие сеансы не имеют ссылок на обозначенный объект;'
WHEN Mode='S' THEN 'S = Коллективная блокировка. Удерживающему сеансу предоставлен коллективный доступ к ресурсу;'
WHEN Mode='U' THEN 'U = Блокировка обновления. Указывает блокировку обновления, полученную на ресурсы, которые со временем могут быть обновлены. Используется для предотвращения общей формы взаимоблокировки, которая возникает, когда множество сеансов блокируют ресурсы для потенциального обновления в последующее время;'
WHEN Mode='X' THEN 'X = Монопольная блокировка. Удерживающему сеансу предоставлен исключительный доступ к ресурсу;'
WHEN Mode='IS' THEN 'IS = Блокировка с намерением коллективного доступа. Указывает намерение поместить S блокировки на некоторые подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='IU' THEN 'IU = Блокировка с намерением обновления. Указывает намерение поместить U блокировки на некоторые подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='IX' THEN 'IX = Блокировка с намерением монопольного доступа. Указывает намерение поместить X блокировки на некоторые подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='SIU' THEN 'SIU = Коллективная блокировка с намерением обновления. Указывает коллективный доступ к ресурсу с намерением получения блокировок обновления на подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='SIX' THEN 'SIX = Коллективная блокировка с намерением монопольного доступа. Указывает коллективный доступ к ресурсу с намерением получения монопольных блокировок на подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='UIX' THEN 'UIX = Блокировка обновления с намерением монопольного доступа. Указывает блокировку обновления ресурса с намерением получения монопольных блокировок на подчиненные ресурсы в иерархии блокировок;'
WHEN Mode='BU' THEN 'BU = Блокировка массового обновления. Используется для массовых операций;'
--[ ELSE else_result_expression ]
END as [Тип блокировки]
,syspr.spid, syspr.dbid, syspr.open_tran, syspr.status, syspr.hostprocess, syspr.loginame, syspr.hostname
From
#LOCK_01_01
inner join master.dbo.sysprocesses as syspr
on syspr.spid = #LOCK_01_01.spid and syspr.dbid = #LOCK_01_01.dbid
where
#LOCK_01_01.Type = 'TAB'
and
#LOCK_01_01.dbid = @dbid
/* Чем занят сервер*/
SELECT s.[spid]
,s.[loginame]
,s.[open_tran]
,s.[blocked]
,s.[waittime]
,s.[cpu]
,s.[physical_io]
,s.[memusage]
INTO #sysprocesses
FROM sys.[sysprocesses] s
WAITFOR DELAY '00:00:01'
SELECT txt.[text]
,s.[spid]
,s.[loginame]
,s.[hostname]
,DB_NAME(s.[dbid]) [db_name]
,SUM(s.[waittime] -ts.[waittime]) [waittime]
,SUM(s.[cpu] -ts.[cpu]) [cpu]
,SUM(s.[physical_io] -ts.[physical_io]) [physical_io]
,s.[program_name]
FROM sys.[sysprocesses] s
JOIN #sysprocesses ts
ON s.[spid] = ts.[spid]
AND s.[loginame] = ts.[loginame]
OUTER APPLY sys.[dm_exec_sql_text](s.[sql_handle]) AS txt
WHERE s.[cpu] -ts.[cpu]
+ s.[physical_io] -ts.[physical_io]
> 500
OR (s.[waittime] -ts.[waittime]) > 3000
GROUP BY
txt.[text]
,s.[spid]
,s.[loginame]
,s.[hostname]
,DB_NAME(s.[dbid])
,s.[program_name]
ORDER BY
[physical_io] DESC
DROP TABLE #sysprocesses
Категория:
Администрирование Загрузка данных в документ из табличного документа (в ТД скопировано из Excel) Частенько пользователи просят упростить ввод данных в программу используя копирование таблиц из Excel. Ниже я приведу пример как загрузить данные скопированные из Excel:
Создаем форму для загрузки данных:
внутри пишем код:
Код 1C v 8.х // Функция ПолучитьТЗИзМакета(ТабДок, КолонкаИндекса = 1)
ТаблицаДанных = Новый ТаблицаЗначений;
НомерКолонки = 0;
Пока Истина Цикл
НомерКолонки = НомерКолонки + 1;
ИмяКолонки = ТабДок.Область(1, НомерКолонки).Текст;
Если ПустаяСтрока(ИмяКолонки) Тогда
Прервать;
КонецЕсли;
ТаблицаДанных.Колонки.Добавить("К"+Строка(НомерКолонки));
КонецЦикла;
СчетчикКолонок = НомерКолонки - 1;
НомерСтроки = 1; ФлагПрерывания = Ложь;
Пока Истина Цикл
НомерСтроки = НомерСтроки + 1;
Стр = ТаблицаДанных.Добавить();
Для А = 1 ПО СчетчикКолонок Цикл
ТекстКолонки = ТабДок.Область(НомерСтроки, А).Текст;
Если ПустаяСтрока(ТекстКолонки) Тогда
Если А = КолонкаИндекса Тогда
Флагпрерывания = Истина;
ТаблицаДанных.Удалить(Стр);
КонецЕсли;
Иначе
Стр[А - 1] = ТекстКолонки
КонецЕсли;
Если Флагпрерывания Тогда
Прервать
КонецЕсли;
КонецЦикла;
Если Флагпрерывания Тогда
Прервать
КонецЕсли;
КонецЦикла;
Возврат ТаблицаДанных
КонецФункции
Процедура ОсновныеДействияФормыЗагрузить(Кнопка)
тзДанных=ПолучитьТЗИзМакета(ЭлементыФормы.ПолеТД);
Закрыть(тзДанных);
КонецПроцедуры
В документ добавлена кнопка - Загрузка из Excel ее код:
Код 1C v 8.х //Функция преобразует строку вида 31.01.2015 в дату
Функция РазобратьДату(ИзмДата);
Возврат Дата(Сред(ИзмДата,7,4)+Сред(ИзмДата,4,2)+Сред(ИзмДата,0,2));
КонецФункции
Процедура ЗагрузитьИзЕкселНажатие(Элемент)
тзДанных = ПолучитьФорму("ФормаЗагрузкиИзExcel").ОткрытьМодально();
//ТЗ получили, загружаем:
ГрафикПлатежейКлиент.Очистить();
Для Каждого стр из тзДанных Цикл
нСтр = ГрафикПлатежейКлиент.Добавить();
нСтр.Дата = РазобратьДату(стр.К1);
нСтр.Сумма = стр.К2;
нСтр.СуммаАкта = стр.К3;
КонецЦикла;
КонецПроцедуры
Смысл в том что из Excel копируют таблицу:
Жмут на кнопку загрузить и в документе Табличная часть заполняется автоматически:
Категория:
Табличный документ Как сформировать диаграмму с типом График В этом примере построим диаграмму с типом График , вида:
Вот код ее формирования:
Код 1C v 8.х Процедура ГрафикКолВоДоставок()
//Создаем таблицу данных
ТабД = Новый ТаблицаЗначений;
ТабД.Колонки.Добавить("ДатаК");
ТабД.Колонки.Добавить("Всего");
кп = КонПериодаЛ;
нп = кп-(86400);
Пока кп>НачПериодаЛ Цикл
Состояние("Кол-во Доставок на: "+ Строка(кп));
КоличествоДоставок = 0; Тоннаж = 0;
Привилегированный.ПолучитьКоличествоДоставок(кп, КоличествоДоставок, Тоннаж);
Нстр = ТабД.Добавить();
Нстр.ДатаК=кп;
Нстр.Всего = КоличествоДоставок;
кп = нп;
нп = кп-(86400);
КонецЦикла;
ДиаграммаВП = ЭлементыФормы.ДиаграммаКолВоДоставок;
ДиаграммаВП.КоличествоТочек=0;
ТабД.Сортировать("ДатаК Возр");
Для Каждого СтрТраб из ТабД Цикл
Точка=ДиаграммаВП.Точки.Добавить(Формат(СтрТраб.Получить(0),"ДФ=dd.MM"));
Индекс=0;
//Для Каждого Серия из ДиаграммаВП.Серии Цикл
Попытка
ДиаграммаВП.УстановитьЗначение(Точка,ДиаграммаВП.Серии[0],?(СтрТраб.Получить(1)=Неопределено,0,СтрТраб.Получить(1)));
Исключение
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Категория:
Диаграмма Установка и настройка 1C Сервер + MS SQL Server 2008 Категория:
Администрирование Регламентные операции на уровне субд для MS SQL Server, Оптимизация работы Одной из часто встречающихся причин не оптимальной работы системы является неправильное или несвоевременное выполнение регламентных операций на уровне СУБД. Особенно важно выполнять эти регламентные процедуры в крупных информационных системах, которые работают под значительной нагрузкой и обслуживают одновременно большое количество пользователей. Специфика таких систем в том, что обычных действий, выполняемых СУБД автоматически (на основании настроек) оказывает недостаточно для эффективной работы.
Если в работающей системе наблюдаются какие-либо симптомы проблем с производительностью, следует проверить, что в системе правильно настроены и регулярно выполняются все рекомендуемые регламентные операции на уровне СУБД.
Выполнение регламентных процедур должно быть автоматизировано. Для автоматизации этих операций рекомендуется использовать встроенное средства MS SQL Server: Maintenance Plan. Существуют так же другие способы автоматизации выполнения этих процедур. В настоящей статье для каждой регламентной процедуры дан пример ее настройки при помощи Maintenance Plan для MS SQL Server 2005.
Для MS SQL Server рекомендуется выполнять следующие регламентные операции:
Обновление статистикОчистка процедурного КЭШаДефрагментация индексовРеиндексация таблиц базы данных
Рекомендуется регулярно контролировать своевременность и правильность выполнения данных регламентных процедур.
Обновление статистик MS SQL Server строит план запроса на основании статистической информации о распределении значений в индексах и таблицах. Статистическая информация собирается на основании части (образца) данных и автоматически обновляется при изменении этих данных. Иногда этого оказывается недостаточно для того, что MS SQL Server стабильно строил наиболее оптимальный план выполнения всех запросов.
В этом случае возможно проявление проблем с производительностью запросов. При этом в планах запросов наблюдаются характерные признаки неоптимальной работы (неоптимальные операции).
Для того, чтобы гарантировать максимально правильную работу оптимизатора MS SQL Server рекомендуется регулярно обновлять статистики базы данных MS SQL.
Для обновления статистик по всем таблицам базы данных необходимо выполнить следующий SQL запрос:
Код SQL exec sp_msforeachtable N'UPDATE STATISTICS ? WITH FULLSCAN'
Обновление статистик не приводит к блокировке таблиц, и не будет мешать работе других пользователей. Статистика может обновляться настолько часто, насколько это необходимо. Следует учитывать, что нагрузка на сервер СУБД во время обновления статистик возрастет, что может негативно сказаться на общей производительности системы.
Оптимальная частота обновления статистик зависит от величины и характера нагрузки на систему и определяется экспериментальным путем. Рекомендуется обновлять статистики не реже одного раза в день.
Приведенный выше запрос обновляет статистики для всех таблиц базы данных. В реально работающей системе разные таблицы требуют различной частоты обновления статистик. Путем анализа планов запроса можно установить, какие таблицы больше других нуждаются в частом обновлении статистик, и настроить две (или более) различных регламентных процедуры: для часто обновляемых таблиц и для всех остальных таблиц. Такой подход позволит существенно снизить время обновления статистик и влияние процесса обновления статистики на работу системы в целом.
Настройка автоматического обновления статистик (MS SQL 2005)
Запустите MS SQL Server Management Studio и подключитесь к серверу СУБД. Откройте папку Management и создайте новый план обслуживания:
Создайте субплан (Add Sublan) и назовите его «Обновление статистик». Добавьте в него задачу Update Statistics Task из панели задач:
Настройте расписание обновления статистик. Рекомендуется обновлять статистики не реже одного раза в день. При необходимости частота обновления статистик может быть увеличена.
Настройте параметры задачи. Для этого следует два раза кликнуть на задачу в правом нижнем углу окна. В появившейся форме укажите имя базу данных (или несколько баз данных) для которых будет выполняться обновление статистик. Кроме этого вы можете указать для каких таблиц обновлять статистики (если точно неизвестно, какие таблицы требуется указать, то устанавливайте значение All).
Обновление статистик необходимо проводить с включенной опцией Full Scan.
Сохраните созданный план. При наступлении указанного в расписании срока обновление статистик будет запущено автоматически.
Очистка процедурного КЭШа Оптимизатор MS SQL Server кэширует планы запросов для их повторного выполнения. Это делается для того, чтобы экономить время, затрачиваемое на компиляцию запроса в том случае, если такой же запрос уже выполнялся и его план известен.
Возможна ситуация, при которой MS SQL Server, ориентируясь на устаревшую статистическую информацию, построит неоптимальный план запроса. Этот план будет сохранен в процедурном КЭШе и использован при повторном вызове такого же запроса. Если Вы обновили статистику, но не очистили процедурный кэш, то SQL Server может выбрать старый (неоптимальный) план запроса из КЭШа вместо того, чтобы построить новый (более оптимальный) план.
Таким образом, рекомендуется всегда после обновления статистик очищать содержимое процедурного КЭШа.
Для очистки процедурного КЭШа MS SQL Server необходимо выполнить следующий SQL запрос:
Код SQL DBCC FREEPROCCACHE
Этот запрос следует выполнять непосредственно после обновления статистики. Соответственно, частота его выполнения должна совпадать с частотой обновления статистики.
Настройка очистки процедурного КЭШа
для (MS SQL 2005)
Поскольку процедурный КЭШ необходимо очищать при каждом обновлении статистики, данную операцию рекомендуется добавить в уже созданный субплан «Обновление статистик». Для этого следует открыть субплан и добавить в его схему задачу Execute T-SQL Statement Task. Затем следует соединить задачу Update Statistics Task стрелочкой с новой задачей.
В тексте созданной задачи Execute T-SQL Statement Task следует указать запрос «DBCC FREEPROCCACHE »:
Дефрагментация индексов При интенсивной работе с таблицами базы данных возникает эффект фрагментации индексов, который может привести к снижению эффективности работы запросов.
Рекомендуется регулярное выполнение дефрагментации индексов. Для дефрагментации всех индексов всех таблиц базы данных необходимо использовать следующий SQL запрос (предварительно подставив имя базы):
Код SQL sp_msforeachtable N'DBCC INDEXDEFRAG (<имя базы данных>, ''?'')'
Дефрагментация индексов не блокирует таблицы, и не будет мешать работе других пользователей, однако создает дополнительную нагрузку на SQL Server. Оптимальная частота выполнения данной регламентной процедуры должна подбираться в соответствии с нагрузкой на систему и эффектом, получаемым от дефрагментации. Рекомендуется выполнять дефрагментацию индексов не реже одного раза в день.
Возможно выполнение дефрагментации для одной или нескольких таблиц, а не для всех таблиц базы данных.
Настройка дефрагментации индексов (MS SQL 2005)
В ранее созданном плане обслуживания создайте новый субплан с именем «Дефрагментация индексов». Добавьте в него задачу Reorganize Index Task:
Задайте расписание выполнения для задачи дефрагментации индексов. Рекомендуется выполнять задачу не реже одного раза в неделю, а при высокой изменчивости данных в базе еще чаще – до одного раза в день.
Настройте задачу, указав базу данных (или несколько баз данных) и выбрав необходимые таблицы. Если точно неизвестно, какие таблицы следует указать, то устанавливайте значение All.
Реиндексация таблиц включает полное перестроение индексов таблиц базы данных, что приводит к существенной оптимизации их работы. Рекомендуется выполнять регулярную переиндексацию таблиц базы данных. Для реиндексации всех таблиц базы данных необходимо выполнить следующий SQL запрос:
Код SQL sp_msforeachtable N'DBCC DBREINDEX (''?'')'
Реиндексация таблиц блокирует их на все время своей работы, что может существенно сказаться на работе пользователей. В связи с этим реиндексацию рекомендуется выполнять во время минимальной загрузки системы.
После выполнения реиндексации нет необходимости делать дефрагментацию индексов.
В ранее созданном плане обслуживания создайте новый субплан с именем «Дефрагментация индексов». Добавьте в него задачу Rebuild Index Task:
Задайте расписание выполнения для задачи реиндексирования таблиц. Рекомендуется выполнять задачу во время минимальной нагрузки на систему, не реже одного раза в неделю.
Настройте задачу, указав базу данных (или несколько баз данных) и выбрав необходимые таблицы. Если точно неизвестно, какие таблицы следует указать, то устанавливайте значение All.
Реиндексация таблиц базы данных Необходимо осуществлять регулярный контроль выполнения регламентных процедур на уровне СУБД. Ниже приведен пример контроля выполнения плана обслуживания для MS SQL Server 2005.
Откройте созданный вами план обслуживания и выберите из контекстного меню пункт «View History»:
Откроется окно с протоколом выполнения всех заданных регламентных процедур.
Успешно выполненные задачи и задачи, выполненные с ошибками, будут помечены соответствующими иконками. Для задач, выполненных с ошибками, доступна подробная информация об ошибке.
Источник: Регламентные операции MS SQL Server. Оптимизация работы
Категория:
Администрирование Как заполнить диаграмму данными? Код 1C v 8.2 УП // Перезаполнит объект Диагамма значениями из Источник
// Параметры:
// Диаграмма - Диаграмма
// Источник - Массив, Таблица значений, Табличная часть - Коллекция,
// для которой доступен обход элементов коллекции посредством оператора Для каждого … Из … Цикл.
// ПараметрыЗаполнения - Структура - обязательные ключи "Точки", "Серии", "Значения"
// имена коллонок Источника
Процедура ЗаполнитьДиаграмму(Диаграмма, Источник, ПараметрыЗаполнения)
Перем ИндексТочек, ИндексСерий;
Перем Серия, Точка;
Перем ЗаписьИсточника;
Перем ПолеТочек, ПолеСерий, ПолеЗначений;
Диаграмма.Очистить();
Диаграмма.Обновление = Ложь;
Если Не (ТипЗнч(ПараметрыЗаполнения) = Тип("Структура")
Или ТипЗнч(ПараметрыЗаполнения) = Тип("ФиксированнаяСтруктура")
Или ТипЗнч(ПараметрыЗаполнения) = Тип("ФиксированноеСоответствие")
Или ТипЗнч(ПараметрыЗаполнения) = Тип("Соответствие")) Тогда
ПараметрыЗаполнения = Новый Структура;
КонецЕсли;
ПараметрыЗаполнения.Свойство("Точки", ПолеТочек);
ПараметрыЗаполнения.Свойство("Серии", ПолеСерий);
ПараметрыЗаполнения.Свойство("Значения", ПолеЗначений);
Для Каждого ЗаписьИсточника Из Источник Цикл
Точка = ПолучитьИндексОбъектаДиаграммы(Диаграмма.Точки, ЗаписьИсточника[ПолеТочек], ИндексТочек);
Серия = ПолучитьИндексОбъектаДиаграммы(Диаграмма.Серии, ЗаписьИсточника[ПолеСерий], ИндексСерий);
Диаграмма.УстановитьЗначение(Точка,Серия,ЗаписьИсточника[ПолеЗначений]);
КонецЦикла;
Диаграмма.Обновление = Истина;
КонецПроцедуры
// Вернёт число - индекс элемента Коллекции (Точки, Серии)
Функция ПолучитьИндексОбъектаДиаграммы(Коллекция, Значение, КешЗначений)
Перем индекс;
Если КешЗначений = Неопределено Тогда
КешЗначений = Новый Массив;
КонецЕсли;
индекс = КешЗначений.Найти(Значение);
Если индекс = Неопределено Тогда
КешЗначений.Добавить(Значение);
Коллекция.Добавить("" + Значение);
Индекс = КешЗначений.Количество()-1;
КонецЕсли;
Возврат индекс;
КонецФункции
Категория:
Диаграмма Работа с бинарными файлами, Двоичные данные и кодировка Base64 Считать данные из двоичного файла можно при помощи функции ДвоичныеДанные(ИмяФайла). Например:
Код 1C v 8.2 УП ДД = ДвоичныеДанные(ИмяФайла);
или через ADODB.Stream
Код 1C v 8.х Процедура Пример(ИмяФайла)
// Перечисления из библиотеки ADO
StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2);
ConnectModeEnum = Новый Структура(
"adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone,
|adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive,
|adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2);
SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2);
StreamIn = Новый COMОбъект("ADODB.Stream"); //Для создания этого объекта требуется MDAC 2.5 и выше
StreamIn.Type = StreamTypeEnum.adTypeBinary;
StreamIn.Open(); //По умолчанию открывается на чтение
StreamIn.LoadFromFile(ИмяФайла); //Очевидно, что для больших файлов так поступать нехорошо.
Data = StreamIn.Read(); //у переменной Data тип COMSafeArray, это массив байтов
StreamIn.Close(); //Больше нам этот поток не нужен - закрываем.
//Конечно, манипуляция в памяти приемлима только для небольших файлов!
СодержимоеМассив = Data.Выгрузить();
//...
//...
//тут можно по-всякому поиздеваться над массивом
//...
//...
//Запихиваем массив 1С в COMSafeArray. VT_UI1 - обозначение однобайтного беззнакового целого.
Data = Новый COMSafeArray(СодержимоеМассив, "VT_UI1", СодержимоеМассив.Количество());
StreamOut = Новый COMОбъект("ADODB.Stream");
StreamOut.Type = StreamTypeEnum.adTypeBinary;
StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись.
StreamOut.Open(); //Открыли на чтение и запись
StreamOut.Write(Data);
StreamOut.SaveToFile(ИмяФайла, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
StreamOut.Close();
КонецПроцедуры
Двоичные данные и кодировка Base64 в 1С 8.Х
Считать данные из двоичного файла можно при помощи функции
ДвоичныеДанные(ИмяФайла). Например:
Код 1C v 8.2 УП ДД = ДвоичныеДанные(ИмяФайла);
Здесть ДД - специальный объект, который называется "двоичные данные".
В языке 1С есть функция, которая преобразует двоичные данные в строку
Base64Строка(ДвоичныеДанные). Например:
Код 1C v 8.2 УП Строка64 = Base64Строка(ДвоичныеДанные);
Здесть Строка64 - обычная строка, с которой можно делать все, что угодно.
В конце статьи приведена функция
Преобразовать64(Строка64 = неопределено, Массив64 = неопределено) , которая преобразовывает строку в массив байтов, и обратно.
Для того, чтобы получить массив байтов из строки, вызываем ее так:
Код 1C v 8.2 УП Массив64 = Преобразовать64(Строка64 , );
Для обратного преобразования вызываем так:
Код 1C v 8.2 УП Строка64 = Преобразовать64( , Массив64 );
Преобразовать строку в двоичные данные можно при помощи функции Base64Значение(Строка64)
Все указанные функции, кроме Преобразовать64, являются встроенными функциям платформы.
Далее листинг функции Преобразовать64:
Код 1C v 8.2 УП //Автор: Гобсек
&НаСервере
Функция Преобразовать64(Строка64 = неопределено, Массив64 = неопределено)
Таб64 = Новый ТаблицаЗначений;
Таб64.Колонки.Добавить("Код");
Таб64.Колонки.Добавить("Символ");
Нпп = 0;
Для Код = КодСимвола("A") По КодСимвола("Z") Цикл
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = Символ(Код);
Нпп = Нпп + 1;
КонецЦикла;
Для Код = КодСимвола("a") По КодСимвола("z") Цикл
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = Символ(Код);
Нпп = Нпп + 1;
КонецЦикла;
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = "0";
Нпп = Нпп + 1;
Для Код = 1 По 9 Цикл
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = Формат(Код,"ЧЦ=1; ЧДЦ=0");
Нпп = Нпп + 1;
КонецЦикла;
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = "+";
Нпп = Нпп + 1;
стр = Таб64.Добавить();
стр.Код = Нпп;
стр.Символ = "/";
Если Массив64 = неопределено Тогда
Если Строка64 = неопределено Тогда
Сообщить("неверный вызов функции");
Возврат неопределено;
КонецЕсли;
//Уберем переносы строк
Строка64 = СтрЗаменить(Строка64, Символ(10), "");
Строка64 = СтрЗаменить(Строка64, Символ(13), "");
//преобразовываем строку в массив
Если СтрДлина(Строка64) % 4 <> 0 Тогда
Сообщить("длина строки на входе должна быть кратна 4");
Сообщить(СтрДлина(Строка64));
Возврат неопределено;
КонецЕсли;
Кол4 = Цел(СтрДлина(Строка64) / 4);
РазмерМ = Кол4 * 3;
Если Прав(Строка64, 2) = "==" Тогда
РазмерМ = РазмерМ - 2;
ИначеЕсли Прав(Строка64, 1) = "=" Тогда
РазмерМ = РазмерМ - 1;
КонецЕсли;
Массив64 = Новый Массив(РазмерМ);
Для А = 1 По Кол4 Цикл
Число3 = 0;
Для Б = 1 По 4 Цикл
Буква1 = Сред(Строка64, (А-1)*4 + Б, 1);
Если Буква1 = "=" Тогда
Код4 = 0;
Иначе
стрН = Таб64.Найти(Буква1, "Символ");
Если стрН = Неопределено Тогда
Сообщить("ошибка при поиске "+ КодСимвола(Буква1));
Иначе
Код4 = стрН.Код;
КонецЕсли;
КонецЕсли;
Число3 = Число3 * 64 + Код4;
КонецЦикла;
Ост = Число3 % 256;
Индекс = (А-1)*3 + 2;
Если Индекс <= РазмерМ - 1 Тогда
Массив64[Индекс] = Ост;
КонецЕсли;
Число3 = (Число3 - Ост) / 256;
Ост = Число3 % 256;
Индекс = (А-1)*3 + 1;
Если Индекс <= РазмерМ - 1 Тогда
Массив64[Индекс] = Ост;
КонецЕсли;
Число3 = (Число3 - Ост) / 256;
Ост = Число3 % 256;
Массив64[(А-1)*3 + 0] = Ост;
КонецЦикла;
Возврат Массив64;
Иначе //Преобразовываем массив в строку
Строка64 = "";
Кол3 = Цел(Массив64.Количество() / 3);
Если Массив64.Количество() % 3 <> 0 Тогда
Кол3 = Кол3 + 1;
КонецЕсли;
Для А = 1 По Кол3 Цикл
Число3 = Массив64[(А-1)*3];
Если (А-1)*3+1 <= Массив64.ВГраница() Тогда
Код3 = Массив64[(А-1)*3+1];
Иначе
Код3 = 0;
КонецЕсли;
Число3 = Число3*256 + Код3;
Если (А-1)*3+2 <= Массив64.ВГраница() Тогда
Код3 = Массив64[(А-1)*3+2];
Иначе
Код3 = 0;
КонецЕсли;
Число3 = Число3*256 + Код3;
Ост4 = Число3 % 64;
Число3 = (Число3 - Ост4) / 64;
Ост3 = Число3 % 64;
Число3 = (Число3 - Ост3) / 64;
Ост2 = Число3 % 64;
Число3 = (Число3 - Ост2) / 64;
Ост1 = Число3 % 64;
Число3 = (Число3 - Ост1) / 64;
стрН = Таб64.Найти(Ост1, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
стрН = Таб64.Найти(Ост2, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
стрН = Таб64.Найти(Ост3, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
стрН = Таб64.Найти(Ост4, "Код");
Если стрН = неопределено Тогда
Сообщить("Ошибка при поиске");
Иначе
Строка64 = Строка64 + стрН.Символ;
КонецЕсли;
КонецЦикла;
//Если количество символов не делится на 3, то на конце должны быть
//знаки "="
Если Массив64.Количество() % 3 = 1 Тогда
Строка64 = Лев(Строка64, СтрДлина(Строка64)-2)+ "==";
ИначеЕсли Массив64.Количество() % 3 = 2 Тогда
Строка64 = Лев(Строка64, СтрДлина(Строка64)-1)+ "=";
КонецЕсли;
Возврат Строка64;
КонецЕсли;
КонецФункции
Категория:
OLE, ActiveX Яндекс, Google, Рамблер Карты и 1С Обработка демонстрирует возможности интеграции 1С с картографическими сервисами, в ней поддерживается работа трех поставщиков услуг / карт — Яндекс, Google. Рамблер.
Автор: Діма Головаченко - http://smaylukk.com.ua
но так вот сама обработка + еще 2 :
Скачивать файлы может только зарегистрированный пользователь!
Код Модуля Обработки:
Код 1C v 8.х Перем СтруктураПоставщиковКарт Экспорт;
Перем СтруктураЧисел;
/////////////////////////РАБОТА С JSON //////////////////////////////////////////
Функция СформироватьСтрокуJSONИзМассива(Объект)
СтрокаJSON = "[";
Для каждого Элемент Из Объект Цикл
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент) + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "]";
КонецФункции
Функция СформироватьСтрокуJSONИзСтруктуры(Объект)
СтрокаJSON = "{";
Для каждого Элемент Из Объект Цикл
Если Элемент.Значение = "" Тогда
Продолжить;
КонецЕсли;
СтрокаJSON = СтрокаJSON + """" + Элемент.Ключ + """" + ":";
Если ТипЗнч(Элемент.Значение) = Тип("Строка") Тогда
СтрокаJSON = СтрокаJSON + """" + URLEncode(Элемент.Значение) + """";
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Число") Тогда
СтрокаJSON = СтрокаJSON + СтрЗаменить(Строка(Элемент.Значение), Символы.НПП, "");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Булево") Тогда
СтрокаJSON = СтрокаJSON + Формат(Элемент.Значение, "БЛ=false; БИ=true");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Дата") Тогда
// преобразование в unixtime
СтрокаJSON = СтрокаJSON + Формат(ТекущаяДата() - Дата(1970,1,1,1,0,0), "ЧГ=0");
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Массив") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("Структура") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
ИначеЕсли ТипЗнч(Элемент.Значение) = Тип("ТаблицаЗначений") Тогда
СтрокаJSON = СтрокаJSON + СформироватьСтрокуJSON(Элемент.Значение);
Иначе
СтрокаJSON = СтрокаJSON + """" + URLEncode(Строка(Элемент.Значение)) + """";
КонецЕсли;
СтрокаJSON = СтрокаJSON + ",";
КонецЦикла;
Если Прав(СтрокаJSON, 1) = "," Тогда
СтрокаJSON = Лев(СтрокаJSON, СтрДлина(СтрокаJSON)-1);
КонецЕсли;
Возврат СтрокаJSON + "}";
КонецФункции
Функция СформироватьСтрокуJSON(Объект) Экспорт
СтрокаJSON = "";
Если ТипЗнч(Объект) = Тип("Массив") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзМассива(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("Структура") Тогда
СтрокаJSON = СформироватьСтрокуJSONИзСтруктуры(Объект);
ИначеЕсли ТипЗнч(Объект) = Тип("ТаблицаЗначений") Тогда
// преобразуем таблицу значений в массив структур - работает дольше, но кода меньше
// если нужна скорость, то нужно отдельно обработать таблицу значений
СоставСтруктуры = "";
Для каждого Колонка Из Объект.Колонки Цикл
СоставСтруктуры = СоставСтруктуры + ?(ЗначениеЗаполнено(СоставСтруктуры), ",", "") + Колонка.Имя;
КонецЦикла;
МассивСтрок = Новый Массив;
Для каждого Строка Из Объект Цикл
СтруктураКолонок = Новый Структура(СоставСтруктуры);
ЗаполнитьЗначенияСвойств(СтруктураКолонок, Строка);
МассивСтрок.Добавить(СтруктураКолонок);
КонецЦикла;
СтрокаJSON = СформироватьСтрокуJSONИзМассива(МассивСтрок);
КонецЕсли;
Возврат СтрокаJSON;
КонецФункции
Процедура ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, ТипДанных)
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2)); // удалим открывающий символ структуры(массива)
НомерЗначения = 0;
Пока ТекстJSON <> "" Цикл
ПервыйСимвол = Лев(ТекстJSON, 1);
Если ПервыйСимвол = "{" Тогда
// вложенная структура
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
ИначеЕсли ТипДанных = "Массив" Тогда
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "[" Тогда
// вложенный массив
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Если ТипДанных = "Структура" Тогда
Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
НомерЗначения = НомерЗначения + 1;
Иначе
Результат.Добавить(Значение);
КонецЕсли;
ИначеЕсли ПервыйСимвол = "}" И ТипДанных = "Структура" Тогда
// структура закончилась
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
ИначеЕсли ПервыйСимвол = "]" И ТипДанных = "Массив" Тогда
// массив закончился
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
Если Лев(ТекстJSON, 1) = "," Тогда
ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
КонецЕсли;
Возврат;
Иначе
Если ТипДанных = "Структура" Тогда
//ПервыйКавычка = Ложь;
//Если Лев(ТекстJSON, 1) = """" Тогда
// ПервыйКавычка = Истина;
//КонецЕсли;
Поз = Найти(ТекстJSON, ":");
Если Поз = 0 Тогда
// неверный формат, прервемся
Прервать;
КонецЕсли;
//ПредпоследнийКавычка = Ложь;
//Если Сред(ТекстJSON, Поз - 1, 1) = """" Тогда
// ПредпоследнийКавычка = Истина;
//КонецЕсли;
ИмяЗначения = СокрЛП(Лев(ТекстJSON, Поз - 1));
ИмяЗначения = СтрЗаменить(ИмяЗначения, """", "");
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз+1));
Если Лев(ТекстJSON, 1) = "{" Тогда
// значение является структурой
Значение = Новый Структура;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
// значение является массивом
Значение = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
Иначе
// обычное значение
ПервыйКавычка = Ложь;
ПредпоследнийКавычка = Ложь;
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = """" Тогда
Если ПервыйКавычка Тогда
ПредпоследнийКавычка = Истина;
Иначе
ПервыйКавычка = Истина;
КонецЕсли;
КонецЕсли;
Если (Символ = "," И ((ПервыйКавычка И ПредпоследнийКавычка) Или (Не ПервыйКавычка И Не ПредпоследнийКавычка))) ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
//ПредпоследнийКавычка = Ложь;
//Если Сред(ТекстJSON, Поз - 1, 1) = """" Тогда
// ПредпоследнийКавычка = Истина;
//КонецЕсли;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз - 1);
Значение = СтрЗаменить(Значение, """", "");
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
КонецЕсли;
Результат.Вставить(ИмяЗначения, Значение);
ИначеЕсли ТипДанных = "Массив" Тогда
// обычное значение
Поз = 0;
Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
Символ = Сред(ТекстJSON, Сч, 1);
Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
Поз = Сч;
Прервать;
КонецЕсли;
КонецЦикла;
//ПредпоследнийКавычка = Ложь;
//Если Сред(ТекстJSON, Поз - 1, 1) = """" Тогда
// ПредпоследнийКавычка = Истина;
//КонецЕсли;
Если Поз = 0 Тогда
Значение = ТекстJSON;
ТекстJSON = "";
Иначе
Значение = Лев(ТекстJSON, Поз - 1);
Значение = СтрЗаменить(Значение, """", "");
ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
КонецЕсли;
Значение = СокрЛП(Значение);
Результат.Добавить(Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЗаполнитьСтруктуруИзОтветаJSON(Знач ТекстJSON) Экспорт
Результат = Новый Структура;
ТекстJSON = СтрЗаменить(ТекстJSON, "\""", """"); // заменим последовательность \" на "
//ТекстJSON = СтрЗаменить(ТекстJSON, """", ""); // а теперь удалим все кавычки
Если Лев(ТекстJSON, 1) = "{" Тогда
// начало структуры
ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, "Структура");
ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
// начало массива
МассивДанных = Новый Массив;
ЗаполнитьДанныеИзОтветаJSON(МассивДанных, ТекстJSON, "Массив");
Результат.Вставить("Значение", МассивДанных);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция КодСимволаASCII(Символ)
КодUNICODE = КодСимвола(Символ);
Если ((КодUNICODE > 1039) И (КодUNICODE < 1104)) Тогда
Возврат (КодUNICODE - 848);
ИначеЕсли КодUNICODE = 8470 Тогда
Возврат 185;
ИначеЕсли КодUNICODE = 1105 Тогда
Возврат 184;
ИначеЕсли КодUNICODE = 1025 Тогда
Возврат 168;
Иначе
Возврат КодUNICODE;
КонецЕсли;
КонецФункции
Функция URLEncode(value)
table = "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14" +
"%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28" +
"%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B%3C" +
"%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F%50" +
"%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F%60%61%62%63%64" +
"%65%66%67%68%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78" +
"%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C" +
"%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0" +
"%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4" +
"%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8" +
"%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC" +
"%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0" +
"%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF";
result = "";
length = СтрДлина( value );
Для i = 1 По length Цикл
symbol = Сред( value, i, 1 );
//code = КодСимвола( symbol );
code = КодСимволаASCII( symbol );
result = result + Сред( table, code*3 + 1, 3 );
КонецЦикла;
Возврат result;
КонецФункции
/////////////////////////РАБОТА С JSON //////////////////////////////////////////
//Функция декодирует полученный unicod текст - из ответа геокодера Рамблера
// в привычный нам
//Параметры:
// Строка
//Возвращаемое значение:
// Строка
Функция UnicodeEncode(Строка) Экспорт
Результат = Истина;
Попытка
//регулярное выражение
Рег = Новый COMОбъект("VBScript.RegExp");
Рег.IgnoreCase = Истина;
Рег.Global = Истина;
Рег.Multiline = Ложь;
Рег.Pattern = "u[0-9a-f]+";
Колекция = Рег.Execute(Строка);
Для Каждого Элемент Из Колекция Цикл
Если СтрДЛина(Элемент.value) = 1 Тогда
Продолжить;
КонецЕсли;
КодСимвола = ПереводЧислаИз16в10(Сред(ВРег(Элемент.value), 2));
Символ = Символ(КодСимвола);
Строка = СтрЗаменить(Строка, "\" + Элемент.value, Символ);
КонецЦикла;
Исключение
Результат = Ложь;
Сообщить("Ошибка преобразования из Unicode", СтатусСообщения.Информация);
КонецПопытки;
Возврат Результат;
КонецФункции
Функция ПереводЧислаИз16в10(Знач Значение)
Результат = 0;
//перевод значения в строку
Если ТипЗнч(Значение) <> Тип("Строка") Тогда
Значение = СокрЛП(Строка(Значение));
КонецЕсли;
МаксРазрядЦелых = 0;
МаксРазрядЦелых = СтрДлина(Значение) - 1;
н = МаксРазрядЦелых;
Ин = 1;
Пока н >= 0 Цикл
ТекЗначение = СтруктураЧисел.Получить(Сред(Значение, Ин, 1)) * Pow(16, н);
Результат = Результат + ТекЗначение;
н = н - 1;
Ин = Ин + 1;
КонецЦикла;
Возврат Результат;
КонецФункции
///////////////////////////
СтруктураПоставщиковКарт = Новый Соответствие;
СтруктураПоставщиковКарт.Вставить(0, "Яндекс");
СтруктураПоставщиковКарт.Вставить(1, "Гугл");
СтруктураПоставщиковКарт.Вставить(2, "2ГИС");
СтруктураПоставщиковКарт.Вставить(3, "Рамблер");
СтруктураЧисел = Новый Соответствие;
СтруктураЧисел.Вставить("0", 0);
СтруктураЧисел.Вставить("1", 1);
СтруктураЧисел.Вставить("2", 2);
СтруктураЧисел.Вставить("3", 3);
СтруктураЧисел.Вставить("4", 4);
СтруктураЧисел.Вставить("5", 5);
СтруктураЧисел.Вставить("6", 6);
СтруктураЧисел.Вставить("7", 7);
СтруктураЧисел.Вставить("8", 8);
СтруктураЧисел.Вставить("9", 9);
СтруктураЧисел.Вставить("A", 10);
СтруктураЧисел.Вставить("B", 11);
СтруктураЧисел.Вставить("C", 12);
СтруктураЧисел.Вставить("D", 13);
СтруктураЧисел.Вставить("E", 14);
СтруктураЧисел.Вставить("F", 15);
Код Формы Управляемой:
Код 1C v 8.2 УП
&НаКлиенте
Процедура НайтиАдрес(Команда)
НайтиАдресНаКарте(ТекАдрес);
КонецПроцедуры
&НаКлиенте
Процедура ИнициализацияКарты(Команда)
ИнициализироватьКарту();
КонецПроцедуры
&НаКлиенте
Процедура СправочнаяИнформация(Команда)
Элементы.ГруппаСправка.Видимость = Не Элементы.ГруппаСправка.Видимость;
КонецПроцедуры
&НаКлиенте
Процедура Разработчик(Команда)
ЗапуститьПриложение("http://smaylukk.com.ua/?lang=Ru");
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.ТипКарты = Параметры.ТипКарты;
ТекОбъект = РеквизитФормыВЗначение("Объект");
Поставщик = ТекОбъект.СтруктураПоставщиковКарт.Получить(Объект.ТипКарты);
Макет = ТекОбъект.ПолучитьМакет("Справка");
ТекстСправки = Макет.ПолучитьОбласть("Справка" + Поставщик).Область().Текст;
Справка = ТекстСправки;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Элементы.ГруппаСправка.Видимость = Ложь;
Заголовок = "Работа с картами. Поставщик - " + Поставщик;
ИнициализироватьКарту();
КонецПроцедуры
&НаКлиенте
Процедура ПриЗакрытии()
//удаление временных файлов
Для Каждого ТекЭлемент Из МассивВременныхФайлов Цикл
УдалитьФайлы(ТекЭлемент.Значение);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
//Процедура составляет имя процедуры поставщика
// и запускает ее на исполнение
//Параметры:
// НачалоИмени - Строка
Процедура ВыполнитьПроцедуруПоставщика(ИмяПроцедуры)
Выполнить ИмяПроцедуры;
КонецПроцедуры
&НаКлиенте
//процедура инициализирует карту постащика из макета
Процедура ИнициализироватьКарту()
Текст = ПолучитьТекстМакета("Макет" + Поставщик);
Эксплорер = Текст;
КонецПроцедуры
&НаСервере
Функция ПолучитьТекстМакета(ИмяМакета)
Макет = РеквизитФормыВЗначение("Объект").ПолучитьМакет(ИмяМакета);
Результат = Макет.ПолучитьТекст();
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура ОчисткаКарты()
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "Reset()";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
///////////////////////////////////////////////////////////////////////
///////////////////ГЕОКОДИРОВАНИЕ И ПОИСК АДРЕСА///////////////////////
///////////////////////////////////////////////////////////////////////
&НаКлиенте
Процедура НайтиАдресНаКарте(Адрес = "")
//поиск адреса
Если Адрес = "" Тогда
Адрес = "Москва";
КонецЕсли;
// дальше пробуем с помощью геокодинга вывести данные поиска в таблицу
ТаблицаАдресов.Очистить();
ПоискАдреса(Адрес);
Если Поставщик = "Яндекс" Тогда
ПроизвестиГеокодинг_Яндекс();
ИначеЕсли Поставщик = "Гугл" Тогда
ПроизвестиГеокодинг_Гугл();
ИначеЕсли Поставщик = "Рамблер" Тогда
ПроизвестиГеокодинг_Рамблер();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПоискАдреса(Адрес)
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "FindAdres(""" + Адрес + """);";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаСервере
//Процедура выводит в таблицу данные геокдинга Яндекса
//
//Параметры:
// ТекАдрес - Строка
Процедура ПроизвестиГеокодинг_Яндекс()
Яндекс = Новый HTTPСоединение("geocode-maps.yandex.ru");
ВременныйФайл = КаталогВременныхФайлов() + "Yandex_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Яндекс.Получить("/1.x/?geocode=" + ТекАдрес + "&results=10", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по яндексу адрес: " + ТекАдрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ВременныйФайл);
ПостроительDOM = Новый ПостроительDOM;
ДокументДОМ = ПостроительDOM.Прочитать(ЧтениеXML);
СписокText = ДокументДОМ.ПолучитьЭлементыПоИмени("text");
СписокPos = ДокументДОМ.ПолучитьЭлементыПоИмени("pos");
Если (СписокText.Количество() = 0) ИЛИ (СписокPos.Количество() = 0) Тогда
Возврат;
КонецЕсли;
Для ъ = 0 по СписокText.Количество()-1 Цикл
Координаты = СписокPos[Ъ].ТекстовоеСодержимое;
Разделитель = Найти(Координаты," ");
Широта = Число(Сред(Координаты, Разделитель + 1));
Долгота = Число(Лев(Координаты, Разделитель - 1));
Если Широта = 0 ИЛИ Долгота = 0 Тогда
Продолжить;
КонецЕсли;
стрАдрес = ТаблицаАдресов.Добавить();
Если СписокText.Количество() > ъ Тогда
стрАдрес.Адрес = СписокText[Ъ].ТекстовоеСодержимое;
стрАдрес.Широта = Широта;
стрАдрес.Долгота = Долгота;
КонецЕсли;
КонецЦикла;
МассивВременныхФайлов.Добавить(ВременныйФайл);
КонецПроцедуры
&НаСервере
//Процедура выводит в таблицу данные геокдинга Гугл
//
//Параметры:
// ТекАдрес - Строка
Процедура ПроизвестиГеокодинг_Гугл()
Гугл = Новый HTTPСоединение("maps.googleapis.com");
ВременныйФайл = КаталогВременныхФайлов() + "Google_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Гугл.Получить("/maps/api/geocode/xml?address=" + ТекАдрес + "&language=ru&sensor=false", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по Google адрес: " + ТекАдрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ВременныйФайл);
ПостроительDOM = Новый ПостроительDOM;
ДокументДОМ = ПостроительDOM.Прочитать(ЧтениеXML);
ТаблицаРезультатов = ДокументДОМ.ПолучитьЭлементыПоИмени("result");
Если ДокументДОМ.ПолучитьЭлементыПоИмени("status")[0].ТекстовоеСодержимое <> "OK" ИЛИ ТаблицаРезультатов.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для ТекРезультат = 0 по ТаблицаРезультатов.Количество() -1 Цикл
СписокText = ТаблицаРезультатов[ТекРезультат].ПолучитьЭлементыПоИмени("formatted_address");
ЭлементыШиротаДолгота = ТаблицаРезультатов[ТекРезультат].ПолучитьЭлементыПоИмени("location");
Широта = ЭлементыШиротаДолгота[0].ПолучитьЭлементыПоИмени("lat")[0].ТекстовоеСодержимое;
Долгота = ЭлементыШиротаДолгота[0].ПолучитьЭлементыПоИмени("lng")[0].ТекстовоеСодержимое;
Если Широта = 0 ИЛИ Долгота = 0 Тогда
Продолжить;
КонецЕсли;
стрАдрес = ТаблицаАдресов.Добавить();
стрАдрес.Широта = Широта;
стрАдрес.Долгота = Долгота;
стрАдрес.Адрес = СписокText[0].ТекстовоеСодержимое;
КонецЦикла;
МассивВременныхФайлов.Добавить(ВременныйФайл);
КонецПроцедуры
&НаСервере
//Процедура выводит в таблицу данные геокдинга Рамблер
//
//Параметры:
// ТекАдрес - Строка
Процедура ПроизвестиГеокодинг_Рамблер()
ТемпАдрес = СтрЗаменить(ТекАдрес, " ", "+");
Рамблер = Новый HTTPСоединение("maps.rambler.ru");
ВременныйФайл = КаталогВременныхФайлов() + "Рамблер_geocode_" + СокрЛП(Новый УникальныйИдентификатор);
Попытка
Рамблер.Получить("/search/?&a=search&q=" + ТемпАдрес + "&n=10", ВременныйФайл);
Исключение
Сообщить("Ошибка при попытке геокодировать по Рамблер адрес: " + ТекАдрес);
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
а = 1;
Т = Новый ТекстовыйДокумент;
Т.Прочитать(ВременныйФайл);
СтрокаОтвет = Т.ПолучитьТекст();
Результат = РеквизитФормыВЗначение("Объект").UnicodeEncode(СтрокаОтвет);
Если Результат Тогда
СтруктураJSON = РеквизитФормыВЗначение("Объект").ЗаполнитьСтруктуруИзОтветаJSON(СтрокаОтвет);
КонецЕсли;
МассивРезультатов = СтруктураJSON.res;
//обрабатываем элементы массива - только адреса. POI можно обработать отдельно пожеланию
Для Каждого Результат Из МассивРезультатов Цикл
Для Каждого ТекРезультат Из Результат.matches Цикл
стрАдрес = ТаблицаАдресов.Добавить();
стрАдрес.Долгота = Число(ТекРезультат.x);
стрАдрес.Широта = Число(ТекРезультат.y);
Если Результат.type = "addr" Тогда //Результат.type = "poi" - содержит в себе список точек интереса
стрАдрес.Адрес = ТекРезультат.addr;
Иначе
стрАдрес.Адрес = ТекРезультат.name + " - " + ТекРезультат.addr;
КонецЕсли;
КонецЦикла;
КонецЦикла;
МассивВременныхФайлов.Добавить(ВременныйФайл);
КонецПроцедуры
&НаКлиенте
Процедура ОбратнПоискАдреса(Широта, Долгота, Адрес)
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "ReverseSearchAdres(" + Широта + "," + Долгота + ", """ + Адрес + """);";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
Процедура ТаблицаАдресовВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Если ЗначениеЗаполнено(ТаблицаАдресов[ВыбраннаяСтрока].Широта) И ЗначениеЗаполнено(ТаблицаАдресов[ВыбраннаяСтрока].Долгота) Тогда
СтандартнаяОбработка = Ложь;
КонецЕсли;
Широта = Формат(ТаблицаАдресов[ВыбраннаяСтрока].Широта, "ЧЦ=10; ЧДЦ=7; ЧРД=.; ЧРГ=");
Долгота = Формат(ТаблицаАдресов[ВыбраннаяСтрока].Долгота, "ЧЦ=10; ЧДЦ=7; ЧРД=.; ЧРГ=");
ОбратнПоискАдреса(Широта, Долгота, ТаблицаАдресов[ВыбраннаяСтрока].Адрес);
КонецПроцедуры
&НаКлиенте
Процедура ТекАдресПриИзменении(Элемент)
НайтиАдресНаКарте(ТекАдрес);
КонецПроцедуры
///////////////////////////////////////////////////////////////////////
///////////////////МАРШРУТИЗАЦИЯ, КЛАСТЕРА И ПОЛИГОН///////////////////////////////////////
///////////////////////////////////////////////////////////////////////
&НаКлиенте
Процедура ЭксплорерПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
ПолучитьКоординаты();
КонецПроцедуры
&НаКлиенте
Процедура ПостроитьМаршрут(Команда)
Если ТаблицаТочек.Количество() <= 1 Тогда
Предупреждение("Недостаточно точек для построение маршрута!");
Возврат;
КонецЕсли;
Если Поставщик = "Яндекс" Тогда
ПостроитьМаршрут_Яндекс();
ИначеЕсли Поставщик = "Гугл" Тогда
ПостроитьМаршрут_Гугл();
ИначеЕсли Поставщик = "Рамблер" Тогда
ПостроитьМаршрут_Рамблер();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
//Процедура выстраивает маршрут для Яндекса
//
//Параметры:
//
Процедура ПостроитьМаршрут_Яндекс()
ПараметрыМаршрута = ПолучитьПараметрыМаршрутаЯндекс();
ОчисткаКарты();
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "calcRoute(" + ПараметрыМаршрута + ")";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
//Функция получает массив точек, для передачи параметров в Яндекс
//
//Параметры:
//
//Возвращаемое значение:
// Строка
Функция ПолучитьПараметрыМаршрутаЯндекс()
Результат = "";
Результат = Результат + "[[" + СтрЗаменить(Строка(ТаблицаТочек[0].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[0].Долгота), ",", ".") + "],";
Для Ин = 1 По ТаблицаТочек.Количество() - 2 Цикл
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ин].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ин].Долгота), ",", ".") + "],";
КонецЦикла;
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Долгота), ",", ".") + "]]";
Возврат Результат;
КонецФункции
&НаКлиенте
//Процедура выстраивает маршрут для Гугл
//
//Параметры:
//
Процедура ПостроитьМаршрут_Гугл()
ПараметрыМаршрута = ПолучитьПараметрыМаршрутаГугл();
ОчисткаКарты();
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "calcRoute(" + ПараметрыМаршрута + ")";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
//Функция получает массив точек, для передачи параметров в Гугл
//
//Параметры:
//
//Возвращаемое значение:
// Строка
Функция ПолучитьПараметрыМаршрутаГугл()
Результат = "";
ВнутрМассив = "";
Результат = Результат + "[[" + СтрЗаменить(Строка(ТаблицаТочек[0].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[0].Долгота), ",", ".") + "],";
Если ТаблицаТочек.Количество() = 2 Тогда
Результат = Результат + "[],";
Иначе
Для Ин = 1 По ТаблицаТочек.Количество() - 2 Цикл
ВнутрМассив = ВнутрМассив + "[" + СтрЗаменить(Строка(ТаблицаТочек[ин].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ин].Долгота), ",", ".") + "],";
КонецЦикла;
Результат = Результат + "[" + Сред(ВнутрМассив, 1, СтрДлина(ВнутрМассив) - 1) + "],";
КонецЕсли;
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Долгота), ",", ".") + "]]";
Возврат Результат;
КонецФункции
&НаКлиенте
//Процедура выстраивает маршрут для Рамблера
//
//Параметры:
//
Процедура ПостроитьМаршрут_Рамблер()
ПараметрыМаршрута = ПолучитьПараметрыМаршрутаРамблер();
ОчисткаКарты();
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "calcRoute(" + ПараметрыМаршрута + ")";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
//Функция получает массив точек, для передачи параметров в Рамблер
//
//Параметры:
//
//Возвращаемое значение:
// Строка
Функция ПолучитьПараметрыМаршрутаРамблер()
Результат = "";
Результат = Результат + "[[" + СтрЗаменить(Строка(ТаблицаТочек[0].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[0].Долгота), ",", ".") + "],";
Для Ин = 1 По ТаблицаТочек.Количество() - 2 Цикл
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ин].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ин].Долгота), ",", ".") + "],";
КонецЦикла;
Результат = Результат + "[" + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Широта), ",", ".") + "," + СтрЗаменить(Строка(ТаблицаТочек[ТаблицаТочек.Количество() - 1].Долгота), ",", ".") + "]]";
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура СоздатьКластер(Команда)
Если ТаблицаТочек.Количество() <= 1 Тогда
Предупреждение("Недостаточно точек для построение кластера!");
Возврат;
КонецЕсли;
ОчисткаКарты();
ПостроитьКластера();
КонецПроцедуры
&НаКлиенте
Процедура ПостроитьКластера()
Кол = ТаблицаТочек.Количество();
Индекс = 1;
Для Каждого ТекСтрока Из ТаблицаТочек Цикл
Широта = формат(ТекСтрока.Широта, "ЧРД=.");
Долгота = формат(ТекСтрока.Долгота, "ЧРД=.");
СодержимоеТочки = "Содерижмое точки"; //опять же можно вставить свое название
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "addToPointArray(" + Широта + "," + Долгота + ", '" + ТекСтрока.Точка + "', """ + СодержимоеТочки + """);";
Элементы.Эксплорер.document.getElementById("WebClient").click();
Состояние("Обработан " + Индекс + " из " + кол);
Индекс = Индекс + 1;
КонецЦикла;
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "drawCluster();";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьВсе(Команда)
ОчисткаКарты();
ТаблицаТочек.Очистить();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьКарту(Команда)
ОчисткаКарты();
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьТаблицу(Команда)
ТаблицаТочек.Очистить();
КонецПроцедуры
&НаКлиенте
//Процедура получает координаты установленной точки
Процедура ПолучитьКоординаты()
Попытка
ЧислоТип = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 12));
КоординатаX = Элементы.Эксплорер.document.getElementById("CoordX").value;
КоординатаX = ЧислоТип.ПривестиЗначение(КоординатаX);
КоординатаY = Элементы.Эксплорер.document.getElementById("CoordY").value;
КоординатаY = ЧислоТип.ПривестиЗначение(КоординатаY);
Кол = ТаблицаТочек.Количество();
Если КоординатаX > 0 И КоординатаY > 0 И (Кол = 0 Или КоординатаX <> ТаблицаТочек[Кол - 1].Широта И КоординатаY <> ТаблицаТочек[Кол - 1].Долгота) Тогда
НоваяСтрока = ТаблицаТочек.Добавить();
НоваяСтрока.Точка = "Точка" + ТаблицаТочек.Количество();
НоваяСтрока.Широта = КоординатаX;
НоваяСтрока.Долгота = КоординатаY;
КонецЕсли;
Исключение
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПострениеПолигона(Команда)
Если ТаблицаТочек.Количество() <= 1 Тогда
Предупреждение("Недостаточно точек для построение полигона!");
Возврат;
КонецЕсли;
ОчисткаКарты();
ПостроитьПолигон();
КонецПроцедуры
&НаКлиенте
//Процедура выстраивает маршрут для Рамблера
//
//Параметры:
//
Процедура ПостроитьПолигон()
МассивТочек = "[";
Для Каждого ТекТочка Из ТаблицаТочек Цикл
Широта = формат(ТекТочка.Широта, "ЧРД=.");
Долгота = формат(ТекТочка.Долгота, "ЧРД=.");
МассивТочек = МассивТочек + "[" + Широта + "," + Долгота + "],";
КонецЦикла;
МассивТочек = Сред(МассивТочек, 1, СтрДлина(МассивТочек) - 1) + "]";
Цвет16 = Получить16Цвет();
Название = "Полигон";//вставить свое
Элементы.Эксплорер.document.getElementById("WebClientOperation").value = "createPolygon(" + МассивТочек + ", '" + Название + "', '" + Цвет16 + "');";
Элементы.Эксплорер.document.getElementById("WebClient").click();
КонецПроцедуры
&НаСервере
//Функция возвращает значение случайного цвета в 16-ричном формате
//
//Параметры:
// нет
//Возвращаемое значение:
// Строка
Функция Получить16Цвет()
Результат = "";
Строка16 = "0123456789ABCDEF";
ГСЧ = Новый ГенераторСлучайныхЧисел;
Результат = "#";
Для н = 1 По 6 Цикл
м = ГСЧ.СлучайноеЧисло(1, 16);
Результат = Результат + Сред(Строка16, м, 1);
КонецЦикла;
Возврат Результат;
КонецФункции
Категория:
COM-объекты, WMI, WSH