Как читать / писать статус флажка Excel в переполнении стека

Я работаю над проблемой, требующей от меня чтения / записи статуса флажка в данной ячейке в Excel.

Я знаю, что вы можете получить доступ к элементам управления ActiveX можно получить с помощью COM / OLE. Тем не менее, я не смог найти никакого решения этой проблемы. На самом деле, я даже не уверен, что вы можете получить доступ к флажку, используя row-column. Я изучил свойства флажка ActiveX. Найдены свойства top и left, но не row-column

Я хочу спросить, если:
1. Есть ли прямой способ сделать это.
2. Если нет, каким-либо косвенным способом, скажем, как-нибудь получить верхний / левый столбец, а затем получить позиции в строках / столбцах и сравнить их.
3. Есть ли способ сделать то же самое с элементами управления формы?

0

Решение

спасибо всем за ваши ответы. Я нашел что-то полезное на MSDN. Немного отредактировал и поделился с вами .. Спасибо за вашу поддержку всем

(Простите за форматирование)

Функция autowrap () из msdn полностью не редактируется:

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 (i.e. app.visible = 1)
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 1;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pXlApp, L"Visible", 1, x);
}

// Make it visible (i.e. 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 (i.e. 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

2

Другие решения

Несмотря на внешний вид, флажки не содержатся в электронной таблице; они нарисованы сверху этого. Поэтому они ничего не знают о строках или столбцах, и вы не можете ссылаться на них таким образом.

Флажки находятся в OLEObjects коллекция. Этот пример из Вот должен предоставить вам необходимую информацию:

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

Я не думаю, что флажки «в ячейках», есть несколько способов (о которых я могу думать), что вы можете получить значение.

Во-первых: не проверяйте значение флажка, проверьте значение его связанной ячейки (если она назначена)

Второе: использование чего-то вроде следующего псевдокода для определения, где находится элемент управления.

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
0
По вопросам рекламы [email protected]