本文分享一个工具“GhostHook”,该工具可以彻底解决调用报表的问题。在使用它加载报表的时候,我们传递给报表的参数可以以Get的方式进行传递,“GhostHook”接受到参数后将模拟用户的输入和提交操作。
来看看“GhostHook”的用法吧:
操作步骤
图1
图2
图3
图4
图5
图6
图7
使用到的代码
GhostHook.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GhostHook.aspx.cs" Inherits="GhostHook" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>GhostHook</title>
</head>
<script language="javascript" type="text/javascript">
/*
作者:GhostBear
制作日期:2012年8月25日
博客地址:Http://blog.csdn.net/ghostbear
简介:接收服务器端传递过来的参数并模拟用户对报表进行输入提交操作。
*/
document.onreadystatechange = oncomplete;
function oncomplete() {
if (document.readyState == "complete") {
Go();
}
}
function Go() {
var tmp = document.getElementById("report").contentWindow.document.getElementById("resultFrame").contentWindow.document.getElementsByTagName("input").length;
if (tmp == 0) {
setTimeout("Go()", 1000);
}
else {
var paramPnl = document.getElementById("report").contentWindow.document.getElementById("resultFrame").contentWindow;
var paramElements = new Array();
var inputElements = paramPnl.document.getElementsByTagName("input");
var ddlElements = paramPnl.document.getElementsByTagName("select");
var boolElements = paramPnl.document.getElementsByTagName("label");
var submitButton = paramPnl.document.getElementById("reportViewer_ctl04_ctl00");
var paramExp = /^reportViewer_ctl04_ctl(\d{2})_(txtValue|rbTrue|rbFalse|ddValue)$/;
var paramValueString = "<%=ParameterValueString%>";
var paramValueArray = paramValueString.split(';');
var ddlButtonExp = /^reportViewer_ctl04_ctl\d{2}_ddDropDownButton$/;
var ddlItemExp = "^reportViewer_ctl04_ctl($NUM$)_divDropDown_ctl\\d{2}$";
Parameter = function (pType, pDom, pNo) {
this.ParameterType = pType;
this.InputDom = pDom;
this.ParameterNo = pNo;
}
//筛选输入类型为文本框的参数
for (var i in inputElements) {
if (inputElements[i].id != undefined) {
if (paramExp.test(inputElements[i].id)) {
if (inputElements[i].nextSibling != null && ddlButtonExp.test(inputElements[i].nextSibling.id)) {//筛选下拉列表类型输入参数
var pNo = inputElements[i].id.match(paramExp)[1];
var curChkExp = new RegExp(ddlItemExp.replace("($NUM$)", pNo));
var curParams = new Array();
for (var j = 0; j < inputElements.length; j++) {
if (inputElements[j].id != undefined && curChkExp.test(inputElements[j].id)) {
curParams.push(inputElements[j]);
}
}
var p = new Parameter("ddl", curParams, pNo);
paramElements.push(p);
}
else {//筛选文本框类型输入参数
var pNo = inputElements[i].id.match(paramExp)[1];
var p = new Parameter("textbox", inputElements[i], pNo);
paramElements.push(p);
}
}
}
}
//筛选输入类型为布尔的参数
var tmpBoolArray = new Array();
for (var i = 0; i < boolElements.length; i++) {
if (boolElements[i].htmlFor != undefined) {
if (paramExp.test(boolElements[i].htmlFor)) {
tmpBoolArray.push(boolElements[i].previousSibling);
}
}
}
tmpBoolArray.sort(function (n1, n2) {
var no1 = parseInt(n1.id.match(paramExp)[1]);
var no2 = parseInt(n2.id.match(paramExp)[1]);
return no1 < no2;
});
for (var i = 0; i < tmpBoolArray.length; i = i + 2) {
var pNo = tmpBoolArray[i].id.match(paramExp)[1];
var p = new Parameter("bool", [tmpBoolArray[i], tmpBoolArray[i + 1]], pNo);
paramElements.push(p);
}
//筛选输入类型为下拉列表的参数
for (var i = 0; i < ddlElements.length; i++) {
if (ddlElements[i].id != undefined) {
if (paramExp.test(ddlElements[i].id)) {
var pNo = ddlElements[i].id.match(paramExp)[1];
var p = new Parameter("select", ddlElements[i], pNo)
paramElements.push(p);
}
}
}
//为参数排序
var tmpElement;
var tmpIndex
for (var i = 0; i < paramElements.length; i++) {
tmpIndex = i;
for (var j = i + 1; j < paramElements.length; j++) {
var n1 = paramElements[tmpIndex].ParameterNo;
var n2 = paramElements[j].ParameterNo;
if (n1 > n2) {
tmpIndex = j;
}
}
if (tmpIndex != i) {
tmpElement = paramElements[i];
paramElements[i] = paramElements[tmpIndex];
paramElements[tmpIndex] = tmpElement;
}
}
//模拟用户录入参数
for (var i = 0; i < paramElements.length; i++) {
switch (paramElements[i].ParameterType) {
case "textbox":
paramElements[i].InputDom.value = paramValueArray[i];
break;
case "bool":
var selectedValue = eval(paramValueArray[i]);
if (selectedValue) {
if (paramElements[i].InputDom[0].id.match(/rbTrue/)) {
paramElements[i].InputDom[0].checked = "checked";
}
else {
paramElements[i].InputDom[1].checked = "checked";
}
}
else {
if (paramElements[i].InputDom[0].id.match(/rbFalse/)) {
paramElements[i].InputDom[0].checked = "checked";
}
else {
paramElements[i].InputDom[1].checked = "checked";
}
}
break;
case "select":
var options = paramElements[i].InputDom.getElementsByTagName("option");
var selectedValue = paramValueArray[i];
for (var j = 0; j < options.length; j++) {
if (options[j].innerText == selectedValue) {
options[j].selected = "selected";
break;
}
}
break;
case "ddl":
var chkItems = paramElements[i].InputDom;
var selectedValue = paramValueArray[i].split(',');
for (var k = 0; k < chkItems.length; k++) {
for (var m = 0; m < selectedValue.length; m++) {
if (chkItems[k].nextSibling.innerText == selectedValue[m]) {
chkItems[k].checked = "checked";
chkItems[k].onclick(this);
break;
}
}
}
break;
default:
break;
}
}
//模拟用户提交操作
submitButton.click();
}
}
</script>
<frameset>
<frame rows="100%" cols="100%" name="report" id="report" src="../../test/crmreports/viewer/viewer.aspx?action=filter&helpID=<%=RDL_Name%>&id=<%=RDL_Id%>" ></frame>
</frameset>
</html>
GhostHook.aspx.cs
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text.RegularExpressions;
public partial class GhostHook : System.Web.UI.Page
{
protected string ParameterValueString;
protected string RDL_Id = string.Empty;
protected string RDL_Name = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
Dictionary<string, string> paramTbl = new Dictionary<string, string>();
//参数的格式:ReportView.aspx?p1=123&p2=5678
foreach (string p in Request.QueryString.AllKeys)
{
if (p == "RDL_Id")
{
RDL_Id = Request.QueryString[p];
continue;
}
if (p == "RDL_Name")
{
RDL_Name = Request.QueryString[p];
continue;
}
paramTbl.Add(p, Request.QueryString[p]);
}
if (string.IsNullOrEmpty(RDL_Id) || string.IsNullOrEmpty(RDL_Name))
{
Response.Clear();
Response.Write("需要提供参数“RDL_Id”和“RDL_Name”。");
}
for (int i = 1; i <= paramTbl.Count; i++)
{
ParameterValueString += string.Format("{1}", "p" + i.ToString(), paramTbl["p" + i.ToString()]);
if (i != paramTbl.Count)
{
ParameterValueString += ";";
}
}
}
}
小结
GhostHook虽然比较强大,但还是有些小弊端:
1.受Get传参的影响,传递参数的大小有限制。(好像是2048个字符,不知道是不是?)
2.JavaScript脚本中的GO()函数是通过轮询的方式来运行的(setTimeout)。如果能将它挂在GhostHook.aspx中嵌入的frame页面的onreadystatechange中就完美了。(大家有没好的建议?)