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

📄 tmsuxlsrowcolentries.pas

📁 TMS Component Pack V5.0包含了超过 280 个为 Delphi 以及 C++Builder 设计的 TMS 生产控件
💻 PAS
📖 第 1 页 / 共 3 页
字号:
    ValueType:=VarDouble; //should be VarType(OleVariant(Value.Value)), but this converts numbers to strings
  end;
  {$ENDIF} //Delphi 6 or above

  if (ValueType = varDate) and (Options1904) then RealValue := double(RealValue) - Date1904Diff;

  case ValueType of
    varEmpty,
    varNull      : if (XF<>DefaultXF) then Cell:= TBlankRecord.CreateFromData(Row,Col,XF);

    varByte,
    varSmallint,
    varInteger,
    varSingle,
    varDouble,
    {$IFDEF FLX_HASCUSTOMVARIANTS}
      varShortInt, VarWord, VarLongWord, varInt64,
    {$ENDIF} //Delphi 6 or above
    varDate,
    varCurrency : if IsRK(RealValue) then Cell:= TRKRecord.CreateFromData(Row,Col,XF)
                                 else Cell:= TNumberRecord.CreateFromData(Row,Col,XF);

    varOleStr,
    varStrArg,
    {$IFDEF DELPHI2008UP}
    varUString,
    {$ENDIF}
    varString   : if (RealValue='') then
                  begin
                    if (XF<>DefaultXF) then Cell:= TBlankRecord.CreateFromData(Row,Col,XF);
                  end
                  else Cell:= TLabelSSTRecord.CreateFromData(Row,Col,XF,FGlobals.SST);

    varBoolean	: Cell:= TBoolErrRecord.CreateFromData(Row,Col,XF);
  end; //case

  if Found then Items[Row].Delete(Index);


  if Found and (Cell=nil) then  //We are deleting a cell
  begin
    if (Row>=Count) or (Items[Row]=nil)or(Items[Row].Count=0)then //Row emptied
      if (not FRowRecordList[Row].IsModified)  then     //Row always exists... it is added at the top
        FRowRecordList[Row]:=nil  //this frees the object
      else
      begin
        FRowRecordList[Row].MinCol:= 0;
        FRowRecordList[Row].MaxCol:= 0;
      end
    else
    begin
      FRowRecordList[Row].MinCol:= Items[Row][0].Column;
      FRowRecordList[Row].MaxCol:= Items[Row][Items[Row].Count-1].Column+1;
    end;
  end;

  //Remove all empty Rows at the end.
  k:=FRowRecordList.Count-1;
  while ((k>Row) or (Cell=nil)) and
        (k>=0) and (not FRowRecordList.HasRow(k) or (not FRowRecordList[k].IsModified)) and
        ((k>=Count) or (Items[k]=nil) or (Items[k].Count=0)) do
  begin
    FRowRecordList.Delete(k);
    if k<Count then Delete(k);
    dec(k);
  end;

  if Cell=nil then exit;

  if Col+1> FRowRecordList[Row].MaxCol then FRowRecordList[Row].MaxCol:=Col+1;
  if Col< FRowRecordList[Row].MinCol then FRowRecordList[Row].MinCol:=Col;

  if (Cell is TLabelSSTRecord) and (Length(RTFRuns)>0) then
  begin
    Rs.Value:=RealValue;
    Rs.RTFRuns:=Copy(RTFRuns);
    (Cell as TLabelSSTRecord).AsRichString:=Rs;
  end else
  Cell.Value:=RealValue;
  if Row>=Count then AddRecord(Cell, Row) else Items[Row].Insert(Index, Cell);
end;

procedure TCellList.FixFormulaTokens(const Formula: TFormulaRecord; const ShrFmlas: TShrFmlaRecordList);
var
  Key: Cardinal;
  Index: integer;
begin
  if not Formula.IsExp(Key) then exit;
  if ShrFmlas.Find(Key, Index) then
    Formula.MixShared(ShrFmlas[Index].Data, ShrFmlas[Index].DataSize)
  else //Array formula
  begin
    //nothing, it's ok
    //raise Exception.Create(ErrShrFmlaNotFound);
  end;
end;

function TCellList.FixTotalSize(const NeedsRecalc: boolean): int64;
var
  i:integer;
begin
  Result:=0;
  for i:=0 to Count-1 do Result:=Result+Items[i].FixTotalSize(NeedsRecalc);

end;

procedure TCellList.FixFormulas(const ShrFmlas: TShrFmlaRecordList);
var
  i, k: integer;
  it: TCellRecordList;
  OldFormulaSize: integer;
begin
  for i:=0 to Count-1 do
  begin
    it:=Items[i];
    for k:=0 to it.Count-1 do
      if it.Items[k] is TFormulaRecord then
      begin
        OldFormulaSize:=(it.Items[k] as TFormulaRecord).DataSize;
        FixFormulaTokens(it.Items[k] as TFormulaRecord, ShrFmlas);
        it.AdaptSize((it.Items[k] as TFormulaRecord).DataSize-OldFormulaSize);
      end;
  end;
end;

function TCellList.GetFormula(Row, Col: integer): UTF16String;
var
  Index: integer;
begin
  if (Row<0) or (Row>Max_Rows) then raise Exception.CreateFmt(ErrInvalidRow,[Row]);
  if (Col>Max_Columns)or (Col<0) then raise Exception.CreateFmt(ErrInvalidCol,[Col]);
  if Row>=Count then begin; Result:=''; exit; end;
  if Items[Row].Find(Col,Index) and (Items[Row][Index] is TFormulaRecord) then
  begin
    Result:=RPNToString(Items[Row][Index].Data, 22, Self);
  end else
  begin
    Result:='';
  end;
end;

procedure TCellList.SetFormula(Row, Col: integer; const Value: UTF16String);
begin
  AssignFormulaX(Row, Col, Value, unassigned , false); //Options1904 doesn't matter here.
end;

function TCellList.ArrayFormula(const Row, Col: integer): PArrayOfByte;
var
  Index: integer;
  Fmla: TFormulaRecord;
begin
  if (Row<0) or (Row>=Count) then raise Exception.CreateFmt(ErrInvalidRow,[Row]);
  if (Col>Max_Columns)or (Col<0) then raise Exception.CreateFmt(ErrInvalidCol,[Col]);
  if Items[Row].Find(Col,Index) and (Items[Row][Index] is TFormulaRecord) then
  begin
    Fmla:=(Items[Row][Index] as TFormulaRecord);
    if Fmla.ArrayRecord=nil then raise Exception.CreateFmt(ErrBadFormula,[Row, Col,1]);
    Result:=Fmla.ArrayRecord.Data;
  end else
  begin
    raise Exception.Create(ErrShrFmlaNotFound);
  end;
end;

function TCellList.TableFormula(const Row, Col: integer): PArrayOfByte;
var
  Index: integer;
  Fmla: TFormulaRecord;
begin
  if (Row<0) or (Row>=Count) then raise Exception.CreateFmt(ErrInvalidRow,[Row]);
  if (Col>Max_Columns)or (Col<0) then raise Exception.CreateFmt(ErrInvalidCol,[Col]);
  if Items[Row].Find(Col,Index) and (Items[Row][Index] is TFormulaRecord) then
  begin
    Fmla:=(Items[Row][Index] as TFormulaRecord);
    if Fmla.TableRecord=nil then raise Exception.CreateFmt(ErrBadFormula,[Row, Col,1]);
    Result:=(Items[Row][Index] as TFormulaRecord).TableRecord.Data;
  end else
  begin
    raise Exception.Create(ErrShrFmlaNotFound);
  end;
end;

function TCellList.GetName(const ExternSheet, NameId: integer): UTF16String;
begin
  Result := FGlobals.References.GetName(ExternSheet, NameId, FGlobals);
end;

function TCellList.GetSheetName(const SheetNumber: integer): UTF16String;
begin
  Result:= FGlobals.References.GetSheetName(SheetNumber, FGlobals);
end;

function TCellList.FindSheet(SheetName: UTF16String; out SheetIndex: Integer): Boolean;
var
  i: Integer;
begin
  SheetName:=WideUpperCase98(SheetName);
  for i:=0 to FGlobals.SheetCount-1 do
  begin
    if SheetName= WideUpperCase98(FGlobals.SheetName[i]) then
    begin
      SheetIndex := i;
      Result := True;
      exit;
    end;
  end;
  SheetIndex := -1;
  Result := False;
end;

function TCellList.AddExternSheet(const FirstSheet: Integer; const LastSheet: Integer): Integer;
begin
  Result := FGlobals.References.AddSheet(FGlobals.SheetCount, FirstSheet, LastSheet);
end;



