Чтение большого файла csv в 1С

Куда ни глянь, в интернете чаще всего предлагается обработка и чтение большого файла csv в 1С при помощи загрузки в «текстовыйДокумент». Примерно так:

ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.Прочитать(ИмяВременногоФайлаХар);
Для Индекс = 2 По ТекстДок.КоличествоСтрок() Цикл
СтрокаФайла = ТекстДок.ПолучитьСтроку(Индекс);
конеццикла;

Что в корне не верно, при обработке большого csv файла, так как в этом случае весь файл вычитывается предварительно в память. А она не безразмерная в большинстве случаев. Правильный же способ обработки — построчное чтение файла. Примерно так:

		Текст = Новый ЧтениеТекста(ИмяВременногоФайлаХар, КодировкаТекста.ANSI);
		Стр = Текст.ПрочитатьСтроку();
		Пока Стр <> Неопределено Цикл 
		   Сообщить(Стр);
		   Стр = Текст.ПрочитатьСтроку();
			МассивПодстрок = СтрРазделить(Стр, ";");
			инф=Новый Структура("то,лс,ипу,окпу,нс,улица,дом,квартира");
			инф.то		=СокрЛП(МассивПодстрок[2]);
			инф.лс		=СокрЛП(СтрЗаменить(МассивПодстрок[3],"-",""));
			инф.ипу		=СокрЛП(МассивПодстрок[31]);
			инф.окпу	=СокрЛП(МассивПодстрок[92]);
			инф.нс		=СокрЛП(МассивПодстрок[8]);
			инф.улица	=СокрЛП(МассивПодстрок[9]);
			инф.дом		=СокрЛП(МассивПодстрок[10]);
			инф.квартира=СокрЛП(МассивПодстрок[11]);
			ИсходныеДанные.субабоненты.Добавить(инф);			
		   КонецЦикла; 		
	

Работа с безопасным хранилищем в 1С

До недавнего времени (еще несколько лет назад) для хранения данных учётных записей в 1С единственной защитой было — показывать поле с паролем со «звездочками». Сам же пароль хранился в практически открытом виде в реквизитах формы. Ну.. возможно это и не безопасно.. Новая методика хранения чувствительных данных в 1С призвана эту безопасность увеличить. Работа с безопасным хранилищем в 1с, Поэтому в БСП были внедрены функции общего назначения «ПрочитатьДанныеИзБезопасногоХранилища» и «ЗаписатьДанныеВБезопасноеХранилище».

Например запишу данные:

       УстановитьПривилегированныйРежим(Истина);
       ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(ТекущийОбъект.Ссылка, Пароль,"ПарольSMTP");
       УстановитьПривилегированныйРежим(Ложь);

Прочитаю данные:

	 УстановитьПривилегированныйРежим(Истина);
	  уз=справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("Учетка для чтения писем");
      Пароли = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(уз, "Пароль, ПарольSMTP");
	УстановитьПривилегированныйРежим(Ложь);	  		

В чём разница между хранением в реквизитах и новой методикой:

  • Имея доступ к объекту метаданных, пользователь может прочитать содержимое реквизита с паролем, что невозможно при использовании безопасного хранилища. Для исключения случаев несанкционированного доступа к безопасному хранилищу получение и запись данных (паролей) возможна только в привилегированном режиме.
  • Данные в безопасном хранилище хранятся в закрытом виде и тем самым исключаются случаи непредумышленной «засветки» паролей.
  • Безопасное хранилище исключено из планов обмена, что предотвращает утечку паролей из информационной базы при обмене данными.
работа с безопасным хранилищем в 1с

Другие статьи по теме 1С

Выгрузить табличную часть в Excel

Задача: выгрузить табличную часть формы в файл формата XLSX. К сожалению на прямую это не сделать, но зато мы можем воспользоваться функционалом компонента ПостроительОтчета, который в свою очередь понимает на входе таблицу значений. В итоге нам остаётся лишь выгрузить табличную часть в таблицу значений, которую в свою оочередь скормить построителю отчетов. На выходе будет ТабличныйДокумент, который уже штатно может сохраняться в т.ч. и в формат xlsx. Код получается примерно такой::

