755 lines
21 KiB
ObjectPascal
755 lines
21 KiB
ObjectPascal
|
||
{******************************************}
|
||
{ }
|
||
{ FastReport VCL }
|
||
{ XLS export }
|
||
{ }
|
||
{ Copyright (c) 1998-2021 }
|
||
{ by Fast Reports Inc. }
|
||
{ }
|
||
{******************************************}
|
||
|
||
{ This module contains a component that allows to
|
||
export prepaired reports to Microsoft Excel 2003 files.
|
||
These files consist of the following parts:
|
||
|
||
- CBFF - Base format. See frxCBFF.pas
|
||
- BIFF - Actual contents of sheets. See frxBIFF.pas
|
||
- Escher - Drawings and images. See frxEscher.pas
|
||
- OLEPS - Additional information. See frxOLEPS.pas
|
||
- RC4 - Document encrypting. See frxCrypto.pas
|
||
|
||
There's a bug or a feature in MS Excel that you should
|
||
know if you want to make good xls files for printing. When
|
||
exporting a report, there can be an object (picture, memo, etc.)
|
||
close to a border of a report page, i.e. the distance between
|
||
this object and a border of the page is zero or very small.
|
||
When creating the appropriate xls file, this object will become
|
||
a text cell or a picture that is aligned to a side of the print page.
|
||
We assume that this object fits to the print page.
|
||
MS Excel assumes that neighbouring cells of this object must be
|
||
printed too, but they don't fit to the print page. There's no
|
||
complete solution of this problem. Partial solutions are:
|
||
|
||
- Do not place any objects close to a side of the page.
|
||
- If you have to place object close to a side of the page,
|
||
decrease the page margins. }
|
||
{$I frx.inc}
|
||
unit frxExportBIFF;
|
||
|
||
interface
|
||
|
||
uses
|
||
Windows,
|
||
SysUtils,
|
||
Classes,
|
||
ShellAPI,
|
||
|
||
frxClass,
|
||
frxExportMatrix,
|
||
frxProgress,
|
||
frxStorage,
|
||
|
||
frxBIFF,
|
||
frxOLEPS,
|
||
frxEscher,
|
||
frxDraftPool,
|
||
frxBiffConverter,
|
||
frxExportBaseDialog
|
||
{$IFDEF DELPHI16}
|
||
, System.UITypes
|
||
{$ENDIF}
|
||
;
|
||
|
||
type
|
||
|
||
TfrxDraftSheet = class
|
||
public
|
||
Options: TfrxBiffPageOptions;
|
||
end;
|
||
|
||
{ Export filter }
|
||
|
||
{$IFDEF DELPHI16}
|
||
[ComponentPlatformsAttribute(pidWin32 or pidWin64)]
|
||
{$ENDIF}
|
||
TfrxBIFFExport = class(TfrxBaseDialogExportFilter)
|
||
private
|
||
FParallelPages: LongInt;
|
||
FProgress: TfrxProgress;
|
||
|
||
{ The following fields control appearance
|
||
of the generated xls file }
|
||
|
||
FSingleSheet: Boolean;
|
||
FDeleteEmptyRows: Boolean;
|
||
FChunkSize: LongInt;
|
||
FGridLines: Boolean;
|
||
FInaccuracy: Extended;
|
||
FFitPages: Boolean;
|
||
FPictures: Boolean;
|
||
FRowHeightScale: Extended;
|
||
FExportFormulas: Boolean;
|
||
|
||
{ The following fields are used internally
|
||
during generating the xls file }
|
||
|
||
FMatrix: TfrxIEMatrix;
|
||
FWB: TBiffWorkbook;
|
||
FZCW: LongInt; // Width in points of '0' char of the 0-th font
|
||
FTSW: LongInt; // Width of three blank characters
|
||
FLastPage: TfrxPageInfo; // Last exported page
|
||
FDraftPool: TDpDraftPool;
|
||
|
||
{ The following fields specify additional
|
||
information that is saved in the generated
|
||
xls file }
|
||
|
||
FAuthor: AnsiString;
|
||
FComment: AnsiString;
|
||
FKeywords: AnsiString;
|
||
FRevision: AnsiString;
|
||
FAppName: AnsiString;
|
||
FSubject: AnsiString;
|
||
FCategory: AnsiString;
|
||
FCompany: AnsiString;
|
||
FTitle: AnsiString;
|
||
FAccess: TOlepsAccess;
|
||
FManager: AnsiString;
|
||
|
||
{ Document encryption }
|
||
|
||
FPassword: WideString;
|
||
|
||
procedure SetChunkSize(Value: LongInt);
|
||
procedure SetPassword(const s: WideString);
|
||
procedure SetParallelPages(Count: LongInt);
|
||
procedure SetRowHeightScale(Value: Extended);
|
||
|
||
{ Returns a partial filled structure containing
|
||
options for exporting a matrix to a sheet. }
|
||
|
||
function GetExportOptionsDraft: TfrxBiffPageOptions;
|
||
|
||
{ Workbook CBFF stream contents }
|
||
|
||
procedure SaveWorkbook(s: TStream);
|
||
|
||
{ <05>SummaryInformation OLEPS stream contents }
|
||
|
||
procedure SaveSI(s: TStream);
|
||
|
||
{ <05>DocumentSummaryInformation OLEPS stream contents }
|
||
|
||
procedure SaveDSI(s: TStream);
|
||
|
||
procedure InitProgressBar(Steps: Integer; Text: string);
|
||
procedure StepProgressBar;
|
||
procedure FreeProgressBar;
|
||
|
||
public
|
||
|
||
constructor Create(AOwner: TComponent); override;
|
||
|
||
class function GetDescription: string; override;
|
||
class function ExportDialogClass: TfrxBaseExportDialogClass; override;
|
||
function Start: Boolean; override;
|
||
procedure Finish; override;
|
||
procedure FinishPage(Page: TfrxReportPage; Index: Integer); override;
|
||
procedure StartPage(Page: TfrxReportPage; Index: Integer); override;
|
||
procedure ExportObject(Obj: TfrxComponent); override;
|
||
function UseParallelPages: Boolean;
|
||
function CreateMatrix: TfrxIEMatrix;
|
||
procedure ExportPage(Draft: TObject);
|
||
|
||
published
|
||
|
||
property OpenAfterExport;
|
||
property OverwritePrompt;
|
||
|
||
{ Normally, each page of a report is saved as a separate excel sheet.
|
||
This property allows to merge all pages and save them as a single
|
||
big excel sheet }
|
||
|
||
property SingleSheet: Boolean read FSingleSheet write FSingleSheet default False;
|
||
|
||
{ Removes empty rows from produced Excel sheets }
|
||
|
||
property DeleteEmptyRows: Boolean read FDeleteEmptyRows write FDeleteEmptyRows default False;
|
||
|
||
{ All row heights will be multiplied by this factor }
|
||
|
||
property RowHeightScale: Extended read FRowHeightScale write SetRowHeightScale {default 1};
|
||
|
||
{ The report can be reorganized in the following way:
|
||
|
||
1. All the data is stored to a single continuos page.
|
||
2. This page is splitted into same sized chunks (each chunk has ChunkSize rows)
|
||
3. Each chunk is written to a separate Excel sheet.
|
||
|
||
If ChunkSize is zero, this method is not used. If ChunkSize is
|
||
greater than zero, the property SingleSheet must be set to True,
|
||
otherwise an exception will be raised when trying to export a report. }
|
||
|
||
property ChunkSize: LongInt read FChunkSize write SetChunkSize;
|
||
|
||
{ Normally, MS Excel draws lines around each cell. This feature
|
||
can be disabled by this property }
|
||
|
||
property GridLines: Boolean read FGridLines write FGridLines default True;
|
||
|
||
{ This property controls TfrxIEMatrix.Inaccuracy field.
|
||
By default, it equals to 0.1. You should not set this
|
||
field to zero, due to this can produce nonpredictable
|
||
results }
|
||
|
||
property Inaccuracy: Extended read FInaccuracy write FInaccuracy;
|
||
|
||
{ Original report is exported to an xls document with an
|
||
inaccuracy. Sometimes this causes that data fitted to
|
||
an original page (A4, A3, etc.) don't fit to the same
|
||
page after exporting. This exporter can shrink the data
|
||
if it doesn't fit to the excel page. }
|
||
|
||
property FitPages: Boolean read FFitPages write FFitPages;
|
||
|
||
{ Specifies whether to export pictures or not }
|
||
|
||
property Pictures: Boolean read FPictures write FPictures;
|
||
|
||
{ The list of properties below specify some attributes of
|
||
the generated xls file. All of these properties may be empty.
|
||
If a property is empty, it will not be written to the
|
||
output file.
|
||
|
||
Note, that all of these properties are not Unicode. That's why
|
||
MS Excel 2003 does not support Unicode strings in document
|
||
properties. }
|
||
|
||
property Author: AnsiString read FAuthor write FAuthor;
|
||
property Comment: AnsiString read FComment write FComment;
|
||
property Keywords: AnsiString read FKeywords write FKeywords;
|
||
property Revision: AnsiString read FRevision write FRevision;
|
||
property AppName: AnsiString read FAppName write FAppName;
|
||
property Subject: AnsiString read FSubject write FSubject;
|
||
property Category: AnsiString read FCategory write FCategory;
|
||
property Company: AnsiString read FCompany write FCompany;
|
||
property Title: AnsiString read FTitle write FTitle;
|
||
property Manager: AnsiString read FManager write FManager;
|
||
|
||
{ If a non empty password is set, the generated document
|
||
will be encrypted with the RC4 cipher. The maximum
|
||
password length is 255 unicode characters. }
|
||
|
||
property Password: WideString read FPassword write SetPassword;
|
||
|
||
{ <20> Description
|
||
|
||
A big report can contain many pages that can be exported separately by
|
||
different parallel threads. A set of report pages can be passed to a few
|
||
threads, afterwards each thread will export a given number of report pages.
|
||
After that all pages will be combined to a single Excel document.
|
||
|
||
<20> Notices
|
||
|
||
This property specifies a count of these threads. Probably, the best value
|
||
of this property is the count of processors on the current machine.
|
||
This property is not actual when the machine is exporting several
|
||
reports in parallel and furthermore creating additional threads in this
|
||
case may lead to a failure, because each thread requires system resources.
|
||
|
||
<20> Implementation notes
|
||
|
||
The export filter begins from a report that contains a set of GUI elements placed
|
||
on a few report pages. The main thread runs over all report pages and for each page
|
||
selects a set of GUI elements that can appear in the resulting document. All
|
||
elements from a report page are put into TfrxIEMatrix object and pushed to a list
|
||
of such matrix objects. A set of threads are waiting for a moment when the list
|
||
of matrix objects will become nonempty. When such an event occurs, some thread
|
||
selects a matrix object and begin creating an Excel sheet. When a thread has
|
||
generated an Excel sheet, it adds this sheet to a list of sheets. When the main
|
||
thread has converted all report pages to matrix object it becomes waiting for
|
||
threads that are generating Excel sheets. When all sheets are generated, the main
|
||
thread gets all sheets from the list of sheets and combines them to a single
|
||
Excel document. Afterwards it optionally performs encrypting and writes the document
|
||
to a specified data stream or a disk file. }
|
||
|
||
property ParallelPages: LongInt read FParallelPages write SetParallelPages; {default 0}
|
||
|
||
{ A memo component can contain a text beginning with the "=" sign. In this case
|
||
the rest of the text is assumed to be an Excel formula and the memo is exported as
|
||
a formula. Example of such a memo:
|
||
|
||
= SUM(A1:B2) + 5
|
||
=AG18*12
|
||
|
||
If the text appears to be an invalid formula (there're either syntax or semantic issues),
|
||
then the memo is exported as a normal text cell.
|
||
|
||
If ExportFormulas = True, then all texts beginning with "=" are assumed to be formulas.
|
||
If ExportFormulas = False, then the leading "=" has no special meaning for the export. }
|
||
|
||
property ExportFormulas: Boolean read FExportFormulas write FExportFormulas default True;
|
||
|
||
end;
|
||
|
||
implementation
|
||
|
||
uses
|
||
frxUtils,
|
||
frxRes,
|
||
Math,
|
||
frxCBFF, frxExportBIFFDialog;
|
||
|
||
{ TfrxIEMatrix.Inaccuracy values }
|
||
|
||
const
|
||
GoodQuality: Extended = 2.0;
|
||
DraftQuality: Extended = 10.0;
|
||
|
||
{ TfrxBIFFExport }
|
||
|
||
constructor TfrxBIFFExport.Create(AOwner: TComponent);
|
||
begin
|
||
inherited;
|
||
|
||
//FParallelPages := 3;
|
||
|
||
FGridLines := True;
|
||
FPictures := True;
|
||
FSingleSheet := False;
|
||
FFitPages := False;
|
||
FInaccuracy := DraftQuality;
|
||
FAccess := OlepsAfAll;
|
||
FRowHeightScale := 1.0;
|
||
FDeleteEmptyRows:= False;
|
||
FExportFormulas := True;
|
||
|
||
DefaultExt := '.xls';
|
||
FilterDesc := frxGet(8009);
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SetChunkSize(Value: LongInt);
|
||
begin
|
||
if Value < 0 then
|
||
raise Exception.Create(frxGet(9160));
|
||
|
||
FChunkSize := Value;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SetPassword(const s: WideString);
|
||
begin
|
||
if Length(s) > 255 then
|
||
raise Exception.CreateFmt(frxGet(9180), [Length(s), 255]);
|
||
|
||
FPassword := s;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SetRowHeightScale(Value: Extended);
|
||
begin
|
||
if Value > 0 then
|
||
FRowHeightScale := Value
|
||
else
|
||
raise Exception.Create('RowHeightScale must be positive')
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SetParallelPages(Count: LongInt);
|
||
begin
|
||
if (Count < 0) or (Count > 64) then
|
||
raise Exception.CreateFmt('Invalid value of ParallelPages property: %d', [Count]);
|
||
|
||
FParallelPages := Count;
|
||
end;
|
||
|
||
function TfrxBIFFExport.UseParallelPages: Boolean;
|
||
begin
|
||
Result := (ParallelPages > 0) and not FSingleSheet;
|
||
end;
|
||
|
||
class function TfrxBIFFExport.GetDescription: string;
|
||
begin
|
||
Result := frxGet(9151);
|
||
end;
|
||
|
||
function TfrxBIFFExport.GetExportOptionsDraft: TfrxBiffPageOptions;
|
||
begin
|
||
ZeroMemory(@Result, SizeOf(Result));
|
||
|
||
Result.Matrix := FMatrix;
|
||
Result.Pictures := FPictures;
|
||
Result.PageBreaks := FSingleSheet;
|
||
Result.WorkBook := FWB;
|
||
Result.Page := FLastPage;
|
||
Result.TSW := FTSW;
|
||
Result.ZCW := FZCW;
|
||
Result.FitPages := FFitPages;
|
||
Result.GridLines := FGridLines;
|
||
Result.RHScale := RowHeightScale;
|
||
Result.Formulas := ExportFormulas;
|
||
end;
|
||
|
||
function TfrxBIFFExport.CreateMatrix: TfrxIEMatrix;
|
||
var
|
||
m: TfrxIEMatrix;
|
||
begin
|
||
m := TfrxIEMatrix.Create(UseFileCache, Report.EngineOptions.TempDir, Report.PictureCacheOptions.CachedImagesBuildType);
|
||
|
||
with m do
|
||
begin
|
||
Background := False;
|
||
BackgroundImage := False;
|
||
Printable := ExportNotPrintable;
|
||
RichText := False;
|
||
PlainRich := False;
|
||
Inaccuracy := FInaccuracy;
|
||
DeleteHTMLTags := False;
|
||
Images := True;
|
||
WrapText := False;
|
||
EmptyLines := not DeleteEmptyRows;
|
||
BrushAsBitmap := False;
|
||
{$IFNDEF FPC}
|
||
EMFPictures := True;
|
||
{$ENDIF}
|
||
MaxCellWidth := 2000.0; // Actually, MS Excel allows 2303.96 pixels
|
||
MaxCellHeight := Floor(8192 / 20 / 72 * 96) / RowHeightScale; // 8192 twips expressed in pixels
|
||
end;
|
||
|
||
m.DotMatrix := Report.DotMatrixReport;
|
||
m.ShowProgress := ShowProgress;
|
||
|
||
Result := m;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.ExportPage(Draft: TObject);
|
||
var
|
||
s: TfrxDraftSheet;
|
||
begin
|
||
s := TfrxDraftSheet(Draft);
|
||
s.Options.Matrix.Prepare;
|
||
|
||
try
|
||
s.Options.Sheet := frxConvertMatrixToBiffSheet(s.Options, False);
|
||
except
|
||
s.Options.Sheet := nil;
|
||
end;
|
||
|
||
s.Options.Matrix.Free;
|
||
s.Options.Matrix := nil;
|
||
end;
|
||
|
||
function TfrxBIFFExport.Start: Boolean;
|
||
begin
|
||
Result := False; // Default
|
||
|
||
{ Splitting to chunks assumes that chunks
|
||
are saved to different sheets. }
|
||
|
||
if (FChunkSize > 0) and FSingleSheet then
|
||
raise Exception.Create(frxGet(9161));
|
||
|
||
if (FileName = '') and not Assigned(Stream) then
|
||
Exit;
|
||
|
||
SuppressPageHeadersFooters := FSingleSheet or (FChunkSize > 0);
|
||
|
||
FWB := TBiffWorkbook.Create;
|
||
FZCW := FWB.Font[0].StrWidth('0');
|
||
FTSW := FWB.Font[0].StrWidth(' ');
|
||
|
||
if UseParallelPages then
|
||
FDraftPool := TDpDraftPool.Create(ParallelPages,
|
||
Report.PreviewPages.Count, ExportPage);
|
||
|
||
Result := True;
|
||
FMatrix := nil;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.StartPage(Page: TfrxReportPage; Index: Integer);
|
||
begin
|
||
if FMatrix = nil then
|
||
FMatrix := CreateMatrix;
|
||
end;
|
||
|
||
class function TfrxBIFFExport.ExportDialogClass: TfrxBaseExportDialogClass;
|
||
begin
|
||
Result := TfrxBIFFExportDialog;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.ExportObject(Obj: TfrxComponent);
|
||
var
|
||
v: TfrxView;
|
||
begin
|
||
inherited;
|
||
if Obj.Page <> nil then
|
||
Obj.Page.Top := FMatrix.Inaccuracy;
|
||
|
||
if IsPageBG(Obj) then
|
||
Exit;
|
||
|
||
if Obj is TfrxView then
|
||
begin
|
||
v := Obj as TfrxView;
|
||
|
||
if vsExport in v.Visibility then
|
||
FMatrix.AddObject(v);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.FinishPage(Page: TfrxReportPage; Index: Integer);
|
||
var
|
||
po: TfrxBiffPageOptions;
|
||
ds: TfrxDraftSheet;
|
||
begin
|
||
with FLastPage do
|
||
begin
|
||
PaperWidth := Page.PaperWidth;
|
||
PaperHeight := Page.PaperHeight;
|
||
LeftMargin := Page.LeftMargin;
|
||
RightMargin := Page.RightMargin;
|
||
TopMargin := Page.TopMargin;
|
||
BottomMargin := Page.BottomMargin;
|
||
Orientation := TfrxPrintOrient(Page.Orientation);
|
||
PaperSize := Page.PaperSize;
|
||
PageCount := Page.PageCount;
|
||
//Name := Page.Name;
|
||
end;
|
||
|
||
if not UseParallelPages then
|
||
with Page do
|
||
FMatrix.AddPage(Orientation, Width, Height, LeftMargin,
|
||
TopMargin, RightMargin, BottomMargin, MirrorMargins, Index);
|
||
|
||
if (FChunkSize = 0) and not FSingleSheet then
|
||
begin
|
||
po := GetExportOptionsDraft;
|
||
po.PageId := Index;
|
||
|
||
if UseParallelPages then
|
||
begin
|
||
ds := TfrxDraftSheet.Create;
|
||
ds.Options := po;
|
||
FDraftPool.AddDraft(ds);
|
||
end
|
||
else
|
||
begin
|
||
FMatrix.Prepare;
|
||
FWB.AddSheet(frxConvertMatrixToBiffSheet(po, False));
|
||
FMatrix.Free;
|
||
end;
|
||
|
||
FMatrix := nil;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.Finish;
|
||
var
|
||
cd: TCbffDocument;
|
||
po: TfrxBiffPageOptions;
|
||
img: TList;
|
||
i: LongInt;
|
||
fs: TStream;
|
||
begin
|
||
|
||
{ Combine all Excel sheets created by a few
|
||
threads into a single workbook }
|
||
|
||
if UseParallelPages then
|
||
begin
|
||
FDraftPool.WaitForThreads;
|
||
|
||
for i := 0 to FDraftPool.Sheets.Count - 1 do
|
||
with TfrxDraftSheet(FDraftPool.Sheets[i]) do
|
||
if Options.Sheet <> nil then
|
||
FWB.AddSheet(Options.Sheet);
|
||
|
||
FDraftPool.Free;
|
||
end;
|
||
|
||
{ Write the entire report to a single excel sheet }
|
||
|
||
if SingleSheet and (FMatrix <> nil) then
|
||
begin
|
||
FMatrix.Prepare;
|
||
po := GetExportOptionsDraft;
|
||
po.PageId := 0;
|
||
FWB.AddSheet(frxConvertMatrixToBiffSheet(po, Showprogress));
|
||
FMatrix.Clear;
|
||
end;
|
||
|
||
{ Split the entire report into chunks }
|
||
|
||
if (FChunkSize > 0) and not FSingleSheet and (FMatrix <> nil) then
|
||
begin
|
||
if FChunkSize > frxBiff.BiffMaxRow then FChunkSize := frxBiff.BiffMaxRow;
|
||
FMatrix.Prepare;
|
||
img := TList.Create;
|
||
|
||
if FPictures then
|
||
for i := 0 to FMatrix.GetObjectsCount - 1 do
|
||
with FMatrix.GetObjectById(i) do
|
||
if (Image <> nil) and (Image.Width <> 0) then
|
||
img.Add(Pointer(i));
|
||
|
||
po := GetExportOptionsDraft;
|
||
po.PageId := 0;
|
||
po.Size.Y := FChunkSize;
|
||
po.Images := img;
|
||
|
||
while po.Source.Y < FMatrix.Height do
|
||
begin
|
||
FWB.AddSheet(frxConvertMatrixToBiffSheet(po, ShowProgress, FMatrix.Height));
|
||
Inc(po.Source.Y, FChunkSize);
|
||
Inc(po.PageId);
|
||
end;
|
||
|
||
img.Free;
|
||
FMatrix.Clear;
|
||
end;
|
||
|
||
if not UseParallelPages then
|
||
begin
|
||
FMatrix.Free;
|
||
FMatrix := nil;
|
||
end;
|
||
|
||
{ The generated xls file is saved
|
||
as a compound document }
|
||
|
||
cd := TCbffDocument.Create;
|
||
InitProgressBar(2, frxGet(9406));
|
||
|
||
try
|
||
|
||
{ Save the workbook to the required CBFF stream }
|
||
|
||
SaveWorkbook(cd.Root.Add('Workbook').Stream);
|
||
StepProgressBar;
|
||
|
||
{ Save the information about the document
|
||
to the required CBFF streams.
|
||
|
||
All unicode strings will be saved as ansi-strings,
|
||
because MS Excel 2003 never uses unicode characters in
|
||
the document information. Although OpenOffice allows
|
||
to save unicode to the information, it does it
|
||
in another way as the documentation [MS-OLEPS]
|
||
specifies and MS Excel cannot read such information. }
|
||
|
||
SaveSI(cd.Root.Add(#5'SummaryInformation').Stream);
|
||
SaveDSI(cd.Root.Add(#5'DocumentSummaryInformation').Stream);
|
||
|
||
{ Serialize the CBFF document to a plain stream }
|
||
|
||
if Assigned(Stream) then
|
||
cd.Flush(Stream)
|
||
else
|
||
begin
|
||
fs := IOTransport.GetStream(FileName);
|
||
|
||
try
|
||
if not IOTransport.DoFilterProcessStream(fs, Self) then
|
||
cd.Flush(fs);
|
||
finally
|
||
IOTransport.FreeStream(fs);
|
||
end;
|
||
end;
|
||
|
||
StepProgressBar;
|
||
finally
|
||
cd.Free;
|
||
FWB.Free;
|
||
FreeProgressBar;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SaveWorkbook(s: TStream);
|
||
var
|
||
bs: TBiffStream;
|
||
begin
|
||
if FPassword <> '' then
|
||
FWB.SetPassword(FPassword);
|
||
|
||
bs := TBiffStream.Create(UseFileCache);
|
||
|
||
try
|
||
FWB.Flush(bs);
|
||
bs.SaveToStream(s);
|
||
finally
|
||
bs.Free;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SaveSI(s: TStream);
|
||
var
|
||
SysTime: SYSTEMTIME;
|
||
Time: FILETIME;
|
||
begin
|
||
DateTimeToSystemTime(CreationTime, SysTime);
|
||
SystemTimeToFileTime(SysTime, Time);
|
||
|
||
with TOlepsStream.Create do
|
||
try
|
||
with Add(OlepsFmtIdSi) do
|
||
begin
|
||
AddAnsi(OlepsSiTitle, FTitle);
|
||
AddAnsi(OlepsSiSubject, FSubject);
|
||
AddAnsi(OlepsSiAuthor, FAuthor);
|
||
AddAnsi(OlepsSiKeywords, FKeywords);
|
||
AddAnsi(OlepsSiLastAuthor, FAuthor);
|
||
AddAnsi(OlepsSiRevision, FRevision);
|
||
AddAnsi(OlepsSiAppName, FAppName);
|
||
AddAnsi(OlepsSiComment, FComment);
|
||
{IfDef EXPORT_TEST}
|
||
Time.dwLowDateTime := 543882400;
|
||
Time.dwHighDateTime:= 30714350;
|
||
{EndIf}
|
||
AddTime(OlepsSiCreation, Time);
|
||
AddTime(OlepsSiLastSave, Time);
|
||
|
||
Add(OlepsSiAccess, OlepsPtInt).Write(FAccess, 4);
|
||
end;
|
||
finally
|
||
Flush(s);
|
||
Free;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.SaveDSI(s: TStream);
|
||
begin
|
||
with TOlepsStream.Create do
|
||
try
|
||
with Add(OlepsFmtIdDsi) do
|
||
begin
|
||
AddAnsi(OlepsDsiCategory, FCategory);
|
||
AddAnsi(OlepsDsiCompany, FCompany);
|
||
AddAnsi(OlepsDsiManager, FManager);
|
||
end;
|
||
finally
|
||
Flush(s);
|
||
Free;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.InitProgressBar(Steps: Integer; Text: string);
|
||
begin
|
||
if ShowProgress then
|
||
begin
|
||
FProgress := TfrxProgress.Create(nil);
|
||
FProgress.Execute(Steps, Text, False, True);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.StepProgressBar;
|
||
begin
|
||
if ShowProgress then
|
||
FProgress.Tick
|
||
end;
|
||
|
||
procedure TfrxBIFFExport.FreeProgressBar;
|
||
begin
|
||
FProgress.Free
|
||
end;
|
||
|
||
end.
|
||
|