procedure TCellList.AssignFormulaX(const Row, Col: integer; const Formula: UTF16String; const Value: variant; const Options1904: boolean);
var
  Cell: TCellRecord;
  ds: integer;
  Ps: TParseString;
  Index, k: integer;
  XF, DefaultXF: integer;
  Found: boolean;
begin
  if (Row<0) or (Row>Max_Rows) then raise Exception.CreateFmt(ErrInvalidRow,[Row]);
  if (Col>Max_Columns)or (Col<0) then raise Exception.CreateFmt(ErrInvalidCol,[Col]);
  FRowRecordList.AddRow(Row);
  if FRowRecordList[Row].IsFormatted then DefaultXF:=FRowRecordList[Row].XF
  else if FColInfoList.Find(Col, Index) then DefaultXF:=FColInfoList[Index].XF
  else DefaultXF:=15;

  Cell:=nil;
  Found:=(Row<Count) and Items[Row].Find(Col,Index);
  XF:=DefaultXF;
  if Found then XF:=Items[Row][Index].XF;
  //if Formula.XF>=0 then XF:=Formula.XF;

  if Formula='' then Cell:=nil else
  begin
    Ps:=TParseString.Create(Formula, Self, fmValue);
    try
      Ps.Parse;
      ds:= Ps.TotalSize+20;
      Cell:= TFormulaRecord.CreateFromData(xlr_FORMULA, ds, Row, Col, XF, Value, Options1904);
      Ps.CopyToPtr(Cell.Data, 20);
    finally
      FreeAndNil(Ps);
    end;
  end;

  try
    if Found then Items[Row].Delete(Index);

    if Found and (Cell=nil) then  //We are deleting a cell
    begin
      if (Row>=Count) or (Items[Row]=nil)or(Items[Row].Count=0)then //Row emptied
        if (not FRowRecordList[Row].IsModified)  then     //Row always exists... it is added at the top
          FRowRecordList[Row]:=nil  //this frees the object
        else
        begin
          FRowRecordList[Row].MinCol:= 0;
          FRowRecordList[Row].MaxCol:= 0;
        end
      else
      begin
        FRowRecordList[Row].MinCol:= Items[Row][0].Column;
        FRowRecordList[Row].MaxCol:= Items[Row][Items[Row].Count-1].Column+1;
      end;
    end;

    //Remove all empty Rows at the end.
    k:=FRowRecordList.Count-1;
    while ((k>Row) or (Cell=nil)) and
          (k>=0) and (not FRowRecordList.HasRow(k) or (not FRowRecordList[k].IsModified)) and
          ((k>=Count) or (Items[k]=nil) or (Items[k].Count=0)) do
    begin
      FRowRecordList.Delete(k);
      if k<Count then Delete(k);
      dec(k);
    end;

    if Cell=nil then exit;

    if Col+1> FRowRecordList[Row].MaxCol then FRowRecordList[Row].MaxCol:=Col+1;
    if Col< FRowRecordList[Row].MinCol then FRowRecordList[Row].MinCol:=Col;
    if Row>=Count then AddRecord(Cell, Row) else Items[Row].Insert(Index, Cell);
  except
    FreeAndNil(Cell);
    raise;
  end; //except
end;

procedure TCellList.SetFormat(const Row, Col, XF: integer);
var
  Index: integer;
  Value: TXlsCellValue;
begin
  if (Row<0) or (Row>Max_Rows) then raise Exception.CreateFmt(ErrInvalidRow,[Row]);
  if (Col>Max_Columns)or (Col<0) then raise Exception.CreateFmt(ErrInvalidCol,[Col]);

  if FRowRecordList.HasRow(Row) and (Row<Count) and (Row>=0) and Items[Row].Find(Col,Index) then
    Items[Row][Index].XF:=XF else
  begin
    Value.Value:=null;
    Value.XF:=XF;
    SetValueX2(Row,Col,Value, nil, false); //options1904 doesn't matter here since value is null.
  end;
end;

procedure TCellList.ArrangeInsertSheet(const SheetInfo: TSheetInfo);
var
  Data: PArrayOfByte;
  i, k: integer;
  it: TCellRecordList;
begin
  for i:=0 to Count-1 do
  begin
    it:=Items[i];
    for k:=0 to it.Count-1 do
      if it.Items[k] is TFormulaRecord then
      begin
        Data:= it.Items[k].Data;
        UXlsTokenArray_ArrangeInsertSheets(Data, 22, 22 + GetWord(Data, 20), SheetInfo);
      end;
  end;
