解决方案 »

  1.   

    1.把ChartTitle.Font.Name拆分(这个你会吧?)2.参考下列代码自行修改成三份,第一份取TChartTitle(TCaption?),第二部份取TFont,第三 部份取stringvar ref:TRttiContext;function GetCaption(aObject: TObject; PropName: string): TCaption;
    var
      RttiType: TRttiType;
      RttiProperty: TRttiProperty;
    begin
      Result := nil;
      RttiType := Ref.GetType(aObject.ClassType);
      RttiProperty := RttiType.GetProperty(PropName);
      if (RttiProperty <> nil) and (RttiProperty.GetValue(aObject).IsObject) and (RttiProperty.GetValue(aObject).AsObject is TCaption) then
      begin
        Result := TCaption(RttiProperty.GetValue(aObject).AsObject);
      end;
    end;
      

  2.   

    To  frank_lee_cn  And  bdmh
    非常感谢,但可以详细点吗?小女子刚接触Delphi,ps:字符串是从数据库里取出来的。“把ChartTitle.Font.Name拆分”这个我会的。
      

  3.   

    > 但是你这里好像不能针对动态字符串的情况吧。也就是说你提供的解决方案,只解决了当已经知道是要取什么属性值的情况,你觉得呢。限制当然是有的,
    但倒也不是很大。例如:Ref.GetType(aObject.ClassType);
    这里只要是TObject即可
    Result := TCaption(RttiProperty.GetValue(aObject).AsObject);
    这里也不一定要知道TCaption,
    用RttiProperty.GetValue(aObject).AsObject也可以继续处理下去,
    直到最终获得string值为止。
      

  4.   

    你有什么需求一定要  将字符串转成可运行的变量呢  说来听听。一定要这么做也是有办法,比较麻烦
    不过楼上给的方法都是针对Property是可以的,但是你这用的是com对象,所以是无效的
      

  5.   

    你确定这代码是可以执行的吗?我这里修改了很多遍都运行不了耶
    我首先把ExcelApp.ActiveSheet.后面的属性都以字符串类型存放在数据库里,要做某道题时,提取出相应的属性,再拼接成ExcelApp.ActiveSheet.Rang['A1:B1'].Font.Name可运行代码去Office上获取答案,这样就不用每道题都在Delphi上写一遍嘛。看样子你是有办法的,能私聊吗?
      

  6.   

    你确定这代码是可以执行的吗?我这里修改了很多遍都运行不了耶
    我首先把ExcelApp.ActiveSheet.后面的属性都以字符串类型存放在数据库里,要做某道题时,提取出相应的属性,再拼接成ExcelApp.ActiveSheet.Rang['A1:B1'].Font.Name可运行代码去Office上获取答案,这样就不用每道题都在Delphi上写一遍嘛。看样子你是有办法的,能私聊吗?
      

  7.   

    我首先把ExcelApp.ActiveSheet.后面的属性都以字符串类型存放在数据库里,要做某道题时,提取出相应的属性,再拼接成ExcelApp.ActiveSheet.Rang['A1:B1'].Font.Name可运行代码去Office上获取答案,这样就不用每道题都在Delphi上写一遍嘛。看样子你是有办法的,能私聊吗?
      

  8.   

    你是类似做这种考试系统的啊,应该就是分割题目。私聊可以的 QQ自已猜
    1,如果非要按你原设计,就是要利用QueryInterface这个接口,以及对象名字符串查找出对象,这个我再研究下 一起学习
    2,我觉得你没必要实现这么麻烦,其实某道题 你只需记录它在excel上面的 col row  就行了吧    
      

  9.   

    以下代码在XE及以后版本可用, 低于XE的版本, rtti相关代码需要变更.
    unit Unit2;interfaceuses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;type
      TCustomFont = class
      public
        function Name : string;
        function Size : integer;
      end;  TCustomChartTitle = class
      private
        FFont : TCustomFont;
      public
        destructor Destroy; override;
        function Font : TCustomFont;
      end;  TCustomChart = class
      private
        FChartTitle : TCustomChartTitle;
      public
        destructor Destroy; override;
        function ChartTitle : TCustomChartTitle;
      end;  TForm2 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
        FChart : TCustomChart;
      public
        { Public declarations }
      end;var
      Form2: TForm2;implementation
    uses System.Rtti, System.TypInfo;
    {$R *.dfm}procedure TForm2.Button1Click(Sender: TObject);
      function Process(const Value : string; AObject : TObject) : TObject;
      var
        obj: TCustomChart;
        rttiType: TRttiType;
        rttiMethod: TRttiMethod;
        rttiValue : TValue;
      begin
        result := nil;
        rttiType := nil;
        rttiMethod := nil;
        rttiValue := nil;    rttiType := TRttiContext.Create.GetType(AObject.ClassType);
        if rttiType = nil then
          exit;    rttiMethod := rttiType.GetMethod(Value);
        if rttiMethod = nil then
          exit;    rttiValue := rttiMethod.Invoke(AObject, []);
        if rttiValue.IsObject then
          result := rttiValue.AsObject
        else
        if rttiValue.TypeInfo^.Kind = tkInteger then
          ShowMessage(IntToStr( rttiValue.AsInteger))
        else
          ShowMessage(rttiValue.AsString);
      end;
    const
      //注意: 如果要反射的字符串和方法名称不相同, 则需要转义
      C_Font : array[0..1] of string = ('ChartTitle.Font.Name', 'ChartTitle.Font.Size');
    var
      i, j : integer;
      sList : Tstringlist;
      oObj : TObject;
    begin
      sList := Tstringlist.Create;
      FChart := TCustomChart.Create;
      try
        sList.Delimiter := '.';
        for i := Low(C_Font) to High(C_Font) do
        begin
          oObj := FChart;
          sList.DelimitedText := C_Font[i];
          for j := 0 to sList.Count - 1 do
          begin
            oObj := Process(sList.Strings[j], oObj);
            if oObj = nil then
              Break;
          end;
        end;
      finally
        FChart.Free;
        sList.Free;
      end;
    end;{ TCustomFont }function TCustomFont.Size: integer;
    begin
      Result := 12;
    end;function TCustomFont.Name: string;
    begin
      Result := 'a';
    end;{ TCustomChartTitle }destructor TCustomChartTitle.Destroy;
    begin
      if Assigned(FFont) then
        FreeAndNil(FFont);  inherited;
    end;function TCustomChartTitle.Font: TCustomFont;
    begin
      if not Assigned(FFont) then
        FFont := TCustomFont.Create;  Result := FFont;
    end;{ TCustomChart }function TCustomChart.ChartTitle: TCustomChartTitle;
    begin
      if not Assigned(FChartTitle) then
        FChartTitle := TCustomChartTitle.Create;  Result := FChartTitle;
    end;destructor TCustomChart.Destroy;
    begin
      if Assigned(FChartTitle) then
        FreeAndNil(FChartTitle);  inherited;
    end;end.
      

  10.   

    ExcelApp:=CreateOleObject('Excel.Application');  你是这样创建ExcelApp这个对象吧,这一点你没讲  各路大神都在讲RTTI,但是我认为com对象是不支持RTTI的。 而com对象通过名字查找 对象属性方法  还没找办法,但delphi本身肯定采用了这套机制,我也在学习。
    比如你执行这句,ExcelApp.ActiveSheet.Rang['A1:B1'].Font.Name  delphi是怎么找到这些属性呢?有一份excel, 数据库里存属性名  程序查找数据库中的属性  再执行获取想要的值。   
    你目前的设计不太好的,1 要存储的属性很多,还有这样真的很怪,设计程序是要找共性,不能这么直接 因为要访问什么东西就直接存起来  2,通过名字访问属性这个没有解决办法 你可以改一下,数据库只用存 某一道题对应excel上的的行列(col row)  ,再想获取内容,直接通过行列到excel去找你想要的属性
      

  11.   

    你这个方法我有想过,如果用VB做的话就比较适合,但用Delphi的话还是得要有字符串转换成变量这一步骤的,主要难度就在这里
      

  12.   

    你思维可以展开一点点,现在不能将字符串转成变量,换角度想想。
    如果你需要从字符串转成变量的并不多,我也想不到有什么理由你需要excel所有属性,可以参照我下面的这种。以你要获取某个单元格value为例,你数据库中存col  row  value(你要用到的属性名字)
    function  getvalue:string;
    var
      col,row :integer;
     valuestr:string; //这三个值从数据库中查
    begin
      if valuestr='value' then
        Result:=ExcelApp.Cells[col,row].Value;
      if valuestr='Font.Name' then
        Result:=ExcelApp.Cells[col,row].Font.Name;
    end;
      

  13.   

    这样不是我想要的,我需要的就是Result:=ExcelApp.Cells[col,row].Font.Name;这句的Font.Name不要写死在这里,要比较灵活地使用If判断里的valuestr。我目前就是像你这样写的,但考虑到以后维护及修改的问题会比较麻烦,不够灵活
      

  14.   

    在没找到更好的方法前,建议还是按照xsl510079027大神的建议做。