⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decodeformula2.pas

📁 一个经典的读写Excel的控件
💻 PAS
📖 第 1 页 / 共 4 页
字号:
          V := SizeOf(TPTGRef8);
        end
        else begin
          DecodeArea7(PPTGRef7(P).Col,PPTGRef7(P).Row,C,R);
          PPTGRef7(P).Row := (PPTGRef7(P).Row and $C000) + R;
          PPTGRef7(P).Col := C;
          V := SizeOf(TPTGRef7);
        end;
      end;
      ptgAreaN,      {2D}
      ptgAreaNV,     {4D}
      ptgAreaNA      {6D} : begin
        case Byte(P^) of
          ptgAreaN:  Byte(P^) := ptgArea;
          ptgAreaNV: Byte(P^) := ptgAreaV;
          ptgAreaNA: Byte(P^) := ptgAreaA;
        end;
        asm inc P end;
        if BIFF8 then begin
          DecodeArea8(PPTGArea8(P).Col1,PPTGArea8(P).Row1,C,R);
          PPTGArea8(P).Row1 := R;
          PPTGArea8(P).Col1 := (PPTGArea8(P).Col1 and $C000) + C;

          DecodeArea8(PPTGArea8(P).Col2,PPTGArea8(P).Row2,C,R);
          PPTGArea8(P).Row2 := R;
          PPTGArea8(P).Col2 := (PPTGArea8(P).Col2 and $C000) + C;
          V := SizeOf(TPTGArea8);
        end
        else begin
          DecodeArea7(PPTGArea7(P).Col1,PPTGArea7(P).Row1,C,R);
          PPTGArea7(P).Row1 := (PPTGArea7(P).Row1 and $C000) + R;
          PPTGArea7(P).Col1 := C;

          DecodeArea7(PPTGArea7(P).Col2,PPTGArea7(P).Row2,C,R);
          PPTGArea7(P).Row2 := (PPTGArea7(P).Row2 and $C000) + R;
          PPTGArea7(P).Col2 := C;
          V := SizeOf(TPTGArea7);
        end;
      end;

      ptgNameX       {39} ,
      ptgNameXV      {59} ,
      ptgNameXA      {79} : if BIFF8 then V := 7 else V := 25;

      ptgRef3d       {3A} ,
      ptgRef3dV      {5A} ,
      ptgRef3dA      {7A} : if BIFF8 then V := 7 else V := 17;

      ptgArea3d      {3B} ,
      ptgArea3dV     {5B} ,
      ptgArea3dA     {7B} : if BIFF8 then V := 11 else V := 21;

      ptgRefErr3d    {3C} ,
      ptgRefErr3dV   {5C} ,
      ptgRefErr3dA   {7C} : if BIFF8 then V := 7 else V := 17;

      ptgAreaErr3d   {3D} ,
      ptgAreaErr3dV  {5D} ,
      ptgAreaErr3dA  {7D} : if BIFF8 then V := 11 else V := 21;

      ptgFuncCEV     {58} : V := 3; // Not sure how to handle these.
      ptgFuncCEA     {78} : V := 3;
      else
        raise Exception.CreateFmt('Unknown ptg[%.2X] in Shared Formula',[Byte(P^)]);
//        V := 1;
    end;
    P := Pointer(Integer(P) + V);
  end;
end;

{ TFormulaRef }

constructor TFormulaRef.Create(Pg: byte; Ref: PByteArray; Abs: TAbsoluteRefs; C1, R1, C2, R2: word; Sht: integer);
begin
  FPTG := Pg;
  FRef := Ref;
  FAbsRef := Abs;
  FCol1 := C1;
  FRow1 := R1;
  FCol2 := C2;
  FRow2 := R2;
  FSheet := Sht
end;

function TFormulaRef.GetIsArea: boolean;
begin
  Result := FPTG in [ptgArea,ptgArea3d];
end;

{ TFormulaRefs }

procedure TFormulaRefs.Add(Pg: byte; Ref: PByteArray; Abs: TAbsoluteRefs; C1, R1, C2, R2: word; Sht: integer);
var
  FmlaRef: TFormulaRef;