&НаСервере
Функция ЭкспортВExcelНаСервере()
	ТабДок = Новый ТабличныйДокумент;
	
		Тз = Новый ТаблицаЗначений;
		тз.Колонки.Добавить("Отделение");
		тз.Колонки.Добавить("Подразделение");
		тз.Колонки.Добавить("ЛС");
		тз.Колонки.Добавить("КодСопоставления");
		тз.Колонки.Добавить("ДатаРождения");
		тз.Колонки.Добавить("МестоРождения");
		тз.Колонки.Добавить("СерияПаспорта");
		тз.Колонки.Добавить("НомерПаспорта");
		тз.Колонки.Добавить("СерияНомерПаспорта");
		тз.Колонки.Добавить("РезультатПроверки");
		
		для каждого стр из объект.РезультатСопоставления цикл
			нс=тз.Добавить();		
			нс.Отделение=стр.Отделение;
			нс.Подразделение=стр.Подразделение;
			нс.ЛС=стр.ЛС;
			нс.КодСопоставления=стр.КодСопоставления;
			нс.ДатаРождения=стр.ДатаРождения;
			нс.МестоРождения=стр.МестоРождения;
			нс.СерияПаспорта=стр.СерияПаспортаС;
			нс.НомерПаспорта=стр.НомерПаспортаС;
			нс.СерияНомерПаспорта=стр.СерияНомерПаспорта;
			нс.РезультатПроверки=стр.РезультатПроверки;
		конеццикла;
		
		Построитель = Новый ПостроительОтчета;
		Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Тз);
		Построитель.Выполнить();
		Построитель.Вывести(ТабДок);
		
	ИмяВременногоФайлаХар = ПолучитьИмяВременногоФайла(".xlsx");		
	ТабДок.Записать(ИмяВременногоФайлаХар,ТипФайлаТабличногоДокумента.XLSX);
	сообщить(ИмяВременногоФайлаХар);
	
	Двоичное=Новый ДвоичныеДанные(ИмяВременногоФайлаХар);
	Адрес=ПоместитьВоВременноеХранилище(Двоичное,ЭтаФорма.УникальныйИдентификатор);	
	
	Возврат Адрес;
	
КонецФункции

&НаКлиенте
Процедура ЭкспортВExcel(Команда)
	Адрес=ЭкспортВExcelНаСервере();
	
	Описание=Новый ОписаниеПередаваемогоФайла(ПолучитьИмяВременногоФайла(".xlsx"),Адрес);
	МассивОписаний=Новый Массив;
	МассивОписаний.Добавить(Описание);
	ПолучитьФайлы(МассивОписаний,,,Ложь);	
	
	 Для Каждого фф Из МассивОписаний Цикл
	  ЗапуститьПриложение(фф.Имя);
	 КонецЦикла;	
	
КонецПроцедуры

Пользователь нажимает кнопку «Экспорт в эксель», на сервере формируется файл и передаётся на клиент. На клиенте он открывается приложением по умолчанию для данного формата файла. Код получился кросс платформенный, что в наше время очень актуально.

1С: чтение почты по протоколу IMAP

Прилетела задача прочитать сообщение из почтового ящика по протоколу IMAP. Последнее из пришедших. В принципе в 1С есть штатный функционал для чтения почты, поэтому пример всё сам расскажет за себя:

Процедура ЧитнутьНаСервереImap()
	Профиль = Новый ИнтернетПочтовыйПрофиль;
	Профиль.АутентификацияPOP3 = Ложь;
	Профиль.АутентификацияSMTP = Ложь;
	
	// IMAP
	Профиль.ИспользоватьSSLIMAP = Истина;
	Профиль.АдресСервераIMAP = "цукацу-укацука.уцкацук.ru";
	Профиль.ПортIMAP = "993"; 	
	Профиль.ПользовательIMAP = "укацу@укацукау.ru";
	Профиль.ПарольIMAP = "цукацукацук";
	Профиль.ТолькоЗащищеннаяАутентификацияIMAP=Ложь;

	Почта = Новый ИнтернетПочта;
	Сообщ = Новый СообщениеПользователю();

		Почта.Подключиться(Профиль, ПротоколИнтернетПочты.IMAP); //ПротоколИнтернетПочты.POP3		
		заголовки=Почта.ПолучитьЗаголовки();
		если заголовки.Количество()>0 тогда		
			ПоследнийЗаголовок=Новый Массив();
			ПоследнийЗаголовок.Добавить(заголовки[заголовки.Количество()-1]);					
			МассивСообщений = Новый Массив;
			МассивСообщений = Почта.Выбрать(Ложь,ПоследнийЗаголовок);		
			
			ТекстСообщения=МассивСообщений[0].тексты[0].Текст;
			сообщить(ТекстСообщения);
		конецесли;
	
	Почта.Отключиться(); 

	

КонецПроцедуры

Из особенностей логики — сначала вычитываю заголовки, т.к. если почты много, то чтение писем будет ОЧЕНЬ долгим. Далее получаю последний по счету заголовок, и вычитываю текст конкретно уже этого письма.

