IE 2017

Универсальные функции с примерами использования

Программирование - Универсальные функции

11 универсальных функций, с примерами использования - для обычного и управляемого интерфейса

Вместо предисловия

Я знаю про CloudConf, и сервисы хранения кода, но на инфостарте сижу каждый день, поэтому мне здесь удобнее. Да и возможность поделиться какими-то своими идеями, получив отклик тоже интересна.
Код я оформляю в соответствии с соглашениями о написании кода.

1. Замер времени выполнения

Для более точных замеров - с версии платформы 8.2.17 можно использовать метод ГК ТекущаяУниверсальнаяДатаВМиллисекундах()

Старт = ТекущаяДата();
// Произвольный код....
Финиш = ТекущаяДата();

КолСекундЛог = Финиш - Старт;
чч = ЦЕЛ(КолСекундЛог/3600);
мм = ЦЕЛ((КолСекундЛог - чч*3600)/60);
сс =  КолСекундЛог - чч*3600 - мм*60;
СтрокаВремя =	Формат(чч, "ЧЦ=2; ЧН=; ЧВН=") + ":" + 
				Формат(мм, "ЧЦ=2; ЧН=; ЧВН=") + ":" + 
				Формат(сс, "ЧЦ=2; ЧН=; ЧВН=") + " ("+ КолСекундЛог +" сек.)";
Сообщить("" + ТекущаяДата() + ": обработано за " + СтрокаВремя + ".", СтатусСообщения.Информация);
		
2. Проверка значения на вхождение в некоторый интервал
// Проверка значения на вхождение в некоторый интервал  
//
//Параметры (название, тип, дифференцированное значение):
// Значение - Число, Дата - Проверяемое значение
// НачалоИнтервала - Число, Дата
// КонецИнтервала - Число, Дата
// СтрогаяПроверка - Булево
//
//Возвращаемое значение:
// Булево
//
Функция ЗначениеВИнтервале(Значение, НачалоИнтервала, КонецИнтервала, СтрогаяПроверка = Ложь)

	Если СтрогаяПроверка Тогда
		Возврат НачалоИнтервала < Значение И Значение < КонецИнтервала;
	Иначе 
		Возврат НачалоИнтервала <= Значение И Значение <= КонецИнтервала; 
	КонецЕсли; 

КонецФункции
		

Пример использования:

//.....
Если НЕ ЗначениеВИнтервале(ДатаПоказателя, НачалоПериода, КонецПериода) Тогда
	Продолжить;
КонецЕсли;
//...
		
3. Разбиение строки на левую и правую часть
// Универсальная функция для парсинга строк.  
//
//Параметры:
// ИсходнаяСтрока - Строка
// СтрокаРазделитель - Строка
// ОбрезатьПробелы - Булево
//
//Возвращаемое значение:
// СтруктураЧастиСтроки - Структура
//	* Левая - Строка - Левая часть строки (до начала СтрокаРазделитель)
//	* Правая - Строка - Правая часть строки (после окончания СтрокаРазделитель)
//	* Разбито - Булево - флаг указывающий что в исходной строке есть СтрокаРазделитель 
//
Функция РазбитьСтроку(ИсходнаяСтрока, СтрокаРазделитель, ОбрезатьПробелы = Истина)
    
    поз = Найти(ИсходнаяСтрока, СтрокаРазделитель);
    ДлинаРазделителя = СтрДлина(СтрокаРазделитель);    
    Разбито = поз > 0;
    ЛеваяЧастьСтроки = Лев(ИсходнаяСтрока, поз - 1);
	Если ОбрезатьПробелы Тогда
		ЛеваяЧастьСтроки = СокрЛП(ЛеваяЧастьСтроки);		
	КонецЕсли; 
	
    ПраваяЧастьСтроки = Сред(ИсходнаяСтрока, поз + ДлинаРазделителя);
	Если ОбрезатьПробелы Тогда
		ПраваяЧастьСтроки = СокрЛП(ПраваяЧастьСтроки);		
	КонецЕсли; 
	
    СтруктураЧастиСтроки = Новый Структура("Левая, Правая, Разбито"
    , ЛеваяЧастьСтроки
    , ПраваяЧастьСтроки
    , Разбито);
    
    Возврат СтруктураЧастиСтроки;
    
КонецФункции

Пример использования:

//Парсинг строки вида "дд.мм.гггг":
Результат = Дата(1,1,1);
СтруктураЧастиСтроки = РазбитьСтроку(ЗначениеЯчейки, ".");

Если СтруктураЧастиСтроки.Разбито Тогда
	ст_дд = Прав(СтруктураЧастиСтроки.Левая, 2);
	чс_дд = Число(ст_дд);
	
	СтруктураЧастиСтроки = РазбитьСтроку(СтруктураЧастиСтроки.Правая, ".");
	
	Если СтруктураЧастиСтроки.Разбито Тогда
		ст_мм = Прав(СтруктураЧастиСтроки.Левая, 2);
		чс_мм = Число(ст_мм);
		
		ст_гггг = Лев(СтруктураЧастиСтроки.Правая, 4);
		чс_гггг = Число(ст_гггг);			
		
		Результат = Дата(чс_гггг, чс_мм,  чс_дд);
		
	КонецЕсли; 
КонецЕсли; 	
Возврат Результат;
		
4. Преобразование табличного документа в таблицу значений (перебор)

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

// Преобразование табличного документа в таблицу значений
//
//Параметры:
// ТабДок - ТабличныйДокумент
//
//Возвращаемое значение:
//	ТаблицаЗначений 
//
Функция ТабличныйДокументВТаблицуЗначений(ТабДок)
    
    ТаблицаДанныеДокумента = Новый ТаблицаЗначений();
    
    Для СчетчикКолонок = 1 По ТабДок.ШиринаТаблицы Цикл
        
        ИмяКолонки = "_" + СчетчикКолонок;
        ТаблицаДанныеДокумента.Колонки.Добавить(ИмяКолонки);
        
        Для СчетчикСтрок = 1 По ТабДок.ВысотаТаблицы Цикл
            
            ИндексСтроки = СчетчикСтрок - 1;
            
            Если СчетчикКолонок = 1 Тогда
                СтрокаТаблицы = ТаблицаДанныеДокумента.Добавить();
            Иначе
                СтрокаТаблицы = ТаблицаДанныеДокумента[ИндексСтроки];
            КонецЕсли;
            
            ТекущаяЯчейка = ТабДок.Область(СчетчикСтрок, СчетчикКолонок);
            ЗначениеЯчейки = ТекущаяЯчейка.Текст;
            
            СтрокаТаблицы[ИмяКолонки] = ЗначениеЯчейки; 
            
        КонецЦикла
        
    КонецЦикла;    
    
    Возврат ТаблицаДанныеДокумента;
    
КонецФункции
		
5. Загрузка файлов: выбор на клиенте, обработка на сервере

Приведенный ниже код иллюстрирует работу с файлом типа "xlsx". Работа ведется из управляемой формы:

  • пользователь выбирает файл;

  • файл помещается в временное хранилище, и становится доступен на сервере в виде двоичных данных;

  • производится запись двоичных данных в временный файл на сервере, с проверкой: если запись временного файла занимает более 30 секунд, пользователь получит уведомление о прерывании загрузки.

// Выбор загружаемого файла, заполнение служебного реквизита формы "АдресФайлаВВременномХранилище"
//
//Возвращаемое значение:
// Булево - Истина при успешном выборе файла
//
&НаКлиенте
Функция ПроизведенУспешныйВыборФайла()
	
	ЭтаФорма.АдресФайлаВВременномХранилище = "";
	
	#Если ВебКлиент Тогда
		
		Если НЕ ПодключитьРасширениеРаботыСФайлами() Тогда
			УстановитьРасширениеРаботыСФайлами();
			ПодключитьРасширениеРаботыСФайлами();
		КонецЕсли;
		
		ПоместитьФайл(ЭтаФорма.АдресФайлаВВременномХранилище);
		
	#Иначе
		
		ДиалогФыбораФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
		
		ДиалогФыбораФайла.Фильтр = "Таблица(*.xlsx)|*.xlsx";
		ДиалогФыбораФайла.Заголовок = "Выберите файл";
		ДиалогФыбораФайла.ПредварительныйПросмотр = Ложь;
		ДиалогФыбораФайла.Расширение = "xlsx";
		ДиалогФыбораФайла.МножественныйВыбор = Ложь;
		
		Если ДиалогФыбораФайла.Выбрать() Тогда
			ФайлЗагрузки = ДиалогФыбораФайла.ПолноеИмяФайла;
		Иначе
			Возврат Ложь;
		КонецЕсли;
		
		ЭтаФорма.АдресФайлаВВременномХранилище = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ДиалогФыбораФайла.ПолноеИмяФайла));
		
	#КонецЕсли
	
	Возврат НЕ ПустаяСтрока(ЭтаФорма.АдресФайлаВВременномХранилище); 
	
КонецФункции
		

Пример использования:

//...		
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
	
	Если ПроизведенУспешныйВыборФайла() Тогда
		ВыполнитьЗагрузкуФайлаНаСервере(); 
	КонецЕсли; 
	
КонецПроцедуры

