diff --git a/README.md b/README.md index 7ef04b3f..068bd779 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Release](https://img.shields.io/github/v/release/firstBitSportivnaya/PSSL?include_prereleases&label=last%20release&style=badge)](https://github.com/firstBitSportivnaya/PSSL/releases/latest) [![GitHub issues](https://img.shields.io/github/issues-raw/firstBitSportivnaya/PSSL?style=badge)](https://github.com/firstBitSportivnaya/PSSL/issues) [![License](https://img.shields.io/github/license/firstBitSportivnaya/PSSL?style=badge)](https://github.com/firstBitSportivnaya/PSSL/blob/develop/LICENSE) -[![OpenYellow](https://img.shields.io/endpoint?url=https://openyellow.neocities.org/badges/4/751858948.json)](https://openyellow.notion.site/openyellow/24727888daa641af95514b46bee4d6f2?p=aec5d010e2aa4fcf9ec351e0b013705e&pm=s) +[![OpenYellow](https://img.shields.io/endpoint?url=https://openyellow.org/data/badges/4/751858948.json)](https://openyellow.org/grid?data=top&repo=751858948) ![image](https://repository-images.githubusercontent.com/751858948/a45ea547-c23c-4ce1-b30e-609d9ac8d558) @@ -31,7 +31,6 @@ 2. [Динамическое Формирование Интерфейса](https://github.com/KotovDima1C/DFI) 3. [Консоль кода](https://github.com/salexdv/bsl_console) 4. [Просмотр файлов JSON с разметкой](https://github.com/plastinin/AllYouNeedIsLove) -5. [Универсальная загрузка XLS с приведением типов](https://github.com/Bayselonarrend/uniloadXLS) ## Информация для контрибьюторов diff --git "a/docs/\320\227\320\260\320\263\321\200\321\203\320\267\320\272\320\260\320\244\320\260\320\271\320\273\320\260\320\247\320\265\321\200\320\265\320\267\320\242\320\260\320\261\320\273\320\270\321\207\320\275\321\213\320\271\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202.md" "b/docs/\320\227\320\260\320\263\321\200\321\203\320\267\320\272\320\260\320\244\320\260\320\271\320\273\320\260\320\247\320\265\321\200\320\265\320\267\320\242\320\260\320\261\320\273\320\270\321\207\320\275\321\213\320\271\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202.md" index 42822d09..d1c2e066 100644 --- "a/docs/\320\227\320\260\320\263\321\200\321\203\320\267\320\272\320\260\320\244\320\260\320\271\320\273\320\260\320\247\320\265\321\200\320\265\320\267\320\242\320\260\320\261\320\273\320\270\321\207\320\275\321\213\320\271\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202.md" +++ "b/docs/\320\227\320\260\320\263\321\200\321\203\320\267\320\272\320\260\320\244\320\260\320\271\320\273\320\260\320\247\320\265\321\200\320\265\320\267\320\242\320\260\320\261\320\273\320\270\321\207\320\275\321\213\320\271\320\224\320\276\320\272\321\203\320\274\320\265\320\275\321\202.md" @@ -1,29 +1,515 @@ # Подсистема загрузки файлов Excel через табличный документ -Пример вызова на форме +Предназначена для универсальной загрузки Excel-файлов (csv-файлов) через табличный документ. +Преобразование происходит в два этапа: +* Чтение файла и сопоставление его колонок с "макетом" - таблицей значений, где описаны свойства колонок и порядок конвертации; +* Конвертация строковых значений в соответствии с "макетом": поиск ссылок для ссылочных объектов, конвертация базовых типов данных (Число, Дата, Булево). -```BSL +Результатом конвертации будет являтся таблица значений, сформированная по описанным в "макете" правилам. + +## Описание свойств колонок файла ("макета") + +Для того, чтобы сопоставить колонки файла со значениями 1С и конвертировать строковые значения, прочитанные из файла, необходимо заполнить "правила конвертации". +Существует два варианта сопоставления колонок: по порядку и по наименованию колонок. +Если установлен вариант "по порядку", тогда сопоставление колонок происходит в строгой последовательности макета. Например, если свойства инициализированы следующих образом +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Номенклатура"; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Артикул"; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Наименование"; +``` +то первая колонка файла всегда будет распознана как номенклатура, не смотря на то, что там может быть значение другого типа (например, контрагент). + +Если установлен вариант "по наименованию", то строка файла с номером начальной строки чтения будет идентифицирована как шапка таблицы. Колонки шапки таблицы будут проанализированы и сопоставлены по наименованию с таблицей свойств. Имя колонки файла должно быть равно либо свойству "ИмяВТабДоке", либо свойству "ИмяКолонки". В противном случае, колонка будет не идентифицирована. Все неидентифицированные колонки файла будут удалены из табличного документа, их значения не загрузятся из файла и не будут доступны для последующей обработки. + +Чтобы инициализировать таблицу свойств необходимо вызвать функцию в зависимости от контекста выполнения кода: + +##### С клиента: + +```bsl +ТаблицаСвойств = пбп_ЗагрузкаФайлаЧерезТабличныйДокументВызовСервера.ИнициализироватьТаблицуСоСвойствамиКолонок() +``` + +##### С сервера: + +```bsl +ТаблицаСвойств = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ИнициализироватьТаблицуСоСвойствамиКолонок() +``` + +Таблица свойств содержит следующие колонки строкового типа: +1) **ИмяКолонки** - имя колонки в итоговой таблице значений для последующего обращения к ней; +2) **ИмяВТабДоке** - имя колонки в файле. Свойство учитывается при сопоставлении колонок по наименованию. Если не заполнено, то имя колонки считается равным значению из "ИмяКолонки", например: +```bsl +// Здесь ИмяВТабДоке не указано, поэтому колонка будет искаться по значению "ЕдиницаХранения" +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "ЕдиницаХранения"; +``` +```bsl +// Здесь ИмяВТабДоке указано, поэтому колонка будет искаться по значению "Единица хранения" +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "ЕдиницаХранения"; +НоваяСтрока.ИмяВТабДоке = "Единица хранения"; +``` +3) **Группа** - имя колонки "группы" ячеек. Под группой подразумевается объединение ячеек строкой выше в шапке таблицы. Например, в примере ниже группой колонок будет являтся "Номенклатура": + + + + + + + + + + + + + + + + +
Номенклатура
НаименованиеАртикулЕдиница хранения
Ложка0000001шт
+ +Тогда инициализация группы в свойствах колонок будет выглядеть следующим образом: +```bsl +ГруппаЯчеек = "Номенклатура"; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Наименование"; +НоваяСтрока.Группа = ГруппаЯчеек; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Артикул"; +НоваяСтрока.Группа = ГруппаЯчеек; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "ЕдиницаХранения"; +НоваяСтрока.ИмяВТабДоке = "Единица хранения"; +НоваяСтрока.Группа = ГруппаЯчеек; +``` +4) **ТипЗначения** - тип значения, в который будет конвертировано значение колонки. Может принимать значения базовых типов: Число, Булево, Дата,- так и ссылочные типы: +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Наименование"; +НоваяСтрока.ТипЗначения = "Строка"; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "ЕдиницаХранения"; +НоваяСтрока.ТипЗначения = "СправочникСсылка.УпаковкиЕдиницыИзмерения"; +НоваяСтрока.ПолеПоиска1 = "Наименование"; +``` +Для конвертации значений "булево" необходимо указывать строковое представление ИСТИНА (по умолчанию, если представление не указано, проверка на "да" и "истина"), для конвертации даты в параметрах чтения файла ключ КонвертироватьДаты должен быть Истина (подробно см. в главе [Параметры чтения файла](#параметры-чтения-файла)). Для конвертации ссылочных типов необходимо заполнить поля поиска. В указанном выше примере единица хранения будет искаться по полю "наименование". +5) **ПолеПоиска1**, **ПолеПоиска2**, **ПолеПоиска3** - название реквизита объекта, по которому будет произведен поиск значения ссылочного типа. +6) **ОператорУсловия** - оператор сравнения в условии соединения таблицы с типом значения между полями поиска. По умолчанию "ИЛИ", также может равняться "И" или "ВИРТ". Например, если в колонке файла "Контрагент" может быть указан либо ИНН, либо ОКПО, либо наименование, и, соответственно, поиск должен производится по этим полям объекта с указанным приоритетом (высший ИНН, низший - наименование), то указываем свойства в следующем порядке: +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Контрагент"; +НоваяСтрока.ТипЗначения = "СправочникСсылка.Контрагенты"; +НоваяСтрока.ПолеПоиска1 = "ИНН"; +НоваяСтрока.ПолеПоиска2 = "КодПоОКПО"; +НоваяСтрока.ПолеПоиска3 = "Наименование"; +``` +На выходе в итоговом запросе конвертации значений ссылочных типов получится следующее соединение: +```bsl +ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты1 + ПО ВходнаяТаблица.Контрагент <> "" И ВходнаяТаблица.Контрагент <> 0 + И (ВходнаяТаблица.Контрагент = Контрагенты1.ИНН + ИЛИ ВходнаяТаблица.Контрагент = Контрагенты1.КодПоОКПО + ИЛИ ВходнаяТаблица.Контрагент = Контрагенты1.Наименование) +``` +При использовании оператора "И" имена полей поиска должны равняться именам колонок обрабатываемой таблицы. Например: если в свойствах макета у колонки заполнен тип ДокументСсылка., ПолеПоиска1 = "Номер", а ПолеПоиска2 = "Дата" И ОператорУсловия = "И", тогда таблица построителя должна иметь колонки "Номер", где лежит номер документа и "Дата", где лежит дата документа: + + + + + + + + + + + + + + + + + +
НомерДатаКонтрагент...
00000000101.01.2023ООО "Ромашка"...
+ +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Реализация"; +НоваяСтрока.ТипЗначения = "ДокументСсылка.РеализацияТоваровУслуг"; +НоваяСтрока.ПолеПоиска1 = "Номер"; +НоваяСтрока.ПолеПоиска2 = "Дата"; +НоваяСтрока.ОператорУсловия = "И"; +``` +Оператор "ВИРТ" предназначен для инициализации "виртуальных" полей ссылочных типов (которые не входят в логику оператора "И"), т.е. которых нет в исходном файле. Например, если колонки "Номенклатура" в файле нет, но есть одно из полей поиска номенклатуры, допустим "Артикул", то используя оператор "ВИРТ" в итоговой таблице мы получим ссылку на номенклатуру, полученную поиском по артикулу: +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Номенклатура"; +НоваяСтрока.ТипЗначения = "СправочникСсылка.Номенклатура"; +НоваяСтрока.ПолеПоиска1 = "Артикул"; +НоваяСтрока.ОператорУсловия = "ВИРТ"; +``` +В этом примере номенклатуру также можно найти с помощью оператора "ИЛИ" напрямую по артикулу +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Артикул"; +НоваяСтрока.ТипЗначения = "СправочникСсылка.Номенклатура"; +НоваяСтрока.ПолеПоиска1 = "Артикул"; +``` +но в этом случае имя колонки "Артикул" будет зарезервировано ссылкой на номенклатуру. Если нужно загрузить оба поля: и номенклатуру, и артикул,- то нужно объявить оба поля, одно из которых будет виртуальным, а другое загружаться из файла как строковое значение: +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Номенклатура"; +НоваяСтрока.ТипЗначения = "СправочникСсылка.Номенклатура"; +НоваяСтрока.ПолеПоиска1 = "Артикул"; +НоваяСтрока.ОператорУсловия = "ВИРТ"; + +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Артикул"; +НоваяСтрока.ТипЗначения = "Строка"; +``` +7) **ФункцияПреобразования** - имя экспортной функции в программном интерфейсе, которая будет вызвана для конвертации значения. Допустим, нам необходимо убрать лидирующие нули в колонке. Тогда в серверном общем модуле ("ТестЗагрузкиФайлаИзТабличногоДокумента") создаем экспортную функцию УбратьЛидирующиеНули с параметром "ВходящееЗначение" (в него придет строковое значение ячейки файла): +```bsl +Функция УбратьЛидирующиеНули(ВходящееЗначение) Экспорт + Возврат СтроковыеФункцииКлиентСервер.УдалитьПовторяющиесяСимволы(ВходящееЗначение, "0"); +КонецФункции +``` +А в свойствах колонки прописываем отношение колонки к этой функции: +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "Наименование"; +НоваяСтрока.ТипЗначения = "Строка"; +НоваяСтрока.ФункцияПреобразования = "ТестЗагрузкиФайлаИзТабличногоДокумента.УбратьЛидирующиеНули"; +``` +8) **ФорматДаты** - формат даты строкой. Если указан, то строковое значение будет конвертироваться в дату по указаному формату. Сам формат представляет собой строку с номерами разрядов через разделитель "_" (например, "1_1_2"). Первый разряд показывает какой разделитель используется в представлении даты, второй разряд показывает положение дня, месяца и года по отношению друг к другу, третий разряд показывает представление времени в дате. Если номер формата "0_0_0" - преобразование происходит из функции XMLЗначение (ISO формат даты вида "2023-12-31T18:30:51"). +* Первый разряд принимает значения: + - 1 - разделитель "."; + - 2 - "/"; + - 3 - "-"; + - 4 - " "; +* Второй разряд принимает значения: + - 0 - месяц, день, год + - 1 - год идет первым, потом месяц и день; + - 2 - сначала день, потом месяц и год; + - 3 - сначала день, месяц СТРОКОЙ и год; +* Третий разряд принимает значения: + - 0 - время отсутствует; + - 1 - время стандартное, 24-часовое представление + - 2 - время в 12-ти часовом представлении (AM / PM) + +Примеры номеров форматов: + - 1_1_2 - "2021.12.01 8:10 PM"; + - 2_1_0 - "2021/12/01"; + - 1_3_1 - "01.дек.2021 20:10"; + - 3_1_1 - "2021-12-01 20:10" + +Если формат даты колонки не указан в свойствах, а тип колонки "Дата", то ее формат будет определен по первому значению колонки в процессе конвертации строковых значений по типам, но только в том случае, если в параметрах чтения файла ключ КонвертироватьДаты равен Истина. Исключением из данного правила являются даты, где месяц указывается первым (например, 12/31/3999). В этом случае ФорматДаты колонки должен быть заполнен явным образом. В этом примере номер формата даты будет равен "2_0_0": +```bsl +НоваяСтрока = ТаблицаСвойств.Добавить(); +НоваяСтрока.ИмяКолонки = "ДатаДокумента"; +НоваяСтрока.ТипЗначения = "Дата"; +НоваяСтрока.ФорматДаты = "2_0_0"; // значение вида "12/31/3999" +``` + +## Параметры чтения файла + +Параметры влияют на чтение данных из файла и их конвертацию. Для того чтобы указать параметры чтения файла необходимо вызвать функцию ПолучитьПараметрыЧтенияФайла(): +```bsl +ПараметрыЧтения = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ПолучитьПараметрыЧтенияФайла(); +``` +При вызове функции клиентской загрузки из XLS (общий модуль "пбп_ЗагрузкаФайлаЧерезТабличныйДокументКлиент") параметры чтения передаются параметрами функции (пример см. в главе [Пример вызова с клиента](#пример-вызова-с-клиента)). + +Структура параметров имеют следующие ключи: +1) **НазваниеЛиста** - Строка - название листа в исходном файле; +2) **НомерСтроки** - Число - начальный номер строки, с которой начинается чтение файла. Обычно, это шапка таблицы. Строки до нее обрезаются; +3) **СопоставлениеПоНаименованию** - Булево - если Истина, то колонки будут сравниваться по наименованию; если Ложь, то по порядку, указанном в таблице свойств колонок (подробно см. в начале главы [Описание свойств колонок файла](#описание-свойств-колонок-файла-макета)). По умолчанию Ложь; +4) **КонвертироватьДаты** - Булево - если Истина, то колонки с типом Дата будут конвертироваться автоматически из строкового значения в дату, по умолчанию Истина; +5) **ВыдаватьОшибкуПриОтсутствииЛиста** - Булево - если Истина, то при отсутствии листа с наименованием, указанном в ключе "НазваниыеЛиста", в файле обработка файла будет прервана с ошибкой. По умолчанию Ложь; +6) **ЗначениеИстина** - Строка - строковое представление значения ИСТИНА для колонок с типом булево (например, "Y" или "Да"). Если не заполнено, то проверяется на равенство строке "истина" или "да"; +7) **ОставитьСтроковыеЗначения** - если Истина, то оставляет колонки с исходными строковыми значениями конвертируемых типов (Булево, Число, Дата) с постфиксом "Строкой". В противном случае удаляет их после конвертации. По умолчанию Ложь; +8) **ИскатьПомеченныеНаУдаление** - если Истина, то при поиске ссылок на объекты игнорирует пометку на удаление. В противном случае, помеченные на удаление не будут учитываться. По умолчанию Истина. + +## Примеры вызова загрузки файла + +После изучения правил заполенения таблицы свойств колонок и параметров чтения можно рассмотреть вызовы загрузки файла на примерах. Дан следующий Excel-файл с данными реализаций товаров и услуг: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
НомерДатаНоменклатура (Артикул)ЦенаКоличествоСумма
00000000101.01.2023 10:30:131231002200
00000000101.01.2023 10:30:137893001300
00000000201.01.2023 15:14:014562004800
00000000302.01.2023 09:46:10123100151500
+ +#### Пример вызова с клиента + +```bsl &НаКлиенте Асинх Процедура ЗагрузитьXLS(Команда) - СтруктураКолонок = Новый Структура; - СтруктураКолонок.Вставить("Спр2" , "СправочникСсылка.Спр2"); - СтруктураКолонок.Вставить("Перечисление1" , "ПеречислениеСсылка.Перечисление1"); - СтруктураКолонок.Вставить("ЛюбоеИмя" , ""); - СтруктураКолонок.Вставить("Док1" , "ДокументСсылка.Док1"); - СтруктураКолонок.Вставить("Спр1" , "СправочникСсылка.Спр1"); + // Заполняем таблицу свойств колонок. Так как свойства лежат в таблице значений, на клиент возвращаем адрес временного хранилища с ТЗ + АдресХранилища = ПолучитьСтруктуруЗагружаемогоОбъекта(); + + ИмяСтраницы = "Лист1"; + НомерПервойСтроки = 2; - ИД = Ждать пбп_ЗагрузкаФайлаЧерезТабличныйДокументКлиент.ЗагрузитьИзXLS(СтруктураКолонок, , 2); + // Заполняем параметры чтения + ПараметрыЧтения = пбп_ЗагрузкаФайлаЧерезТабличныйДокументКлиент.ПолучитьПараметрыЧтенияФайла(); + ПараметрыЧтения.НазваниеЛиста = ИмяСтраницы; + ПараметрыЧтения.НомерСтроки = НомерПервойСтроки; + ПараметрыЧтения.СопоставлениеПоНаименованию = Истина; + ПараметрыЧтения.ЗначениеИстина = "Y"; - Если ЗначениеЗаполнено(ИД) Тогда + // Переменная ИД равняется адресу итоговой таблицы во временном хранилище + ИД = Ждать пбп_ЗагрузкаФайлаЧерезТабличныйДокументКлиент.ЗагрузитьИзXLS(АдресХранилища, ПараметрыЧтения); + + Если ЗначениеЗаполнено(ИД) Тогда ЗагрузкаНаСервере(ИД); КонецЕсли; КонецПроцедуры +&НаСервере +Функция ПолучитьСтруктуруЗагружаемогоОбъекта() + + СтруктураКолонок = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ИнициализироватьТаблицуСоСвойствамиКолонок(); + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Реализация"; + НоваяСтрока.ТипЗначения = "ДокументСсылка.РеализацияТоваровУслуг"; + НоваяСтрока.ПолеПоиска1 = "Номер"; + НоваяСтрока.ПолеПоиска2 = "Дата"; + НоваяСтрока.ОператорУсловия = "И"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Номер"; + НоваяСтрока.ТипЗначения = "Строка"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Дата"; + НоваяСтрока.ТипЗначения = "Дата"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Номенклатура"; + НоваяСтрока.ИмяВТабДоке = "Номенклатура (Артикул)"; + НоваяСтрока.ТипЗначения = "СправочникСсылка.РеализацияТоваровУслуг"; + НоваяСтрока.ПолеПоиска1 = "Артикул"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Цена"; + НоваяСтрока.ТипЗначения = "Число"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Количество"; + НоваяСтрока.ТипЗначения = "Число"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Сумма"; + НоваяСтрока.ТипЗначения = "Число"; + + АдресХранилища = ПоместитьВоВременноеХранилище(СтруктураКолонок, Новый УникальныйИдентификатор); + + Возврат АдресХранилища; + +КонецПроцедуры + &НаСервере Процедура ЗагрузкаНаСервере(ИД) ТЗ = ПолучитьИзВременногоХранилища(ИД); + + // Пост-обработка полученных данных + // ... +КонецПроцедуры +``` + +#### Пример вызова с сервера + +```bsl +Процедура ЗагрузитьXSL(ДвоичныеДанныеФайла, Расширение) + + СтруктураКолонок = ПолучитьСтруктуруЗагружаемогоОбъекта(); + + // Инициализируем параметры чтения для дальнейшей передачи + // Для серверного контекста вызывается функция из серверного модуля + ПараметрыЧтения = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ПолучитьПараметрыЧтенияФайла(); + ПараметрыЧтения.НазваниеЛиста = "Лист1"; + ПараметрыЧтения.НомерСтроки = 2; + ПараметрыЧтения.СопоставлениеПоНаименованию = Истина; + ПараметрыЧтения.КонвертироватьДаты = Истина; + ПараметрыЧтения.ВыдаватьОшибкуПриОтсутствииЛиста = Ложь; + ПараметрыЧтения.ЗначениеИстина = "Y"; + ПараметрыЧтения.ОставитьСтроковыеЗначения = Ложь; + ПараметрыЧтения.ИскатьПомеченныеНаУдаление = Ложь; + + // Помещаем файл в хранилище на сервере + АдресВХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, Новый УникальныйИдентификатор); + ТаблицаДанных = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер + .КонвертироватьДанныеТабличногоДокументаВТаблицуЗначений( + АдресВХранилище, Расширение, ТаблицаСвойств, ПараметрыЧтения); + + // Для не найденных значений в итоговой таблице будут Null. Уберем их + пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ТаблицаЗначенийБезNull(ТаблицаДанных); + + // Пост-обработка полученных данных + // ... + +КонецПроцедуры + +Функция ПолучитьСтруктуруЗагружаемогоОбъекта() + + СтруктураКолонок = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ИнициализироватьТаблицуСоСвойствамиКолонок(); + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Реализация"; + НоваяСтрока.ТипЗначения = "ДокументСсылка.РеализацияТоваровУслуг"; + НоваяСтрока.ПолеПоиска1 = "Номер"; + НоваяСтрока.ПолеПоиска2 = "Дата"; + НоваяСтрока.ОператорУсловия = "И"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Номер"; + НоваяСтрока.ТипЗначения = "Строка"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Дата"; + НоваяСтрока.ТипЗначения = "Дата"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Номенклатура"; + НоваяСтрока.ИмяВТабДоке = "Номенклатура (Артикул)"; + НоваяСтрока.ТипЗначения = "СправочникСсылка.РеализацияТоваровУслуг"; + НоваяСтрока.ПолеПоиска1 = "Артикул"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Цена"; + НоваяСтрока.ТипЗначения = "Число"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Количество"; + НоваяСтрока.ТипЗначения = "Число"; + + НоваяСтрока = СтруктураКолонок.Добавить(); + НоваяСтрока.ИмяКолонки = "Сумма"; + НоваяСтрока.ТипЗначения = "Число"; + + Возврат СтруктураКолонок; + КонецПроцедуры +``` + +### Чтение CSV-файла + +Порядок вызова функций для чтения CSV-файлов будет немного отличаться от аналогичного чтения Excel-файлов. Подсистема распознает два вида заполнения файлов: где есть разделители, и где разделители условны, а значения колонок находятся на определенных позициях строки, например: + + +123 Номенклатура №1 шт + +456 Номенклатура №2 исшт + + +Во второй строке видно, что разделитель между наименованием номенклатуры и наименованием единицы измерения ("шт") отсутствует, но, очевидно, это разные колонки. + +Для файлов, где есть разделители, параметры чтения от Excel отличаться не будут, за исключением того, что чтение csv-файлов происходит в строгом порядке, указанном в таблице свойств колонок. +Для файлов, где значения колонок стоят на определенных позициях строки, для каждой колонки необходимо заполнить начальный символ в строке файла и длину значения. Для этого свойства таблицы необходимо инициализоровать не посредством вызова функции "ИнициализироватьТаблицуСоСвойствамиКолонок", а посредством вызова "ИнициализироватьТаблицуСоСвойствамиCSV". Для выше указанного файла заполнение будет выглядеть следующим образом: +```bsl +СтруктураКолонок = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ИнициализироватьТаблицуСоСвойствамиCSV(); +НоваяСтрока = СтруктураКолонок.Добавить(); +НоваяСтрока.ИмяКолонки = "Артикул"; +НоваяСтрока.ТипЗначения = "Строка"; +НоваяСтрока.Начало = 0; +НоваяСтрока.Длина = 3; + +НоваяСтрока = СтруктураКолонок.Добавить(); +НоваяСтрока.ИмяКолонки = "Наименование"; +НоваяСтрока.ТипЗначения = "Строка"; +НоваяСтрока.Начало = 7; +НоваяСтрока.Длина = 18; + +НоваяСтрока = СтруктураКолонок.Добавить(); +НоваяСтрока.ИмяКолонки = "ЕдиницаХранения"; +НоваяСтрока.ТипЗначения = "Строка"; +НоваяСтрока.Начало = 25; +НоваяСтрока.Длина = 2; ``` + +#### Пример чтения CSV-файла + +```bsl +Процедура ЗагрузитьCSV(ДвоичныеДанныеФайла, Расширение) + + // Либо аналогична примерам с Excel, либо свойства с началом и длиной + СтруктураКолонок = ПолучитьСтруктуруЗагружаемогоОбъекта(); + + // Помещаем файл во временное хранилище на сервере + ПутьКФайлу = ПолучитьИмяВременногоФайла(Расширение); + ДвоичныеДанныеФайла.Записать(ПутьКФайлу); + + // Если загрузка файла с разделителями, то 4-ым параметром указывается разделитель, например ";" + // В противном случае не указывается + // 3-им параметром указывается кодировка файла. По умолчанию "UTF8" + СыраяТаблица = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер + .ПолучитьПромежуточнуюТаблицуИзCSVФайла(ПутьКФайлу, СтруктураКолонок); + + // Вызываем функцию конвертации строковых значений и передаем таблицу, полученную после чтения CSV-файла + ТаблицаРезультат = пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер + .ПреобразоватьСтроковыеЗначенияПоТипамСвойств(СыраяТаблица, СтруктураКолонок, Истина, "Y", , Ложь); + + // Для не найденных значений в итоговой таблице будут Null. Уберем их + пбп_ЗагрузкаФайлаЧерезТабличныйДокументСервер.ТаблицаЗначенийБезNull(ТаблицаДанных); + + // Пост-обработка полученных данных + // ... + +КонецПроцедуры +``` + +#### Благодарность + +Отдельная благодарность за идею реализации репозиторию [Универсальная загрузка XLS с приведением типов](https://github.com/Bayselonarrend/uniloadXLS) \ No newline at end of file