FastReport 交流群

群   号:554714044

前言

由于公司开发新产品,前后端分离.netcore +Angular ,之前C/S项目一直使用FastReport ,考虑到员工切换比较困难,而且最最重要的是BS版少了很多内容,例如合计,函数最常用的功能都没有,所以B/S端打印控件继续沿用C/S模式。

一、逻辑视图

二、具体实现

1.Winform设计

如上图所示,这里做了一个打印模板与数据源的管理。在这里可以指定具体页面要调什么后端接口,打印什么数据,打印格式设计。全部WinForm实现。将数据源与打印格式模板存储到数据库。后端直接调取即可。

优点:1.与之前WinForm版无缝对接,开发人员不用学习即可使用。

2.做到数据源与打印格式集中化管理,而且可以根据客户需求,实施人员自己调整添加打印格式,不需要开发程序。

3.数据源多样化,可以根据特殊需求,自己拼接sql,也可以直接查询数据库表。满足客户多样化,个性化需求。

4.可以根据具体单据ID,调试打印格式。

缺点:WinForm 没有做成网络版,此设计器只能在服务器端(内网)使用。(本来设计就是要服务器设计,下面的人员用不到,缺点还可以接受

以下是部分代码

       /// <summary>
/// 绑定数据明细
/// </summary>
public void BindGridDts()
{
SReportManageDtsRule rule = new SReportManageDtsRule();
DataTable dtDts = rule.RShow(" AND DMainID=" + SysString.ToDBString(HTDataID) + " ORDER BY DSeq", ProcessGrid.GetQueryField(gridView1)); gridView1.GridControl.DataSource = dtDts;
gridView1.GridControl.Show();
} /// <summary>
/// 新增
/// </summary>
public string EntityAdd()
{
SReportManageRule rule = new SReportManageRule();
SReportManage entity = EntityGet();
SReportManageDts[] entitydts = EntityDtsGet();
SReportFile entityFile = new SReportFile();
if (chkMB.Checked)
{
entityFile.DContext = HttSoft.WinUIBase.FastReportX.ConvertToBinaryByPath(txtFilePath.Text.Trim());
entityFile.DFileName = entity.DFileName;
} rule.RAdd(entity, entitydts, entityFile);
return entity.DID;
} /// <summary>
/// 修改
/// </summary>
public void EntityUpdate()
{
SReportManageRule rule = new SReportManageRule();
SReportManage entity = EntityGet();
SReportManageDts[] entitydts = EntityDtsGet();
SReportFile entityFile = new SReportFile();
if (chkMB.Checked)
{
entityFile.DID = entity.DFileID;
entityFile.SelectByID();
entityFile.DContext = HttSoft.WinUIBase.FastReportX.ConvertToBinaryByPath(txtFilePath.Text.Trim());
entityFile.DFileName = entity.DFileName;
} rule.RUpdate(entity, entitydts, entityFile);
} /// <summary>
/// 设置
/// </summary>
public void EntitySet()
{
SReportManage entity = new SReportManage();
entity.DID = HTDataID;
bool findFlag = entity.SelectByID();
drpForm.Text = SysConvert.ToString(entity.DMenuID);
txtReportName.Text = entity.DReportName.ToString();
txtDSeq.Text = entity.DSeq.ToString();
txtAPI.Text = entity.DWebApi.ToString(); BindGridDts();
} /// <summary>
/// 删除
/// </summary>
public void EntityDelete()
{
SReportManageRule rule = new SReportManageRule();
SReportManage entity = EntityGet();
rule.RDelete(entity);
} #region 自定义方法
/// <summary>
/// 获得实体
/// </summary>
/// <returns></returns>
private SReportManage EntityGet()
{
SReportManage entity = new SReportManage();
entity.DID = HTDataID;
entity.SelectByID();
entity.DMenuID = SysConvert.ToString(drpForm.Text.Trim());
entity.DReportName = txtReportName.Text.Trim();
entity.DSeq = SysConvert.ToInt32(txtDSeq.Text.Trim());
entity.DWebApi = txtAPI.Text.Trim();
entity.DFileName = txtReportName.Text.Trim() + ".frx"; return entity;
} /// <summary>
/// 获得实体
/// </summary>
/// <returns></returns>
private SReportManageDts[] EntityDtsGet()
{ int index = ;
for (int i = ; i < gridView1.RowCount; i++)
{
if (SysConvert.ToString(gridView1.GetRowCellValue(i, "SqlName")) != "")
{
index++;
}
}
SReportManageDts[] entitydts = new SReportManageDts[index];
index = ;
for (int i = ; i < gridView1.RowCount; i++)
{
if (SysConvert.ToString(gridView1.GetRowCellValue(i, "SqlName")) != "")
{
entitydts[index] = new SReportManageDts();
entitydts[index].DMainID = SysConvert.ToString(gridView1.GetRowCellValue(i, "DMainID"));
if (entitydts[index].DMainID == HTDataID && HTDataID != "")//已存在表示修改
{
entitydts[index].DID = SysConvert.ToString(gridView1.GetRowCellValue(i, "DID"));
entitydts[index].SelectByID();
}
else//新增
{
entitydts[index].DMainID = HTDataID;
entitydts[index].DSeq = i + ;
} entitydts[index].DMainID = SysConvert.ToString(gridView1.GetRowCellValue(i, "DMainID"));
entitydts[index].DSeq = SysConvert.ToInt32(gridView1.GetRowCellValue(i, "DSeq"));
entitydts[index].DataSourceName = SysConvert.ToString(gridView1.GetRowCellValue(i, "DataSourceName"));
entitydts[index].SqlName = SysConvert.ToString(gridView1.GetRowCellValue(i, "SqlName"));
entitydts[index].SqlStr = SysConvert.ToString(gridView1.GetRowCellValue(i, "SqlStr"));
entitydts[index].QueryName = SysConvert.ToString(gridView1.GetRowCellValue(i, "QueryName"));
entitydts[index].SqlFlag = SysConvert.ToInt32(gridView1.GetRowCellValue(i, "SqlFlag"));
entitydts[index].SourceType = SysConvert.ToInt32(gridView1.GetRowCellValue(i, "SourceType"));
entitydts[index].Remark = SysConvert.ToString(gridView1.GetRowCellValue(i, "Remark")); index++;
}
}
return entitydts;
} #endregion
//添加一个基础模板
private void btnLook_Click(object sender, EventArgs e)
{
try
{
if (HTFormStatus == FormStatus.新增 || HTFormStatus == FormStatus.修改)
{
openFileDialog1.FileName = "";
openFileDialog1.Filter = "(*.frx)|*.frx|(*.fr3)|*.fr3|(*.*)|*.*";
openFileDialog1.ShowDialog();
if (openFileDialog1.FileName != string.Empty)
{
txtFilePath.Text = openFileDialog1.FileName;
}
} }
catch (Exception E)
{
MessageBox.Show(E.Message);
}
}
//窗体加载
private void HSPrintEdit_Load(object sender, EventArgs e)
{
//Common.BindFormID(drpForm);
Common.BindReportSource(drpReportSource, true);
}
//设计
private void btnDesign_Click(object sender, EventArgs e)
{
try
{
if (HTDataID == "")
{
MessageBox.Show("请先保存单据");
return;
}
SReportManage reportManage = new SReportManage();
reportManage.DID = HTDataID;
reportManage.SelectByID();
if (reportManage.DFileID == "")
{
MessageBox.Show("没有找到打印格式");
return;
} if (!chksql.Checked)
{
if (SysConvert.ToString(txtDataID.Text.Trim()) == "")
{
MessageBox.Show("请输入数据源ID");
return;
}
FastReport.ReportRun(HTDataID, (int)ReportPrintType.设计, new string[] { "DID", "DMainID" }, new string[] { SysConvert.ToString(txtDataID.Text.Trim()), SysConvert.ToString(txtDataID.Text.Trim()) });
}
else
{
if (SysConvert.ToString(txtsql.Text.Trim()) == "")
{
MessageBox.Show("请输入数据源sql");
return;
}
DataTable dt = SysUtils.Fill(txtsql.Text.Trim());
FastReport.ReportRunTable(HTDataID, (int)ReportPrintType.设计, dt);
} }
catch (Exception E)
{
MessageBox.Show(E.Message);
}
}
//预览
private void btnPreview_Click(object sender, EventArgs e)
{
try
{
if (HTDataID == "")
{
MessageBox.Show("请先保存单据");
return;
}
SReportManage reportManage = new SReportManage();
reportManage.DID = HTDataID;
reportManage.SelectByID();
if (reportManage.DFileID == "")
{
MessageBox.Show("没有找到打印格式");
return;
} if (!chksql.Checked)
{
if (SysConvert.ToString(txtDataID.Text.Trim()) == "")
{
MessageBox.Show("请输入数据源ID");
return;
}
FastReport.ReportRun(HTDataID, (int)ReportPrintType.预览, new string[] { "DID", "DMainID" }, new string[] { SysConvert.ToString(txtDataID.Text.Trim()), SysConvert.ToString(txtDataID.Text.Trim()) });
}
else
{
if (SysConvert.ToString(txtsql.Text.Trim()) == "")
{
MessageBox.Show("请输入数据源");
return;
}
DataTable dt = SysUtils.Fill(txtsql.Text.Trim());
FastReport.ReportRunTable(HTDataID, (int)ReportPrintType.预览, dt);
} }
catch (Exception E)
{
MessageBox.Show(E.Message);
}
}
 

  2.MVC端

为了将打印格式发布出去,这里特意做了一个mvc的程序,放在前端与后端之间,作为桥梁。

因为客户端只需要预览和打印,所以这里我只做了一个预览+打印的接口。设计在WinForm端处理,这里不需要。

以下是Preview的代码实现。

      public ActionResult Preview()
{
webReport = new WebReport();
webReport.Width = Unit.Percentage();
webReport.Height = Unit.Percentage(); string DataID = Request.QueryString["id"]; string ReportID = Request.QueryString["rid"]; string token = Request.QueryString["token"]; ReportModel model = new ReportModel();
model.DataID = DataID;
model.ReportID = ReportID; String token2 = "Bearer " + token;
HttpClient client = new HttpClient();
client.BaseAddress = _baseAddress;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
//获取模板文件地址,获取打印数据源webapi接口地址
#region 获取模板文件地址,获取打印数据源webapi接口地址
var jsonStr = JsonConvert.SerializeObject(model);
HttpContent cont = new StringContent(jsonStr);
cont.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var returnStr = "";
HttpResponseMessage resp = client.PostAsync("/api/SReportManage/getdataurl", cont).Result;//post提交数据,
if (resp.IsSuccessStatusCode)
{
returnStr = resp.Content.ReadAsStringAsync().Result;
}
ReportResult dtos = JsonConvert.DeserializeObject<ReportResult>(returnStr); #endregion //获取打印数据源
#region 获取打印数据源 HttpClient client2 = new HttpClient();
client2.BaseAddress = _baseAddress;
client2.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client2.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); var jsonStr2 = JsonConvert.SerializeObject(model);
HttpContent cont2 = new StringContent(jsonStr2);
cont2.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var returnStr2 = "";
HttpResponseMessage resp2 = client2.PostAsync(dtos.Data.WebApi, cont2).Result;//post提交数据,
if (resp2.IsSuccessStatusCode)
{
returnStr2 = resp2.Content.ReadAsStringAsync().Result;
}
ReportSourceResult result = JsonConvert.DeserializeObject<ReportSourceResult>(returnStr2);
if (result != null)
{
for (int i = ; i < result.Data.Count; i++)
{
webReport.Report.RegisterData(result.Data[i].dtsource, result.Data[i].TBName);
webReport.Report.GetDataSource(result.Data[i].TBName).Enabled = true;
}
} #endregion //webReport.Report.Load(dtos.Data.FileUrl + "Test.frx");
webReport.Report.Load(ConfigurationManager.AppSettings["ReportFilePath"] + dtos.Data.FileUrl);
webReport.ToolbarStyle = ToolbarStyle.Small;
webReport.ToolbarIconsStyle = ToolbarIconsStyle.Blue;
webReport.ToolbarBackgroundStyle = ToolbarBackgroundStyle.Custom; //webReport.PrintPdf(); webReport.PreviewMode = true;//预览模式
webReport.PrintInPdf = true;//在PDF打印 //webReport.DesignerPath = "~/WebReportDesigner/index.html";
//webReport.DesignerSavePath = "~/App_Data/DesignedReports";
//webReport.DesignerSaveCallBack = "~/Report/SaveDesignedReport";
webReport.ID = "DesignReport";
ViewBag.WebReport = webReport;
return View();
}

