Задача: Открыть файл прикрепленный к справочнику на клиенте приложением по умолчанию (передать файл с сервера на клиент)
Решение: любой файл который «прикреплен» к справочнику, если используется БСП , на самом деле находится в справочнике Файлы. Это для старых версий БСП. В новых версиях имя справочника носит шаблонное имя [ИмяСправочника]ПрисоединенныеФайлы. В обоих вариантах у этик справочников есть реквизит «Владелец файла». Вот по нему и получим самый первый прикрепленный файл.
&НаСервере
Функция ОткрытьФайлНаСервере()
фф="";
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Файлы.Ссылка КАК Ссылка,
| Файлы.ПолноеНаименование КАК ПолноеНаименование,
| Файлы.ТекущаяВерсияПутьКФайлу КАК ТекущаяВерсияПутьКФайлу,
| Файлы.ТекущаяВерсияТом.ПолныйПутьWindows КАК ТекущаяВерсияТомПолныйПутьWindows,
| Файлы.ГлавныйФайл КАК ГлавныйФайл,
| Файлы.ТекущаяВерсияРасширение КАК ТекущаяВерсияРасширение,
| Файлы.Наименование КАК Наименование
|ИЗ
| Справочник.Файлы КАК Файлы
|ГДЕ
| Файлы.ВладелецФайла = &ВладелецФайла
| И Файлы.ПометкаУдаления = ЛОЖЬ";
Запрос.УстановитьПараметр("ВладелецФайла", объект.ДокОб);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
сообщить(ВыборкаДетальныеЗаписи.Ссылка);
фф=ВыборкаДетальныеЗаписи.ТекущаяВерсияТомПолныйПутьWindows+ВыборкаДетальныеЗаписи.ТекущаяВерсияПутьКФайлу;
КонецЦикла;
если фф<>"" тогда
Двоичное=Новый ДвоичныеДанные(фф);
Адрес=ПоместитьВоВременноеХранилище(Двоичное,ЭтаФорма.УникальныйИдентификатор);
Возврат Новый Структура("error,address,filename",false,Адрес,ВыборкаДетальныеЗаписи.Наименование+"."+ВыборкаДетальныеЗаписи.ТекущаяВерсияРасширение);
иначе
Возврат Новый Структура("error,address,filename",true);
конецесли
КонецФункции
На клиенте таким образом мы получим имя файла и адрес во временном хранилище. Остаётся сохранить файл во временный каталог и открыть его приложением по умолчанию:
&НаКлиенте
Процедура ОткрытьФайл(Команда)
рез=ОткрытьФайлНаСервере();
если рез.error=false тогда
Двоичное=ПолучитьИзВременногоХранилища(рез.address);
ИмяФайла = КаталогВременныхФайлов() + рез.filename;
Двоичное.Записать(ИмяФайла);
ЗапуститьПриложение(ИмяФайла);
конецесли;
КонецПроцедуры
Со временем, даже в небольших конфигурациях 1С количество пользователей чаще всего увеличивается. А если еще и компания достаточно большая, то возникает необходимость следить за тем, чтобы учётки вовремя отключались. А еще и были безопасны с точки зрения использования. Например: достаточно часто пользователь меняет пароль, включена ли у него доменная авторизация и т.п., Фактически полноценная проверка безопасности пользователей 1С
В моём случае возникла необходимость регулярно мониторить служебные учётные данные. Количество разработчиков большое. Количество http и web сервисов не большое, но постоянно растёт, т.к. мы придерживаюсь принципа: один сервис — одна учётка для доступа. Делается это для того чтобы было удобнее логировать и отслеживать кто что и как. Соответственно необходимо чтобы эти служебные пользователи имели строго определенные доступы, и не имели возможность непосредственного входа в 1С через толстый и тонкий клиенты.
После калькуляции требований безопасности я выявил следующие показатели для того чтобы считать учётную запись «неблагонадёжной»:
нет доменной авторизации
разрешен вход в 1с (галочка «Доступ к информационной базе разрешен» в справочнике Пользователи)
у пользователя включены роли ЗапускВебКлиента, ЗапускТолстогоКлиента, ЗапускВнешнегоСоединения
При ответе «Да» на все три условия, пользователя помещаю в соответствующий список.
Кроме того дополнительно провожу проверку, что в правах одной из ролей есть права: ЗапускВебКлиента, ЗапускТолстогоКлиента, ЗапускВнешнегоСоединения
В итоге родил такую обработку:
Процедура СК_ГР_ПроверкаБезопасностиПользователя() экспорт
УстановитьПривилегированныйРежим(Истина);
Выборка = ПользователиИнформационнойБазы.ПолучитьПользователей();
МассивДляОтчета=Новый Массив();
данные="";
бд=НСтр(СтрокаСоединенияИнформационнойБазы(), "Ref");
Для Каждого ЭлементМассива Из Выборка Цикл
если ЭлементМассива.АутентификацияОС=ложь тогда
если ЭлементМассива.АутентификацияСтандартная=истина тогда
инф=Новый Структура("полноеимя,имя,email,датапароля,показыватьвспискевыбора,роли,пользователь,ЗапускВебКлиента,ЗапускТолстогоКлиента,ЗапускТонкогоКлиента,ЗапускВнешнегоСоединения");
инф.полноеимя=ЭлементМассива.ПолноеИмя;
инф.имя=ЭлементМассива.Имя;
инф.email=ЭлементМассива.АдресЭлектроннойПочты;
инф.датапароля=ЭлементМассива.ДатаУстановкиПароля;
инф.показыватьвспискевыбора=ЭлементМассива.ПоказыватьВСпискеВыбора;
инф.роли="";
ЕстьПароль = ЭлементМассива.ПарольУстановлен;
Роли = ЭлементМассива.Роли;
Для Каждого Роль Из Роли Цикл
если ПравоДоступа("ВебКлиент",Метаданные,Роль) тогда
инф.роли=инф.роли+Роль.Имя+", ";
иначеесли ПравоДоступа("ВнешнееСоединение",Метаданные,Роль) тогда
инф.роли=инф.роли+Роль.Имя+", ";
иначеесли ПравоДоступа("ТолстыйКлиент",Метаданные,Роль) тогда
инф.роли=инф.роли+Роль.Имя+", ";
иначеесли ПравоДоступа("ТонкийКлиент",Метаданные,Роль) тогда
инф.роли=инф.роли+Роль.Имя+", ";
конецесли;
КонецЦикла;
поль=Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ",ЭлементМассива.УникальныйИдентификатор);
ЗапускРоль="";
если поль<>Справочники.Пользователи.ПустаяСсылка() тогда
инф.ЗапускВебКлиента=УправлениеДоступом.ЕстьРоль("ЗапускВебКлиента",, поль);
если инф.ЗапускВебКлиента=истина тогда
ЗапускРоль=ЗапускРоль+"Веб, ";
конецесли;
инф.ЗапускТолстогоКлиента=УправлениеДоступом.ЕстьРоль("ЗапускТолстогоКлиента",, поль);
если инф.ЗапускТолстогоКлиента=истина тогда
ЗапускРоль=ЗапускРоль+"Толстый, ";
конецесли;
инф.ЗапускТонкогоКлиента=УправлениеДоступом.ЕстьРоль("ЗапускТонкогоКлиента",, поль);
если инф.ЗапускТонкогоКлиента=истина тогда
ЗапускРоль=ЗапускРоль+"Тонкий, ";
конецесли;
инф.ЗапускВнешнегоСоединения=УправлениеДоступом.ЕстьРоль("ЗапускВнешнегоСоединения",, поль);
если инф.ЗапускВнешнегоСоединения=истина тогда
ЗапускРоль=ЗапускРоль+"Внешние, ";
конецесли;
конецесли;
инф.пользователь=поль.Наименование;
МассивДляОтчета.Добавить(инф);
данные=данные+"<tr>";
данные=данные+" <td>"+инф.полноеимя+"</td>";
данные=данные+" <td>"+инф.имя+"</td>";
данные=данные+" <td>"+инф.пользователь+"</td>";
данные=данные+" <td>"+инф.email+"</td>";
данные=данные+" <td>"+инф.датапароля+"</td>";
данные=данные+" <td>"+инф.показыватьвспискевыбора+"</td>";
данные=данные+" <td>"+ЗапускРоль+"</td>";
данные=данные+" <td>"+инф.роли+"</td>";
данные=данные+"</tr>";
Конецесли;
Конецесли;
КонецЦикла;
если МассивДляОтчета.Количество()>0 тогда
тело="<style>td {border: 1px solid;} th{border: 1px solid;} table.table {word-wrap:true;border-collapse: collapse;border-spacing: 0;}table.table > thead > tr > th {font-size: 14px;font-weight: normal;padding-top: 7px;padding-bottom: 7px;}.table > thead > tr > th {vertical-align: bottom;border-bottom: 2px solid #ddd;}table.table th {background-color: #153e76;}</style>";
тело=тело+"Критерии попадания в этот список: отключена доменная авторизация, разрешен вход в 1С<br/>";
тело=тело+"<strong>Подозрительные учётки</strong>: <br/>";
тело=тело+"<table class='table'>";
тело=тело+" <thead>";
тело=тело+" <tr>";
тело=тело+" <th scope='col'> Полное имя</th>";
тело=тело+" <th scope='col'> Имя</th>";
тело=тело+" <th scope='col'> Пользователь</th>";
тело=тело+" <th scope='col'> Email</th>";
тело=тело+" <th scope='col'> Дата пароля</th>";
тело=тело+" <th scope='col'> В списке выбора</th>";
тело=тело+" <th scope='col'> Вид запуска</th>";
тело=тело+" <th scope='col'> Роли с доступом в 1С</th>";
тело=тело+" </tr>";
тело=тело+" </thead>";
тело=тело+" <tbody>";
тело=тело+данные;
тело=тело+" </tbody>";
тело=тело+"</table>";
emails=Новый Массив();
emails.Добавить("цкуаука@куауцкацук.ru");
для каждого email из emails цикл
если email<>"" тогда
попытка
ПараметрыПисьма = Новый Структура("Кому, Тема, Тело,ТипТекста", email, "Подозрительные учётки в БД: "+бд, тело,"HTML");
если бд="укму" тогда
УчетнаяЗаписьПочты = РаботаСПочтовымиСообщениями.ПолучитьСистемнуюУчетнуюЗапись();
РаботаСПочтовымиСообщениями.ОтправитьСообщение(УчетнаяЗаписьПочты, ПараметрыПисьма);
иначеесли бд="куепуке" тогда
УчетнаяЗаписьПочты = РаботаСПочтовымиСообщениями.ПолучитьСистемнуюУчетнуюЗапись();
РаботаСПочтовымиСообщениями.ОтправитьСообщение(УчетнаяЗаписьПочты, ПараметрыПисьма);
иначеесли бд="укепуке" тогда
РаботаСПочтовымиСообщениями.ОтправитьПочтовоеСообщение(РаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись(),ПараметрыПисьма);
иначеесли бд="куепук" тогда
РаботаСПочтовымиСообщениями.ОтправитьПочтовоеСообщение(РаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись(),ПараметрыПисьма);
конецесли;
исключение
ЗаписьЖурналаРегистрации("Ошибка", УровеньЖурналаРегистрации.Ошибка,,ОписаниеОшибки(),);
конецпопытки;
конецесли;
конеццикла;
конецесли;
УстановитьПривилегированныйРежим(ложь);
КонецПроцедуры
Обработкой я перебираю всех пользователей информационной базы, и ищу соответствующего пользователя из справочника «Пользователи». В том случае, если пользователя признаю потенциально не безопасным, то отправляю заинтересованному лицу уведомление на электронную почту.
Довольно часто встречается задача автоматизировать заполнение всяческих заявлений..ну например в бухгалтерию. Это вполне можно сделать и на PHP, позволив пользователю на форме веб страницы заполнить основные данные, а затем отдав ему уже сформированный на основе шаблона файл формата docx (файл docx на основе шаблона).
На JavaScript создам функцию — обработчик нажатия на кнопку «Сформировать заявление». Функция делает запрос на сервер, а в ответ получает сформированный файл. Браузер автоматически предложит его сохранить.
function CreateZay(){
console.log("--создаётся заявление..");
var xhr = new XMLHttpRequest();
xhr.open('POST', '/sever/zayav.php', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var link=document.createElement('a');
link.href=window.URL.createObjectURL(this.response);
link.download="result.docx";
link.click();
}
else {
console.log(e);
}
};
var form_data = new FormData();
form_data.append("position_at_work", position_at_work.value);
form_data.append("me_unit", me_unit.value);
form_data.append("me_name", me_name.value);
form_data.append("date_start", date_start.value);
form_data.append("long_vacation", long_vacation.value);
xhr.send(form_data);
};
С клиентской частью (ну которая в браузере) разобрались. Теперь займемся сервером. Чтобы ничего не изобретать, воспользуемся пакетом phpoffice/phpword:
composer require phpoffice/phpword
Далее подготовим файл-шаблон. Можно в любом редакторе, который поддерживает расширение docx. В файле , те части которые мы хотим заменить, обрамляем ${имя_переменноя}, чтобы получилось например что-то вроде:
Далее, серверная часть, которая заполняет непосредственно сам шаблон:
Задача: Необходимо чтобы при отображении на HTML странице поля input с типом дата, автоматически подставлялась определенная дата (заполнение текущей датой поля input). Ну например текущая+14 дней.
Решение: собственно без javascript тут не обойтись (ну если исключить вариант, что html генерируется на сервере, и соответственно заполняется поле value. Но это не наш метод (с)
<script>
var date = new Date(Date.now());
date.setDate(date.getDate() + 14);
date_start.value=date.toISOString().split("T")[0];
</script>
Что тут интересного? Ну фактически мы пользуемся тем, что value у тега input с типом даты обязательно должно быть в формате гггг-мм-дд, т.е. ISO формат, а в ISO формат мы можем пере конвертировать дату полученную при помощи функции Date. Время нам не нужно, поэтому отсекаем его, разделив дату по разделителю «Т», и взяв первый элемент массива.