Универсальные функции с примерами использования
Разработка - Универсальные функции
Вместо предисловия
Я знаю про CloudConf, и сервисы хранения кода, но на Инфостарте сижу каждый день, поэтому мне здесь удобнее. Да и возможность поделиться какими-то своими идеями, получив отклик, тоже интересна.
Код я оформляю в соответствии с соглашениями о написании кода.
// Описание разницы времени в формате "чч:мм:сс (ВсегоСекунд.ОстатокМиллисекунд сек.)"
//
// Параметры:
// Старт - Число - результат значения работы функции "ТекущаяУниверсальнаяДатаВМиллисекундах()"
// Финиш - Число - результат значения работы функции "ТекущаяУниверсальнаяДатаВМиллисекундах()"\
//
// Возвращаемое значение:
// Строка
//
Функция ОписаниеЗамераВремени(Старт, Финиш)
КолМлСекундЛог = Финиш - Старт;
КолСекундЛог = ЦЕЛ(КолМлСекундЛог / 1000);
КолМлСекунд = КолМлСекундЛог - КолСекундЛог;
ФорматКолМС = "" + КолМлСекунд;
ФорматКолМС = СтрЗаменить(ФорматКолМС, ",", "");
ФорматКолМС = СтрЗаменить(ФорматКолМС, " ", "");
ФорматКолМС = Лев(ФорматКолМС, 3);
Пока Прав(ФорматКолМС, 1) = "0" Цикл
ФорматКолМС = Сред(ФорматКолМС, 1, СтрДлина(ФорматКолМС)-1);
КонецЦикла;
ФорматСекунд = "" + КолСекундЛог + "." + ФорматКолМС;
чч = ЦЕЛ(КолСекундЛог/3600);
мм = ЦЕЛ((КолСекундЛог - чч*3600)/60);
сс = КолСекундЛог - чч*3600 - мм*60;
СтрокаВремя = Формат(чч, "ЧЦ=2; ЧН=; ЧВН=") + ":" +
Формат(мм, "ЧЦ=2; ЧН=; ЧВН=") + ":" +
Формат(сс, "ЧЦ=2; ЧН=; ЧВН=") + " ("+ ФорматСекунд +" сек.)";
Возврат СтрокаВремя;
КонецФункции
Пример использования:
Старт = ТекущаяУниверсальнаяДатаВМиллисекундах();
//.. код
Финиш = ТекущаяУниверсальнаяДатаВМиллисекундах();
Сообщить("Обработка завершена за " + ОписаниеЗамераВремени(Финиш, Старт));
// -> Обработка завершена за 00:00:03 (3.303 сек.)
// Проверка значения на вхождение в некоторый интервал
//
// Параметры:
// Значение - Число, Дата - Проверяемое значение
// НачалоИнтервала - Число, Дата
// КонецИнтервала - Число, Дата
// СтрогаяПроверка - Булево
//
// Возвращаемое значение:
// Булево
//
Функция ЗначениеВИнтервале(Значение, НачалоИнтервала, КонецИнтервала, СтрогаяПроверка = Ложь)
Если СтрогаяПроверка Тогда
Возврат НачалоИнтервала < Значение И Значение < КонецИнтервала;
Иначе
Возврат НачалоИнтервала <= Значение И Значение <= КонецИнтервала;
КонецЕсли;
КонецФункции
Пример использования:
//.....
Если НЕ ЗначениеВИнтервале(ДатаПоказателя, НачалоПериода, КонецПериода) Тогда
Продолжить;
КонецЕсли;
//...
// Универсальная функция для парсинга строк
//
// Параметры:
// ИсходнаяСтрока - Строка
// СтрокаРазделитель - Строка
// ОбрезатьПробелы - Булево
//
// Возвращаемое значение:
// СтруктураЧастиСтроки - Структура
// * Левая - Строка - Левая часть строки (до начала СтрокаРазделитель)
// * Правая - Строка - Правая часть строки (после окончания СтрокаРазделитель)
// * Разбито - Булево - флаг указывающий что в исходной строке есть СтрокаРазделитель
//
Функция РазбитьСтроку(ИсходнаяСтрока, СтрокаРазделитель, ОбрезатьПробелы = Истина)
поз = Найти(ИсходнаяСтрока, СтрокаРазделитель);
ДлинаРазделителя = СтрДлина(СтрокаРазделитель);
Разбито = поз > 0;
ЛеваяЧастьСтроки = Лев(ИсходнаяСтрока, поз - 1);
Если ОбрезатьПробелы Тогда
ЛеваяЧастьСтроки = СокрЛП(ЛеваяЧастьСтроки);
КонецЕсли;
ПраваяЧастьСтроки = Сред(ИсходнаяСтрока, поз + ДлинаРазделителя);
Если ОбрезатьПробелы Тогда
ПраваяЧастьСтроки = СокрЛП(ПраваяЧастьСтроки);
КонецЕсли;
СтруктураЧастиСтроки = Новый Структура("Левая, Правая, Разбито"
, ЛеваяЧастьСтроки
, ПраваяЧастьСтроки
, Разбито);
Возврат СтруктураЧастиСтроки;
КонецФункции
Пример использования:
//Парсинг строки вида "дд.мм.гггг":
Результат = Дата(1,1,1);
СтруктураЧастиСтроки = РазбитьСтроку(ЗначениеЯчейки, ".");
Если СтруктураЧастиСтроки.Разбито Тогда
ст_дд = Прав(СтруктураЧастиСтроки.Левая, 2);
чс_дд = Число(ст_дд);
СтруктураЧастиСтроки = РазбитьСтроку(СтруктураЧастиСтроки.Правая, ".");
Если СтруктураЧастиСтроки.Разбито Тогда
ст_мм = Прав(СтруктураЧастиСтроки.Левая, 2);
чс_мм = Число(ст_мм);
ст_гггг = Лев(СтруктураЧастиСтроки.Правая, 4);
чс_гггг = Число(ст_гггг);
Результат = Дата(чс_гггг, чс_мм, чс_дд);
КонецЕсли;
КонецЕсли;
Возврат Результат;
В комментарии ниже дан более логичный код, с использованием построителя для этих целей (к сожалению, не пойму сейчас как ссылку на коммент дать). Оставил здесь эту функцию потому что мне иногда нужен перебор табличного документа, и ее использую качестве заготовки.
// Преобразование табличного документа в таблицу значений
//
// Параметры:
// ТабДок - ТабличныйДокумент
//
// Возвращаемое значение:
// ТаблицаЗначений
//
Функция ТабличныйДокументВТаблицуЗначений(ТабДок)
ТаблицаДанныеДокумента = Новый ТаблицаЗначений();
Для СчетчикКолонок = 1 По ТабДок.ШиринаТаблицы Цикл
ИмяКолонки = "_" + СчетчикКолонок;
ТаблицаДанныеДокумента.Колонки.Добавить(ИмяКолонки);
Для СчетчикСтрок = 1 По ТабДок.ВысотаТаблицы Цикл
ИндексСтроки = СчетчикСтрок - 1;
Если СчетчикКолонок = 1 Тогда
СтрокаТаблицы = ТаблицаДанныеДокумента.Добавить();
Иначе
СтрокаТаблицы = ТаблицаДанныеДокумента[ИндексСтроки];
КонецЕсли;
ТекущаяЯчейка = ТабДок.Область(СчетчикСтрок, СчетчикКолонок);
ЗначениеЯчейки = ТекущаяЯчейка.Текст;
СтрокаТаблицы[ИмяКолонки] = ЗначениеЯчейки;
КонецЦикла
КонецЦикла;
Возврат ТаблицаДанныеДокумента;
КонецФункции
Решение задачи чтения иерархии табличного документа. Здесь стоит упомянуть статью Чтение группировок табличного документа:
- Сам алгоритм статьи не отрабатывает корректно, если есть несколько вложенных уровней группировок. Его исправили в последнем комментарии, но автор статью почему-то обновлять не стал.
- Предложенная там реализация отличается плохо читабельным кодом. Кроме этого задействовано три метода, в моем подходе - один. Подход к решению тоже разный: я использую видимость области строки, там используется парсинг таб. дока через документ DOM.
- При этом по скорости оба алгоритма показывают примерно одинаковое время
// Дерево значений по табличному документу, с аналогичной иерархией существующих группировок
//
// Параметры:
// ТабДок - ТабличныйДокумент
// СвойстваКолонок - ТаблицаЗначений
// *Имя - Строка - Имя колонки дерева, в которую будут помещены данные области колонки табличного документа
// *Номер - Число - Номер колонки в табличном документе
// ВысотаШапки - Число - для отсечения незначащих строк
// УдалятьФлаговыеКолонки - Булево - При анализе табличного документа в дерево добавляются служебные колонки
// "Начало" и "Конец", где сохраняются диапазоны группировки. Если Истина - то эти колонки при окончании
// алгоритма будут удалены.
// ИсключатьПустыеСтроки - Булево - Если Истина, то строки в которых значения всех колонок пустые будут исключены
//
// Возвращаемое значение:
// ДеревоЗначений
//
Функция ТабличныйДокументВДеревоЗначений(ТабДок, СвойстваКолонок, ВысотаШапки = 0, УдалятьФлаговыеКолонки = Истина, ИсключатьПустыеСтроки = Истина)
ДеревоДокумента = Новый ДеревоЗначений;
Для каждого ОписаниеКолонки Из СвойстваКолонок Цикл
ДеревоДокумента.Колонки.Добавить(ОписаниеКолонки.Имя);
КонецЦикла;
ДеревоДокумента.Колонки.Добавить("Начало");
ДеревоДокумента.Колонки.Добавить("Конец");
Кэш = Новый ТабличныйДокумент;
Кэш.Вывести(ТабДок);
Для сч = -Кэш.КоличествоУровнейГруппировокСтрок() По 0 Цикл
Кэш.ПоказатьУровеньГруппировокСтрок(-сч);
КонецЦикла;
ПройденныеСтроки = Новый Соответствие;
ПройденныеУровни = Новый Соответствие;
ПустыеСтроки = Новый Соответствие;
КоличествоУровней =Кэш.КоличествоУровнейГруппировокСтрок();
Для СчетчикУровня=1 По КоличествоУровней Цикл
ПройденныеУровни.Вставить(СчетчикУровня, Новый Массив);
Кэш.ПоказатьУровеньГруппировокСтрок(СчетчикУровня-1);
Для СчетчикСтрок=1 По Кэш.ВысотаТаблицы Цикл
Если СчетчикСтрок <= ВысотаШапки Тогда
Продолжить;
КонецЕсли;
Если ПройденныеСтроки.Получить(СчетчикСтрок) = Истина Тогда
Продолжить;
КонецЕсли;
Если ИсключатьПустыеСтроки Тогда
ЭтоПустаяСтрока = ПустыеСтроки.Получить(СчетчикСтрок);
Если ЭтоПустаяСтрока = Неопределено Тогда
ЭтоПустаяСтрока = Истина;
Для каждого ОписаниеКолонки Из СвойстваКолонок Цикл
ОбластьЯчейки = Кэш.Область(СчетчикСтрок, ОписаниеКолонки.Номер);
Если ЗначениеЗаполнено(ОбластьЯчейки.Текст) Тогда
ЭтоПустаяСтрока = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
ПустыеСтроки.Вставить(СчетчикСтрок, ЭтоПустаяСтрока);
КонецЕсли;
Если ЭтоПустаяСтрока Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
ИмяОбласти = "R" + Формат(СчетчикСтрок, "ЧГ=");
ОбластьСтроки = Кэш.Область(ИмяОбласти);
Если ОбластьСтроки.Видимость Тогда
Если СчетчикУровня = 1 Тогда
Родитель = ДеревоДокумента;
Иначе
МассивНомеровСтрокПредУровня = ПройденныеУровни.Получить(СчетчикУровня-1);
Для сч=-МассивНомеровСтрокПредУровня.ВГраница() По 0 Цикл
НомерСтрокиРодителя = МассивНомеровСтрокПредУровня[-сч];
Если НомерСтрокиРодителя < СчетчикСтрок Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Родитель = ДеревоДокумента.Строки.Найти(НомерСтрокиРодителя, "Начало", Истина);
КонецЕсли;
Узел = Родитель.Строки.Добавить();
Узел.Начало = СчетчикСтрок;
Для каждого ОписаниеКолонки Из СвойстваКолонок Цикл
ОбластьЯчейки = Кэш.Область(СчетчикСтрок, ОписаниеКолонки.Номер);
Узел[ОписаниеКолонки.Имя] = СокрЛП(ОбластьЯчейки.Текст);
КонецЦикла;
Если СчетчикУровня < КоличествоУровней Тогда
ПройденныеСтроки.Вставить(СчетчикСтрок, Истина);
МассивНомеровСтрокУровня = ПройденныеУровни.Получить(СчетчикУровня);
МассивНомеровСтрокУровня.Добавить(СчетчикСтрок);
КонецЕсли;
КонецЕсли;
Если Узел <> Неопределено Тогда
Узел.Конец = СчетчикСтрок;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если УдалятьФлаговыеКолонки Тогда
ДеревоДокумента.Колонки.Удалить("Начало");
ДеревоДокумента.Колонки.Удалить("Конец");
КонецЕсли;
Возврат ДеревоДокумента;
КонецФункции
Приведенный ниже код иллюстрирует работу с файлом типа "xlsx". Работа ведется из управляемой формы:
-
пользователь выбирает файл;
-
файл помещается в временное хранилище, и становится доступен на сервере в виде двоичных данных;
-
производится запись двоичных данных в временный файл на сервере, с проверкой: если запись временного файла занимает более 30 секунд, пользователь получит уведомление о прерывании загрузки.
// Выбор загружаемого файла, заполнение служебного реквизита формы "АдресФайлаВВременномХранилище"
//
// Возвращаемое значение:
// Булево - Истина при успешном выборе файла
//
&НаКлиенте
Функция ПроизведенУспешныйВыборФайла()
ЭтаФорма.АдресФайлаВВременномХранилище = "";
#Если ВебКлиент Тогда
Если НЕ ПодключитьРасширениеРаботыСФайлами() Тогда
УстановитьРасширениеРаботыСФайлами();
ПодключитьРасширениеРаботыСФайлами();
КонецЕсли;
ПоместитьФайл(ЭтаФорма.АдресФайлаВВременномХранилище);
#Иначе
ДиалогФыбораФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогФыбораФайла.Фильтр = "Таблица(*.xlsx)|*.xlsx";
ДиалогФыбораФайла.Заголовок = "Выберите файл";
ДиалогФыбораФайла.ПредварительныйПросмотр = Ложь;
ДиалогФыбораФайла.Расширение = "xlsx";
ДиалогФыбораФайла.МножественныйВыбор = Ложь;
Если ДиалогФыбораФайла.Выбрать() Тогда
ФайлЗагрузки = ДиалогФыбораФайла.ПолноеИмяФайла;
Иначе
Возврат Ложь;
КонецЕсли;
ЭтаФорма.АдресФайлаВВременномХранилище = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ДиалогФыбораФайла.ПолноеИмяФайла));
#КонецЕсли
Возврат НЕ ПустаяСтрока(ЭтаФорма.АдресФайлаВВременномХранилище);
КонецФункции
Пример использования:
//...
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
Если ПроизведенУспешныйВыборФайла() Тогда
ВыполнитьЗагрузкуФайлаНаСервере();
КонецЕсли;
КонецПроцедуры
//...
&НаСервере
Процедура ВыполнитьЗагрузкуФайлаНаСервере()
АдресВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
// Запись двоичных данных из вр. хранилища:
ДвДанные = ПолучитьИзВременногоХранилища(ЭтаФорма.АдресФайлаВВременномХранилище);
Если ЗаписьФайлаПроизошлаУспешно(ДвДанные, АдресВременногоФайла) Тогда // см. ниже "Проверка записи файла
// обработка данных файла...
Иначе
ЛОГ("загрузка прервана на сервере - файл """+ АдресВременногоФайла +""" не обнаружен...");
КонецЕсли;
КонецПроцедуры
//...
// Попытка записи данных в файл с таймаутом на время записи
//
// Параметры:
// Источник - Произвольный объект 1С, поддерживающий запись в файл через метод "Записать" - например ДвоичныеДанные или ТекстовыйДокумент
// АдресФайла - Строка
// ОграничениеВремениЗаписи - Число, количество секунд в течение которого будет выполнятся проверка существования файла
// КомандаЗаписи - Строка, для различных случаев сохранения файла, в алгоритме будет параметром метода "Выполнить"
//
// Возвращаемое значение:
// Булево
//
Функция ЗаписьФайлаПроизошлаУспешно(Источник, АдресФайла, ОграничениеВремениЗаписи = 30, КомандаЗаписи = "")
Попытка
Если ПустаяСтрока(КомандаЗаписи) Тогда
Источник.Записать(АдресФайла);
Иначе
Выполнить(КомандаЗаписи);
КонецЕсли;
ТекДата = ТекущаяДата();
ПредСекунда = 0;
Пока Истина Цикл
КолСекунд = ТекущаяДата() - ТекДата;
ТекСекунда = КолСекунд;
Если ПредСекунда < ТекСекунда Тогда
// Раз в секунду - проверка существования записываемого файла
ЗаписываемыйФайл = Новый Файл(АдресФайла);
Если ЗаписываемыйФайл.Существует() Тогда
Возврат Истина;
КонецЕсли;
ПредСекунда = ТекСекунда;
КонецЕсли;
Если КолСекунд > ОграничениеВремениЗаписи Тогда
ВызватьИсключение "время записи файла превысило "+ ОграничениеВремениЗаписи +" секунд";
КонецЕсли;
КонецЦикла;
Исключение
Лог("неудачная попытка записи файла на сервере - " + ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
Пример использования:
//...
ТекстXSD = ЭтотОбъект.ПолучитьМакет("МакетXSD");
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xsd");
// Запись xsd файла с проверкой по тайм-ауту
Если НЕ ЗаписьФайлаПроизошлаУспешно(ТекстXSD, ИмяВременногоФайла, 5) Тогда
Возврат;
КонецЕсли;
// Или, если нужна запись с параметром:
Если НЕ ЗаписьФайлаПроизошлаУспешно(ТекстXSD, ИмяВременногоФайла, 5, "Источник.Записать(АдресФайла, КодировкаТекста.UTF8);") Тогда
Возврат;
КонецЕсли;
//...
// Проверка доступности переданного узла с помощью команды 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
//...
// Упрощенный конструктор описания типа
//
// Параметры:
// ИмяТипа - Строка, Массив элементов типа "Тип" - первый параметр конструктора ОписаниеТипов()
// п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));
тз.Колонки.Вставить("ДатаОперации" , ОписаниеТипа("Дата"));
МассивТипов = Новый Массив();
МассивТипов.Добавить(Тип("ДокументСсылка.Встреча"));
МассивТипов.Добавить(Тип("ДокументСсылка.ЗапланированноеВзаимодействие"));
тз.Колонки.Вставить("Событие" , ОписаниеТипа(МассивТипов));
тз.Колонки.Вставить("Ответственный" , ОписаниеТипа("СправочникСсылка.Пользователи"));
Возврат тз;
КонецФункции
//...
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 = Неопределено;
Этот метод служит для решения частной задачи отображения группировок колонок в табличных документах, полученных с помощью СКД. Исходная идея вот здесь: СКД. Как объединить заголовки родительских группировок колонок в таблице, я лишь причесал код. Этот вариант не будет работать с уже объединенными ячейками. Может позже допилю, пока нет нужды. Как использовать: в СКД делаем одну группировку колонок, в которую добавлем необходимые поля. После вывода табличного документа на форму вызываем метод.
// Объединяет ячейки шапки табличного документа с повторяющимся текстом
// Служит для решения задачи отображения группировок колонок в табличных документах, полученных с помощью СКД
//
// Параметры:
// ТабДок - ТабличныйДокумент
// ВысотаШапки - Число, если не передана, высотой шапки считается высота фиксации таблицы
//
Процедура СвернутьЗаголовкиШапкиТабличногоДокумента(ТабДок, ВысотаШапки = 0)
ВысотаШапки = ?(ВысотаШапки = 0, ТабДок.ФиксацияСверху, ВысотаШапки);
НачалоШапки = ?(ТабДок.ФиксацияСлева = 0, 1, ТабДок.ФиксацияСлева);
ЭтоПервоеОбъединение = Истина;
Для СчетчикСтрок=1 По ВысотаШапки Цикл
НомерПервойКолонкиОбъединения = 0;
Для СчетчикКолонок=НачалоШапки По ТабДок.ШиринаТаблицы Цикл
ОбъединятьЯчейки = Ложь;
Ячейка = ТабДок.Область(СчетчикСтрок, СчетчикКолонок);
Если ПустаяСтрока(Ячейка.Текст) Тогда
Продолжить;
КонецЕсли;
ЯчейкаСлед = ТабДок.Область(СчетчикСтрок, СчетчикКолонок+1);
ОбъединятьЯчейки = Ячейка.Текст = ЯчейкаСлед.Текст;
Если ОбъединятьЯчейки Тогда
НомерПервойКолонкиОбъединения = ?(НомерПервойКолонкиОбъединения = 0, СчетчикКолонок, НомерПервойКолонкиОбъединения);
ИначеЕсли НомерПервойКолонкиОбъединения > 0 Тогда
ТекстЗаголовка = ТабДок.Область(СчетчикСтрок, СчетчикКолонок).Текст;
ОбъединяемаяОбласть = ТабДок.Область(СчетчикСтрок, НомерПервойКолонкиОбъединения, СчетчикСтрок, СчетчикКолонок);
ОбъединяемаяОбласть.Объединить();
ОбъединяемаяОбласть.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
ОбъединяемаяОбласть.Текст = ТекстЗаголовка;
НомерПервойКолонкиОбъединения = 0;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
// Формирование идентификатора по правилам образования имен переменных 1С по входящей строке
// Пример "Статья возмещение НДС" => "СтатьяВозмещениеНДС"
//
// Параметры:
// стр - Строка - от которой необходимо получить идентификатор
//
// Возвращаемое значение:
// Строка
//
Функция ИдентификаторПоСтроке(ЗНАЧ стр)
ДопустимыеСимволы = "ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁQWERTYUIOPASDFGHJKLZXCVBNM" +
"йцукенгшщзхъфывапролджэячсмитьбюёqwertyuiopasdfghjklzxcvbnm_ ";
СимволыЦифр = "0987654321";
ДопустимыеСимволы = СимволыЦифр + ДопустимыеСимволы;
Пока Найти(стр, " ") > 0 Цикл
стр = СтрЗаменить(стр, " ", " ");
КонецЦикла;
ДлинаСтроки = СтрДлина(стр);
СледующаяЗаглавная = Истина;
Идентификатор = "";
Для сч=1 По ДлинаСтроки Цикл
сим = Сред(стр, сч, 1);
Если Найти(ДопустимыеСимволы, сим) = 0 Тогда
сим = "_";
КонецЕсли;
Если сч = 1 И сим = "_" Тогда
Продолжить;
КонецЕсли;
Если сим = " " Тогда
СледующаяЗаглавная = Истина;
Продолжить;
КонецЕсли;
Если СледующаяЗаглавная Тогда
СледующаяЗаглавная = Ложь;
Сим = Врег(Сим);
КонецЕсли;
ЭтоЦифра = Найти(СимволыЦифр, сим) > 0;
Если сч = 1 И ЭтоЦифра Тогда
сим = "_" + сим;
КонецЕсли;
Если ЭтоЦифра Тогда
СледующаяЗаглавная = Истина;
КонецЕсли;
Идентификатор = Идентификатор + Сим;
КонецЦикла;
Возврат Идентификатор;
КонецФункции
// Преобразование переданного идентификатора в представление
//
// Параметры:
// Идентификатор - Строка - образованная по правилам формирования идентификаторов 1С
//
// Возвращаемое значение:
// Строка - преобразованный идентификатор.
// - Первая буква всегда заглавная
// - Первое подчеркивание пропускается
// - Прочие заглавные буквы преобразуются в нижний регистр, после вставляется пробел
// - Между цифрой и буквой вставляется пробел, между подряд идущими цифрами пробелов нет
// - Несколько сплошных подчеркиваний воспринимаются как один, превращаются в пробел
// - В строке может присутствовать символ, отличный от допустимых в идентификаторе - не обрабатывается
// - Учитывается капитель (аббревиатуры) и спецсимволы в капители
//
// Примеры:
// "ЭтоДата23_05_06" -> "Это дата 23 05 06"
// "Это____ПримерС_Подчеркиваниями" -> "Это пример с подчеркиваниями"
// "это_ПримерС_ПервойНеЗаглавной" -> "Это пример с первой не заглавной"
// "Это_ПримерС_НевернымИден???тификатором*" -> "Это пример с неверным иден???тификатором*"
// "_Это_ПримерС_первымПодчеркиванием" -> "Это пример с первым подчеркиванием"
// "Это_КАПИ_ТЕЛЬ" -> "Это КАПИТЕЛЬ"
// "Это_КАПИ99ТЕЛЬ" -> "Это КАПИ 99 ТЕЛЬ"
// "Это_КАПИ??ТЕЛЬ" -> "Это КАПИ??ТЕЛЬ"
//
Функция ИдентификаторВПредставление(Идентификатор) Экспорт
Цифры = "0123456789";
Алфавит = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
ИдентификаторКОбработке = СокрЛП(Идентификатор);
Пока Найти(ИдентификаторКОбработке, "__") Цикл
ИдентификаторКОбработке = СтрЗаменить(ИдентификаторКОбработке, "__", "_");
КонецЦикла;
Пока Лев(ИдентификаторКОбработке, 1) = "_" Цикл
ИдентификаторКОбработке = Сред(ИдентификаторКОбработке, 2);
КонецЦикла;
ПредыдущийЗнакЭтоПробел = Ложь;
ПредыдущийЗнакЭтоЦифра = Ложь;
ПредыдущийЗнакЭтоЗаглавная = Ложь;
ПредыдущийЗнакЭтоСпецСимвол = Ложь;
Слово = "";
Для сч=1 По СтрДлина(ИдентификаторКОбработке) Цикл
ДобавитьПробел = Ложь;
Сим = Сред(ИдентификаторКОбработке, сч, 1);
ВрегСим = Врег(Сим);
НрегСим = Нрег(Сим);
СимВСлово = Сим;
ЭтоНижнийСлэш = сим = "_";
ЭтоЦифра = Найти(Цифры, Сим) > 0;
ЭтоБуква = Найти(Алфавит, ВрегСим) > 0;
ЭтоПрочийЗнак = НЕ (ЭтоНижнийСлэш ИЛИ ЭтоЦифра);
ЭтоЗаглавная = (Сим = ВрегСим) И (Сим <> НрегСим);
Если сч=1 Тогда
СимВСлово = ВрегСим;
ИначеЕсли ЭтоЦифра И НЕ ПредыдущийЗнакЭтоЦифра Тогда
ДобавитьПробел = Истина;
ИначеЕсли ЭтоНижнийСлэш Тогда
ДобавитьПробел = Истина;
СимВСлово = "";
ИначеЕсли ЭтоПрочийЗнак И ЭтоЗаглавная И НЕ ПредыдущийЗнакЭтоЗаглавная И НЕ ПредыдущийЗнакЭтоСпецСимвол Тогда
ДобавитьПробел = Истина;
СимВСлово = НрегСим;
КонецЕсли;
ЭтоВторойСимволКапители = ЭтоЗаглавная И ПредыдущийЗнакЭтоЗаглавная;
Если ЭтоВторойСимволКапители Тогда
ПоследнийСимвол = Прав(Слово, 1);
Слово = Сред(Слово, 1, СтрДлина(Слово)-1) + ВРЕГ(ПоследнийСимвол);
КонецЕсли;
ДобавитьПробел = ДобавитьПробел И НЕ ПредыдущийЗнакЭтоПробел;
Если ДобавитьПробел Тогда
СимВСлово = " " + СимВСлово;
КонецЕсли;
Слово = Слово + СимВСлово;
ПредыдущийЗнакЭтоПробел = СимВСлово = " ";
ПредыдущийЗнакЭтоЦифра = ЭтоЦифра;
ПредыдущийЗнакЭтоЗаглавная = ЭтоЗаглавная;
ПредыдущийЗнакЭтоСпецСимвол = НЕ (ЭтоБуква ИЛИ ЭтоНижнийСлэш ИЛИ ЭтоЦифра);
КонецЦикла;
Возврат Слово;
КонецФункции
// Формирование структуры для первой (единственной) записи результата запроса
//
// Параметры:
// РезультатЗапроса - РезультатЗапроса, источник данных
//
// Возвращаемое значение:
// Структура - Набор ключей повторяет набор колонок результат запроса, значения заполняются
// значениями первой записи выборки
//
Функция РезультатЗапросаВСтруктуру(РезультатЗапроса) Экспорт
СтруктураРезультат = Новый Структура;
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Для каждого Колонка Из РезультатЗапроса.Колонки Цикл
Если Выборка.Количество() = 0 Тогда
МассивТипов = Колонка.ТипЗначения.Типы();
ОбщегоНазначенияКлиентСервер.УдалитьЗначениеИзМассива(МассивТипов, Тип("Null"));
ОписаниеТиповБезNULL = Новый ОписаниеТипов(МассивТипов);
ЗначениеПоля = ОписаниеТиповБезNULL.ПривестиЗначение();
Иначе
ЗначениеПоля = Выборка[Колонка.Имя];
КонецЕсли;
СтруктураРезультат.Вставить(Колонка.Имя, ЗначениеПоля);
КонецЦикла;
Возврат СтруктураРезультат;
КонецФункции
Вступайте в нашу телеграмм-группу Инфостарт
Замер времени вхождение в интервал разбить строку парсинг строки
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
См. также
Универсальные функции 1С 8.3 1С:Документооборот Россия Платные (руб)
ДО+ — расширение конфигурации, в котором собран постоянно пополняемый набор из 33 востребованных доработок для 1С:Документооборот КОРП 3.0: согласование задач прямо из мессенджеров MAX и Telegram, отзыв согласования и исполнения, гибкие повторные круги, эскалация с точностью до минут, контроль исполнительской дисциплины, выгрузка вложений в ZIP и склейка PDF, реестр документов в Excel, проверка дублей контрагентов и регистрационных номеров. Каждая возможность активируется отдельным флажком в режиме предприятия — включается только то, что нужно конкретной организации. Список функций расширяется с каждым релизом — текущая версия 2.1.0. Режим AddOn: типовая конфигурация не модифицируется, обновления ДО ставятся штатно, дополнительные лицензии и внешние компоненты не требуются. Внедрение силами администратора — около часа.
30000 руб.
09.07.2026 1466 1 0
Загрузка и выгрузка в Excel Универсальные функции Разработчик 1С:Предприятие 8 Россия Бесплатно (free)
Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).
30.10.2025 8821 Abysswalker 11
Универсальные функции Работа с интерфейсом Разработчик 1С:Предприятие 8 Бесплатно (free)
Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.
14.05.2025 14599 DeerCven 16
Инструментарий разработчика Универсальные функции Запросы Разработчик 1С:Предприятие 8 1C:Бухгалтерия 1С:Бухгалтерия 3.0 1С:Зарплата и Управление Персоналом 3.x Бесплатно (free)
Внешняя обработка для создания запроса на основании табличных данных.
22.07.2024 12000 278 ixijixi 10
Универсальные функции Разработчик 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.
21.05.2024 68984 dimanich70 87
Универсальные функции Разработчик 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)
Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.
1 стартмани
18.03.2024 9352 7 John_d 13
Универсальные функции Разработчик Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.
12.02.2024 86011 atdonya 31
Универсальные функции Разработчик 1С:Предприятие 8 Бесплатно (free)
На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.
30.11.2023 13524 ke.92@mail.ru 18
ТекущаяУниверсальнаяДатаВМиллисекундах(). Функция появилась в каком-то релизе 8.3
(2) tireal, спасибо за комментарий. Но:
- свою функцию я могу использовать в любом релизе платформы. Да, я порой работаю с 8.1 - как ни странно оно еще есть.
- если мне когда-нибудь понадобится настолько низкоуровневое отслеживание выполнения алгоритма - я скорее воспользуюсь замером времени отладчика
- могу предположить что назначение использования вашей функции - тестирование скорости исполнения алгоритма (т. е. она для этой цели писалась); моей - просто замер времени работы для сообщения/ помещения в лог - секунды вполне устраивают
Останусь при своем, но буду знать и о таком варианте, еще раз спасибо.
Попытка
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, почитайте внимательнее мой комментарий в (3) . И да, мне удобнее воспользоваться замером времени, чем вставлять в конфу отладочную печать. Не могу вспомнить случая, когда я не мог без этого обойтись. Может опыта еще маловато)
Имхо, все извращения с получением настолько точного времени - связаны с необходимостью отслеживать СКОРОСТЬ, а не ВРЕМЯ выполнения алгоритма. Разница трудноуловима, но она есть. Мне не надо с точностью до миллисекунды знать сколько времени проводился массив документов - 20 мин меня вполне устроит. Но если я тестирую напр. как быстрее создавать таблицу значений - тут нужны миллисекунды. Просто для универсальности функция замера обычно реализуется наиболее детализированно - т.е. через тот-же ява-скрипт. Ну а мне как-то не нужно было. Если понадобится - возьму из (6).
Смешно. Вы думаете всякие извращения с джаваскриптами и т.п. появились потому что ни кто не додумался время выполнения в отладчике смотреть?!
Спасибо любимой 1С, они хоть от необходимости использовать внешние скрипты избавили, добавив в платформу функцию
ТекущаяУниверсальнаяДатаВМиллисекундах()А для старых версий платформы остается только замерять время выполнения при помощи внешних средств, например джава-скрипта.
докВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
//процедура замера
докВремяКонцаВыполнения = ТекущаяУниверсальнаяДатаВМиллисекундах();
докДельта = (докВремяКонцаВыполнения - докВремяНачала) / 1000;
докДельтаПредставление = ПолучитьПредставлениеВремени(докДельта);
Функция ПолучитьПредставлениеВремени(Время)
Секунды = Время % 60;
Минуты = (Время-Секунды)/60;
Минуты = Минуты % 60;
Часы = (Время-Секунды-Минуты)/3600;
Возврат "" + Окр(Часы) + " ч. " + Окр(Минуты) + " мин. " + Окр(Секунды, 2) + " сек.";
КонецФункции
ПоказатьВ 1С далеко не дураки сидят
Вы можете ошибаться... собственное развитие и вынужденная работа со старыми версиями конфигураций в учетных системах заказчика/ работодателя - в большинстве случаев ни как не связаны.
Переход предприятия на новую систему учета/ платформу - это достаточно дорогое удовольствие, и только из-за желания программиста работать с новыми версиями платформ/ конфигураций ни кто, в здравом уме, переходить не будет.
Вот это вроде с давних времен работает
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных=Новый ОписаниеИсточникаДанных(ТабДок.Область());
Построитель.Выполнить();
ТЗ = Построитель.Результат.Выгрузить();
// клиентский модуль
Процедура ЗасечьТаймер() Экспорт
УправляемыйИнтерфейсСервер.СохранитьЗначениеВХранилище( "ТекВремяТаймера", ТекущаяДата() );
//ПоместитьВоВременноеХранилище( ТекущаяДата(), );
КонецПроцедуры
Процедура ПоказатьВремяТаймера( пЗаголовок = "", пЧерезСообщение = Ложь ) Экспорт
д = УправляемыйИнтерфейсСервер.ПолучитьЗначениеИзХранилища( "ТекВремяТаймера" );
общ = ТекущаяДата() - д;
мин = цел( общ / 60 );
сек = общ - мин * 60;
час = цел( мин / 60);
мин = мин - час * 60;
лВрем = ?( пЧерезСообщение, "Время выполнения:", "Время:" );
Если час <> 0 Тогда
лВрем = лВрем + " " + час + " час"
КонецЕсли;
Если Мин <> 0 Тогда
лВрем = лВрем + " " + мин + " мин"
КонецЕсли;
лВрем = лВрем + " " + сек + " сек";
Если пЧерезСообщение=Ложь Тогда
ПоказатьОповещениеПользователя( пЗаголовок, , лВрем );
Иначе
Сообщить( ?( ПустаяСтрока( пЗаголовок ), "Действие выполнено", пЗаголовок ) + ". " + лВрем );
КонецЕсли;
КонецПроцедуры
// серверный модуль УправляемыйИнтерфейсСервер
Процедура СохранитьЗначениеВХранилище( пКлюч, пЗначение ) Экспорт
ХранилищеСистемныхНастроек.Сохранить( , пКлюч, пЗначение, , ПараметрыСеанса.ТекущийПользователь );
КонецПроцедуры
Функция ПолучитьЗначениеИзХранилища( пКлюч ) Экспорт
Возврат ХранилищеСистемныхНастроек.Загрузить( , пКлюч, , ПараметрыСеанса.ТекущийПользователь );
КонецФункции
// пример использования
&НаКлиенте
Процедура СделатьЧтоТо()
УправляемыйИнтерфейс.ЗасечьТаймер();
// что-то делаем
// ......................
УправляемыйИнтерфейс.ПоказатьВремяТаймера("Сделали что-то!");
КонецПроцедуры
ПоказатьСпециально не тестил, свое предназначение выполняет; вообще, должна. Возможно в регистрах символов будет различие, но т.к не имею кода платформы на руках 100% гарантии дать не могу)
// Проверяет, является ли строка уникальным идентификатором.
// В качестве уникального идентификатора предполагается строка вида
// "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", где X = [0..9,a..f].
//
// Параметры:
// Значение - Строка - проверяемая строка.
//
// Возвращаемое значение:
// Булево - Истина, если переданная строка является уникальным идентификатором.
//
Функция ЭтоУникальныйИдентификатор(Знач Значение) Экспорт
Шаблон = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
Если СтрДлина(Шаблон) <> СтрДлина(Значение) Тогда
Возврат Ложь;
КонецЕсли;
Для Позиция = 1 По СтрДлина(Значение) Цикл
Если КодСимвола(Шаблон, Позиция) = 88 // X
И ((КодСимвола(Значение, Позиция) < 48 Или КодСимвола(Значение, Позиция) > 57) // 0..9
И (КодСимвола(Значение, Позиция) < 97 Или КодСимвола(Значение, Позиция) > 102) // a..f
И (КодСимвола(Значение, Позиция) < 65 Или КодСимвола(Значение, Позиция) > 70)) // A..F
Или КодСимвола(Шаблон, Позиция) = 45 И КодСимвола(Значение, Позиция) <> 45 Тогда // -
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
ПоказатьНу или сделать опциональный параметр в функции ТабличныйДокументВТаблицуЗначений по значению которого будет возвращаться таблица значений или массив структур
Хотя, конечно, это частный случай. Но я на всякий пожарный стараюсь использовать такой способ, чтобы потом не переделывать. Пару раз наталкивался
| Код |
|---|
// Процедура удаляет строки из таблицы значений по условию.
//
// Параметры:
// прТаблица - ТаблицаЗначений - таблица значений.
// прУсловие - Строка - условие по которому присходит удаление.
// прСтруктураДопЗначений - Структура - дополнительные значения, передаваймые в процедуру
// для использования в условии удаления
//
Процедура УдалитьСтрокиПоУсловию(прТаблица, прУсловие = "", прСтруктураДопЗначений = Неопределено) Экспорт
КолвоСтрок = прТаблица.Количество();
Если прУсловие = "" Тогда Возврат; КонецЕсли;
Условие = "ВыполненоУсловиеУдаления = (" + прУсловие + ")";
Для ОбратныйИндекс = 1 По КолвоСтрок Цикл
СтрокаТаблицы = прТаблица[КолвоСтрок - ОбратныйИндекс];
ВыполненоУсловиеУдаления = Ложь;
Выполнить(Условие);
Если ВыполненоУсловиеУдаления Тогда
прТаблица.Удалить(СтрокаТаблицы);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ТаблицаЗначенийВТаблицуХТМЛ(ТабЗначений,СтруктураПараметрыТаблицыХТМЛ = Неопределено) Экспорт
//СтруктураПараметрыТаблицыХТМЛ
//
//Общие параметры:
//СтруктураПараметрыТаблицыХТМЛ.ШиринаТаблицы - общая ширина таблица
//СтруктураПараметрыТаблицыХТМЛ.ЦветШапки - цвет шапки таблицы пример "eadbaf"
//СтруктураПараметрыТаблицыХТМЛ.ПунктПорядкуИспользуется - по умолчанию ЛОЖЬ
//
//Индивиуальные для каждой колонки:
//СтруктураПараметрыТаблицыХТМЛ.Заголовок1 - заголовок для первой колонки, цифра на конце обознает номер колонки (не с нуля)
//СтруктураПараметрыТаблицыХТМЛ.Ширина1 - ширина для первой колонки, цифра на конце обознает номер колонки (не с нуля)
//СтруктураПараметрыТаблицыХТМЛ.Положение1 - отвечает за положение текста в колонке (по умол. лево), передовать "center" или "right"
//ТабЗначений = Новый ТаблицаЗначений;
МассивИменКолонок = Новый Массив;
Если ТипЗнч(СтруктураПараметрыТаблицыХТМЛ) <> Тип("Структура") Тогда
СтруктураПараметрыТаблицыХТМЛ = Новый Структура;
КонецЕсли;
КоличествоКолонок = ТабЗначений.Колонки.Количество();
ПунктПорядкуИспользуется = ?(СтруктураПараметрыТаблицыХТМЛ.Свойство("ПунктПорядкуИспользуется"),СтруктураПараметрыТаблицыХТМЛ.ПунктПорядкуИспользуется,ЛОЖЬ);
Если КоличествоКолонок < 0 Тогда
Возврат Неопределено;
КонецЕсли;
ЦветШапки = ?(СтруктураПараметрыТаблицыХТМЛ.Свойство("ЦветШапки")," bgcolor=""#" + СтруктураПараметрыТаблицыХТМЛ.ЦветШапки + """","");
ШиринаТаблицы = ?(СтруктураПараметрыТаблицыХТМЛ.Свойство("ШиринаТаблицы")," style=""width:" + СтруктураПараметрыТаблицыХТМЛ.ШиринаТаблицы + "px""","");
ТаблицаХТМЛ = "<table border=""1"" cellpadding=""1"" cellspacing=""0"" " + ШиринаТаблицы + ">
|<tbody>
|<tr>";
//Первым выводим столбик П/П если он задан в шапку
Если ПунктПорядкуИспользуется Тогда
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|<td" + ЦветШапки + " style=""width:30px"" align=""center"">п/п</td>";
КонецЕсли;
//Формируем шапку
Для Счетчик = 1 по КоличествоКолонок Цикл
ИмяСвойстваШирина = "Ширина" + Счетчик;
ШиринаСтолбца = ?(СтруктураПараметрыТаблицыХТМЛ.Свойство(ИмяСвойстваШирина)," style=""width:" + СтруктураПараметрыТаблицыХТМЛ[ИмяСвойстваШирина] + "px""","");
ИмяКолонки = ТабЗначений.Колонки[Счетчик-1].Имя;
ИмяСвойстваЗаголовок = "Заголовок" + Счетчик;
ЗаголовокКолонки = ?(СтруктураПараметрыТаблицыХТМЛ.Свойство(ИмяСвойстваЗаголовок),СтруктураПараметрыТаблицыХТМЛ[ИмяСвойстваЗаголовок],ИмяКолонки);
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|<td" + ЦветШапки + ШиринаСтолбца + " align=""center"">" + ЗаголовокКолонки + "</td>";
МассивИменКолонок.Добавить(ИмяКолонки);
КонецЦикла;
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|</tr>";
//Заполняем таблицу
ПунктПорядку = 0;
Для каждого СтрокаТаблицы Из ТабЗначений Цикл
ПунктПорядку = ПунктПорядку + 1;
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|<tr>" + ?(ПунктПорядкуИспользуется, Символы.ПС + "<td align=""center"">" + ПунктПорядку + "</td>","") + "";
Для Счетчик = 0 по КоличествоКолонок - 1 Цикл
ИмяСвойстваПоложение = "Положение" + Строка(Счетчик + 1);
Положение = " align=""" + ?(СтруктураПараметрыТаблицыХТМЛ.Свойство(ИмяСвойстваПоложение),СтруктураПараметрыТаблицыХТМЛ[ИмяСвойстваПоложение],"left") + """";
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|<td " + Положение + ">" + СтрокаТаблицы[МассивИменКолонок[Счетчик]] + "</td>";
КонецЦикла;
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|</tr>";
КонецЦикла;
ТаблицаХТМЛ = ТаблицаХТМЛ + "
|</tbody>
|</table>";
Возврат ТаблицаХТМЛ;
КонецФункции
Показать полностью |
Возвращать кучу данных на клиент, которые по здравой логике должен отработать сервер, вернув более лёгкий ответ - могу назвать только костылями.
Соглашусь, что случаи бывают разные. Но здесь заплатки публиковать не намерен.
Посмотрите функцию БСП ОбщегоНазначения.ТаблицаЗначенийВМассив
Ничего не напоминает? Да это же тот же самый костыль который мы сейчас обсуждаем! Это массив структур из таблицы значений. А для чего 1с его сделали? наверное как раз для тех же самых целей, которые вы считаете костылем. Передача коллекции с сервера на клиента.
// Преобразует таблицу значений в массив структур.
// Может использоваться для передачи на клиент данных в том случае, если таблица
// значений содержит только такие значения, которые могут
// быть переданы с сервера на клиент.
//
// Полученный массив содержит структуры, каждая из которых повторяет
// структуру колонок таблицы значений.
//
// Не рекомендуется использовать для преобразования таблиц значений
// с большим количеством строк.
//
// Параметры:
// ТаблицаЗначений - ТаблицаЗначений - исходная таблица значений.
//
// Возвращаемое значение:
// Массив - коллекция строк таблицы в виде структур.
//
Функция ТаблицаЗначенийВМассив(ТаблицаЗначений) Экспорт
Массив = Новый Массив();
СтруктураСтрокой = "";
НужнаЗапятая = Ложь;
Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
Если НужнаЗапятая Тогда
СтруктураСтрокой = СтруктураСтрокой + ",";
КонецЕсли;
СтруктураСтрокой = СтруктураСтрокой + Колонка.Имя;
НужнаЗапятая = Истина;
КонецЦикла;
Для Каждого Строка Из ТаблицаЗначений Цикл
НоваяСтрока = Новый Структура(СтруктураСтрокой);
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
Массив.Добавить(НоваяСтрока);
КонецЦикла;
Возврат Массив;
КонецФункции
ПоказатьПро передачу большого количества данных - тут бесспорно. Нельзя так делать
// Длительность - в миллисекундах
ВремяСтрокой = Формат('00010101' + Цел(Длительность/ 1000), "ДЛФ=T");
Все остальное - ну очень не лениво :)
Как быть если возвращается верно, как преобразовать в кириллицу?
ћў¬ґ ї єґв ¬ё б ya.ru [87.250.250.242] б 32 ў ©в ¬ё ¤ ле:
ћвўґв ®в 87.250.250.242: зёб«® ў ©в=32 ўаґ¬п=76¬б ttl=54
ћвўґв ®в 87.250.250.242: зёб«® ў ©в=32 ўаґ¬п=67¬б ttl=54
ћвўґв ®в 87.250.250.242: зёб«® ў ©в=32 ўаґ¬п=68¬б ttl=54
ћвўґв ®в 87.250.250.242: зёб«® ў ©в=32 ўаґ¬п=67¬б ttl=54
‘в вёбвёє ping ¤«п 87.250.250.242:
џ єґв®ў: ®вїа ў«ґ® = 4, ї®«гзґ® = 4, ї®вґап® = 0
(0% ї®вґам)
џаёў«ё§ёвґ«м®ґ ўаґ¬п їаёґ¬ -їґаґ¤ зё ў ¬б:
њёё¬ «м®ґ = 67¬бґє, њ єбё¬ «м®ґ = 76 ¬бґє, ‘തґґ = 69 ¬бґє
Функция Пинг(АдресURL = "")
Если ПустаяСтрока(АдресURL) Тогда
АдресURL = "www.ya.ru";
КонецЕсли;
objShell = Новый COMОбъект("WScript.Shell") ;
objScriptExec = objShell.Exec("ping.exe -n 4 " + АдресURL);
strPingResults = НРег(objScriptExec.StdOut.ReadAll());
ЕстьСоединение = Найти(strPingResults, "ttl=") > 0;
Возврат ЕстьСоединение;
КонецФункции
&НаКлиенте
Процедура КомандаПинг(Команда)
ЕстьСоединениеСИнтернетом = Пинг();
КонецПроцедуры
ПоказатьВы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 449681
Создание 26.02.16 01:55
Обновление 03.11.19 01:33
Просмотры 54606
Загрузки 0
Рейтинг
315
Комментарии 48
Код открыт Да
Рубрики Универсальные функции
Кому Разработчик
Тип файла Нет файла
Платформа 1С:Предприятие 8
Конфигурация Универсальные
Операционная система Не имеет значения
Страна Не имеет значения
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)