其中以下几点是我做了特殊化的设置

webReport.ToolbarStyle = ToolbarStyle.Small; //将原先的图标变小(太大太难看了)
webReport.ToolbarIconsStyle = ToolbarIconsStyle.Blue;
webReport.ToolbarBackgroundStyle = ToolbarBackgroundStyle.Custom;

(下拉菜单的汉化还没有找到,需要研究一下。)
webReport.PreviewMode = true;//预览模式
webReport.PrintInPdf = true;//在PDF打印

这里就是对接前端的打印接口。前端只需要调取我发布的网址,并且把我需要的参数(数据ID,打印模板ID,token传送给我即可。)

3.后端

后端接口主要是实现根据MVC端传送过来的打印模板ID,将数据源和模板传送给MVC端。由MVC端进行拼接组装。

主要代码如下:

         public List<ReportDataSource> GetDataSource(ReportModel entitydto)
{
try
{
List<ReportDataSource> lst = new List<ReportDataSource>();
IDBTransAccess sqlTrans = TransSysUtils.GetDBTransAccess();
try
{
sqlTrans.OpenTrans(); lst = this.GetDataSource(entitydto, sqlTrans); sqlTrans.CommitTrans();
return lst;
}
catch (Exception TE)
{
sqlTrans.RollbackTrans();
throw TE;
}
}
catch (BaseException)
{
throw;
}
catch (Exception E)
{
throw new BaseException(E.Message);
}
} public List<ReportDataSource> GetDataSource(ReportModel entitydto, IDBTransAccess sqlTrans)
{
try
{
List<ReportDataSource> lst = ReportRun(entitydto.ReportID, new string[] { "DID","DMainID" }, new string[] { entitydto.DataID,entitydto.DataID }, sqlTrans); return lst; }
catch (BaseException)
{
throw;
}
catch (Exception E)
{
throw new BaseException(E.Message);
}
} #endregion public List<ReportDataSource> ReportRun(string reportID, string[] queryName, string[] queryValue, IDBTransAccess sqlTrans)
{
List<ReportDataSource> lst = new List<ReportDataSource>();
string sql = "Select * from Data_SReportManageDts where DMainID=" + SysString.ToDBString(reportID);
DataTable dtSource = sqlTrans.Fill(sql);
if (dtSource.Rows.Count > )
{
foreach (DataRow dr in dtSource.Rows)
{
bool findSource = false;
string conditionStr = string.Empty;
if (SysConvert.ToInt32(dr["SqlFlag"]) == )
{
string[] tempA = dr["QueryName"].ToString().Split(' ');
for (int q = ; q < queryName.Length; q++)
{
for (int fi = ; fi < tempA.Length; fi++)
{
if (queryName[q].ToString().ToUpper() == tempA[fi].ToUpper())
{
if (conditionStr != string.Empty)
{
conditionStr += " AND ";
}
conditionStr += queryName[q].ToString() + "=" + SysString.ToDBString(queryValue[q]);
findSource = true;
break;
}
} }
}
else
{
conditionStr = SysConvert.ToString(dr["QueryName"]).ToUpper();
for (int i = ; i < queryName.Length; i++)
{
string queryStr = "{" + queryName[i].ToUpper() + "}"; conditionStr = conditionStr.Replace(queryStr, SysString.ToDBString(queryValue[i]));
}
if (conditionStr.Contains("{") || conditionStr.Contains("}"))
{
findSource = false;
}
else
{
findSource = true;
}
}
if (findSource)
{ if (SysConvert.ToInt32(dr["SqlFlag"]) == )
{ sql = "select * from (" + dr["SqlStr"].ToString() + ") a where " + conditionStr;
}
else
{ sql = dr["SqlStr"].ToString() + " " + conditionStr;
}
DataTable dt = sqlTrans.Fill(sql); ReportDataSource source = new ReportDataSource();
source.dtsource = dt;
source.TBName = dr["SqlName"].ToString();
lst.Add(source); }
else
{
if (dr["SqlStr"].ToString() != string.Empty)
{
sql = dr["SqlStr"].ToString();
DataTable dt = sqlTrans.Fill(sql); ReportDataSource source = new ReportDataSource();
source.dtsource = dt;
source.TBName = dr["SqlName"].ToString();
lst.Add(source); }
}
}
} return lst;
}

