#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); bool opened = false; if (FileExists(fileName)) { if (!FileToTrashBin(fileName)) opened = true; } int ret; if (opened) ret = Ole::Method(Book, "Save"); else 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