8.х Выгрузка в Excel

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 8"", создана пользователем Korolev, 25 июн 2010.

  1. TopicStarter Overlay
    Korolev
    Offline

    Korolev Опытный в 1С

    Регистрация:
    20 апр 2010
    Сообщения:
    269
    Симпатии:
    0
    Баллы:
    26
    Проблема такая. Если файл (xls файл для выгрузки) заранее создан, то выгружаются данные нормально.
    Если файла нет, то выскакивает ошибка ( о том что файл не найден).

    Как правильно настроить условие, чтобы при отсутствии файла этот файл создавался?

    Функция формирования выглядит так:
    Код:
    Функция Сформировать() Экспорт 
    Попытка     
    Эксель = Новый COMОбъект("Excel.Application"); 
    Исключение     
    Сообщить(ОписаниеОшибки()); 
    КонецПопытки; 
    Книга = Эксель.WorkBooks.Open(ИмяФайлаВыгрузки);
    
    Лист = Книга.WorkSheets(1);
    //далее идет запрос и заполнение
    Эксель.Application.Quit();
    
    Возврат Истина;
    
    КонецФункции
    
    
    Вот процедуры из модуля формы, которые отвечают за выбор и выполнение
    Код:
    Процедура ИмяФайлаВыгрузкиНачалоВыбора(Элемент, СтандартнаяОбработка) 
    
    ДиалогВыбораФайла								=	Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
    
    ДиалогВыбораФайла.Фильтр						=	"Файл данных (*.xls)|*.xls";
    ДиалогВыбораФайла.Заголовок						=	"Выберите файл";
    ДиалогВыбораФайла.ПредварительныйПросмотр		=	Ложь;
    ДиалогВыбораФайла.Расширение					=	"xls";
    ДиалогВыбораФайла.ИндексФильтра					=	0;
    ДиалогВыбораФайла.ПолноеИмяФайла				=	Элемент.Значение;
    ДиалогВыбораФайла.ПроверятьСуществованиеФайла	=	Ложь;
    
    Если ДиалогВыбораФайла.Выбрать() Тогда
    
    Элемент.Значение = ДиалогВыбораФайла.ПолноеИмяФайла;
    
    КонецЕсли;
    
    КонецПроцедуры // ИмяФайлаВыгрузкиНачалоВыбора()
    Процедура КнопкаВыполнитьНажатие(Элемент)
    
    Если ПустаяСтрока(ИмяФайлаВыгрузки) Тогда
    Предупреждение("Не указано имя файла для выгрузки данных");
    Возврат;
    КонецЕсли;
    
    Если Сформировать() = Ложь Тогда
    
    Предупреждение("Ошибка создания файла!
    |Указано пустое или неверное имя файла.");
    
    Иначе
    
    Вопрос("Выгрузка описания структуры конфигурации успешно завершена.",  РежимДиалогаВопрос.ОК, 10);
    
    КонецЕсли;
    
    КонецПроцедуры // КнопкаВыполнитьНажатие()
    
    
  2. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.548
    Симпатии:
    716
    Баллы:
    204
    файл экселевский нужно сохранять самим экселем. Код формирования книги эксель будет несколько отличатся.

    Т.е. нужно сделать примерно следующее:
    Эксель = Новый COMОбъект("Excel.Application");
    Книга = Эксель.WorkBooks().Add();
    Лист = Книга.Sheets().Add();
    Лист.Cells(1,1).Value = <Значение>;
    Книга.SaveAs(ИмяФайлаВыгрузки);
    Эксель.Quit();
  3. TopicStarter Overlay
    Korolev
    Offline

    Korolev Опытный в 1С

    Регистрация:
    20 апр 2010
    Сообщения:
    269
    Симпатии:
    0
    Баллы:
    26
    Я делал приблизительно так.
    Но Эксель.WorkBooks().Add() создает книгу, тем самым если человек захочет выгрузить данные в уже созданную - у него не получится..
  4. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.548
    Симпатии:
    716
    Баллы:
    204
    получится, если не добавлять книгу, а юзать
    Эксель.ActiveWorkBooks().Sheets.Add(), т.е. добавляем в существующую книгу лист.
  5. TopicStarter Overlay
    Korolev
    Offline

    Korolev Опытный в 1С

    Регистрация:
    20 апр 2010
    Сообщения:
    269
    Симпатии:
    0
    Баллы:
    26
    Так. Опять же получается, что у нас книга должна быть создана? (p.s. даже если будем делать так, и с тем учетом что файл создан, то у него уже 3 листа, а если они еще и пустые, а информация будет на 4м листе, то это будет немного странно).

    Просто я делал несколькими вариантами, в одном случае у меня создавалась книга, но не мог добавить уже в существующую, в другом наоборот. :) Вот хочется чтобы было все и сразу :)
  6. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.548
    Симпатии:
    716
    Баллы:
    204
    Насчет листов: Они выбираются либо по номеру(с 0 вроде бы), либо по названию.
    А книга не может быть не создана, если файл уже существует.
    Делаем файл - обязательно добавляем книгу и лист, иначе не проверял чего будет :)
  7. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.548
    Симпатии:
    716
    Баллы:
    204
    Проверил код на работоспособность:
    Эксель = Новый COMОбъект("Excel.Application");
    Книга = Эксель.WorkBooks().Add();
    Лист = Книга.Sheets(1);
    Лист.Cells(1,1).Value = "Тест";
    Книга.SaveAS("E:\test.xls");
    Книга.Close();
    Эксель.Quit();

    работает.
    Оказалось, что при добавлении книги, 3 листа создаются автоматом.
    Нумерация листов - с 1.
  8. Ger@_in
    Offline

    Ger@_in

    Регистрация:
    2 окт 2007
    Сообщения:
    19
    Симпатии:
    0
    Баллы:
    1
    Доброго времени суток, уважаемые коллеги :) Чтобы не плодить темы пишу здесь. Есть задача выгрузки большой ТЗ в excel. Код следующий:

    ФайлЕхсеl = ПолучитьCOMОбъект("", "Excel.Application");
    ФайлЕхсеl.Application.Visible = False;
    Книга = ФайлЕхсеl.WorkBooks.Open(ВыбИмя);
    Лист = ФайлЕхсеl.Sheets("РеестрПродаж");
    Для Стр = 0 По Таблица.Количество()-1 Цикл
    Для Кол = 0 по Таблица.Колонки.Количество()-1 Цикл
    Если ТипЗнч(Таблица.Получить(Стр).Получить(Кол)) <> тип("Число") Тогда
    Лист.Cells(Стр+2,Кол+1).Value = Строка(Таблица.Получить(Стр).Получить(Кол));
    Иначе
    Лист.Cells(Стр+2,Кол+1).Value = Таблица.Получить(Стр).Получить(Кол);
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;

    В приницпе все работает, но очень долго, порядка двух часов, необходимо оптимизировтаь. Сложность в том что "ВыбИмя" есть шаблон на первом листе которого данные, остальные листы это сводные таблицы по этим данным, данный шаблон в виде двоичных данных прикреплен к обработке. Есть ли какая то возможность, выгрузить данные через ADO в уже существующую таблицу???
  9. uza
    Offline

    uza 1С, VBA (EXCEL), VB (.NET + WEB)

    Регистрация:
    10 июл 2007
    Сообщения:
    1.845
    Симпатии:
    1
    Баллы:
    29
    nomad_irk
    3 листа - это по умолчанию, в экселе можно в настройках указать кол-во листов в новой книге.
    Так чта доверяй, но проверяй. Лучше самому добавить новый лист(ы) и поудалять все остальные (есть у объекта Sheets свойство или метод Count).
    И да, если у пользователя эксель будет английской - то листы будут именоваться не Лист1, Лист2... а Sheet1, Sheet2... (а ежли эксель китайской или еще какой?)
    Поэтому обращение либо по номеру листа (по умолчанию счет ведется с 1), либо, если создаете листы сами - то и присваивать им имя. Но к Вам это не
    относиться (я смотрю вы и так обращаетесь по номеру)

    Лист = Книга.Sheets(1); можно заменить на конструкцию Лист = Книга.Sheets.Add();

    Ger@_in - можно, покурите меню экселя Данные/Импорт внешних данных. Только вот незадача, 1С нет как драйвера БД. И отчет, перед импортом
    данных надо сейвить как эксель, например.
    Еще вариант, в самом экселе написать код (макрос типа) по подключению к 1С как ADO, выполнению запроса 1С и выковыривания данных.
    Но все это IMHO гемор.

    Оптимизация (визуальная)

    1) Эксель не надо делать анвизибл (Visible = False True) и при обходе "подсвечивать" строки напрмер так Лист.Rows(Стр+2).Select(); -
    работать станет чуть медленее, зато у юзвера что то будет бегать на экране (это успокаивает пользователя... да и программера тоже)

    2) Отключите автовычисления экселю на момент обработки и включите по окончании и выполните "принудительный" расчет.

    3) Эксель, каждый раз когда вы вносите строку в него перестраивает сводные таблицы - и это дает особые тормоза.
    Кажется это он делает независимо от вкл/выкл автовычислений - если это так (проверить легко, удалите сводные таблицы
    и засеките время записи первых 100 - 300 строк с сводныими и без них). Если разница на 100 проверочных строках с сводными таблицами
    и без них существенна - то используйте следующий финт:
    3.1) Создайте/откройте чистую книгу
    3.2) Данные вносите в чистую книгу (не связанную со сводными таблицами)
    3.3) Откройте книгу со сводными табами
    3.4) Из чистой книги скопируйте лист (все ячейки листа) и вставьте в лист книги со сводными таблицами - таким образом перестройка сводных таблиц будет
    выполненна ОДИН раз сразу по всему массиву данных.
  10. uza
    Offline

    uza 1С, VBA (EXCEL), VB (.NET + WEB)

    Регистрация:
    10 июл 2007
    Сообщения:
    1.845
    Симпатии:
    1
    Баллы:
    29
    Да.
    2 - если на листе, куда вносятся данные есть вычисляемые поля
    Набор нужных методов экселя
    1) Книга.Application.Calculation = xlManual //xlManual = -4135 - отключение автовычислений
    2) ЧистыйЛист = Книга.Sheets.Add() - добавление новго листа, не связанного со сводными таблицами (не надо создавать чистую книгу)
    3) ЧистыйЛист.Cells.Select() - выделение ВСЕГО листа (происходит, когда пользователь тыкает в ячейку 0,0 (левый верхний угол)
    4) Книга.Selection.Copy - копирование выделенного в буфер
    5) Книга.Sheets(ИмяИлиНомерЛистаСвязанногоСоСводными).Select - переключение на лист, связанный со сводными таблицами
    6) Книга.Sheets(ИмяИлиНомерЛистаСвязанногоСоСводными).Cells.Select - снова выделение всего листа
    7) ActiveSheet.Paste - вставка того, что скопировали (4) в лист, связанный со сводными таблицами
    8) Книга.Application.Calculation = xlAutomatic - включение автовычислений (xlAutomatic = -4105)
    9) Книга.Calculate - принудительный приказ экселю пересчитать все формулы.

    10) ну и да, не забудьте после всего удалить созданный (2) лист - дабы не плодить "чистюль"
  11. Ger@_in
    Offline

    Ger@_in

    Регистрация:
    2 окт 2007
    Сообщения:
    19
    Симпатии:
    0
    Баллы:
    1
    uza Спасибо. Данная обработка запускается ночью, как регламентированное задание. Не замечал, что бы сводные таблицы обновлялись. Все таки по всей видимости здесь имеют место проблемы с производительностью и загруженностью сервера, так в терминале на центральной базе обработка выполняется 2 часа, на копии этой базы но не рабочей уже 25 минут. Обе базы крутятся на SQL. Именно поэтому хотелось пропробовать координально другой метод.

    Что то вроде этого:

    СтрокаПодключения = "
    |Provider=Microsoft.Jet.OLEDB.4.0;
    |Data Source="+ВыбИмя+";
    |Extended Properties=""Excel 8.0;HDR=No;"";";

    // Создаем объект ADOX.Catalog
    Catalog = Новый COMОбъект("ADOX.Catalog");
    Catalog.ActiveConnection = СтрокаПодключения;

    Table = Новый COMОбъект("ADOX.Table");
    Table.Name = "Table";
    Table.Columns.Append("Колонка1");
    Table.Columns.Append("Колонка2");
    Table.Columns.Append("КолонкаN");

    // Присоединяем таблицу
    Catalog.Tables.Append(Table);
    Table = Неопределено;
    Catalog = Неопределено;

    // Создаем соединение
    Connection = Новый COMОбъект("ADODB.Connection");
    Connection.Open(СтрокаПодключения);
    Command = Новый COMОбъект("ADODB.Command");
    Command.ActiveConnection = Connection;
    Command.CommandType = 1;

    Для Стр = 0 По Таблица.Количество()-1 Цикл
    Command.CommandText = "
    |INSERT INTO [Table] VALUES (";
    Для Кол = 0 по Таблица.Колонки.Количество()-1 Цикл
    Command.CommandText = Command.CommandText + "'"+Строка(Таблица.Получить(0).Получить(Кол))+"'"+?(Кол <> Таблица.Колонки.Количество()-1,",","");
    КонецЦикла;
    Command.CommandText = Command.CommandText + ")";
    Command.Execute();
    КонецЦикла;

    //Закрываем соединение
    Command = Неопределено;
    Connection.Close();
    Connection = Неопределено;

    Данный алгоритм добавляет в наш шаблон новый лист и благополучно за считанный секунды выгружает туда данные. Не могу понять, как выгрузить данные на уже существующий лист шаблона. А так же возможно ли задать типы колонок, по умолчанию все колонки со строковым типом.
  12. uza
    Offline

    uza 1С, VBA (EXCEL), VB (.NET + WEB)

    Регистрация:
    10 июл 2007
    Сообщения:
    1.845
    Симпатии:
    1
    Баллы:
    29
    Типы колонок задать можно - попробуй в екселе начать запись, указать руками тип колонки, оставноить запись - смотрим получившийся код.

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

    Сервер то наверное пошустрее чем рабочая станция - так что наверное вопрос не загрузки сервера. Возможно, проблема в терминале (ексель не видимый, но ведь обновляется). Проверить этот момент.
    Если сервер 64х разрядный, а ексель(офис) 32х разрядый - то поставьте 64х разрядный ексель.

    Иных причин вроде не вижу. И да, совсем забыл, что можно из 1С подцепиться к екселю как к БД.
  13. full_lamer
    Offline

    full_lamer Опытный в 1С

    Регистрация:
    15 авг 2006
    Сообщения:
    97
    Симпатии:
    0
    Баллы:
    26
    Вопрос почти в продолжение темы.
    А можно ли созданный "ТабличныйДокумент" программно выгрузить в лист Excel.

    То есть.
    Создал я аппликацию Excel;
    Создал новую книгу;
    Создал новый лист (1);
    Создал я (из макетов) ТабличныйДокумент (2);

    И вот как этот ТабличныйДокумент (2) загрузить (со всеми форматами) в ранее созданый лист (1)?

    P.S. То что можно написать обработку по ячейкового переноса - это я знаю, и то что можно писать отчет сразу в лист Excel - это я тоже знаю. А как нибудь быстро и просто?
  14. UnNone
    Offline

    UnNone Опытный в 1С

    Регистрация:
    21 мар 2007
    Сообщения:
    148
    Симпатии:
    0
    Баллы:
    26
    Код:
    ТабДок.Записать(<имя файла>,типфайлатабличногодокумента.XLS);
    
    Сохраняет табличный документ в указанный документ excel.
  15. full_lamer
    Offline

    full_lamer Опытный в 1С

    Регистрация:
    15 авг 2006
    Сообщения:
    97
    Симпатии:
    0
    Баллы:
    26
    Это я итак знаю. А как например записать несколько табличных документов в отдельные листы в одном файле?
  16. UnNone
    Offline

    UnNone Опытный в 1С

    Регистрация:
    21 мар 2007
    Сообщения:
    148
    Симпатии:
    0
    Баллы:
    26
    Как вариант сохранять оба табличных документа и копировать листы. Вот тут парень игрался с сохранением и копированием и вроде, как пишет, получилось(у меня на быструю руку не получилось, загвоздка в правильном использовании команды copy). Дерзайте. Получится тут поделитесь. :)
  17. full_lamer
    Offline

    full_lamer Опытный в 1С

    Регистрация:
    15 авг 2006
    Сообщения:
    97
    Симпатии:
    0
    Баллы:
    26
    Товарищи, у меня вроде бы получилось.

    ПечатьКонтейнер - табличный документ с уже созданным отчетом.
    Почему-то символ слеша (косая честа) не отображается.
    Единственное что придется делать - это нажимать "Да" - если потребуется перезаписать уже существующий результирующий документ Excel. Как это обойти я пока не знаю...

    Код:
    ПечатьКонтейнер.Область (1, 1).Текст = "1";
    ПечатьКонтейнер.Записать ("c:file1.xls", ТипФайлаТабличногоДокумента.XLS);
    ПечатьКонтейнер.Область (1, 1).Текст = "2";
    ПечатьКонтейнер.Записать ("c:file2.xls", ТипФайлаТабличногоДокумента.XLS);
    ПечатьКонтейнер.Область (1, 1).Текст = "3";
    ПечатьКонтейнер.Записать ("c:file3.xls", ТипФайлаТабличногоДокумента.XLS);
    
    AppExcel1    = новый COMОбъект ("Excel.Application");
    
    Book2        = AppExcel1.WorkBooks().Add();
    
    Book1        = AppExcel1.Workbooks.Open ("c:file1.xls");
    Book1.ActiveSheet.Cells.Select ();
    AppExcel1.Selection.Copy ();
    Book2.Sheets.Add ();
    Book2.ActiveSheet.Paste ();
    AppExcel1.CutCopyMode = False;
    Book1.Close (false);
    
    Book1        = AppExcel1.Workbooks.Open ("c:file2.xls");
    Book1.ActiveSheet.Cells.Select ();
    AppExcel1.Selection.Copy ();
    Book2.Sheets.Add ();
    Book2.ActiveSheet.Paste ();
    AppExcel1.CutCopyMode = False;
    Book1.Close (false);
    
    Book1        = AppExcel1.Workbooks.Open ("c:file3.xls");
    Book1.ActiveSheet.Cells.Select ();
    AppExcel1.Selection.Copy ();
    Book2.Sheets.Add ();
    Book2.ActiveSheet.Paste ();
    AppExcel1.CutCopyMode = False;
    Book1.Close (false);
    
    Book2.SaveAs ("c:file0.xls");
    
    AppExcel1.Quit ();
    
    
    
  18. privet20044
    Offline

    privet20044

    Регистрация:
    13 дек 2010
    Сообщения:
    5
    Симпатии:
    0
    Баллы:
    1
    Спасибо!!! С некоторыми доработками все здорово работает
  19. Kossstya
    Offline

    Kossstya

    Регистрация:
    4 дек 2007
    Сообщения:
    13
    Симпатии:
    0
    Баллы:
    1
    А как сделать, чтоб группировки в файлах сохранялись?

Поделиться этой страницей