begin
  FmlaRef := TFormulaRef.Create(Pg,Ref,Abs,C1,R1,C2,R2,Sht);
  inherited Add(FmlaRef);
end;

procedure TFormulaRefs.FindRefs(BIFF8: boolean; Buf: Pointer; Len: integer);
var
  V,C1,R1,C2,R2: integer;
  Ok: boolean;
  P,P2: PByteArray;
begin
  P := Buf;
  while (Integer(P) - Integer(Buf)) < Len do begin
    case P[0] of
      ptgExp         {01} : V := 1;
      ptgTbl         {02} : V := 5;
      ptgAdd         {03} : V := 1;
      ptgSub         {04} : V := 1;
      ptgMul         {05} : V := 1;
      ptgDiv         {06} : V := 1;
      ptgPower       {07} : V := 1;
      ptgConcat      {08} : V := 1;
      ptgLT          {09} : V := 1;
      ptgLE          {0A} : V := 1;
      ptgEQ          {0B} : V := 1;
      ptgGE          {0C} : V := 1;
      ptgGT          {0D} : V := 1;
      ptgNE          {0E} : V := 1;
      ptgIsect       {0F} : V := 1;
      ptgUnion       {10} : V := 1;
      ptgRange       {11} : V := 1;
      ptgUplus       {12} : V := 1;
      ptgUminus      {13} : V := 1;
      ptgPercent     {14} : V := 1;
      ptgParen       {15} : V := 1;
      ptgMissArg     {16} : V := 1;
      ptgStr         {17} : begin
        asm inc P end;
        if BIFF8 then begin
          if PByteArray(P)[1] = 0 then
            V := PByteArray(P)[0] + 2
          else
            V := (PByteArray(P)[0] * 2) + 2;
        end
        else
          V := PByteArray(P)[0] + 1;
      end;
      ptgAttr        {19} : begin
        asm inc P end;

        if P[0] = $04 then begin
          asm inc P end;
          V := (Word(Pointer(P)^) + 1) * SizeOf(word) + 2;
        end
        else
          V := 3;
      end;
      ptgSheet       {1A} : V := 1;
      ptgEndSheet    {1B} : V := 1;
      ptgErr         {1C} : V := 2;
      ptgBool        {1D} : V := 2;
      ptgInt         {1E} : V := 3;
      ptgNum         {1F} : V := 9;

      ptgArray       {20} ,
      ptgArrayV      {40} ,
      ptgArrayA      {60} : V := 8;

      ptgFunc        {21} ,
      ptgFuncV       {41} ,
      ptgFuncA       {61} : V := 3;

      ptgFuncVar     {22} ,
      ptgFuncVarV    {42} ,
      ptgFuncVarA    {62} : V := 4;

      ptgName        {23} ,
      ptgNameV       {43} ,
      ptgNameA       {63} : if BIFF8 then V := 7 else V := 15;

      ptgRef         {24} ,
      ptgRefV        {44} ,
      ptgRefA        {64} ,
      ptgRefN        {2C} ,
      ptgRefNV       {4C} ,
      ptgRefNA       {6C} : begin
                              P := Pointer(Integer(P) + 1);
                              if BIFF8 then begin
                                C1 := PPTGRef8(P).Col and $3FFF;
                                R1 := PPTGRef8(P).Row;
                                Add(ptgRef,P,MakeAbsR((PPTGRef8(P).Col and $8000) <> $8000,(PPTGRef8(P).Col and $4000) <> $4000),C1,R1,C1,R1,-1);
                                V := 4;
                              end
                              else begin
                                C1 := PPTGRef7(P).Col;
                                R1 := PPTGRef7(P).Row;
                                Add(ptgRef,P,MakeAbsR((PPTGRef8(P).Row and $8000) <> $8000,(PPTGRef8(P).Row and $4000) <> $4000),C1,R1,C1,R1,-1);
                                V := 3;
                              end;
                            end;

      ptgRefErr      {2A} ,
      ptgRefErrV     {4A} ,
      ptgRefErrA     {6A} : if BIFF8 then V := 5 else V := 4;

      ptgArea        {25} ,
      ptgAreaV       {45} ,
      ptgAreaA       {65} ,
      ptgAreaN       {2D} ,
      ptgAreaNV      {4D} ,
      ptgAreaNA      {6D} : begin
                              P := Pointer(Integer(P) + 1);
                              if BIFF8 then begin
                                C1 := PPTGArea8(P).Col1 and $3FFF;
                                R1 := PPTGArea8(P).Row1;
                                C2 := PPTGArea8(P).Col2 and $3FFF;
                                R2 := PPTGArea8(P).Row2;
                                Add(ptgArea,P,MakeAbsA((PPTGArea8(P).Col1 and $8000) <> $8000,(PPTGArea8(P).Col1 and $4000) <> $4000,(PPTGArea8(P).Col2 and $8000) <> $8000,(PPTGArea8(P).Col2 and $4000) <> $4000),C1,R1,C2,R2,-1);
                                V := 8;
                              end
                              else begin
                                C1 := PPTGArea7(P).Col1;
                                R1 := PPTGArea7(P).Row1;
                                C2 := PPTGArea7(P).Col2;
                                R2 := PPTGArea7(P).Row2;
                                Add(ptgArea,P,MakeAbsA((PPTGArea7(P).Row1 and $8000) <> $8000,(PPTGArea7(P).Row1 and $4000) <> $4000,(PPTGArea7(P).Row2 and $8000) <> $8000,(PPTGArea7(P).Row2 and $4000) <> $4000),C1,R1,C2,R2,-1);
                                V := 6;
                              end;
                            end;

      ptgAreaErr     {2B} ,
      ptgAreaErrV    {4B} ,
      ptgAreaErrA    {6B} : if BIFF8 then V := 9 else V := 7;

      ptgMemArea     {26} ,
      ptgMemAreaV    {46} ,
      ptgMemAreaA    {66} : V := Word(Pointer(Integer(P) + 1)^) + 7;

      ptgMemAreaN    {2E} ,
      ptgMemAreaNV   {4E} ,
      ptgMemAreaNA   {6E} : V := Word(Pointer(Integer(P) + 1)^) + 3;

      ptgMemErr      {27} ,
      ptgMemErrV     {47} ,
      ptgMemErrA     {67} : V := Word(Pointer(Integer(P) + 1)^) + 7;

      ptgMemNoMem    {28} ,
      ptgMemNoMemV   {48} ,
      ptgMemNoMemA   {68} : V := Word(Pointer(Integer(P) + 1)^) + 7;

      ptgMemNoMemN   {2F} ,
      ptgMemNoMemNV  {4F} ,
      ptgMemNoMemNA  {6F} : V := Word(Pointer(Integer(P) + 1)^) + 3;

      ptgMemFunc     {29} ,
      ptgMemFuncV    {49} ,
      ptgMemFuncA    {69} : V := Word(Pointer(Integer(P) + 1)^) + 3;

      ptgNameX       {39} ,
      ptgNameXV      {59} ,
      ptgNameXA      {79} : if BIFF8 then V := 7 else V := 25;

      ptgRef3d       {3A} ,
      ptgRef3dV      {5A} ,
      ptgRef3dA      {7A} : begin
                              P := Pointer(Integer(P) + 1);
                              if BIFF8 then begin
                                C1 := PPTGRef3d8(P).Col and $3FFF;
                                R1 := PPTGRef3d8(P).Row;
                                Add(ptgRef3d,P,MakeAbsR((PPTGRef3d8(P).Col and $8000) <> $8000,(PPTGRef3d8(P).Col and $4000) <> $4000),C1,R1,C1,R1,PPTGRef3d8(P).Index);
                                V := 6;
                              end
                              else begin
                                C1 := PPTGRef3d7(P).Col;
                                R1 := PPTGRef3d7(P).Row;
                                Add(ptgRef3d,P,MakeAbsR((PPTGRef3d7(P).Row and $8000) <> $8000,(PPTGRef3d7(P).Row and $4000) <> $4000),C1,R1,C1,R1,PPTGRef3d7(P).Index);
                                V := 16;
                              end;
                            end;

      ptgRefErr3d    {3C} ,
      ptgRefErr3dV   {5C} ,
      ptgRefErr3dA   {7C} : if BIFF8 then V := 7 else V := 17;

      ptgArea3d      {3B} ,
      ptgArea3dV     {5B} ,
      ptgArea3dA     {7B} : begin
                              P := Pointer(Integer(P) + 1);
                              if BIFF8 then begin
                                C1 := PPTGArea3d8(P).Col1 and $3FFF;
                                R1 := PPTGArea3d8(P).Row1;
                                C2 := PPTGArea3d8(P).Col2 and $3FFF;
                                R2 := PPTGArea3d8(P).Row2;
                                Add(ptgArea3d,P,MakeAbsA((PPTGArea3d8(P).Col1 and $8000) <> $8000,(PPTGArea3d8(P).Col1 and $4000) <> $4000,(PPTGArea3d8(P).Col2 and $8000) <> $8000,(PPTGArea3d8(P).Col2 and $4000) <> $4000),C1,R1,C2,R2,PPTGArea3d8(P).Index);
                                V := 10;
                              end
                              else begin
                                C1 := PPTGArea3d7(P).Col1;
                                R1 := PPTGArea3d7(P).Row1;
                                C2 := PPTGArea3d7(P).Col2;
                                R2 := PPTGArea3d7(P).Row2;
                                Add(ptgArea3d,P,MakeAbsA((PPTGArea3d7(P).Row1 and $8000) <> $8000,(PPTGArea3d7(P).Row1 and $4000) <> $4000,(PPTGArea3d7(P).Row2 and $8000) <> $8000,(PPTGArea3d7(P).Row2 and $4000) <> $4000),C1,R1,C2,R2,PPTGArea3d7(P).SheetIndex);
                                V := 20;
                              end;
                            end;

      ptgAreaErr3d   {3D} ,
      ptgAreaErr3dV  {5D} ,
      ptgAreaErr3dA  {7D} : if BIFF8 then V := 11 else V := 21;

      ptgFuncCEV     {58} : V := 3; // Not sure how to handle these.
      ptgFuncCEA     {78} : V := 3;
      else
        raise Exception.CreateFmt('Unknown ptg[%.2X] in FindRefs',[P[0]]);
    end;
    P := Pointer(Integer(P) + V);
  end;
