Пример работы с общим макетом типа ActiveDocument в клиент-серверном варианте Код 1C v 8.х //**********************************************************************************
//получаем макет на сервере, сохраняем в файл и передаем на клиента
&НаСервере
Функция ПолучитьДанныеМакета()
АдресХранилища = Новый УникальныйИдентификатор();
Макет = ПолучитьОбщийМакет("Договор");
ВременныйФайл = ПолучитьИмяВременногоФайла("doc");
Макет.Записать(ВременныйФайл);
Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ВременныйФайл), АдресХранилища);
УдалитьФайлы(ВременныйФайл);
Возврат Адрес;
КонецФункции
//**********************************************************************************
//код сотрудника, нужно для создания уникального имени файла для каждого пользователя
&НаСервере
Функция КодПользователя(Пользователь)
Возврат СокрЛП(Пользователь.Сотрудник.Код);
КонецФункции
//**********************************************************************************
//Ссылка - ссылка на договор(ссылка справочника, нужно для подстановки реквизитов)
//РеквизитыДляПечати - структура с нужными реквизитами
&НаКлиенте
Процедура ПечатьДоговора(Ссылка,РеквизитыДляПечати)
Пользователь = ОбщегоНазначения.ТекущийПользователь();
Каталог = КаталогВременныхФайлов();
Каталог = ?(Прав(Каталог,1) = "\", Каталог, Каталог+"\");
ПолноеИмяФайла = Каталог+"Договор_"+КодПользователя(Пользователь)+".doc";
Попытка
Индификатор = ПолучитьДанныеМакета();
МакетДоговора = ПолучитьИзВременногоХранилища(Индификатор);
МакетДоговора.Записать(ПолноеИмяФайла);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Попытка
MSWord = Новый COMОбъект("Word.Application");
Исключение
Сообщить("Ошибка при попытке создать объект ""MS Word""!" + Символы.ПС +
"Возможно приложение ""MS Word"" не установлено или установлено неправильно.", СтатусСообщения.Внимание);
КонецПопытки;
MSWord.Documents.Open(ПолноеИмяФайла);
Попытка
Документ = MSWord.Application.Documents(1);
Документ.Activate();
Исключение
// Если произойдет ошибка, выводятся данные об ошибке, и объект закрывается.
Сообщение = Новый СообщениеПользователю();
Сообщение.Текст = ОписаниеОшибки();
Сообщение.Сообщить();
MSWord.Application.Quit();
Возврат;
КонецПопытки;
//*******************************************
//тут выполняем замену
Попытка
Замена = Документ.Content.Find;
Замена.Execute("{ЧтоМеняем}", Ложь, Истина, Ложь, , , Истина, , Ложь, "На что меняем");
Исключение
КонецПопытки;
// Делаем видимым приложение и активизируем его.
MSWord.Application.Visible = Истина;
MSWord.Activate();
КонецПроцедуры
Категория:
Работа с Microsoft Office и OpenOffice Как изменить путь 1c server_addr в CentOS При установке CentOS , неверно указал hostname, из за чего сервер невиден по имени.
Имя сервера в /etc/sysconfig/network и /etc/hosts сменил, а в логах пишет имя которое было при установке сервера. Где еще нужно сменить имя сервера?
Нужно поменять имя в настоечных файлах сервера:
В Linux - файлы лежат в домашнем каталоге пользователя от имени которого запускается сервис: usr1cv8/home/.1cv8/1C/1cv8
открыв файл, делаем замену старого имени на новое:
На всякий случай: для Windows зайдите в каталог c:\program files\1c\1cv82\srvinfo
Категория:
Linux: CentOS, Debian, Ubuntu, ALT и д.р Сравнение: Конкатенация, ТекстовыйДокумент, ЗаписьXML Немного теории:
Конкатенация (соединение строк). Казалось бы - ну что может быть проще и однозначнее? Ан нет. Выражение T = "А"+"Б"; (если оно не вычислено на этапе компиляции/разбора) требует выделения памяти для "А", памяти для "Б", анализа длин "А" и "Б", выделение памяти для T, копирование первой строки, копирование второй строки. Это медленно, особенно если в цикле дописывается кусочек в конец строки.
В "нормальных" системах, например в .NET от этого можно уйти используя так называемые StringBuilder - это специальный объект, который более эффективно выделяет память (крупными блоками) и не копирует зря строки. По сути это поток (stream) который используется для записи в память, как в файл. А вот в 1С такого нет. Фиг вам товарищи, а не эффективная работа со строками
Но фиг только тем у кого хитрости мало, а для остальных есть варианты.
ТекстовыйДокумент
Оказывается, что метод ДобавитьСтроку() для типа ТекстовыйДокумент для больших строк работает гораздо эффективнее чем тупая конкатенация. Возможно, это связано с тем, что этот тип - обёртка к текстовому редактору, встроенному в 1С. Кстати, этот редактор для простых текстовых файлов файлов мне нравится гораздо больше, чем например, notepad или редактор Visual Studio - он позволяет бодрее работать с большими текстами, как в длину, так и в ширину.
Но! У этого способа есть недостаток - в 8.0 и 8.1 он не доступен на сервере, т.к. считается "интерфейсным". Обидно. Но это заставляет искать нас более эффективный способ:
ЗаписьXML
Опа! А при чём здесь XML? Правильно, XML нам не нужен. Но важно, что тип ЗаписьXML представляет собой как раз обёртку над последовательной записью в поток. А если учесть, что он позволяет формировать результат в память в виде строки, а не только в файл, то это уже готовый кандидат на
замену StringBuilder. Осталось только упомянуть, что он позволяет дозаписывать в "XML" всё что угодно при помощи метода ЗаписатьБезОбработки().
Код 1C v 8.2 УП ДлинаДобавляемогоКуска = 200; //символов, последний - ПС
ОбщаяДлинаСтроки = 1000000;
КоличествоИтераций = 10;
//Создаём базовую строчку:
БазоваяСтрока = "";
Для Сч = 1 по ДлинаДобавляемогоКуска-1 Цикл
БазоваяСтрока = БазоваяСтрока + "Ы";
КонецЦикла;
БазоваяСтрокаПС = БазоваяСтрока + Символы.ПС;
//Способ 1. Добавление строк к концу строки
Сообщить("Способ 1. Добавление строк к концу строки - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 1. Добавление строк к концу строки - " + Строка(СчИтераций));
СтрокаРезультат = "";
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
СтрокаРезультат = СтрокаРезультат + БазоваяСтрокаПС;
КонецЦикла;
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 1. Добавление строк к концу строки - Окончание " + Строка(ТекущаяДата()));
//Способ 2. Добавление строк в текстовый документ
Сообщить("Способ 2. Добавление строк в текстовый документ - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 2. Добавление строк в текстовый документ - " + Строка(СчИтераций));
ТекстПостроитель = Новый ТекстовыйДокумент;
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
ТекстПостроитель.ДобавитьСтроку(БазоваяСтрока); //ПС добавляется сам
КонецЦикла;
СтрокаРезультат = ТекстПостроитель.ПолучитьТекст();
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 2. Добавление строк в текстовый документ - Окончание " + Строка(ТекущаяДата()));
//Способ 3. Создание через ЗаписьXML
Сообщить("Способ 3. Создание через ЗаписьXML - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 3. Создание через ЗаписьXML - " + Строка(СчИтераций));
ТекстПостроитель = Новый ЗаписьXML;
ТекстПостроитель.УстановитьСтроку();
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
ТекстПостроитель.ЗаписатьБезОбработки(БазоваяСтрокаПС);
КонецЦикла;
СтрокаРезультат = ТекстПостроитель.Закрыть();
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 3. Создание через ЗаписьXML - Окончание " + Строка(ТекущаяДата()));
//ЗЫ: данный код проверен в 8.2
Результаты забегов
У меня на тестовой среде получилось примерно следующее время:
1. Конкатенация - 24 секунды
2. Текстовый документ 1,5 секунды
3. ЗаписьXML - около 0,4 секунды
Пишет
Alexander Speshilov Категория:
Работа с Текстом (Строкой) Как заменить значение ресурса регистра сведений – универсальная процедура В том случае, когда в каком-то регистре сведений нужно заменить несколько видов значений какого-то конкретного ресурса на заданное значение, лучше использовать вот такую универсальную процедуру (при ее вызове достаточно подставить название регистра, название ресурса и передать старые заменяемые значения и новое, на которое они заменяются):
Код 1C v 8.х // Процедура выполняет в независимом регистре сведений "ИмяРегистраСведений" замену
// всех значений ресурса "ИмяИзменяемогоРесурса", // соответствующих массиву "МассивСтарыхЗначенийРесурса"
// на новое значение ресурса "НовоеЗначениеРесурса".
// В запрос можно передать дополнительное условие, ограничивающее выборку данных из регистра "ДопУсловие"
Процедура ЗаменаРесурсаНезависимогоРегистра(ИмяРегистраСведений, ИмяИзменяемогоРесурса, МассивСтарыхЗначенийРесурса, НовоеЗначениеРесурса, ДопУсловие = "")
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("МассивСтарыхЗначенийИзмерения", МассивСтарыхЗначенийРесурса);
Запрос.УстановитьПараметр("НовоеЗначениеИзмерения", НовоеЗначениеРесурса);
// Подготовим таблицу значений для позиционирования (установки отбора) на нужных записях регистра:
Запрос.Текст =
"ВЫБРАТЬ *
|ИЗ
| РегистрСведений." + ИмяРегистраСведений + " КАК Регистр
|ГДЕ
| Регистр." + ИмяИзменяемогоРесурса + " В (&МассивСтарыхЗначенийИзмерения)" + ДопУсловие;
Сообщить("1 Приступаем к выполнению запроса к данным регистра """ + ИмяРегистраСведений + """ - " + ТекущаяДата());
ТаблицаЗаполнения = Запрос.Выполнить().Выгрузить();
Сообщить("2 Приступаем к обработке результата запроса к регистру """ + ИмяРегистраСведений + """ - " + ТекущаяДата());
// заполнение строки progress bar
ЭлементыФормы.Индикатор2.Значение = 0; // обнуляем, чтобы при повторном запуске статусбар сбросился в 0
ЭлементыФормы.Индикатор2.МаксимальноеЗначение = ТаблицаЗаполнения.Количество(); // задаем значение для 100%
// для каждой строки таблицы значений установим отбор и перезапишем регистр
Для Каждого СтрокаЗаполнения Из ТаблицаЗаполнения Цикл
ЭлементыФормы.Индикатор2.Значение = ЭлементыФормы.Индикатор2.Значение + 1; //указываем прирост внутри цикла
// попробуем через СоздатьМенеджерЗаписи()
текЗапись = РегистрыСведений[ИмяРегистраСведений].СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(текЗапись, СтрокаЗаполнения);
// прочитаем эту запись (внимание, эта команда обязательна, иначе можно ненароком очистить весь регистр!)
текЗапись.Прочитать();
Если текЗапись.Выбран() Тогда // убедились, что спозиционироваться удалось
// сообщаем, что именно и на какое значение нужно изменить в регистре
текЗапись[ИмяИзменяемогоРесурса] = НовоеЗначениеРесурса;
// записываем изменения в регистре
текЗапись.Записать();
Иначе // спозиционироваться не удалось, можно выходить
Сообщить("Возникла проблема определения " + НовоеЗначениеРесурса + " в регистре через менеджер записи " + НовоеЗначениеРесурса);
КонецЕсли;
КонецЦикла;
Сообщить("3 Окончание исправления регистра """ + ИмяРегистраСведений + """ - " + ТекущаяДата());
КонецПроцедуры // ЗаменаИзмеренияНезависимогоРегистра()
Категория:
Регистры сведений Использование регулярных выражений (RegExp) в 1С Регулярные выражения (Regular Expressions) являются известным и мощным средством для поиска, тестирования и замены подстрок. Эта технология доступна и в 1С - через объект VBScript.RegExp. Нужный объект уже встроен в современные версии Windows (начиная с Windows 98), и устанавливать дополнительно ничего не нужно.
Приведенные ниже примеры были протестированы в 1С:Предприятие 7.7; для 1С:Предприятие 8.x изменяется способ создания объекта:
Код 1C v 8.х RegExp = Новый COMОбъект("VBScript.RegExp");
Кроме того, там уже есть логические константы Истина и Ложь - объявлять их не нужно.
Более подробное описание самой технологии RegExp (что означают те или иные значки или скобочки, или какие шаблоны поиска или замены можно использовать в типичных ситуациях) можно найти в специальной литературе (например Бен Форта "Освой самостоятельно регулярные выражения (regexp) за 10 минут") или на сайтах в сети Internet.
Код 1C v 7.x ///////////////////////////////////////////////////////////////////////
//Поиск вхождений подстроки
Процедура RegExp_Exec()
//Для 1С 7.7:
Истина=-1;
Ложь=0;
RegExp = CreateObject("VBScript.RegExp");
RegExp.IgnoreCase = Ложь; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим
RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML
Matches=RegExp.Execute("Это <hr> строка <br> с тегами HTML");
ЧислоВхождений=Matches.Count();
Если ЧислоВхождений>0 Тогда
Для к = 0 По ЧислоВхождений-1 Цикл
Match = Matches.Item(к);
Сообщить("Найден тег:"+ Match.Value);
КонецЦикла;
Иначе
Сообщить("Вхождений шаблона не найдено");
КонецЕсли;
//Выдаст в окно сообщений:
//Найден тег:<hr>
//Найден тег:<br>
КонецПроцедуры
Более продвинутый пример разбора HTML использует подвыражения (SubMatches) и позволяет находить как сами теги, так и текст между ними.
Код 1C v 7.x ///////////////////////////////////////////////////////////////////////
//Поиск вхождений подстроки с использованием подвыражений
Процедура RegExp_Exec1()
//Для 1С 7.7:
Истина=-1;
Ложь=0;
RegExp = CreateObject("VBScript.RegExp");
RegExp.IgnoreCase = Ложь; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим
RegExp.Pattern = "([^<]*)(<[^>]*>)([^<]*)"; //Ищем теги HTML, а также текст до и после тега
Matches=RegExp.Execute(" <tr><td id=aaa>Дятел <td> долбит <td> сосну </tr>");
ЧислоВхождений=Matches.Count();
Если ЧислоВхождений>0 Тогда
Для к = 0 По ЧислоВхождений-1 Цикл
Match = Matches.Item(к);
SubMatches = Match.SubMatches;
ЧислоПодвыражений=SubMatches.Count();
Для н = 0 По ЧислоПодвыражений-1 Цикл
SubMatch=SubMatches.Item(н);
Если SubMatch="" Тогда
Продолжить;
КонецЕсли;
Сообщить("Подстрока: "+SubMatch);
КонецЦикла;
КонецЦикла;
Иначе
Сообщить("Вхождений шаблона не найдено");
КонецЕсли;
КонецПроцедуры
//Выводит в окно сообщений:
//Подстрока:
//Подстрока: <tr>
//Подстрока: <td id=aaa>
//Подстрока: Дятел
//Подстрока: <td>
//Подстрока: долбит
//Подстрока: <td>
//Подстрока: сосну
//Подстрока: </tr>
Часто регулярные выражения используются для тестирования строк, например пользовательского ввода.
Этот пример позволяет узнать, является ли строка целым числом.
Код 1C v 7.x ///////////////////////////////////////////////////////////////////////
//Проверка подстроки
Процедура RegExp_Test()
RegExp = CreateObject("VBScript.RegExp");
RegExp.Pattern = "^\d+$"; //Шаблон, который соответствует целому числу
стр="12345";//Строка, которую тестируем
Если RegExp.Test(стр)=0 Тогда
Сообщить("Это не целое число");
Иначе
Сообщить("Это целое число");
КонецЕсли;
//Выдаст в окно сообщений:
//"Это целое число"
КонецПроцедуры
Регулярные выражения поддерживают не только поиск, но и
замену текста. При этом найденные подвыражения (в круглых скобках) могут быть представлены в строке замены как $1, $2 и т. д.
(знак доллара используется в VBScript.RegExp; в других средах программирования, например в JavaScript, используемый для этой цели символ может отличаться).
Код 1C v 7.x ///////////////////////////////////////////////////////////////////////
//Замена текста в подстроке
Процедура RegExp_Replace()
//Строка, где мы будем производить замены
стр="Дятел долбил сосну";
Истина=-1;
Ложь=0;
RegExp = CreateObject("VBScript.RegExp");
RegExp.IgnoreCase = Истина; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Истина; //Многострочный режим
RegExp.Pattern = "(долбил)";
стр=RegExp.Replace(стр, "про$1");
Сообщить(стр);
//Выдаст в окно сообщений:
//"Дятел продолбил сосну"
КонецПроцедуры
Источник Категория:
Регулярные выражения Как сформировать новый документ на основании файла, шаблона Microsoft Office Word и OpenOffice? Код 1C v 8.х Перем СсылкаНаДокумент;
Процедура СформироватбФайл_MS_Word_И_OpenOffice(Кнопка)
ДокументСсылка = СсылкаНаДокумент;
ИмяФайла = ПолучитьИмяВременногоФайла();
// Теперь формируем файл из MS Wordа
Попытка
MSWord = новый COMОбъект("Word.Application");
//Передаем текущие параметры форм в MSWord
MSWord.Documents.Open(ИмяФайла);
MSWordDoc = MSWord.ActiveDocument();
WordContent = MSWord.ActiveDocument().ActiveWindow.S_election;
//------------------------------------------------------------
// Перебираем таблицы в документе, и сопоставляем имена переменных
// с именами табличных частей.
Для ТекущаяТаблица = 1 ПО MSWordDoc.Tables.Count Цикл
мТабличнаяЧасть = Неопределено;
Для ТекущаяСтрока = 1 ПО MSWordDoc.Tables(ТекущаяТаблица).Rows.Count Цикл
Для ТекущаяКолонка = 1 ПО MSWordDoc.Tables(ТекущаяТаблица).Columns.Count Цикл
мТабличнаяЧасть = ИмяТабличнойЧастиВСтроке(
ПолучитьСтартПеременной( MSWordDoc.Tables(ТекущаяТаблица).Cell(ТекущаяСтрока,ТекущаяКолонка).Range.Text )
,ДокументСсылка);
Если мТабличнаяЧасть <> Неопределено Тогда
Прервать;;
КонецЕсли;
КонецЦикла;
Если мТабличнаяЧасть <> Неопределено Тогда
Прервать;;
КонецЕсли;
КонецЦикла;
//Итак мы имеем номер текущей таблицы и имя табличной части
Если мТабличнаяЧасть <> Неопределено Тогда
//Производим редактирование нашей таблицы в соответствии с количеством строк
ВсегоСтрокТЧ = 0;
Для Каждого строкаТЧ Из ДокументСсылка[мТабличнаяЧасть.Имя] Цикл
ВсегоСтрокТЧ = ВсегоСтрокТЧ+1;
КонецЦикла;
//ВсегоСтрокТЧ = ДокументСсылка[мТабличнаяЧасть.Имя].Количество;
// Добавляем строки
Для ТекущаяСтрокаТЧ = 1 По ВсегоСтрокТЧ Цикл
Если ТекущаяСтрокаТЧ <> ВсегоСтрокТЧ Тогда
MSWordDoc.Tables(ТекущаяТаблица).Rows.Add(MSWordDoc.Tables(ТекущаяТаблица).Rows(ТекущаяСтрока+ТекущаяСтрокаТЧ-1));
КонецЕсли;
//MSWordDoc.Tables(ТекущаяТаблица).Cell(ТекущаяСтрока+ТекущаяСтрокаТЧ-1,2).Range.Text = Строка(ТекущаяСтрокаТЧ);
Для ТекКол = 1 ПО MSWordDoc.Tables(ТекущаяТаблица).Columns.Count Цикл
Если ТекущаяСтрокаТЧ <> ВсегоСтрокТЧ Тогда
ТекстПеременной = ПолучитьПеременнуюИзСтроки(СокрЛП(MSWordDoc.Tables(ТекущаяТаблица).Cell(ТекущаяСтрока+ТекущаяСтрокаТЧ,ТекКол).Range.Text));
ТекстПеременной = ?(ПустаяСтрока(ТекстПеременной),"", "["+"_"+Строка(ТекущаяСтрокаТЧ)+"_"+ТекстПеременной+"]");
MSWordDoc.Tables(ТекущаяТаблица).Cell(ТекущаяСтрока+ТекущаяСтрокаТЧ-1,ТекКол).Range.Text = ТекстПеременной;
Иначе
ТекстПеременной = ПолучитьПеременнуюИзСтроки(СокрЛП(MSWordDoc.Tables(ТекущаяТаблица).Cell(ТекущаяСтрока+ТекущаяСтрокаТЧ-1,ТекКол).Range.Text));
ТекстПеременной = ?(ПустаяСтрока(ТекстПеременной),"", "["+"_"+Строка(ТекущаяСтрокаТЧ)+"_"+ТекстПеременной+"]");
MSWordDoc.Tables(ТекущаяТаблица).Cell(ТекущаяСтрока+ТекущаяСтрокаТЧ-1,ТекКол).Range.Text = ТекстПеременной;
КонецЕсли;
КонецЦикла;
КонецЦикла;
//MSWordDoc.Tables(ТекущаяТаблица).Rows.Delete();
//MSWordDoc.Tables(ТекущаяТаблица).Rows(3).Delete();
КонецЕсли;
КонецЦикла;
//------------------------------------------------------------
// Вытаскивам из шаблона текст
ТекстДокумента = MSWordDoc.Range(0, MSWordDoc.Characters.Count).Text;
// Из текста вытаскиваем Имена переменных залюченных а скобки []
Список = ПолучитьСписокПеременных(ТекстДокумента);
//Список.ВыбратьЭлемент();
// Заполняем в структуру ревизитовперечень переменных
СтруктураРеквизитов=СтруктураРеквизитовДокумента(ДокументСсылка);
ЗначениеРеквизита="";
Для Каждого ЭлементСписка Из Список Цикл
// Если находится соответствие переменной из документа и шаблона то производим замену
Если СтруктураРеквизитов.Свойство(ЭлементСписка.Значение, ЗначениеРеквизита ) Тогда
//Сообщить("["+ЭлементСписка.Значение+"]"+" : "+ЗначениеРеквизита);
WordContent.Find.Execute("["+ЭлементСписка.Значение+"]",0,0,0,0,0,-1,,,Строка(ЗначениеРеквизита),2);
Иначе
Сообщить("-> " + ЭлементСписка.Значение+" - Не найден в структуре документа");
// Заменим переменную на пустую строку
WordContent.Find.Execute("["+ЭлементСписка.Значение+"]",0,0,0,0,0,-1,,," ",2);
КонецЕсли;
КонецЦикла;
//автоматически обновляем поля документа
MSWord.S_election.WholeStory();
MSWord.S_election.Fields.Update();
MSWord.S_election.HomeKey();
//MSWordDoc.SaveAs(ИмяФайла);
//отображаем MSWord
MSWord.Visible=1;
MSWord.Activate();
Исключение
Предупреждение(ОписаниеОшибки());
MSWord.Quit();
КонецПопытки;
// Теперь формируем файл из OpenOffice
Попытка
ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
Reflection = ServiceManager.createInstance("com.sun.star.reflection.CoreReflection");
Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");
Args = Новый COMSafeArray("VT_DISPATCH", 1);
OOДокумент = Desktop.loadComponentFromURL(ПреобразоватьВURL(ИмяФайла), "_blank", 0, Args);
//------------------------------------------------------------
// Перебираем таблицы в документе, и сопоставляем имена переменных
// с именами табличных частей.
Для ТекущаяТаблица = 0 ПО OOДокумент.getTextTables().Count-1 Цикл
мТабличнаяЧасть = Неопределено;
Для ТекущаяСтрока = 0 ПО OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).Rows.Count-1 Цикл
Для ТекущаяКолонка = 0 ПО OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).Columns.Count-1 Цикл
мТабличнаяЧасть = ИмяТабличнойЧастиВСтроке(
ПолучитьСтартПеременной( OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).getCellByPosition(ТекущаяКолонка, ТекущаяСтрока).string )
,ДокументСсылка);
Если мТабличнаяЧасть <> Неопределено Тогда
Прервать;;
КонецЕсли;
КонецЦикла;
Если мТабличнаяЧасть <> Неопределено Тогда
Прервать;;
КонецЕсли;
КонецЦикла;
//Итак мы имеем номер текущей таблицы и имя табличной части
Если мТабличнаяЧасть <> Неопределено Тогда
//Производим редактирование нашей таблицы в соответствии с количеством строк
ВсегоСтрокТЧ = 0;
Для Каждого строкаТЧ Из ДокументСсылка[мТабличнаяЧасть.Имя] Цикл
ВсегоСтрокТЧ = ВсегоСтрокТЧ+1;
КонецЦикла;
//ВсегоСтрокТЧ = ДокументСсылка[мТабличнаяЧасть.Имя].Количество;
// Добавляем строки
Для ТекущаяСтрокаТЧ = 1 По ВсегоСтрокТЧ Цикл
Если ТекущаяСтрокаТЧ <> ВсегоСтрокТЧ Тогда
// Добавляем строку перед нашей
OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).Rows.I_nsertByIndex(ТекущаяСтрока+ТекущаяСтрокаТЧ-1, 1);
КонецЕсли;
Для ТекКол = 0 ПО OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).Columns.Count-1 Цикл
Если ТекущаяСтрокаТЧ <> ВсегоСтрокТЧ Тогда
ТекстПеременной = ПолучитьПеременнуюИзСтроки(СокрЛП(OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).getCellByPosition(ТекКол, ТекущаяСтрока+ТекущаяСтрокаТЧ).string));
ТекстПеременной = ?(ПустаяСтрока(ТекстПеременной),"", "["+"_"+Строка(ТекущаяСтрокаТЧ)+"_"+ТекстПеременной+"]");
OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).getCellByPosition(ТекКол, ТекущаяСтрока+ТекущаяСтрокаТЧ-1).string = ТекстПеременной;
Иначе
ТекстПеременной = ПолучитьПеременнуюИзСтроки(СокрЛП(OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).getCellByPosition(ТекКол, ТекущаяСтрока+ТекущаяСтрокаТЧ-1).string));
ТекстПеременной = ?(ПустаяСтрока(ТекстПеременной),"", "["+"_"+Строка(ТекущаяСтрокаТЧ)+"_"+ТекстПеременной+"]");
OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).getCellByPosition(ТекКол, ТекущаяСтрока+ТекущаяСтрокаТЧ-1).string = ТекстПеременной;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЦикла;
//------------------------------------------------------------
// Вытаскивам из шаблона текст
//ТекстДокумента = MSWordDoc.Range(0, MSWordDoc.Characters.Count).Text;
ТекстДокумента = ООПолучитьТекст(OOДокумент);
// Из текста вытаскиваем Имена переменных залюченных а скобки []
Список = ПолучитьСписокПеременных(ТекстДокумента);
//Список.ВыбратьЭлемент();
// Заполняем в структуру ревизитовперечень переменных
СтруктураРеквизитов=СтруктураРеквизитовДокумента(ДокументСсылка);
ЗначениеРеквизита="";
OOЗамена = OOДокумент.CreateReplaceDescriptor();
Для Каждого ЭлементСписка Из Список Цикл
// Если находится соответствие переменной из документа и шаблона то производим замену
Если СтруктураРеквизитов.Свойство(ЭлементСписка.Значение, ЗначениеРеквизита ) Тогда
OOЗамена.SearchString = "["+ЭлементСписка.Значение+"]";
OOЗамена.ReplaceString = Строка(ЗначениеРеквизита);
OOДокумент.ReplaceAll(OOЗамена);
Иначе
Сообщить("-> " + ЭлементСписка.Значение+" - Не найден в структуре документа");
// Заменим переменную на пустую строку
OOЗамена.SearchString = "["+ЭлементСписка.Значение+"]";
OOЗамена.ReplaceString = " ";
OOДокумент.ReplaceAll(OOЗамена);
КонецЕсли;
КонецЦикла;
OOДокумент.getCurrentController().getFrame().getContainerWindow().setFocus();
Исключение
Предупреждение(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Код 1C v 8.х //ДОПОЛНИТЕЛЬНО НЕОБХОДИМЫЕ ФУНКЦИИ
// Добавлем форматы представления полей и дополнительную информацию о полях
Процедура ДобавитьФорматы(ПереченьРеквизитов,Значение,пПредставлениеРеквизита, ДокументСсылка = Неопределено)
Если ТипЗнч(Значение) = Тип("Дата") Тогда // расширяем представление даты
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"ДФddMMyyyy",Формат(Значение,"ДФ=dd.MM.yyyy"));
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"ДЛФDD",Формат(Значение,"ДЛФ=DD"));
ИначеЕсли ТипЗнч(Значение) = Тип("Число") Тогда // расширяем представление числа
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"ЧДЦ2ЧГ0",Формат(Значение,"ЧДЦ=2; ЧГ=0"));
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"ЧДЦ2",Формат(Значение,"ЧДЦ=2"));
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"ЧПропись",Значение);
ИначеЕсли (ТипЗнч(Значение) = Тип("СправочникСсылка.КонтактныеЛица")) или (ТипЗнч(Значение) = Тип("СправочникСсылка.ФизическиеЛица")) Тогда
// Расширяем выводимые поля для типов физ. лица, контакные лица сокращением инициалов
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"ФИО",Строка(Значение));
КонецЕсли
КонецПроцедуры
Процедура ЗаполнитьРеквизиты(мГлубинаРекурсии,ПереченьРеквизитов,РеквизитСсылка,Реквизит,пПредставлениеРеквизита)
мГлубинаРекурсии = мГлубинаРекурсии+1;
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"Код",РеквизитСсылка["Код"]);
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+"Наименование",РеквизитСсылка["Наименование"]);
Для Каждого ЭлементРеквизита Из Реквизит.Реквизиты Цикл
ПереченьРеквизитов.Вставить(пПредставлениеРеквизита+"_"+ЭлементРеквизита.Имя,РеквизитСсылка[ЭлементРеквизита.Имя]);
Если (Найти(ЭлементРеквизита.Тип,"Справочник ссылка")>0) И (мГлубинаРекурсии <=3) И (Найти(ЭлементРеквизита.Тип,",")=0) Тогда
///+++
ЗаполнитьРеквизиты(мГлубинаРекурсии, ПереченьРеквизитов,РеквизитСсылка[ЭлементРеквизита.Имя],РеквизитСсылка[ЭлементРеквизита.Имя].Метаданные(),пПредставлениеРеквизита+"_"+ЭлементРеквизита.Имя);
Иначе
ДобавитьФорматы(ПереченьРеквизитов,РеквизитСсылка[ЭлементРеквизита.Имя],пПредставлениеРеквизита+"_"+ЭлементРеквизита.Имя);
КонецЕсли
КонецЦикла;
КонецПроцедуры
Функция ПолучитьСписокПеременных(ТекстШаблона)
СписокПеременных = Новый СписокЗначений();
ЕщеЕсть = Истина;
Пока ЕщеЕсть Цикл
ПервыйСимвол = Найти(ТекстШаблона,"[");
Если ПервыйСимвол > 0 Тогда
ВторойСимвол = Найти(ТекстШаблона,"]");
Если (ВторойСимвол > 0 И ВторойСимвол > ПервыйСимвол) Тогда
СписокПеременных.Добавить(Сред(ТекстШаблона,ПервыйСимвол + 1,ВторойСимвол - ПервыйСимвол - 1));
ТекстШаблона = Сред(ТекстШаблона,ВторойСимвол + 1);
Иначе
ЕщеЕсть = Ложь;
КонецЕсли;
Иначе
ЕщеЕсть = Ложь;
КонецЕсли;
КонецЦикла;
Возврат СписокПеременных;
КонецФункции
Функция СтруктураРеквизитовДокумента(ДокументСсылка) Экспорт
ПереченьРеквизитов = Новый Структура;
ПереченьРеквизитов.Вставить("Дата",ДокументСсылка["Дата"]);
ДобавитьФорматы(ПереченьРеквизитов,ДокументСсылка["Дата"],"Дата");
ПереченьРеквизитов.Вставить("Номер",ДокументСсылка["Номер"]);
Реквизиты = ДокументСсылка.Метаданные().Реквизиты;
Для Каждого Реквизит Из Реквизиты Цикл
мГлубинаРекурсии = 1;
ПереченьРеквизитов.Вставить(Реквизит.Имя,ДокументСсылка[Реквизит.Имя]);
ДобавитьФорматы(ПереченьРеквизитов,ДокументСсылка[Реквизит.Имя],Реквизит.Имя,ДокументСсылка);
Если Найти(Реквизит.Тип,"Справочник ссылка")>0 Тогда
ЗаполнитьРеквизиты(мГлубинаРекурсии,ПереченьРеквизитов,ДокументСсылка[Реквизит.Имя],ДокументСсылка[Реквизит.Имя].Метаданные(),Реквизит.Имя);
Иначе
//ДобавитьФорматы(ПереченьРеквизитов,ДокументСсылка[Реквизит.Имя],Реквизит.Имя);
КонецЕсли;
КонецЦикла;
ТабличныеЧасти = ДокументСсылка.Метаданные().ТабличныеЧасти;
Для Каждого ТабличнаяЧасть Из ТабличныеЧасти Цикл
// Сообщить(ТабличнаяЧасть); // Для таблицы характеристик отрабатываем свой код // с выводом табличной части как набора реквизитов
Если ТабличнаяЧасть.Имя = "Характеристики" Тогда
Для Каждого СтрокаТабличнойЧасти Из ДокументСсылка[ТабличнаяЧасть.Имя] Цикл
мПредставлениеРеквизита = "Характеристика"+"_"+СтрЗаменить(СтрокаТабличнойЧасти["ВидХарактеристики"], " ", "_");
мЗначение = СтрокаТабличнойЧасти["ЗначениеХарактеристики"];
ПереченьРеквизитов.Вставить(мПредставлениеРеквизита,мЗначение);
ДобавитьФорматы(ПереченьРеквизитов,мЗначение,мПредставлениеРеквизита,ДокументСсылка);
Если Найти(ТипЗнч(мЗначение),"Справочник ссылка")>0 Тогда
ЗаполнитьРеквизиты(мГлубинаРекурсии,ПереченьРеквизитов,мЗначение,мЗначение.Метаданные(),мПредставлениеРеквизита);
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Перечень реквизитов табличной части
Реквизиты = ТабличнаяЧасть.Реквизиты;
Для Каждого Реквизит Из Реквизиты Цикл
Для Каждого СтрокаТабличнойЧасти Из ДокументСсылка[ТабличнаяЧасть.Имя] Цикл
мГлубинаРекурсии = 1;
мПредставлениеРеквизита = "_"+СтрокаТабличнойЧасти.НомерСтроки+"_"+ТабличнаяЧасть.Имя+"_НомерСтроки";
ПереченьРеквизитов.Вставить(мПредставлениеРеквизита,Строка(СтрокаТабличнойЧасти.НомерСтроки));
мПредставлениеРеквизита = "_"+СтрокаТабличнойЧасти.НомерСтроки+"_"+ТабличнаяЧасть.Имя+"_"+Реквизит.Имя;
мЗначение = СтрокаТабличнойЧасти[Реквизит.Имя];
ПереченьРеквизитов.Вставить(мПредставлениеРеквизита,мЗначение);
ДобавитьФорматы(ПереченьРеквизитов,мЗначение,мПредставлениеРеквизита,ДокументСсылка);
Если Найти(ТипЗнч(мЗначение),"Справочник ссылка")>0 Тогда
ЗаполнитьРеквизиты(мГлубинаРекурсии,ПереченьРеквизитов,мЗначение,мЗначение.Метаданные(),мПредставлениеРеквизита);
Иначе
//ДобавитьФорматы(ПереченьРеквизитов,мЗначение,мПредставлениеРеквизита);
КонецЕсли;
КонецЦикла;
//Если реквизит числовой, то подсчитываем итог
Если Реквизит.Тип.СодержитТип(Тип("Число")) Тогда
мЗначение = ДокументСсылка[ТабличнаяЧасть.Имя].Итог(Реквизит.Имя);
мПредставлениеРеквизита = "Итог"+"_"+ТабличнаяЧасть.Имя+"_"+Реквизит.Имя;
ПереченьРеквизитов.Вставить(мПредставлениеРеквизита,мЗначение);
ДобавитьФорматы(ПереченьРеквизитов,мЗначение,мПредставлениеРеквизита,ДокументСсылка);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат ПереченьРеквизитов;
КонецФункции
Функция ИмяТабличнойЧастиВСтроке(Строка,ДокументСсылка)
ТабличнаяЧасть=Неопределено;
Если НЕ ПустаяСтрока(Строка) Тогда
ТабличнаяЧасть = ДокументСсылка.Метаданные().ТабличныеЧасти.Найти(Строка)
КонецЕсли;
Возврат ТабличнаяЧасть;
КонецФункции
//Получает первый кусок переменной до _
Функция ПолучитьСтартПеременной(ПереданнаяСтрока) Экспорт
СтартПеременной = "";
ПервыйСимвол = Найти(ПереданнаяСтрока,"[");
Если ПервыйСимвол > 0 Тогда
ВторойСимвол = Найти(ПереданнаяСтрока,"]");
Если (ВторойСимвол > 0) И (ВторойСимвол > ПервыйСимвол) Тогда
Переменная = (Сред(ПереданнаяСтрока,ПервыйСимвол+1,ВторойСимвол-ПервыйСимвол-1));
ВторойСимвол = Найти(Переменная,"_");
Если (ВторойСимвол > 0) И (ВторойСимвол > 1) Тогда
СтартПеременной = Сред(Переменная,1,ВторойСимвол-1);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат СтартПеременной;
КонецФункции
// Получает переменную заключенную в скобки
Функция ПолучитьПеременнуюИзСтроки(ПереданнаяСтрока) Экспорт
Переменная = "";
ПервыйСимвол = Найти(ПереданнаяСтрока,"[");
Если ПервыйСимвол > 0 Тогда
ВторойСимвол = Найти(ПереданнаяСтрока,"]");
Если (ВторойСимвол > 0) И (ВторойСимвол > ПервыйСимвол) Тогда
Переменная = (Сред(ПереданнаяСтрока,ПервыйСимвол+1,ВторойСимвол-ПервыйСимвол-1));
КонецЕсли;
КонецЕсли;
Возврат Переменная;
КонецФункции// Идентифицирует табличную часть в строке
// Функция преобразует Windows имя файла в URL OpenOffice
Функция ПреобразоватьВURL(ИмяФайла)
Возврат "file:///" + СтрЗаменить(ИмяФайла, "\", "/");
КонецФункции
// Функция извлекает текст из документа
Функция ООПолучитьТекст(OOДокумент)
Текст = "";
oParEnum = OOДокумент.getText().createEnumeration();
Пока oParEnum.hasMoreElements() Цикл
oPar = oParEnum.nextElement();
Если oPar.supportsService("com.sun.star.text.Paragraph") ТОгда
Текст = Текст + oPar.getString();
ИначеЕсли oPar.supportsService("com.sun.star.text.TextTable") Then
//Сообщить(oPar.getString());
КонецЕсли;
КонецЦикла;
Для ТекущаяТаблица = 0 ПО OOДокумент.getTextTables().Count-1 Цикл
Для ТекущаяСтрока = 0 ПО OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).Rows.Count-1 Цикл
Для ТекущаяКолонка = 0 ПО OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).Columns.Count-1 Цикл
Текст = Текст + OOДокумент.getTextTables().getByIndex(ТекущаяТаблица).getCellByPosition(ТекущаяКолонка, ТекущаяСтрока).string;
КонецЦикла;
КонецЦикла;
КонецЦикла;
Возврат Текст;
КонецФункции
Категория:
Работа с Microsoft Office и OpenOffice Функция разбора (разложения) строки в массив Данные функции позволяют разложить строку в массив, используя заданный разделитель
Например есть строка: абв$dfd$232$-0oj$5
Выполнив код: НашМассив = РазложитьСтрокуВМассив(абв$dfd$232$-0oj$5, "$") ;
Получим: НашМассив = абв
dfd
232
-0oj
5
Код 1C v 8.х
// Функция "расщепляет" строку на подстроки, используя заданный
// разделитель. Разделитель может иметь любую длину.
// Если в качестве разделителя задан пробел, рядом стоящие пробелы
// считаются одним разделителем, а ведущие и хвостовые пробелы параметра Стр
// игнорируются.
// Например,
// РазложитьСтрокуВМассивПодстрок(",ку,,,му", ",") возвратит массив значений из пяти элементов,
// три из которых - пустые строки, а
// РазложитьСтрокуВМассивПодстрок(" ку му", " ") возвратит массив значений из двух элементов
//
// Параметры:
// Стр - строка, которую необходимо разложить на подстроки.
// Разделитель - строка-разделитель, по умолчанию - запятая.
//
// Возвращаемое значение:
// массив значений, элементы которого - подстроки
//
Функция РазложитьСтрокуВМассив(Знач Стр, Разделитель = ",") Экспорт
МассивСтрок = Новый Массив();
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
КонецФункции
Пример с использованием предустановленной библиотеки RegExp, т.е. она есть в любом windows.
Плюсы RegExp:
1. Хорошая скорость анализа, т.к. 1С анализ строк (разбор) обычно реализуется циклами и функциями: Лев, Прав, Сред, Найти, а встроенный язык медленный
2. Высокая читаемость и модифицированность (более предсказуем в случае несоответствия строки - разбору)
3. Дополнительный функционал (можно осуществлять анализ,
замену и проверку строковых выражений)
Минусы RegExp:
1. Не все задачи можно решить (например рекурсивные разборы тип 1 + (2+3*(2-7)) в случае если нужно разобрать на выражения в скобках) приходится смешивать с кодом.
2. Возможность зависания при использовании сложных шаблонов(редкость, но бывает).
3. RegExp - это дополнительная библиотека и инициализация занимает значительное время.
Код 1C v 8.х // Пример с использованием предустановленной библиотеки RegExp, т.е. она есть в любом windows.
Функция РазложитьСтрокуВМассив(Строка, Разделитель = ",") Экспорт
RegExp = Новый COMОбъект("VBScript.RegExp"); // создаем объект для работы с регулярными выражениями
//Параметры:
RegExp.MultiLine = Ложь; // истина — текст многострочный, ложь — одна строка
RegExp.Global = Истина; // истина — поиск по всей строке, ложь — до первого совпадения
RegExp.IgnoreCase = Ложь; // истина — игнорировать регистр строки при поиске
//Разбор строки вида 1,СЛОВО,(1+2); Маска для разделителя ',' [^\,]*"
RegExp.Pattern = "[^\" + Разделитель + "]+";
Matches = RegExp.Execute (Строка);
Массив = Новый Массив;
Для Сч = 0 По Matches.Count - 1 Цикл
Массив.Добавить(Matches.Item(Сч).Value);
КонецЦикла;
RegExp = Неопределено;
Возврат Массив;
КонецФункции
Посмотрите
Функцию разложить строку на подстроки (в список значений), используя заданный разделитель. Категория:
Работа с Текстом (Строкой) Быстрый перенос списка баз с одного компьютера на другой Для 8.1 :
1. Список баз 8.1 можно сохранять в файл.Для этого правой кнопкой мыши по корневому элементу "
Информационные базы ", далее "
Сохранить ссылку в файл ".
2. Получаем файл с расширением
v8i , это текстовый файл в кодировке UTF-8.
Если необходимо, то при помощи любого текстового редактора в файле можно провести замену , например заменить имя сервера приложений и т.д.
3. Далее можно загрузить этот файл со списком баз (только предварительно очистите существующий список баз) щелкнув двойным щелчком на нем.
или - Как прописать список баз всем пользователям?
1. Для начала формируем список баз у одного пользователя вручную.
2. Данный список хранится в файле
c:\Documents and Settings\[Имя Пользователя]\Application Data\1C\1CEStart\ibases.v8i
3. Копируем этот файл и файл 1CEStart.cfg всем остальным пользователям по указанному пути.
Для 7.7 :
На компьютере из которого нужно выгрузить список баз запускаем:
Код DOS Batch File regedit /ea 1СBase.reg HKEY_CURRENT_USER\Software\1C\1Cv7\7.7\Titles
В результате получается reg файл 1СBase.reg со списком баз, запускаем его на другом компьютере, запускаем 1С и базы уже занесены
Категория:
Администрирование Значения NULL ( ЕСТЬ NULL и ЕСТЬNULL()) NULL – отсутствующие значения.
Не путать с нулевым значением! NULL – это не число, не равно пробелу, пустой ссылке, Неопределено.
NULL – типообразующее значение, т.е. есть тип NULL и единственное значение этого типа.
NULL значения появляются в запросе в следующих ситуациях:
а) Внешнее соединение, при котором не было найдено соответствующей записи в другой таблице (при левом – во второй, при правом – в первой, при полном – в обоих)
б) Обращение к реквизитам элементов для группы и наоборот.
в) NULL в списке полей выборки (ВЫБРАТЬ)
г) Обращение к реквизитам для битой ссылки
ЕСТЬ NULL используется в операторе ВЫБРАТЬ (как бы проверя, что значение это есть пустое ( Значение ЕСТЬ NULL )):
Код 1C v 8.х
ВЫБОР
КОГДА Значение ЕСТЬ NULL ТОГДА РезультатЕслиNULL
ИНАЧЕ Значение
КОНЕЦ
еще пример:
Код 1C v 8.х ВЫБРАТЬ
СправочникНоменклатуры.Наименование,
ВЫБОР КОГДА УчетНоменклатурыОстатки.КоличествоОстаток ЕСТЬ NULL ТОГДА 0
ИНАЧЕ УчетНоменклатурыОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатуры
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.УчетНоменклатуры.Остатки КАК УчетНоменклатурыОстатки
ПО УчетНоменклатурыОстатки.Номенклатура = СправочникНоменклатуры.Ссылка
ГДЕ
СправочникНоменклатуры.ЭтоГруппа = ЛОЖЬ
Функция
ЕСТЬNULL (значение, РезультатЕслиNULL) возвращает значение своего первого параметра, в случае если он не равен NULL, и значение второго параметра в противном случае
Является свернутым ВЫБОР…КОНЕЦ, но ЕСТЬNULL предпочтительнее.
Код 1C v 8.х
ВЫБРАТЬ
ЕСТЬNULL(Справочник.Номенклатура.Артикул, "---") КАК Артикул,
Справочник.Номенклатура.Представление КАК Номенклатура
еще пример:
Код 1C v 8.х
ВЫБРАТЬ
СправочникНоменклатуры.Наименование,
ЕСТЬNULL(УчетНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатуры
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.УчетНоменклатуры.Остатки КАК УчетНоменклатурыОстатки
ПО УчетНоменклатурыОстатки.Номенклатура = СправочникНоменклатуры.Ссылка
ГДЕ
СправочникНоменклатуры.ЭтоГруппа = ЛОЖЬ
В данном примере получаются все элементы справочника номенклатуры, после чего, для каждой номенклатуры из регистра накопления получаются текущие остатки. Т.к. для номенклатуры, по которой отсутствуют остатки, виртуальная таблица остатков не запись вернет, то в результате соединения в поле "УчетНоменклатурыОстатки.КоличествоОстаток" будут значения NULL для номенклатуры, по которой не было остатков. Для того чтобы вместо значения NULL в результате запроса присутствовало значение 0, мы использовали функцию ЕСТЬNULL(), которая осуществит желаемую
замену .
ЕСТЬNULL отличается от ВЫБОР по следующим причинам:
а) При ЕСТЬNULL лучше читается запрос (проще)
б) При ЕСТЬNULL, если проверяется сложное выражение, то работает быстрее, поскольку вычисляется один раз
в) При ЕСТЬNULL выражение замены приводится к типу проверяемого выражения, если оно имеет тип Строка (длина) или Число (разрядность).
Нельзя проверять значения на NULL обычным равенством, потому что в SQL действует трехзначная логика – Истина, Ложь, NULL, и результатом такого сравнения будет UNKNOWN, что в 1С 8.0 аналогично ЛОЖЬ.
NULL <> 0, поэтому при левых внешних соединениях спр. Номенклатура с таблицами остатков, цен, Контрагентов со взаиморасчетами при отсутствии таких записей там будет NULL, который не равен 0. Лучшее решение – ЕСТЬNULL
Категория:
Запросы