Как программисту быстро загрузить данные из 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 не будет опубликован. Обязательные поля помечены *