1С 8.x Как в одну книгу объединить несколько файлов .xls?

Автор Ryan, 6 октября 2011, 15:45

0 Пользователи и 1 гость просматривают эту тему.

Ryan

В 1С8 формируется отчет который содержит более 65536 записей,
при записи в .xls, он ругается, поэтому нужно записать его по частям.
вопрос:
Как в одну книгу объединить несколько файлов, соответственно на каждый лист?

JohnSUN

Для начала одно уточнение: после объединения сохранять будем в xls? Или все-таки в "родном" формате? И если в "родном", то в чьем родном - 1С или OOo (LO)?
Просто существует несколько решений и от ответа про формат хранения зависит выбор варианта решения...
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Ryan


JohnSUN

#3
Жаль. У Calc'а высота листа в 16 раз больше... Глядишь, отчет целиком и поместился бы...

Тогда еще раз о задаче.
Несколько раз запускаем один и тот же отчет, зажав параметрами количество результирующих строк. Ну, как бы составные части общего отчета... Каждый из них сохраняем на диск со своим именем и расширением .xls. Требуется способ соединить все эти листы в одну книгу. Так?

Ну, для такой задачи самый простой способ решения - Вставка - Лист из файла...

PS. На всякий случай еще уточнение: в сторону этой программы не смотрели? Распространяется бесплатно, к размерам файлов вроде бы (!) не придирается.
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Ryan

Да так,
отчет будет автоматически формироваться и сохранятся по частям в xls (это не проблема),

объем данных большой и отчет используется часто,
поэтому возник вопрос о том как программно делать вставку, если возможно

(та программа проблему не решает, там не поддерживается формат .xls, постоянно придется переключатся с одной программы на другую)

JohnSUN

Цитата: Ryan от  6 октября 2011, 17:02
отчет будет автоматически формироваться и сохранятся по частям в xls (это не проблема),
О! Так у вас есть возможность ковырять конфигурацию? Тогда ни Calc, ни бэйсик не понадобятся!

// Процедура копирует первый лист из книги ПутьИмяЛиста
// в книгу ПутьИмяКнигиОтчетов и присваивает этому листу имя НовоеИмяЛиста.
// Если книги ПутьИмяКнигиОтчетов еще нет - она создается
// Если в книге ПутьИмяКнигиОтчетов уже есть лист с именем НовоеИмяЛиста - он заменяется на новый
Процедура ПеренестиОтчетВКнигуExcel(ПутьИмяКнигиОтчетов, ПутьИмяЛиста, НовоеИмяЛиста) Экспорт
// Дотянуться до Экселя
Попытка
Эксель = СоздатьОбъект("Excel.Application");
Исключение
Предупреждение("У Вас на компьютере не установлен Microsoft Excel. Импорт невозможен!");
Возврат;
КонецПопытки;
// Сам Эксель невидимый
Эксель.Visible = 0;   
// И лишних вопросов задавать не должен
Эксель.DisplayAlerts = 0;
// Получить книгу из параметра ПутьИмяКнигиОтчетов
Попытка                         
КнигаОтчетов = Эксель.Workbooks.Open(ПутьИмяКнигиОтчетов);
Исключение
КнигаОтчетов = Эксель.Workbooks.Add;
КнигаОтчетов.SaveAs(ПутьИмяКнигиОтчетов);
КонецПопытки;
// Получить книгу из параметра ПутьИмяЛиста
Попытка                         
ЛистОтчета = Эксель.Workbooks.Open(ПутьИмяЛиста);
Исключение
Предупреждение("Не найден файл "+ПутьИмяЛиста+"!");
Эксель = 0;
Возврат;
КонецПопытки;
// Попробовать удалить отчет НовоеИмяЛиста из книги, если он уже есть
Попытка                         
КнигаОтчетов.Worksheets(НовоеИмяЛиста).Delete();
Исключение
КонецПопытки; 
// Скопировать лист из ЛистОтчета в КнигаОтчетов:
ЛистОтчета.Worksheets(1).Name = НовоеИмяЛиста;
ЛистОтчета.Worksheets(1).Copy(КнигаОтчетов.Worksheets(1));
ЛистОтчета.Close(0);
КнигаОтчетов.Save();
КнигаОтчетов.Close(-1);
Эксель = 0;
КонецПроцедуры

