1

Possible Duplicate:
Is COM broken in XE2, and how might I work around it?

The VCL applications referred to call EXCEL via "early binding" as instructed in Deborah Pate's Automating Excel Pages(http://www.djpate.freeserve.co.uk/AutoExcl.htm). Specifically, the applications modify the font of certain characters of two cells.

The application compiled using Delphi XE runs as expected. However, the application compiled using Delphi XE2 gives access violation in the second iteration of for-loop. I mean, if I do not use for-loop, and modify the two cells manually, the application runs as expected. I have no clue what the cause could be. Any help will be appreciated!

The EXCEL type library .pas files are generated by DXE and DXE2, respectively.

The source codes of the main unit are pasted below for your convenience. The whole directories are packaged into .zip files and can be downloaded here.

http://www.fileserve.com/file/HxyZw9w/TestExcelCharacters_1_DXE.zip

http://www.fileserve.com/file/pd8Q8qm/TestExcelCharacters_1_DXE2.zip

Source code in Delphi XE VCL application

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  ComObj, ActiveX, Excel_TLB;

procedure TForm1.FormCreate(Sender: TObject);
var
  lcid: integer;
  AppWasRunning: boolean;
  Result: HResult;
  Unknown: IUnknown;
  Excel: _Application;
  WBk: _Workbook;
  WS: _WorkSheet;

  l_RIdxStr, l_CIdxStr: string;
  l_CharStartIdx, l_CharLength: Integer;
  l_XlsSpinLine: string;

  I: Integer;
begin
  lcid := LOCALE_USER_DEFAULT;
  AppWasRunning := False;

  Result := GetActiveObject(CLASS_ExcelApplication, nil, Unknown);
  if (Result = MK_E_UNAVAILABLE) then
  begin
    Excel := CoExcelApplication.Create
  end
  else
  begin
    OleCheck(Result);
    OleCheck(Unknown.QueryInterface(_Application, Excel));
    AppWasRunning := True;
  end;
  Excel.Visible[lcid] := True;

  // Create empty Excel workbook
  WBk := Excel.Workbooks.Add(EmptyParam, LCID);

  WS := WBk.Worksheets.Item['Sheet1'] as _Worksheet;
  WS.Activate(LCID);

  WS.Range['D5', 'D5'].Value[xlRangeValueDefault] := 'Ru12.11256 Ru2-1.22587';
  WS.Range['D6', 'D6'].Value[xlRangeValueDefault] := 'Ru10.11256 Ru2-0.22587';
  WS.Range['D5', 'D5'].EntireColumn.AutoFit;

  for I := 0 to 1 do
  begin
    l_RIdxStr := 'D' + IntToStr(5 + I);
    l_CIdxStr := l_RIdxStr;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[1, 2].Font.Superscript := False;
    WS.Range[l_RIdxStr, l_CIdxStr].Characters[1, 2].Font.Subscript := False;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[3, 1].Font.Subscript := True;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[4, 7].Font.Superscript := True;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[11, 1].Font.Superscript := False;
    WS.Range[l_RIdxStr, l_CIdxStr].Characters[11, 1].Font.Subscript := False;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[12, 2].Font.Superscript := False;
    WS.Range[l_RIdxStr, l_CIdxStr].Characters[12, 2].Font.Subscript := False;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[14, 1].Font.Subscript := True;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[15, 8].Font.Superscript := True;
  end;
end;

end.

Source code in Delphi XE2 VCL application

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  ComObj, ActiveX, Excel_TLB;

procedure TForm1.FormCreate(Sender: TObject);
var
  lcid: integer;
  AppWasRunning: boolean;
  Result: HResult;
  Unknown: IUnknown;
  Excel: _Application;
  WBk: _Workbook;
  WS: _WorkSheet;

  l_RIdxStr, l_CIdxStr: string;
  l_CharStartIdx, l_CharLength: Integer;
  l_XlsSpinLine: string;

  I: Integer;
begin
  lcid := LOCALE_USER_DEFAULT;
  AppWasRunning := False;

  Result := GetActiveObject(CLASS_ExcelApplication, nil, Unknown);
  if (Result = MK_E_UNAVAILABLE) then
  begin
    Excel := CoExcelApplication.Create
  end
  else
  begin
    OleCheck(Result);
    OleCheck(Unknown.QueryInterface(_Application, Excel));
    AppWasRunning := True;
  end;
  Excel.Visible[lcid] := True;

  // Create empty Excel workbook
  WBk := Excel.Workbooks.Add(EmptyParam, LCID);

  WS := WBk.Worksheets.Item['Sheet1'] as _Worksheet;
  WS.Activate(LCID);

  WS.Range['D5', 'D5'].Value[xlRangeValueDefault] := 'Ru12.11256 Ru2-1.22587';
  WS.Range['D6', 'D6'].Value[xlRangeValueDefault] := 'Ru10.11256 Ru2-0.22587';
  WS.Range['D5', 'D5'].EntireColumn.AutoFit;

  for I := 0 to 1 do
  begin
    l_RIdxStr := 'D' + IntToStr(5 + I);
    l_CIdxStr := l_RIdxStr;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[1, 2].Font.Superscript := False;
    WS.Range[l_RIdxStr, l_CIdxStr].Characters[1, 2].Font.Subscript := False;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[3, 1].Font.Subscript := True;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[4, 7].Font.Superscript := True;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[11, 1].Font.Superscript := False;
    WS.Range[l_RIdxStr, l_CIdxStr].Characters[11, 1].Font.Subscript := False;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[12, 2].Font.Superscript := False;
    WS.Range[l_RIdxStr, l_CIdxStr].Characters[12, 2].Font.Subscript := False;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[14, 1].Font.Subscript := True;

    WS.Range[l_RIdxStr, l_CIdxStr].Characters[15, 8].Font.Superscript := True;
  end;
end;

end.
Community
  • 1
  • 1
SOUser
  • 3,802
  • 5
  • 33
  • 63
  • 2
    Maybe this can help you http://stackoverflow.com/questions/7886116/is-com-broken-in-xe2-and-how-might-i-work-around-it – RRUZ Nov 01 '11 at 15:05
  • 3
    This sounds identical to the issue I raised here recently: http://stackoverflow.com/questions/7886116/is-com-broken-in-xe2-and-how-might-i-work-around-it – David Heffernan Nov 01 '11 at 15:14
  • 3
    In fact, this question is a dupe. :-) – Warren P Nov 01 '11 at 15:15
  • Thank you for your opinions! Cannot believe I missed that great page! The cause should be the same. I didn't notice any workaround for the case described here, though. Could you help to comment? – SOUser Nov 01 '11 at 15:51
  • 1
    First step should be to extract the contents of the for loop into a separate function which receives `I` as a parameter. Then call it from the for loop passing `I`. – David Heffernan Nov 01 '11 at 17:00
  • Thank you for your very helpful comments! Meanwhile, the Delphi XE2 update 2 is released. According to the bugfix list, your QC report #100414 has been fixed! – SOUser Nov 02 '11 at 01:44
  • 1
    @Xichen Thanks. I'd noticed that too and was about to post a comment here to let you know. You are clearly ahead of me! – David Heffernan Nov 02 '11 at 10:54
  • @David That is because I was thinking to read your QC report more carefully this morning, when I saw the XE2 Update2 announcement :) – SOUser Nov 02 '11 at 12:36

0 Answers0