#include "disphelper.h" #include "api.h" #include "buffer.h" #include #include using namespace std; #define XLS_TYPE 'XLS' #pragma warning(disable: 4244) ///////////////////////////////////////////////////////////////////// class zsExcel { public: zsExcel() { xls = 0; ptr = 0; size = 0; dhInitialize(TRUE); } ~zsExcel() { if (xls) { dhCallMethod(xls, L".Quit"); SAFE_RELEASE(xls); } dhUninitialize(TRUE); delete[] ptr; } void checksize(size_t size) { if (this->size < size || this->size > 2*size) { delete[] ptr; ptr = new double[size]; this->size = size; } } IDispatch *xls; double *ptr; size_t size; }; ///////////////////////////////////////////////////////////////////// void xls_destroy(void* ptr) { delete (zsExcel*)ptr; ptr = 0; } bool xls_isnumber(IDispatch *xls, int i, int j) { DISPATCH_OBJ(range); BOOL flag; dhGetValue(L"%o", &range, xls, L".ActiveSheet.Cells(%d,%d)", i, j); dhGetValue(L"%b", &flag, xls, L".WorksheetFunction.IsNumber(%o)", range); SAFE_RELEASE(range); return (flag!=0); } bool xls_istext(IDispatch *xls, int i, int j) { DISPATCH_OBJ(range); BOOL flag; dhGetValue(L"%o", &range, xls, L".ActiveSheet.Cells(%d,%d)", i, j); dhGetValue(L"%b", &flag, xls, L".WorksheetFunction.IsText(%o)", range); SAFE_RELEASE(range); return (flag!=0); } ///////////////////////////////////////////////////////////////////// void* xls_excel(void *ctx, int nargs, void** args) { zsExcel *o = new zsExcel; try { dhCreateObject(L"Excel.Application", NULL, &o->xls); } catch (string errstr) { delete o; o = 0; api_runtime_error(ctx, errstr.c_str()); } if (nargs > 0 && api_get_integer(ctx, args[0]) != 0) dhToggleExceptions(TRUE); return api_create_user(ctx, o, 0, xls_destroy, XLS_TYPE); } void* xls_visible(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); dhPutValue(o->xls, L".Visible = %b", api_get_integer(ctx, args[1])); return 0; } void* xls_open(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); dhCallMethod(o->xls, L".Workbooks.Open(%s)", api_get_string(ctx, args[1])); return 0; } void* xls_close(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); dhCallMethod(o->xls, L".Quit"); return 0; } void* xls_save(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); if (nargs > 1) { dhCallMethod(o->xls, L".ActiveWorkbook.SaveAs(%s)", api_get_string(ctx, args[1])); } else { dhCallMethod(o->xls, L".ActiveWorkbook.Save"); } return 0; } void* xls_activate(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); HRESULT ret = dhCallMethod(o->xls, L".ActiveWorkbook.Worksheets(%d).Activate", api_get_integer(ctx, args[1])); return api_create_integer(ctx, ret); } void* xls_add(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); HRESULT ret = dhCallMethod(o->xls, L".Sheets.Add"); if (nargs > 1) dhPutValue(o->xls, L".ActiveSheet.Name = %s", api_get_string(ctx, args[1])); return api_create_integer(ctx, ret); } void* xls_delete(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); HRESULT ret = dhCallMethod(o->xls, L".Sheets.Delete"); return api_create_integer(ctx, ret); } void* xls_get(void *ctx, int nargs, void** args) { if (nargs < 3) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); int i0, i1, j0, j1, nrow, ncol; if (api_is_array(args[1])) { i0 = api_get_integer(ctx, api_get_array_object(ctx, args[1], "0")); i1 = api_get_integer(ctx, api_get_array_object(ctx, args[1], "1")); } else { i0 = api_get_integer(ctx, args[1]); i1 = i0; } if (api_is_array(args[2])) { j0 = api_get_integer(ctx, api_get_array_object(ctx, args[2], "0")); j1 = api_get_integer(ctx, api_get_array_object(ctx, args[2], "1")); } else { j0 = api_get_integer(ctx, args[2]); j1 = j0; } if (i0 < 1 || i1 < i0 || j0 < 1 || j1 < j0) api_input_error(ctx); nrow = (i1-i0+1); ncol = (j1-j0+1); if (nrow > 1 || ncol > 1) { o->checksize(nrow * ncol); for (int i = i0; i <= i1; i++) { int k = (i-i0)*ncol; for (int j = j0; j <= j1; j++) { dhGetValue(L"%e", &o->ptr[k+j-j0], o->xls, L".ActiveSheet.Cells(%d,%d)", i, j); } } return api_create_user(ctx, o->ptr, 0, 0, 0); } if (xls_isnumber(o->xls, i0,j0)) { double value; dhGetValue(L"%e", &value, o->xls, L".ActiveSheet.Cells(%d,%d)", i0, j0); return api_create_real(ctx, value); } if (xls_istext(o->xls, i0,j0)) { LPWSTR wstr = NULL; dhGetValue(L"%S", &wstr, o->xls, L".ActiveSheet.Cells(%d,%d).Text", i0, j0); int n = WideCharToMultiByte(CP_ACP, 0, wstr, -1, 0, 0, 0, 0); zsBuffer buf(n+2); WideCharToMultiByte(CP_ACP, 0, wstr, -1, buf.u.pchar, n+2, NULL, NULL); void *ret = api_create_string(ctx, buf.u.pchar); dhFreeString(wstr); return ret; } return 0; } void* xls_set(void *ctx, int nargs, void** args) { if (nargs < 4) api_input_error(ctx); zsExcel *o = (zsExcel*)api_get_user(ctx, args[0], XLS_TYPE); int i0, i1, j0, j1; if (api_is_array(args[1])) { i0 = api_get_integer(ctx, api_get_array_object(ctx, args[1], "0")); i1 = api_get_integer(ctx, api_get_array_object(ctx, args[1], "1")); } else { i0 = api_get_integer(ctx, args[1]); i1 = i0; } if (api_is_array(args[2])) { j0 = api_get_integer(ctx, api_get_array_object(ctx, args[2], "0")); j1 = api_get_integer(ctx, api_get_array_object(ctx, args[2], "1")); } else { j0 = api_get_integer(ctx, args[2]); j1 = j0; } if (i0 < 1 || i1 < i0 || j0 < 1 || j1 < j0) api_input_error(ctx); if (api_is_number(args[3])) { real_t value = api_get_number(ctx, args[3]); for (int i = i0; i <= i1; i++) { for (int j = j0; j <= j1; j++) { dhPutValue(o->xls, L".ActiveSheet.Cells(%d,%d).Value = %e", i, j, value); } } return 0; } if (api_is_user(args[3])) { double *ptr = (double*)api_get_ptr(ctx, args[3]); int k = 0; for (int i = i0; i <= i1; i++) { for (int j = j0; j <= j1; j++) { dhPutValue(o->xls, L".ActiveSheet.Cells(%d,%d).Value = %e", i, j, ptr[k++]); } } return 0; } if (api_is_string(args[3])) { const char *str = api_get_string(ctx, args[3]); for (int i = i0; i <= i1; i++) { for (int j = j0; j <= j1; j++) { dhPutValue(o->xls, L".ActiveSheet.Cells(%d,%d).Value = %s", i, j, str); } } return 0; } api_input_error(ctx); return 0; } ///////////////////////////////////////////////////////////////////// class zsRegPrimitive { public: zsRegPrimitive() { api_add_primitive("excel", 0, xls_excel); api_add_primitive("visible", XLS_TYPE, xls_visible); api_add_primitive("open", XLS_TYPE, xls_open); api_add_primitive("close", XLS_TYPE, xls_close); api_add_primitive("save", XLS_TYPE, xls_save); api_add_primitive("activate", XLS_TYPE, xls_activate); api_add_primitive("add", XLS_TYPE, xls_add); api_add_primitive("delete", XLS_TYPE, xls_delete); api_add_primitive("__get", XLS_TYPE, xls_get); api_add_primitive("__set", XLS_TYPE, xls_set); } ~zsRegPrimitive() { } }; zsRegPrimitive xls_register;