прочитать сообщение из почтового ящика по протоколу IMAP

Другие статьи по тегу 1С можете почитать тут

Как добавить рабочие дни к дате

Задача добавление рабочих дней к дате (добавить рабочие дни к дате) встречается довольно часто. И штатно должна решаться с помощью стандартного функционала БСП — «Производственный календарь». Например так:

Функция ДобавитьКДатеРабочиеДни(ДатаНач,ЧислоРабочихДней) экспорт
    Запрос=Новый Запрос;
    Запрос.Текст="ВЫБРАТЬ
                 |    ВЫБОР
                 |        КОГДА РегламентированныйПроизводственныйКалендарь.ВидДня = &РабочийДень
                 |                ИЛИ РегламентированныйПроизводственныйКалендарь.ВидДня = &ПредпраздничныйДень
                 |            ТОГДА 1
                 |        ИНАЧЕ 0
                 |    КОНЕЦ КАК ЧислоРабочихДней,
                 |    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК ДатаКалендаря
                 |ПОМЕСТИТЬ ТЗ
                 |ИЗ
                 |    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
                 |ГДЕ
                 |    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря МЕЖДУ &ДатаНач И &ДатаКон
                 |;
                 |
                 |////////////////////////////////////////////////////////////////////////////////
                 |ВЫБРАТЬ
                 |    ТЗ.ДатаКалендаря,
                 |    СУММА(ТЗ1.ЧислоРабочихДней) КАК ЧислоРабочихДней
                 |ПОМЕСТИТЬ ТЗНакопл
                 |ИЗ
                 |    ТЗ КАК ТЗ
                 |        ЛЕВОЕ СОЕДИНЕНИЕ ТЗ КАК ТЗ1
                 |        ПО (ТЗ1.ДатаКалендаря <= ТЗ.ДатаКалендаря)
                 |
                 |СГРУППИРОВАТЬ ПО
                 |    ТЗ.ДатаКалендаря
                 |;
                 |
                 |////////////////////////////////////////////////////////////////////////////////
                 |ВЫБРАТЬ
                 |    МАКСИМУМ(ТЗ.ДатаКалендаря) КАК ДатаКалендаря
                 |ИЗ
                 |    ТЗНакопл КАК ТЗ
                 |ГДЕ
                 |    ТЗ.ЧислоРабочихДней = &ЧислоРабочихДней";
    Запрос.УстановитьПараметр("ДатаНач",             ДатаНач);
    ЧислоНедель = Цел(ЧислоРабочихДней/5+0.5);
    ЧислоВыходныхДней = ЧислоНедель*2;
    МаксимальноеКоличествоПраздничныхДнейПодряд = 8; //РождественскиеКаникулы
    ДатаКон = ДатаНач+(ЧислоВыходныхДней+ЧислоРабочихДней+МаксимальноеКоличествоПраздничныхДнейПодряд)*24*60*60;
    Запрос.УстановитьПараметр("ДатаКон",ДатаКон);
    Запрос.УстановитьПараметр("ЧислоРабочихДней",ЧислоРабочихДней);
    Запрос.УстановитьПараметр("РабочийДень",         Перечисления.ВидыДнейПроизводственногоКалендаря.Рабочий);
    Запрос.УстановитьПараметр("ПредпраздничныйДень", Перечисления.ВидыДнейПроизводственногоКалендаря.Предпраздничный);
    Выборка = Запрос.Выполнить().Выбрать();
    Результат = 0;
    Если Выборка.Следующий() Тогда
        Результат = КонецДня(Выборка.ДатаКалендаря)+1; 
    Конецесли;    
    Возврат Результат;
КонецФункции  

Однако не всё же не все конфигурации содержат производственный календарь. Например почему-то обделено Делопроизводство 2.0. Что-бы не городить огород,, решил задачу «в лоб», без учёта праздничных дней — просто проверяю выпадение даты на субботу-воскресенье. В моём случае этого хватило.

Функция ДобавитьКДатеРабочиеДни(ДатаПроверки,дней)
    добавлено=0;
	пока добавлено<>дней цикл
	  ДатаПроверки=ДатаПроверки+86400;	         
	  Если ДеньНедели(ДатаПроверки) <> 6 ИЛИ ДеньНедели(ДатаПроверки) <> 7 Тогда
		  добавлено=добавлено+1;
	  конецесли;	  
     конеццикла;	
  	Возврат ДатаПроверки;
КонецФункции
добавить рабочие дни к дате

Другие статьи по теме 1С, можно почитать тут

1 8 9 10 11 12 52