12 #import "libid:{2df8d04c-5bfa-101b-bde5-00aa0044de52}" auto_rename
14 #import "libid:{0002e157-0000-0000-c000-000000000046}" auto_rename
16 #import "libid:{00020813-0000-0000-c000-000000000046}" auto_rename
18 using namespace Excel;
22 //#define SIMANTICS_DEBUG(...) \
23 //{ FILE *fp = fopen("d:/excel.log", "ab"); fprintf(fp, __VA_ARGS__); fflush(fp); fclose(fp); }
25 #define SIMANTICS_DEBUG(...)
27 //using namespace std;
28 //using namespace Office;
30 map<int, _WorksheetPtr> handles;
31 static int handleCounter = 1;
33 void replace(std::string &s, const std::string &s1, const std::string &s2) {
37 index = s.find(s1, index);
38 while(index != std::string::npos) {
39 s.replace(index, s1.length(), s2.c_str(), s2.length());
40 index = s.find(s1, index + 1);
45 boolean getString(JNIEnv *env, jstring str, char *target) {
48 const char *chars = env->GetStringUTFChars(str, &iscopy);
49 if(!chars) return false;
51 strcpy(target, chars);
53 env->ReleaseStringUTFChars(str, chars);
59 string getString(JNIEnv *env, jstring str) {
62 const char *chars = env->GetStringUTFChars(str, &iscopy);
64 string result = chars;
65 env->ReleaseStringUTFChars(str, chars);
70 Excel::_ApplicationPtr getApplication(bool create) {
72 Excel::_ApplicationPtr application;
75 HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
80 if (!SUCCEEDED(application.GetActiveObject(clsid)))
83 hr = application.CreateInstance(clsid);
92 application->EnableEvents = VARIANT_FALSE;
98 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_init(JNIEnv *env, jobject) {
100 SIMANTICS_DEBUG("Excel init\r\n");
102 HRESULT hr = ::OleInitialize(NULL);
108 Excel::_ApplicationPtr application = getApplication(true);
109 if(!application) return -1;
110 bstr_t version = application->GetVersion(0);
112 os << version << endl;
113 SIMANTICS_DEBUG("Init successful with version %s\r\n", os.str().c_str());
115 application->put_Interactive( 0, VARIANT_FALSE );
116 application->put_Visible( 0, VARIANT_FALSE );
123 Excel::_WorkbookPtr getWorkbook(const Excel::_ApplicationPtr &application, const string &fileName) {
125 SIMANTICS_DEBUG("getWorkbook(%s)\r\n", fileName.c_str());
127 for(int i=0;i<application->Workbooks->Count;i++) {
129 Excel::_WorkbookPtr workbook = application->Workbooks->GetItem( _variant_t(i+1) );
130 workbook->get_FullName(0, &fullName.GetBSTR());
131 std::string fullNameStr = fullName;
132 SIMANTICS_DEBUG("'%s'\r\n", fullNameStr.c_str());
133 if(fullNameStr == fileName) return workbook;
140 Excel::_WorksheetPtr getWorksheet(const Excel::_WorkbookPtr workbook, const string &sheetName) {
142 SIMANTICS_DEBUG("getWorksheet(%s)\r\n", sheetName.c_str());
144 for(int i=0;i<workbook->Sheets->Count;i++) {
145 Excel::_WorksheetPtr sheet = workbook->Sheets->GetItem(_variant_t(i+1));
146 std:string name = sheet->Name;
147 SIMANTICS_DEBUG("'%s'\r\n", name.c_str());
148 if(name == sheetName) return sheet;
157 JNIEXPORT jstring JNICALL Java_org_simantics_excel_Excel_open(JNIEnv *env, jobject, jstring fileName, jstring sheetName_) {
159 string name = getString(env, fileName);
160 string sheetName = getString(env, sheetName_);
162 _variant_t varOption( (long) DISP_E_PARAMNOTFOUND, VT_ERROR );
164 Excel::_ApplicationPtr application = getApplication(true);
165 if(!application) return env->NewStringUTF("Excel application could not be started.");
167 Excel::_WorkbookPtr workbook = getWorkbook(application, name);
170 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Opening.\r\n", name.c_str());
172 FILE *fp = fopen(name.c_str(), "r");
175 SIMANTICS_DEBUG("getWorkbook(%s) book was found. Opening file.\r\n", name.c_str());
178 workbook = application->Workbooks->OpenXML(_bstr_t(name.c_str()),
179 varOption, varOption);
180 if(!workbook) return env->NewStringUTF("File could not be opened.");
184 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creating file.\r\n", name.c_str());
186 workbook = application->Workbooks->Add(varOption);
188 if(!workbook) return env->NewStringUTF("New workbook could not be created.");
192 Excel::_WorksheetPtr sheet = workbook->Sheets->Add();
193 sheet->Name = _bstr_t(sheetName.c_str());
196 // Does not work for some unknown reason
197 for(int i=0;i<workbook->Sheets->Count;i++) {
198 Excel::_WorksheetPtr sheet = workbook->Sheets->GetItem(_variant_t(i+1));
199 if(name != sheetName)
200 sheet->PutVisible(0, Excel::XlSheetVisibility::xlSheetVeryHidden);
204 workbook->SaveAs(_bstr_t(name.c_str()), varOption, varOption, varOption, varOption,
205 varOption, Excel::xlExclusive, varOption, varOption, varOption, varOption, 0);
207 } catch (_com_error& e) {
208 _bstr_t bstr = _bstr_t(e.ErrorMessage());
210 _bstr_t bstr2 = _bstr_t(e.Description());
212 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 1 '%s' '%s'\r\n", name.c_str(), s.c_str(), s2.c_str());
213 strcpy(message, s2.c_str());
214 return env->NewStringUTF(message);
215 } catch (exception& e) {
216 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 2 '%s'\r\n", name.c_str(), e.what());
217 return env->NewStringUTF(e.what());
219 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 3 \r\n", name.c_str());
220 return env->NewStringUTF("Undefined error");
228 application->put_Interactive( 0, VARIANT_TRUE );
229 application->put_Visible( 0, VARIANT_TRUE );
231 workbook->Activate();
233 SIMANTICS_DEBUG("getWorkbook(%s) searches for sheet '%s'\r\n", name.c_str(), sheetName.c_str());
236 Excel::_WorksheetPtr sheet = getWorksheet(workbook, sheetName);
238 SIMANTICS_DEBUG("creating sheet %s for '%s'\r\n", sheetName.c_str(), name.c_str());
239 sheet = workbook->Sheets->Add();
240 sheet->Name = _bstr_t(sheetName.c_str());
242 int handle = handleCounter++;
243 SIMANTICS_DEBUG("opened handle %d for '%s'\r\n", handle, name.c_str());
244 handles[handle] = sheet;
247 return env->NewStringUTF(os.str().c_str());
249 } catch (_com_error& e) {
250 _bstr_t bstr = _bstr_t(e.ErrorMessage());
252 _bstr_t bstr2 = _bstr_t(e.Description());
254 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 1 '%s' '%s'\r\n", name.c_str(), s.c_str(), s2.c_str());
255 return env->NewStringUTF(s2.c_str());
256 } catch (exception& e) {
257 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error 2 '%s'\r\n", name.c_str(), e.what());
258 return env->NewStringUTF(e.what());
260 SIMANTICS_DEBUG("getWorkbook(%s) book was not found. Creation error\r\n", name.c_str());
261 return env->NewStringUTF("Unhandled exception.");
265 //Excel::_WorksheetPtr sheet = workbook->ActiveSheet;
266 //if(!sheet) return -4;
271 string cellName(int row, int column) {
275 SIMANTICS_DEBUG("cellName(%d, %d) -> ", row, column);
278 char rem = column % 26;
289 SIMANTICS_DEBUG("%s\r\n", result.c_str());
296 Excel::_WorkbookPtr getWorkbook(int handle) {
297 map<int, Excel::_WorkbookPtr>::iterator it = handles.find(handle);
298 if(it != handles.end()) return (*it).second;
303 Excel::_WorksheetPtr getWorksheet(int handle) {
304 map<int, Excel::_WorksheetPtr>::iterator it = handles.find(handle);
305 if(it != handles.end()) return (*it).second;
309 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setDouble(JNIEnv *env, jobject, jint handle, jint row, jint column, jdouble value) {
311 SIMANTICS_DEBUG("setDouble(%d, %d, %f)\r\n", row, column, value);
313 Excel::_WorksheetPtr sheet = getWorksheet(handle);
314 if(!sheet) return -1;
315 Excel::RangePtr range = sheet->Cells;
316 if(!range) return -2;
317 range->Item[row+1][column+1] = value;
323 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setString(JNIEnv *env, jobject, jint handle, jint row, jint column, jstring value) {
325 string val = getString(env, value);
327 SIMANTICS_DEBUG("setString(%d, %d, %s)\r\n", row, column, val.c_str());
329 Excel::_WorksheetPtr sheet = getWorksheet(handle);
330 if(!sheet) return -1;
331 Excel::RangePtr range = sheet->Cells;
332 if(!range) return -2;
334 const char *text = val.c_str();
336 range->Item[row+1][column+1] = text;
337 //range->Name[row+1][column+1] = text;
343 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setName(JNIEnv *env, jobject, jint handle, jint row, jint column, jstring value) {
345 string val = getString(env, value);
347 SIMANTICS_DEBUG("setName(%d, %d, %s)\r\n", row, column, val.c_str());
349 Excel::_WorksheetPtr sheet = getWorksheet(handle);
350 if(!sheet) return -1;
352 Excel::RangePtr range = sheet->GetRange(_variant_t(cellName(row, column).c_str()));
353 if(!range) return -2;
354 range->Name = _variant_t(val.c_str());
357 //range->Item[row+1][column+1] = text;
358 //range->Name[row+1][column+1] = text;
364 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_setVisible(JNIEnv *env, jobject, jint handle, jboolean value) {
366 SIMANTICS_DEBUG("setVisible(%d)\r\n", value);
368 Excel::_WorksheetPtr sheet = getWorksheet(handle);
369 if(!sheet) return -1;
370 Excel::_ApplicationPtr application = sheet->Application;
371 if(!application) return -2;
374 application->put_Interactive( 0, VARIANT_TRUE );
375 application->put_Visible( 0, VARIANT_TRUE );
377 application->put_Interactive( 0, VARIANT_FALSE );
378 application->put_Visible( 0, VARIANT_FALSE );
385 JNIEXPORT jint JNICALL Java_org_simantics_excel_Excel_close(JNIEnv *env, jobject, jint handle) {
387 SIMANTICS_DEBUG("closing handle %d\r\n", handle);
389 Excel::_WorksheetPtr sheet = getWorksheet(handle);
390 if(!sheet) return -1;
391 Excel::_ApplicationPtr application = sheet->Application;
392 if(!application) return -2;
394 Excel::_WorkbookPtr workbook = (Excel::_WorkbookPtr)sheet->Parent;
395 if(!workbook) return -3;
397 // SIMANTICS_DEBUG("About to save\r\n");
398 HRESULT hr = workbook->Save();
399 // workbook->put_Saved(0, VARIANT_TRUE);
401 SIMANTICS_DEBUG("Save failed with %d\r\n", hr);
404 // SIMANTICS_DEBUG("About to AcceptAllChanges\r\n");
405 // HRESULT hr = workbook->AcceptAllChanges();
408 //SIMANTICS_DEBUG("Close failed with %d\r\n", hr);
412 // Release this reference for Close
413 handles.erase(handle);
415 map<int, Excel::_WorksheetPtr>::iterator it = handles.begin();
416 for(;it != handles.end();++it) {
417 Excel::_WorksheetPtr sheet2 = (*it).second;
418 Excel::_WorkbookPtr book = (Excel::_WorkbookPtr)sheet2->Parent;
419 // The book remains open
420 if(book->Name == workbook->Name) return 0;
423 //SIMANTICS_DEBUG("About to PutUserControl\r\n");
424 //workbook->PutUserControl(VARIANT_FALSE);
425 SIMANTICS_DEBUG("About to Close\r\n");
426 hr = workbook->Close(VARIANT_FALSE);
428 SIMANTICS_DEBUG("Close failed with %d\r\n", hr);
434 application->Workbooks->get_Count(&remaining);
436 application->put_Interactive( 0, VARIANT_FALSE );
437 application->put_Visible( 0, VARIANT_FALSE );
438 hr = application->Quit();
440 SIMANTICS_DEBUG("Close failed with %d\r\n", hr);
445 // SIMANTICS_DEBUG("About to hide");
447 // application->put_Interactive( 0, VARIANT_FALSE );
448 // application->put_Visible( 0, VARIANT_FALSE );
450 // if(handles.empty())
451 // application->Quit();
458 JNIEXPORT jdouble JNICALL Java_org_simantics_excel_Excel_getDouble(JNIEnv *env, jobject, jint handle, jint row, jint column) {
460 SIMANTICS_DEBUG("getDouble(%d, %d)\r\n", row, column);
462 Excel::_WorksheetPtr sheet = getWorksheet(handle);
463 if(!sheet) return 0.0; // TODO: NAN
464 Excel::RangePtr range = sheet->Cells;
465 if(!range) return 0.0; // TODO: NAN
467 variant_t val = range->Item[row+1][column+1];
468 if (val.vt != VT_NULL) {
471 SIMANTICS_DEBUG("%f\r\n",d);
474 return 0.0; // TODO: NAN
477 return 0.0; // TODO: NAN
481 JNIEXPORT jstring JNICALL Java_org_simantics_excel_Excel_getString(JNIEnv *env, jobject, jint handle, jint row, jint column) {
483 //string val = getString(env, value);
485 SIMANTICS_DEBUG("getString(%d, %d)\r\n", row, column);
487 Excel::_WorksheetPtr sheet = getWorksheet(handle);
488 if(!sheet) return NULL;
489 Excel::RangePtr range = sheet->Cells;
490 if(!range) return NULL;
492 _bstr_t val = _bstr_t(range->Item[row + 1][column + 1]);
493 //if (val.vt != VT_NULL) { // val.vt seems to be always VT_DISPATCH.
495 //this call will crash the application, if the cell is empty!
496 //_bstr_t bstrt = val;
497 //std::string text(val);
501 // 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.
502 //_stprintf(text, _T("%s"), (LPCTSTR)bstrt);
503 //const char *text = bstrt;
504 SIMANTICS_DEBUG("%s\r\n",text);
509 return env->NewStringUTF(text.c_str());
515 //SIMANTICS_DEBUG("%d\r\n",val.vt);