Table of Contents

Templates in the executable (C++)

Note

This demo is available in your FlexCel installation at <FlexCel Install Folder>\Demo\Cpp\Modules\20.Reports\60.Templates In The Exe and also at https:​//​github.​com/​tmssoftware/​TMS-​FlexCel.​VCL-​demos/​tree/​master/​Cpp/​Modules/​20.​Reports/​60.​Templates In The Exe

Overview

Sometimes you might want to distribute your templates embedded in your application, instead of shipping the separately.

Concepts

  • How to embed a template directly in the exe file. For step-by-step instructions please read Embedding Excel files in your application

  • Dealing with includes. Included files are normally searched on the same path as the original file, but here, as we are reading from a stream, we must tell FlexCel where to find the embedded template. This is done with the TFlexCelReport.GetInclude event.

  • While here we show how to use a stream to read a template from the executable, you can use a very similar approach to store your templates in a database, or in any place you like. Just call the TFlexCelReport.Run with a stream with your data, and assign the TFlexCelReport.GetInclude event to assign the data for the included files.

Files

UMainForm.pas

unit UMainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  FlexCel.VCLSupport, FlexCel.Core, FlexCel.XlsAdapter, FlexCel.Report, FlexCel.Render,
  {$if CompilerVersion >= 23.0} System.UITypes, {$IFEND}
  ShellApi,
  Controls, Forms, Dialogs, StdCtrls, ExtCtrls;

type
  TMainForm = class(TForm)
    btnCancel: TButton;
    btnGo: TButton;
    SaveDialog: TSaveDialog;
    Label1: TLabel;
    procedure btnCancelClick(Sender: TObject);
    procedure btnGoClick(Sender: TObject);
  private
    procedure RunReport;
    procedure GetIncludes(const sender: TObject;const e: TGetIncludeEventArgs);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation
uses IOUtils, DemoData;

{$R *.dfm}

procedure TMainForm.btnCancelClick(Sender: TObject);
begin
  Close;
end;

procedure TMainForm.btnGoClick(Sender: TObject);
begin
  RunReport;

end;


procedure TMainForm.GetIncludes(const sender: TObject; const e: TGetIncludeEventArgs);
var
  IncReport: TResourceStream;
  b: TBytes;
begin
  IncReport := TResourceStream.Create(hinstance, TPath.GetFileNameWithoutExtension(e.FileName), RT_RCDATA);
  try
    SetLength(b, IncReport.Size);
    if (Length(b) > 0) then IncReport.Read(b[0], Length(b));
    e.IncludeData := b;
  finally
    IncReport.Free;
  end;
end;

procedure TMainForm.RunReport;
var
  Report: TFlexCelReport;
  TemplateStream: TResourceStream;
  OutputStream: TFileStream;
begin
  if not SaveDialog.Execute then exit;

  Report := TFlexCelReport.Create(true);
  try
    Report.GetInclude := GetIncludes; //this is only needed if you have includes.
    Report.AddTable(DemoTables);
    Report.SetValue('Date', Now);

    TemplateStream := TResourceStream.Create(hinstance, 'TemplatesInTheExe', RT_RCDATA);
    try
      OutputStream := TFileStream.Create(SaveDialog.FileName, fmCreate);
      try
        Report.Run(TemplateStream, OutputStream);
      finally
        OutputStream.Free;
      end;
    finally
      TemplateStream.Free;
    end;
  finally
    Report.Free;
  end;

  if MessageDlg('Do you want to open the generated file?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  begin
    ShellExecute(0, 'open', PCHAR(SaveDialog.FileName), nil, nil, SW_SHOWNORMAL);
  end;


end;

end.

TemplatesInTheExe.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
USEFORM("UMainForm.cpp", MainForm);
USEFORM("..\SharedData\DemoData.cpp", DemoTables); /* TDataModule: File Type */
//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	try
	{
		Application->Initialize();
		Application->MainFormOnTaskBar = true;
		Application->CreateForm(__classid(TMainForm), &MainForm);
		Application->CreateForm(__classid(TDemoTables), &DemoTables);
		Application->Run();
	}
	catch (Exception &exception)
	{
		Application->ShowException(&exception);
	}
	catch (...)
	{
		try
		{
			throw Exception("");
		}
		catch (Exception &exception)
		{
			Application->ShowException(&exception);
		}
	}
	return 0;
}
//---------------------------------------------------------------------------

UMainForm.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UMainForm.h"
#include <IOUtils.hpp>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::btnCancelClick(TObject *Sender)
{
  Close();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::btnGoClick(TObject *Sender)
{
  RunReport();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::GetIncludes(TObject* sender, TGetIncludeEventArgs* e)
{
  TResourceStream* IncReport = new TResourceStream((THandle)HInstance, TPath::GetFileNameWithoutExtension(e->FileName), RT_RCDATA);
  __try
  {
	TBytes b;
	b.Length = IncReport->Size;
	if (b.Length > 0) IncReport->ReadBuffer(&(b[0]), b.Length);
	e->IncludeData = b;
  }
  __finally
  {
	IncReport->Free();
  }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::RunReport()
{
  if (!SaveDialog->Execute()) return;

  TFlexCelReport* Report = new TFlexCelReport(true);
  __try
  {
	Report->GetInclude = GetIncludes; //this is only needed if you have includes.
	Report->AddTable(DemoTables);
	Report->SetValue("Date", TReportValue::Create(TCellValue::Create(Now())));

	TResourceStream* TemplateStream = new TResourceStream((THandle)HInstance, "TemplatesInTheExe", RT_RCDATA);
	__try
	{
	  TStream* OutputStream = new TFileStream(SaveDialog->FileName, fmCreate);
	  __try
	  {
		Report->Run(TemplateStream, OutputStream);
	  }
	  __finally
	  {
		OutputStream->Free();
	  }
	}
	__finally
	{
	  TemplateStream->Free();
	}
  }
  __finally
  {
	Report->Free();
  }

 if (MessageDlg(L"Do you want to open the generated file?", mtConfirmation,
	  TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes)
	  {
			ShellExecute(0, L"open", SaveDialog->FileName.c_str(), NULL, NULL,
			SW_SHOWNORMAL);
	  }


}
//---------------------------------------------------------------------------


UMainForm.h

//---------------------------------------------------------------------------

#ifndef UMainFormH
#define UMainFormH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Dialogs.hpp>
#include "DemoData.h"
#include <FlexCel.VCLSupport.hpp>
#include <FlexCel.Core.hpp>
#include <FlexCel.XlsAdapter.hpp>
#include <FlexCel.Report.hpp>


//---------------------------------------------------------------------------
class TMainForm : public TForm
{
__published:	// IDE-managed Components
	TLabel *Label1;
	TButton *btnCancel;
	TButton *btnGo;
	TSaveDialog *SaveDialog;
	void __fastcall btnCancelClick(TObject *Sender);
	void __fastcall btnGoClick(TObject *Sender);
private:	// User declarations
	void __fastcall RunReport();
	void __fastcall GetIncludes(TObject* sender, TGetIncludeEventArgs* e);
public:		// User declarations
	__fastcall TMainForm(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TMainForm *MainForm;
//---------------------------------------------------------------------------
#endif