6
votes

I am trying to convert a program from Delphi 2010 to Delphi XE7 (32 bit/windows VCL). Code that used to work in D2010 that automated Excel via late binding OLE now gives the exception "Unable to set the Window state property of the application class" in Delphi XE7, when the app is maximized or minimized.

I am getting the constants xlmaximized and xlminimized from the ExcelXP unit that has these constants: xlMaximized = $FFFFEFD7; xlMinimized = $FFFFEFD4;

However, if I use the simple constant values -4137 and -4140 the program does work OK. I realize I must be doing something simple that is wrong.

Below is some sample code that illustrates the problem. I tested this and it works in Delphi 2010, but not in Delphi XE7. I suppose it must be something to do with how constants are handled in newer versions(?) Can someone point me in the right direction? Thanks in advance!

//XLA is a global variable of type OLEVariant;
//Program uses ComObj and ExcelXP unit

//This proc just runs or connects to Excel

procedure TForm3.RunExcelClick(Sender: TObject);

begin
  try
    xla := GetActiveOLEObject('Excel.Application');
  except
    try
      xla := CreateOleObject('Excel.Application');
    except
      on E: Exception do
        begin
          ShowMessage(E.Message);
        end;
    end;
    xla.Visible := true;
  end;
end;


procedure TForm3.MaxExcelClick(Sender: TObject);
begin
   //This is the code that gives the exception
   xla.windowstate := xlmaximized;  //-4137;  Works OK if use this number
end;

procedure TForm3.MinExcelClick(Sender: TObject);
begin
   //Or this.  I also get exceptions 
  xla.windowstate := xlminimized ; //-4140; Works OK if use this number
end;
1
The constants are defined in the Excel object model, but it would appear not in Delphi XE7 (if they worked in Delphi 2010, then they must be defined there too). It is typical of late binding that you need to specify constants by their value (or declare them as constansts yourself. Are you sure that was not done in your original Delphi 2010 code?). You could always use early binding...chris neilsen
I think I've found the issue but dont really understand what is going on. The constants are the same in both and are defined with $ signs in ExcelXP unit as hexadecimal values. In Delphi2010 these get used as shortint values (up 32768) so the hex value for xlmaximized ($FFFFEFD7) gets used as -4137. But in Delphi XE7 this same hex value becomes 4294963159 (a LongInt). Im rather confused though when and why this change was made since it seems to break the use of OLE constants. Or maybe I am missing some basic setting in Delphi?CHEAPS
A short term solution is to wrap the constants like this: ShortInt(xlmaximized).CHEAPS
It's probably a data type issue. $FFFFEFD7 as a singed 32 bit integer is -4137 (and is what Excel expects). According to a quick goolge search Delphi Longint is signed 32 bit int, so maybe there is some type casting going on..chris neilsen
OK - I think Ive got it. The Longint/shortint was a red herring. Thanks for that @Chris and sorry it took me a while to absorb your point. Turns out you need to set this: System.Variants.DispatchUnsignedAsSigned := True; See this: docwiki.embarcadero.com/Libraries/XE7/en/…CHEAPS

1 Answers

3
votes

It's probably a data type issue. $FFFFEFD7 as a signed 32 bit integer is -4137 (and is what Excel expects). According to a quick goolge search Delphi Longint is signed 32 bit int, so maybe there is some type casting going on...

According to OP's own research, setting

System.Variants.DispatchUnsignedAsSigned := True;

solves it.