end;

procedure TCellList.RecalcRowHeights(const Workbook: pointer; const Row1: integer; const Row2: integer; const Forced: Boolean; const KeepAutofit: Boolean; const Adjustment: Extended);
var
  RowCalc: TRowHeightCalc;
  RowMultDisplay: Extended;
  ColMultDisplay: Extended;
  i: integer;
  Row: TRowRecord;
  MaxCellHeight: integer;
  Columns: TCellRecordList;
  cCount: integer;
  c: integer;
  Cell: TXlsCellValue;
  rx: TRichString;
  CellHeight: integer;
  Color, index: integer;
  XF: integer;
begin
  //For autofitting all the workoobk:
  //Row2 should be = FRowRecordList.Count - 1;
  //Row1 should be 0.
  RowCalc := TRowHeightCalc.Create(FGlobals);
  try
    RowMultDisplay := RowMult;
    ColMultDisplay := ColMult;
    for i := Row1 to Row2 do
    begin
      if not FRowRecordList.HasRow(i) then
        continue;

      Row := FRowRecordList[i];
      if Row = nil then
        continue;

      if not Forced and not Row.IsAutoHeight then
        continue;

      rx.Value:='';
      SetLength(rx.RTFRuns, 0);
      MaxCellHeight := RowCalc.CalcCellHeight(i + 1, -1, rx, Row.XF, Workbook, RowMultDisplay, ColMultDisplay);
      if i < Count then
      begin
        Columns := Self[i];
        cCount := Columns.Count;
        for c := 0 to cCount - 1 do
        begin
          GetValueX2(i, Columns[c].Column, Cell, Rx.RTFRuns);
          XF:= Cell.XF;
          if XF<0 then
          begin
            XF:=FRowRecordList[i].XF;
            if (XF<=0) and (FColInfoList.Find(Columns[c].Column, index)) then XF:=  FColInfoList[index].XF;
          end;
          if (XF<0) then XF:=15;

          rx.Value:= XlsFormatValue1904(Cell.Value, TExcelFile(Workbook).FormatList[XF].Format, TExcelFile(Workbook).Options1904Dates, Color);

          CellHeight := RowCalc.CalcCellHeight(i + 1, Columns[c].Column + 1, rx, XF, Workbook, RowMultDisplay, ColMultDisplay);
          if CellHeight > MaxCellHeight then MaxCellHeight := CellHeight;
        end;

      end;

      if (Adjustment <> 1) and (Adjustment >= 0) then
        MaxCellHeight := Round(MaxCellHeight * Adjustment);

      if MaxCellHeight > $7FFF then
        MaxCellHeight := $7FFF;

      Row.Height := word(MaxCellHeight);
      if not KeepAutofit then
        Row.ManualHeight;

    end;
  finally
    FreeAndNil(RowCalc);
  end;
end;

procedure TCellList.AutofitColumn(const Workbook: pointer; const Column: integer; const ColCalc: TColWidthCalc; const RowMultDisplay: Extended; const ColMultDisplay: Extended; const IgnoreStrings: Boolean; const Adjustment: Extended);
var
  MaxWidth: integer;
  r: integer;
  CellWidth: integer;

  Cell: TXlsCellValue;
  rx: TRichString;
  Color, index: integer;
  XF: integer;

begin
  MaxWidth := 0;
  for r :=  FRowRecordList.Count - 1 downto 0 do
  begin
    GetValueX2(r, Column, Cell, Rx.RTFRuns);
    XF:= Cell.XF;
    if XF<0 then
    begin
      if (FRowRecordList.HasRow(r)) then XF:=FRowRecordList[r].XF;
      if (XF<=0) and (FColInfoList.Find(Column, index)) then XF:=  FColInfoList[index].XF;
    end;
    if (XF<0) then XF:=15;

    rx.Value:= XlsFormatValue1904(Cell.Value, TExcelFile(Workbook).FormatList[XF].Format, TExcelFile(Workbook).Options1904Dates, Color);

    if IgnoreStrings then
    begin
      if (Items[r].Find(Column,Index)) and (Items[r][index] is TLabelSSTRecord) then continue;
    end;

    CellWidth := ColCalc.CalcCellWidth(r + 1, Column + 1, rx, XF, Workbook, RowMultDisplay, ColMultDisplay);
    if CellWidth > MaxWidth then
      MaxWidth := CellWidth;

  end;

⌨️ 快捷键说明

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