📄 tmsuxlsrowcolentries.pas
字号:
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 + -