FastReport 交流群

群   号:554714044

B/S FastReprot使用的更多相关文章

  1. FastReport调用Delphi中的自定义函数(人民币大写金额)mtm

    1. 在 FormCreate 中向FastReprot添加函数 (fPrint)窗口 procedure TfPrint.FormCreate(Sender: TObject); frxReport ...

随机推荐

  1. 服装类Web原型制作分享——Rodd & Gunn

    Rodd & Gunn是国外知名的服装类品牌,服装种类繁多,有衣服.帽子.穿戴饰品等. 本原型由国产Mockplus(原型工具)和iDoc(智能标注,一键切图工具)提供. 网站原型以图文排版为 ...

  2. 摹客首家发布Adobe XD插件

    10月19日,摹客iDoc发布了支持Adobe XD的插件,这是中国国内首款基于Adobe XD 正式API的插件. 设计师在Adobe XD 中安装并使用此插件,可以将设计稿上传到摹客iDoc,并使 ...

  3. Vue热更新报错(log.error('[WDS] Errors while compiling. Reload prevented.'))

    log.error('[WDS] Errors while compiling. Reload prevented.');中的WDS其实是webpack-dev-serverwebpack的意思,用来 ...

  4. canvas 实现烟花效果

    一:创建画布 <canvas width="600" height="600" id="canvas" style="bor ...

  5. gcc 库路径里同时有相同文件名的动态库和静态库

    找不到库的处理方案 有两种方法: 一.可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行). 二.把当前路径加 ...

  6. 2018.11.06 bzoj1093: [ZJOI2007]最大半连通子图(缩点+拓扑排序)

    传送门 先将原图缩点,缩掉之后的点权就是连通块大小. 然后用拓扑排序统计最长链数就行了. 自己yyyyyy了一下一个好一点的统计方法. 把所有缩了之后的点都连向一个虚点. 然后再跑拓扑,这样最后虚点的 ...

  7. 牛客训练四:Applese 涂颜色(费马小定理+快速幂)

    题目链接:传送门 思路: 考虑每一列有2种颜色,总共有n行,每一行的第一个格确定颜色,由于左右颜色不相同,后面的行就确定了. 所以总共有2^n中结果. 由于n太大,所以要用到费马小定理a^n%mod= ...

  8. 1-9-假期训练心得(dp+bfs)

    题目一:传送门 思路:就是简单的bfs,注意仔细审题,加上对转弯次数的判断. 题目二:传送门 思路:简单dp,记录每一秒每个位置接到的大饼的数量. 状态转移方程:dp[i][j]=max(dp[i][ ...

  9. IntelliJ IDEA 2017版 Spring5最基本的bean例子创建

    一.简述         SpringBoot是基于spring框架之上的快速开发的框架.Spring4核心就是容器,容器提供了对bean的装配和管理.       spring依赖加载:       ...

  10. 词袋模型(BOW, bag of words)

    词集模型:单词构成的集合,每个单词只出现一次. 词袋模型:把每一个单词都进行统计,同时计算每个单词出现的次数. 在train_x中,总共有6篇文档,每一行代表一个样本即一篇文档.我们的目标是将trai ...