📄 tmsuxlspagebreaks.pas
字号:
unit tmsUXlsPageBreaks;
{$INCLUDE ..\FLXCOMPILER.INC}
interface
uses tmsUXlsBaseRecords, tmsUXlsBaseList, tmsXlsMessages, Classes, SysUtils, tmsUFlxMessages, tmsUOle2Impl;
type
THBreakData= packed record
Row: Word;
Col1: Word;
Col2: Word;
end;
TVBreakData= packed record
Col: Word;
Row1: Word;
Row2: Word;
end;
THPageBreakRecord = class (TBaseRecord)
public
function Count: Word;
function BreakData(const index: integer): THBreakData;
end;
TVPageBreakRecord = class (TBaseRecord)
public
function Count: Word;
function BreakData(const index: integer): TVBreakData;
end;
THPageBreak=class
public
BreakData: THBreakData;
constructor Create(const aBreakData: THBreakData);
function CopyTo: THPageBreak;
end;
TVPageBreak=class
public
BreakData: TVBreakData;
constructor Create(const aBreakData: TVBreakData);
function CopyTo: TVPageBreak;
end;
THPageBreakList= class (TBaseList)
private
procedure SaveToStreamExt(const DataStream: TOle2File; const FirstRecord, RecordCount: integer);
procedure CalcIncludedRangeRecords(const CellRange: TXlsCellRange; out FirstRecord, RecordCount: integer);
function TotalSizeExt(const RecordCount:integer): int64;
{$INCLUDE THPageBreakListHdr.inc}
public
procedure AddRecord(const aRecord: THPageBreakRecord);
procedure AddBreak(const aRow: Longint);
procedure DeleteBreak(const aRow: Integer);
procedure CopyFrom(const aBreakList: THPageBreakList);
procedure SaveToStream(const DataStream: TOle2File);
procedure SaveRangeToStream(const DataStream: TOle2File; const CellRange: TXlsCellRange);
function TotalSize: int64;
function TotalRangeSize(const CellRange: TXlsCellRange): int64;
procedure InsertRows(const DestRow: integer; const aCount: integer);
procedure DeleteRows(const DestRow: integer; const aCount: integer);
function HasPageBreak( const Row: integer): boolean;
end;
TVPageBreakList= class (TBaseList)
private
procedure SaveToStreamExt(const DataStream: TOle2File; const FirstRecord, RecordCount: integer);
procedure CalcIncludedRangeRecords(const CellRange: TXlsCellRange; out FirstRecord, RecordCount: integer);
function TotalSizeExt(const RecordCount:integer): int64;
{$INCLUDE TVPageBreakListHdr.inc}
public
procedure AddRecord(const aRecord: TVPageBreakRecord);
procedure AddBreak(const aCol: Longint);
procedure DeleteBreak(const aCol: Integer);
procedure CopyFrom(const aBreakList: TVPageBreakList);
procedure SaveToStream(const DataStream: TOle2File);
procedure SaveRangeToStream(const DataStream: TOle2File; const CellRange: TXlsCellRange);
function TotalSize: int64;
function TotalRangeSize(const CellRange: TXlsCellRange): int64;
procedure InsertCols(const DestCol: integer; const aCount: integer);
procedure DeleteCols(const DestCol: integer; const aCount: integer);
function HasPageBreak( const Col: integer): boolean;
end;
implementation
{$INCLUDE THPageBreakListImp.inc}
{$INCLUDE TVPageBreakListImp.inc}
{ THPageBreakRecord }
function THPageBreakRecord.BreakData(const index: integer): THBreakData;
begin
Move(Data[2+index*SizeOf(THBreakData)],Result, SizeOf(THBreakData));
end;
function THPageBreakRecord.Count: Word;
begin
Result:= GetWord(Data, 0);
end;
{ THPageBreak }
function THPageBreak.CopyTo: THPageBreak;
begin
Result:= THPageBreak.Create(BreakData);
end;
constructor THPageBreak.Create(const aBreakData: THBreakData);
begin
inherited Create;
BreakData:= aBreakData;
end;
{ THPageBreakList }
procedure THPageBreakList.AddBreak(const aRow: Integer);
var
Index: integer;
BreakData: THBreakData;
begin
BreakData.Row:=aRow;
BreakData.Col1:=0;
BreakData.Col2:=$FF;
if Count>MaxHPageBreaks then raise Exception.Create(ErrTooManyPageBreaks);
if not Find(aRow, Index) then Insert(Index, THPageBreak.Create(BreakData));
end;
procedure THPageBreakList.DeleteBreak(const aRow: Integer);
var
Index: integer;
begin
if Find(aRow, Index) then Delete(Index);
end;
procedure THPageBreakList.AddRecord(const aRecord: THPageBreakRecord);
var
i, Index: integer;
begin
for i:=0 to aRecord.Count - 1 do
if not Find(aRecord.BreakData(i).Row, Index) then Insert(Index, THPageBreak.Create(aRecord.BreakData(i)));
aRecord.Free;
end;
procedure THPageBreakList.CalcIncludedRangeRecords(const CellRange: TXlsCellRange; out FirstRecord, RecordCount: integer);
var
LastRecord, i: integer;
begin
Sort; //just in case
FirstRecord:=-1;
LastRecord:=-1;
for i:=0 to Count-1 do
begin
if (FirstRecord<0) and (Items[i].BreakData.Row>=CellRange.Top) then FirstRecord:=i;
if Items[i].BreakData.Row<=CellRange.Bottom then LastRecord:=i;
end;
if (FirstRecord>=0) and (LastRecord>=0) and (FirstRecord<=LastRecord) then
RecordCount:=LastRecord-FirstRecord+1
else
begin
FirstRecord:=0;
RecordCount:=0;
end;
end;
procedure THPageBreakList.CopyFrom(const aBreakList: THPageBreakList);
var
i:integer;
begin
if aBreakList=nil then exit;
for i:=0 to aBreakList.Count-1 do Add(aBreakList[i].CopyTo);
end;
procedure THPageBreakList.DeleteRows(const DestRow, aCount: integer);
var
Index: integer;
i: integer;
begin
Find(DestRow, Index);
for i:=Count-1 downto Index do
if Items[i].BreakData.Row<DestRow+aCount then Delete(i) else dec(Items[i].BreakData.Row, aCount);
end;
procedure THPageBreakList.InsertRows(const DestRow, aCount: integer);
var
Index: integer;
i: integer;
begin
Find(DestRow, Index);
for i:=Index to Count-1 do IncMax(Items[i].BreakData.Row, aCount, $FFFF);
end;
procedure THPageBreakList.SaveToStreamExt(const DataStream: TOle2File; const FirstRecord, RecordCount: integer);
var
RecordHeader: TRecordHeader;
MyRecordCount: word;
i: integer;
begin
if RecordCount > 0 then
begin
Sort; //just in case...
MyRecordCount:=RecordCount;
RecordHeader.Id:= xlr_HORIZONTALPAGEBREAKS;
RecordHeader.Size:= SizeOf(MyRecordCount)+RecordCount*SizeOf(THBreakData);
DataStream.WriteMem(RecordHeader, Sizeof(RecordHeader));
DataStream.WriteMem(MyRecordCount, Sizeof(MyRecordCount));
for i:=FirstRecord to FirstRecord+RecordCount-1 do
begin
DataStream.WriteMem(Items[i].BreakData, SizeOf(Items[i].BreakData));
end;
end;
end;
procedure THPageBreakList.SaveRangeToStream(const DataStream: TOle2File; const CellRange: TXlsCellRange);
var
FirstRecord, RecordCount: integer;
begin
CalcIncludedRangeRecords(CellRange, FirstRecord, RecordCount);
SaveToStreamExt(DataStream, FirstRecord, RecordCount);
end;
procedure THPageBreakList.SaveToStream(const DataStream: TOle2File);
begin
SaveToStreamExt(DataStream, 0, Count);
end;
function THPageBreakList.TotalRangeSize(const CellRange: TXlsCellRange): int64;
var
FirstRecord, RecordCount: integer;
begin
CalcIncludedRangeRecords(CellRange, FirstRecord, RecordCount);
Result:=TotalSizeExt(RecordCount);
end;
function THPageBreakList.TotalSize: int64;
begin
Result:=TotalSizeExt(Count);
end;
function THPageBreakList.TotalSizeExt(const RecordCount: integer): int64;
begin
if RecordCount=0 then Result:=0
else Result:=sizeOf(TRecordHeader)+SizeOf(Word)+RecordCount*SizeOf(THBreakData);
end;
function THPageBreakList.HasPageBreak(const Row: integer): boolean;
var
Index: integer;
begin
Result:=Find(Row, Index);
end;
//---------------------------- VERTICAL PAGE BREAKS ----------------------//
//------------------------------------------------------------------------//
{ TVPageBreakRecord }
function TVPageBreakRecord.BreakData(const index: integer): TVBreakData;
begin
Move(Data[2+index*SizeOf(TVBreakData)],Result, SizeOf(TVBreakData));
end;
function TVPageBreakRecord.Count: Word;
begin
Result:= GetWord(Data, 0);
end;
{ TVPageBreak }
function TVPageBreak.CopyTo: TVPageBreak;
begin
Result:= TVPageBreak.Create(BreakData);
end;
constructor TVPageBreak.Create(const aBreakData: TVBreakData);
begin
inherited Create;
BreakData:= aBreakData;
end;
{ TVPageBreakList }
procedure TVPageBreakList.AddBreak(const aCol: Integer);
var
Index: integer;
BreakData: TVBreakData;
begin
BreakData.Col:=aCol;
BreakData.Row1:=0;
BreakData.Row2:=$FFFF;
if Count>MaxVPageBreaks then raise Exception.Create(ErrTooManyPageBreaks);
if not Find(aCol, Index) then Insert(Index, TVPageBreak.Create(BreakData));
end;
procedure TVPageBreakList.DeleteBreak(const aCol: Integer);
var
Index: integer;
begin
if Find(aCol, Index) then Delete(Index);
end;
procedure TVPageBreakList.AddRecord(const aRecord: TVPageBreakRecord);
var
i, Index: integer;
begin
for i:=0 to aRecord.Count - 1 do
if not Find(aRecord.BreakData(i).Col, Index) then Insert(Index, TVPageBreak.Create(aRecord.BreakData(i)));
aRecord.Free;
end;
procedure TVPageBreakList.CalcIncludedRangeRecords(const CellRange: TXlsCellRange; out FirstRecord, RecordCount: integer);
var
LastRecord, i: integer;
begin
Sort; //just in case
FirstRecord:=-1;
LastRecord:=-1;
for i:=0 to Count-1 do
begin
if (FirstRecord<0) and (Items[i].BreakData.Col>=CellRange.Left) then FirstRecord:=i;
if Items[i].BreakData.Col<=CellRange.Right then LastRecord:=i;
end;
if (FirstRecord>=0) and (LastRecord>=0) and (FirstRecord<=LastRecord) then
RecordCount:=LastRecord-FirstRecord+1
else
begin
FirstRecord:=0;
RecordCount:=0;
end;
end;
procedure TVPageBreakList.CopyFrom(const aBreakList: TVPageBreakList);
var
i:integer;
begin
if aBreakList=nil then exit;
for i:=0 to aBreakList.Count-1 do Add(aBreakList[i].CopyTo);
end;
procedure TVPageBreakList.DeleteCols(const DestCol, aCount: integer);
var
Index: integer;
i: integer;
begin
Find(DestCol, Index);
for i:=Count-1 downto Index do
if Items[i].BreakData.Col<DestCol+aCount then Delete(i) else dec(Items[i].BreakData.Col, aCount);
end;
procedure TVPageBreakList.InsertCols(const DestCol, aCount: integer);
var
Index: integer;
i: integer;
begin
Find(DestCol, Index);
for i:=Index to Count-1 do IncMax(Items[i].BreakData.Col, aCount, $FF);
end;
procedure TVPageBreakList.SaveToStreamExt(const DataStream: TOle2File; const FirstRecord, RecordCount: integer);
var
RecordHeader: TRecordHeader;
MyRecordCount: word;
i: integer;
begin
if RecordCount > 0 then
begin
Sort; //just in case...
MyRecordCount:=RecordCount;
RecordHeader.Id:= xlr_VERTICALPAGEBREAKS;
RecordHeader.Size:= SizeOf(MyRecordCount)+RecordCount*SizeOf(TVBreakData);
DataStream.WriteMem(RecordHeader, Sizeof(RecordHeader));
DataStream.WriteMem(MyRecordCount, Sizeof(MyRecordCount));
for i:=FirstRecord to FirstRecord+RecordCount-1 do
begin
DataStream.WriteMem(Items[i].BreakData, SizeOf(Items[i].BreakData));
end;
end;
end;
procedure TVPageBreakList.SaveRangeToStream(const DataStream: TOle2File; const CellRange: TXlsCellRange);
var
FirstRecord, RecordCount: integer;
begin
CalcIncludedRangeRecords(CellRange, FirstRecord, RecordCount);
SaveToStreamExt(DataStream, FirstRecord, RecordCount);
end;
procedure TVPageBreakList.SaveToStream(const DataStream: TOle2File);
begin
SaveToStreamExt(DataStream, 0, Count);
end;
function TVPageBreakList.TotalRangeSize(const CellRange: TXlsCellRange): int64;
var
FirstRecord, RecordCount: integer;
begin
CalcIncludedRangeRecords(CellRange, FirstRecord, RecordCount);
Result:=TotalSizeExt(RecordCount);
end;
function TVPageBreakList.TotalSize: int64;
begin
Result:=TotalSizeExt(Count);
end;
function TVPageBreakList.TotalSizeExt(const RecordCount: integer): int64;
begin
if RecordCount=0 then Result:=0
else Result:=sizeOf(TRecordHeader)+SizeOf(Word)+RecordCount*SizeOf(TVBreakData);
end;
function TVPageBreakList.HasPageBreak(const Col: integer): boolean;
var
Index: integer;
begin
Result:=Find(Col, Index);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -