Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: 1С 8: Работаем с файлами MS Excel используя OpenOffice/LibreOffice
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > База знаний > Не наши статьи > 1С:Предприятие 8.2
Vofka
Работа через COM с фйлами MS Excel используя OpenOffice/LibreOffice.

Есть ситуации, когда нет возможности установить Excel на стороне клиента, а нужно загружать в базу данные *.xls файлов. Спасением является бесплатный OpenOffice (либо LibreOffice, т.к. работа через COM с ними абсолютно одинакова).

Ниже привожу процедуры загрузки и выгрузки.

Функция ЗагрузитьТЗизФайла(ПутьКФайлу)

       //OpenOffice Calc//////////////////////////////////////////////////////////////////////////////////////////////
       Попытка
                ServiceManager = Новый COMОбъект("com.sun.star.ServiceManager");
       Исключение
                Предупреждение(ОписаниеОшибки() + Символы.ПС + "программа OpenOffice\LibreOffice не установлена на данном компьютере!");
       Возврат Неопределено;
       КонецПопытки;
       Desktop = ServiceManager.createInstance("com.sun.star.frame.Desktop");
       Свойства = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
       Свойства.Name = "AsTemplate";
       Свойства.Value = Истина;
       Args = Новый COMSafeArray("VT_VARIANT", 2);
       Args.SetValue(0, Свойства);
       Свойства1 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
       Свойства1.Name = "Hidden";
       Свойства1.Value = Истина;
       Args.SetValue(1,Свойства1);
       Document = Desktop.LoadComponentFromURL(ПривестиФайлКУРЛ(ПутьКФайлу), "_blank", 0, Args);
       Sheets = Document.getSheets();
       Sheet = Sheets.getByIndex(текЛист-1);
       локТабЗнач = Новый ТаблицаЗначений;
       begCol = 0;
       begRow = 0;
       endCol = Sheet.Data.GetLength(6) - 1;
       endRow = Sheet.Data.GetLength() - 1;
       нКол = 0;
       локТабЗнач.Колонки.Очистить();

       КС = Новый КвалификаторыСтроки(50);
       Массив = Новый Массив;
       Массив.Добавить(Тип("Строка"));

       ОписаниеТиповСтрока = Новый ОписаниеТипов(Массив, , КС);

       Пока нКол <= endCol Цикл
            ИмяКол = "К"+Строка(нкол+1);
            локТабЗнач.Колонки.Добавить(ИмяКол,ОписаниеТиповСтрока);
            нКол = нКол + 1;
       КонецЦикла;
       Range = Sheet.getCellRangeByPosition(begCol, begRow, endCol, endRow);
       МассивКом = Новый COMSafeArray("VT_VARIANT", Range.Columns.Count, Range.Rows.Count);
       МассивКом = Range.getDataArray();
       тмпПростойМассив = МассивКом.Выгрузить();
       Для каждого массив из тмпПростойМассив Цикл
             ит = 0;
             НовСтрока = локТабЗНач.Добавить();
             Для каждого ЭлементМассива из массив цикл
                   НовСтрока[ит] = ЭлементМассива;
                   ит = ит + 1;
             КонецЦикла;
       КонецЦикла;
       Возврат локТабЗнач;

КонецФункции


Как видно из функции ЗагрузитьТЗизФайла - читается сразу вся область данных файла, поэтому с быстродействием все отлично. На выходе имеем готовую таблицу значений. В данном случае каждой колонке опреден тип Строка(50), но можна этого и не делать, просто это нужно если собираетесь, например, помещать ее во временную таблицу.

Процедура ВыгрузитьТЗвФайл(ТаблицаРезультата)

    //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 = Истина;
    Args = Новый COMSafeArray("VT_VARIANT", 3);
    Args.SetValue(0, Свойства);
    Свойства1 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
    Свойства1.Name = "Hidden";
    Свойства1.Value = Истина;
    Args.SetValue(1, Свойства1);
    Document = Desktop.LoadComponentFromURL("private:factory/scalc", "_blank", 0, Args);
    Sheets = Document.getSheets();
    Sheet = Sheets.getByIndex(0);
    мИтКол = 0;
    Для каждого кол из ТаблицаРезультата.Колонки Цикл
        Sheet.getCellByPosition(мИтКол,0).setString(кол.Имя);
        мИтКол = мИтКол + 1;
    КонецЦикла
    
    ВсегоСтрок = ТаблицаРезультата.Количество();
    ВсегоКолонок = ТаблицаРезультата.Колонки.Количество();
    МассивКОМ = Новый COMSafeArray("VT_VARIANT", ВсегоСтрок,ВсегоКолонок);
    иткол = 0;
    итстр = 0;

    Для каждого стр из ТаблицаРезультата Цикл
        Для каждого кол из ТаблицаРезультата.Колонки Цикл
            стрРез = СокрЛП(стр[кол.Имя]);
            МассивКОМ.SetValue(итстр,иткол,стрРез);
            иткол = иткол+1;
         КонецЦикла;
        иткол = 0;
        итстр = ?(итстр=ВсегоСтрок,0,итстр+1);
    КонецЦикла;
    begCol = 0;
    begRow = 1;
    endCol = ВсегоКолонок-1;
    endRow = ВсегоСтрок;
    Range = Sheet.getCellRangeByPosition(begCol, begRow, endCol, endRow);
    Range.setDataArray(МассивКОМ);
    //Document.storeToURL(ПривестиФайлКУРЛ(ПутьКФайлу),Args);
    Свойства2 = ServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue");
    Свойства2.Name = "FilterName";
    Свойства2.Value = "MS Excel 97";
    Args.SetValue(2,Свойства2);
    Document.GetCurrentController().GetFrame().GetContainerWindow().SetVisible(Истина);
    //Document.storeToURL(ПривестиФайлКУРЛ(ФайлКартотеки),Args);

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


Процедура ВыгрузитьТЗвФайл сохраняет любую таблицу значений в файл MS Excel. В текущем примере откроется OpenOffice/LibreOffice Calc c данными переданной таблицы значений. Если раскомментировать строки:

//Document.storeToURL(ПривестиФайлКУРЛ(ПутьКФайлу),Args);

...................................................

//Document.storeToURL(ПривестиФайлКУРЛ(ФайлКартотеки),Args);


и закомментировать

Document.GetCurrentController().GetFrame().GetContainerWindow().SetVisible(Истина);


при этом добавив Параметр ПутьКФайлу, то данные запишутся в файл без открытия Calc`a. Если обратить внимание на сохранение, то сразу бросается двойной вызов Document.storeToURL - это необходимо для корректного сохранения в формате MS Excel.

функция ПривестиФайлКУРЛ(ПутьКФайлу)

    ПутьКФайлу = СтрЗаменить(ПутьКФайлу," ","%20");
    ПутьКФайлу = СтрЗаменить(ПутьКФайлу,"\","/");
    Возврат "file:/" + "/localhost/" + ПутьКФайлу;

Конецфункции


Функция ПривестиФайлКУРЛ просто приводит путь к виду, необходимому OpenOffice/LibreOffice.

Вот и все. Как вы смогли убедиться - работа с Calc`ом не сложнее таковой с Microsoft Excel.

необходимо зарегистрироваться для просмотра ссылки
alex_shkut
Спасибо, эта публикация как раз помогла. Но только приведенный пример имеет ошибку.
Функция ЗагрузитьТЗизФайла(ПутьКФайлу,текЛист)

и в тело функции добавить проверку на превышение количества листов в книге Эксель.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.