c++excelcom

setting an excel column to autofit using c++ and com automation fails


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;
  }

Solution

  • 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.