如何在c ++中读取/写入excelcheckbox状态

我正在处理一个问题,需要我读取/写入Excel中给定单元格中checkbox的状态。

我知道你可以访问使用COM / OLE访问的ActiveX控件。 但是,我一直没能find解决这个问题的办法。 事实上,我甚至不确定是否可以使用行列访问checkbox。 我研究了activeXcheckbox的属性。 find顶部和左侧的属性,但不是行列

我想问一下:1.有没有直接的方法可以做到这一点。 2.如果不是这样,任何间接的方式,比如说得到顶部/左边的列,然后得到行/列的位置,并比较两者。 3.有什么办法可以用表单控件做同样的事情吗?

感谢所有的答复。 我在MSDN上发现了一些有用的东西。 已经编辑了一下,并与您分享..感谢您的支持每个人

(原谅格式)

msdn中的Autowrap()函数是完全未经编辑的:

HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) { // Begin variable-argument list... va_list marker; va_start(marker, cArgs); if(!pDisp) { MessageBox(NULL, "NULL IDispatch passed to AutoWrap()", "Error", 0x10010); _exit(0); } // Variables used... DISPPARAMS dp = { NULL, NULL, 0, 0 }; DISPID dispidNamed = DISPID_PROPERTYPUT; DISPID dispID; HRESULT hr; char buf[200]; char szName[200]; // Convert down to ANSI WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL); // Get DISPID for name passed... hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID); if(FAILED(hr)) { sprintf(buf, "IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr); MessageBox(NULL, buf, "AutoWrap()", 0x10010); _exit(0); return hr; } // 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); if(FAILED(hr)) { sprintf(buf, "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr); MessageBox(NULL, buf, "AutoWrap()", 0x10010); _exit(0); return hr; } // End variable-argument section... va_end(marker); delete [] pArgs; return hr; } 

这是编辑的main()函数:

 int main() { // Initialize COM for this thread... CoInitialize(NULL); // Get CLSID for our server... CLSID clsid; HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid); if(FAILED(hr)) { ::MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 0x10010); return -1; } // Start server and get IDispatch... IDispatch *pXlApp; hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pXlApp); if(FAILED(hr)) { ::MessageBox(NULL, "Excel not registered properly", "Error", 0x10010); return -2; } // Make it visible (ie app.visible = 1) { VARIANT x; x.vt = VT_I4; x.lVal = 1; AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"Visible", 1, x); } // Make it visible (ie app.visible = 1) { VARIANT x; x.vt = VT_BSTR; x.bstrVal = ::SysAllocString (L"D:\\"); AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"DefaultFilePath", 1, x); } // Get Workbooks collection IDispatch *pXlBooks; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"Workbooks", 0); pXlBooks = result.pdispVal; } // Call Workbooks.Add() to get a new workbook... IDispatch *pXlBook; { VARIANT parm; parm.vt = VT_BSTR; parm.bstrVal = ::SysAllocString(L"a.xlsx"); VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_METHOD, &result, pXlBooks, L"Open", 1,parm); pXlBook = result.pdispVal; } // Get ActiveSheet object IDispatch *pXlSheet; { enter code here VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pXlBook, L"ActiveSheet",0); if(result.pdispVal != NULL) pXlSheet = result.pdispVal; } //Get shapes collection.. IDispatch *pShapes; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pXlSheet, L"Shapes",0); pShapes = result.pdispVal; } int nControls; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pShapes, L"Count",0); if(result.vt == VT_I4) nControls = result.lVal; } for(int i = 1; i <= nControls; ++i) { IDispatch * pShape; { VARIANT x; x.vt = VT_I4; x.lVal = i; VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_METHOD, &result, pShapes, L"Item",1, x); pShape = result.pdispVal; } IDispatch *pControlFormat = NULL; { VARIANT result; VariantInit(&result); AutoWrap(DISPATCH_PROPERTYGET, &result, pShape, L"Type",0); // msoFormControl if(result.lVal == 8) { VARIANT result0; VariantInit(&result0); AutoWrap(DISPATCH_PROPERTYGET, &result0, pShape, L"FormControlType",0); // xlCheckBox if(result0.lVal == 1) { // Get range containing cell to be tested VARIANT result2; VariantInit(&result2); IDispatch * range; { VARIANT param1; param1.vt= VT_BSTR; param1.bstrVal = ::SysAllocString(L"F5"); VARIANT result3; VariantInit(&result3); AutoWrap(DISPATCH_PROPERTYGET, &result3, pXlSheet,L"Range",1,param1); range = result3.pdispVal; } // Get the top, left, bottom, right of cell DOUBLE top, left, bottom, right; { VARIANT result4; VariantInit(&result4); AutoWrap(DISPATCH_PROPERTYGET,&result4, range,L"Top",0); top = result4.dblVal; AutoWrap(DISPATCH_PROPERTYGET,&result4, range,L"Left",0); left = result4.dblVal; AutoWrap(DISPATCH_PROPERTYGET,&result4, range,L"Height",0); bottom = top + result4.dblVal; AutoWrap(DISPATCH_PROPERTYGET,&result4, range,L"Width",0); right = left + result4.dblVal; } range->Release(); // Get the top, left of checkbox FLOAT shapetop, shapeleft; { VARIANT result5; VariantInit(&result5); AutoWrap(DISPATCH_PROPERTYGET,&result5, pShape,L"Top",0); shapetop = result5.fltVal; AutoWrap(DISPATCH_PROPERTYGET,&result5, pShape,L"Left",0); shapeleft = result5.fltVal; } // Get hold of control format VARIANT result1; VariantInit(&result1); AutoWrap(DISPATCH_PROPERTYGET, &result1, pShape, L"ControlFormat",0); pControlFormat = result1.pdispVal; // Check if the checkbox if within the range boundary. If yes, then check it, else dont if((top <= shapetop) && (bottom >= shapetop) && (left <= shapeleft) && (right >= shapeleft)) { // Perpare the parameter VARIANT parm; VARIANT_BOOL t = VARIANT_TRUE;; parm.vt = VT_BOOL; parm.pboolVal = &t; AutoWrap(DISPATCH_PROPERTYPUT, NULL, pControlFormat, L"Value", 1, parm); } } } } if(pControlFormat != NULL) pControlFormat->Release(); pShape->Release(); } // to save when we tell Excel to quit... { VARIANT x; x.vt = VT_I4; x.lVal = 1; AutoWrap(DISPATCH_METHOD, NULL, pXlBook, L"Save", 0); } // Wait for user... ::MessageBox(NULL, "All done.", "Notice", 0x10000); // Tell Excel to quit (ie App.Quit) AutoWrap(DISPATCH_METHOD, NULL, pXlApp, L"Quit", 0); // Release references... pShapes->Release(); pXlSheet->Release(); pXlBook->Release(); pXlBooks->Release(); pXlApp->Release(); // Uninitialize COM for this thread... CoUninitialize(); return 0; } 

欲了解更多详情:
http://support.microsoft.com/kb/216686
http://msdn.microsoft.com/en-us/library/office/bb149081%28v=office.12%29.aspx

尽pipe出现,电子表格不包含checkbox, 他们被画在上面。 所以他们不知道任何关于行或列的内容,你不能以这种方式引用它们。

checkbox保存在OLEObjects集合中。 这个例子从这里应该给你你需要的信息:

 Private Sub chkFinished_Click() ActiveSheet.OLEObjects("CheckBox1").Object.Value = 1 End Sub 

我不认为checkbox是“单元格”,有几种方法(我可以想到),你可以得到的价值。

第一:不检查checkbox的值,检查链接的单元格的值(如果分配的话)

第二:使用类似下面的伪代码来确定哪个控件是在哪里。

 ForEach Sheet.Controls As Control If Control.Type = Checkbox Then Row = 1 YPos = 0 Do If YPos + Sheet.Rows(Row).RowHeight > Control.Top Then Exit Do Else YPos = YPos + Sheets.Rows(Row).RowHeight End If Loop Column = 1 XPos = 0 Do If XPos + Sheet.Columns(Column).ColumnWidth > Control.Left Then Exit Do Else XPos = XPos + Sheets.Columns(Column).ColumnWidth End If Loop Debug.Print Control.Name & " is in Cell(" & XPos & ", " & YPos & ")" End If End ForEach