Как программисту быстро загрузить данные из Excel

Встала как-то разовая задача — загрузить данные из Excel в базу…
Идея не новая, на ИС имеются уже готовые подобные разработки, но предлагается сделать самостоятельно. Пригодится в будущем.

Идея не новая, на ИС имеются уже готовые подобные разработки, например

но предлагается сделать то же самое самостоятельно. Пригодится в будущем.

 

Пример из жизни: Принесли листик с именами клиентов и суммами зарплат — нужно внести в базу.

Как быть?

1. Взять чужую готовую разработку (плюс: ничего разрабатывать не надо, можно отдать бухгалтеру на растерзание, минус: как правило, бухгалтер придет к Вам с «просьбой» показать как и что делать… возможно, придется шаманить с настройками — особенно если обмен не удастся).

2. Написать «простенькую» обработку загрузки из Excel через OLE (тут ключевое слово «простенькую»… Помимо наладки обмена, нужно вкратце знать как устроен Excel — и как к нему обращаться. Скорее всего — нужен хотя бы минимальный опыт написания макросов. Хотя примеров более чем достаточно).

3. Простое решение:

Создаем внешнюю обработку, туда вставим табличное поле. Включим показывать заголовки колонок и строк и разрешить редактирование. При работе — нужную таблицу копируем из  Excel в буфер обмена и вставляем в табличный документ. При этом форматирование теряется, но оно нам не особо надо.

Далее на ту же форму кидаем кнопку «Выполнить» (хотя вообще-то эта кнопка уже должна быть создана автоматически) и в процедуре-обработчике описываем цикл по строкам с чтением и выполнением нужных действий:

Процедура КнопкаВыполнитьНажатие(Кнопка)

ТабДок = ЭлементыФормы.ПолеТабличногоДокумента1;

НачальнаяСтрока = 2;
КонечнаяСтрока = ЭлементыФормы.ТабДок.ВысотаТаблицы;

Док = Документы.КорректировкаЗаписейРегистровНакопления.СоздатьДокумент();
НовСтр = Док.ТаблицаРегистровНакопления.Добавить();
НовСтр.Имя = Метаданные.РегистрыНакопления.ВзаиморасчетыСРаботникамиОрганизаций.Имя;
НовСтр.Представление = Метаданные.РегистрыНакопления.ВзаиморасчетыСРаботникамиОрганизаций.Представление();

Рег = Док.Движения.ВзаиморасчетыСРаботникамиОрганизаций;

Для сч=НачальнаяСтрока по КонечнаяСтрока Цикл

СуммаВзаиморасчетов = СокрЛП(ТабДок.Область(сч, 2).Текст);
СуммаВзаиморасчетов = Число(СуммаВзаиморасчетов);

ИмяФизЛица = СокрЛП(ТабДок.Область(сч, 1).Текст);
Если ИмяФизЛица="" Тогда

Продолжить;

КонецЕсли;

ФизЛицо = Справочники.ФизическиеЛица.НайтиПоНаименованию(ИмяФизЛица);
Если ФизЛицо.Пустая() Тогда

Сообщить("Физ. лицо не найдено: "+ИмяФизЛица);
Продолжить;

КонецЕсли;

НовЗапись = Рег.ДобавитьПриход();
НовЗапись.Активность = истина;
НовЗапись.ФизЛицо = ФизЛицо;
НовЗапись.СуммаВзаиморасчетов = СуммаВзаиморасчетов;

КонецЦикла;

Док.ПолучитьФорму().Открыть();

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

В принципе, этого достаточно чтобы загрузить данные в документ и показать форму — остальные поля в форме можно заполнить вручную. Можно доработать: вынести на форму поля для заполнения значений при создании конкретного документа, настройку начальной и конечной строк и т.п. Тут как говорится — нет предела совершенству.

Плюсы: пишем все сами — не надо изучать чужой код или что-то настраивать, не требуется знание макросов и устройства Excel (как и сам Excel), не заморачиваемся с OLE-подключением.

Минусы: Универсальностью данное решение не обладает, но как вариант — сделать «по-быстрому» и «на один раз».

Итог: у меня рядом с обработкой «ЗагрузкаИзExcel.epf» со временем накопились обработки, которые делал по-быстрому, копируя ее и изменяя тело цикла «Для«…

 

53 Comments

  1. murat_

    А чем не устроила универсальная обработка с ИТС-диска «ЗагрузкаДанныхИзТабличногоДокумента» ?

    Для разовых задач она самое то и писать ничего не нужно.

    Reply
  2. DrAku1a

    Устраивает, но порой проще и быстрее — написать самому.

    Reply
  3. dka80

    Логично… )))

    Reply
  4. Attest

    Спасибо, пригодится

    Reply
  5. Craig

    (1) Тоже поддерживаю. Обработка с диска ИТС ЗагрузкаДанныхИзТабличногоДокумента универсальна, там возможности куда больше чем в «простенькой» обработке написанной быстро на коленях.

    Reply
  6. kea35

    Обработка имеет шанс на жизнь

    Reply
  7. MICK77
    Craig пишет:

    (1) Тоже поддерживаю. Обработка с диска ИТС ЗагрузкаДанныхИзТабличногоДокумента универсальна, там возможности куда больше чем в «простенькой» обработке написанной быстро на коленях.

    этой обработкой с диска можно загрузить только в 1 документ. а если надо их много?

    Reply
  8. vikorn

    Спасибо, пригодится

    Reply
  9. Вообще-то боян, но некоторые не знают, что так действительно удобнее.

    Не нужно вводить имя файла.

    Reply
  10. (1) ей еще надо научить пользоваться пользователей. А тут можно просто написать простенькую обработку, научить пользователя в нее копировать данные и все.

    Reply
  11. murat_

    (10) Автор вообще-то ясно указал «разовая задача» для «программиста», про повседневную работу пользователей речь здесь не шла.

    Reply
  12. Andrusha1

    Прикольно, идея копировать в буфер не приходила в голову. Хотя все оригинальное, просто.

    Reply
  13. westx

    Да, как-то не дошло до мозга о такой возможности, спасибо автору.

    Reply
  14. Alexey26

    Неплохо!

    Reply
  15. petrovaUL

    Спасибо, пригодится

    Reply
  16. Fruit83

    Спасибо за статью, для меня это сейчас самое то!:)

    murat_ и Craig разница между обработкой и публикацией все-таки есть. 🙂

    Reply
  17. maloi_a

    Замечание.

    Поправьте в примере «КонечнаяСтрока = ЭлементыФормы.ТабДок . ВысотаТаблицы ;»

    на «КонечнаяСтрока = ТабДок.ВысотаТаблицы;»

    Reply
  18. DrAku1a

    (17) Хорошо. Хотя оба варианта работоспособны.

    Reply
  19. annak2980

    Спасибо автору за интересную идею, описанную полностью в виде статьи

    Reply
  20. GTV

    А мне понравилось! Автор — молодец!

    Reply
  21. Fruit83

    У меня проблема возникла. Сперва система ругалась на СуммаВзаиморасчетов = Число(СуммаВзаиморасчетов); , писала что не может преобразовать к типу число. Теперь просто значение не присваивается.

    Reply
  22. DrAku1a

    (21) Используйте СуммаВзаиморасчетов = Число(СокрЛП(СуммаВзаиморасчетов));, кроме того нужно проверять что сумма взаиморасчетов — не пустая строка, а также, если вы перекидываете данные из отчетов 8-ки — то учтите, что по-умолчанию 8-ка вставляет разделитель (пробел) между триадами числа, например код А = Число(Строка(1000)); вызовет в 8-ке ошибку.

    Функция ВЧисло(знач Текст)
    ДопустимыеЗнаки = «0123456789,-«;
    Текст = СокрЛП(«»+Текст);
    Ответ = «»;
    Для сч = 1 по СтрДлина(Текст) Цикл
    Символ = Сред(Текст, сч, 1);
    Если Найти(ДопустимыеЗнаки, Символ)>0 Тогда
    Ответ = Ответ + Символ;
    КонецЕсли;
    КонецЦикла
    Возврат ?(Ответ=»», 0, Число(Ответ));
    КонецФункции
    

    Показать

    Reply
  23. Fruit83

    СуммаВзаиморасчетов = Число(СокрЛП(СуммаВзаиморасчетов)) не помогло, а вот функция помогла. Добавил ее в форму и вызвал СуммаВзаиморасчетов = ВЧисло(СуммаВзаиморасчетов);

    Спасибо!

    Reply
  24. Fruit83

    Чем отличается Текст = СокрЛП(«»+Текст) от Текст = СокрЛП(Текст)?

    Reply
  25. DrAku1a

    (24) По-сути ничем, но есть один ньюанс:

    ИМХО, проверено методом тыка: 1С при анализе выражений использует правило сложения переменных вариантного типа, как в Basic (результат выражения имеет такой же тип, как первая переменная (операнд) выражения, все остальные выражения приводятся к типу первого операнда).

    Т.е. конструкция «»+Текст — это указание 1С, что если Текст не является строкой — то его нужно преобразовать в строку. Хотя 1С должна сама делать такое преобразование внутри СокрЛП() — я на это не полагаюсь и лишний раз перестраховываюсь от ошибок при выполнении кода.

    Reply
  26. Fruit83

    А как обойти обойти проблему контроля уникальности кодов? При загрузке справочника их надо указывать, но, если идет совпадение по кодам, загрузка прерывается…Мне сейчас приходится страховаться и указывать коды, которые наверняка не встретятся в справочнике.

    Reply
  27. DrAku1a

    (26) Сделайте предварительную выборку по справочнику (до цикла загрузки) на предмет максимального кода — можно запросом, можно вручную. Поместите в отдельную переменную. Затем при добавлении нового значения в справочник — увеличивайте эту переменную на 1 и присваивайте код новому элементу.

    Reply
  28. nurislam

    Спасибо.Иногда нужна такая.

    Reply
  29. Koles

    Интересный приемчик. Спасибо.

    Reply
  30. Murom

    Очень интересный прием. Да и правда быстро и удобно.

    Но я по-старинке пользуюсь универсальной «ЗагрузкаДанныхИзТабличногоДокумента». Хотя идея имеет место на жизнь. И еще удобно, если у клиента надо что-то загрузить, а «ЗагрузкаДанныхИзТабличногоДокумента» нет под рукой, то можно очень быстро набросать такую обработочку.

    Reply
  31. baton_pk

    Да! Определённо наш метод!

    Ещё можно табличный документ засунуть в макет внешней обработки и брать данные оттуда. Я использую это, когда мне надо одни и те же данные загрузить в пару тестовых баз по паре десятков раз, а потом отправить клиенту (ну или своими руками) для загрузки в рабочую. Единоразовый копипаст и дальше всё уже решается нажатием одной кнопки — товарищ Бух это любит.

    Reply
  32. Fruit83

    (31) baton_pk, не могли бы вы по-подробнее рассказать о том, как засунуть макет внешней обработки?

    Reply
  33. baton_pk

    (32) Fruit83!

    Всё то же самое:

    во внешней обработке добавляем новый макет — табличный документ и копипастом из Excel вставляем табличку в макет.

    Потом в коде просто вызываем ПолучитьМакет(«НашаТабличка») и пробегаемся по табличке.

    Можно посмотреть типовые — заполнение первоначальных данных в пустой базе или подбор из классификатора валют, например.

    Reply
  34. DrAku1a

    (33) Можно обойтись и без макета — а вставить данные из Excel в поле табличного документа на форме — в режиме конфигуратора. И они сохранятся с обработкой.

    Reply
  35. baton_pk

    (34) DrAku1a.

    Можно, но оно тогда наружу торчать будет. В моих случаях хотелось всё это дело скрыть: таблиц для загрузки было несколько да и на форме были другие элементы, более нужные пользователю.

    А так, да, Ваш вариант на все 100% справедлив.

    Reply
  36. nshrek

    спасибо, хоть и полно в инете аналогичных обработок но думаю пригодится и эта.

    Reply
  37. ivn75

    Смысл темы? В инете полно примеров решений загрузки из Excel при помощи DCOM объектов, при помощи которых можно не только загружать из Excel и Open office, но и выгрузки обратно с форматированием, проставлением формул и гиперссылок.

    Reply
  38. DrAku1a

    (37) Чтобы использовать имеющиеся в инете примеры — нужно вникать в чужой код, возможно — читать документацию… и еще — немао подводных камней встретится… Правда, есть у меня в арсенале функция, которая Excel-файл через OLE считывает в таблицу значений — но пользуюсь ей редко. А так — не выходя из комфортной среды 1С, без изучения доп. материалов можно сделать загрузку данных. Быстро просто и удобно.

    Reply
  39. BalVlad

    Спасибо, пригодится +

    Reply
  40. Yury1001

    Мысль верная (идея рабочая), дубовая (надёжная), помнится копирование документов между базами так писал, и даже из 8 в 7.7 было. Только я в многострочную строку вставлял, потом Список.ИзСтрокиСРазделителями() и вот готовое соответствие так сказать, пользуй не хочу.

    +

    Reply
  41. sai-2010

    Спасибо автору.

    Очень четко и толково все написал.

    Действительно выгрузка и загрузка справочников, это часто возникающая задача.

    Надо срочно и именнно этот справочник.

    Эта статья очень помогла мне.

    Огромное спасибо.

    Удачи.

    Reply
  42. Bezeus

    (38) Вот именно из таких редко используемых функций и строятся «программерские запасы».

    Reply
  43. vladismi

    Отличная идея. А то, как правило, начинаешь вспоминать, как подключиться к Ёкселю… 🙂

    Reply
  44. olezhe

    Немедля использовал для загрузки множества документов из единой таблицы. Плюсанул. Спасибо за подсказку.

    Reply
  45. ledogora

    Полезная статья.Спасибо.

    Reply
  46. wbazil

    обычно копировал подключение к Excel из другой обработки, но часто бывало что потом в процессе отладки этих екселей плодиться много, приходиться прибивать процессы, а тут красиво и элегантно.

    Спасибо за идею!

    Reply
  47. WanGoff

    Ну как-то слишком уж несерьезно, на мой взгляд. Статья для тех, кто второй месяц занимается 1С.

    Reply
  48. DrAku1a

    (47) Да, но… Посмотри сколько народу сказали что классная идея!..

    Reply
  49. WanGoff

    (48) Сложно спорить. Видимо, многим и правда помогло. Ну что ж, и то хорошо.

    Reply
  50. Ele1234567

    Все зависит от решаемой задачи. Но стоит взять на заметку

    Reply
  51. Dionisy_nb

    Отличная идея, если нужно что-то одноразовое. Или редкоиспользуемое.

    Reply
  52. Andrey@

    Как вариант можно использовать при разовой загрузке данных, а то и настроить загрузку номенклатуры из накладной в Excel от поставщика.Спасибо.

    Reply
  53. SurmachAU

    Спасибо! Даже сейчас ваша статься помогла. Но вот у меня вопрос, так получилось, что при загрузке не считывает 1-й столбец, т.е. постоянно надо контролировать, чтобы данные не по подали в первый столбец.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *