Pull to refresh

Автоматизация OpenOffice: Окончание

C++ *
Продолжение первой части статьи.

OpenOffice Win C++

2. Повторное использование DLL в своей программе


Возможности:
  • открытие XLS файла,
  • открытие файлов OpenOffice
  • возможность открытия в скрытом режиме
  • чтение данных из электронной таблицы
  • полный спектр манипуляции с данными: вставка текста, числа, форматирование, объединение ячеек, установка границ, установка ширина столбца
  • выгрузка xls таблицы на диск
  • возмоность работы под WINE, при условий установки OpenOffice под Wine
  • использование формул
  • генерация версионно зависимого RDB файла налету (при необходимости)

На работе мы используем C++ Builder для написания внутренних программ, так что я делаю еще одну обертку над DLL для удобной работы с API.


//ooapi3.h
#ifndef ooapi3H
#define ooapi3H

#include <windows.h>
#include <vcl.h>
#include "StrUtils.hpp"

class OOAPI3 {
   private:
      HANDLE hLib;
      
   protected:
      //указатели на функции
      bool (*ooConect)(const char *, bool);
      void (*ooDisconect)();
      bool (*ooSelectSheet)(short);
      void (*ooSetVal)(int, int, double);
      void (*ooSetFormula)(int, int, const wchar_t *);
      bool (*ooSetBold)(int, int);
      bool (*ooSetFontColor)(int, int, int, int, int);
      bool (*ooSetBgColor)(int, int, int, int, int);
      bool (*ooSetFontSize)(int, int, short);
      bool (*ooSetItalic)(int, int);
      bool (*ooSetHoriz)(int, int, short);
      bool (*ooSetBorders)(int, int, bool, bool, bool, bool, short, short, short);
      bool (*ooSetColWidth)(int, long);
      bool (*ooMergeRange)(const char *);
      bool (*ooExportToUrl)(const wchar_t *);
      double   (*ooGetVal)(int, int);
      wchar_t* (*ooGetText)(int, int);
      bool (*ooIsInstall)();
      bool (*ooIsWin)();

   public:
        __fastcall OOAPI3();
        __fastcall ~OOAPI3();

        bool __fastcall connect(const char* file, bool hidden = false);
        bool __fastcall setSheet(short sheet);
        void __fastcall setVal(int x, int y, double val);
        void __fastcall setText(int x, int y,  AnsiString val);
        bool __fastcall setBold(int x, int y);
        bool __fastcall setItalic(int x, int y);
        bool __fastcall setFontColor(int x, int y, int r, int g, int b);
        bool __fastcall setBgColor(int x, int y, int r, int g, int b);
        bool __fastcall setFontSize(int x, int y, short size);
        bool __fastcall setHoriz(int x, int y, short horiz);
        bool __fastcall setBorders(int x, int y, bool l, bool t, bool r, bool d, short rd, short gr, short bl);
        bool __fastcall setBorders(int x, int y, bool l, bool t, bool r, bool d);
        bool __fastcall setBorders(int x, int y);
        bool __fastcall setColWidth(int col, long mm);
        bool __fastcall mergeRange(AnsiString from, AnsiString to);
        bool __fastcall mergeRange(int x1, int y1, int x2, int y2);
        bool __fastcall export2XLS(AnsiString to);
        double     __fastcall getVal(int x, int y);
        AnsiString __fastcall getText(int x, int y);
        bool __fastcall isWin();
        bool __fastcall isInstall();
        AnsiString __fastcall getColNameById(int id);
};


#endif



//ooapi3.cpp
#include "ooapi3.h"

__fastcall OOAPI3::OOAPI3() {
  //подгружаем модуль
  HMODULE hLib = LoadLibrary("ooapi3.dll");
  if(hLib == NULL) {
        throw;
  }

  //загрузим указатели на функции разом
  (FARPROC &)ooConect           = GetProcAddress(hLib, "connect");
  (FARPROC &)ooDisconect        = GetProcAddress(hLib, "disconnect");
  (FARPROC &)ooSelectSheet      = GetProcAddress(hLib, "selectSheet");
  (FARPROC &)ooSetVal           = GetProcAddress(hLib, "setVal");
  (FARPROC &)ooSetFormula       = GetProcAddress(hLib, "setText");
  (FARPROC &)ooSetBold          = GetProcAddress(hLib, "setBold");
  (FARPROC &)ooSetFontColor     = GetProcAddress(hLib, "setFontColor");
  (FARPROC &)ooSetBgColor       = GetProcAddress(hLib, "setBgColor");
  (FARPROC &)ooSetFontSize      = GetProcAddress(hLib, "setFontSize");
  (FARPROC &)ooSetItalic        = GetProcAddress(hLib, "setItalic");
  (FARPROC &)ooSetHoriz         = GetProcAddress(hLib, "setHoriz");
  (FARPROC &)ooSetBorders       = GetProcAddress(hLib, "setBorders");
  (FARPROC &)ooSetColWidth      = GetProcAddress(hLib, "setColWidth");
  (FARPROC &)ooMergeRange       = GetProcAddress(hLib, "mergeRange");
  (FARPROC &)ooExportToUrl      = GetProcAddress(hLib, "exportToUrl");
  (FARPROC &)ooGetVal           = GetProcAddress(hLib, "getVal");
  (FARPROC &)ooGetText          = GetProcAddress(hLib, "getText");
  (FARPROC &)ooIsWin            = GetProcAddress(hLib, "isWin");
  (FARPROC &)ooIsInstall        = GetProcAddress(hLib, "isInstall");
}

//создание нового или открытие существующего файла
//hidden - открыть(создать) файл скрытым
bool __fastcall OOAPI3::connect(const char* file, bool hidden) {
  // private:factory/scalc - создает новый excel документ
  //или
  // file:///путь до файла

  //hidden: скрыть офис можно при экспорте данных из файла
  
  return ooConect(file, hidden);
}

//выбор листа книги
bool __fastcall OOAPI3::setSheet(short sheet) {
  return ooSelectSheet(sheet);
}

//установка числового значения для ячейки
void __fastcall OOAPI3::setVal(int x, int y, double val) {
  ooSetVal(x, y, val);
}

//установка текста или формулы для ячейки
void __fastcall OOAPI3::setText(int x, int y,  AnsiString val) {
  //конвертация в unicode
  int iSize = val.WideCharBufSize();
  wchar_t *uval = new wchar_t[iSize];
  val.WideChar(uval, iSize);
  ooSetFormula(x, y, uval);
  delete[] uval;
}

//делает жирным текст в ячейке
bool __fastcall OOAPI3::setBold(int x, int y) {
  return ooSetBold(x, y);
}

//курсив
bool __fastcall OOAPI3::setItalic(int x, int y) {
  return ooSetItalic(x, y);
}

//установка цвета для шрифта
bool __fastcall OOAPI3::setFontColor(int x, int y, int r, int g, int b) {
  //TODO: возможно нужны проверки на > 0, < 255
  return ooSetFontColor(x, y, r, g, b);
}

//установка цвета фона
bool __fastcall OOAPI3::setBgColor(int x, int y, int r, int g, int b) {
  return ooSetBgColor(x, y, r, g, b);
}

//установка размера шрифта
bool __fastcall OOAPI3::setFontSize(int x, int y, short size) {
  return ooSetFontSize(x, y, size);
}

//горизонтальная ориентация текста
//1 - лево, 2 - центр, 3 - право
bool __fastcall OOAPI3::setHoriz(int x, int y, short horiz) {
  //TODO: проверки-проверочки нужны
  return ooSetHoriz(x, y, horiz);
}

//установка показа границ
//лево, верх, право, низ, r, g, b
bool __fastcall OOAPI3::setBorders(int x, int y, bool l, bool t, bool r, bool d, short rd, short gr, short bl) {
  return ooSetBorders(x, y, l, t, r, d, rd, gr, bl);
}

//установка показа границ
//лево, верх, право, низ
bool __fastcall OOAPI3::setBorders(int x, int y, bool l, bool t, bool r, bool d) {
  //черные границы
  return ooSetBorders(x, y, l, t, r, d, 0, 0, 0);
}

//установка показа границ
//показать все границы
bool __fastcall OOAPI3::setBorders(int x, int y) {
  return ooSetBorders(x, y, true, true, true, true, 0, 0, 0);
}

//установка ширины столбца в милиметрах
bool __fastcall OOAPI3::setColWidth(int col, long mm) {
  return ooSetColWidth(col, mm);
}

//объединить диапозон ячеек
//к примеру A1:C7
bool __fastcall OOAPI3::mergeRange(AnsiString from, AnsiString to) {
  return ooMergeRange(AnsiString(from+":"+to).c_str());
}

//наименование столбца, по его номеру
AnsiString __fastcall OOAPI3::getColNameById(int id) {
  id++;
  AnsiString abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//26
  AnsiString ret;
  int x;
  if(id > 26) {
    x = (int)id/26;
    ret = abc.SubString(x, 1);
    id = id - x*26;
  }
  ret += abc.SubString(id, 1);
  
  return ret;
}

//объединить диапозон ячеек
//вариант с цифрами
bool __fastcall OOAPI3::mergeRange(int x1, int y1, int x2, int y2) {
  y1++; y2++;

  AnsiString from = OOAPI3::getColNameById(x1) + AnsiString(y1);
  AnsiString to = OOAPI3::getColNameById(x2) + AnsiString(y2);

  return OOAPI3::mergeRange(from, to);
}

//экспорт документа в excel на диск
//пример: file:///C:/тест.xls
bool __fastcall OOAPI3::export2XLS(AnsiString to) {
  to = ReplaceStr(to, "\\", "/");
  to = "file:///"+to;

  //конвертация в unicode
  int iSize = to.WideCharBufSize();
  wchar_t *uval = new wchar_t[iSize];
  to.WideChar(uval, iSize);
  bool r = ooExportToUrl(uval);
  delete[] uval;
  return r;
}

//получить числовое значение ячейки
double   __fastcall OOAPI3::getVal(int x, int y) {
  return ooGetVal(x, y);
}

//получить текст ячейки
AnsiString __fastcall OOAPI3::getText(int x, int y) {
  return AnsiString(ooGetText(x, y));
}

//определяет где запущено приложение:windows/wine
bool  __fastcall OOAPI3::isWin() {
  return ooIsWin();
}

//установлен ли опен офис?
bool __fastcall OOAPI3::isInstall() {
  return ooIsInstall();
}

//отключаемся от сервера, освобождаем библиотеку
__fastcall OOAPI3::~OOAPI3() {
  ooDisconect();
  FreeLibrary(hLib);
}

2.1. Пример небольшой программы по выгрузке данных


Пример использования библиотеки. Результат картинкой представлен вначале статьи.

  OOAPI3 *t = new OOAPI3();
  if(!t->isInstall()) return;
  t->connect("private:factory/scalc");
  t->setSheet(0);
  t->mergeRange(26,1,29,2);
  t->setVal(1,1, -178.576);
  t->setText(0, 2, "Тест1");
  t->setVal(1,1, 5);
  t->setVal(0,0, 3.14);
  t->setBorders(0,0);
  t->setText(0, 2, "Тест1");
  t->setBold(0, 2);
  t->setFontColor(0, 2, 0, 0, 255);
  t->setBgColor(0,2,255,255,0);
  t->setFontSize(0,2,20);
  t->setItalic(0,2);
  t->setHoriz(0,2,3);//1-л, 2-центр, 3-п
  t->setColWidth(0, 100);
  t->setBorders(1,1);
  t->mergeRange("A1", "C2");
  t->export2XLS("C:/export123.xls");
  delete t;


Скачать пример программы со всем необходимыми библиотеками.
В архиве лежат либы для запуска билдеровского exe их можно удалить (список либ в note.txt)

Более сложная выгрузка из реальной жизни:


На текущий момент остались проблемы:
— скрытие офиса в момент загрузки в него данных.
— генерация RDB файла под WINE (скорей всего неправильное преобразование в юникод в функции createProcess )
Tags:
Hubs:
Total votes 45: ↑37 and ↓8 +29
Views 4.8K
Comments Comments 20