0. StepByStep 3257 01.11.13 10:08 Сейчас в теме

Загрузка из EXCEL в 1С. Чтение файла XLSX средствами 1С. ЧтениеXML

ПРАКТИЧЕСКОЕ ПОСОБИЕ РАЗРАБОТЧИКА: Метод "NativeXLSX" (ЧтениеXML).
Обрабатываются данные EXCEL типов: "Строка", "Число", "Дата" ("Время"), "Булево", "Процент".

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
1. Evgen.Ponomarenko 542 01.11.13 18:50 Сейчас в теме
Мега зачетно! В копилку готовых решений на пожизненно! )))
StepByStep; +1 Ответить
2. peterxx 19 01.11.13 20:59 Сейчас в теме
Очень неплохо, а то внешние компоненты - кот в мешке, ADO - бывает лень возиться и т.п.
StepByStep; +1 Ответить
4. TheGrr 139 03.11.13 12:23 Сейчас в теме
(3) Eugeneer, а вы в каждой публикации, касающейся загрузки из Excel, будете обсирать автора? :) Уже ведь даже не смешно. Я прекрасно понимаю, что это Ваша вотчина. Но я лично за то, чтобы различных решений одной задачи было много и разных, в т.ч. и бесплатных ;)
yuraskas; quNas; StepByStep; +3 Ответить
6. Yashazz 2848 05.11.13 12:46 Сейчас в теме
Ну, пущай будет, как оглавление. А то и правда, неохота иной раз лазить да искать.

(5) Кое в чём склонен согласиться.
StepByStep; +1 Ответить
8. sergnik 06.11.13 12:33 Сейчас в теме
(5) Eugeneer,
Позволю себе с вами не согласиться.
Сама публикация не то чтобы сильно заинтересовала, но была в топе, и я сюда зашел.
Просмотрел остальные 5 публикаций автора, о которых вы написали

Каждая публикация описывает совсем разные методы обработки информации,
поэтому это не выжимание из воздуха.
Кроме того, весь код выложен прямо в публикации, не нужно качать "кота в мешке" чтобы оценить работу
кода. Уже за одно это автору - ОГРОМНЕЙШИЙ ПЛЮС

Быть может, у Вас личная неприязнь к автору? ))
user687869_ip.kolotei; Knych; HitGroove; CratosX; Alex_IT; StepByStep; +6 Ответить
10. Nick_Godspeed 06.11.13 15:14 Сейчас в теме
(5) Eugeneer, не ревнуйте :)
Как верно подметил (8) только за открытый код, да плюс за такую всестороннюю проработку вопроса автор заслужил хоть сто постов по одному вопросу.
14. Abadonna 3833 07.11.13 06:20 Сейчас в теме
(5)
А тут мы видим банальное выжимание рейтинга. Ведь те кто первую публикацию скачал будут еще ставить рейтинги в других пяти. Это очевидно)))

Нет, Евген, тут ты как раз не прав! Плюсуют/качают только то, что на виду. Не будут еще ставить рейтинги в других пяти, за редчайшими исключениями. По личному опыту;)..
P.S. Давным-давно, хохмы ради, я опубликовал свою же обработку под другим ником. Как попёрли плюсы! А самое интересное: продолжали плюсовать даже после того, как я написал, что это шутка и указал первоисточник. Продолжали!
StepByStep; +1 Ответить
7. Pavl0 86 06.11.13 10:27 Сейчас в теме
Замечательно! Утащил к себе, проверю на досуге.
StepByStep; +1 Ответить
12. StepByStep 3257 06.11.13 18:36 Сейчас в теме
(7) Pavl0,
Если не затруднит - отпишитесь, пожалуйста, о результатах.
9. CagoBHuK 31 06.11.13 14:56 Сейчас в теме
Для тех, кто хочет сделать действительно красивое решение: открываете XML XSLX файла и с помощью XSLT преобразуете в сериализованный табличный документ. А дальше - обычная рассериализация с помощью фабрики XDTO. Никакого геморроя и лишнего текста. Все будет работать штатными средствами.
SoNiKa; quNas; nSpirit2; i.kovtun; zarucheisky; StepByStep; +6 Ответить
13. StepByStep 3257 06.11.13 18:47 Сейчас в теме
(9) CagoBHuK,
ПРЕКРАСНО. Существует еще способ.
37. nSpirit2 20.08.14 15:07 Сейчас в теме
Меня очень нервирует способ объявление переменных взятый явно из Делфи. Ну а так полностью согласен с (9) CagoBHuK все намного проще :)
11. LexSeIch 203 06.11.13 16:34 Сейчас в теме
Мир этому дому!
Мне нравиться, когда код публикуется в статье. Автору плюс.
15. Abadonna 3833 07.11.13 07:09 Сейчас в теме
16. StepByStep 3257 07.11.13 10:45 Сейчас в теме
(15) Abadonna,
Упоминание об этой работе встречал. Страница была недоступна. Причина - неизвестна.
А вообще, хорошая мысль, сделать подборку ссылок по вопросу "Загрузки из EXCEL ..." от разных авторов в разных "ракурсах".
Соберу - выложу.
17. StepByStep 3257 07.11.13 13:30 Сейчас в теме
07.11.2013.
Добавлены ссылки на публикации других авторов.
Если что-то не увидел, не обессудьте.
18. soap 56 07.11.13 15:45 Сейчас в теме
Интересно. Оч хор что код прямо в статье.
Автору плюс
19. Abadonna 3833 07.11.13 16:55 Сейчас в теме
(0) В тексте поправь
Импирически:
-Эмпирически ;)
20. StepByStep 3257 07.11.13 20:35 Сейчас в теме
(19) Abadonna,
СПАСИБО. "Велик и Могуч Русский язык".
21. RainyAugust22 234 08.11.13 06:37 Сейчас в теме
Плюсую. Взял на заметку.
22. zspr 22 15.11.13 15:01 Сейчас в теме
Автору большое спасибо
Прикрепленные файлы:
24. mvgfirst 4 20.01.14 13:28 Сейчас в теме
Кто нибудь тестировал это на практических данных?
Значения ячеек с формулами полностью игнорируются при использовании этого метода.
Вернее не метода а если скопировать приведенный исходный код.

Без допиливания руками - никак не обойтись.
dimontit; +1 Ответить
25. StepByStep 3257 30.01.14 13:02 Сейчас в теме
(24) mvgfirst,
СПАСИБО.
Действительно так. Надо "допилить".
26. StepByStep 3257 01.02.14 14:18 Сейчас в теме
(24) mvgfirst,
01.02.2014.
Изменена функция ЗагрузитьМетодом_1CXML().
Дополнена считыванием значений из ячеек, содержащих формулы.
27. Al-X 05.02.14 10:48 Сейчас в теме
+ Актуально-то как !!! Жлобы, не хотят офис покупать !! ))))
28. smilebringer 26.02.14 12:05 Сейчас в теме
Эмпирическая догадка не верна, любое целое, дробное число, процент, время, и другие числовые форматы будут интерпретироваться как дата. Строковые значения будут верно обрабатываться.
30. StepByStep 3257 27.02.14 16:56 Сейчас в теме
(28) smilebringer,
СПАСИБО.
Строки, числа, даты читаются.
Процент, время - посмотрю, подправлю.
32. StepByStep 3257 01.03.14 23:16 Сейчас в теме
01.03.2014 г. Обновление.
(28) smilebringer, (29) igyo,
СПАСИБО за указанные неточности.
Доработал.
Если обнаружите неточности - напишите, пожалуйста.
29. igyo 104 27.02.14 10:08 Сейчас в теме
Косяк если в колонке будет пустая ячейка, смещаются колонки тогда... :(
31. StepByStep 3257 27.02.14 16:58 Сейчас в теме
(29) igyo,
Это проверялось.
В смысле одна или несколько пустых ячеек в колонке или вся колонка пустая?
Если можно - файл выложите, пожалуйста.
33. spaminfostart 15 05.03.14 16:47 Сейчас в теме
и тут спрошу про 255 столбцов... таки не обрабатывает такие файлы?
34. smilebringer 11.03.14 13:43 Сейчас в теме
Тебе бы еще такие вещи вынести на git или другую систему контроля версий, тебе тогда и сообщество укажет, где что поправить, может и свой вариант кто-то предложит. А так изменение читать тяжело и поэтому лениво :)
35. Glk 15.04.14 14:36 Сейчас в теме
// ЧИСЛО.
                                        Если Прав(ЗначениеЯчейки, 5) = "E-003" Тогда
                                            УдалитьПоследнийСимволВСтроке(ЗначениеЯчейки, 5);
                                            Попытка
                                                ЗначениеЯчейки = Число(ЗначениеЯчейки);
                                            Исключение
                                            КонецПопытки;
                                            // ЧИСЛО.
                                        ИначеЕсли Прав(ЗначениеЯчейки, 3) = "E-3" Тогда
                                            УдалитьПоследнийСимволВСтроке(ЗначениеЯчейки, 3);
                                            Попытка
                                                ЗначениеЯчейки = Число(ЗначениеЯчейки);
                                            Исключение
                                            КонецПопытки;
Показать

Обрезать обрезали, а поделить на 1000 забыли.
StepByStep; +1 Ответить
36. StepByStep 3257 20.08.14 15:46 Сейчас в теме
38. Glk 23.08.14 01:13 Сейчас в теме
(36) Кстати, пришлось еще добавить аналогичную конструкцию для
Прав(ЗначениеЯчейки, 3) = "E-2"
, регулярно попадалось в присылаемых нам файликах.
39. StepByStep 3257 27.08.14 21:02 Сейчас в теме
(38) Glk,
Скоро будет новая редакция. В ней будет и Е-..., Е+... и др.
40. StepByStep 3257 03.09.14 13:57 Сейчас в теме
(38) Glk,
03.09.2014. Новая редакция.
41. Glk 03.09.14 16:39 Сейчас в теме
ИндексКолонки = ?(ИндексКолонки = Неопределено, КоличествоСлужебныхКолонок-1, ИндексКолонки+КоличествоСлужебныхКолонок-1);

Непонятно, зачем тут КоличествоСлужебныхКолонок-1, если имя колонки никак от количества служебных не зависит.
У меня добавляется еще одна служебная колонка с уровнем группировки для загрузки иерархических справочников номенклатуры от поставщиков, возможно стоит ее добавить и в вашу обработку для универсальности.
НоваяСтрока.УровеньГруппировки=SheetX.ЗначениеАтрибута("outlineLevel");


StepByStep; +1 Ответить
42. StepByStep 3257 03.09.14 22:43 Сейчас в теме
(41) Glk,
ИндексКолонки = ?(ИндексКолонки = Неопределено, КоличествоСлужебныхКолонок-1, ИндексКолонки+КоличествоСлужебныхКолонок-1);
СПАСИБО.

