using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using FastReport.Utils;
using FastReport.Preview;
using System.Drawing;
namespace FastReport.Export
{
///
/// The base class for all export filters.
///
public partial class ExportBase : Base
{
private PageRange pageRange;
private string pageNumbers;
private int curPage;
private Stream stream;
private string fileName;
private List pages;
private bool openAfter;
private bool allowOpenAfter;
private float zoom;
private List generatedFiles;
private bool allowSaveSettings;
private bool showProgress;
private int exportTickCount;
private bool hasMultipleFiles;
private bool shiftNonExportable;
private string saveInitialDirectory;
private List generatedStreams;
private bool exportTabs;
protected bool webPreview;
#region Properties
///
/// Gets list of generated streams.
///
public List GeneratedStreams
{
get { return generatedStreams; }
protected set { generatedStreams = value; }
}
///
/// Zoom factor for output file
///
public float Zoom
{
get { return zoom; }
set { zoom = value; }
}
///
/// File filter that can be used in the "Save file" dialog.
///
public string FileFilter
{
get { return GetFileFilter(); }
}
///
/// Range of pages to export.
///
public PageRange PageRange
{
get { return pageRange; }
set { pageRange = value; }
}
///
/// Page numbers to export.
///
///
/// Use page numbers separated by comma and/or page ranges, for example: "1,3-5,12". Empty string means
/// that all pages need to be exported.
///
public string PageNumbers
{
get { return pageNumbers; }
set { pageNumbers = value; }
}
///
/// Current page number.
///
///
/// Page number need to be exported if user selects "Current page" radiobutton in the export options dialog.
/// This property is typically set to current page number in the preview window.
///
public int CurPage
{
get { return curPage; }
set { curPage = value; }
}
///
/// Open the document after export.
///
public bool OpenAfterExport
{
get { return openAfter; }
set { openAfter = value; }
}
///
/// Allows or disables the OpenAfterExport feature.
///
public bool AllowOpenAfter
{
get { return allowOpenAfter; }
set { allowOpenAfter = value; }
}
///
/// Gets or sets a value that determines whether to show progress window during export or not.
///
public bool ShowProgress
{
get { return showProgress; }
set { showProgress = value; }
}
///
/// Gets a list of files generated by this export.
///
public List GeneratedFiles
{
get { return generatedFiles; }
}
///
/// Gets a value indicating that the export may produce multiple output files.
///
public bool HasMultipleFiles
{
get { return hasMultipleFiles; }
set { hasMultipleFiles = value; }
}
///
/// Gets or sets a value indicating that the report bands should be shifted, if page
/// has any non-exportable bands
///
public bool ShiftNonExportable
{
get { return shiftNonExportable; }
set { shiftNonExportable = value; }
}
///
/// Gets or sets the initial directory that is displayed by a save file dialog.
///
public string SaveInitialDirectory
{
get { return saveInitialDirectory; }
set { saveInitialDirectory = value; }
}
///
/// Gets or sets a value indicating that pages will exporting from all open tabs.
///
public bool ExportAllTabs
{
get { return exportTabs; }
set { exportTabs = value; }
}
///
/// Stream to export to.
///
protected Stream Stream
{
get { return stream; }
}
///
/// File name to export to.
///
protected string FileName
{
get { return fileName; }
}
///
/// Array of page numbers to export.
///
protected int[] Pages
{
get { return pages.ToArray(); }
}
internal bool AllowSaveSettings
{
get { return allowSaveSettings; }
set { allowSaveSettings = value; }
}
#endregion
#region Private Methods
private bool Parse(string pageNumbers, int total)
{
pages.Clear();
string s = pageNumbers.Replace(" ", "");
if (s == "") return false;
if (s[s.Length - 1] == '-')
s += total.ToString();
s += ',';
int i = 0;
int j = 0;
int n1 = 0;
int n2 = 0;
bool isRange = false;
while (i < s.Length)
{
if (s[i] == ',')
{
n2 = int.Parse(s.Substring(j, i - j));
j = i + 1;
if (isRange)
{
while (n1 <= n2)
{
pages.Add(n1 - 1);
n1++;
}
}
else
pages.Add(n2 - 1);
isRange = false;
}
else if (s[i] == '-')
{
isRange = true;
n1 = int.Parse(s.Substring(j, i - j));
j = i + 1;
}
i++;
}
return true;
}
private void PreparePageNumbers()
{
pages.Clear();
int total = Report.PreparedPages.Count;
if (PageRange == PageRange.Current)
pages.Add(CurPage - 1);
else if (!Parse(PageNumbers, total))
{
for (int i = 0; i < total; i++)
pages.Add(i);
}
// remove invalid page numbers
for (int i = 0; i < pages.Count; i++)
{
if (pages[i] < 0 || pages[i] >= total)
{
pages.RemoveAt(i);
i--;
}
}
}
private void OpenFile()
{
try
{
Process proc = new Process();
proc.EnableRaisingEvents = false;
#if NETCOREAPP
proc.StartInfo.FileName = "cmd";
proc.StartInfo.Arguments = $"/c \"{fileName}\"";
proc.StartInfo.CreateNoWindow = true;
#else
proc.StartInfo = new ProcessStartInfo(fileName) { UseShellExecute = true };
#endif
proc.Start();
}
catch
{
}
}
private void SaveSettings()
{
XmlItem root = Config.Root.FindItem("Preview").FindItem("Exports").FindItem(ClassName);
using (FRWriter writer = new FRWriter(root))
{
root.Clear();
writer.Write(this);
}
}
private void RestoreSettings()
{
XmlItem root = Config.Root.FindItem("Preview").FindItem("Exports").FindItem(ClassName);
using (FRReader reader = new FRReader(null, root))
{
reader.Read(this);
}
}
#endregion
#region Protected Methods
///
/// Returns a file filter for a save dialog.
///
/// String that contains a file filter, for example: "Bitmap image (*.bmp)|*.bmp"
protected virtual string GetFileFilter()
{
return "";
}
///
/// This method is called when the export starts.
///
protected virtual void Start()
{
this.Report.OnExportParameters(new ExportParametersEventArgs(this));
}
///
/// This method is called at the start of exports of each page.
///
/// Page for export may be empty in this method.
protected virtual void ExportPageBegin(ReportPage page)
{
page = GetOverlayPage(page);
}
///
/// This method is called at the end of exports of each page.
///
/// Page for export may be empty in this method.
protected virtual void ExportPageEnd(ReportPage page)
{
}
///
/// This method is called for each band on exported page.
///
/// Band, dispose after method compite.
protected virtual void ExportBand(BandBase band)
{
band.UpdateWidth();
}
///
/// This method is called when the export is finished.
///
protected virtual void Finish()
{
}
///
/// Gets a report page with specified index.
///
/// Zero-based index of page.
/// The prepared report page.
protected ReportPage GetPage(int index)
{
ReportPage page = Report.PreparedPages.GetPage(index);
return GetOverlayPage(page);
}
#endregion
#region Public Methods
///
public override void Assign(Base source)
{
BaseAssign(source);
}
///
public override void Serialize(FRWriter writer)
{
writer.WriteValue("PageRange", PageRange);
writer.WriteStr("PageNumbers", PageNumbers);
writer.WriteBool("OpenAfterExport", OpenAfterExport);
writer.WriteBool("ExportAllTabs", ExportAllTabs);
}
///
/// Exports the report to a stream.
///
/// Report to export.
/// Stream to export to.
///
/// This method does not show an export options dialog. If you want to show it, call
/// method prior to calling this method, or use the "Export(Report report)" method instead.
///
public void Export(Report report, Stream stream)
{
if (report == null || report.PreparedPages == null)
return;
SetReport(report);
this.stream = stream;
PreparePageNumbers();
GeneratedFiles.Clear();
exportTickCount = Environment.TickCount;
if (pages.Count > 0)
{
if (!String.IsNullOrEmpty(FileName))
GeneratedFiles.Add(FileName);
Start();
report.SetOperation(ReportOperation.Exporting);
if (ShowProgress)
Config.ReportSettings.OnStartProgress(Report);
else
Report.SetAborted(false);
try
{
for (int i = 0; i < GetPagesCount(pages); i++)
{
if (ShowProgress)
{
Config.ReportSettings.OnProgress(Report,
String.Format(Res.Get("Messages,ExportingPage"), i + 1, pages.Count), i + 1, pages.Count);
}
if (!Report.Aborted && i < pages.Count)
ExportPageNew(pages[i]);
else
break;
}
}
finally
{
Finish();
if (ShowProgress)
Config.ReportSettings.OnProgress(Report, String.Empty);
if (ShowProgress)
Config.ReportSettings.OnFinishProgress(Report);
report.SetOperation(ReportOperation.None);
exportTickCount = Environment.TickCount - exportTickCount;
ShowPerformance(exportTickCount);
if (openAfter && AllowOpenAfter && stream != null)
{
stream.Close();
OpenFile();
}
}
}
}
public void InstantExportStart(Report report, Stream stream)
{
SetReport(report);
this.stream = stream;
GeneratedFiles.Clear();
if (!String.IsNullOrEmpty(FileName))
GeneratedFiles.Add(FileName);
Start();
}
public void InstantExportBeginPage(ReportPage page)
{
ExportPageBegin(page);
}
public void InstantExportExportBand(BandBase band)
{
ExportBand(band);
}
public void InstantExportEndPage(ReportPage page)
{
ExportPageEnd(page);
}
public void InstantExportFinish()
{
Finish();
}
internal void ExportPageNew(int pageNo)
{
PreparedPage ppage = Report.PreparedPages.GetPreparedPage(pageNo);
{
ReportPage page = null;
try
{
page = ppage.StartGetPage(pageNo);
page.Width = ppage.PageSize.Width;
page.Height = ppage.PageSize.Height;
ExportPageBegin(page);
float topShift = 0;
foreach (Base obj in ppage.GetPageItems(page, false))
{
BandBase band = obj as BandBase;
if (shiftNonExportable && topShift != 0 && obj is BandBase &&
!(obj is PageFooterBand) && !band.PrintOnBottom)
{
band.Top -= topShift;
}
if (band.Exportable
|| webPreview)
ExportBand(band);
else if (obj != null)
{
if (shiftNonExportable)
topShift += band.Height;
obj.Dispose();
}
}
ExportPageEnd(page);
}
finally
{
ppage.EndGetPage(page);
}
if(page != null)
page.Dispose();
}
}
///
/// Exports the report to a file.
///
/// Report to export.
/// File name to export to.
///
/// This method does not show an export options dialog. If you want to show it, call
/// method prior to calling this method, or use the "Export(Report report)" method instead.
///
public void Export(Report report, string fileName)
{
this.fileName = fileName;
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
Export(report, stream);
stream.Close();
}
}
internal string GetFileName(Report report)
{
return Path.GetFileNameWithoutExtension(Path.GetFileName(report.FileName));
}
internal string GetFileExtension()
{
string extension = FileFilter;
return extension.Substring(extension.LastIndexOf('.'));
}
internal void ExportAndZip(Report report, Stream stream)
{
string tempFolder = Config.GetTempFolder() + Path.GetRandomFileName();
Directory.CreateDirectory(tempFolder);
try
{
string filePath = Path.Combine(tempFolder, GetFileName(report) + GetFileExtension());
Export(report, filePath);
ZipArchive zip = new ZipArchive();
zip.AddDir(tempFolder);
zip.SaveToStream(stream);
}
finally
{
Directory.Delete(tempFolder, true);
}
}
#endregion
///
/// Initializes a new instance of the class.
///
public ExportBase()
{
pageNumbers = "";
pages = new List();
curPage = 1;
fileName = "";
allowOpenAfter = true;
zoom = 1;
generatedFiles = new List();
exportTabs = false;
shiftNonExportable = false;
}
}
}