Sim, vc pode personalizar, até colocar salvar no cliente, o modelo do boleto, eu tenho dessa forma, o cara quer algo diferente, edito, salvo no banco e vida que segue.
Abstraia o código:
procedure TDMBoleto.ConfigurarFastReport;
var
ST: TMemoryStream;
begin
frxReport1.Clear;
frxReport1.Report.Clear;
frxDBReceber.RangeBegin := rbFirst;
frxDBReceber.RangeEnd := reLast;
frxReport1.EnabledDataSets.Clear;
frxReport1.DataSets.Clear;
frxReport1.DataSets.Add(frxDBReceber);
frxReport1.EnabledDataSets.Add(frxDBReceber);
ST := TMemoryStream.Create;
try
if FDSCfgMod.FieldByName('ARQUIVO_CFGBLMOD').IsNull then // Quando for atualizado, em Novembro de 2018, esse campo vai ficar vazio na tabela
begin
case FDSCfgMod.FieldByName('LAYOUT_CFGBLMOD').AsInteger of
1:
begin
TFuncoesSistemaOperacional.LerRecursoDLL('BOLETO_1PP_PIX', sNomeDaDLL, ST);
end;
2: TFuncoesSistemaOperacional.LerRecursoDLL('BOLETO_2PP', sNomeDaDLL, ST);
3: TFuncoesSistemaOperacional.LerRecursoDLL('BOLETO_3PP_CARNE', sNomeDaDLL, ST);
else // 3
raise Exception.Create('Tipo de Documento: Boleto ou carnê não selecionado na configuração.');
end;
end
else
TBlobField(FDSCfgMod.FieldByName('ARQUIVO_CFGBLMOD')).SaveToStream(ST);
ST.Position := 0;
frxReport1.LoadFromStream(ST);
finally
FreeAndNil(ST);
end;
// desnecessário, mantido pois tem modelo salvo no cliente, e gera erro
Var
S: string;
with frxReport1 do
begin
S := 'procedure INICIALIZA()';
if Script.FindLocal(S) = nil then
Script.AddMethod(S, CallMethod);
end;
end;
OnSaveReport, do Designer:
function TDMBoleto.frxDesignerBoleto_SaveReport(Report: TfrxReport;
SaveAs: Boolean): Boolean;
var
Stream: TStream;
begin
Stream := TMemoryStream.Create;
try
Report.SaveToStream(Stream);
Stream.Position := 0;
IBQryCfgMod.Edit;
TBlobField(IBQryCfgMod.FieldByName('ARQUIVO_CFGBLMOD')).LoadFromStream(Stream);
IBQryCfgMod.Post;
finally
Stream.Free;
end;
Result := True;
end;