end;

function TFormulaRefs.GetItems(Index: integer): TFormulaRef;
begin
  Result := TFormulaRef(inherited Items[Index]);
end;

function TFormulaRefs.MakeAbsR(C,R: boolean): TAbsoluteRefs;
begin
  Result := [];
  if C then
    Result := Result + [arCol1,arCol2];
  if R then
    Result := Result + [arRow1,arRow2];
end;

function TFormulaRefs.MakeAbsA(C1,R1,C2,R2: boolean): TAbsoluteRefs;
begin
  Result := [];
  if C1 then
    Result := Result + [arCol1];
  if R1 then
    Result := Result + [arRow1];
  if C2 then
    Result := Result + [arCol2];
  if R2 then
    Result := Result + [arRow2];
end;

function TFormulaRefs.Find(Formula: TFormulaCell): boolean;
begin
  FindRefs(FVersion = xvExcel97,Formula.PTGS,Formula.Size);
  Result := Count > 0;
end;

constructor TFormulaRefs.Create(Version: TExcelVersion);
begin
  FVersion := Version;
end;

procedure TFormulaRefs.AdjustRefR1InArea(C1, R1, C2, R2: word; Delta: integer);
var
  i: integer;
begin
  for i := 0 to Count - 1 do begin
    if Items[i].IsArea and (Items[i].FCol1 >= C1) and (Items[i].FRow1 >= R1) and (Items[i].FCol1 <= C2) and (Items[i].FRow1 <= R2) then begin
      if Items[i].FPTG = ptgArea then
        PPTGArea8(Items[i].FRef).Row1 := PPTGArea8(Items[i].FRef).Row1 + Delta;
    end;
  end;
end;

initialization
  StrTRUE := 'TRUE';
  StrFALSE := 'FALSE';
  FuncArgSeparator := ListSeparator;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -