Архив рубрики: 1С Предприятие 7.7

1С 7.7 Сравнение двух внешних отчетов (обработок)

Чтобы сравнить два внешних отчета (обработки) в 1С 7.7 можно воспользоваться функцией в меню: Файл — Сравнить файлы. Если оба файла окажутся внешними отчетами 1С 7.7, система предложит сравнить их тексты стандартным способом.
Если один отчет находится в конфигурации, а другой в файле, нужно выгрузить в файл и тот, который в конфигурации и сравнить. Как в 8.х сравнивать объекты конфигурации с файлами внешних отчетов и обработок я не нашел стандартных средств для этого.

Как программно переключить закладку в 1С 7.7

При переключении закладки в 1С 7.7 столкнулся с тем, что просто показать нужный слой ничего не дает.

То есть фраза:

Форма.ИспользоватьСлой ("Запрос");

Попросту «тушит» текущий слой, и не переходит на нужную закладку. В результате пустая форма.

Хорошо. Вспоминаю, что закладки — это банальный обьект «СписокЗначений». Делаю так:

Форма.Закладки.ТекущаяСтрока(2);

Форма.ИспользоватьСлой("Запрос");

Теперь работает

Для того, чтобы не путаться в закладках и слегка автоматизировать переключение, пишу так:

Форма.Закладки.ТекущаяСтрока(2);

ПриВыбореЗакладки (2,Форма.Закладки.ПолучитьЗначение(2));

Ну, а в процедуре "ПриВыбореЗакладки" уже описаны все действия, которые у меня происходят при смене закладок.

 

Как получить дату документа прямым запросом 1С 7.7++ пример

1С 7.7, прямые запросы, CPP, пример получения даты документа

SELECT

NullIf(Cast(Left(Жур.DATE_TIME_IDDOC, 8) AS datetime), '17530101') ДатаДок

......

FROM $РегистрОбороты.Обороты(:ДатаС,:ДатаПо~,Документ,

.........

  ) AS табОбороты

    INNER JOIN _1Sjourn AS жур ON RIGHT(табОбороты.ПозицияДокумента,9) = жур.IDDOC

Так как дата находится в таблице журнала, соединение с _1Sjourn обязательно

Пакетные запросы в 1С7.7 ++

В 1С 8.2 я нашел достаточно приятной возможность написания пакетных запросов. То есть когда в одном тексте подготавливаешь несколько результатов запроса и используешь в результатирующем. Другой вариант — постепенно приходить к окончательной выборке, разбив сложный запрос на ряд простых.

Подобный механизм можно реализовать и в 1С 7.7 в том случае, если у вас установлена библиотека CPP (v7plus.dll).

Принцип построения практически тот же. Разница в том, что в 1С8.2 можно выбирать результат любого из запросов в пакете. В 1С 7.7, к сожалению лишен такой возможности. Но остальные возможности SQL к вашим услугам.

Суть такова.

WITH таблица_1 AS
(SELECT f1,f2,f3 FROM my_table_1)

SELECT
таблица_1.f1
,таблица_1.f2
,f3 --можно и так
FROM
таблица_1

 Думаю, всё просто, принцип не нуждается в комментариях. Используем в результатирующем запросе алиасы таблиц, заключенные между WITH и AS, в нашем случае это «таблица_1», которая, в свою очередь является результатом запроса. Таких таблиц можно делать сколько угодно.  Можно ли делать подобные «пакетные» запросы вложенными, мною не тестировалось. Может быть кому нибудь из читателей захочется попробовать использовать этот принцип во вложенных запросах, буду рад почитать о результатах.

1C 7.7. Прямой запрос с группировкой без индексированной таблицы

Прямые запросы в 1С++ — это отличный способ в тысячи раз ускорить выборки данных по сравнению со стандартными запросами 1С 7.7. Особенно полезно для крупных баз, свыше 100Гб, где требуется оптимизация. Группировка индексной таблицей — это дополнительные затраты серверного ресурса, и порой долгие минуты ожидания для пользователя. Запросы с использованием ROLLUP позволят получать данные с итогами по группировкам уже в самом запросе.

К примеру, получим остатки.

ТекстЗапроса = "SELECT
|тмц [ТМЦ $Справочник.ТМЦ]
|,Партия [Партия $Справочник.Партии]
|,GROUPING(ТМЦ) AS ИтогПоТоварам 
|,GROUPING(Партия) AS ИтогПоПартиям
|,MAX(Склад) [Склад $Справочник.Склады]
|,MAX($спрТМЦ.БазЕдиница) [БазЕдиница $Перечисление.Единицы]
|,sum(КвоОстаток) as количество
|FROM
|$РегистрОстатки.Остатки(:ДатаПо~
|,
|,ВидУчета = :выбВидУчета
|,(ТМЦ,Партия,Склад)) AS ОстаткиТМЦ
|LEFT JOIN $Справочник.ТМЦ AS спрТМЦ
|ON ОстаткиТМЦ.ТМЦ = спрТМЦ.ID
|group BY ТМЦ,Партия WITH ROLLUP
|HAVING SUM(КвоОстаток) > 0
|ORDER BY ТМЦ,Партия,MAX(Склад), SUM(КвоОстаток) DESC";

Как видно из запроса, мы создаем две группы: ТМЦ и Партия.

Теперь поля приобртают значение в зависимости от уровня группировки: ИтогПоТоварам =1 и ИтогПоПартиям = 1 ,  — это общий итог.

ИтогПоТоварам =0 и ИтогПоПартиям = 1 , когда попадаем на строку с итогом по товару, куда «всуммировались» и итоги по каждой партии отдельно

ИтогПоТоварам =0 и ИтогПоПартиям = 0 , когда попадаем на строку с итогом по партии, который в свою очередь находится внутри итога по товару. Они же детальные строки.

Как можно использовать это?

Смотрим пример обхода результата выборки.

Запрос.УстановитьТекстовыйПараметр("ДатаПо",ДатаПо);
Запрос.УстановитьТекстовыйПараметр("выбВидУчета",выбВидУчета);
тз = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
//тз.выбратьСтроку();

ТабДок = СоздатьОбъект("Таблица");

КолВоСтрок = тз.КоличествоСтрок();
табДок = СоздатьОбъект("таблица")    ;
табДок.ИсходнаяТаблица("таблица");
.....

тз.ВыбратьСтроки();
нппТовар = 1;
нппПартия=1;
Пока тз.ПолучитьСтроку()=1 Цикл
 Если (тз.ИтогПоТоварам=1) И (тз.ИтогПоПартиям=1) Тогда
  Количество = тз.Количество;
  ТабДок.ВывестиСекцию ("Итого");
  нппПартия=1;
ИначеЕсли (тз.ИтогПоТоварам=0) И (тз.ИтогПоПартиям=1) Тогда
  ТМЦ = тз.ТМЦ;
  Количество = тз.Количество;
  ТабДок.ВывестиСекцию ("СтрокаТовара");
  нппТовар=нппТовар+1;
  нппПартия=1;
 ИначеЕсли тз.ИтогПоПартиям=0 тогда
  Партия = тз.Партия;
  Количество = тз.Количество;
  Склад = ТЗ.Склад;
  БазЕдиница = ТЗ.БазЕдиница;
  ТабДок.ВывестиСекцию ("СтрокаПартии");
  нппПартия=нппПартия+1;
 КонецЕсли;
 нпп=нпп+1;
 проц = Окр(нпп/КолВоСтрок*100,1,1);
 Состояние ("Вывод отчета "+Строка(проц)+"%");
КонецЦикла;

Ну и результат, привычно для отчетов, которые любят в 1С 8.х — когда итоги размещаются сверху групп, их не надо суммировать в переменные, или группировать в индексированной таблице. Всё выводится очень быстро и естественно.

 

Желаю удачи!

1C Выделене подстрок с помощью регулярного выражения

Пример тестировался на 1С 7.7, в 1С 8.х нужно только вместо «СоздатьОбъект» писать «Новый», ну и учитывать тот факт, что в восьмерке есть булев тип данных.

К примеру, перед нами задача, получить номер документа для вывода на печать налоговой накладной. Но в базе документы имеют примерно такие номера «FGT-00072», «AR-00120» и т.д. Если бы до тире было фиксированное число символов, можно было бы брать подстроку по знак «-«, затем брать из строки ту часть, которая стоит за минусом и применять чункцию Число(). В результате получим то, что нужно, то есть «FGT-00072» превратится в 72, а если вместо фиксированной части поиском найти позицию «-«, то и второй номер можно легко преобразовать. Но случаи бывают разные, я предлагаю создать универсальную функцию, с помощью которой вы можете находить любые подстроки, используя регулярное выражение.