Атрибут "outlineLevel" может отсутствовать, например, если файл создан в MS EXCEL.
При сохранении в LibreOffice - он есть.
43. Glk 04.09.14 12:47 Сейчас в теме
(42)
Он отсутствует, если нет собственно группировки в текущей строке, но это не мешает загружать его для остальных. А если определить колонку как
ТаблицаРезультат.Колонки.Добавить("УровеньГруппировки", Новый ОписаниеТипов("Число"), "Гр", 4);

то даже проверку на Неопределено делать не приходится - само в 0 преобразуется.
StepByStep; +1 Ответить
44. StepByStep 3257 04.09.14 15:22 Сейчас в теме
45. StepByStep 3257 04.09.14 15:32 Сейчас в теме
46. 7OH 32 05.09.14 01:53 Сейчас в теме
Ни на что не претендую.
Добавил:
1. чистку временного каталога за собой
2. выбор листа
Переделал:
1. Определение колонок (не по первой строке, а по служебным данным "DIMENSION\ref" )
2. Имена колонок - немного подправил аглоритм - вылетало часто.
3. Сорри - но обычных формах - переделать не сложно.
Прикрепленные файлы:
ЗагрузкаXLSX.erf
Ponommax; quNas; StepByStep; Glk; +4 Ответить
47. StepByStep 3257 05.09.14 13:44 Сейчас в теме
(46) 7OH,
Определение колонок (не по первой строке, а по служебным данным "DIMENSION\ref"

Сталкнулся с несоответствием служебных данных и реальных колонок - поэтому по 1-ой строке "по факту".
Имена колонок - немного подправил аглоритм - вылетало часто

Если не сложно опишите пример.
СПАСИБО.
49. 7OH 32 06.09.14 15:30 Сейчас в теме
(47)
в первой строке шапка документа в виде
Склад : техника
ответственный: Пупкин
и тут пошла шапка колонок
итого он определяет всего 2 колонки и при попытке считывания на шапке вываливается с ошибкой
а так в DIMENSION вроде красиво лежит весь диапазон - спеациально ставил спрва снизу подальше одну букву - подхватывало
50. StepByStep 3257 10.09.14 13:53 Сейчас в теме
48. StepByStep 3257 05.09.14 17:14 Сейчас в теме
(46) 7OH,
Не заполненная/не полностью заполненная 1-я строка ?
63. XelOla 15 18.10.15 00:39 Сейчас в теме
(46) 7OH, будет ли это работать в обычном приложении?
Что еще можно использовать для работы с Эксель без установленного Офиса?
66. StepByStep 3257 15.11.15 19:36 Сейчас в теме
(63) XelOla,
будет ли это работать в обычном приложении?
Что еще можно использовать для работы с Эксель без установленного Офиса?

Да, будет.
См. также
Методы загрузки из внешнего источника:
- Метод "MS ADO" (Чтение файлов xls, xlsx средствами Microsoft ADO): http://infostart.ru/public/163640/
- Метод "NativeXLSX" (Чтение файлов xlsx с картинками средствами 1С. ПостроительDOM): http://infostart.ru/public/300092/
- Метод "Excel1C" (Загрузка на платформе 8.3.6 с картинками. Чтение файлов xls, xlsx, ods): http://infostart.ru/public/341855/

При установленном бесплатном LibreOffice:
- Метод "LO CALC" (Чтение файлов xls, xlsx, ods, sxc с картинками средствами LibreOffice): http://infostart.ru/public/163642/
51. Drizer2000 13 24.09.14 15:57 Сейчас в теме
Эх описал бы кто преимущество, того или иного метода, я не читал все статьи автора, может где и есть. Например, мне нужно загружать в базу из экселя прайсы поставщиков. Прайсы могут содержать до 10 тыс строк, вот и думаю какой бы метод использовать. Сейчас сделано классичеси через ОЛЕ,но относительно медленно идет загрузка.
52. jobkostya1c8 24.09.14 16:19 Сейчас в теме
Ставлю "плюс" за подборку решений. Все равно для разных задач приходится свое писать. В одной из нехороших обработок по загрузке основных средств лучшего решения чем вручную указание пользователем номеров колонок не было.
53. Drizer2000 13 24.09.14 20:54 Сейчас в теме
А кто знает какой используется метод для обработки указанной вот по этой ссылке:
http://infostart.ru/public/21810/
54. SinglCOOLer 210 26.09.14 14:08 Сейчас в теме
все бы вроде не плохо, но часть данных колонок почему то берется с нужно листа, а часть с другого
57. StepByStep 3257 25.11.14 23:20 Сейчас в теме
(54), (55) SinglCOOLer,
В ранних версиях обработки "Импорт (загрузка) из внешнего источника (Excel,LibreOffice,SQL,DBF,MXL) в 1С 8.2/8.3: Розница,УТ,БП,КА. /РОССИЯ,УКРАИНА,БЕЛАРУСЬ/" http://infostart.ru/public/120961/ описанный метод использовался и корректно брал данные с необходимого листа.
55. SinglCOOLer 210 26.09.14 14:34 Сейчас в теме
Если делаешь лист 1 и единственным, то перестает путать и грузит корректно
56. MishaHD 28 05.11.14 07:32 Сейчас в теме
Update :) Написал хвалебный комментарий, а потом нашел косяк. В представленных выше процедурах когда мы формируем МассивSharedStrings из файла SharedStrings.xml не учитывается то, что может встречаться значение "пустая строка". То есть условие
Если ВРег(SharedStrings.Имя) = "#TEXT" Тогда
не будет отрабатывать. Соответственно если в файле SharedStrings.xml встретилась пустая строка, то начинаю "плыть" индексы массива МассивSharedStrings, а за ними "плывет" результирующая таблица.

Написал следующий костыль, может кому полезно будет:

Вот это:
Пока SharedStrings.Прочитать() Цикл
        Если ВРег(SharedStrings.Имя) = "#TEXT" Тогда
            МассивSharedStrings.Добавить(SharedStrings.Значение);
        КонецЕсли;
    КонецЦикла;


Меняем на это:
ФлагСтрокаЗаписана = Ложь;
    
	Пока SharedStrings.Прочитать() Цикл
		Если ВРег(SharedStrings.Имя) = "SI" и SharedStrings.ТипУзла = ТипУзлаXML.НачалоЭлемента тогда
			ФлагСтрокаЗаписана = Ложь;
		КонецЕсли;
		
        Если ВРег(SharedStrings.Имя) = "#TEXT" Тогда
            МассивSharedStrings.Добавить(SharedStrings.Значение);
			ФлагСтрокаЗаписана = Истина;
		КонецЕсли;
		
		Если ВРег(SharedStrings.Имя) = "SI" и SharedStrings.ТипУзла = ТипУзлаXML.КонецЭлемента и не ФлагСтрокаЗаписана тогда
			//встретили пустую строку!
			 МассивSharedStrings.Добавить("");
		КонецЕсли;
		
    КонецЦикла;
Показать


Спасибо за процедуры, приятно что все нормально отлажено и работает (как выяснилось кроме некоторых косяков))). Небольшое пожелание, бы бы удобно если бы колонки именовались из заголовочных данных (например если указываем что заголовок - это строка №1).
It-developer; InShallaH; [4EPHbIYY_KOT]; Glk; +4 Ответить
58. StepByStep 3257 25.11.14 23:21 Сейчас в теме
(56) MishaHD,
Рекомендую обратить внимание на "Загрузка из EXCEL в 1С. Чтение файла XLSX средствами 1С. ПостроительDOM" http://infostart.ru/public/300092/
59. MishaHD 28 21.12.14 08:33 Сейчас в теме
(58) спасибо за совет. В принципе допилил то, что в этом посте выложено под свои нужды, все работает без косяков
67. [4EPHbIYY_KOT] 37 09.02.16 10:31 Сейчас в теме
(56) MishaHD, ещё бы автор это подправил - вообще был бы зачёт. А то без разбора кода пооткрывали файлики, плывёт всё жестко. Даже с соседних листов данные берёт :)
68. InShallaH 50 27.02.17 18:00 Сейчас в теме
(56)
Ты просто сделал мой день :)
70. It-developer 20 13.04.18 17:09 Сейчас в теме
60. jobkostya1c8 28.01.15 13:41 Сейчас в теме
Вопрос граждане по отказоустойчивости при чтении из Excel. Тут есть сервер 1С (вроде 64 битный без установленного на нем офисного пакета. Соответственно на нем нет зарегистрированного объекта COMОбъект "Excel.Application". Как раз смотрели недавнюю статью Настройка DCOM компоненты "Excel.Application" на 64-битном сервере приложений 1С
Суть вопроса в чем. Мне прислали такое техническое мнение корпорации Майкрософт:
Корпорация Microsoft на сегодняшний день не рекомендует производить и не поддерживает автоматизацию программ из пакета Microsoft Office с помощью автоматических, неинтерактивных клиентских приложений или компонентов (включая ASP, DCOM и службы NT), поскольку при запуске в этом окружении программы пакета Office могут работать нестабильно или зависать.

Насчет при запуске в этом окружении программы пакета Office могут работать нестабильно или зависать частично согласен. Методы закрытия работают плохо и висят на сервере о чем писали.
Что народ скажед по поводу данного мнения? Не хотелось бы вступать в админские споры. Если загрузка хотя бы периодическая под контролем оператора? Насколько это критично. В чем получается преимущество ADO? В том что не надо пакет офисный ставить (я про уклон в лицензионную политику)? Или еще есть преимущества (про скорость и прочие радости излишне).
64. StepByStep 3257 15.11.15 19:31 Сейчас в теме
(60) kostyaomsk, (61) kostyaomsk,
См. Загрузка из EXCEL в 1С. MS ADODB.Connection : http://infostart.ru/public/163640/
61. jobkostya1c8 28.01.15 14:17 Сейчас в теме
Насчет "универсального ADO" как-то начал обработку чтения xls в тонком клиенте для БП 3.0 с анализом ошибок. Предполагалось сделать универсальной с ведением протокола ошибок на сервере с передачей на клиент.
Сразу предупреждаю, данную обработку запускать осторожно чтоб не повредить данные. Тут выкладываю только с целью сравнения и отладки технологии по чтению из екселя с помощью ADO.
По крайней мере лист начинает читать без всяких настроек ADO и локального Екслея (на компе только Libre office).
Код чтения (главное, метод ADODBConnection.Open(); срабатывает:
// Инициализация основного объекта ADODB.Connection. Открытие соединения.
		ADODBConnection = Новый COMОбъект("ADODB.Connection");		
		ADODBConnection.ConnectionString =  СonnectionString;
		
		ADODBConnection.Provider = "Microsoft.Jet.OLEDB.4.0"; //????? ставился САМ MSSQL -		
		ADODBConnection.Open();
		// Импирически определенный параметр для правильного определения количества строк листа.
		ADODBConnection.CursorLocation = 3;    // По-умолчанию 2.
		
	ТекстЗапроса = "SELECT * FROM [" + ИмяЛиста + "$]";
	
	// Создание Recordset. Дочерний объект ADODBConnection. Набор записей по запросу.
	
		ADODBRecordset = Новый COMОбъект("ADODB.Recordset");
		ADODBRecordset.Open(ТекстЗапроса, ADODBConnection);
		
		// Проверка заполненности листа.
		Если (ADODBRecordset.EOF ИЛИ ADODBRecordset.BOF) Тогда
			КолвоСтрокExcel = 0;
			ДобавитьВЛогНаСервере("Лист екселя " + ИмяЛиста + ": не содержит данных (вообще)!");
			
			// Завершение работы.
			// Закрытие Объектов.
			ADODBRecordset.Close();
			ADODBConnection.Close();
			ADODBRecordset   = Неопределено;
			ADODBConnection = Неопределено;
			
			Возврат;
		КонецЕсли;
		
		// Импирически определенные параметры для правильного определения количества строк листа.
		ADODBRecordset.AbsolutePage     = 1;
		ADODBRecordset.AbsolutePosition = 1;
		
	// Параметр, возвращаемый в вызывающую процедуру.
	КолвоСтрокExcel = ADODBRecordset.RecordCount + 1;    // (+1) - учет Строки-Заголовока, которая "съедается".
	КолвоКолонокExcel = ADODBRecordset.Fields.Count;
	
	// Проверка заполненности листа.
	Если КолвоСтрокExcel <= 2 Тогда
		КолвоСтрокExcel = 0;
		 ДобавитьВЛогНаСервере("Лист екселя " + ИмяЛиста + ": не содержит данных (строк)!");
		
		// Завершение работы.
		// Закрытие Объектов.
		ADODBRecordset.Close();
		ADODBConnection.Close();
		ADODBRecordset   = Неопределено;
		ADODBConnection = Неопределено;
		
		Возврат;
	КонецЕсли;
Показать

обработка прилагается
Прикрепленные файлы:
ЗагрузкаВБухгалтерию3.epf
62. Petrony 20.08.15 16:53 Сейчас в теме
Также не распознаются ячейки с Дата+Время.
Поскольку Дата+Время - это не целое число, которое больше 1, то оно не распознается ни процедурой ЭтоДатаXLSX() ни процедурой ЭтоВремяXLSX
В принципе, можно из функции ЭтоДатаXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) убрать проверку на то, что значение ячейки - целое число. Или отдельно создать функцию.
65. StepByStep 3257 15.11.15 19:32 Сейчас в теме
69. vladismi 161 12.10.17 16:41 Сейчас в теме
71. It-developer 20 18.04.18 17:52 Сейчас в теме
Все хорошо, но у меня был косяк, когда ничего не было в заголовке - происходило смещение колонок. Помогло исправить изменение функции ПолучитьМассивИменКолонокНаЛистеXLSX_Новый. Не все в ней нужно, но суть, думаю, понятна

Функция ПолучитьМассивИменКолонокНаЛистеXLSX_Новый(SheetX)
    Перем ДиапазонДанных, ДиапазонКолонок, ПерваяКолонка, ПоследняяКолонка, НомерПервойК, НомерПоследнейК;
    Перем Подсчет, ИмяКолонки;
    Перем МассивИменКолонокXLSX, КолвоКолонокEXCEL;
    
    МассивИменКолонокXLSX = Новый Массив;
    
    Подсчет = Ложь;
    // Считать очередной узел XML.
    Пока SheetX.Прочитать() Цикл
        // DIMENSION.
        Если ВРег(SheetX.Имя) = "DIMENSION" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
            ДиапазонДанных     = SheetX.ПолучитьАтрибут("ref");
            ДиапазонКолонок = ЗаменитьОдниСимволыДругими("0123456789", ДиапазонДанных, "");
            ПерваяКолонка     = Лев(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") - 1);
            ПоследняяКолонка= Сред(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") + 1);
            НомерПервойК    = НомерКолонкиДесятичный(ПерваяКолонка);
            НомерПоследнейК    = НомерКолонкиДесятичный(ПоследняяКолонка);
        КонецЕсли;
    КонецЦикла;
	
	к = НомерПервойК;
	Пока к <= НомерПоследнейК Цикл
		МассивИменКолонокXLSX.Добавить(ИмяКолонкиПоНомеру(к));
		к = к + 1;
	КонецЦикла;	
    
    КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество();
    Если НЕ НомерПоследнейК = Неопределено Тогда
        Если КолвоКолонокEXCEL < НомерПоследнейК Тогда
            Сообщить("Строка заголовков колонок (1-я строка) заполнена не полностью:
            |К-во колонок строки меньше объявленной: " + КолвоКолонокEXCEL + "<" + НомерПоследнейК);
            ДополнитьМассивИменКолонокXLSX(НомерПоследнейК, МассивИменКолонокXLSX);
        ИначеЕсли КолвоКолонокEXCEL > НомерПоследнейК Тогда
            Сообщить("Строка заголовков колонок (1-я строка) содержит больше колонок, чем объявлено:
            |К-во колонок строки больше объявленной:" + КолвоКолонокEXCEL + ">" + НомерПоследнейК);
        КонецЕсли;
    КонецЕсли;
        
    Возврат МассивИменКолонокXLSX;
    
КонецФункции

Функция ИмяКолонкиПоНомеру(НомерКолонки)
	
	Латиница = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";    // 26.
	
	Если НомерКолонки <= 26 Тогда
		Возврат Сред(Латиница, НомерКолонки, 1)
	Иначе
		Возврат Сред(Латиница, Цел((НомерКолонки-1)/26), 1) + Сред(Латиница, НомерКолонки - 26*Цел((НомерКолонки-1)/26), 1)
	КонецЕсли;	
	
КонецФункции
Показать
72. AlexeyPapanov 12.09.18 23:36 Сейчас в теме
Коллеги, я одного не догоню.

Колонки смешиваются по непонятному принципу. Т.е. они не идут в ТЗ в таком порядке как они были в эксель-файле.
Я хочу дать юзеру возможность видеть на форме всю ТЗ результата.

Мне надо взять нужные колонки из ТЗ результата загрузки.
А как я ее выведу, если колонки в неведомом мне порядке идут.
Прикрепленные файлы:
73. fanlexa 2 28.09.18 10:24 Сейчас в теме
Всем доброго дня. С выше указанными доработками, все отлично работает, за что всем огромное спасибо! Но у меня вот какая проблема, при выгрузке из клиент банка(сбербанк) в формате excel, файлы выгруженные на разных компах имеют почему-то разную структуру xml файлов, т.е. на одних компах файлы выгружается с "правильной " структурой и в заголовке файла sheet1.xml: "<?xml version="1.0" encoding="UTF-8" standalone="true"?>

-<worksheet xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" mc:Ignorable="x14ac" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">",

а в НЕ правильных файлах: "<?xml version="1.0" encoding="UTF-8"?>

-<worksheet xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">", кроме того у них разная структура папок внутри. Но если "не правильный файл" открыть в excel, и просто нажать сохранить, то его структура становится правильной и читается нормально... не понимаю как победить пока, может кто уже сталкивался?
74. fanlexa 2 28.09.18 14:04 Сейчас в теме
Пока ждал проверку модератерами сам починил, может кому пригодится:

1.
Функция ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX)
	//Возврат МассивИменКолонокXLSX;
	Перем ДиапазонДанных, ДиапазонКолонок, ПерваяКолонка, ПоследняяКолонка, НомерПервойК, НомерПоследнейК;
	Перем Подсчет, ИмяКолонки;
	Перем МассивИменКолонокXLSX, КолвоКолонокEXCEL;
	
	МассивИменКолонокXLSX = Новый Массив;
	
	Подсчет = Ложь;
	// Считать очередной узел XML.
	Пока SheetX.Прочитать() Цикл
		// DIMENSION.
		Если ВРег(SheetX.Имя) = "DIMENSION" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			ДиапазонДанных     = SheetX.ПолучитьАтрибут("ref");
			//{[+](фрагмент добавлен), 
			Если СтрДлина(ДиапазонДанных) = 2 Тогда
				ДиапазонДанных = ДиапазонДанных + ":ZZ";
			КонецЕсли; 
			//} 
			ДиапазонКолонок = ЗаменитьОдниСимволыДругими("0123456789", ДиапазонДанных, "");
			ПерваяКолонка     = Лев(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") - 1);
			ПоследняяКолонка= Сред(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") + 1); 			
			НомерПервойК    = НомерКолонкиДесятичный(ПерваяКолонка);
			НомерПоследнейК    = НомерКолонкиДесятичный(ПоследняяКолонка);
		КонецЕсли;
	КонецЦикла;
	
	к = НомерПервойК;
	Пока к <= НомерПоследнейК Цикл
		МассивИменКолонокXLSX.Добавить(ИмяКолонкиПоНомеру(к));
		к = к + 1;
	КонецЦикла;    
	
	КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество();
	Если НЕ НомерПоследнейК = Неопределено Тогда
		Если КолвоКолонокEXCEL < НомерПоследнейК Тогда
			Сообщить("Строка заголовков колонок (1-я строка) заполнена не полностью:
			|К-во колонок строки меньше объявленной: " + КолвоКолонокEXCEL + "<" + НомерПоследнейК);
			ДополнитьМассивИменКолонокXLSX(НомерПоследнейК, МассивИменКолонокXLSX);
		ИначеЕсли КолвоКолонокEXCEL > НомерПоследнейК Тогда
			Сообщить("Строка заголовков колонок (1-я строка) содержит больше колонок, чем объявлено:
			|К-во колонок строки больше объявленной:" + КолвоКолонокEXCEL + ">" + НомерПоследнейК);
		КонецЕсли;
	КонецЕсли;
	
	Возврат МассивИменКолонокXLSX;
	
КонецФункции
Показать


2.

Функция ЗагрузитьМетодом_NativeXLSX(Знач ФайлEXCEL, Знач ИмяНомерЛиста, Знач СтрокаЗаголовка = 1, Знач НачСтрока = 0, Знач КонСтрока = 0, КолвоСтрокExcel = 0)
	Перем ZIPКаталог, ФайлИмяЛиста, ФайлНомерЛиста, КолвоКолонокEXCEL, НомерСтроки, НомерКолонки, ИмяКолонки, ИндексКолонки, ШиринаКолонки, ДлинаСтроки;
	Перем МассивИменКолонокXLSX, МассивSharedStrings, МассивNumFmtId, СоответствиеNumFmtIdFormatCode;
	Перем SheetX,ЗначениеЯчейки, ТипЗначения, ФорматЯчейки, ФорматСтиля;
	Перем ТаблицаРезультат, НоваяСтрока;
	
	ФайлНомерЛиста  = ИмяНомерЛиста.НомерЛиста;
	ФайлНомерЛиста = ?(ФайлНомерЛиста = 0, 1, ФайлНомерЛиста);
	
	ZIPКаталог = КаталогВременныхФайлов() + "XLSX\";
	Если НЕ ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) Тогда
		Возврат Новый ТаблицаЗначений;
	КонецЕсли;
	
	СоответствиеNumFmtIdFormatCode = Новый Соответствие;
	МассивNumFmtId = ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode);
	
	МассивSharedStrings = ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог);
	
	SheetX = Новый ЧтениеXML;
	SheetX.ОткрытьФайл(ZIPКаталог + "XL\WorkSheets\Sheet" + ФайлНомерЛиста + ".xml");
	
	МассивИменКолонокXLSX = ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX);
	КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество();
	
	// Создание результирующей таблицы, в которую будут записываться считанные из EXCEL данные.
	ТаблицаРезультат = Новый ТаблицаЗначений;
	// Формирование колонок результирующей таблицы.
	// "НомерСтроки" - для наглядности и удобства.
	// В зависимости от разрабатываемой обработки.
	// "Сопоставлено" - может быть другим.
	// Здесь же могут быть добавлены другие колонки, не формируемые из содержимого файла EXCEL.
	ТаблицаРезультат.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"), "№", 4);
	ТаблицаРезультат.Колонки.Добавить("Сопоставлено", Новый ОписаниеТипов("Булево"), "Сопоставлено", 1);
	ТаблицаРезультат.Колонки.Добавить("УровеньГруппировки", Новый ОписаниеТипов("Число"), "Гр", 2); // Группировка строк в файле EXCEL.
	Для ит = 1 ПО КолвоКолонокExcel Цикл
		ИмяКолонки = "N" + ит;
		Колонка = ТаблицаРезультат.Колонки.Добавить(ИмяКолонки);
	КонецЦикла;
	
	SheetX = Новый ЧтениеXML;
	SheetX.ОткрытьФайл(ZIPКаталог + "XL\WorkSheets\Sheet" + ФайлНомерЛиста + ".xml");
	
	ЭтоНачалоДанных = Ложь;
	// Считать очередной узел XML.
	Пока SheetX.Прочитать() Цикл
		Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			ЭтоНачалоДанных = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Если НЕ ЭтоНачалоДанных Тогда
		Возврат Новый ТаблицаЗначений;
	КонецЕсли;
	
	// Считать очередной узел XML.
	НомерСтроки = 0;
	Пока SheetX.Прочитать() Цикл
		Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
			Прервать;   // Окончание данных.
		КонецЕсли;
		Если ВРег(SheetX.Имя) = "ROW" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			НомерСтроки = НомерСтроки + 1;
			Если НЕ НачСтрока = 0 И НЕ НомерСтроки = 1 И НомерСтроки < НачСтрока Тогда
				Продолжить;
			КонецЕсли;
			НоваяСтрока = ТаблицаРезультат.Добавить();
			НоваяСтрока.НомерСтроки = НомерСтроки;
			НоваяСтрока.УровеньГруппировки = SheetX.ЗначениеАтрибута("outlineLevel");
			Пока SheetX.Прочитать() Цикл    // Считаем колонки строки EXCEL.
				Если ВРег(SheetX.Имя) = "ROW" Тогда
					Прервать;
				КонецЕсли;
				Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
					Прервать;   // Окончание данных.
				КонецЕсли;
				Если ВРег(SheetX.Имя) = "C" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
					ТипЗначения = SheetX.ЗначениеАтрибута("t");
					ФорматЯчейки = SheetX.ЗначениеАтрибута("s");
					ИмяКолонки = SheetX.ЗначениеАтрибута("r");
					ИмяКолонкиБезЦифр = ЗаменитьОдниСимволыДругими("0123456789", ИмяКолонки, "");
					ИндексКолонки = МассивИменКолонокXLSX.Найти(ИмяКолонкиБезЦифр)+1;
					SheetX.Прочитать();
					Если ВРег(SheetX.Имя) = "V"  ИЛИ ВРег(SheetX.Имя) = "F" ИЛИ ВРег(SheetX.Имя) = "IS" Тогда   // "V" - Значение, "F" - Формула.  "IS" - добавлено для формата файла из сбербанка
						Если ВРег(SheetX.Имя) = "F" Тогда
							Пока НЕ ВРег(SheetX.Имя) = "V" Цикл
								SheetX.Прочитать();
							КонецЦикла;
						КонецЕсли;
						//{[+](фрагмент добавлен)
						Если ВРег(SheetX.Имя) = "IS" Тогда 						
							Пока НЕ ВРег(SheetX.Имя) = "T" Цикл
								SheetX.Прочитать();
							КонецЦикла;
						КонецЕсли;
						//} 
						SheetX.Прочитать();
						Если ВРег(SheetX.Имя) = "#TEXT" Тогда
							ЗначениеЯчейки = SheetX.Значение;
							ФорматСтиля = "";
							Если (НЕ ФорматЯчейки = "" И НЕ ФорматЯчейки = Неопределено) Тогда
								Попытка
									ИндексФормата = Число(ФорматЯчейки);
									ФорматСтиля = СоответствиеNumFmtIdFormatCode.Получить(МассивNumFmtId[ИндексФормата]);
								Исключение
									ФорматСтиля = "";
								КонецПопытки;
							КонецЕсли;
							Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда
								Если ТипЗначения = Неопределено ИЛИ ВРег(ТипЗначения) = "N" ИЛИ ВРег(ТипЗначения) = "B" Тогда
									Попытка
										Значение1 = Число(ЗначениеЯчейки);
									Исключение
										Значение1 = ЗначениеЯчейки;
									КонецПопытки;
									ЗначениеЯчейки = Значение1;
									Если (ФорматСтиля = "" ИЛИ ФорматСтиля = Неопределено) Тогда
										// ФорматСтиля = Неопределено - Атрибут "s" отсутствует.
										// MS Office (2010) может не формировать в xml-файле описание стиля форматирования для ячейки.
										// LibreOffice (4.1.5) формирует в xml-файле необходимые описания стиля форматирования ячейки.
										// Сообщить("Не определен стиль форматирования для кода " + ФорматЯчейки + " значения " + ЗначениеЯчейки);
									КонецЕсли;
									
									Если ТипЗнч(ЗначениеЯчейки) = Тип("Строка")
										И (Найти(ЗначениеЯчейки, "E-") > 0 ИЛИ Найти(ЗначениеЯчейки, "E+") > 0) Тогда
										ЗначениеЯчейки = ПолучитьЧислоВСтепениИзСтроковогоЗначения(ЗначениеЯчейки);
									КонецЕсли;
									
									Если ТипЗнч(ЗначениеЯчейки) = Тип("Число") Тогда
										// ПРОЦЕНТ.
										Если ЭтоПроцентXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда
											ЗначениеЯчейки = Окр(ЗначениеЯчейки * 100, 3);
											// БУЛЕВО.
										ИначеЕсли ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда
											ЗначениеЯчейки = Булево(ЗначениеЯчейки);
											// ВРЕМЯ.
										ИначеЕсли ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда
											ЗначениеЯчейки = КонвертироватьЧислоXLSXвДатуВремя(ЗначениеЯчейки);
											// ДАТА.
										ИначеЕсли ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда
											ЗначениеЯчейки = КонвертироватьЧислоXLSXвДату(ЗначениеЯчейки);
											// ЧИСЛО.
										ИначеЕсли ТипЗначения = Неопределено
											ИЛИ ( ЭтоЧислоXLSX(ЗначениеЯчейки, ФорматСтиля) 
											И НЕ ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля)
											И НЕ ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля)
											И НЕ ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) )
											Тогда
											// Без преобразования.
										Иначе
											// Прочие форматы.
										КонецЕсли;
										
									Иначе
										
										Сообщить("Не удалось преобразовать значение к ""числовому""(процент, время, дата, число) типу.");
										
									КонецЕсли;
									
								ИначеЕсли ВРег(ТипЗначения) = "S" Тогда
									
									// МассивSharedStrings может быть пустым.
									Попытка
										ЗначениеЯчейки = СокрЛП(МассивSharedStrings[Число(SheetX.Значение)]);
									Исключение
										ЗначениеЯчейки = "";
									КонецПопытки;
									
								ИначеЕсли ВРег(ТипЗначения) = "STR" ИЛИ ВРег(ТипЗначения) = "INLINESTR" Тогда //{[+](фрагмент добавлен) 
									
									Если ТипЗнч(ЗначениеЯчейки) = Тип("Строка") Тогда
										ЗначениеЯчейки = СокрЛП(ЗначениеЯчейки);
									КонецЕсли;
									
								КонецЕсли;
							КонецЕсли;
							
							ИмяКолонки = "N"+ИндексКолонки;
							НоваяСтрока[ИмяКолонки] = ЗначениеЯчейки;
							// Используется при формировании таблицы на форме обработки.
							ШиринаКолонки = ТаблицаРезультат.Колонки[ИмяКолонки].Ширина;
							ДлинаСтроки = СтрДлина(СокрЛП(ЗначениеЯчейки));
							ТаблицаРезультат.Колонки[ИмяКолонки].Ширина = ?(ШиринаКолонки < ДлинаСтроки, ДлинаСтроки, ШиринаКолонки);							
						КонецЕсли;								
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;
			Если ((НЕ КонСтрока = 0 И (НомерСтроки + 1) > КонСтрока)
				ИЛИ (НЕ КолвоСтрокExcel = 0  И (НомерСтроки + 1) > КолвоСтрокExcel)) Тогда
				Прервать;   // Окончание диапазона считываемых данных.
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	// Завершение работы.
	// Закрытие Объектов.
	SheetX.Закрыть();
	
	УдалитьКолонкиСНулевойШириной(ТаблицаРезультат);
	
	Возврат ТаблицаРезультат;
	
КонецФункции
Показать



Фишка в том, что сбербанк когда выгружает свои данные в excel, сами данные выгружает не в отдельный файл xl\sharedStrings.xml - как положено, а напрямую в файл xl\worksheets\sheet1.xml, хотя там должны хранится только индексы на данные в файле xl\sharedStrings.xml ))))))))
75. user1114234 26.04.19 09:51 Сейчас в теме
Почему может писать, чтo:
Файл не существует/не доступен:
D:\Товар.xlsx
Хотя файл там. Пробовал разные директории, даже файл пустым делал. Всё равно не хочет видеть
76. Petrony 26.04.19 13:30 Сейчас в теме
(75) Если у вас клиент-сервер, то возможно, загрузка у вас происходит на сервере и тогда файл должен быть там, а не на локальном компьютере. И наоборот. Если нужно выбрать файл на локальном компьютере, а прочитать на сервере, помещайте во временное хранилище.
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист 1С
Москва
зарплата от 120 000 руб. до 150 000 руб.
Полный день

Программист 1С
Санкт-Петербург
зарплата от 80 000 руб. до 120 000 руб.
Полный день


Программист 1С
Москва
зарплата от 130 000 руб.
Полный день

Технический лидер, архитектор 1С, руководитель проектов
Санкт-Петербург
зарплата от 150 000 руб.
Полный день