📄 uescherrecords.pas
字号:
procedure TEscherClientDataRecord.AssignClientData(const aClientData: TBaseClientData);
begin
ClientData:= aClientData;
if (ClientData<>nil) then
begin
if (ClientData.Id> DwgCache.MaxObjId) then DwgCache.MaxObjId:=ClientData.Id;
end;
end;
constructor TEscherClientDataRecord.Create( const aEscherHeader: TEscherRecordHeader; const aDwgGroupCache: PEscherDwgGroupCache; const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
begin
inherited;
if DwgCache.Obj<>nil then DwgCache.Obj.Add(Self);
end;
constructor TEscherClientDataRecord.CreateFromData(
const aDwgGroupCache: PEscherDwgGroupCache;
const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
var
aEscherHeader: TEscherRecordHeader;
begin
aEscherHeader.Pre:=0;
aEscherHeader.Id:=MsofbtClientData;
aEscherHeader.Size:=0;
Create( aEscherHeader, aDwgGroupCache, aDwgCache, aParent);
LoadedDataSize:=0;
end;
destructor TEscherClientDataRecord.Destroy;
begin
if (DwgCache.Obj<>nil) and not DwgCache.Destroying then DwgCache.Obj.Remove(Self);
FreeAndNil(ClientData);
//MADE: remover los otros que referencian a estos objs.
inherited;
end;
function TEscherClientDataRecord.DoCopyTo(const NewDwgCache: PEscherDwgCache; const RowOfs, ColOfs: integer): TEscherRecord;
begin
Result:=inherited DoCopyTo(NewDwgCache, RowOfs, ColOfs);
(Result as TEscherClientDataRecord).AssignClientData(ClientData.CopyTo);
if NewDwgCache=DwgCache then (Result as TEscherClientDataRecord).ClientData.ArrangeId(DwgCache.MaxObjId);
(Result as TEscherClientDataRecord).ArrangeCopyRowsAndCols(RowOfs, ColOfs);
end;
function TEscherClientDataRecord.Loaded: boolean;
begin
Result:= inherited Loaded;
end;
function TEscherClientDataRecord.ObjId: word;
begin
if ClientData<>nil then Result:=ClientData.Id else Result:=0;
end;
procedure TEscherClientDataRecord.SaveToStream(const DataStream: TStream; const BreakList: TBreakList);
var
StreamPos: integer;
begin
inherited;
StreamPos:= DataStream.Position;
if ClientData<>nil then ClientData.SaveToStream(DataStream);
BreakList.AddToZeroPos(DataStream.Position-StreamPos);
end;
procedure TEscherClientDataRecord.SplitRecords(var NextPos,
RealSize: integer; var NextDwg: integer; const BreakList: TBreakList);
begin
inherited;
if ClientData<>nil then inc(RealSize, ClientData.TotalSize);
NextDwg:=xlr_MSODRAWING;
end;
function TEscherClientDataRecord.TotalSizeNoSplit: int64;
begin
TotalSizeNoSplit:=inherited TotalSizeNoSplit;
end;
function TEscherClientDataRecord.WaitingClientData(var ClientType: ClassOfTBaseClientData): boolean;
begin
Result:= inherited Loaded and (ClientData=nil);
ClientType:=TMsObj;
end;
//////////////////////////////////////Other Records ///////////////////////////7
{ TEscherClientAnchorRecord }
constructor TEscherClientAnchorRecord.Create(const aEscherHeader: TEscherRecordHeader; const aDwgGroupCache: PEscherDwgGroupCache; const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
begin
inherited;
Anchor:=PClientAnchor(Data);
if DwgCache.Anchor<>nil then DwgCache.Anchor.Add(Self);
if FParent <> nil then (FParent as TEscherSPContainerRecord).ClientAnchor:=Self;
end;
constructor TEscherClientAnchorRecord.CreateFromData(const aAnchor: TClientAnchor;const aEscherHeader: TEscherRecordHeader; const aDwgGroupCache: PEscherDwgGroupCache; const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
begin
Create(aEscherHeader, aDwgGroupCache, aDwgCache, aParent);
move(aAnchor, Anchor^, Sizeof(TClientAnchor));
LoadedDataSize:=TotalDataSize;
end;
procedure TEscherClientAnchorRecord.ArrangeInsertRowsAndCols(const aRowPos, aRowCount, aColPos, aColCount: integer; const SheetInfo: TSheetInfo; const Forced: boolean);
var
dr, dc: integer;
Af: word;
begin
if SheetInfo.FormulaSheet<> SheetInfo.InsSheet then exit;
if Forced then Af:=2 else Af:=Anchor.Flag;
case Af and 3 of
0: //move and resize
begin
//Rows
if Anchor.Row1>=aRowPos then
begin
dr:= Anchor.Row1+aRowCount;
IncMaxMin(Anchor.Row1, aRowCount, Max_Rows, aRowPos);
if dr< aRowPos then Anchor.Dy1:=0;
end;
if Anchor.Row2>=aRowPos then
begin
dr:= Anchor.Row2+aRowCount;
IncMaxMin(Anchor.Row2, aRowCount, Max_Rows, aRowPos);
if dr< aRowPos then Anchor.Dy2:=0;
end;
//Columns
if Anchor.Col1>=aColPos then
begin
dc:= Anchor.Col1+aColCount;
IncMaxMin(Anchor.Col1, aColCount, Max_Columns, aColPos);
if dc< aColPos then Anchor.Dx1:=0;
end;
if Anchor.Col2>=aColPos then
begin
dc:= Anchor.Col2+aColCount;
IncMaxMin(Anchor.Col2, aColCount, Max_Columns, aColPos);
if dc< aColPos then Anchor.Dx2:=0;
end;
end;
2: //move
begin
if Anchor.Row1>=aRowPos then
begin
dr:= Anchor.Row1;
IncMaxMin(Anchor.Row1, aRowCount, Max_Rows, aRowPos);
IncMaxMin(Anchor.Row2, Anchor.Row1-dr, Max_Rows, Anchor.Row1);
end;
if Anchor.Col1>=aColPos then
begin
dc:= Anchor.Col1;
IncMaxMin(Anchor.Col1, aColCount, Max_Columns, aColPos);
IncMaxMin(Anchor.Col2, Anchor.Col1-dc, Max_Columns, Anchor.Col1);
end;
end;
3: //dont move
begin
end;
end; //case
end;
destructor TEscherClientAnchorRecord.Destroy;
begin
if (DwgCache.Anchor<> nil) and not DwgCache.Destroying then DwgCache.Anchor.Remove(Self);
if FParent <> nil then (FParent as TEscherSpContainerRecord).ClientAnchor:=nil;
inherited;
end;
function TEscherClientAnchorRecord.AllowCopy(const FirstRow, LastRow, FirstCol, LastCol: integer): boolean;
begin
AllowCopy:= ((Anchor.Flag and 3) in [0,2])
and (Anchor.Row1>=FirstRow) and (Anchor.Row2<=LastRow)
and (Anchor.Col1>=FirstCol) and (Anchor.Col2<=LastCol);
end;
function TEscherClientAnchorRecord.AllowDelete(const FirstRow, LastRow, FirstCol, LastCol: integer): boolean;
begin
AllowDelete:= ((Anchor.Flag and 3) in [0])
and (Anchor.Row1>=FirstRow) and (Anchor.Row2<=LastRow)
and (Anchor.Col1>=FirstCol) and (Anchor.Col2<=LastCol);
end;
function TEscherClientAnchorRecord.DoCopyTo(const NewDwgCache: PEscherDwgCache; const RowOfs, ColOfs: integer): TEscherRecord;
begin
Result:=inherited DoCopyTo(NewDwgCache, RowOfs, ColOfs);
(Result.FParent as TEscherSPContainerRecord).ClientAnchor:=Result as TEscherClientAnchorRecord;
inc((Result as TEscherClientAnchorRecord).Anchor.Row1, RowOfs);
inc((Result as TEscherClientAnchorRecord).Anchor.Row2, RowOfs);
inc((Result as TEscherClientAnchorRecord).Anchor.Col1, ColOfs);
inc((Result as TEscherClientAnchorRecord).Anchor.Col2, ColOfs);
end;
function TEscherClientAnchorRecord.Col: integer;
begin
Result:= Anchor.Col1;
end;
function TEscherClientAnchorRecord.Row: integer;
begin
Result:= Anchor.Row1;
end;
function TEscherClientAnchorRecord.GetAnchor: TClientAnchor;
begin
Result:= Anchor^;
end;
procedure TEscherClientAnchorRecord.SetAnchor(
const aAnchor: TClientAnchor);
begin
move(aAnchor, Anchor^, Sizeof(TClientAnchor));
end;
{ TEscherBSERecord }
procedure TEscherBSERecord.AddRef;
begin
IncLongWord(Data,24,1);
end;
function TEscherBSERecord.CompareRec( const aRecord: TEscherRecord): integer;
type
TUid=array[0..15] of byte;
PUid=^TUid;
var
Uid1, Uid2: PUid;
i:integer;
begin
//We can't just compare the data of the 2 records, because cRef can be different
//no inherited
if TotalDataSize< aRecord.TotalDataSize then Result:=-1 else if TotalDataSize> aRecord.TotalDataSize then Result:=1 else
begin
Uid1:= PUid(PChar(Data)+2);
Uid2:= PUid(PChar((aRecord as TEscherBSERecord).Data)+2);
for i:=0 to SizeOf(TUid)-1 do
if Uid1[i]<Uid2[i] then
begin
Result:=-1;
exit;
end else
if Uid1[i]>Uid2[i] then
begin
Result:=1;
exit;
end;
Result:= 0;
end;
end;
procedure TEscherBSERecord.CopyFromData(
const BSEHeader: Pointer; const BlipHeader: TEscherRecordHeader; const BlipData: TStream);
var
blp: PArrayOfByte;
begin
if 36+BlipData.Size+SizeOf(BlipHeader)<> TotalDataSize then raise exception.Create(ErrInternal);
System.Move(BSEHeader^, Data^, 36);
System.Move(BlipHeader, (PChar(Data)+36)^, SizeOf(BlipHeader));
blp:=PArrayOfByte(pchar(Data)+36+SizeOf(BlipHeader));
BlipData.Read(blp^, BlipData.Size);
LoadedDataSize:=TotalDataSize;
end;
function TEscherBSERecord.References: LongWord;
begin
References:= GetLongWord(Data, 24);
end;
procedure TEscherBSERecord.Release;
begin
if self=nil then exit;
IncLongWord(Data,24,-1);
if (References=0)and (DwgGroupCache.BStore<>nil) then
DwgGroupCache.BStore.ContainedRecords.Remove(Self); //When refs=0 , delete from bstore
end;
//This is the header to write a bitmap to disk
type
tagBITMAPFILEHEADER = packed record
bfType: Word;
bfSize: LongWord;
bfReserved1: Word;
bfReserved2: Word;
bfOffBits: LongWord;
end;
procedure TEscherBSERecord.SaveGraphicToStream(const aData: TStream; var aDataType: TXlsImgTypes);
var
HeadOfs: integer;
BmpHead: tagBITMAPFILEHEADER;
begin
case Data[0] of
msoblipEMF : aDataType:=xli_Emf;
msoblipWMF : aDataType:=xli_Wmf;
msoblipJPEG : aDataType:=xli_Jpeg;
msoblipPNG : aDataType:=xli_Png;
msoblipDIB : aDataType:=xli_Bmp;
else aDataType:=xli_Unknown;
end; //case
if aDataType in [xli_JPEG, xli_PNG, xli_BMP] then HeadOfs:=17 else HeadOfs:=16;
if aDataType = xli_Bmp then
begin
FillChar(BmpHead, SizeOf(BmpHead), 0);
BmpHead.BfType:=$4D42;
aData.WriteBuffer(BmpHead, SizeOf(BmpHead));
end;
aData.WriteBuffer((PChar(Data)+36+SizeOf(TEscherRecordHeader)+HeadOfs)^ , TotalDataSize-36-SizeOf(TEscherRecordHeader)-HeadOfs);
end;
{ TEscherBStoreRecord }
procedure TEscherBStoreRecord.AddRef(const BlipPos: integer);
begin
if (BlipPos<1)or(BlipPos> FContainedRecords.Count) then raise Exception.Create(ErrExcelInvalid);
(FContainedRecords[BlipPos-1] as TEscherBSERecord).AddRef;
end;
constructor TEscherBStoreRecord.Create(const aEscherHeader: TEscherRecordHeader; const aDwgGroupCache: PEscherDwgGroupCache; const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
begin
inherited;
if (DwgGroupCache.BStore=nil) then DwgGroupCache.BStore:=Self else raise Exception.Create(ErrBStroreDuplicated);
end;
destructor TEscherBStoreRecord.Destroy;
begin
DwgGroupCache.BStore:=nil;
inherited;
end;
procedure TEscherBStoreRecord.Release(const BlipPos: integer);
begin
if (BlipPos<1)or(BlipPos> FContainedRecords.Count) then raise Exception.Create(ErrExcelInvalid);
(FContainedRecords[BlipPos-1] as TEscherBSERecord).Release;
end;
procedure TEscherBStoreRecord.SaveToStream(const DataStream: TStream;
const BreakList: TBreakList);
var
i: integer;
begin
//Fix bse positions
for i:=0 to FContainedRecords.Count-1 do (FContainedRecords[i] as TEscherBSERecord).BStorePos:=i+1;
inherited;
end;
{ TEscherDgRecord }
constructor TEscherDgRecord.Create(const aEscherHeader: TEscherRecordHeader; const aDwgGroupCache: PEscherDwgGroupCache; const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
begin
inherited;
Dg:= Pdg(Data);
if (DwgCache.Dg=nil) then DwgCache.Dg:=Self else raise Exception.Create(ErrDgDuplicated);
end;
constructor TEscherDgRecord.CreateFromData(const csp, cspidCur: LongWord;
const aDwgGroupCache: PEscherDwgGroupCache;
const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
var
EscherHeader: TEscherRecordHeader;
begin
EscherHeader.Pre:=$10;
EscherHeader.Id:=MsofbtDg;
EscherHeader.Size:=2*SizeOf(LongWord);
Create(EscherHeader, aDwgGroupCache, aDwgCache, aParent);
SetLongWord(Data, 0, csp);
SetLongWord(Data, 4, cspidCur);
LoadedDataSize:=TotalDataSize;
end;
procedure TEscherDgRecord.DecShapeCount;
begin
dec(Dg.ShapeCount);
end;
destructor TEscherDgRecord.Destroy;
begin
DwgCache.Dg:=nil;
inherited;
end;
function TEscherDgRecord.IncMaxShapeId: LongWord;
begin
inc(Dg^.MaxSpId);
Result:= Dg^.MaxSpId;
inc(Dg^.ShapeCount);
//PENDING: cuando llega a 1024, new dgg group
end;
{ TEscherSPRecord }
constructor TEscherSPRecord.Create(const aEscherHeader: TEscherRecordHeader; const aDwgGroupCache: PEscherDwgGroupCache; const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
begin
inherited;
ShapeId:=PLongWord(Data);
if DwgCache.Shape<>nil then DwgCache.Shape.Add(Self);
if FParent <> nil then (FParent as TEscherSpContainerRecord).SP:=self;
end;
constructor TEscherSPRecord.CreateFromData(const Pre, aShapeId, Flags: LongWord;
const aDwgGroupCache: PEscherDwgGroupCache;
const aDwgCache: PEscherDwgCache; const aParent: TEscherContainerRecord);
var
RecordHeader: TEscherRecordHeader;
begin
RecordHeader.Id:=MsofbtSp;
RecordHeader.Pre:=Pre;
RecordHeader.Size:=8;
Create(RecordHeader, aDwgGroupCache, aDwgCache, aParent);
ShapeId^:=aShapeId;
SetLongWord(Data, 4, Flags);
LoadedDataSize:=RecordHeader.Size;
end;
destructor TEscherSPRecord.Destroy;
var
Index: integer;
begin
if not DwgCache.Destroying then
begin
if DwgCache.Dg<>nil then DwgCache.Dg.DecShapeCount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -