From 8faf65609189e4e16f02440b130de457319d4780 Mon Sep 17 00:00:00 2001 From: koldo Date: Tue, 14 Jul 2009 22:26:04 +0000 Subject: [PATCH] git-svn-id: svn://ultimatepp.org/upp/trunk@1413 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/OfficeAutomation/OfficeAutomation.cpp | 2613 +++++++++++++++++ bazaar/OfficeAutomation/OfficeAutomation.h | 113 + bazaar/OfficeAutomation/OfficeAutomation.t | 27 + bazaar/OfficeAutomation/OfficeAutomation.upp | 20 + .../OfficeAutomation/OfficeAutomationBase.h | 260 ++ bazaar/OfficeAutomation/init | 4 + .../src.tpp/OfficeDoc$en-us.tpp | 121 + .../src.tpp/OfficeSheet$en-us.tpp | 234 ++ .../srcdoc.tpp/OfficeAutomation$en-us.tpp | 18 + 9 files changed, 3410 insertions(+) create mode 100644 bazaar/OfficeAutomation/OfficeAutomation.cpp create mode 100644 bazaar/OfficeAutomation/OfficeAutomation.h create mode 100644 bazaar/OfficeAutomation/OfficeAutomation.t create mode 100644 bazaar/OfficeAutomation/OfficeAutomation.upp create mode 100644 bazaar/OfficeAutomation/OfficeAutomationBase.h create mode 100644 bazaar/OfficeAutomation/init create mode 100644 bazaar/OfficeAutomation/src.tpp/OfficeDoc$en-us.tpp create mode 100644 bazaar/OfficeAutomation/src.tpp/OfficeSheet$en-us.tpp create mode 100644 bazaar/OfficeAutomation/srcdoc.tpp/OfficeAutomation$en-us.tpp diff --git a/bazaar/OfficeAutomation/OfficeAutomation.cpp b/bazaar/OfficeAutomation/OfficeAutomation.cpp new file mode 100644 index 000000000..8accb4fd2 --- /dev/null +++ b/bazaar/OfficeAutomation/OfficeAutomation.cpp @@ -0,0 +1,2613 @@ +#include + +#ifndef PLATFORM_WIN32 +#error Sorry: This platform is not supported!. Look for OfficeAutomation in Bazaar Upp Forum to search for info and new news +#endif + +#include + +#include "SysInfo/SysInfo.h" +#include "OfficeAutomationBase.h" +#include "OfficeAutomation.h" + +//////////////////////////////////////////////////////////////////////////////////////// +VariantOle::VariantOle() +{ + VariantInit(&var); + VariantClear(&var); +} +VariantOle::~VariantOle() +{ + if (var.vt == VT_BSTR) + SysFreeString(var.bstrVal); +} +void VariantOle::Bool(bool val) +{ + var.vt = VT_BOOL; + var.boolVal = val; +} +void VariantOle::Int(int val) +{ + var.vt = VT_I4; + var.intVal = val; +} +void VariantOle::Int4(long val) +{ + var.vt = VT_I4; + var.lVal = val; +} +void VariantOle::Real4(float val) +{ + var.vt = VT_R4; + var.fltVal = val; +} +void VariantOle::Real8(double val) +{ + var.vt = VT_R8; + var.dblVal = val; +} +void VariantOle::BString(String str) +{ + WCHAR wfileName[1024*sizeof(WCHAR)]; + + MultiByteToWideChar(CP_UTF8, 0, str, -1, wfileName, sizeof(wfileName)/sizeof(wfileName[0])); + var.vt = VT_BSTR; + var.bstrVal = ::SysAllocString(wfileName); +} +void VariantOle::Optional() +{ + var.vt = VT_ERROR; + var.scode = DISP_E_PARAMNOTFOUND; +} +void VariantOle::ObjectOle(::ObjectOle val) +{ + var.vt = VT_DISPATCH; + var.pdispVal = val; +} +void VariantOle::Time(Upp::Time t) +{ + var.vt = VT_DATE; + SYSTEMTIME stime; + stime.wDay = t.day; + stime.wMonth = t.month; + stime.wYear = t.year; + stime.wHour = t.hour; + stime.wMinute = t.minute; + stime.wSecond = t.second; + SystemTimeToVariantTime(&stime, &(var.date)); +} +void VariantOle::ArrayDim(int sizeX) +{ + var.vt = VT_ARRAY | VT_VARIANT; + SAFEARRAYBOUND sab[1]; // 1 dimension + sab[0].lLbound = 1; sab[0].cElements = sizeX; + var.parray = SafeArrayCreate(VT_VARIANT, 1, sab); +} +void VariantOle::ArrayDim(int sizeX, int sizeY) +{ + var.vt = VT_ARRAY | VT_VARIANT; + SAFEARRAYBOUND sab[2]; // 2 dimension + sab[0].lLbound = 1; sab[0].cElements = sizeY; + sab[1].lLbound = 1; sab[1].cElements = sizeX; + var.parray = SafeArrayCreate(VT_VARIANT, 2, sab); +} +void VariantOle::ArraySetValue(int x, ::Value value) +{ + VariantOle tmp; + tmp.Value(value); + long indices[] = {x}; + SafeArrayPutElement(var.parray, indices, (void *)&tmp); +} +void VariantOle::ArraySetVariant(int x, VariantOle &value) +{ + long indices[] = {x}; + SafeArrayPutElement(var.parray, indices, (void *)&value); +} +void VariantOle::ArraySetValue(int x, int y, ::Value value) +{ + VariantOle tmp; + tmp.Value(value); + long indices[] = {y, x}; + SafeArrayPutElement(var.parray, indices, (void *)&tmp); +} +void VariantOle::ArraySetVariant(int x, int y, VariantOle &value) +{ + long indices[] = {y, x}; + SafeArrayPutElement(var.parray, indices, (void *)&value); +} +void VariantOle::Value(::Value value) +{ + if(value.Is()) { + bool v = value; + Bool(v); + } else if(value.Is()) { + int v = value; + Int(v); + } else if(value.Is()) { + int64 v = value; + Int4((long)v); + //} else if(value.Is()) { + // float v = value; + // Real4(v); + } else if(value.Is()) { + double v = value; + Real8(v); + } else if(value.Is()) { + String v = value; + BString(v); + } else if(IsDateTime(value)) { + Upp::Time v = value; + Time(v); + } else { + String v = value; + BString(v); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +class Ole +{ +public: + static bool Invoke(int autoType, VARIANT *pvResult, IDispatch *pDisp, String name, int cArgs...); + static void Init(); + static bool Close(); + static ObjectOle CreateObject(String application); + static ObjectOle GetObject(ObjectOle from, String what); + static ObjectOle GetObject(ObjectOle from, String which, VariantOle &value); + static ObjectOle GetObject(ObjectOle from, String which, VariantOle &value, VariantOle &value2); + static bool SetValue(ObjectOle from, String which, VariantOle &value); + static bool SetValue(ObjectOle from, String which, VariantOle &value, VariantOle &value2); + static bool SetValue(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3); + static Value GetValue(ObjectOle from, String which); + static Value GetValue(ObjectOle from, String which, VariantOle &value); + static Value GetValue(ObjectOle from, String which, VariantOle &value, VariantOle &value2); + static bool Method(ObjectOle from, String which); + static bool Method(ObjectOle from, String which, VariantOle &value); + static bool Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2); + static bool Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3); + static bool Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4); + static bool Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4, VariantOle &value5); + static bool Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4, VariantOle &value5, VariantOle &value6, VariantOle &value7, VariantOle &value8, VariantOle &value9, VariantOle &value10, VariantOle &value11); + static ObjectOle MethodGet(ObjectOle from, String which); + static ObjectOle MethodGet(ObjectOle from, String which, VariantOle &value); + static ObjectOle MethodGet(ObjectOle from, String which, VariantOle &value, VariantOle &value2); + static ObjectOle MethodGet(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3); + static ObjectOle MethodGet(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4); + static bool IsOn() {return numOleInit > 0;}; +private: + static int numOleInit; +}; + +int Ole::numOleInit = 0; + +void Ole::Init() +{ // Initialize COM for this thread + if (numOleInit == 0) { + OleInitialize(NULL); + CoInitialize(NULL); + numOleInit++; + } +} +bool Ole::Close() +{ // Uninitialize COM for this thread + numOleInit--; + if (numOleInit == 0) + CoUninitialize(); + if (numOleInit < 0) { // This is a mistake + numOleInit = 0; + return false; + } else + return true; +} +// Invoke() - Automation helper function +bool Ole::Invoke(int autoType, VARIANT *pvResult, IDispatch *pDisp, String name, int cArgs ...) +{ + // Begin variable-argument lis + va_list marker; + va_start(marker, cArgs); + + if(!pDisp) { + MessageBox(NULL, t_("OfficeAutomation internal error. NULL IDispatch passed to AutoWrap()"), t_("Error"), 0x10010); + return false; + } + // Variables used + DISPPARAMS dp = { NULL, NULL, 0, 0 }; + DISPID dispidNamed = DISPID_PROPERTYPUT; + DISPID dispID; + HRESULT hr; + char buf[200]; + char szName[200]; + WString wname = name.ToWString(); + WStringBuffer ptName(wname); + + // Convert down to ANSI + WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL); + + // Get DISPID for name passed + hr = pDisp->GetIDsOfNames(IID_NULL, (LPOLESTR *)&ptName, 1, LOCALE_USER_DEFAULT, &dispID); + if(FAILED(hr)) { + //sprintf(buf, "Command IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr); + sprintf(buf, t_("OfficeAutomation internal error. Command \"%s\" not found for object or problem when running it"), szName); + MessageBox(NULL, buf, t_("Ole error"), 0x10010); + return false; + } + // Allocate memory for arguments + VARIANT *pArgs = new VARIANT[cArgs+1]; + // Extract arguments + for(int i = 0; i < cArgs; i++) + pArgs[i] = va_arg(marker, VARIANT); + + // Build DISPPARAMS + dp.cArgs = cArgs; + dp.rgvarg = pArgs; + + // Handle special-case for property-puts! + if(autoType & DISPATCH_PROPERTYPUT) { + dp.cNamedArgs = 1; + dp.rgdispidNamedArgs = &dispidNamed; + } + // Make the call! + hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL); + + // End variable-argument section + va_end(marker); + + delete [] pArgs; + + if(FAILED(hr)) { + //sprintf(buf, "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr); + //MessageBox(NULL, buf, "Ole::Invoke()", 0x10010); + return false; + } + return true; +} +ObjectOle Ole::CreateObject(String application) +{ + CLSID clsid; + HRESULT hr = CLSIDFromProgID(application.ToWString(), &clsid); // Get CLSID for our server + if(FAILED(hr)) { + //::MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 0x10010); + return NULL; + } + ObjectOle app; + // Start server and get IDispatch + hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&app); + if(FAILED(hr)) { + ::MessageBox(NULL, t_("OfficeAutomation internal error. Application not registered properly"), t_("Error"), 0x10010); + return NULL; + } + return app; +} +ObjectOle Ole::GetObject(ObjectOle from, String which) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_PROPERTYGET, &result, from, which, 0)) + return NULL; + else + return result.pdispVal; +} +ObjectOle Ole::GetObject(ObjectOle from, String which, VariantOle &value) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_PROPERTYGET, &result, from, which, 1, value.var)) + return NULL; + else + return result.pdispVal; +} +ObjectOle Ole::GetObject(ObjectOle from, String which, VariantOle &value, VariantOle &value2) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_PROPERTYGET, &result, from, which, 2, value.var, value2.var)) + return NULL; + else + return result.pdispVal; +} +Value Ole::GetValue(ObjectOle from, String which) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_PROPERTYGET|DISPATCH_METHOD, &result, from, which, 0)) + return ""; + + return GetVARIANT(result); +} +bool Ole::SetValue(ObjectOle from, String which, VariantOle &value) +{ + return Ole::Invoke(DISPATCH_PROPERTYPUT, NULL, from, which, 1, value.var); +} +bool Ole::SetValue(ObjectOle from, String which, VariantOle &value, VariantOle &value2) +{ + return Ole::Invoke(DISPATCH_PROPERTYPUT, NULL, from, which, 2, value.var, value2.var); +} +bool Ole::SetValue(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3) +{ + return Ole::Invoke(DISPATCH_PROPERTYPUT, NULL, from, which, 3, value.var, value2.var, value3.var); +} +// result var is not used but OpenOffice automation requires it (I do not why) +bool Ole::Method(ObjectOle from, String which) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 0); +} +bool Ole::Method(ObjectOle from, String which, VariantOle &value) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 1, value.var); +} +bool Ole::Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 2, value.var, value2.var); +} +bool Ole::Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 3, value.var, value2.var, value3.var); +} +bool Ole::Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 3, value.var, value2.var, value3.var, value4.var); +} +bool Ole::Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4, VariantOle &value5) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 3, value.var, value2.var, value3.var, value4.var, value5.var); +} +bool Ole::Method(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4, VariantOle &value5, VariantOle &value6, VariantOle &value7, VariantOle &value8, VariantOle &value9, VariantOle &value10, VariantOle &value11) +{ + VARIANT result; + VariantInit(&result); + return Ole::Invoke(DISPATCH_METHOD, &result, from, which, 11, value.var, value2.var, value3.var, value4.var, value5.var, value6.var, value7.var, value8.var, value9.var, value10.var, value11.var); +} +ObjectOle Ole::MethodGet(ObjectOle from, String which) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_METHOD, &result, from, which, 0)) + return NULL; + else + return result.pdispVal; +} +ObjectOle Ole::MethodGet(ObjectOle from, String which, VariantOle &value) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_METHOD, &result, from, which, 1, value.var)) + return NULL; + else + return result.pdispVal; +} +ObjectOle Ole::MethodGet(ObjectOle from, String which, VariantOle &value, VariantOle &value2) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_METHOD, &result, from, which, 2, value.var, value2.var)) + return NULL; + else + return result.pdispVal; +} +ObjectOle Ole::MethodGet(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_METHOD, &result, from, which, 3, value.var, value2.var, value3.var)) + return NULL; + else + return result.pdispVal; +} +ObjectOle Ole::MethodGet(ObjectOle from, String which, VariantOle &value, VariantOle &value2, VariantOle &value3, VariantOle &value4) +{ + VARIANT result; + VariantInit(&result); + if(!Ole::Invoke(DISPATCH_METHOD, &result, from, which, 4, value.var, value2.var, value3.var, value4.var)) + return NULL; + else + return result.pdispVal; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MSSheet::MSSheet() +{ + App = Books = Book = Sheet = Range = NULL; + quit = false; + + App = Ole::CreateObject("Excel.Application"); + if (!(Books = Ole::GetObject(App, "Workbooks"))) { + ::MessageBox(NULL, t_("Excel workbooks not loaded properly"), t_("Error"), 0x10010); + return; + } +} +MSSheet::~MSSheet() +{ + if (Range) + Range->Release(); + if (Sheet) + Sheet->Release(); + if (Book) + Book->Release(); + if (Books) + Books->Release(); + if (App) { + Quit(); + App->Release(); + } +} +bool MSSheet::IsAvailable() +{ + ObjectOle app = Ole::CreateObject("Excel.Application"); + + if (!app) + return false; + else { + app->Release(); + return true; + } +} +bool MSSheet::SetVisible(bool visible) +{ + if (!Books) + return false; + + VariantOle vVisible; + vVisible.Int4(visible? 1: 0); + return Ole::SetValue(App, "Visible", vVisible); +} +bool MSSheet::SetSaved(bool saved) +{ + if (!Books && !Book) + return false; + + // Set .Saved property of workbook to TRUE so we aren't prompted + // to save when we tell Excel to quit... + VariantOle vSaved; + vSaved.Int4(saved? 1: 0); + return Ole::SetValue(Book, "Saved", vSaved); +} +bool MSSheet::Quit() +{ + if (!quit) { + quit = true; + return Ole::Method(App, "Quit"); + } + return true; +} +bool MSSheet::AddSheet(bool visible) +{ + if (!Books) + return false; + + if (!(Book = Ole::GetObject(Books, "Add"))) + return false; + if (!(Sheet = Ole::GetObject(App, "ActiveSheet"))) + return false; + + SetVisible(visible); + return true; +} +bool MSSheet::OpenSheet(String fileName, bool visible) +{ + if (!Books) + return false; + + VariantOle vFileName; + vFileName.BString(fileName); + if (!(Book = Ole::GetObject(Books, "Open", vFileName))) + return false; + if (!(Sheet = Ole::GetObject(App, "ActiveSheet"))) + return false; + + SetVisible(visible); + return true; +} +bool MSSheet::Select(String range) +{ + VariantOle vRange; + vRange.BString(range); + + if (!(Range = Ole::GetObject(Sheet, "Range", vRange))) + return false; + return true; +} +bool MSSheet::Select(int fromX, int fromY, int toX, int toY) +{ + String range = OfficeSheet::ColRowToCell(fromX, fromY) + ":" + OfficeSheet::ColRowToCell(toX, toY); + VariantOle vRange; + vRange.BString(range); + + if (!(Range = Ole::GetObject(Sheet, "Range", vRange))) + return false; + return true; +} +bool MSSheet::Select() +{ + if (!(Range = Ole::GetObject(Sheet, "Cells"))) // ActiveSheet.Cells.Select + return false; + return Ole::Method(Range, "Select"); +} +void MSSheet::DefMatrix(int width, int height) +{ + Matrix.ArrayDim(width, height); +} +void MSSheet::SetMatrixValue(int x, int y, ::Value value) +{ + Matrix.ArraySetValue(x, y, value); +} +bool MSSheet::FillSelectionMatrix() +{ + if (!Range) + return false; + + bool ret = Ole::Invoke(DISPATCH_PROPERTYPUT, NULL, Range, "Value", 1, Matrix.var); + + return ret; +} + +bool MSSheet::SetValue(String cell, Value value) // cell in textual format like "B14" +{ + int col, row; + + OfficeSheet::CellToColRow(cell, col, row); + return MSSheet::SetValue(col, row, value); +} +bool MSSheet::SetValue(int col, int row, Value value) +{ + if (!Sheet) + return false; + + VariantOle x, y, val; + x.Int4(col); + y.Int4(row); + val.Value(value); + + return Ole::SetValue(Sheet, "Cells", val, x, y); +} +bool MSSheet::SetValue(Value value) +{ + if (!Sheet) + return false; + + if (!Range) + return false; + + VariantOle val; + val.Value(value); + + return Ole::SetValue(Range, "Value", val); +} +bool MSSheet::Replace(Value search, Value replace) +{ + if (!App) + return false; + + ObjectOle selection; // Call Application.Selection.Replace(search, replace) + if (!(selection = Ole::GetObject(App, "Selection"))) + return false; + + VariantOle vSearch, vReplace; + vSearch.Value(search); + vReplace.Value(replace); + + return Ole::Method(selection, "Replace", vReplace, vSearch); +} +Value MSSheet::GetValue(int col, int row) +{ + if (!Sheet) + return false; + + VariantOle x, y; + x.Int4(col); + y.Int4(row); + + return Ole::GetValue(Ole::GetObject(Sheet, "Cells", x, y), "value"); +} +Value MSSheet::GetValue(String cell) +{ + int row, col; + + OfficeSheet::CellToColRow(cell, col, row); + return GetValue(col, row); +} +bool MSSheet::SaveAs(String fileName, String type) +{ + if (!Book) + return false; + + fileName = ForceExt(fileName, "." + type); + + VariantOle vFileName, vType; + + vFileName.BString(fileName); + if (type == "csv") + vType.Int(6); + else if (type == "html") + vType.Int(44); + else if (type == "txt") + vType.Int(20); + else if (type == "xlsx") + vType.Int(51); + else // xls + vType.Int(-4143); + + int ret = Ole::Method(Book, "SaveAs", vType, vFileName); + + return (bool)ret; +} +bool MSSheet::SetBold(String cell, bool bold) +{ + int col, row; + OfficeSheet::CellToColRow(cell, col, row); + return SetBold(col, row, bold); +} +bool MSSheet::SetBold(int col, int row, bool bold) +{ + if (!Sheet) + return false; + + VariantOle x, y; + x.Int4(col); + y.Int4(row); + + VariantOle val; + val.Bool(bold); + return Ole::SetValue(Ole::GetObject(Ole::GetObject(Sheet, "Cells", x, y), "Font"), "Bold", val); +} +bool MSSheet::SetBold(bool bold) +{ + if (!Range) + return false; + + VariantOle val; + val.Bool(bold); + return Ole::SetValue(Ole::GetObject(Range, "Font"), "Bold", val); +} +bool MSSheet::SetFont(String cell, String name, int size) +{ + int col, row; + OfficeSheet::CellToColRow(cell, col, row); + return SetFont(col, row, name, size); +} +bool MSSheet::SetFont(int col, int row, String name, int size) +{ + if (!Sheet) + return false; + + VariantOle x, y; + x.Int4(col); + y.Int4(row); + + ObjectOle font = Ole::GetObject(Ole::GetObject(Sheet, "Cells", x, y), "Font"); + if (!font) + return false; + + VariantOle vName; + vName.BString(name); + if(!Ole::SetValue(font, "Name", vName)) + return false; + VariantOle vSize; + vSize.Int(size); + if(!Ole::SetValue(font, "Size", vSize)) + return false; + return true; +} +bool MSSheet::SetFont(String name, int size) +{ + if (!Range) + return false; + + ObjectOle font = Ole::GetObject(Range, "Font"); + if (!font) + return false; + + VariantOle vName; + vName.BString(name); + if(!Ole::SetValue(font, "Name", vName)) + return false; + VariantOle vSize; + vSize.Int(size); + if(!Ole::SetValue(font, "Size", vSize)) + return false; + return true; +} +bool MSSheet::Print() +{ + if (!Sheet) + return false; + + bool ret = Ole::Method(Sheet, "PrintOut"); + + return ret; +} + +enum XLSheetTypes {xlWorksheet = -4167, xlChart = -4109, xlExcel4MacroSheet = 3, xlExcel4IntlMacroSheet = 4}; + +bool MSSheet::InsertTab(String name) // Insert tab after the last +{ + if (!App) + return false; + + if (!(Sheet = Ole::GetObject(Ole::GetObject(App, "Sheets"), "Add"))) + return false; + VariantOle vName; + vName.BString(name); + if(!Ole::SetValue(Sheet, "Name", vName)) + return false; + //return true; + + VariantOle vOptional; + vOptional.Optional(); + + ObjectOle lastSheet; + VariantOle vId; + vId.Int(GetNumTabs()); + if (!(lastSheet = Ole::GetObject(App, "Sheets", vId))) + return false; + VariantOle vAfter; + vAfter.ObjectOle(lastSheet); + + return Ole::Method(Sheet, "Move", vAfter, vOptional); // Apending tab after last tab +} +bool MSSheet::ChooseTab(String name) +{ + if (!App) + return false; + + VariantOle vName; + vName.BString(name); + if (!(Sheet = Ole::GetObject(App, "Sheets", vName))) + return false; + + return Ole::Method(Sheet, "select"); +} +bool MSSheet::ChooseTab(int index) +{ + if (!App) + return false; + + VariantOle vId; + vId.Int(index+1); + if (!(Sheet = Ole::GetObject(App, "Sheets", vId))) + return false; + + return Ole::Method(Sheet, "select"); +} +bool MSSheet::RemoveTab(String name) +{ + if (!App) + return false; + + ObjectOle DelSheet; + VariantOle vName; + vName.BString(name); + if (!(DelSheet = Ole::GetObject(App, "Sheets", vName))) + return false; + + return Ole::Method(DelSheet, "delete"); +} +bool MSSheet::RemoveTab(int index) +{ + if (!App) + return false; + + ObjectOle DelSheet; + VariantOle vId; + vId.Int(index+1); + if (!(DelSheet = Ole::GetObject(App, "Sheets", vId))) + return false; + + return Ole::Method(DelSheet, "delete"); +} +int MSSheet::GetNumTabs() +{ + if (!App) + return -1; + + return Ole::GetValue(Ole::GetObject(App, "Sheets"), "count"); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MSDoc::MSDoc() +{ + App = Docs = Doc = Selection = NULL; + quit = false; + + App = Ole::CreateObject("Word.Application"); + if (!(Docs = Ole::GetObject(App, "Documents"))) { + ::MessageBox(NULL, t_("Word document not loaded properly"), t_("Error"), 0x10010); + return; + } +} +MSDoc::~MSDoc() +{ + if (Selection) + Selection->Release(); + if (Doc) + Doc->Release(); + if (Docs) + Docs->Release(); + if (App) { + Quit(); + App->Release(); + } + Ole::Close(); +} +bool MSDoc::SetVisible(bool visible) +{ + if (!Docs) + return false; + + VariantOle vVisible; + vVisible.Int4(visible? 1: 0); + return Ole::SetValue(App, "Visible", vVisible); +} +bool MSDoc::IsAvailable() +{ + ObjectOle app = Ole::CreateObject("Word.Application"); + + if (!app) + return false; + else { + app->Release(); + return true; + } +} +bool MSDoc::SetSaved(bool saved) +{ + if (!Doc) + return false; + + VariantOle vSaved; + vSaved.Int4(saved? 1: 0); + return Ole::SetValue(Doc, "Saved", vSaved); +} +bool MSDoc::Quit() +{ + if (!quit) { + quit = true; + return Ole::Method(App, "Quit"); + } + return true; +} +bool MSDoc::AddDoc(bool visible) +{ + if (!Docs) + return false; + + if (!(Doc = Ole::MethodGet(Docs, "Add"))) + return false; + + if(!(Selection = Ole::GetObject(App, "Selection"))) + return false; + + SetVisible(visible); + return true; +} +bool MSDoc::OpenDoc(String fileName, bool visible) +{ + if (!Docs) + return false; + + VariantOle vFileName; + vFileName.BString(fileName); + if (!(Doc = Ole::MethodGet(Docs, "Open", vFileName))) + return false; + + if(!(Selection = Ole::GetObject(App, "Selection"))) + return false; + + SetVisible(visible); + return true; +} +bool MSDoc::SaveAs(String fileName, String type) +{ + if (!Doc) + return false; + + fileName = ForceExt(fileName, "." + type); + + VariantOle vFileName, vType; + + vFileName.BString(fileName); + if (type == "rtf") + vType.Int(6); + else if (type == "html") + vType.Int(8); + else if (type == "txt") + vType.Int(2); + else if (type == "docx") + vType.Int(13); + else // doc + vType.Int(0); + + int ret = Ole::Method(Doc, "SaveAs", vType, vFileName); + + return (bool)ret; +} +bool MSDoc::WriteText(String value) +{ + if (!Selection) + return false; + + VariantOle val; + val.BString(value); + return Ole::Method(Selection, "TypeText", val); +} +bool MSDoc::SetFont(String type, int size) +{ + ObjectOle font; + + if(!(font = Ole::GetObject(Selection, "Font"))) + return false; + + VariantOle vType; + vType.BString(type); + if(!Ole::SetValue(font, "Name", vType)) + return false; + VariantOle vSize; + vSize.Int(size); + if(!Ole::SetValue(font, "Size", vSize)) + return false; + + return true; +} +bool MSDoc::SetBold(bool bold) +{ + VariantOle vBold; + vBold.Bool(bold); + if(!Ole::SetValue(Ole::GetObject(Selection, "Font"), "Bold", vBold)) + return false; + + return true; +} +bool MSDoc::SetItalic(bool italic) +{ + VariantOle vItalic; + vItalic.Bool(italic); + if(!Ole::SetValue(Ole::GetObject(Selection, "Font"), "Italic", vItalic)) + return false; + + return true; +} +bool MSDoc::Print() +{ + if (!Docs && !Doc) + return false; + + bool ret = Ole::Method(Doc, "PrintOut"); + + return ret; +} +bool MSDoc::Select() +{ + return Ole::Method(Selection, "WholeStory"); +} +// Some tricks as Ole Replace does not work properly for texts to replace longer than +// about 250 chars and for some special chars +bool MSDoc::Replace(String search, String _replace) +{ + String replace = CleanString(_replace); + replace = ::Replace(replace, "^", " "); + replace = ::Replace(replace, "\r", ""); // To remove squares + + String replaceSubset; + while (replace.GetCount() > 200) { + replaceSubset = replace.Left(200); + replaceSubset.Cat(search); + replace = replace.Right(replace.GetCount() - 200); + + replaceSubset = ::Replace(replaceSubset, "\n", "^l"); + if (!ReplaceSubset(search, replaceSubset)) + return false; + } + replace = ::Replace(replace, "\n", "^l"); + return ReplaceSubset(search, replace); +} +String MSDoc::CleanString(String str) // Clean chars in String +{ + String ret; + String valid = ">=<ºª%€&()$1234567890áéíóúÁÉÍÓÚñÑçÇ,.,:-_/¿?+*[]{}'\"!¡ \r\n"; + for (int i = 0; i < str.GetCount(); ++i) { + int s = str[i]; + if (IsLetter(s) || valid.Find(s) >= 0) + ret.Cat(s); + } + return ret; +} +bool MSDoc::ReplaceSubset(String search, String replace) +{ + ObjectOle find; + if (!(find = Ole::GetObject(Selection, "Find"))) + return false; + + if(!Ole::Method(find, "ClearFormatting")) // Selection.Find.ClearFormatting + return false; + + VariantOle vFindText; + vFindText.BString(search); + + VariantOle vMatchCase; + vMatchCase.Bool(false); + + VariantOle vMatchWholeWord; + vMatchWholeWord.Bool(false); + + VariantOle vMatchWildcards; + vMatchWildcards.Bool(false); + + VariantOle vMatchSoundsLike; + vMatchSoundsLike.Bool(false); + + VariantOle vMatchAllWordForms; + vMatchAllWordForms.Bool(false); + + VariantOle vForward; + vForward.Bool(true); + + VariantOle vWrap; + vWrap.Int(wdFindContinue); + + VariantOle vFormat; + vFormat.Bool(false); + + VariantOle vReplaceWith; + vReplaceWith.BString(replace); + + VariantOle vReplace; + vReplace.Int(wdReplaceAll); + + return Ole::Method(find, "Execute", vReplace, vReplaceWith, vFormat, vWrap, vForward, vMatchAllWordForms, vMatchSoundsLike, vMatchWildcards, vMatchWholeWord, vMatchCase, vFindText); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class OOo +{ +public: + static ObjectOle MakePropertyValue(String name, ::Value value) + { + ObjectOle ServiceManager; + if (!(ServiceManager = Ole::CreateObject("com.sun.star.ServiceManager"))) + return NULL; + + ObjectOle Struct; + VariantOle vstr; + vstr.BString("com.sun.star.beans.PropertyValue"); + if (!(Struct = Ole::MethodGet(ServiceManager, "Bridge_GetStruct", vstr))) + return NULL; + + VariantOle vname, vvalue; + vname.BString(name); + if (!Ole::SetValue(Struct, "Name", vname)) + return NULL; + vvalue.Value(value); + if (!Ole::SetValue(Struct, "Value", vvalue)) + return NULL; + return Struct; + } + static String ConvertToUrl(String strFile) + { + String ret; + String c; + + for (int i = 0; i < strFile.GetCount(); ++i) { + if (strFile[i] >= 123) + c = "%" + Format("%x", strFile[i]); + else { + switch (strFile[i]) { + case 9: c = "%09"; break; + case 13: c = "%0d"; break; + case 10: c = "%0a"; break; + case 32: case 33: case 34: case 35: case 37: case 38: case 39: case 40: case 41: case 43: + case 44: case 59: case 60: case 61: case 62: case 63: case 91: case 93: case 94: case 96: + c = "%" + Format("%x", strFile[i]); break; + case '\\': c = "/"; break; + case ':': c = "|"; break; + default: c = strFile.Mid(i, 1); + } + } + ret.Cat(c); + } + return "file:///" + ret; + } + static ObjectOle CreateUnoService(String strServiceName) + { + ObjectOle ServiceManager; + if (!(ServiceManager = Ole::CreateObject("com.sun.star.ServiceManager"))) + return NULL; + + VariantOle vService; + vService.BString(strServiceName); + return Ole::MethodGet(ServiceManager, "createInstance", vService); + } +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OPENSheet::OPENSheet() +{ + ServiceManager = CoreReflection = Desktop = Document = Sheets = Sheet = Cell = Range = NULL; + selectedAll = false; + quit = false; + + // The service manager is always the starting point + // If there is no office running then an office is started up + ObjectOle ServiceManager; + if (!(ServiceManager = Ole::CreateObject("com.sun.star.ServiceManager"))) + return; + + // Create the CoreReflection service that is later used to create structs + ObjectOle CoreReflection; + VariantOle vInstance; + vInstance.BString("com.sun.star.reflection.CoreReflection"); + if (!(CoreReflection = Ole::MethodGet(ServiceManager, "createInstance", vInstance))) + return; + + // Create the Desktop + VariantOle vDesktop; + vDesktop.BString("com.sun.star.frame.Desktop"); + if (!(Desktop = Ole::MethodGet(ServiceManager, "createInstance", vDesktop))) + return; +} + +OPENSheet::~OPENSheet() +{ + if (Cell) + Cell->Release(); + if (Range) + Range->Release(); + if (Sheet) + Sheet->Release(); + if (Sheets) + Sheets->Release(); + if (Document) + Document->Release(); + if (Desktop) { + Quit(); + Desktop->Release(); + } + if (CoreReflection) + CoreReflection->Release(); + if (ServiceManager) + ServiceManager->Release(); +} +bool OPENSheet::IsAvailable() +{ + ObjectOle serviceManager; + if (!(serviceManager = Ole::CreateObject("com.sun.star.ServiceManager"))) + return false; + else { + serviceManager->Release(); + return true; + } +} +bool OPENSheet::SetSaved(bool saved) +{ + VariantOle vval; + vval.Bool(!saved); // Modified is the opposite to saved + return Ole::Method(Document, "setModified", vval); +} +bool OPENSheet::Quit() +{ + if (!quit) { + quit = true; + return Ole::Method(Desktop, "Terminate"); + } + return true; +} +bool OPENSheet::InsertTab(String name) +{ + if (!Sheets) + return false; + VariantOle vStr; + vStr.BString("com.sun.star.sheet.Spreadsheet"); + if (!(Sheet = Ole::MethodGet(Document, "createInstance", vStr))) + return false; + + vStr.BString(name); + + VariantOle vsheet; + vsheet.ObjectOle(Sheet); + + if (!(Ole::Method(Sheets, "insertByName", vsheet, vStr))) + return false; + + // Set tab as active + ObjectOle View; + if (!(View = Ole::MethodGet(Document, "getCurrentController"))) + return false; + + VariantOle vSheet; + vSheet.ObjectOle(Sheet); + return Ole::SetValue(View, "ActiveSheet", vSheet); +} +bool OPENSheet::ChooseTab(String name) +{ + if (!Sheets) + return false; + VariantOle vStr; + vStr.BString(name); + if (!(Sheet = Ole::MethodGet(Sheets, "getByName", vStr))) + return false; + + // Set tab as active + ObjectOle View; + if (!(View = Ole::MethodGet(Document, "getCurrentController"))) + return false; + + VariantOle vSheet; + vSheet.ObjectOle(Sheet); + return Ole::SetValue(View, "ActiveSheet", vSheet); +} +bool OPENSheet::ChooseTab(int index) +{ + if (!Sheets) + return false; + VariantOle vId; + vId.Int(index); + if (!(Sheet = Ole::MethodGet(Sheets, "getByIndex", vId))) + return false; + + // Set tab as active + ObjectOle View; + if (!(View = Ole::MethodGet(Document, "getCurrentController"))) + return false; + + VariantOle vSheet; + vSheet.ObjectOle(Sheet); + return Ole::SetValue(View, "ActiveSheet", vSheet); +} +bool OPENSheet::RemoveTab(String name) +{ + if (!Sheets) + return false; + VariantOle vStr; + vStr.BString(name); + if (!Ole::Method(Sheets, "removeByName", vStr)) + return false; + return true; +} +bool OPENSheet::RemoveTab(int index) +{ + if (!Sheets) + return false; + VariantOle vId; + vId.Int(index); + if (!Ole::Method(Sheets, "removeByIndex", vId)) + return false; + return true; +} +int OPENSheet::GetNumTabs() +{ + if (!Sheets) + return -1; + Value count; + count = Ole::GetValue(Sheets, "getCount"); + return count; +} +bool OPENSheet::AddSheet(bool visible) +{ + if (!Desktop) + return false; + + VariantOle vArray; + vArray.ArrayDim(1); + VariantOle vobject; + vobject.ObjectOle(OOo::MakePropertyValue("Hidden", true)); + vArray.ArraySetVariant(1, vobject); + + VariantOle vFile; + vFile.BString("_blank"); + VariantOle vSize; + vSize.Int4(0); + VariantOle vDocument; + vDocument.BString("private:factory/scalc"); + if (!(Document = Ole::MethodGet(Desktop, "loadComponentFromURL", vArray, vSize, vFile, vDocument))) + return false; + + if (!(Sheets = Ole::MethodGet(Document, "getSheets"))) + return false; + + if (!visible) + SetVisible(visible); + return true; //ChooseTab(0); // Select the first tab +} +bool OPENSheet::OpenSheet(String fileName, bool visible) +{ + if (!Desktop) + return false; + + VariantOle vArray; + vArray.ArrayDim(0); + + VariantOle vFile; + vFile.BString("_blank"); + VariantOle vSize; + vSize.Int4(0); + VariantOle vDocument; + vDocument.BString(OOo::ConvertToUrl(fileName)); + if (!(Document = Ole::MethodGet(Desktop, "loadComponentFromURL", vArray, vSize, vFile, vDocument))) + return false; + + if (!(Sheets = Ole::MethodGet(Document, "getSheets"))) + return false; + + if (!visible) + SetVisible(visible); + return ChooseTab(0); // Select the first tab +} +// Problem: It does hidden but not set visible again the window !!! +bool OPENSheet::SetVisible(bool visible) +{ + if (!Document) + return false; + ObjectOle DocCtrl; + if (!(DocCtrl = Ole::MethodGet(Document, "getCurrentController"))) + return false; + ObjectOle DocFrame; + if (!(DocFrame = Ole::MethodGet(DocCtrl, "getFrame"))) + return false; + ObjectOle DocWindow; + if (!(DocWindow = Ole::MethodGet(DocFrame, "getContainerWindow"))) + return false; + + VariantOle vvisible; + vvisible.Bool(visible); + return Ole::Method(DocWindow, "setVisible", vvisible); +} +bool OPENSheet::Select(String range) +{ + if (!Sheet) + return false; + VariantOle vrange; + vrange.BString(range); + if (!(Range = Ole::MethodGet(Sheet, "getCellRangeByName", vrange))) + return false; + return true; +} +bool OPENSheet::Select(int fromX, int fromY, int toX, int toY) +{ + if (!Sheet) + return false; + VariantOle vX1, vY1, vX2, vY2; + vX1.Int(fromX-1); // Comienza en 0 + vY1.Int(fromY-1); + vX2.Int(toX-1); // Comienza en 0 + vY2.Int(toY-1); + if (!(Range = Ole::MethodGet(Sheet, "getCellRangeByPosition", vY2, vX2, vY1, vX1))) + return false; + selectedAll = false; + return true; +} +bool OPENSheet::Select() +{ + if (!Sheet) + return false; + selectedAll = true; + return true; +} +/* +void OPENSheet::DefMatrix(int width, int height) +{ + return; +} +void OPENSheet::SetMatrixValue(int x, int y, ::Value value) +{ + return; +} +bool OPENSheet::FillSelectionMatrix() +{ + return false; +} +*/ +bool OPENSheet::Replace(Value search, Value replace) +{ + if (!Sheet) + return false; + ObjectOle Search; + if (!(Search = Ole::MethodGet(Sheet, "createReplaceDescriptor"))) + return false; + VariantOle vsearch, vreplace; + vsearch.BString(search); + Ole::Method(Search, "setSearchString", vsearch); + vreplace.BString(replace); + Ole::Method(Search, "setReplaceString", vreplace); + VariantOle vsrep; + vsrep.ObjectOle(Search); + + ObjectOle *data; + if (selectedAll) { + if (!Sheet) + return false; + data = &Sheet; + } else { + if (!Range) + return false; + data = &Range; + } + if (!Ole::Method(*data, "replaceAll", vsrep)) + return false; + return true; +} +Value OPENSheet::GetValue(int col, int row) +{ + if (!SelCell(col, row)) + return false; + return Ole::GetValue(Cell, "getFormula"); // Also valid getValue and getString +} +Value OPENSheet::GetValue(String cell) +{ + int row, col; + + OfficeSheet::CellToColRow(cell, col, row); + return GetValue(col, row); +} +bool OPENSheet::SaveAs(String fileName, String type) +{ + if (!Document) + return false; + + fileName = ForceExt(fileName, "." + type); + VariantOle vFileName; + vFileName.BString(OOo::ConvertToUrl(fileName)); + + String filter; + if (type == "xls") + filter = "MS Excel 97"; + else if (type == "pxl") + filter = "Pocket Excel"; + else if (type == "html") + filter = "HTML (StarCalc)"; + else if (type == "txt") + filter = "Text - txt - csv (StarCalc)"; + else if (type == "pdf") + filter = "calc_pdf_Export"; + else if (type == "ods") + filter = ""; + else + return false; + + VariantOle vArraySave; + if (filter.IsEmpty()) { + vArraySave.ArrayDim(0); + return Ole::Method(Document, "storeToURL", vArraySave, vFileName); + } else { + VariantOle vArg; + vArg.ObjectOle(OOo::MakePropertyValue("FilterName", filter)); + vArraySave.ArrayDim(1); + vArraySave.ArraySetVariant(1, vArg); + return Ole::Method(Document, "storeToURL", vArraySave, vFileName); + } +} + +bool OPENSheet::SelCell(int x, int y) +{ + if (!Sheet) + return false; + VariantOle vX, vY; + vX.Int(x-1); // Comienza en 0 + vY.Int(y-1); + if (!(Cell = Ole::MethodGet(Sheet, "getCellByPosition", vY, vX))) + return false; + return true; +} + +bool OPENSheet::SetValue(String cell, Value value) // cell in textual format like "B14" +{ + int col, row; + OfficeSheet::CellToColRow(cell, col, row); + return SetValue(col, row, value); +} +bool OPENSheet::SetValue(int col, int row, Value value) +{ + if (!SelCell(col, row)) + return false; + VariantOle vText; + vText.Value(value); + if (value.Is() || value.Is() || value.Is