Это, вообще-то, 7.7... Но должно сработать в любой из "восьмёрок" с минимальными правками... После формирования каждого из промежуточных листов, вызываем ПеренестиОтчетВКнигуExcel() и всё...
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Ryan

на компьютерах используется только OpenOffice,
т.е этот код не будет работать

RFJ

Цитата: Ryan от  6 октября 2011, 14:45Как в одну книгу объединить несколько файлов, соответственно на каждый лист?
Вопрос элементарный.
Не понимаю, в чем проблема?

Ryan


RFJ

Как программно скопировать листы из нескольких файлов в один файл на разные листы?

JohnSUN

Беда!.. (с) доктор Быков

Ну, тогда значит берем этот заведомо неработающий код, скрещиваем его с кодом smaharbA из темы Работа ООо с адинес... Убеждаемся, что Calc можно запустить...
Потом придумываем, на что заменить строчку "ЛистОтчета.Worksheets(1).Copy(КнигаОтчетов.Worksheets(1));", чтобы Calc её понял... То ли диспетчер вызывать (у Питоньяка такой код со ссылкой на Stephan Wunderlich приведен), то ли создавать лист и просто копировать данные (у того же Питоньяка это код от Oliver Brinzing)...
И отлаживаем...

Ну, или макрорекордером записываем последовательность действий по вставке одного листа и зацикливаем для всех имеющихся исходных листов...
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Ryan


Ryan

тема закрыта, рабочий код для 1С8:
Процедура ОбъединитьФайлыXLS()
ПутьКФайлу = "D:\";
КоличествоЛистов = 4;
//OpenOffice Calc///////////////////////////////////////////////////////////////////////////
Попытка
ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
Исключение
Предупреждение(ОписаниеОшибки() + Символы.ПС + "программа OpenOffice не установлена на данном компьютере!");
Возврат;
КонецПопытки;
Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");
Свойства = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
Свойства.Name = "AsTemplate";
Свойства.Value = Истина;
Массив = Новый COMSafeArray("VT_VARIANT", 3);
Массив.SetValue(0, Свойства);
Свойства1 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
Свойства1.Name = "Hidden";
Свойства1.Value = Истина;
Массив.SetValue(1, Свойства1);
Документ = Desktop.LoadComponentFromURL("private:factory/scalc", "_blank", 0, Массив);
БазКнига = Документ.getSheets();

Документ.lockControllers();
Документ.addActionLock();

ПутьКФайлу = ПривестиФайлКУРЛ(ПутьКФайлу);

НомерПоследнегоЛиста = БазКнига.getCount();

Для Сч = 1 по КоличествоЛистов Цикл                                                   
Попытка   
ДокументКопия = DeskTop.LoadComponentFromURL(ПутьКФайлу + Строка(Сч) + ".xls", "_blank", 0, Массив);
КнигаКопия = ДокументКопия.getSheets();
Исключение
Продолжить;
КонецПопытки;

ЛистКопия = КнигаКопия.getByIndex(0);

Если Сч > НомерПоследнегоЛиста Тогда
БазКнига.InsertNewByName("Лист" + Строка(Сч), БазКнига.getCount());
КонецЕсли;

БазЛист = БазКнига.getByName("Лист" + Строка(Сч));

ДокументКопия.getCurrentController().Select(ЛистКопия); 
dispatchURL(ДокументКопия, ".uno:SelectAll", ServiceManager);
dispatchURL(ДокументКопия, ".uno:Copy", ServiceManager);

Документ.getCurrentController().Select(БазЛист);
dispatchURL(Документ, ".uno:Paste", ServiceManager);

ДокументКопия.Close(-1);
КонецЦикла;


Свойства2 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
Свойства2.Name = "FilterName";
Свойства2.Value = "MS Excel 97";
Массив.SetValue(2, Свойства2);
Документ.storeToURL(ПутьКФайлу + "Отчет.xls", Массив);

Документ.unLockControllers();
Документ.removeActionLock();

Документ.close(-1);


Сообщить("Отчет сохранен - " + ПутьКФайлу + "Отчет.xls");   

Документ = "";
ДокументКопия = "";
КонецПроцедуры

