|
发表于 2021-12-1 00:43:20
|
显示全部楼层
没人帮你写吗?那我帮你写了,就趁此机会再复习一下C语言操作 COM接口
windows 下可以用 office 提供的 COM接口来操作 office
说真的,用 C语言操作 COM接口是真的不好玩
用 VBA 多好?为什么要用不适合的工具做这件事?
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <stdarg.h>
- #include <windows.h>
- #include <combaseapi.h>
- VARIANT invoke(IDispatch *disp, const OLECHAR *name, WORD wFlags, size_t count, ...) {
- VARIANT result = {0};
- DISPID dispIdMember;
- HRESULT hr = disp->lpVtbl->GetIDsOfNames(disp, &IID_NULL, (LPOLESTR *)&name, 1, LOCALE_USER_DEFAULT, &dispIdMember);
- if(hr != S_OK) return result;
- DISPPARAMS dp = {0};
- VARIANT *rgvarg = NULL;
- if(count) {
- rgvarg = malloc(sizeof(VARIANT) * count);
- va_list ap; va_start(ap, count);
- for(size_t i = 0; i < count; ++i) {
- rgvarg[i] = *va_arg(ap, VARIANT *);
- }
- va_end(ap);
- dp.rgvarg = rgvarg;
- dp.cArgs = count;
- }
- DISPID dispIdNamed = DISPID_PROPERTYPUT;
- if(wFlags & DISPATCH_PROPERTYPUT) {
- dp.rgdispidNamedArgs = &dispIdNamed;
- dp.cNamedArgs = 1;
- }
- disp->lpVtbl->Invoke(disp, dispIdMember, &IID_NULL, LOCALE_USER_DEFAULT, wFlags, &dp, &result, NULL, NULL);
- if(count) {
- va_list ap; va_start(ap, count);
- for(size_t i = 0; i < count; ++i) {
- *va_arg(ap, VARIANT *) = rgvarg[i];
- }
- va_end(ap);
- free(rgvarg);
- }
- return result;
- }
- VARIANT get_column(IDispatch *range) {
- VARIANT columns = invoke(range, L"Columns", DISPATCH_PROPERTYGET, 0);
- VARIANT count = invoke(columns.pdispVal, L"Count", DISPATCH_PROPERTYGET, 0);
- VariantClear(&columns);
- return count;
- }
- VARIANT get_row(IDispatch *range) {
- VARIANT rows = invoke(range, L"Rows", DISPATCH_PROPERTYGET, 0);
- VARIANT count = invoke(rows.pdispVal, L"Count", DISPATCH_PROPERTYGET, 0);
- VariantClear(&rows);
- return count;
- }
- int main(void) {
- CoInitialize(NULL);
- CLSID id;
- CLSIDFromProgID(L"Excel.Application", &id);
- IDispatch *Application;
- CoCreateInstance(&id, NULL, CLSCTX_LOCAL_SERVER, &IID_IDispatch, (LPVOID *)&Application);
- {
- VARIANT boolean = {.vt = VT_BOOL, .boolVal = true};
- invoke(Application, L"Visible", DISPATCH_PROPERTYPUT, 1, &boolean);
- VariantClear(&boolean);
- }
- VARIANT wbs = invoke(Application, L"Workbooks", DISPATCH_PROPERTYGET, 0);
- VARIANT filename = {.vt = VT_BSTR, .bstrVal = SysAllocString(L"C:\\cygwin64\\tmp\\test.xlsx")};
- VARIANT wb = invoke(wbs.pdispVal, L"Open", DISPATCH_METHOD, 1, &filename);
- VariantClear(&filename);
- VARIANT wss = invoke(wb.pdispVal, L"Worksheets", DISPATCH_PROPERTYGET, 0);
- VARIANT index = {.vt = VT_BSTR, .bstrVal = SysAllocString(L"Sheet1")};
- VARIANT ws = invoke(wss.pdispVal, L"Item", DISPATCH_PROPERTYGET, 1, &index);
- VariantClear(&index);
- VARIANT range = invoke(ws.pdispVal, L"UsedRange", DISPATCH_PROPERTYGET, 0);
- VARIANT column = get_column(range.pdispVal);
- VARIANT row = get_row(range.pdispVal);
- for(size_t y = 0; y < row.lVal; ++y) {
- for(size_t x = 0; x < column.lVal; ++x) {
- VARIANT vx = {.vt = VT_I4, .lVal = x + 1};
- VARIANT vy = {.vt = VT_I4, .lVal = y + 1};
- VARIANT cell = invoke(range.pdispVal, L"Item", DISPATCH_PROPERTYGET, 2, &vx, &vy);
- VARIANT value = invoke(cell.pdispVal, L"Value", DISPATCH_PROPERTYGET, 0);
- switch(value.vt) {
- case VT_BSTR:
- {
- int size = WideCharToMultiByte(CP_UTF8, 0, value.bstrVal, -1, NULL, 0, NULL, NULL);
- char *str = malloc(size);
- WideCharToMultiByte(CP_UTF8, 0, value.bstrVal, -1, str, size, NULL, NULL);
- printf("'%s' ", str);
- free(str);
- }
- break;
- case VT_R8:
- printf("'%.3lf' ", value.dblVal);
- break;
- default:
- printf("'null' ");
- }
- VariantClear(&value);
- VariantClear(&cell);
- VariantClear(&vy);
- VariantClear(&vx);
- }
- puts("");
- }
- VariantClear(&row);
- VariantClear(&column);
- VariantClear(&range);
- VariantClear(&ws);
- VariantClear(&wss);
- {
- VARIANT boolean = {.vt = VT_BOOL, .boolVal = false};
- invoke(wb.pdispVal, L"Close", DISPATCH_METHOD, 1, &boolean);
- VariantClear(&boolean);
- }
- VariantClear(&wb);
- VariantClear(&wbs);
- invoke(Application, L"Quit", DISPATCH_METHOD, 0);
- Application->lpVtbl->Release(Application);
- CoUninitialize();
- return 0;
- }
复制代码
- $ gcc -g -Wall -o main main.c -lole32 -luuid -loleaut32
- $ ./main
- 'hello world' 'main' 'printf' 'puts' 'getchar'
- '1234.000' '9876.000' '1024.000' '9999.000' '512.000'
- '文件' '开始' 'null' '数据' '视图'
- '帮助' 'null' '空间' 'null' 'null'
- 'null' 'null' 'null' 'null' 'null'
- '对齐方式' 'null' '检查单元格' 'null' '你好,世界'
- $
复制代码
|
|