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 提交上来的，所以必须分拆这些条件, 分别设置到指定单元格中去, 然后模拟常规的客户端功能：执行计算、转换输出.