65.9K
CodeProject 正在变化。 阅读更多。
Home

创建自定义报告以在 SharePoint 2013 中显示 SSRS 报告使用情况详细信息

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2016年7月19日

CPOL

4分钟阅读

viewsIcon

26866

本文介绍如何在 SharePoint 网站中创建 SSRS 报表的自定义使用情况报告。

引言

我们将为部署在 SharePoint 网站中的 SSRS 报表生成使用情况报告。该报告的来源是配置 SharePoint 服务器上的 SSRS 服务应用程序时创建的 Reporting Service 数据库。

生成报告的步骤

  1. 配置 SSRS 服务应用程序
  2. 生成查询以从数据库中检索使用情况数据
  3. 使用 Asp.net 和 C#.net 代码在 GridView 中显示数据

报告概述

下图描绘了我们将如何使用 Asp.net 中的 GridView 控件在 SharePoint 页面上呈现数据。

步骤 1:配置 SSRS 服务应用程序

有关配置 SSRS 服务应用程序的详细步骤,请参阅以下链接。

在 SharePoint 服务器中配置 SSRS 报表

步骤 2:生成查询以检索 SSRS 报表的使用情况数据

请按照以下步骤生成查询。

  1. 导航到已配置 SSRS 数据库的 SharePoint 服务器。
  2. 打开 SQL Management Studio 并连接到 Reporting Service 数据库“ReportingService_SharePoint”。数据库名称可能因您的环境而异,请记住配置服务应用程序时输入的数据库名称。

在 Reporting Service 数据库中,我们仅使用了两个表来获取执行日志详细信息。

1. Catalog 表

此表包含上传到 SharePoint 文档库的 rdl 文件/报表的元数据。

  • ItemId – 项目的 guid
  • Path – 文件在文档库中的位置
  • Name – 上传文件到文档库时为 rdl 文件指定的名称

2. ExecutionLogStorage 表

此表包含 SharePoint 网站中每个 RDL 报表的执行详细信息。

  • Parameter – 访问报表时传递的参数
  • Format – 文件类型(RPL / HTML 等)
  • TimeStart – 执行开始时间
  • TimeEnd – 执行结束时间
  • TimeDataRetrival – 数据检索时间
  • TimeProcessing – 处理时间

3. 展开 View 文件夹以获取 SSRS 报表的执行日志。默认情况下,数据库中有 3 个视图,如下图所示。

ExecutionLog3 查询

SELECT [InstanceName] ,[ItemPath],[UserName],[ExecutionId],[RequestType] ,[Format],[Parameters],[ItemAction]
      ,[TimeStart],[TimeEnd],[TimeDataRetrieval],[TimeProcessing],[TimeRendering],[Source],[Status]
      ,[ByteCount],[RowCount],[AdditionalInfo]
  FROM [ReportingService].[dbo].[ExecutionLog3]

其中

InstanceName – 应用程序 ID

ItemPath – RDL 文件路径。格式为 /{Guid}/{libraryName}/{filename}

/{5901b745-d657-41cd-9969-7fddc3c7b670}/Display Message/RPT_Display_Message.rdl

UserName – 访问报表的用户名

用于从 exutionlogview 3 检索数据的自定义查询

根据我们的需求,我们可以自定义查询来过滤执行日志详细信息。在下面的查询中,我使用了报表名称、用户名以及访问的开始和结束日期来检索数据。

SELECT [userName],ItemPath,[TimeStart] as Date, [TimeDataRetrieval],[TimeProcessing],[TimeRendering],[Status],[ByteCount],[RowCount]
FROM ExecutionLog3
where ItemPath like '{0}' and CONVERT(DATE,TimeStart) between '{2}' and '{3}' and userName='{1}'order by TimeStart desc", reportName, loginName, fromDate, toDate

在 GridView 中显示数据

在本节中,我们将了解如何使用 GridView 控件在 UI 中表示执行日志详细信息。

表单代码

<table width="100%" style="padding: 5px;">
  <tr>
    <td style="width: 10px">From</td>
    <td style="width: 10px">
      <spuc:datetimecontrol runat="server" dateonly="true" id="ru_datefrom" />
    </td>
    <td style="width: 10px">To</td>
    <td style="width: 10px">
      <spuc:datetimecontrol dateonly="true" runat="server" id="ru_dateto" />
    </td>
    <td style="width: 25px">
      <asp:dropdownlist id="ru_userddl" runat="server"></asp:dropdownlist>
    </td>
    <td style="width: 25px">
      <asp:dropdownlist id="ru_reportddl" runat="server"></asp:dropdownlist>
    </td>
    <td>
      <asp:button id="rubtnapply" runat="server" text="Apply" onclick="rubtnapply_Click" />
    </td>
  </tr>
  <tr>
    <td colspan="9">
      <asp:datagrid id="ReportUsageGrid" allowsorting="true" width="100%" cssclass="Grid" runat="server" autogeneratecolumns="False" gridlines="Vertical" cellpadding="3"
        borderstyle="None" borderwidth="1px" bordercolor="black" onsortcommand="ReportUsageGrid_SortCommand">
        <alternatingitemstyle backcolor="Gainsboro"></alternatingitemstyle>
        <headerstyle font-bold="True" forecolor="white" backcolor="#00B3E3"></headerstyle>
        <columns>
          <asp:templatecolumn headertext="Report Name">
            <itemtemplate>
              <asp:label ID="ReportName" runat="server" Text='<%#GetReportName(DataBinder.Eval(Container.DataItem, "ItemPath").ToString())%>'></asp:label>
            </itemtemplate>
          </asp:templatecolumn>
          <asp:templatecolumn headertext="File Name" sortexpression="ItemPath">
            <itemtemplate>
              <asp:label ID="ItemPath" runat="server" Text='<%#FormatItemPath(DataBinder.Eval(Container.DataItem, "ItemPath").ToString())%>'></asp:label>
            </itemtemplate>
          </asp:templatecolumn>
          <asp:templatecolumn headertext="User Name" sortexpression="UserName">
            <itemtemplate>
              <asp:label ID="username" runat="server" Text='<%#FormatUserName(DataBinder.Eval(Container.DataItem, "UserName").ToString())%>'></asp:label>
            </itemtemplate>
          </asp:templatecolumn>
          <asp:templatecolumn headertext="Execution Count" sortexpression="ExecutionCount">
            <itemtemplate>
              <a onclick="ReportUsageReportDialog('<%#FormatReportParameter(DataBinder.Eval(Container.DataItem, " username").tostring(),databinder.eval(container.dataitem, "ItemPath" ).tostring())%>')" href="javascript:void(0);" id="ExecutionCount"><%#Eval("ExecutionCount") %></a>
            </itemtemplate>
          </asp:templatecolumn>
        </columns>
        <pagerstyle horizontalalign="Center" forecolor="white" backcolor="#999999" mode="NumericPages"></pagerstyle>
      </asp:datagrid>
    </td>
  </tr>
</table>

单击执行次数链接时,将打开一个弹出窗口,显示报表的详细信息,包括检索时间、渲染时间和报表状态。我使用了以下脚本在 SharePoint 模态弹出窗口中打开详细信息表单。

<script type="text/javascript">
        function ReportUsageReportDialog(parameter) {
            var options = {
                url: "/_layouts/15/ReportUsageDetails.aspx?" + parameter,
                title: "Report Usage Details",
                dialogReturnValueCallback: function (dialogResult) {
                    if (dialogResult == 1) {
                        SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', AddAlertoptions);
                    }
                },
                allowMaximize: false
            };
            SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', options);
        }
    </script>

代码隐藏

GetReportName

此方法将从 itempath 列值中提取报表名称。

 public string GetReportName(string RDLfileName)
  {
    DataTable reportMaster = (DataTable)ViewState["ReportMaster"];
    if (reportMaster == null)
    {
      LoadReportMaster();
      reportMaster = (DataTable)ViewState["ReportMaster"];
    }
    RDLfileName = RDLfileName.Contains("/") ? RDLfileName.Split('/')[RDLfileName.Split('/').Length - 1].ToString() : RDLfileName;
    DataView view = new DataView(reportMaster);
    view.RowFilter = "LinkFilename2='" + RDLfileName + "'"; ;
    DataTable results = view.ToTable();
    if (results.Rows.Count > 0)
    {
      return results.Rows[0]["Title"] != null ? results.Rows[0]["Title"].ToString().Trim() : string.Empty;
    }
    else
    {
      return string.Empty;
    }
  }

FormatItemPath

此方法将使用 itempath 列值构建报表 URL。

 protected string FormatItemPath(string itempath)
  {
    return itempath.Contains("/") ? itempath.Split('/')[itempath.Split('/').Length - 1].ToString().Trim() : itempath.Trim();
  }

BindReportUserNameDDL

此方法绑定用户名下拉列表的值。

 void BindReportUserNameDDL()
  {
    SPUser user = null;
    try
    {
      record = (DataTable)ViewState["ReportUsageRecords"];
      ru_userddl.Items.Clear();
      if (!ru_userddl.Items.Contains(new ListItem("All")))
      {
        ru_userddl.Items.Add(new ListItem("All"));
      }
      ru_userddl.SelectedValue = "All";
      foreach (DataRow row in record.Rows)
      {
        SPContext.Current.Web.AllowUnsafeUpdates = true;
        try
        {
          user = SPContext.Current.Web.EnsureUser(row["UserName"].ToString());
        }
        catch()
        { }
        if (user != null)
        {
          SPContext.Current.Web.AllowUnsafeUpdates = false;
          if (!ru_userddl.Items.Contains(new ListItem(user.Name, user.LoginName.Contains("|") ? user.LoginName.Split('|')[1] : user.LoginName)))
          {
            ru_userddl.Items.Add(new ListItem(user.Name, user.LoginName.Contains("|") ? user.LoginName.Split('|')[1] : user.LoginName));
          }
        }
        else
        {
          if (!ru_userddl.Items.Contains(new ListItem(row["UserName"].ToString(), row["UserName"].ToString())))
          {
            ru_userddl.Items.Add(new ListItem(row["UserName"].ToString(), row["UserName"].ToString()));
          }
        }
      }
    }
    catch (Exception ex)
    {
      throw;
    }
  }

SPContext.Current.Web.EnsureUser – 这会消耗大量时间通过 SharePoint 网站中的用户名获取用户详细信息。如果用户不存在,将在 catch 块中捕获错误消息,并继续处理其他用户。

为避免性能问题,我们可以创建一个 UserMaster 表来存储用户信息,如用户密钥、用户名、电子邮件 ID 和登录名。

逻辑是,当用户首次访问报表时,会检查用户是否已在用户表中。如果不存在,则将用户添加到表中并返回用户名。如果用户已存在,则通过 exution log 表中的登录名 ID 返回用户名。

 void LoadUsers(DropDownList ddl)
  {
    try
    {
      ddl.Items.Clear();
      if (ViewState["UserMaster"] == null)
      {
        record = new DataTable();
        query = string.Format(@"SELECT [UserKey],[UserName],[EmailId],[LoginName] 
                      FROM [dbo].[UserMaster] 
                      where isArchived=0 order by [UserName] asc");
        record = objBLL.GetData(query);
        ViewState["UserMaster"] = record;
      }
      else
      {
        record = (DataTable)ViewState["UserMaster"];
      }
      ddl.DataTextField = "UserName";
      ddl.DataValueField = "LoginName";
      ddl.DataSource = record;
      ddl.DataBind();
      if (!ddl.Items.Contains(new ListItem("All")))
      {
        ddl.Items.Add(new ListItem("All"));
      }
      ddl.SelectedValue = "All";
      ViewState["UserMaster"] = record;
    }
    catch (Exception ex)
    {
    }
  }

FormatUserName

此方法在传递登录名作为参数时返回用户名。

   protected string FormatUserName(string loginName)
  {
    try
    {
      if (ViewState["UserMaster"] == null)
      {
        record = new DataTable();
        query = string.Format(@"SELECT [UserKey],[UserName],[EmailId],[LoginName],[GlobalUser] 
                    FROM [dbo].[UserMaster] 
                    where isArchived=0");
        record = objBLL.GetData(query);
        ViewState["UserMaster"] = record;
      }
      else
      {
        record = (DataTable)ViewState["UserMaster"];
      }
      row = record.Select("loginname='" + loginName.ToLower() + "'");
      if ((row != null && row.Length > 0))
      {
        username = row[0]["UserName"].ToString();
      }
    }
    catch (Exception) { }
    return username;

  }

Bind Grid

此方法绑定 GridView,参数应为开始日期、结束日期、用户名和报表名称。

 private void BindReportUsageGrid(DateTime objFromDate, DateTime objToDate, string UserName, string ReportName)
  {
    try
    {
      query = string.Format(@"SELECT ItemPath, UserName, COUNT(ItemPath) as ExecutionCount FROM ExecutionLog3
           where (ItemPath like '%{0}%') and CONVERT(DATE,TimeStart) between '{1}' and '{2}' and UserName like '%{3}%'                       group by ItemPath, UserName
           order by ExecutionCount desc
           ", ReportName, objFromDate.ToString("yyyy-MM-dd"), objToDate.ToString("yyyy-MM-dd"), UserName);
      dt = SPtable.GetData(query);
      ReportUsageGrid.DataSource = dt;
      ReportUsageGrid.DataBind();
      ViewState["ReportUsageRecords"] = dt;
    }
    catch (Exception ex)
    {
      string str = ex.Message;
    }
  }

结论

我希望本文能帮助您为在 SharePoint 网站中执行的 SSRS 报表创建自定义使用情况报告。如果您有任何疑问或评论,请告诉我。

历史

2016 年 7 月 19 日:创建初始版本。

© . All rights reserved.