//...
&НаСервере
Процедура ВыполнитьЗагрузкуФайлаНаСервере()
	
	АдресВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
	
    // Запись двоичных данных из вр. хранилища:
    ДвДанные = ПолучитьИзВременногоХранилища(ЭтаФорма.АдресФайлаВВременномХранилище);

	Если ЗаписьФайлаПроизошлаУспешно(ДвДанные, АдресВременногоФайла) Тогда // см. ниже "Проверка записи файла
		// обработка данных файла...	
	Иначе
		ЛОГ("загрузка прервана на сервере - файл """+ АдресВременногоФайла +""" не обнаружен...");
	КонецЕсли; 	
	
КонецПроцедуры
//...
		
6. Попытка записи данных в файл с таймаутом на время записи
// Попытка записи данных в файл с таймаутом на время записи
//
//Параметры:
// Источник - Произвольный объект 1С, поддерживающий запись в файл через метод "Записать" - например ДвоичныеДанные или ТекстовыйДокумент
// АдресФайла - Строка
// ОграничениеВремениЗаписи - Число, количество секунд в течение которого будет выполнятся проверка существования файла
// КомандаЗаписи - Строка, для различных случаев сохранения файла, в алгоритме будет параметром метода "Выполнить"
//
//Возвращаемое значение: 
// Булево
//
Функция ЗаписьФайлаПроизошлаУспешно(Источник, АдресФайла, ОграничениеВремениЗаписи = 30, КомандаЗаписи = "")
    
	Попытка 
		
		Если ПустаяСтрока(КомандаЗаписи) Тогда
			Источник.Записать(АдресФайла);				
		Иначе
			Выполнить(КомандаЗаписи);
		КонецЕсли; 
		
        ТекДата = ТекущаяДата();
        ПредСекунда = 0;
        Пока Истина Цикл
            
            КолСекунд = ТекущаяДата() - ТекДата;
            ТекСекунда = КолСекунд;
            
            Если ПредСекунда < ТекСекунда Тогда
                // Раз в секунду - проверка существования записываемого файла
                ЗаписываемыйФайл = Новый Файл(АдресФайла);
                Если ЗаписываемыйФайл.Существует() Тогда
                    Возврат Истина;
                КонецЕсли; 
                
                ПредСекунда = ТекСекунда;
            КонецЕсли; 
            
            Если КолСекунд > ОграничениеВремениЗаписи Тогда
                ВызватьИсключение "время записи файла превысило "+ ОграничениеВремениЗаписи +" секунд";
            КонецЕсли; 
        КонецЦикла; 
        
    Исключение
        Лог("неудачная попытка записи файла на сервере - " + ОписаниеОшибки()); 
        Возврат Ложь;
    КонецПопытки;    
    
КонецФункции
		

Пример использования:

 //...
ТекстXSD = ЭтотОбъект.ПолучитьМакет("МакетXSD");
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xsd"); 

// Запись xsd файла с проверкой по тайм-ауту
Если НЕ ЗаписьФайлаПроизошлаУспешно(ТекстXSD, ИмяВременногоФайла, 5) Тогда
	Возврат;	
КонецЕсли;  

// Или, если нужна запись с параметром:
Если НЕ ЗаписьФайлаПроизошлаУспешно(ТекстXSD, ИмяВременногоФайла, 5, "Источник.Записать(АдресФайла, КодировкаТекста.UTF8);") Тогда
	Возврат;	
КонецЕсли;  
//...
		
7. Проверка интернет-соединения (ping)
// Проверка доступности переданного узла с помощью команды "ping"
//
//Параметры:
// АдресURL - пингуемый адрес
//
//Возвращаемое значение: 
//	Булево
//
Функция Пинг(АдресURL = "")
	
	Если ПустаяСтрока(АдресURL) Тогда
		АдресURL = "www.ya.ru";			
	КонецЕсли; 
	
	objShell = Новый COMОбъект("WScript.Shell") ;
	objScriptExec = objShell.Exec("ping.exe -n 1 " + АдресURL);
	strPingResults = НРег(objScriptExec.StdOut.ReadAll());
	ЕстьСоединение = Найти(strPingResults, "ttl=") > 0;	
	
	Возврат ЕстьСоединение;
	
КонецФункции
		

Пример использования:

//...
ЕстьСоединениеСИнтернетом = Пинг(); // По-умолчанию пингуется www.ya.ru
//...
		
8. Быстрое описание типа
// Упрощенный конструктор описания типа
//
//Параметры:
// ИмяТипа - Строка, Массив элементов типа "Тип" - первый параметр конструктора ОписаниеТипов()
// п1 - Произвольный, первый параметр квалификатора 
// п2 - Произвольный, второй параметр квалификатора 
// п3 - Произвольный, третий параметр квалификатора 
//
//Возвращаемое значение: 
//	ОписаниеТипов
//
Функция ОписаниеТипа(ИмяТипа, п1 = Неопределено, п2 = Неопределено, п3 = Неопределено)
    
    Перем Результат;
    
    Если ИмяТипа = "Строка" Тогда
        
        п1 = ?(п1 = Неопределено, 0, п1);
		Если п2 = Неопределено Тогда
     	   п2 = ДопустимаяДлина.Переменная;			
		КонецЕсли; 
      
        КвалСтроки = Новый КвалификаторыСтроки(п1, п2);
        Результат = Новый ОписаниеТипов(ИмяТипа,,,,КвалСтроки);
        
    ИначеЕсли ИмяТипа = "Число" Тогда    
        
        п1 = ?(п1 = Неопределено, 0, п1);
        п2 = ?(п2 = Неопределено, 0, п2);
		Если п3 = Неопределено Тогда
    	    п3 = ДопустимыйЗнак.Любой;			
		КонецЕсли; 
        
        КвалЧисла = Новый КвалификаторыЧисла(п1, п2, п3);
        Результат = Новый ОписаниеТипов(ИмяТипа,,,КвалЧисла);
        
    ИначеЕсли ИмяТипа = "Дата" Тогда
		
		Если п1 = Неопределено Тогда
        	п1 = ЧастиДаты.ДатаВремя;			
		КонецЕсли; 
        
        КвалДаты = Новый КвалификаторыДаты(п1);
        Результат = Новый ОписаниеТипов(ИмяТипа,,,,,КвалДаты);
        
    Иначе
        Результат = Новый ОписаниеТипов(ИмяТипа);
    КонецЕсли; 
    
    Возврат Результат;
    
КонецФункции
		

Пример использования:

//...
Функция НоваяТаблицаОписанияОпераций()
	
	тз = Новый ТаблицаЗначений;
	тз.Колонки.Добавить("Сумма"         , ОписаниеТипа("Число", 15, 2)); 
	тз.Колонки.Вставить("Описание"      , ОписаниеТипа("Строка", 100));
	тз.Колонки.Вставить("ДатаОперации"  , ОписаниеТипа("Дата"));

	МассивТипов = Новый Массив();
	МассивТипов.Добавить(Тип("ДокументСсылка.Встреча"));
	МассивТипов.Добавить(Тип("ДокументСсылка.ЗапланированноеВзаимодействие"));
	тз.Колонки.Вставить("Событие"       , ОписаниеТипа(МассивТипов));

	тз.Колонки.Вставить("Ответственный" , ОписаниеТипа("СправочникСсылка.Пользователи"));
	Возврат тз;
		
КонецФункции
//...
		
9. Шаблон чтения Excell через ADO
    ADODBConnection = Новый COMОбъект("ADODB.Connection");
    ADODBConnection.Provider = "Microsoft.ACE.OLEDB.12.0";
    ADODBConnection.Properties("Data Source").Value = СокрЛП(ЭтотОбъект.ПутьКФайлу);
    ADODBConnection.Properties("Extended Properties").Value = "Excel 12.0;HDR=Yes;IMEX=1";
    ADODBConnection.Open();

//  Получить список имен листов:
//    ADODBRecordset = Новый COMОбъект("ADODB.Recordset");
//    ADODBRecordset = ADODBConnection.OpenSchema(20);
//    СписокЛистов = Новый СписокЗначений;
//    Пока НЕ ADODBRecordset.EOF Цикл        
//        ИмяЛиста = ADODBRecordset.Fields("TABLE_NAME").Value;
//        Если Найти(ИмяЛиста, "_xlnm#_FilterDatabase") = 0 Тогда
//            СписокЛистов.Добавить(ИмяЛиста); 
//        КонецЕсли;                 
//        ADODBRecordset.MoveNext();
//    КонецЦикла;
//    ADODBRecordset.Close();

//    СписокЛистов.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
//    ИмяЛиста = СписокЛистов[0].Значение;
    
    ТекстЗапроса = "SELECT * FROM [" + ЭтотОбъект.ИмяЛиста + "$]";
    
    ADODBRecordset = Новый COMОбъект("ADODB.Recordset");
    ADODBRecordset.Open(ТекстЗапроса, ADODBConnection);
    
    КолвоКолонокExcel = ADODBRecordset.Fields.Count;
    
    СчетчикСтрок = 1;    
    Пока ADODBRecordset.EOF() = 0 Цикл
		
        Для СчетчикКолонок = 1 ПО КолвоКолонокExcel Цикл
            
            Поле = ADODBRecordset.Fields.Item(СчетчикКолонок - 1);
                
            Если Поле.ActualSize = 0 Тогда// Пустое поле EXCEL.
                Продолжить;
            КонецЕсли;
                
            ЗначениеЯчейки = Поле.Value; 
   // Обработка значения ячейки 
 
        КонецЦикла;
        
        ADODBRecordset.MoveNext();   // Следующая строка.
        СчетчикСтрок = СчетчикСтрок + 1;
        
    КонецЦикла;

    ADODBConnection.Close();
    
    ADODBRecordset = Неопределено;
    ADODBConnection = Неопределено;   
10. Объединение ячеек шапки табличного документа с повторяющимся текстом

Этот метод служит для решения частной задачи отображения группировок колонок в табличных документах, полученных с помощью СКД. Исходная идея вот здесь: СКД. Как объединить заголовки родительских группировок колонок в таблице. Я причесал код и добавил расчет ширины для объединяемой колонки - СКД при группировке выводит дубли колонок с исходной шириной, логично при свертке к ней и вернуться. Этот вариант не будет работать с уже объединенными ячейками. Может позже допилю, пока нет нужды. Как использовать: в СКД делаем одну группировку колонок, в которую добавлем необходимые поля. После вывода табличного документа на форму вызываем метод.

// Объединяет ячейки шапки табличного документа с повторяющимся текстом
// Служит для решения задачи отображения группировок колонок в табличных документах, полученных с помощью СКД
//
//Параметры:
// ТабДок - ТабличныйДокумент
// ВысотаШапки - Число, если не передана, высотой шапки считается высота фиксации таблицы
//
Процедура СвернутьЗаголовкиШапкиТабличногоДокумента(ТабДок, ВысотаШапки = 0)

	ВысотаШапки = ?(ВысотаШапки = 0, ТабДок.ФиксацияСверху, ВысотаШапки);		
	НачалоШапки = ?(ТабДок.ФиксацияСлева = 0, 1, ТабДок.ФиксацияСлева);
	
	Для СчетчикСтрок=1 По ВысотаШапки Цикл
		
		НомерПервойКолонкиОбъединения = 0;
		Для СчетчикКолонок=НачалоШапки По ТабДок.ШиринаТаблицы Цикл			

			ОбъединятьЯчейки = Ложь;
			Ячейка = ТабДок.Область(СчетчикСтрок, СчетчикКолонок);
			Если ПустаяСтрока(Ячейка.Текст) Тогда
				Продолжить;				
			КонецЕсли; 
			ЯчейкаСлед = ТабДок.Область(СчетчикСтрок, СчетчикКолонок+1);
			ОбъединятьЯчейки = Ячейка.Текст = ЯчейкаСлед.Текст;
			
			Если ОбъединятьЯчейки Тогда				
				НомерПервойКолонкиОбъединения = ?(НомерПервойКолонкиОбъединения = 0, СчетчикКолонок, НомерПервойКолонкиОбъединения);
				
			ИначеЕсли НомерПервойКолонкиОбъединения > 0 Тогда
				ТекстЗаголовка = ТабДок.Область(СчетчикСтрок, СчетчикКолонок).Текст;
				ОбъединяемаяОбласть = ТабДок.Область(СчетчикСтрок, НомерПервойКолонкиОбъединения, СчетчикСтрок, СчетчикКолонок);
				ОбъединяемаяОбласть.Объединить();
				
				КоличествоКолонокВОбъединении = СчетчикКолонок - НомерПервойКолонкиОбъединения;
				ОбъединяемаяОбласть.ШиринаКолонки = ОбъединяемаяОбласть.ШиринаКолонки / КоличествоКолонокВОбъединении;
				
				ОбъединяемаяОбласть.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
				ОбъединяемаяОбласть.Текст = ТекстЗаголовка;
				
				НомерПервойКолонкиОбъединения = 0;
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

11. Формирование идентификатора по строке
// Формирование идентификатора по правилам образования имен переменных 1С по входящей строке
// Пример "Статья возмещение НДС" => "СтатьяВозмещениеНДС"
//
//Параметры:
// стр - Строка - от которой необходимо получить идентификатор
//
//Возвращаемое значение: 
// Строка
//
Функция ИдентификаторПоСтроке(ЗНАЧ стр)
    ДопустимыеСимволы = "ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁQWERTYUIOPASDFGHJKLZXCVBNM" + 
	"йцукенгшщзхъфывапролджэячсмитьбюёqwertyuiopasdfghjklzxcvbnm_ ";
    
    Пока Найти(стр, "  ") > 0 Цикл
        стр = СтрЗаменить(стр, "  ", " ");            
    КонецЦикла; 
    
    ДлинаСтроки = СтрДлина(стр);
    СледующаяЗаглавная = Истина;
    Слово = "";
    Для сч=1 По ДлинаСтроки Цикл
        
        сим = Сред(стр, сч, 1);
		
		Если сч = 1 И сим = "_" Тогда
			Продолжить;			
		КонецЕсли; 
		
        Если Найти(ДопустимыеСимволы, сим) = 0 Тогда
            Продолжить;            
        КонецЕсли; 
        Если сим = " " Тогда
            СледующаяЗаглавная = Истина;
            Продолжить;
        КонецЕсли; 
        
        Если СледующаяЗаглавная Тогда
            СледующаяЗаглавная = Ложь;
            Сим = Врег(Сим);            
        КонецЕсли; 
        
        Слово = Слово + Сим;                
    КонецЦикла; 
        
    Возврат Слово;
КонецФункции

См. также

Комментарии
1. Артем Бардюг (Йожкин Кот) 1038 26.02.16 17:21 Сейчас в теме
Замер времени можно сделать точнее:
ТекущаяУниверсальнаяДатаВМиллисекундах(). Функция появилась в каком-то релизе 8.3
Dmitriy_T; JesteR; dark_wolf; vladir; +4 Ответить 1
2. tireal 66 02.03.16 08:36 Сейчас в теме
вот держи в копилку, вместо своего замера
докВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
//процедура замера
докВремяКонцаВыполнения = ТекущаяУниверсальнаяДатаВМиллисекундах();
докДельта = (докВремяКонцаВыполнения - докВремяНачала) / 1000;


докДельтаПредставление = ПолучитьПредставлениеВремени(докДельта);

Функция ПолучитьПредставлениеВремени(Время)
	Секунды = Время % 60;
	Минуты = (Время-Секунды)/60;
	Минуты = Минуты % 60;
	Часы = (Время-Секунды-Минуты)/3600;
	
	Возврат "" + Окр(Часы) + " ч. " + Окр(Минуты) + " мин. " + Окр(Секунды, 2) + " сек.";
	
КонецФункции
...Показать Скрыть
3. Роман Уничкин (unichkin) 545 02.03.16 12:01 Сейчас в теме
(1) Йожкин Кот, это поддерживается только с 8.2.17
(2) tireal, спасибо за комментарий. Но:
- свою функцию я могу использовать в любом релизе платформы. Да, я порой работаю с 8.1 - как ни странно оно еще есть.
- если мне когда-нибудь понадобится настолько низкоуровневое отслеживание выполнения алгоритма - я скорее воспользуюсь замером времени отладчика
- могу предположить что назначение использования вашей функции - тестирование скорости исполнения алгоритма (т. е. она для этой цели писалась); моей - просто замер времени работы для сообщения/ помещения в лог - секунды вполне устраивают
Останусь при своем, но буду знать и о таком варианте, еще раз спасибо.
4. Виктор Назаров (androgin) 02.03.16 14:58 Сейчас в теме
вместо Функция РазбитьСтроку(стр, сим)
можно вполне использовать СтрРазделить()
5. Роман Уничкин (unichkin) 545 02.03.16 15:12 Сейчас в теме
(4) androgin, Во-первых назначение СтрРазделить() и моей РазбитьСтроку() - разное. От слова совсем. Во-вторых СтрРазделить() - это начиная с 8.3.6.1977.
6. Андрей Акулов (DrAku1a) 1213 03.03.16 02:46 Сейчас в теме
(3) unichkin, посмотри как сделано в ИР и универсальном отчете (от alexk-is), там есть до миллиекунд.
Попытка
		Scr = Новый COMОбъект("MSScriptControl.ScriptControl");
	Исключение
		Сообщить(ОписаниеОшибки(), СтатусСообщения.Внимание);
		Возврат 0;
	КонецПопытки;
	Scr.Language = "javascript";
	Время = Scr.Eval("new Date().getTime()");
	Возврат Время;
...Показать Скрыть

По поводу разделения строки - держи в копилку:
Функция ИзвлечьСлово(Строка, Разделитель)
	П = найти(Строка+Разделитель, Разделитель);
	Ответ = Лев(Строка, П-1);
	Строка = Сред(Строка, П+СтрДлина(Разделитель));
	Возврат Ответ;
КонецФункции

Пример:
стр = "1,2,3,4";
Сообщить(ИзвлечьСлово(стр, ",")); //1
Сообщить(стр); // 2,3,4
Сообщить(ИзвлечьСлово(стр, ",")); //2
Сообщить(стр); // 3,4
Сообщить(ИзвлечьСлово(стр, ",")); //3
Сообщить(стр); // 4
Сообщить(ИзвлечьСлово(стр, ",")); //4
Сообщить(стр); // "" (пустая строка)
Сообщить(ИзвлечьСлово(стр, ",")); // "" (пустая строка)
...Показать Скрыть

Если заранее известно, что строка не содержит символов перевода строки, то можно пользоваться стандартным:
СтрПолучитьСтроку(СтрЗаменить(<ИсходнаяСтрока>, <Разделитель>, Символы.ПС), <НомерСлова>)
7. Андрей К (h00k) 45 03.03.16 05:28 Сейчас в теме
(3) unichkin,
- если мне когда-нибудь понадобится настолько низкоуровневое отслеживание выполнения алгоритма - я скорее воспользуюсь замером времени отладчика

Смешно. Вы думаете всякие извращения с джаваскриптами и т.п. появились потому что ни кто не додумался время выполнения в отладчике смотреть?!
Спасибо любимой 1С, они хоть от необходимости использовать внешние скрипты избавили, добавив в платформу функцию
ТекущаяУниверсальнаяДатаВМиллисекундах()

А для старых версий платформы остается только замерять время выполнения при помощи внешних средств, например джава-скрипта.
8. Роман Уничкин (unichkin) 545 03.03.16 11:43 Сейчас в теме
(6) Знаю я об этих фишках, спасибо. Функция "ИзвлечьСлово" - не учитывает что символа может и не быть. И режет исходную строку. Как-раз чтобы этого избежать я наваял сп_РазбитьСтроку() - ее конечно не стоит применять на большом массиве данных, но для чтения небольших листов Excell - самое оно.
(7) h00k, почитайте внимательнее мой комментарий в (3) . И да, мне удобнее воспользоваться замером времени, чем вставлять в конфу отладочную печать. Не могу вспомнить случая, когда я не мог без этого обойтись. Может опыта еще маловато)

Имхо, все извращения с получением настолько точного времени - связаны с необходимостью отслеживать СКОРОСТЬ, а не ВРЕМЯ выполнения алгоритма. Разница трудноуловима, но она есть. Мне не надо с точностью до миллисекунды знать сколько времени проводился массив документов - 20 мин меня вполне устроит. Но если я тестирую напр. как быстрее создавать таблицу значений - тут нужны миллисекунды. Просто для универсальности функция замера обычно реализуется наиболее детализированно - т.е. через тот-же ява-скрипт. Ну а мне как-то не нужно было. Если понадобится - возьму из (6).
9. Валерий Дегрик (mars207) 24 09.03.16 09:37 Сейчас в теме
Загрузка файлов: выбор на клиенте, обработка на сервере

На веб клиенте давно не работает. Проблема всплывающих окон в браузерах. На последних релизах платформы не тестировал, но подозреваю что не исправили.
10. Роман Уничкин (unichkin) 545 09.03.16 09:39 Сейчас в теме
(9) mars207, тестировал на 8.3.5 - у меня работает. чяднт?
11. Виктор Назаров (androgin) 13.03.16 02:25 Сейчас в теме
(9) mars207, все прекрасно работает
12. Виктор Назаров (androgin) 13.03.16 02:26 Сейчас в теме
(5) unichkin, уже давно все типовые версии требуют 8.3.6.2094 как минимальную
13. Михаил (MishaD) 12 13.03.16 10:03 Сейчас в теме
Странно, у меня половина типовых на 8.2.14.540, а еще половина на 7.7.027
14. Роман Уничкин (unichkin) 545 13.03.16 13:18 Сейчас в теме
(12) androgin, далеко не все используют исключительно типовые, и далеко не все еще перешли на новые конфы с УФ и БСП. Я уже писал в (3) что и с 8.1 иногда работаю.
15. Виктор Назаров (androgin) 21.03.16 14:33 Сейчас в теме
(14) unichkin, то, что вы тормозите собственное развитие и сидите в старых платформах и на старых методах - вынуждает вас писать подобные коды и изобретать очередной велосипед.
В 1С далеко не дураки сидят
16. Андрей К (h00k) 45 21.03.16 22:31 Сейчас в теме
(15) androgin,
то, что вы тормозите собственное развитие и сидите в старых платформах и на старых методах - вынуждает вас писать подобные коды

Вы можете ошибаться... собственное развитие и вынужденная работа со старыми версиями конфигураций в учетных системах заказчика/ работодателя - в большинстве случаев ни как не связаны.
Переход предприятия на новую систему учета/ платформу - это достаточно дорогое удовольствие, и только из-за желания программиста работать с новыми версиями платформ/ конфигураций ни кто, в здравом уме, переходить не будет.
17. Роман Уничкин (unichkin) 545 22.03.16 01:56 Сейчас в теме
(15) androgin, не понимаю сути претензий. И с чего вы решили что я где-то там "торможусь"?.. Я подписан на рассылку, просматриваю ИТС, мониторю зазеркалье (о птичках) работаю в основном на 8.3.6. И абсолютно солидарен с вами что в 1С сидят не дураки. Я только не понимаю, к чему это было сказано) Лучше перечитайте (5), попробуйте вникнуть в назначение сп_РазбитьСтроку() и понять таки что СтрРазделитьСтроку() в ее контексте в принципе не нужна. Я наверное сам дал еды троллю - лишним было писать "Во-вторых СтрРазделить() - это начиная с 8.3.6.1977".
18. Андрей Крутских (K_A_O) 486 28.03.16 11:33 Сейчас в теме
> Преобразование табличного документа в таблицу значений

Вот это вроде с давних времен работает

Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных=Новый ОписаниеИсточникаДанных(ТабДок.Область());       
Построитель.Выполнить();
ТЗ = Построитель.Результат.Выгрузить();
Azimut-tm; terrorion; yukon; pavlov_dv; TreeDogNight; Rokstedi; unichkin; +7 Ответить 1
19. Александр Шипков (sansys) 34 07.01.17 12:17 Сейчас в теме
Спасибо за статью. Иногда стоит вылезти из своего болота и посмотреть как люди делают :))))) +1
20. Сергей Долинин (ImHunter) 13 09.01.17 07:52 Сейчас в теме
Про замеры времени. Написал пару процедур - засечь время и показать время замера (+ 2 вспомогательные). Недостаток - в многопотоке некорректно работает. А так, удобненько.
// клиентский модуль

Процедура ЗасечьТаймер() Экспорт 
	УправляемыйИнтерфейсСервер.СохранитьЗначениеВХранилище( "ТекВремяТаймера", ТекущаяДата() );
	//ПоместитьВоВременноеХранилище( ТекущаяДата(), );
КонецПроцедуры

Процедура ПоказатьВремяТаймера( пЗаголовок = "", пЧерезСообщение = Ложь ) Экспорт 
	д = УправляемыйИнтерфейсСервер.ПолучитьЗначениеИзХранилища( "ТекВремяТаймера" );
	общ = ТекущаяДата() - д;
	мин = цел( общ / 60 );
	сек = общ - мин * 60;
	час = цел( мин / 60);
	мин = мин - час * 60;
	лВрем = ?( пЧерезСообщение, "Время выполнения:", "Время:" );
	Если час <> 0 Тогда 
		лВрем = лВрем + " " + час + " час"
	КонецЕсли;
	Если Мин <> 0 Тогда 
		лВрем = лВрем + " " + мин + " мин"
	КонецЕсли;
	лВрем = лВрем + " " + сек + " сек";
	Если пЧерезСообщение=Ложь Тогда 
		ПоказатьОповещениеПользователя( пЗаголовок, , лВрем );
	Иначе 
		Сообщить( ?( ПустаяСтрока( пЗаголовок ), "Действие выполнено", пЗаголовок ) + ". " + лВрем );
	КонецЕсли;
КонецПроцедуры

// серверный модуль УправляемыйИнтерфейсСервер

Процедура СохранитьЗначениеВХранилище( пКлюч, пЗначение ) Экспорт
	ХранилищеСистемныхНастроек.Сохранить( , пКлюч, пЗначение, , ПараметрыСеанса.ТекущийПользователь );	
КонецПроцедуры

Функция ПолучитьЗначениеИзХранилища( пКлюч ) Экспорт
	Возврат ХранилищеСистемныхНастроек.Загрузить( , пКлюч, , ПараметрыСеанса.ТекущийПользователь );
КонецФункции


// пример использования
&НаКлиенте
Процедура СделатьЧтоТо()
  УправляемыйИнтерфейс.ЗасечьТаймер();
  // что-то делаем
  // ......................
  УправляемыйИнтерфейс.ПоказатьВремяТаймера("Сделали что-то!");
КонецПроцедуры

...Показать Скрыть
21. Альтаир (Altair777) 639 06.07.17 09:21 Сейчас в теме
(18) А у меня еще дополнено
Построитель.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
Построитель.ЗаполнитьНастройки();
22. Иван Устьянцев (nSpirit2) 09.08.17 13:55 Сейчас в теме
Я конечно все понимаю но раз вы пишите
Код я оформляю в соответствии с соглашениями о написании кода.


Еще раз прочитайте эту часть
https://its.1c.ru/db/v8std#content:2149184103:hdoc

Мне кажется вы не правильно поняли блок как не надо делать
23. Роман Уничкин (unichkin) 545 09.08.17 17:34 Сейчас в теме
(22)
Мне кажется вы не правильно поняли блок как не надо делать

Какой участок кода навел вас на эту мысль?
Оставьте свое сообщение