2

I try to set an excel column to autofit width using com automation. I get an access violation when calling Invoke. I know that the range that points to the column is ok, because I can use it to change the color, for instance.

This is my code

  DISPID dispid1;
  dispid1 = GetDispID(pWorksheet, L"Columns");
  VARIANT arg;
  arg.vt = VT_I4;
  arg.intVal = col;
  DISPPARAMS dp = {
        &arg, NULL, 1, 0
  };
  VariantInit(&vResult);
  hr = pWorksheet->Invoke(dispid1, IID_NULL, LOCALE_SYSTEM_DEFAULT,
        DISPATCH_PROPERTYGET, &dp, &vResult, NULL, NULL);
  if (FAILED(hr)) {
        ShowMessage("fail");
        return;
  }
  pRange = vResult.pdispVal;
  if (!pRange) {
        return;
  }

  DISPID dispid2;
  OLECHAR* szAutoFit = L"AutoFit";
  hr = pRange->GetIDsOfNames(IID_NULL, &szAutoFit, 1, LOCALE_USER_DEFAULT, &dispid2);
  if (FAILED(hr)) {
        ShowMessage("fail");
        return;
  }
  // the below call displays an access violation
  hr = pRange->Invoke(dispid2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, NULL, NULL,
        NULL, NULL);

  if (FAILED(hr)) {
        ShowMessage("fail");
        return;
  }
4
  • Just to point out. If your range is NOT ok, you may have good looking value for the color, and not for the width. In fact you can have anything for "all working good" to "my computer die". If you try to read some data you shouldn't it's Undefined Behavior (UB) in C++. And your soft may do whatever he want, if you are lucky, a nice error, if you don't bug only production :/ Commented Apr 30 at 7:06
  • 1
    You must pass a valid DISPPARAMS (even zeroed) structure to the pDispParams arg. Commented Apr 30 at 7:19
  • @MartinMorterol you are right, but it is not just that the function call succeds, the issue is that the resulting file has the color of the column applied, seems to me that this should prove that the range is ok. Commented Apr 30 at 8:13
  • @SimonMourier You are right, it is working now. Post it as an answer if you want to. Thank you very much Commented Apr 30 at 8:52

1 Answer 1

7
+500

The IDispatch::Invoke method is documented like this:

[in, out] pDispParams

Pointer to a DISPPARAMS structure containing an array of arguments, an array of argument DISPIDs for named arguments, and counts for the number of elements in the arrays.

It doesn't say the pDispParams can be null, while it does say it can for other parameters in the same method (it happens that documentation is not complete...).

So, for no parameters, you must allocate at least a zeroed DISPPARAMS structure.

PS: it's actually surprising that the method implementation doesn't validate against null (and return E_INVALIDARG or E_POINTER), it's usually how its done in the Windows API.

Sign up to request clarification or add additional context in comments.

1 Comment

Indeed, it is not the same a null than a pointer to a zeroed DISPPARAMS, my fault. Had the function returned an INVALIDARG, it would have saved me a lot of time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.