Procedure dispatchURL(Docum, aUrl, ServiceManager)
noProps = Новый COMSafeArray("VT_VARIANT", 0);
frame = Docum.getCurrentController().getFrame();
oDisp = ServiceManager.CreateInstance("com.sun.star.frame.DispatchHelper");
oDisp.executeDispatch(frame,aUrl, "", 0, noProps);
EndProcedure

функция ПривестиФайлКУРЛ(ПутьКФайлу)
    ПутьКФайлу = СтрЗаменить(ПутьКФайлу," ","%20");
    ПутьКФайлу = СтрЗаменить(ПутьКФайлу,"\","/");
    Возврат "file:///" + ПутьКФайлу;
Конецфункции


Ryan

еще напоследок, код который копирует не только данные и формат, но и структуру:


Процедура ОбъединитьФайлыXLS()
ПутьКФайлу = "D:\";
ТабДок = Новый ТабличныйДокумент;
ТабДок.Записать(ПутьКФайлу + "Отчет.xls", ТипФайлаТабличногоДокумента.XLS);
КоличествоЛистов = 4;
Попытка
ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
Исключение
Предупреждение(ОписаниеОшибки() + Символы.ПС + "программа OpenOffice не установлена на данном компьютере!");
Возврат;
КонецПопытки;
Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");

Свойства = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
Массив = Новый COMSafeArray("VT_VARIANT", 1);

ПутьКФайлу = ПривестиФайлКУРЛ(ПутьКФайлу);

Документ = DeskTop.LoadComponentFromURL(ПутьКФайлу + "Отчет.xls", "_blank", 0, Массив);

Для Сч = 1 по КоличествоЛистов Цикл                                                   
Попытка   
ДокументКопия = DeskTop.LoadComponentFromURL(ПутьКФайлу + Строка(Сч) + ".xls", "_blank", 0, Массив);
Исключение
Продолжить;
КонецПопытки;
currentFrame = ДокументКопия.getCurrentController().getFrame();
Переместить("Отчет", currentFrame, ServiceManager);
ДокументКопия.Close(-1);
КонецЦикла;

Книга = Документ.getSheets();
Книга.removeByName(Книга.getByIndex(0).getName());
Документ.store();
Документ.close(-1);


Сообщить("Отчет сохранен - " + ПутьКФайлу + "Отчет.xls");   

Документ = "";
ДокументКопия = "";
КонецПроцедуры

Процедура Переместить(ИмяФайла, currentFrame, ServiceManager)
МассивToJump = Новый COMSafeArray("VT_VARIANT", 1);
СвойстваToJump = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
СвойстваToJump.Name = "Nr";
СвойстваToJump.Value = 1;
МассивToJump.SetValue(0, СвойстваToJump);

МассивToCopy  = Новый COMSafeArray("VT_VARIANT", 3);
СвойстваToCopy1 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
СвойстваToCopy1.Name = "DocName";
СвойстваToCopy1.Value = ИмяФайла;
СвойстваToCopy2 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
СвойстваToCopy2.Name = "Index";
СвойстваToCopy2.Value = 32767;
СвойстваToCopy3 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
СвойстваToCopy3.Name = "Copy";
СвойстваToCopy3.Value = true;
МассивToCopy.SetValue(0, СвойстваToCopy1);
МассивToCopy.SetValue(1, СвойстваToCopy2);
МассивToCopy.SetValue(2, СвойстваToCopy3);

dispatcher = ServiceManager.CreateInstance("com.sun.star.frame.DispatchHelper");
dispatcher.executeDispatch(currentFrame, ".uno:JumpToTable", "", 0, МассивToJump);
dispatcher.executeDispatch(currentFrame, ".uno:Move", "", 0, МассивToCopy);
КонецПроцедуры


функция ПривестиФайлКУРЛ(ПутьКФайлу)
    ПутьКФайлу = СтрЗаменить(ПутьКФайлу," ","%20");
    ПутьКФайлу = СтрЗаменить(ПутьКФайлу,"\","/");
    Возврат "file:///" + ПутьКФайлу;
Конецфункции


JohnSUN

Тоже красиво... Только, мне кажется, стоит диспетчер создать еще до цикла по документам и передавать в Переместить не сервис-менеджер, а сразу диспетчер. Так же как и МассивToCopy стоило бы создать один раз, а потом менять только ИмяФайла.

Мигание окон не раздражает? Не пробовал Hidden=True?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне