15 #import "c:/program files (x86)/common files/microsoft shared/office12/mso.dll" \
16 rename( "RGB", "MSORGB" )
18 using namespace Office;
20 #import "c:/program files (x86)/common files/microsoft shared/vba/vba6/vbe6ext.olb" \
22 using namespace VBIDE;
24 #import "c:/program files (x86)/microsoft office/office12/excel.exe" \
25 rename( "DialogBox", "ExcelDialogBox" ) \
26 rename( "RGB", "ExcelRGB" ) \
27 rename( "CopyFile", "ExcelCopyFile" ) \
28 rename( "ReplaceText", "ExcelReplaceText" )
32 //#define SIMANTICS_DEBUG(...) \
33 //{ FILE *fp = fopen("d:/excel.log", "ab"); fprintf(fp, __VA_ARGS__); fflush(fp); fclose(fp); }
35 #define SIMANTICS_DEBUG(...)
38 using namespace Excel;
40 map<int, Excel::_WorksheetPtr> handles;
41 static int handleCounter = 1;
43 void replace(std::string &s, const std::string &s1, const std::string &s2) {
47 index = s.find(s1, index);
48 while(index != std::string::npos) {
49 s.replace(index, s1.length(), s2.c_str(), s2.length());
50 index = s.find(s1, index + 1);
55 boolean getString(JNIEnv *env, jstring str, char *target) {
58 const char *chars = env->GetStringUTFChars(str, &iscopy);
59 if(!chars) return false;
61 strcpy(target, chars);
63 env->ReleaseStringUTFChars(str, chars);
69 string getString(JNIEnv *env, jstring str) {
72 const char *chars = env->GetStringUTFChars(str, &iscopy);
74 string result = chars;
75 env->ReleaseStringUTFChars(str, chars);
80 Excel::_ApplicationPtr getApplication(bool create) {
82 Excel::_ApplicationPtr application;
85 HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
90 if (!SUCCEEDED(application.GetActiveObject(clsid)))
93 hr = application.CreateInstance(clsid);
102 application->EnableEvents = VARIANT_FALSE;
108 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_init(JNIEnv *env, jobject) {
110 SIMANTICS_DEBUG("Excel init\r\n");
112 HRESULT hr = ::OleInitialize(NULL);
118 Excel::_ApplicationPtr application = getApplication(true);
119 if(!application) return -1;
120 bstr_t version = application->GetVersion(0);
122 os << version << endl;
123 SIMANTICS_DEBUG("Init successful with version %s\r\n", os.str().c_str());
125 application->put_Interactive( 0, VARIANT_FALSE );
126 application->put_Visible( 0, VARIANT_FALSE );
133 Excel::_WorkbookPtr getWorkbook(const Excel::_ApplicationPtr &application, const string &fileName) {
135 SIMANTICS_DEBUG("getWorkbook(%s)\r\n", fileName.c_str());
137 for(int i=0;i<application->Workbooks->Count;i++) {
139 Excel::_WorkbookPtr workbook = application->Workbooks->GetItem( _variant_t(i+1) );
140 workbook->get_FullName(0, &fullName.GetBSTR());
141 std::string fullNameStr = fullName;
142 SIMANTICS_DEBUG("'%s'\r\n", fullNameStr.c_str());
143 if(fullNameStr == fileName) return workbook;
150 Excel::_WorksheetPtr getWorksheet(const Excel::_WorkbookPtr workbook, const string &sheetName) {
152 SIMANTICS_DEBUG("getWorksheet(%s)\r\n", sheetName.c_str());
154 for(int i=0;i<workbook->Sheets->Count;i++) {
155 Excel::_WorksheetPtr sheet = workbook->Sheets->GetItem(_variant_t(i+1));
156 std:string name = sheet->Name;
157 SIMANTICS_DEBUG("'%s'\r\n", name.c_str());
158 if(name == sheetName) return sheet;
167 JNIEXPORT jstring JNICALL Java_org_simantics_excel_Excel_open(JNIEnv *env, jobject, jstring fileName, jstring sheetName_) {
169 string name = getString(env, fileName);
170 string sheetName = getString(env, sheetName_);
172 _variant_t varOption( (long) DISP_E_PARAMNOTFOUND, VT_ERROR );
174 Excel::_ApplicationPtr application = getApplication(true);
175 if(!application) return env->NewStringUTF("Excel application could not be started.");
177 Excel::_WorkbookPtr workbook = getWorkbook(application, name);
180 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Opening.\r\n", name.c_str());
182 FILE *fp = fopen(name.c_str(), "r");
185 SIMANTICS_DEBUG("getWorkbook(%s) book was found. Opening file.\r\n", name.c_str());
188 workbook = application->Workbooks->OpenXML(_bstr_t(name.c_str()),
189 varOption, varOption);
190 if(!workbook) return env->NewStringUTF("File could not be opened.");
194 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creating file.\r\n", name.c_str());
196 workbook = application->Workbooks->Add(varOption);
198 if(!workbook) return env->NewStringUTF("New workbook could not be created.");
202 Excel::_WorksheetPtr sheet = workbook->Sheets->Add();
203 sheet->Name = _bstr_t(sheetName.c_str());
206 // Does not work for some unknown reason
207 for(int i=0;i<workbook->Sheets->Count;i++) {
208 Excel::_WorksheetPtr sheet = workbook->Sheets->GetItem(_variant_t(i+1));
209 if(name != sheetName)
210 sheet->PutVisible(0, Excel::XlSheetVisibility::xlSheetVeryHidden);
214 workbook->SaveAs(_bstr_t(name.c_str()), varOption, varOption, varOption, varOption,
215 varOption, Excel::xlExclusive, varOption, varOption, varOption, varOption, 0);
217 } catch (_com_error& e) {
218 _bstr_t bstr = _bstr_t(e.ErrorMessage());
220 _bstr_t bstr2 = _bstr_t(e.Description());
222 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 1 '%s' '%s'\r\n", name.c_str(), s.c_str(), s2.c_str());
223 strcpy(message, s2.c_str());
224 return env->NewStringUTF(message);
225 } catch (exception& e) {
226 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 2 '%s'\r\n", name.c_str(), e.what());
227 return env->NewStringUTF(e.what());
229 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 3 \r\n", name.c_str());
230 return env->NewStringUTF("Undefined error");
238 application->put_Interactive( 0, VARIANT_TRUE );
239 application->put_Visible( 0, VARIANT_TRUE );
241 workbook->Activate();
243 SIMANTICS_DEBUG("getWorkbook(%s) searches for sheet '%s'\r\n", name.c_str(), sheetName.c_str());
246 Excel::_WorksheetPtr sheet = getWorksheet(workbook, sheetName);
248 SIMANTICS_DEBUG("creating sheet %s for '%s'\r\n", sheetName.c_str(), name.c_str());
249 sheet = workbook->Sheets->Add();
250 sheet->Name = _bstr_t(sheetName.c_str());
252 int handle = handleCounter++;
253 SIMANTICS_DEBUG("opened handle %d for '%s'\r\n", handle, name.c_str());
254 handles[handle] = sheet;
257 return env->NewStringUTF(os.str().c_str());
259 } catch (_com_error& e) {
260 _bstr_t bstr = _bstr_t(e.ErrorMessage());
262 _bstr_t bstr2 = _bstr_t(e.Description());
264 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 1 '%s' '%s'\r\n", name.c_str(), s.c_str(), s2.c_str());
265 return env->NewStringUTF(s2.c_str());
266 } catch (exception& e) {
267 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 2 '%s'\r\n", name.c_str(), e.what());
268 return env->NewStringUTF(e.what());
270 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error\r\n", name.c_str());
271 return env->NewStringUTF("Unhandled exception.");
275 //Excel::_WorksheetPtr sheet = workbook->ActiveSheet;
276 //if(!sheet) return -4;
281 string cellName(int row, int column) {
285 SIMANTICS_DEBUG("cellName(%d, %d) -> ", row, column);
288 char rem = column % 26;
299 SIMANTICS_DEBUG("%s\r\n", result.c_str());
306 Excel::_WorkbookPtr getWorkbook(int handle) {
307 map<int, Excel::_WorkbookPtr>::iterator it = handles.find(handle);
308 if(it != handles.end()) return (*it).second;
313 Excel::_WorksheetPtr getWorksheet(int handle) {
314 map<int, Excel::_WorksheetPtr>::iterator it = handles.find(handle);
315 if(it != handles.end()) return (*it).second;
319 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setDouble(JNIEnv *env, jobject, jint handle, jint row, jint column, jdouble value) {
321 SIMANTICS_DEBUG("setDouble(%d, %d, %f)\r\n", row, column, value);
323 Excel::_WorksheetPtr sheet = getWorksheet(handle);
324 if(!sheet) return -1;
325 Excel::RangePtr range = sheet->Cells;
326 if(!range) return -2;
327 range->Item[row+1][column+1] = value;
333 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setString(JNIEnv *env, jobject, jint handle, jint row, jint column, jstring value) {
335 string val = getString(env, value);
337 SIMANTICS_DEBUG("setString(%d, %d, %s)\r\n", row, column, val.c_str());
339 Excel::_WorksheetPtr sheet = getWorksheet(handle);
340 if(!sheet) return -1;
341 Excel::RangePtr range = sheet->Cells;
342 if(!range) return -2;
344 const char *text = val.c_str();
346 range->Item[row+1][column+1] = text;
347 //range->Name[row+1][column+1] = text;
353 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setName(JNIEnv *env, jobject, jint handle, jint row, jint column, jstring value) {
355 string val = getString(env, value);
357 SIMANTICS_DEBUG("setName(%d, %d, %s)\r\n", row, column, val.c_str());
359 Excel::_WorksheetPtr sheet = getWorksheet(handle);
360 if(!sheet) return -1;
362 Excel::RangePtr range = sheet->GetRange(_variant_t(cellName(row, column).c_str()));
363 if(!range) return -2;
364 range->Name = _variant_t(val.c_str());
367 //range->Item[row+1][column+1] = text;
368 //range->Name[row+1][column+1] = text;
374 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setVisible(JNIEnv *env, jobject, jint handle, jboolean value) {
376 SIMANTICS_DEBUG("setVisible(%d)\r\n", value);
378 Excel::_WorksheetPtr sheet = getWorksheet(handle);
379 if(!sheet) return -1;
380 Excel::_ApplicationPtr application = sheet->Application;
381 if(!application) return -2;
384 application->put_Interactive( 0, VARIANT_TRUE );
385 application->put_Visible( 0, VARIANT_TRUE );
387 application->put_Interactive( 0, VARIANT_FALSE );
388 application->put_Visible( 0, VARIANT_FALSE );
395 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_close(JNIEnv *env, jobject, jint handle) {
397 SIMANTICS_DEBUG("closing handle %d\r\n", handle);
399 Excel::_WorksheetPtr sheet = getWorksheet(handle);
400 if(!sheet) return -1;
401 Excel::_ApplicationPtr application = sheet->Application;
402 if(!application) return -2;
404 Excel::_WorkbookPtr workbook = (Excel::_WorkbookPtr)sheet->Parent;
405 if(!workbook) return -3;
407 // SIMANTICS_DEBUG("About to save\r\n");
408 HRESULT hr = workbook->Save();
409 // workbook->put_Saved(0, VARIANT_TRUE);
411 SIMANTICS_DEBUG("Save failed with %d\r\n", hr);
414 // SIMANTICS_DEBUG("About to AcceptAllChanges\r\n");
415 // HRESULT hr = workbook->AcceptAllChanges();
418 //SIMANTICS_DEBUG("Close failed with %d\r\n", hr);
422 // Release this reference for Close
423 handles.erase(handle);
425 map<int, Excel::_WorksheetPtr>::iterator it = handles.begin();
426 for(;it != handles.end();++it) {
427 Excel::_WorksheetPtr sheet2 = (*it).second;
428 Excel::_WorkbookPtr book = (Excel::_WorkbookPtr)sheet2->Parent;
429 // The book remains open
430 if(book->Name == workbook->Name) return 0;
433 //SIMANTICS_DEBUG("About to PutUserControl\r\n");
434 //workbook->PutUserControl(VARIANT_FALSE);
435 SIMANTICS_DEBUG("About to Close\r\n");
436 hr = workbook->Close(VARIANT_FALSE);
438 SIMANTICS_DEBUG("Close failed with %d\r\n", hr);
444 application->Workbooks->get_Count(&remaining);
446 application->put_Interactive( 0, VARIANT_FALSE );
447 application->put_Visible( 0, VARIANT_FALSE );
448 hr = application->Quit();
450 SIMANTICS_DEBUG("Close failed with %d\r\n", hr);
455 // SIMANTICS_DEBUG("About to hide");
457 // application->put_Interactive( 0, VARIANT_FALSE );
458 // application->put_Visible( 0, VARIANT_FALSE );
460 // if(handles.empty())
461 // application->Quit();
468 JNIEXPORT jdouble JNICALL Java_org_simantics_excel_Excel_getDouble(JNIEnv *env, jobject, jint handle, jint row, jint column) {
470 SIMANTICS_DEBUG("getDouble(%d, %d)\r\n", row, column);
472 Excel::_WorksheetPtr sheet = getWorksheet(handle);
473 if(!sheet) return 0.0; // TODO: NAN
474 Excel::RangePtr range = sheet->Cells;
475 if(!range) return 0.0; // TODO: NAN
477 variant_t val = range->Item[row+1][column+1];
478 if (val.vt != VT_NULL) {
481 SIMANTICS_DEBUG("%f\r\n",d);
484 return 0.0; // TODO: NAN
487 return 0.0; // TODO: NAN
491 JNIEXPORT jstring JNICALL Java_org_simantics_excel_Excel_getString(JNIEnv *env, jobject, jint handle, jint row, jint column) {
493 //string val = getString(env, value);
495 SIMANTICS_DEBUG("getString(%d, %d)\r\n", row, column);
497 Excel::_WorksheetPtr sheet = getWorksheet(handle);
498 if(!sheet) return NULL;
499 Excel::RangePtr range = sheet->Cells;
500 if(!range) return NULL;
502 variant_t val = range->Item[row+1][column+1];
503 if (val.vt != VT_NULL) { // val.vt seems to be always VT_DISPATCH.
505 //this call will crash the application, if the cell is empty!
508 // TODO: this uses wide character (16-bit) while NewStringUTF expext regular character (8-bit), hence Java gets only the fisrt charater of the whole string.
509 _stprintf(text, _T("%s"), (LPCTSTR)bstrt);
510 //const char *text = bstrt;
511 SIMANTICS_DEBUG("%s\r\n",text);
513 // this code returns "??" for all cells.
514 //BSTR bstr = val.bstrVal;
515 //const char *text = _com_util::ConvertBSTRToString(bstr);
517 jstring ret = env->NewStringUTF((const char*)text);
524 SIMANTICS_DEBUG("%d\r\n",val.vt);