Загрузка данных


// Форма «Загрузка артикулов» внешнего отчета «Остатки товаров по артикулам».
//
// Открывается из основной формы отчета, возвращает владельцу Массив из Строка —
// введенные артикулы. При отказе возвращает Неопределено.
//
// Артикулы вводятся в поле табличного документа, а не в таблицу формы: только так
// работает вставка колонки из буфера обмена (Ctrl+V) — таблица управляемой формы
// многострочную вставку не принимает. Строка 1 — шапка «Артикулы», данные с 2-й.
// Так же устроены типовые формы загрузки из внешних файлов, например
// ОбщаяФорма.ЗагрузкаИдентификаторовИзВнешнихФайлов.

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	ИнициализироватьТабличныйДокумент();

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

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура Готово(Команда)

	СписокАртикулов = ВведенныеАртикулы();

	Если СписокАртикулов.Количество() = 0 Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Не введено ни одного артикула.'"));
		Возврат;
	КонецЕсли;

	Закрыть(СписокАртикулов);

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

&НаКлиенте
Процедура ЗакрытьФорму(Команда)

	Закрыть(Неопределено);

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

&НаКлиенте
Процедура ОчиститьСписок(Команда)

	ИнициализироватьТабличныйДокумент();

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

&НаКлиенте
Процедура ЗаполнитьИзФайла(Команда)

	Оповещение = Новый ОписаниеОповещения("ЗаполнитьИзФайлаЗавершение", ЭтотОбъект);

	ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
	ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;
	ПараметрыЗагрузки.Диалог.Заголовок = НСтр("ru = 'Выберите файл с артикулами'");
	ПараметрыЗагрузки.Диалог.Фильтр = НСтр(
		"ru = 'Все поддерживаемые форматы (*.xlsx;*.xls;*.ods;*.mxl;*.csv;*.txt)|*.xlsx;*.xls;*.ods;*.mxl;*.csv;*.txt'");

	ФайловаяСистемаКлиент.ЗагрузитьФайл(Оповещение, ПараметрыЗагрузки);

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

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Обработчик выбора файла: дописывает артикулы из первой колонки файла в таблицу.
//
// Параметры:
//   ПомещенныйФайл - Структура - см. ФайловаяСистемаКлиент.ЗагрузитьФайл
//                  - Неопределено - пользователь отказался от выбора.
//   ДополнительныеПараметры - Произвольный - не используется.
//
&НаКлиенте
Процедура ЗаполнитьИзФайлаЗавершение(ПомещенныйФайл, ДополнительныеПараметры) Экспорт

	Если ПомещенныйФайл = Неопределено Тогда
		Возврат;
	КонецЕсли;

	Добавлено = ДобавитьАртикулыИзФайла(ПомещенныйФайл.Хранение, ПомещенныйФайл.Имя);

	Если Добавлено = 0 Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'В первой колонке файла нет ни одного значения.'"));
	КонецЕсли;

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

// Готовит пустой бланк: шапка «Артикулы» в первой строке, ниже — место для ввода.
//
&НаСервере
Процедура ИнициализироватьТабличныйДокумент()

	ТаблицаАртикулов.Очистить();

	Линия = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная);

	Шапка = ТаблицаАртикулов.Область("R1C1");
	Шапка.Текст = НСтр("ru = 'Артикулы'");
	Шапка.Шрифт = Новый Шрифт(, , Истина);
	Шапка.ЦветФона = Новый Цвет(240, 240, 240);
	Шапка.Обвести(Линия, Линия, Линия, Линия);
	Шапка.ШиринаКолонки = 40;

	ТаблицаАртикулов.ФиксацияСверху = 1;

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

// Считывает непустые значения первой колонки, начиная со строки под шапкой.
//
// Возвращаемое значение:
//   Массив из Строка
//
&НаСервере
Функция ВведенныеАртикулы()

	Артикулы = Новый Массив;

	Для НомерСтроки = 2 По ТаблицаАртикулов.ВысотаТаблицы Цикл

		Артикул = СокрЛП(ТаблицаАртикулов.Область("R" + НомерСтроки + "C1").Текст);

		Если Не ПустаяСтрока(Артикул) Тогда
			Артикулы.Добавить(Артикул);
		КонецЕсли;

	КонецЦикла;

	Возврат Артикулы;

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

// Дописывает в таблицу артикулы из файла.
//
// Параметры:
//   АдресФайла - Строка - адрес двоичных данных файла во временном хранилище.
//   ИмяФайла   - Строка - имя файла с расширением.
//
// Возвращаемое значение:
//   Число - сколько значений добавлено.
//
&НаСервере
Функция ДобавитьАртикулыИзФайла(АдресФайла, ИмяФайла)

	ИзФайла = АртикулыИзФайла(АдресФайла, ИмяФайла);

	НомерСтроки = Макс(ТаблицаАртикулов.ВысотаТаблицы, 1);

	Для Каждого Артикул Из ИзФайла Цикл
		НомерСтроки = НомерСтроки + 1;
		ТаблицаАртикулов.Область("R" + НомерСтроки + "C1").Текст = Артикул;
	КонецЦикла;

	Возврат ИзФайла.Количество();

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

// Разбирает файл и возвращает артикулы из первой колонки.
//
// Файл читается потоком из временного хранилища, без временных файлов на диске:
// дополнительные отчеты исполняются в безопасном режиме, где доступ к файловой
// системе закрыт.
//
// Параметры:
//   АдресФайла - Строка - адрес двоичных данных файла во временном хранилище.
//   ИмяФайла   - Строка - имя файла с расширением, по нему выбирается способ чтения.
//
// Возвращаемое значение:
//   Массив из Строка - непустые значения первой колонки, по одному на строку файла.
//
&НаСервереБезКонтекста
Функция АртикулыИзФайла(АдресФайла, ИмяФайла)

	Артикулы = Новый Массив;

	Точка = СтрНайти(ИмяФайла, ".", НаправлениеПоиска.СКонца);
	Расширение = ?(Точка = 0, "", НРег(Сред(ИмяФайла, Точка + 1)));

	ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайла);

	Если Расширение = "txt" Тогда

		Чтение = Новый ЧтениеТекста(ДвоичныеДанные.ОткрытьПотокДляЧтения(), КодировкаТекста.UTF8);
		СтрокаФайла = Чтение.ПрочитатьСтроку();
		Пока СтрокаФайла <> Неопределено Цикл
			ДобавитьАртикул(Артикулы, СтрокаФайла);
			СтрокаФайла = Чтение.ПрочитатьСтроку();
		КонецЦикла;
		Чтение.Закрыть();

	Иначе

		ТабличныйДокумент = Новый ТабличныйДокумент;
		ТабличныйДокумент.Прочитать(ДвоичныеДанные.ОткрытьПотокДляЧтения(),
			СпособЧтенияЗначенийТабличногоДокумента.Значение);

		Для НомерСтроки = 1 По ТабличныйДокумент.ВысотаТаблицы Цикл
			ДобавитьАртикул(Артикулы, ТабличныйДокумент.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
		КонецЦикла;

	КонецЕсли;

	Возврат Артикулы;

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

// Добавляет в массив очищенное значение артикула, если оно непустое.
//
// Параметры:
//   Артикулы - Массив из Строка - приемник.
//   Значение - Произвольный - исходное значение ячейки или строки файла.
//
&НаСервереБезКонтекста
Процедура ДобавитьАртикул(Артикулы, Значение)

	Артикул = СокрЛП(Строка(Значение));
	Если Не ПустаяСтрока(Артикул) Тогда
		Артикулы.Добавить(Артикул);
	КонецЕсли;

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

#КонецОбласти