📄 uxlsescher.pas
字号:
end;
function TDrawing.GetDrawingRow(index: integer): integer;
begin
Assert(Index<FRecordCache.Blip.Count,'Index out of range');
Result:=FRecordCache.Blip[index].Row;
end;
procedure TDrawing.InsertAndCopyRowsAndCols(const FirstRow, LastRow, DestRow, RowCount, FirstCol, LastCol, DestCol,
ColCount: integer; const SheetInfo: TSheetInfo);
var
i,k, myDestRow, myFirstRow, myLastRow, myDestCol, myFirstCol, myLastCol: integer;
begin
if (FDgContainer=nil) or (FRecordCache.Anchor= nil) then exit; //no drawings on this sheet
if DestRow>FirstRow then
begin
myFirstRow:=FirstRow; myLastRow:=LastRow;
end else
begin
myFirstRow:=FirstRow+RowCount*(LastRow-FirstRow+1);
myLastRow:=LastRow+RowCount*(LastRow-FirstRow+1);
end;
if DestCol>FirstCol then
begin
myFirstCol:=FirstCol; myLastCol:=LastCol;
end else
begin
myFirstCol:=FirstCol+ColCount*(LastCol-FirstCol+1);
myLastCol:=LastCol+ColCount*(LastCol-FirstCol+1);
end;
//Insert cells
ArrangeInsertRowsAndCols(DestRow, RowCount*(LastRow-FirstRow+1), DestCol, ColCount*(LastCol-FirstCol+1), SheetInfo);
//Copy the images
//First the rows...
myDestRow:=DestRow;
for k:= 0 to RowCount-1 do
begin
FDgContainer.ClearCopiedTo;
for i:= 0 to FRecordCache.Anchor.Count-1 do
if FRecordCache.Anchor[i].AllowCopy(myFirstRow, myLastRow, 0, Max_Columns+1)then
begin
FRecordCache.Anchor[i].CopyDwg(myDestRow-myFirstRow,0);
end;
inc(myDestRow, (LastRow-FirstRow+1));
if FRecordCache.Solver<>nil then FRecordCache.Solver.ArrangeCopyRowsAndCols;
end;
//Now the columns... as we already copied the rows, now we will make an array of images
myDestCol:=DestCol;
for k:= 0 to ColCount-1 do
begin
FDgContainer.ClearCopiedTo;
for i:= 0 to FRecordCache.Anchor.Count-1 do
if FRecordCache.Anchor[i].AllowCopy(0, Max_Rows+1, myFirstCol, myLastCol)then
begin
FRecordCache.Anchor[i].CopyDwg(0, myDestCol-myFirstCol);
end;
inc(myDestCol, (LastCol-FirstCol+1));
if FRecordCache.Solver<>nil then FRecordCache.Solver.ArrangeCopyRowsAndCols();
end;
end;
procedure TDrawing.CreateBasicDrawingInfo;
var
EscherHeader: TEscherRecordHeader;
Dg: TEscherDgRecord;
SPRec: TEscherSpContainerRecord;
SPgrRec:TEscherDataRecord;
SP: TEscherSPRecord;
begin
Assert (FDrawingGroup<>nil,'DrawingGroup can''t be nil');
FRecordCache.MaxObjId:=0;
FRecordCache.Dg:=nil; FRecordCache.Patriarch:=nil; FRecordCache.Solver:=nil;
FRecordCache.Anchor:= TEscherAnchorCache.Create;
FRecordCache.Obj:= TEscherObjCache.Create;
FRecordCache.Shape:= TEscherShapeCache.Create;
FRecordCache.Blip:=TEscherOPTCache.Create;
EscherHeader.Pre:=$F;
EscherHeader.Id:=MsofbtDgContainer;
EscherHeader.Size:=0;
FDgContainer:=TEscherContainerRecord.Create(EscherHeader, FDrawingGroup.RecordCache, @FRecordCache ,nil);
FDrawingGroup.AddDwg;
//Add required records...
Dg:=TEscherDgRecord.CreateFromData(0,$401,FDrawingGroup.RecordCache, @FRecordCache, FDgContainer);
FDgContainer.ContainedRecords.Add(Dg);
EscherHeader.Pre:=$F;
EscherHeader.Id:=MsofbtSpgrContainer;
EscherHeader.Size:=0;
FRecordCache.Patriarch:= TEscherSpgrContainerRecord.Create(EscherHeader, FDrawingGroup.RecordCache, @FRecordCache, FDgContainer);
FDgContainer.ContainedRecords.Add(FRecordCache.Patriarch);
EscherHeader.Id:=MsofbtSpContainer;
EscherHeader.Pre:=$F;
EscherHeader.Size:=0; //Size for a container is calculated later
SPRec:=TEscherSpContainerRecord.Create(EscherHeader, FDrawingGroup.RecordCache, @FRecordCache, FRecordCache.Patriarch);
SPRec.LoadedDataSize:=EscherHeader.Size;
FRecordCache.Patriarch.ContainedRecords.Add(SPRec);
EscherHeader.Id:=MsofbtSpgr;
EscherHeader.Pre:=$1;
EscherHeader.Size:=16;
SPgrRec:=TEscherDataRecord.Create(EscherHeader, FDrawingGroup.RecordCache, @FRecordCache, FRecordCache.Patriarch);
SPgrRec.LoadedDataSize:=EscherHeader.Size;
SPgrRec.ClearData;
SPRec.ContainedRecords.Add(SPgrRec);
SP:=TEscherSPRecord.CreateFromData($2,FRecordCache.Dg.IncMaxShapeId, $5 , FDrawingGroup.RecordCache, @FRecordCache, SPRec);
SPRec.ContainedRecords.Add(SP);
end;
procedure TDrawing.AddImage(Data: string; DataType: TXlsImgTypes; const Properties: TImageProperties;const Anchor: TFlxAnchorType);
var
SPRec: TEscherSpContainerRecord;
AnchorRec: TEscherClientAnchorRecord;
RecordHeader: TEscherRecordHeader;
ClientAnchor: TClientAnchor;
ClientData: TEscherClientDataRecord;
SP: TEscherSPRecord;
OPTRec:TEscherOPTRecord;
begin
if Data='' then
begin
Data:=EmptyBmp;
DataType:=xli_Bmp;
end;
if (FDgContainer=nil) or (FRecordCache.Anchor= nil) then //no drawings on this sheet
CreateBasicDrawingInfo;
if (FRecordCache.Patriarch=nil) then raise Exception.Create(ErrLoadingEscher);
RecordHeader.Id:=MsofbtSpContainer;
RecordHeader.Pre:=$F;
RecordHeader.Size:=0; //Size for a container is calculated later
SPRec:=TEscherSpContainerRecord.Create(RecordHeader, FDrawingGroup.RecordCache, @FRecordCache, FRecordCache.Patriarch);
SPRec.LoadedDataSize:=RecordHeader.Size;
SP:=TEscherSPRecord.CreateFromData($04B2, FRecordCache.Dg.IncMaxShapeId, $A00 , FDrawingGroup.RecordCache, @FRecordCache, SPRec);
SPRec.ContainedRecords.Add(SP);
OPTRec:=TEscherOPTRecord.CreateFromDataImg(Data, DataType, Properties.FileName, FDrawingGroup.RecordCache, @FRecordCache, SPRec);
SPRec.ContainedRecords.Add(OPTRec);
RecordHeader.Id:=MsofbtClientAnchor;
RecordHeader.Pre:=0;
RecordHeader.Size:=SizeOf(TClientAnchor);
case Anchor of
at_MoveAndResize: ClientAnchor.Flag:=00;
at_DontMoveAndDontResize: ClientAnchor.Flag:=03;
else ClientAnchor.Flag:=02;
end; //case
ClientAnchor.Col1:=Properties.Col1;
ClientAnchor.Dx1:=Properties.dx1;
ClientAnchor.Col2:=Properties.Col2;
ClientAnchor.Dx2:=Properties.dx2;
ClientAnchor.Row1:=Properties.Row1;
ClientAnchor.Dy1:=Properties.dy1;
ClientAnchor.Row2:=Properties.Row2;
ClientAnchor.Dy2:=Properties.dy2;
AnchorRec:=TEscherClientAnchorRecord.CreateFromData(ClientAnchor, RecordHeader, FDrawingGroup.RecordCache, @FRecordCache, SPRec);
SPRec.ContainedRecords.Add(AnchorRec);
RecordHeader.Id:=MsofbtClientData;
RecordHeader.Pre:=0;
RecordHeader.Size:=0;
ClientData:= TEscherClientDataRecord.Create(RecordHeader, FDrawingGroup.RecordCache, @FRecordCache, SPRec);
ClientData.AssignClientData(TMsObj.CreateEmptyImg(FRecordCache.MaxObjId));
ClientData.LoadedDataSize:=RecordHeader.Size;
SPRec.ContainedRecords.Add(ClientData);
FRecordCache.Patriarch.ContainedRecords.Add(SPRec);
end;
procedure TDrawing.LoadFromStream(const DataStream: TStream;
const First: TDrawingRecord; const SST: TSST);
var
aPos, CdPos: integer;
EscherHeader: TEscherRecordHeader;
RecordHeader: TRecordHeader;
MyRecord, CurrentRecord, R, CdRecord: TBaseRecord;
FClientData: TBaseClientData;
ClientType: ClassOfTBaseClientData;
begin
Assert (FDrawingGroup<>nil,'DrawingGroup can''t be nil');
if FDgContainer<>nil then raise Exception.Create(ErrExcelInvalid);
FRecordCache.MaxObjId:=0;
FRecordCache.Dg:=nil; FRecordCache.Patriarch:=nil; FRecordCache.Solver:=nil;
FRecordCache.Anchor:= TEscherAnchorCache.Create;
FRecordCache.Obj:= TEscherObjCache.Create;
FRecordCache.Shape:= TEscherShapeCache.Create;
FRecordCache.Blip:= TEscherOPTCache.Create;
aPos:=0;
MyRecord:= First; CurrentRecord:= First;
try
ReadMem(MyRecord, aPos, SizeOf(EscherHeader), @EscherHeader);
FDgContainer:= TEscherContainerRecord.Create(EscherHeader, FDrawingGroup.RecordCache, @FRecordCache ,nil);
while (not FDgContainer.Loaded) or FDgContainer.WaitingClientData(ClientType) do
begin
if not FDgContainer.WaitingClientData(ClientType) then
begin
if (MyRecord.Continue=nil) and (aPos=MyRecord.DataSize) then
begin
if CurrentRecord<> First then FreeAndNil(CurrentRecord);
if (DataStream.Read(RecordHeader, sizeof(RecordHeader)) <> sizeof(RecordHeader)) then
raise Exception.Create(ErrExcelInvalid);
CurrentRecord:=LoadRecord(DataStream, RecordHeader);
MyRecord:= CurrentRecord;
aPos:=0;
if not(MyRecord is TDrawingRecord) then raise Exception.Create(ErrExcelInvalid);
end;
FDgContainer.Load(MyRecord, aPos);
end else
begin
if not ((MyRecord.Continue=nil) and (aPos=MyRecord.DataSize)) then raise Exception.Create(ErrExcelInvalid);
if (DataStream.Read(RecordHeader, sizeof(RecordHeader)) <> sizeof(RecordHeader)) then
raise Exception.Create(ErrExcelInvalid);
R:=LoadRecord(DataStream, RecordHeader);
try
if (R is ClientType.ObjRecord) then
begin
FClientData:= ClientType.Create;
try
FClientData.LoadFromStream(DataStream, R , SST);
FDgContainer.AssignClientData(FClientData);
if FClientData.RemainingData<>nil then
begin
CdRecord:=FClientData.RemainingData; //we dont have to free this
CdPos:=0;
FDgContainer.Load(CdRecord, CdPos);
end;
except
FreeAndNil(FClientData);
raise;
end; //except
end else raise Exception.Create(ErrInvalidDrawing);
except
FreeAndNil(R);
raise;
end; //Except
end;
end; //while
finally
if CurrentRecord<>First then FreeAndNil(CurrentRecord);
end; //finally
FRecordCache.Shape.Sort; // only here the values are loaded...
if FRecordCache.Solver <>nil then FRecordCache.Solver.FixPointers;
//PENDING: Wmf, emf
First.Free; //last statment
end;
procedure TDrawing.SaveToStream(const DataStream: TStream);
var
BreakList: TBreakList;
NextPos, RealSize, NewDwg: integer;
begin
if FDgContainer=nil then exit;
BreakList:= TBreakList.Create(DataStream.Position);
try
NextPos:=0;
RealSize:=0;
NewDwg:= xlr_MSODRAWING;
FDgContainer.SplitRecords(NextPos, RealSize, NewDwg, BreakList);
BreakList.Add(0, NextPos);
FDgContainer.SaveToStream(DataStream, BreakList);
finally
FreeAndNil(BreakList);
end; //finally
end;
function TDrawing.TotalSize: int64;
var
NextPos, RealSize, NewDwg: integer;
begin
if FDgContainer=nil then begin Result:=0; exit;end;
NextPos:=0; RealSize:=0; NewDwg:= xlr_MSODRAWINGGROUP;
FDgContainer.SplitRecords(NextPos, RealSize, NewDwg, nil);
Result:=RealSize;
end;
function TDrawing.AddNewComment(const Properties: TImageProperties): TEscherClientDataRecord;
var
aTXO: TTXO;
aMsObj: TMsObj;
SP: TEscherSPRecord;
SPRec: TEscherSpContainerRecord;
RecordHeader: TEscherRecordHeader;
TXORec: TEscherClientTextBoxRecord;
Obj: TEscherClientDataRecord;
ClientAnchor: TClientAnchor;
AnchorRec: TEscherClientAnchorRecord;
OPTRec:TEscherOPTRecord;
begin
FDrawingGroup.EnsureDwgGroup;
if (FDgContainer=nil) or (FRecordCache.Anchor= nil) then //no drawings on this sheet
CreateBasicDrawingInfo;
RecordHeader.Id:=MsofbtSpContainer;
RecordHeader.Pre:=$F;
RecordHeader.Size:=0; //Size for a container is calculated later
SPRec:=TEscherSpContainerRecord.Create(RecordHeader, FDrawingGroup.RecordCache, @FRecordCache, FRecordCache.Patriarch);
try
SPRec.LoadedDataSize:=RecordHeader.Size;
SP:=TEscherSPRecord.CreateFromData($0CA2, FRecordCache.Dg.IncMaxShapeId, $A00 , FDrawingGroup.RecordCache, @FRecordCache, SPRec);
try
SPRec.ContainedRecords.Add(SP);
except
FreeAndNil(SP);
raise;
end; //except
OPTRec:=TEscherOPTRecord.CreateFromDataNote(FDrawingGroup.RecordCache, @FRecordCache, SPRec);
try
SPRec.ContainedRecords.Add(OPTRec);
except
FreeAndNil(OPTRec);
raise;
end; //except
RecordHeader.Id:=MsofbtClientAnchor;
RecordHeader.Pre:=0;
RecordHeader.Size:=SizeOf(TClientAnchor);
ClientAnchor.Flag:=03;
ClientAnchor.Col1:=Properties.Col1;
ClientAnchor.Dx1:=Properties.dx1;
ClientAnchor.Col2:=Properties.Col2;
ClientAnchor.Dx2:=Properties.dx2;
ClientAnchor.Row1:=Properties.Row1;
ClientAnchor.Dy1:=Properties.dy1;
ClientAnchor.Row2:=Properties.Row2;
ClientAnchor.Dy2:=Properties.dy2;
AnchorRec:=TEscherClientAnchorRecord.CreateFromData(ClientAnchor, RecordHeader, FDrawingGroup.RecordCache, @FRecordCache, SPRec);
try
SPRec.ContainedRecords.Add(AnchorRec);
except
FreeAndNil(AnchorRec);
raise;
end;
Obj:=TEscherClientDataRecord.CreateFromData(FDrawingGroup.RecordCache, @FRecordCache, SPRec);
try
aMsObj:=TMsObj.CreateEmptyNote(FRecordCache.MaxObjId);
try
Obj.AssignClientData(aMsObj);
except
FreeAndNil(aMsObj);
raise;
end; //Except
SPRec.ContainedRecords.Add(Obj);
except
FreeAndNil(Obj);
raise;
end;
TXORec:= TEscherClientTextBoxRecord.CreateFromData(FDrawingGroup.RecordCache, @FRecordCache, SPRec);
try
aTXO:=TTXO.CreateFromData;
try
TXORec.AssignClientData(aTXO);
except
FreeAndNil(aTXO);
raise;
end;
SPRec.ContainedRecords.Add(TXORec);
except
FreeAndNil(TXORec);
raise;
end; //except
FRecordCache.Patriarch.ContainedRecords.Add(SPRec);
except
FreeAndNil(SPRec);
raise;
end; //except
Result:=Obj;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -