9.4.一体化查询

  硕正报表从1.0.101.0开始,支持以 jQuery Mobile 的语法规则的动态嵌入模板, 如果一体化查询的报表有专门用于输入查询条件的工作表, 该工作表将能被转换成比较符合移动设备的界面展示:

  上面的报表是来自在线演示 "32.一体化查询(三)", 该报表的动态下拉数据、工作表 "Sheet" 的查询结果数据, 均来自数据源,转换成移动页面时,仍然依赖并重用了这些数据源数据,也就是说,后端的 C#/Java 数据源程序不需要另行开发.
  报表XML模板要转换成 jQuery Mobile 的样式, 首先必须在模板中为需要转换的单元格设置 TabOrder,即人工认定哪些单元格是可输入的查询条件:
  此外, 转换过程也依赖 jQuery Mobile 样式的模板。

9.4.1 模版分析

  模版文件是 template_search.txt
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.css">
<script src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://apps.bdimg.com/libs/jquerymobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

<script src="../uploadxml.js"></script>
<script>
<!--SUPCAN_REPORT_JS-->

$(document).ready(function() {
  //"开始查询" 按钮点击事件, 打开新页面
  $("#search").click(function() {
    var s = $("#form1").serialize();    //取得 Form 的提交串
    window.open("../query.aspx?page=2&" + s);
  });
});
</script>
</head>

<body>
<div data-role="page">
  <div data-role="header" data-theme="b">
    <a href="#" class="ui-btn ui-corner-all ui-shadow ui-icon-home ui-btn-icon-left">主页</a>
    <h1><!--SUPCAN_REPORT_WorkSheetName--></h1>
    <a href="#" class="ui-btn ui-corner-all ui-shadow ui-icon-search ui-btn-icon-left">搜索</a>
  </div>

  <div data-role="main" class="ui-content" data-theme="b">
    <form id="form1">
      <div class="ui-field-contain">
<!--SUPCAN_REPORT_dMain-->
      </div>
      <input id="search" type="button" value="开始查询">
    </form>
  </div>
</div>
</body>
</html>
  前 8 行是 jQuery Mobile固定的引用, 第 9 行使用了硕正的 uploadxml.js 文件, 该文件原本是用于上报的, 但本例只是共享了其中下拉关联、以及数据源的 ajax 访问的部分代码. 文件在 uploadmobile.zip 包中. 部署 uploadxml.js 时请注意相对URL的位置: 它是相对于最终生成的 html,而不是这个模版的位置。

  第 17 行执行查询的语句, 它是打开了一个新页面, 如果你解决了页面来回跳转的数据持续问题, 那么也可以修改这个模板, 改成用 <Form action="..." rel="external"> 直接跳转,不过此功能和硕正的动态转换并没有什么关系。

  模板的关键部分是第 34 行,用到了占位符 <!--SUPCAN_REPORT_dMain-->,动态生成的 html Form 表单内容都在此处插入的,硕正报表自动生成的替换内容是类似这种的:
<label for="sup_dat_E4">请选择区域:</label>
<select id="sup_dat_E4" name="E4" droplistName="sup_droplist2" affectTo="sup_dat_E6" value="1">
</select><br>
<label for="sup_dat_E6">国家:</label>
<select id="sup_dat_E6" name="E6" droplistName="sup_droplist1" dependent="sup_dat_E4" value="Austria">
</select><br>
<label for="sup_dat_E7">仅百吨以上货物</label>
<input id="sup_dat_E7" name="RADIOGROUP1" type="radio" value="E7"/><br>
<label for="sup_dat_E8">全部货物</label>
<input id="sup_dat_E8" name="RADIOGROUP1" type="radio" value="E8" checked="true"/><br>
<input name="allfieldname" type="text" value="E4,E6,RADIOGROUP1" style="display:none;"/>

9.4.2 C#源码分析

  C# 源码文件为 query.aspx, 里面大部分代码和服务器专版的其它演示功能的代码都差不多, 下面只分析关键实现部分。
  报表有 2 个工作表, 所以分别有二段代码, 查询条件页的 C# 如下:
if(page == "1") {       //第一个页面
 // jQueryMobile 模版文件, 它位于当前目录下
 String TemplateFile = Server.MapPath("template_search.txt");
 //转换
 dll.func("callfunc", "105\r\n type=htm; isQueryPage=true; Template=" +TemplateFile+ "; filename=" + TempFilename);
}
  调用 105 功能号且设置 isQueryPage=true , 以及 jQueryMobile 模板,这就是关键所在了。

  第二段代码略复杂:
else if(page == "2") {      //第二个页面
 //取得 Form 内容, 设置到报表第一个工作表中
 String[] arrCellname = Request.Params["allfieldname"].Split(new Char[] {','});
 foreach(String CellName in arrCellname) {
  String Data = Request.Params[CellName];
  if(Data == null) Data = "";
  if(CellName.Length > 10) {
   if(CellName.Substring(0, 10) == "RADIOGROUP") {
    dll.func("SetCellDataEx", Data + "\r\n1");
    continue;
   }
  }
  dll.func("SetCellDataEx", CellName + "\r\n" + Data);
 }
 //切换到工作表二
 dll.func("SetCurrentWorksheet", "1");
 //计算当前工作表
 dll.func("calc", "range=current");
 //转换
 dll.func("callfunc", "105\r\n type=htm; filename=" + TempFilename);
}
  由于查询条件是 Form 提交上来的,所以必须分拆这些条件, 分别设置到指定单元格中去, 然后模拟常规的客户端功能:执行计算、转换输出.