Название функции возможно каламбурное, но не будем на это обращать внимание. Она получает текст, регулярное выражение применяемое к этому тексту и номер позиции, которую нужно возвратить.

Пример:

НомДокБН = регВырИгнорРегистр(Строка(«FGT-00072″),»([a-zA-Z]*)-?(0*?)([^0]\d*)»,2); //вернет «72»
ПостфиксБН = регВырИгнорРегистр(Строка(«03″),»(0*?)([^0]\d*)»,1);//Вернет «3» (универсальный убиратель ведущих нулей)

Мне такой подход понравился из-за универсальности, не нужно писать новые циклы и поиски с проверками под разные ситуации. Используем регулярное выражение и всё.

Собственно сама функция

//Выполняет поиск в строке по регулярному выражению
//номер позиции с нуля
//
функция регВырИгнорРегистр (текст, выражение, номерПозиции)
Если (ПустоеЗначение(текст)=1) ИЛИ (ПустоеЗначение(выражение) =1) ИЛИ (ПустоеЗначение(номерПозиции)=1) Тогда
возврат текст;
КонецЕсли;
Истина=-1;
Ложь=0;
RegExp = CreateObject(«VBScript.RegExp»);

RegExp.IgnoreCase = Истина; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим

RegExp.Pattern = выражение; //Ищем вхождение
Matches=RegExp.Execute(текст);
ЧислоВхождений=Matches.Count();
Если ЧислоВхождений>0 Тогда
Match = Matches.Item(0);
SubMatches = Match.SubMatches;
SubMatch=SubMatches.Item(номерПозиции);
возврат (SubMatch);
Иначе
возврат «»;
КонецЕсли;
Возврат «»;
КонецФункции

1С 7.7 функция распознавания типа значения

Гениальное просто
Гениальное просто

Эта функция использует регулярные выражения vbscript и может делить любое переданное значение на: целое число, число вообще, дату и строку. Изначально нужно передавать строковой параметр, к примету «12,5», функция вернет «Число», а если передать «12», тогда вернет «ЧислоЦелое»

Возвращает: Определяемый тип, возвращаемый тип — строка. Возможные варианты: «Число», «ЧислоЦелое», «Строка», «Дата».

Обратите внимание, что если передать в качестве параметра строку «12.0», будет возвращен параметр «Число», а не «ЧислоЦелое».

Применение: Я использую для определения типа при чтении данных из различных файлов типа excel, csv или ADO таблиц.

Текст функции:

Функция глОпределитьТипЯчейкиADO(Значение)
//Разделяет типы на строку, число и дату
 Если ПустоеЗначение(Значение)=1 тогда
  возврат 0;
 конецЕсли;
Значение=Строка(Значение);
Истина=-1;
Ложь=0;
RegExp = CreateObject("VBScript.RegExp");

RegExp.IgnoreCase = Ложь; //Игнорировать регистр
RegExp.Global = Истина; //Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; //Многострочный режим
//есть ли буквы
RegExp.Pattern = "^[-\+]?\d+$";
 Если RegExp.Test(Значение)=Истина Тогда
 Возврат "ЧислоЦелое";
КонецЕсли;
RegExp.Pattern = "^[-\+]?\d*[.,]?[\d]{0,}$"; //число вообще (и целое и со знаками после точки или запятой)
Если RegExp.Test(Значение)=Истина Тогда
 Возврат "Число";
иначе
 RegExp.Pattern = "^\d{1,2}[\.\/-]([0]?\d|1[12])[\.\/-]\d{2,4}$"; //Дата
 //датой считает форматы вида 2.12.2014 , 01.12.14, 3.08.2014, 30-10-2014, 15/12/14 и т.д. первая цифра может быть
 //    одна или две. Цифр года 2, 3 или 4
 если RegExp.Test(Значение) = Истина Тогда
  Возврат "Дата";
 Иначе
  Возврат "Строка";
 КонецЕсли;
КонецЕсли;
КонецФункции